diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 0a5684b2d9eb3d..3bb78f4ca03294 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -35,7 +35,8 @@ RUN apt-get -fy install git vim emacs sudo \ wget curl telnet \ docker.io \ iputils-ping net-tools \ - libncurses5 + libncurses5 \ + libpython2.7 RUN groupadd -g $USER_GID $USERNAME RUN useradd -s /bin/bash -u $USER_UID -g $USER_GID -G docker -m $USERNAME @@ -83,3 +84,5 @@ RUN sed -i '/^TIZEN_SDK_DATA_PATH/d' $TIZEN_SDK_ROOT/sdk.info \ && echo TIZEN_SDK_DATA_PATH=/home/$USERNAME/tizen-sdk-data >> $TIZEN_SDK_ROOT/sdk.info \ && ln -sf /home/$USERNAME/.tizen-cli-config $TIZEN_SDK_ROOT/tools/.tizen-cli-config \ && : # last line + +ENV TIZEN_ROOTFS /tizen_rootfs diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index ba21e5e4402d30..e80dfa78bded48 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -17,29 +17,30 @@ "build": { "dockerfile": "Dockerfile", "args": { - "BUILD_VERSION": "0.5.77" + "BUILD_VERSION": "0.5.79" } }, "remoteUser": "vscode", // Add the IDs of extensions you want installed when the container is created in the array below. "extensions": [ - "ms-azuretools.vscode-docker", - "xaver.clang-format", - "github.vscode-pull-request-github", - "maelvalais.autoconf", - "yzhang.markdown-all-in-one", - "eamodio.gitlens", - "yuichinukiyama.vscode-preview-server", "aaron-bond.better-comments", - "foxundermoon.shell-format", + "augustocdias.tasks-shell-input", + "christian-kohler.path-intellisense", + "eamodio.gitlens", "editorconfig.editorconfig", "esbenp.prettier-vscode", - "redhat.vscode-yaml", - "christian-kohler.path-intellisense", + "foxundermoon.shell-format", + "github.vscode-pull-request-github", "knisterpeter.vscode-github", - "npclaudiu.vscode-gn", + "maelvalais.autoconf", "marus25.cortex-debug", - "msedge-dev.gnls" + "ms-azuretools.vscode-docker", + "msedge-dev.gnls", + "npclaudiu.vscode-gn", + "redhat.vscode-yaml", + "xaver.clang-format", + "yuichinukiyama.vscode-preview-server", + "yzhang.markdown-all-in-one" ], // Use 'settings' to set *default* container specific settings.json values on container create. // You can edit these settings after create using File > Preferences > Settings > Remote. diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt index 624b6f22c74deb..9189db4df34508 100644 --- a/.github/.wordlist.txt +++ b/.github/.wordlist.txt @@ -626,7 +626,6 @@ IlluminanceMeasurement IM imager imagetool -ImageURI imageUri img Impl @@ -1278,6 +1277,7 @@ timedInteractionTimeoutMs TimeFormatLocalization timeoutMs TimeSynchronization +tinycrypt Tizen TKIP tlsr diff --git a/.github/workflows/bloat_check.yaml b/.github/workflows/bloat_check.yaml index 39efab85d61e66..f7a59c578317e5 100644 --- a/.github/workflows/bloat_check.yaml +++ b/.github/workflows/bloat_check.yaml @@ -30,7 +30,7 @@ jobs: runs-on: ubuntu-latest container: - image: connectedhomeip/chip-build:0.5.77 + image: connectedhomeip/chip-build:0.5.79 steps: - uses: Wandalen/wretry.action@v1.0.15 diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 7b1a88b1b3ee9a..19c5c6350dcfff 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -32,7 +32,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build:0.5.77 + image: connectedhomeip/chip-build:0.5.79 volumes: - "/tmp/log_output:/tmp/test_logs" options: --sysctl "net.ipv6.conf.all.disable_ipv6=0 @@ -107,7 +107,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build:0.5.77 + image: connectedhomeip/chip-build:0.5.79 volumes: - "/tmp/log_output:/tmp/test_logs" options: --sysctl "net.ipv6.conf.all.disable_ipv6=0 @@ -237,7 +237,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build:0.5.77 + image: connectedhomeip/chip-build:0.5.79 volumes: - "/tmp/log_output:/tmp/test_logs" options: --sysctl "net.ipv6.conf.all.disable_ipv6=0 diff --git a/.github/workflows/chef.yaml b/.github/workflows/chef.yaml index 7f856d8e9f085c..249636e9b5f3c2 100644 --- a/.github/workflows/chef.yaml +++ b/.github/workflows/chef.yaml @@ -29,7 +29,7 @@ jobs: runs-on: ubuntu-latest if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build:0.5.77 + image: connectedhomeip/chip-build:0.5.79 options: --user root steps: - uses: Wandalen/wretry.action@v1.0.15 @@ -53,7 +53,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build:0.5.77 + image: connectedhomeip/chip-build:0.5.79 options: --user root steps: @@ -77,7 +77,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build-esp32:0.5.77 + image: connectedhomeip/chip-build-esp32:0.5.79 options: --user root steps: @@ -101,7 +101,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build-nrf-platform:0.5.77 + image: connectedhomeip/chip-build-nrf-platform:0.5.79 options: --user root steps: diff --git a/.github/workflows/cirque.yaml b/.github/workflows/cirque.yaml index ca77207d322d94..914b5d6a8a34be 100644 --- a/.github/workflows/cirque.yaml +++ b/.github/workflows/cirque.yaml @@ -38,7 +38,7 @@ jobs: # need to run with privilege, which isn't supported by job.XXX.contaner # https://github.com/actions/container-action/issues/2 # container: - # image: connectedhomeip/chip-build-cirque:0.5.77 + # image: connectedhomeip/chip-build-cirque:0.5.79 # volumes: # - "/tmp:/tmp" # - "/dev/pts:/dev/pts" diff --git a/.github/workflows/darwin-tests.yaml b/.github/workflows/darwin-tests.yaml index c6603eaac00f4e..0f0f57b57104a5 100644 --- a/.github/workflows/darwin-tests.yaml +++ b/.github/workflows/darwin-tests.yaml @@ -29,7 +29,7 @@ concurrency: jobs: test_suites_chip_tool_darwin: name: Test Suites - Darwin - timeout-minutes: 120 + timeout-minutes: 135 strategy: matrix: @@ -96,7 +96,7 @@ jobs: --copy-artifacts-to objdir-clone \ " - name: Run Tests - timeout-minutes: 45 + timeout-minutes: 60 run: | ./scripts/run_in_build_env.sh \ "./scripts/tests/run_test_suite.py \ diff --git a/.github/workflows/doxygen.yaml b/.github/workflows/doxygen.yaml index a3ccea381f4060..a9b503ac0f4835 100644 --- a/.github/workflows/doxygen.yaml +++ b/.github/workflows/doxygen.yaml @@ -82,7 +82,7 @@ jobs: runs-on: ubuntu-20.04 container: - image: connectedhomeip/chip-build-doxygen:0.5.77 + image: connectedhomeip/chip-build-doxygen:0.5.79 if: github.actor != 'restyled-io[bot]' diff --git a/.github/workflows/examples-ameba.yaml b/.github/workflows/examples-ameba.yaml index fdfeae09cdefae..b52f0c998157e3 100644 --- a/.github/workflows/examples-ameba.yaml +++ b/.github/workflows/examples-ameba.yaml @@ -32,7 +32,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build-ameba:0.5.77 + image: connectedhomeip/chip-build-ameba:0.5.79 options: --user root steps: diff --git a/.github/workflows/examples-cc13x2x7_26x2x7.yaml b/.github/workflows/examples-cc13x2x7_26x2x7.yaml index ab358c4e7721a9..885133547c3d54 100644 --- a/.github/workflows/examples-cc13x2x7_26x2x7.yaml +++ b/.github/workflows/examples-cc13x2x7_26x2x7.yaml @@ -34,7 +34,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build-ti:0.5.77 + image: connectedhomeip/chip-build-ti:0.5.79 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-efr32.yaml b/.github/workflows/examples-efr32.yaml index 548909c27aa7bb..8c2da30d946b36 100644 --- a/.github/workflows/examples-efr32.yaml +++ b/.github/workflows/examples-efr32.yaml @@ -35,7 +35,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build-efr32:0.5.77 + image: connectedhomeip/chip-build-efr32:0.5.79 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-esp32.yaml b/.github/workflows/examples-esp32.yaml index f7f27572b4b35f..6d69ce40937e43 100644 --- a/.github/workflows/examples-esp32.yaml +++ b/.github/workflows/examples-esp32.yaml @@ -32,7 +32,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build-esp32:0.5.77 + image: connectedhomeip/chip-build-esp32:0.5.79 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" @@ -118,7 +118,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build-esp32:0.5.77 + image: connectedhomeip/chip-build-esp32:0.5.79 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" diff --git a/.github/workflows/examples-infineon.yaml b/.github/workflows/examples-infineon.yaml index 8604a3b6756326..5f381cc180cd5e 100644 --- a/.github/workflows/examples-infineon.yaml +++ b/.github/workflows/examples-infineon.yaml @@ -32,7 +32,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build-infineon:0.5.77 + image: connectedhomeip/chip-build-infineon:0.5.79 steps: - uses: Wandalen/wretry.action@v1.0.15 diff --git a/.github/workflows/examples-k32w.yaml b/.github/workflows/examples-k32w.yaml index 3342c4f5739884..e43db4cef5c77b 100644 --- a/.github/workflows/examples-k32w.yaml +++ b/.github/workflows/examples-k32w.yaml @@ -34,7 +34,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build-k32w:0.5.77 + image: connectedhomeip/chip-build-k32w:0.5.79 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-linux-arm.yaml b/.github/workflows/examples-linux-arm.yaml index 88ffe8491e48df..369500947303e5 100644 --- a/.github/workflows/examples-linux-arm.yaml +++ b/.github/workflows/examples-linux-arm.yaml @@ -31,7 +31,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build-crosscompile:0.5.77 + image: connectedhomeip/chip-build-crosscompile:0.5.79 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" diff --git a/.github/workflows/examples-linux-imx.yaml b/.github/workflows/examples-linux-imx.yaml index c1c9971c9dd985..2236761bc264ea 100644 --- a/.github/workflows/examples-linux-imx.yaml +++ b/.github/workflows/examples-linux-imx.yaml @@ -31,7 +31,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build-imx:0.5.77 + image: connectedhomeip/chip-build-imx:0.5.79 steps: - uses: Wandalen/wretry.action@v1.0.15 diff --git a/.github/workflows/examples-linux-standalone.yaml b/.github/workflows/examples-linux-standalone.yaml index f557aaeb597f9f..2e6e0edb3f40e4 100644 --- a/.github/workflows/examples-linux-standalone.yaml +++ b/.github/workflows/examples-linux-standalone.yaml @@ -34,7 +34,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build:0.5.77 + image: connectedhomeip/chip-build:0.5.79 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" diff --git a/.github/workflows/examples-mbed.yaml b/.github/workflows/examples-mbed.yaml index 19d59ad4bad2a8..65bf46ebfcdf71 100644 --- a/.github/workflows/examples-mbed.yaml +++ b/.github/workflows/examples-mbed.yaml @@ -37,7 +37,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build-mbed-os:0.5.77 + image: connectedhomeip/chip-build-mbed-os:0.5.79 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" diff --git a/.github/workflows/examples-nrfconnect.yaml b/.github/workflows/examples-nrfconnect.yaml index 458bf7fa712c80..b15ad7d4aa1da0 100644 --- a/.github/workflows/examples-nrfconnect.yaml +++ b/.github/workflows/examples-nrfconnect.yaml @@ -34,7 +34,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build-nrf-platform:0.5.77 + image: connectedhomeip/chip-build-nrf-platform:0.5.79 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" diff --git a/.github/workflows/examples-qpg.yaml b/.github/workflows/examples-qpg.yaml index 278d535dbe0a55..e1e4b40b1f6d3c 100644 --- a/.github/workflows/examples-qpg.yaml +++ b/.github/workflows/examples-qpg.yaml @@ -34,7 +34,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build:0.5.77 + image: connectedhomeip/chip-build:0.5.79 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-telink.yaml b/.github/workflows/examples-telink.yaml index 58fea93d501b9f..1089f0a31af578 100644 --- a/.github/workflows/examples-telink.yaml +++ b/.github/workflows/examples-telink.yaml @@ -32,7 +32,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build-telink:0.5.77 + image: connectedhomeip/chip-build-telink:0.5.79 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" diff --git a/.github/workflows/examples-tizen.yaml b/.github/workflows/examples-tizen.yaml index eeadfd200d916b..2e6b2ae48d2bad 100644 --- a/.github/workflows/examples-tizen.yaml +++ b/.github/workflows/examples-tizen.yaml @@ -32,7 +32,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build-tizen:0.5.77 + image: connectedhomeip/chip-build-tizen:0.5.79 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 cd278c6c1e75b0..09960d78aaba1e 100644 --- a/.github/workflows/full-android.yaml +++ b/.github/workflows/full-android.yaml @@ -34,7 +34,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build-android:0.5.77 + image: connectedhomeip/chip-build-android:0.5.79 volumes: - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/fuzzing-build.yaml b/.github/workflows/fuzzing-build.yaml index c2ecc70cdecd91..dedc1b67b109c4 100644 --- a/.github/workflows/fuzzing-build.yaml +++ b/.github/workflows/fuzzing-build.yaml @@ -31,7 +31,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build:0.5.77 + image: connectedhomeip/chip-build:0.5.79 volumes: - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index b5c296573021d7..ce0a12059f6916 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -85,6 +85,10 @@ jobs: if: always() run: scripts/tools/check_includes.sh + - name: Check for zcl.json and extension sync status + if: always() + run: scripts/tools/check_zcl_file_sync.py . + - name: Ensure all PICS are set for tests (to true or false) if: always() run: | diff --git a/.github/workflows/qemu.yaml b/.github/workflows/qemu.yaml index c9e26c8cc97914..60f620195025d4 100644 --- a/.github/workflows/qemu.yaml +++ b/.github/workflows/qemu.yaml @@ -34,7 +34,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build-esp32-qemu:0.5.77 + image: connectedhomeip/chip-build-esp32-qemu:0.5.79 volumes: - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/release_artifacts.yaml b/.github/workflows/release_artifacts.yaml index 4ab6fcfbe0f6b3..de38d645157cd8 100644 --- a/.github/workflows/release_artifacts.yaml +++ b/.github/workflows/release_artifacts.yaml @@ -29,7 +29,7 @@ jobs: runs-on: ubuntu-latest container: - image: connectedhomeip/chip-build-esp32:0.5.77 + image: connectedhomeip/chip-build-esp32:0.5.79 steps: - uses: Wandalen/wretry.action@v1.0.15 @@ -75,7 +75,7 @@ jobs: runs-on: ubuntu-latest container: - image: connectedhomeip/chip-build-efr32:0.5.77 + image: connectedhomeip/chip-build-efr32:0.5.79 steps: - uses: Wandalen/wretry.action@v1.0.15 name: Checkout diff --git a/.github/workflows/smoketest-android.yaml b/.github/workflows/smoketest-android.yaml index bf59a586b67bde..dc800768554bd3 100644 --- a/.github/workflows/smoketest-android.yaml +++ b/.github/workflows/smoketest-android.yaml @@ -34,7 +34,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build-android:0.5.77 + image: connectedhomeip/chip-build-android:0.5.79 volumes: - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 771c4949340f04..753819af894e77 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -28,7 +28,7 @@ concurrency: jobs: test_suites_linux: name: Test Suites - Linux - timeout-minutes: 120 + timeout-minutes: 140 strategy: matrix: @@ -43,7 +43,7 @@ jobs: runs-on: ubuntu-latest container: - image: connectedhomeip/chip-build:0.5.77 + image: connectedhomeip/chip-build:0.5.79 options: --privileged --sysctl "net.ipv6.conf.all.disable_ipv6=0 net.ipv4.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1" @@ -76,7 +76,7 @@ jobs: .environment/gn_out/.ninja_log .environment/pigweed-venv/*.log - name: Build Apps - timeout-minutes: 30 + timeout-minutes: 45 run: | ./scripts/run_in_build_env.sh \ "./scripts/build/build_examples.py \ @@ -90,7 +90,7 @@ jobs: --copy-artifacts-to objdir-clone \ " - name: Run Tests - timeout-minutes: 40 + timeout-minutes: 60 run: | ./scripts/run_in_build_env.sh \ "./scripts/tests/run_test_suite.py \ @@ -121,7 +121,7 @@ jobs: retention-days: 5 test_suites_darwin: name: Test Suites - Darwin - timeout-minutes: 120 + timeout-minutes: 140 strategy: matrix: @@ -190,7 +190,7 @@ jobs: --copy-artifacts-to objdir-clone \ " - name: Run Tests - timeout-minutes: 50 + timeout-minutes: 70 run: | ./scripts/run_in_build_env.sh \ "./scripts/tests/run_test_suite.py \ @@ -237,7 +237,7 @@ jobs: runs-on: ubuntu-latest container: - image: connectedhomeip/chip-build:0.5.77 + image: connectedhomeip/chip-build:0.5.79 options: --privileged --sysctl "net.ipv6.conf.all.disable_ipv6=0 net.ipv4.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1" diff --git a/.github/workflows/unit_integration_test.yaml b/.github/workflows/unit_integration_test.yaml index 92c5db7a27a938..d13919cd245a64 100644 --- a/.github/workflows/unit_integration_test.yaml +++ b/.github/workflows/unit_integration_test.yaml @@ -37,7 +37,7 @@ jobs: runs-on: ubuntu-latest container: - image: connectedhomeip/chip-build:0.5.77 + image: connectedhomeip/chip-build:0.5.79 volumes: - "/tmp/log_output:/tmp/test_logs" options: --privileged --sysctl "net.ipv6.conf.all.disable_ipv6=0 net.ipv4.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1" diff --git a/.github/workflows/zap_regeneration.yaml b/.github/workflows/zap_regeneration.yaml index 0584c11887fd1d..ebd49b363048a6 100644 --- a/.github/workflows/zap_regeneration.yaml +++ b/.github/workflows/zap_regeneration.yaml @@ -28,7 +28,7 @@ jobs: runs-on: ubuntu-20.04 container: - image: connectedhomeip/chip-build-zap:0.5.77 + image: connectedhomeip/chip-build-zap:0.5.79 defaults: run: shell: sh diff --git a/.github/workflows/zap_templates.yaml b/.github/workflows/zap_templates.yaml index f5a1d809540dfd..56355d7e351324 100644 --- a/.github/workflows/zap_templates.yaml +++ b/.github/workflows/zap_templates.yaml @@ -29,7 +29,7 @@ jobs: runs-on: ubuntu-20.04 container: - image: connectedhomeip/chip-build-zap:0.5.77 + image: connectedhomeip/chip-build-zap:0.5.79 defaults: run: shell: sh diff --git a/.gitmodules b/.gitmodules index 8e6b6ad0545da7..0682becb54cfce 100644 --- a/.gitmodules +++ b/.gitmodules @@ -246,3 +246,8 @@ url = https://github.com/bouffalolab/bl_iot_sdk_matter.git branch = bl602_release platforms = bl602 +[submodule "third_party/nxp/libs/mbedtls/repo"] + path = third_party/nxp/libs/mbedtls/repo + url = https://github.com/NXPmicro/mbedtls.git + branch = tinycrypt-mbedtls-2.28 + platforms = k32w0 diff --git a/.restyled.yaml b/.restyled.yaml index eb9e0e6a92d8ea..937a8b4afa2a53 100644 --- a/.restyled.yaml +++ b/.restyled.yaml @@ -70,6 +70,7 @@ exclude: - "src/controller/python/chip/clusters/Objects.py" # generated file, no point to restyle - "src/controller/python/chip/clusters/CHIPClusters.py" # generated file, no point to restyle - "scripts/idl/tests/outputs/**/*" # Matches generated output 1:1 + - "examples/chef/sample_app_util/test_files/*.yaml" - "examples/chef/zzz_generated/**/*" diff --git a/.vscode/extensions.json b/.vscode/extensions.json index d92e0983873689..6ce0339c697719 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -3,7 +3,26 @@ // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp // List of extensions which should be recommended for users of this workspace. - "recommendations": ["marus25.cortex-debug"], + "recommendations": [ + "aaron-bond.better-comments", + "augustocdias.tasks-shell-input", + "christian-kohler.path-intellisense", + "eamodio.gitlens", + "editorconfig.editorconfig", + "esbenp.prettier-vscode", + "foxundermoon.shell-format", + "github.vscode-pull-request-github", + "knisterpeter.vscode-github", + "maelvalais.autoconf", + "marus25.cortex-debug", + "ms-azuretools.vscode-docker", + "msedge-dev.gnls", + "npclaudiu.vscode-gn", + "redhat.vscode-yaml", + "xaver.clang-format", + "yuichinukiyama.vscode-preview-server", + "yzhang.markdown-all-in-one" + ], // List of extensions recommended by VS Code that should not be recommended for users of this workspace. "unwantedRecommendations": [] } diff --git a/.vscode/launch.json b/.vscode/launch.json index 3439327d84e5a2..77739937fc05a0 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -90,6 +90,39 @@ } ] }, + { + "name": "LightingApp (Tizen) [remote]", + "type": "cppdbg", + "request": "launch", + "cwd": "${workspaceFolder}/out/tizen-arm-light", + "program": "${workspaceFolder}/out/tizen-arm-light/chip-lighting-app", + "miDebuggerPath": "${env:TIZEN_SDK_ROOT}/tools/arm-linux-gnueabi-gcc-9.2/bin/arm-linux-gnueabi-gdb", + "additionalSOLibSearchPath": "${env:TIZEN_ROOTFS}", + "preLaunchTask": "Launch LightingApp with gdbserver attached (Tizen)", + "miDebuggerServerAddress": "localhost:9999", + "linux": { + "MIMode": "gdb" + }, + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "text": "set solib-absolute-prefix ${env:TIZEN_ROOTFS}" + }, + { + "text": "set sysroot ${env:TIZEN_SDK_SYSROOT}" + }, + { + "text": "set debug-file-directory {env:TIZEN_SDK_SYSROOT}/usr/lib/debug" + }, + { + "text": "set solib-search-path ${workspaceFolder}/out/tizen-arm-light" + } + ] + }, { "name": "Debug Mbed examples", diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 9f34c08e27a6af..20aff730a74613 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -192,6 +192,68 @@ "problemMatcher": { "base": "$gcc" } + }, + { + "label": "Build LightingApp (Tizen)", + "type": "shell", + "command": "scripts/run_in_build_env.sh", + "args": [ + "${workspaceFolder}/scripts/build/build_examples.py --target tizen-arm-light --enable-flashbundle build" + ], + "group": "build", + "problemMatcher": { + "base": "$gcc" + } + }, + { + "label": "Connect to device (Tizen)", + "type": "shell", + "command": "sdb", + "args": ["connect", "${input:tizenTargetDeviceAddress}"], + "problemMatcher": [], + "runOptions": { + "reevaluateOnRerun": false + } + }, + { + "label": "Install LightingApp (Tizen)", + "type": "shell", + "command": "sdb", + "args": [ + "-s", + "${input:tizenTargetDeviceAddressSdb}", + "install", + "${workspaceFolder}/out/tizen-arm-light/package/out/org.tizen.matter.example.lighting-1.0.0.tpk" + ], + "problemMatcher": [], + "runOptions": { + "reevaluateOnRerun": false + } + }, + { + "label": "Launch LightingApp with gdbserver attached (Tizen)", + "type": "shell", + "command": "bash", + "args": [ + "${workspaceFolder}/scripts/helpers/tizen_gdbserver_run.sh", + "--app-name", + "org.tizen.matter.example.lighting", + "--target", + "${input:tizenTargetDeviceAddressSdb}" + ], + "problemMatcher": [], + "runOptions": { + "reevaluateOnRerun": false + }, + "isBackground": false, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": true + } } ], "inputs": [ @@ -377,6 +439,21 @@ "telink-tlsr9518adk80d-light-switch", "tizen-arm-light" ] + }, + { + "type": "promptString", + "id": "tizenTargetDeviceAddress", + "description": "Enter the target device address and port in format
:" + }, + { + "id": "tizenTargetDeviceAddressSdb", + "type": "command", + "command": "shellCommand.execute", + "args": { + "command": "sdb devices | grep -v 'List of devices attached' |awk '{print $1 \"|\" $1, $3, \"(\" $2 \")\"}'", + "fieldSeparator": "|", + "description": "Select target device" + } } ] } diff --git a/build_overrides/mbedtls.gni b/build_overrides/mbedtls.gni index 04f377ed99eabc..ac8a6f16203880 100644 --- a/build_overrides/mbedtls.gni +++ b/build_overrides/mbedtls.gni @@ -15,4 +15,5 @@ declare_args() { # Root directory for mbedTLS. mbedtls_root = "//third_party/mbedtls" + mbedtls_repo = "//third_party/mbedtls" } diff --git a/build_overrides/zephyr.gni b/build_overrides/zephyr.gni new file mode 100644 index 00000000000000..9ad63cf8d53544 --- /dev/null +++ b/build_overrides/zephyr.gni @@ -0,0 +1,15 @@ +# Copyright (c) 2021 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. + +# place holder diff --git a/config/ameba/chip.cmake b/config/ameba/chip.cmake index 40dc11bd659711..0f5cd186367b0f 100644 --- a/config/ameba/chip.cmake +++ b/config/ameba/chip.cmake @@ -110,7 +110,7 @@ if (matter_enable_rpc) #string(APPEND CHIP_GN_ARGS "remove_default_configs = [\"//third_party/connectedhomeip/third_party/pigweed/repo/pw_build:cpp17\"]\n") string(APPEND CHIP_GN_ARGS "chip_build_pw_rpc_lib = true\n") string(APPEND CHIP_GN_ARGS "pw_log_BACKEND = \"//third_party/connectedhomeip/third_party/pigweed/repo/pw_log_basic\"\n") -string(APPEND CHIP_GN_ARGS "pw_assert_BACKEND = \"//third_party/connectedhomeip/third_party/pigweed/repo/pw_assert_log\"\n") +string(APPEND CHIP_GN_ARGS "pw_assert_BACKEND = \"//third_party/connectedhomeip/third_party/pigweed/repo/pw_assert_log:check_backend\"\n") string(APPEND CHIP_GN_ARGS "pw_sys_io_BACKEND = \"//third_party/connectedhomeip/examples/platform/ameba/pw_sys_io:pw_sys_io_ameba\"\n") string(APPEND CHIP_GN_ARGS "dir_pw_third_party_nanopb = \"//third_party/connectedhomeip/third_party/nanopb/repo\"\n") string(APPEND CHIP_GN_ARGS "pw_build_LINK_DEPS = [\"//third_party/connectedhomeip/third_party/pigweed/repo/pw_assert:impl\", \"//third_party/connectedhomeip/third_party/pigweed/repo/pw_log:impl\"]\n") diff --git a/config/bouffalolab/bl602/lib/pw_rpc/pw_rpc.gni b/config/bouffalolab/bl602/lib/pw_rpc/pw_rpc.gni index 29f549efd4b088..69bd1634363ebc 100644 --- a/config/bouffalolab/bl602/lib/pw_rpc/pw_rpc.gni +++ b/config/bouffalolab/bl602/lib/pw_rpc/pw_rpc.gni @@ -16,7 +16,7 @@ import("//build_overrides/chip.gni") import("//build_overrides/pigweed.gni") pw_log_BACKEND = "$dir_pw_log_basic" -pw_assert_BACKEND = "$dir_pw_assert_log" +pw_assert_BACKEND = "$dir_pw_assert_log:check_backend" pw_sys_io_BACKEND = "${chip_root}/examples/platform/bl602/pw_sys_io:pw_sys_io_bl602" diff --git a/config/efr32/lib/pw_rpc/pw_rpc.gni b/config/efr32/lib/pw_rpc/pw_rpc.gni index b0ef83d19dabd6..68f1c6154f4a91 100644 --- a/config/efr32/lib/pw_rpc/pw_rpc.gni +++ b/config/efr32/lib/pw_rpc/pw_rpc.gni @@ -16,7 +16,7 @@ import("//build_overrides/chip.gni") import("//build_overrides/pigweed.gni") pw_log_BACKEND = "$dir_pw_log_basic" -pw_assert_BACKEND = "$dir_pw_assert_log" +pw_assert_BACKEND = "$dir_pw_assert_log:check_backend" pw_sys_io_BACKEND = "${chip_root}/examples/platform/efr32/pw_sys_io:pw_sys_io_efr32" diff --git a/config/esp32/components/chip/CMakeLists.txt b/config/esp32/components/chip/CMakeLists.txt index 4f8c60e4af25d4..6744546453060f 100644 --- a/config/esp32/components/chip/CMakeLists.txt +++ b/config/esp32/components/chip/CMakeLists.txt @@ -81,11 +81,11 @@ endif() if(CONFIG_ENABLE_PW_RPC) string(APPEND chip_gn_args "import(\"//build_overrides/pigweed.gni\")\n") - chip_gn_arg_append("remove_default_configs" "[\"//third_party/connectedhomeip/third_party/pigweed/repo/pw_build:cpp17\"]") + chip_gn_arg_append("remove_default_configs" "[\"//third_party/connectedhomeip/third_party/pigweed/repo/pw_build:toolchain_cpp_standard\"]") chip_gn_arg_append("chip_build_pw_rpc_lib" "true") chip_gn_arg_append("chip_build_pw_trace_lib" "true") chip_gn_arg_append("pw_log_BACKEND" "\"//third_party/connectedhomeip/third_party/pigweed/repo/pw_log_basic\"") - chip_gn_arg_append("pw_assert_BACKEND" "\"//third_party/connectedhomeip/third_party/pigweed/repo/pw_assert_log\"") + chip_gn_arg_append("pw_assert_BACKEND" "\"//third_party/connectedhomeip/third_party/pigweed/repo/pw_assert_log:check_backend\"") chip_gn_arg_append("pw_sys_io_BACKEND" "\"//third_party/connectedhomeip/examples/platform/esp32/pw_sys_io:pw_sys_io_esp32\"") chip_gn_arg_append("pw_trace_BACKEND" "\"//third_party/connectedhomeip/third_party/pigweed/repo/pw_trace_tokenized\"") chip_gn_arg_append("dir_pw_third_party_nanopb" "\"//third_party/connectedhomeip/third_party/nanopb/repo\"") diff --git a/config/ios/CHIPProjectConfig.h b/config/ios/CHIPProjectConfig.h index f9be4d998c7319..6a9d7eb3213836 100644 --- a/config/ios/CHIPProjectConfig.h +++ b/config/ios/CHIPProjectConfig.h @@ -40,6 +40,8 @@ #define CHIP_CONFIG_MAX_SOFTWARE_VERSION_LENGTH 128 +#ifndef CHIP_CONFIG_KVS_PATH #define CHIP_CONFIG_KVS_PATH "chip.store" +#endif #endif /* CHIPPROJECTCONFIG_H */ diff --git a/config/mbed/CMakeLists.txt b/config/mbed/CMakeLists.txt index dbf7e91ba13708..337020b56c3d62 100644 --- a/config/mbed/CMakeLists.txt +++ b/config/mbed/CMakeLists.txt @@ -383,8 +383,9 @@ target_include_directories(${APP_TARGET} PRIVATE ${PIGWEED_ROOT}/pw_sys_io/public ${PIGWEED_ROOT}/pw_assert/public ${PIGWEED_ROOT}/pw_assert/assert_lite_public_overrides + ${PIGWEED_ROOT}/pw_assert_log/assert_backend_public_overrides + ${PIGWEED_ROOT}/pw_assert_log/check_backend_public_overrides ${PIGWEED_ROOT}/pw_assert_log/public - ${PIGWEED_ROOT}/pw_assert_log/public_overrides ${PIGWEED_ROOT}/pw_bytes/public ${PIGWEED_ROOT}/pw_checksum/public ${PIGWEED_ROOT}/pw_containers/public diff --git a/config/mbed/chip-gn/lib/pw_rpc/pw_rpc.gni b/config/mbed/chip-gn/lib/pw_rpc/pw_rpc.gni index f35741414952c5..2b03f6b4c9958c 100644 --- a/config/mbed/chip-gn/lib/pw_rpc/pw_rpc.gni +++ b/config/mbed/chip-gn/lib/pw_rpc/pw_rpc.gni @@ -16,7 +16,7 @@ import("//build_overrides/chip.gni") import("//build_overrides/pigweed.gni") pw_log_BACKEND = "$dir_pw_log_basic" -pw_assert_BACKEND = "$dir_pw_assert_log" +pw_assert_BACKEND = "$dir_pw_assert_log:check_backend" pw_sys_io_BACKEND = "${chip_root}/examples/platform/mbed/pw_sys_io:pw_sys_io_mbed" pw_rpc_system_server_BACKEND = diff --git a/config/nrfconnect/chip-module/CMakeLists.txt b/config/nrfconnect/chip-module/CMakeLists.txt index ac4a8f7e561aa1..13bb2e70c47305 100644 --- a/config/nrfconnect/chip-module/CMakeLists.txt +++ b/config/nrfconnect/chip-module/CMakeLists.txt @@ -257,7 +257,7 @@ if (CONFIG_CHIP_PW_RPC) set(PIGWEED_DIR "//third_party/pigweed/repo") chip_gn_arg_bool("chip_build_pw_trace_lib" "true") chip_gn_arg_string("pw_trace_BACKEND" ${PIGWEED_DIR}/pw_trace_tokenized) - chip_gn_arg_string("pw_assert_BACKEND" ${PIGWEED_DIR}/pw_assert_log) + chip_gn_arg_string("pw_assert_BACKEND" ${PIGWEED_DIR}/pw_assert_log:check_backend) chip_gn_arg_string("pw_log_BACKEND" ${PIGWEED_DIR}/pw_log_basic) chip_gn_arg("pw_build_LINK_DEPS" [\"${PIGWEED_DIR}/pw_assert:impl\",\ \"${PIGWEED_DIR}/pw_log:impl\"]) endif() diff --git a/config/qpg/lib/pw_rpc/pw_rpc.gni b/config/qpg/lib/pw_rpc/pw_rpc.gni index 1f1a5012e803ea..60fb93e6b8fc44 100644 --- a/config/qpg/lib/pw_rpc/pw_rpc.gni +++ b/config/qpg/lib/pw_rpc/pw_rpc.gni @@ -16,7 +16,7 @@ import("//build_overrides/chip.gni") import("//build_overrides/pigweed.gni") pw_log_BACKEND = "$dir_pw_log_basic" -pw_assert_BACKEND = "$dir_pw_assert_log" +pw_assert_BACKEND = "$dir_pw_assert_log:check_backend" pw_sys_io_BACKEND = "${chip_root}/examples/platform/qpg/pw_sys_io:pw_sys_io_qpg" pw_build_LINK_DEPS = [ diff --git a/config/zephyr/Kconfig b/config/zephyr/Kconfig index 42055393de2a58..b197f0491a9689 100644 --- a/config/zephyr/Kconfig +++ b/config/zephyr/Kconfig @@ -139,6 +139,26 @@ config CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT help Enables Thread Sleepy End Device support in Matter. +if CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT + +config CHIP_SED_IDLE_INTERVAL + int "Sleepy End Device idle interval (ms)" + default 1000 + help + SED wake interval in milliseconds while the device is idle, meaning that + there is no active exchange to or from the device, and its commissioning + window is closed. + +config CHIP_SED_ACTIVE_INTERVAL + int "Sleepy End Device active interval (ms)" + default 200 + help + SED wake interval in milliseconds while the device is active, meaning that + there is an active exchange to or from the device, or its commissioning + window is open. + +endif # CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT + config CHIP_THREAD_SSED bool "Enable Thread Synchronized Sleepy End Device support" depends on OPENTHREAD_CSL_RECEIVER && CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT diff --git a/config/zephyr/README.md b/config/zephyr/README.md new file mode 100644 index 00000000000000..bb780288a34606 --- /dev/null +++ b/config/zephyr/README.md @@ -0,0 +1,10 @@ +# Zephyr build and configuration files + +This directory contains build scripts and common configuration files used by +CHIP Zephyr applications. It is structured as follows: + +| File/Folder | Contents | +| ----------- | ----------------------------------------------------------------------------------------------------------------------------------- | +| chip-gn | GN project used to build selected CHIP libraries with the _Zephyr_ platform integration layer | +| chip-module | CMake wrapper for the GN project defined in `chip-gn` directory, and other components that allow one to use CHIP as a Zephyr module | +| app | Common and optional Kconfig configuration files that can be used in Zephyr applications | diff --git a/config/zephyr/app/copy-flashbundle-firmware.cmake b/config/zephyr/app/copy-flashbundle-firmware.cmake new file mode 100644 index 00000000000000..93464f7aceb837 --- /dev/null +++ b/config/zephyr/app/copy-flashbundle-firmware.cmake @@ -0,0 +1,25 @@ +# +# Copyright (c) 2022 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Copy the merged.hex file if it exists, otherwise copy zephyr.hex + +set(HEX_NAME merged.hex) + +if(EXISTS "zephyr/${HEX_NAME}") + configure_file("zephyr/${HEX_NAME}" "${FLASHBUNDLE_FIRMWARE}" COPYONLY) +else() + configure_file("zephyr/${KERNEL_HEX_NAME}" "${FLASHBUNDLE_FIRMWARE}" COPYONLY) +endif() diff --git a/config/zephyr/app/enable-gnu-std.cmake b/config/zephyr/app/enable-gnu-std.cmake new file mode 100644 index 00000000000000..5f31e1a5c62ab8 --- /dev/null +++ b/config/zephyr/app/enable-gnu-std.cmake @@ -0,0 +1,6 @@ +add_library(gnu17 INTERFACE) +target_compile_options(gnu17 + INTERFACE + $<$:-std=gnu++17> + -D_SYS__PTHREADTYPES_H_) +target_link_libraries(app PRIVATE gnu17) diff --git a/config/zephyr/app/flashing.cmake b/config/zephyr/app/flashing.cmake new file mode 100644 index 00000000000000..b70e166ff28cfe --- /dev/null +++ b/config/zephyr/app/flashing.cmake @@ -0,0 +1,55 @@ +# +# Copyright (c) 2021 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. +# + +# Adds rules to generate a flashing wrapper script for an nrfconnect firmware. + +set(FLASHBUNDLE_FLASHER_COMMON ${CMAKE_PROJECT_NAME}/firmware_utils.py) +set(FLASHBUNDLE_FLASHER_PLATFORM ${CMAKE_PROJECT_NAME}/nrfconnect_firmware_utils.py) +set(FLASHBUNDLE_FLASHER_WRAPPER ${CMAKE_PROJECT_NAME}/${CMAKE_PROJECT_NAME}.flash.py) +set(FLASHBUNDLE_FIRMWARE ${CMAKE_PROJECT_NAME}/${CMAKE_PROJECT_NAME}.hex) +set(FLASHBUNDLE_FILES ${FLASHBUNDLE_FLASHER_COMMON} ${FLASHBUNDLE_FLASHER_PLATFORM} ${FLASHBUNDLE_FLASHER_WRAPPER} ${FLASHBUNDLE_FIRMWARE}) + +get_filename_component(FLASHBUNDLE_FIRMWARE_BASENAME ${FLASHBUNDLE_FIRMWARE} NAME) + +list(JOIN FLASHBUNDLE_FILES "\n" FLASHBUNDLE_MANIFEST) + +file(GENERATE + OUTPUT ${CMAKE_PROJECT_NAME}.flashbundle.txt + CONTENT "${FLASHBUNDLE_MANIFEST}\n" + ) + +add_custom_command(OUTPUT "${FLASHBUNDLE_FLASHER_COMMON}" + COMMAND ${CMAKE_COMMAND} ARGS -E copy "${PROJECT_SOURCE_DIR}/third_party/connectedhomeip/scripts/flashing/firmware_utils.py" "${FLASHBUNDLE_FLASHER_COMMON}" + VERBATIM) + +add_custom_command(OUTPUT "${FLASHBUNDLE_FLASHER_PLATFORM}" + COMMAND ${CMAKE_COMMAND} ARGS -E copy "${PROJECT_SOURCE_DIR}/third_party/connectedhomeip/scripts/flashing/nrfconnect_firmware_utils.py" "${FLASHBUNDLE_FLASHER_PLATFORM}" + VERBATIM) + +add_custom_command(OUTPUT "${FLASHBUNDLE_FIRMWARE}" + DEPENDS zephyr/${KERNEL_HEX_NAME} + COMMAND ${CMAKE_COMMAND} ARGS -DFLASHBUNDLE_FIRMWARE=${FLASHBUNDLE_FIRMWARE} -DKERNEL_HEX_NAME=${KERNEL_HEX_NAME} -P "${CHIP_ROOT}/config/nrfconnect/app/copy-flashbundle-firmware.cmake" + VERBATIM) + +add_custom_command(OUTPUT "${CMAKE_PROJECT_NAME}/${CMAKE_PROJECT_NAME}.flash.py" + COMMAND ${python} + "${PROJECT_SOURCE_DIR}/third_party/connectedhomeip/scripts/flashing/gen_flashing_script.py" nrfconnect + --output "${FLASHBUNDLE_FLASHER_WRAPPER}" + --application "${FLASHBUNDLE_FIRMWARE_BASENAME}" + COMMENT "To flash ${FLASHBUNDLE_FIRMWARE_BASENAME} run ${FLASHBUNDLE_FLASHER_WRAPPER}" + VERBATIM) + +add_custom_target(flashing_script DEPENDS ${FLASHBUNDLE_FILES}) diff --git a/config/zephyr/app/overlay-usb_support.conf b/config/zephyr/app/overlay-usb_support.conf new file mode 100644 index 00000000000000..1b4a2d56fe8490 --- /dev/null +++ b/config/zephyr/app/overlay-usb_support.conf @@ -0,0 +1,24 @@ +# +# Copyright (c) 2020 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +CONFIG_GPIO=y + +CONFIG_USB=y +CONFIG_USB_DEVICE_STACK=y +CONFIG_USB_UART_CONSOLE=y + +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_UART_LINE_CTRL=y diff --git a/config/zephyr/chip-gn/.gn b/config/zephyr/chip-gn/.gn new file mode 100644 index 00000000000000..2024e95fed6079 --- /dev/null +++ b/config/zephyr/chip-gn/.gn @@ -0,0 +1,29 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/build.gni") +import("//build_overrides/chip.gni") + +# The location of the build configuration file. +buildconfig = "${build_root}/config/BUILDCONFIG.gn" + +# CHIP uses angle bracket includes. +check_system_includes = true + +default_args = { + target_cpu = "" + target_os = "zephyr" + + import("${chip_root}/config/zephyr/chip-gn/args.gni") +} diff --git a/config/zephyr/chip-gn/BUILD.gn b/config/zephyr/chip-gn/BUILD.gn new file mode 100644 index 00000000000000..85288992c84812 --- /dev/null +++ b/config/zephyr/chip-gn/BUILD.gn @@ -0,0 +1,40 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/build.gni") +import("//build_overrides/chip.gni") + +import("${chip_root}/build/chip/tests.gni") + +assert(current_os == "zephyr") + +declare_args() { + chip_build_example_providers = false +} + +group("zephyr") { + deps = [ "${chip_root}/src/lib" ] + + if (chip_build_tests) { + deps += [ "${chip_root}/src:tests" ] + } + + if (chip_build_example_providers) { + deps += [ "${chip_root}/examples/providers:device_info_provider" ] + } +} + +group("default") { + deps = [ ":zephyr" ] +} diff --git a/config/zephyr/chip-gn/args.gni b/config/zephyr/chip-gn/args.gni new file mode 100644 index 00000000000000..e5d5aedf5bc17d --- /dev/null +++ b/config/zephyr/chip-gn/args.gni @@ -0,0 +1,27 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/chip.gni") + +chip_device_platform = "zephyr" + +chip_build_tests = false + +chip_project_config_include = "" +chip_system_project_config_include = "" +chip_ble_project_config_include = "" + +custom_toolchain = "${chip_root}/config/zephyr/chip-gn/toolchain:zephyr" + +pw_build_PIP_CONSTRAINTS = [ "${chip_root}/scripts/constraints.txt" ] diff --git a/config/zephyr/chip-gn/toolchain/BUILD.gn b/config/zephyr/chip-gn/toolchain/BUILD.gn new file mode 100644 index 00000000000000..28fbe6d8e939b0 --- /dev/null +++ b/config/zephyr/chip-gn/toolchain/BUILD.gn @@ -0,0 +1,33 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/toolchain/gcc_toolchain.gni") +import("//build_overrides/build.gni") + +declare_args() { + zephyr_ar = "" + zephyr_cc = "" + zephyr_cxx = "" +} + +gcc_toolchain("zephyr") { + ar = zephyr_ar + cc = zephyr_cc + cxx = zephyr_cxx + + toolchain_args = { + current_os = "zephyr" + is_clang = false + } +} diff --git a/config/zephyr/chip-module/CMakeLists.txt b/config/zephyr/chip-module/CMakeLists.txt new file mode 100644 index 00000000000000..ba25a316f57a2e --- /dev/null +++ b/config/zephyr/chip-module/CMakeLists.txt @@ -0,0 +1,257 @@ +# +# Copyright (c) 2022 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# +# @file +# CMake sub-project defining 'chip' target which represents CHIP library +# Since CHIP doesn't provide native CMake support, ExternalProject +# module is used to build the required artifacts with GN meta-build +# system. It is assumed that find_package(Zephyr) has been called before +# including this file. +# + +if (CONFIG_CHIP) + +include(ExternalProject) +include(../zephyr-util.cmake) + +# ============================================================================== +# Declare configuration variables and define constants +# ============================================================================== + +# C/C++ compiler flags passed to CHIP build system +list(APPEND CHIP_CFLAGS) + +# C compiler flags passed to CHIP build system +list(APPEND CHIP_CFLAGS_C) + +# C++ compiler flags passed to CHIP build system +list(APPEND CHIP_CFLAGS_CC) + +# CHIP libraries that the application should be linked with +list(APPEND CHIP_LIBRARIES) + +# GN meta-build system arguments in the form of 'key1 = value1\nkey2 = value2...' string +string(APPEND CHIP_GN_ARGS) + +# C/C++ compiler flags which should not be forwarded to CHIP +# build system (e.g. because CHIP configures them on its own) +set(CHIP_CFLAG_EXCLUDES + "-fno-asynchronous-unwind-tables" + "-fno-common" + "-fno-defer-pop" + "-fno-reorder-functions" + "-ffunction-sections" + "-fdata-sections" + "-g*" + "-O*" + "-W*" +) + +# ============================================================================== +# Helper macros +# ============================================================================== + +macro(chip_gn_arg_import FILE) + string(APPEND CHIP_GN_ARGS "import(\"${FILE}\")\n") +endmacro() + +macro(chip_gn_arg_string ARG STRING) + string(APPEND CHIP_GN_ARGS "${ARG} = \"${STRING}\"\n") +endmacro() + +macro(chip_gn_arg_bool ARG BOOLEAN) + if (${BOOLEAN}) + string(APPEND CHIP_GN_ARGS "${ARG} = true\n") + else() + string(APPEND CHIP_GN_ARGS "${ARG} = false\n") + endif() +endmacro() + +macro(chip_gn_arg_cflags ARG CFLAGS) + set(CFLAG_EXCLUDES "[") + foreach(cflag ${CHIP_CFLAG_EXCLUDES}) + string(APPEND CFLAG_EXCLUDES "\"${cflag}\", ") + endforeach() + string(APPEND CFLAG_EXCLUDES "]") + string(APPEND CHIP_GN_ARGS "${ARG} = filter_exclude(string_split(\"${CFLAGS}\"), ${CFLAG_EXCLUDES})\n") +endmacro() + +# ============================================================================== +# Prepare CHIP configuration based on the project Kconfig configuration +# ============================================================================== + +if (NOT CHIP_ROOT) + get_filename_component(CHIP_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../.. REALPATH) +endif() + +set(GN_ROOT_TARGET ${CHIP_ROOT}/config/zephyr/chip-gn) + +if (CONFIG_POSIX_API) + list(APPEND CHIP_CFLAGS + -D_SYS__PTHREADTYPES_H_ + -isystem${ZEPHYR_BASE}/include/zephyr/posix + ) +endif() + +list(APPEND CHIP_CFLAGS -isystem${ZEPHYR_BASE}/../modules/crypto/mbedtls/include/) + +zephyr_get_compile_flags(CHIP_CFLAGS_C C) +zephyr_get_compile_flags(CHIP_CFLAGS_CC CXX) +zephyr_get_gnu_cpp_standard(CHIP_CFLAGS_CC) + +convert_list_of_flags_to_string_of_flags(CHIP_CFLAGS CHIP_CFLAGS) +convert_list_of_flags_to_string_of_flags(CHIP_CFLAGS_C CHIP_CFLAGS_C) +convert_list_of_flags_to_string_of_flags(CHIP_CFLAGS_CC CHIP_CFLAGS_CC) + +# Prepare CHIP libraries that the application should be linked with + +if (NOT CHIP_LIBRARIES) + set(CHIP_LIBRARIES -lCHIP) +endif() + +if (CONFIG_CHIP_LIB_SHELL) + list(APPEND CHIP_LIBRARIES -lCHIPShell) +endif() + +if (CONFIG_CHIP_PW_RPC) + list(APPEND CHIP_LIBRARIES -lPwRpc) +endif() + + +# Set up CHIP project configuration file + +if (CONFIG_CHIP_PROJECT_CONFIG) + get_filename_component(CHIP_PROJECT_CONFIG + ${CONFIG_CHIP_PROJECT_CONFIG} + REALPATH + BASE_DIR ${CMAKE_SOURCE_DIR} + ) + set(CHIP_PROJECT_CONFIG "<${CHIP_PROJECT_CONFIG}>") +else() + set(CHIP_PROJECT_CONFIG "") +endif() + +# Set up custom OpenThread configuration + +if (CONFIG_CHIP_OPENTHREAD_CONFIG) + get_filename_component(CHIP_OPENTHREAD_CONFIG + ${CONFIG_CHIP_OPENTHREAD_CONFIG} + REALPATH + BASE_DIR ${CMAKE_SOURCE_DIR} + ) + zephyr_set_openthread_config(${CHIP_OPENTHREAD_CONFIG}) +endif() + +# Find required programs + +find_program(GN_EXECUTABLE gn) +if (${GN_EXECUTABLE} STREQUAL GN_EXECUTABLE-NOTFOUND) + message(FATAL_ERROR "The 'gn' command was not found. Make sure you have GN installed.") +else() + # Parse the 'gn --version' output to find the installed version. + set(MIN_GN_VERSION 1000) + execute_process( + COMMAND + ${GN_EXECUTABLE} --version + OUTPUT_VARIABLE gn_version_output + ERROR_VARIABLE gn_error_output + RESULT_VARIABLE gn_status + ) + + if(${gn_status} EQUAL 0) + if(gn_version_output VERSION_LESS ${MIN_GN_VERSION}) + message(FATAL_ERROR "Found unsuitable version of 'gn'. Required is at least ${MIN_GN_VERSION}") + endif() + else() + message(FATAL_ERROR "Could NOT find working gn: Found gn (${GN_EXECUTABLE}), but failed to load with:\n ${gn_error_output}") + endif() +endif() + +find_package(Python3 REQUIRED) + +# ============================================================================== +# Generate configuration for CHIP GN build system +# ============================================================================== +chip_gn_arg_cflags("target_cflags" ${CHIP_CFLAGS}) +chip_gn_arg_cflags("target_cflags_c" ${CHIP_CFLAGS_C}) +chip_gn_arg_cflags("target_cflags_cc" ${CHIP_CFLAGS_CC}) +chip_gn_arg_string("zephyr_ar" ${CMAKE_AR}) +chip_gn_arg_string("zephyr_cc" ${CMAKE_C_COMPILER}) +chip_gn_arg_string("zephyr_cxx" ${CMAKE_CXX_COMPILER}) +chip_gn_arg_string("chip_project_config_include" "${CHIP_PROJECT_CONFIG}") +chip_gn_arg_string("chip_system_project_config_include" "${CHIP_PROJECT_CONFIG}") +chip_gn_arg_bool ("is_debug" CONFIG_DEBUG) +chip_gn_arg_bool ("chip_enable_openthread" CONFIG_NET_L2_OPENTHREAD) +chip_gn_arg_bool ("chip_openthread_ftd" CONFIG_OPENTHREAD_FTD) +chip_gn_arg_bool ("chip_inet_config_enable_ipv4" CONFIG_NET_IPV4) +chip_gn_arg_bool ("chip_build_tests" CONFIG_CHIP_BUILD_TESTS) +chip_gn_arg_bool ("chip_inet_config_enable_tcp_endpoint" CONFIG_CHIP_BUILD_TESTS) +chip_gn_arg_bool ("chip_build_libshell" CONFIG_CHIP_LIB_SHELL) + +if (CONFIG_CHIP_ENABLE_DNSSD_SRP) + chip_gn_arg_string("chip_mdns" "platform") +endif() + +file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/args.gn CONTENT ${CHIP_GN_ARGS}) + +# ============================================================================== +# Define 'chip-gn' target that builds CHIP library(ies) with GN build system +# ============================================================================== + +ExternalProject_Add( + chip-gn + PREFIX ${CMAKE_CURRENT_BINARY_DIR} + SOURCE_DIR ${CHIP_ROOT} + BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR} + CONFIGURE_COMMAND ${GN_EXECUTABLE} + --root=${CHIP_ROOT} + --root-target=${GN_ROOT_TARGET} + --dotfile=${GN_ROOT_TARGET}/.gn + --script-executable=${Python3_EXECUTABLE} + gen --check --fail-on-unused-args ${CMAKE_CURRENT_BINARY_DIR} + BUILD_COMMAND ninja + INSTALL_COMMAND "" + BUILD_BYPRODUCTS ${CHIP_LIBRARIES} + BUILD_ALWAYS TRUE + USES_TERMINAL_CONFIGURE TRUE + USES_TERMINAL_BUILD TRUE +) +add_dependencies(chip-gn kernel) + +# ============================================================================== +# Define 'chip' target that exposes CHIP headers & libraries to the application +# ============================================================================== + +zephyr_interface_library_named(chip) +target_compile_definitions(chip INTERFACE CHIP_HAVE_CONFIG_H) +target_include_directories(chip INTERFACE + ${CHIP_ROOT}/src + ${CHIP_ROOT}/src/include + ${CHIP_ROOT}/src/lib + ${CHIP_ROOT}/third_party/nlassert/repo/include + ${CMAKE_CURRENT_BINARY_DIR}/gen/include +) +target_link_directories(chip INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/lib) + +if (CONFIG_CHIP_LIB_SHELL) + target_link_options(chip INTERFACE -Wl,--whole-archive -lCHIPShell -Wl,--no-whole-archive) +endif() + +target_link_libraries(chip INTERFACE -Wl,--start-group ${CHIP_LIBRARIES} -Wl,--end-group) +add_dependencies(chip chip-gn) + +endif() # CONFIG_CHIP \ No newline at end of file diff --git a/config/zephyr/chip-module/Kconfig b/config/zephyr/chip-module/Kconfig new file mode 100644 index 00000000000000..90c7d73f470b8f --- /dev/null +++ b/config/zephyr/chip-module/Kconfig @@ -0,0 +1,17 @@ +# +# Copyright (c) 2021 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. +# + +rsource "../Kconfig" \ No newline at end of file diff --git a/config/zephyr/chip-module/Kconfig.defaults b/config/zephyr/chip-module/Kconfig.defaults new file mode 100644 index 00000000000000..4cf4edea17a939 --- /dev/null +++ b/config/zephyr/chip-module/Kconfig.defaults @@ -0,0 +1,225 @@ +# +# Copyright (c) 2022 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# The purpose of this file is to define new default values of settings used when building Matter samples. +# This file only changes defaults and thus all symbols here must be promptless +# and safeguarded so that they only are applied when building Matter. + +if CHIP + +config LOG + bool + default y + +if LOG + +choice LOG_MODE + default LOG_MODE_MINIMAL +endchoice + +choice MATTER_LOG_LEVEL_CHOICE + default MATTER_LOG_LEVEL_DBG +endchoice + +config LOG_DEFAULT_LEVEL + int + default 2 + +endif + +config PRINTK_SYNC + bool + default y + +config ASSERT + bool + default y + +config HW_STACK_PROTECTION + bool + default y + +config FPU + bool + default y + +config SHELL + bool + default y + +# Enable getting reboot reasons information +config HWINFO + bool + default y + +# Generic networking options +config NET_SOCKETS_POSIX_NAMES + bool + default n + +# Application stack size +config MAIN_STACK_SIZE + int + default 8192 + +config INIT_STACKS + bool + default y + +config CHIP_DEVICE_VENDOR_ID + int + default 65521 + +config CHIP_DEVICE_PRODUCT_ID + int + default 32768 + +# Disable certain parts of Zephyr IPv6 stack +config NET_IPV6_NBR_CACHE + bool + default n + +config NET_IPV6_MLD + bool + default y + +config NET_IF_MCAST_IPV6_ADDR_COUNT + int + default 14 + +# Network buffers +config NET_PKT_RX_COUNT + int + default 16 + +config NET_PKT_TX_COUNT + int + default 16 + +config NET_BUF_RX_COUNT + int + default 80 + +config NET_BUF_TX_COUNT + int + default 80 + +# Bluetooth Low Energy configs +config BT + bool + default y + +config BT_PERIPHERAL + bool + default y + +config BT_PERIPHERAL_PREF_MIN_INT + int + default 36 + +config BT_PERIPHERAL_PREF_MAX_INT + int + default 36 + +config BT_GAP_AUTO_UPDATE_CONN_PARAMS + bool + default y + +config BT_GATT_DYNAMIC_DB + bool + default y + +config BT_DEVICE_NAME_DYNAMIC + bool + default y + +config BT_DEVICE_NAME_MAX + int + default 15 + +config BT_MAX_CONN + int + default 1 + +config BT_L2CAP_TX_MTU + int + default 247 + +config BT_BUF_ACL_RX_SIZE + int + default 251 + +config BT_BUF_ACL_TX_SIZE + int + default 251 + +config BT_RX_STACK_SIZE + int + default 1200 + +config CHIP_OTA_REQUESTOR + bool + default y + +# Enable extended discovery +config CHIP_EXTENDED_DISCOVERY + bool + default y + +config NVS_LOOKUP_CACHE + bool + default y + +# Enable OpenThread +config NET_L2_OPENTHREAD + bool + default y + +# Enable mbedTLS +config MBEDTLS_ENABLE_HEAP + bool + default y + +config MBEDTLS_HEAP_SIZE + int + default 15360 + +# Disable not used shell modules +config SENSOR_SHELL + bool + default n + +config DEVICE_SHELL + bool + default n + +config DATE_SHELL + bool + default n + +config DEVMEM_SHELL + bool + default n + +config MCUBOOT_SHELL + bool + default n + +config FLASH_SHELL + bool + default n + +endif # CHIP diff --git a/config/zephyr/chip-module/Kconfig.features b/config/zephyr/chip-module/Kconfig.features new file mode 100644 index 00000000000000..bc800095dc7ce0 --- /dev/null +++ b/config/zephyr/chip-module/Kconfig.features @@ -0,0 +1,68 @@ +# +# Copyright (c) 2022 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# The purpose of this file is to define Kconfig options enabling specific features. +# Feature options will define defaults for settings that are related to the specific feature. + +if CHIP + +# MCU Manager and SMP configuration +config MCUMGR + bool + default y + +config MCUMGR_CMD_IMG_MGMT + bool + default y + +config MCUMGR_CMD_OS_MGMT + bool + default y + +config MCUMGR_SMP_BT + bool + default y + +config MCUMGR_SMP_BT_AUTHEN + bool + default n + +config MCUMGR_BUF_COUNT + int + default 6 + +# Increase BT MTU and RX buffer for big size DFU messages +config BT_L2CAP_TX_MTU + int + default 498 + +config BT_BUF_ACL_RX_SIZE + int + default 502 + +# Increase MCUMGR_BUF_SIZE, as it must be big enough to fit MAX MTU + overhead and for single-image DFU default is 384 B +config MCUMGR_BUF_SIZE + int + default 1024 + +# Increase system workqueue size, as SMP is processed within it +config SYSTEM_WORKQUEUE_STACK_SIZE + int + default 2800 + +endif # CHIP_DFU_OVER_BT_SMP + +endif # CHIP diff --git a/config/zephyr/chip-module/Kconfig.mcuboot.defaults b/config/zephyr/chip-module/Kconfig.mcuboot.defaults new file mode 100644 index 00000000000000..4d5979330000f4 --- /dev/null +++ b/config/zephyr/chip-module/Kconfig.mcuboot.defaults @@ -0,0 +1,89 @@ +# +# Copyright (c) 2022 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# The purpose of this file is to define new default values of settings used when building mcuboot child image for Matter samples. + +config MAIN_STACK_SIZE + int + default 10240 + +config BOOT_SWAP_SAVE_ENCTLV + bool + default n + +config BOOT_ENCRYPT_RSA + bool + default n + +config BOOT_ENCRYPT_EC256 + bool + default n + +config BOOT_ENCRYPT_X25519 + bool + default n + +config BOOT_BOOTSTRAP + bool + default n + +config PM + bool + default n + +config FLASH + bool + default y + +config FPROTECT + bool + default y + +config BOOT_MAX_IMG_SECTORS + int + default 256 + +config LOG + bool + default n + +config CONSOLE_HANDLER + bool + default n + +config BOOT_BANNER + bool + default n + +config TIMESLICING + bool + default n + +config RESET_ON_FATAL_ERROR + bool + default n + +config MULTITHREADING + bool + default n + +config TICKLESS_KERNEL + bool + default n + +config TIMEOUT_64BIT + bool + default n diff --git a/config/zephyr/chip-module/Kconfig.mcuboot.root b/config/zephyr/chip-module/Kconfig.mcuboot.root new file mode 100644 index 00000000000000..e8756636dfd66d --- /dev/null +++ b/config/zephyr/chip-module/Kconfig.mcuboot.root @@ -0,0 +1,21 @@ +# +# Copyright (c) 2022 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# The purpose of this file is to create a wrapper Kconfig file that will be set as +# mcuboot_KCONFIG_ROOT and processed before any other Kconfig for mcuboot child image. + +rsource "Kconfig.mcuboot.defaults" +source "${ZEPHYR_BASE}/../bootloader/mcuboot/boot/zephyr/Kconfig" diff --git a/config/zephyr/chip-module/Kconfig.multiprotocol_rpmsg.defaults b/config/zephyr/chip-module/Kconfig.multiprotocol_rpmsg.defaults new file mode 100644 index 00000000000000..dea52bae56e2f4 --- /dev/null +++ b/config/zephyr/chip-module/Kconfig.multiprotocol_rpmsg.defaults @@ -0,0 +1,91 @@ +# +# Copyright (c) 2022 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# The purpose of this file is to define new default values of settings used when building multiprotocol_rpmsg child image for Matter samples. + +config LOG + bool + default n + +config HEAP_MEM_POOL_SIZE + int + default 8192 + +config MAIN_STACK_SIZE + int + default 2048 + +config SYSTEM_WORKQUEUE_STACK_SIZE + int + default 2048 + +config BT + bool + default y + +config BT_HCI_RAW + bool + default y + +config BT_MAX_CONN + int + default 1 + +config BT_PERIPHERAL + bool + default y + +config BT_CENTRAL + bool + default n + +config BT_BUF_ACL_RX_SIZE + int + default 502 + +config BT_BUF_ACL_TX_SIZE + int + default 251 + +config BT_CTLR_DATA_LENGTH_MAX + int + default 251 + +config BT_CTLR_ASSERT_HANDLER + bool + default y + +config BT_HCI_RAW_RESERVE + int + default 1 + +# Workaround: Unable to allocate command buffer when using K_NO_WAIT since +# Host number of completed commands does not follow normal flow control. +config BT_BUF_CMD_TX_COUNT + int + default 10 + +config ASSERT + bool + default y + +config DEBUG_INFO + bool + default y + +config EXCEPTION_STACK_TRACE + bool + default y diff --git a/config/zephyr/chip-module/Kconfig.multiprotocol_rpmsg.root b/config/zephyr/chip-module/Kconfig.multiprotocol_rpmsg.root new file mode 100644 index 00000000000000..b34c82243585b4 --- /dev/null +++ b/config/zephyr/chip-module/Kconfig.multiprotocol_rpmsg.root @@ -0,0 +1,21 @@ +# +# Copyright (c) 2022 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# The purpose of this file is to create a wrapper Kconfig file that will be set as +# multiprotocol_rpmsg_KCONFIG_ROOT and processed before any other Kconfig for multiprotocol_rpmsg child image. + +rsource "Kconfig.multiprotocol_rpmsg.defaults" +source "Kconfig.zephyr" diff --git a/config/zephyr/chip-module/make_gn_args.py b/config/zephyr/chip-module/make_gn_args.py new file mode 100644 index 00000000000000..f30cd459a6e7d4 --- /dev/null +++ b/config/zephyr/chip-module/make_gn_args.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 + +# +# Copyright (c) 2021 Project CHIP Authors +# All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import argparse +import re +import sys + +GN_SPECIAL_CHARACTERS = r'(["$\\])' +GN_CFLAG_EXCLUDES = [ + '-fno-asynchronous-unwind-tables', + '-fno-common', + '-fno-defer-pop', + '-fno-reorder-functions', + '-ffunction-sections', + '-fdata-sections', + '-g*', + '-O*', + '-W*', +] + + +def escape_strings(gn_args): + return [[key, re.sub(GN_SPECIAL_CHARACTERS, r'\\\1', value)] for key, value in gn_args] + + +def write_gn_args(args): + if args.module: + sys.stdout.write('import("{}")\n'.format(args.module)) + + for key, value in args.arg: + sys.stdout.write('{} = {}\n'.format(key, value)) + + for key, value in args.arg_string: + sys.stdout.write('{} = "{}"\n'.format(key, value)) + + cflag_excludes = ', '.join(['"{}"'.format(exclude) + for exclude in GN_CFLAG_EXCLUDES]) + + for key, value in args.arg_cflags: + sys.stdout.write('{} = filter_exclude(string_split("{}"), [{}])\n'.format( + key, value, cflag_excludes)) + + +def main(): + parser = argparse.ArgumentParser(fromfile_prefix_chars='@') + parser.add_argument('--module', action='store') + parser.add_argument('--arg', action='append', nargs=2, default=[]) + parser.add_argument('--arg-string', action='append', nargs=2, default=[]) + parser.add_argument('--arg-cflags', action='append', nargs=2, default=[]) + args = parser.parse_args() + args.arg_string = escape_strings(args.arg_string) + args.arg_cflags = escape_strings(args.arg_cflags) + write_gn_args(args) + + +if __name__ == "__main__": + main() diff --git a/config/zephyr/chip-module/zephyr/module.yml b/config/zephyr/chip-module/zephyr/module.yml new file mode 100644 index 00000000000000..c09c9ea59e218a --- /dev/null +++ b/config/zephyr/chip-module/zephyr/module.yml @@ -0,0 +1,22 @@ +# +# Copyright (c) 2021 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. +# + +name: connectedhomeip +build: + cmake: . + kconfig: Kconfig + depends: + - openthread diff --git a/docs/guides/infineon_p6_software_update.md b/docs/guides/infineon_p6_software_update.md new file mode 100644 index 00000000000000..ae88abc5701260 --- /dev/null +++ b/docs/guides/infineon_p6_software_update.md @@ -0,0 +1,76 @@ +# Matter Software Update with Infineon P6 example applications + +The Over The Air (OTA) Software Update functionality can be added to any of the +Infineon P6 example applications by passing the `chip_enable_ota_requestor=true` +option to the build script. + +## Running the OTA Download scenario + +- An OTA Provider is a node that can respond to the OTA Requestors' queries + about available software updates and share the update packages with them. An + OTA Requestor is any node that needs to be updated and can communicate with + the OTA Provider to fetch applicable software updates. In the procedure + described below, the OTA Provider will be a Linux application and the + example running on the Infineon P6 board will work as the OTA Requestor. + +- On a Linux or Darwin platform build the chip-tool and the ota-provider-app + as follows: + + ``` + scripts/examples/gn_build_example.sh examples/chip-tool out/ + scripts/examples/gn_build_example.sh examples/ota-provider-app/linux out/debug chip_config_network_layer_ble=false + ``` + +- Build the P6 OTA Requestor application from the chip root dir: + + $ ./examples//p6/ota_base_build.sh + +- Build the P6 OTA Update application from the chip root dir: + + $ ./examples//p6/ota_update_build.sh + +* Additionally a pre-compiled bootloader must be flashed to the board using + [Cypress Programmer](https://softwaretools.infineon.com/tools/com.ifx.tb.tool.cypressprogrammer). + This image can be found at: + + $ ./third_party/p6/p6_sdk/ota/matter-psoc6-mcuboot-bootloader.hex + +* In a terminal start the Provider app passing to it the path to the Matter + OTA file created in the previous step:(output of ota_update_build step) + + ``` + rm -r /tmp/chip_* + ./out/debug/chip-ota-provider-app -f chip-p6-lighting-example.ota + ``` + +* In a separate terminal run the chip-tool commands to provision the Provider: + + ``` + ./out/chip-tool pairing onnetwork 1 20202021 + ./out/chip-tool accesscontrol write acl '[{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [112233], "targets": null}, {"fabricIndex": 1, "privilege": 3, "authMode": 2, "subjects": null, "targets": null}]' 1 0 + ``` + +* If the application device had been previously commissioned press USER Button + 2 to factory-reset the device. + +* In the chip-tool terminal enter: + + ``` + ./out/chip-tool pairing ble-wifi 2 20202021 3840 + ``` + +* Once the commissioning process completes enter: + + ``` + ./out/chip-tool otasoftwareupdaterequestor announce-ota-provider 1 0 0 0 2 0 + ``` + +* The application device will connect to the Provider and start the image + download. Status of the transfer can be monitored in the OTA Provider + terminal. Once the image is downloaded the device will reboot into the + downloaded image. + +In order for the Provider to successfully serve the image to a device during the +OTA Software Update process the softwareVersion parameter in the Provider config +file must be greater than the CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION +parameter set in the application's CHIPProjectConfig.h file. diff --git a/docs/guides/nrfconnect_examples_configuration.md b/docs/guides/nrfconnect_examples_configuration.md index 236008b740f6c4..119852b3929a89 100644 --- a/docs/guides/nrfconnect_examples_configuration.md +++ b/docs/guides/nrfconnect_examples_configuration.md @@ -179,6 +179,12 @@ following Kconfig options: - `CONFIG_OPENTHREAD_MTD` - `CONFIG_CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT` +The following Kconfig options can be used to tune Thread Sleepy End Device wake +intervals: + +- `CONFIG_CHIP_SED_IDLE_INTERVAL` +- `CONFIG_CHIP_SED_ACTIVE_INTERVAL` + **Commissioning with NFC support** You can configure the Matter protocol to use an NFC tag for commissioning, diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter index feff6233251481..0c3584f915158f 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter @@ -1461,6 +1461,7 @@ server cluster GeneralCommissioning = 48 { struct BasicCommissioningInfo { int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; } attribute access(write: administer) int64u breadcrumb = 0; @@ -1728,74 +1729,6 @@ server cluster Groups = 4 { command access(invoke: manage) AddGroupIfIdentifying(AddGroupIfIdentifyingRequest): DefaultSuccess = 5; } -server cluster IasZone = 1280 { - enum IasEnrollResponseCode : ENUM8 { - kSuccess = 0; - kNotSupported = 1; - kNoEnrollPermit = 2; - kTooManyZones = 3; - } - - enum IasZoneType : ENUM16 { - kStandardCie = 0; - kMotionSensor = 13; - kContactSwitch = 21; - kFireSensor = 40; - kWaterSensor = 42; - kGasSensor = 43; - kPersonalEmergencyDevice = 44; - kVibrationMovementSensor = 45; - kRemoteControl = 271; - kKeyFob = 277; - kKeypad = 541; - kStandardWarningDevice = 549; - kGlassBreakSensor = 550; - kCarbonMonoxideSensor = 551; - kSecurityRepeater = 553; - kInvalidZoneType = 65535; - } - - bitmap IasZoneStatus : BITMAP16 { - kAlarm1 = 0x1; - kAlarm2 = 0x2; - kTamper = 0x4; - kBattery = 0x8; - kSupervisionReports = 0x10; - kRestoreReports = 0x20; - kTrouble = 0x40; - kAc = 0x80; - kTest = 0x100; - kBatteryDefect = 0x200; - } - - readonly attribute enum8 zoneState = 0; - readonly attribute enum16 zoneType = 1; - readonly attribute bitmap16 zoneStatus = 2; - attribute node_id iasCieAddress = 16; - readonly attribute int8u zoneId = 17; - readonly attribute bitmap32 featureMap = 65532; - readonly attribute int16u clusterRevision = 65533; - - request struct ZoneEnrollResponseRequest { - IasEnrollResponseCode enrollResponseCode = 0; - INT8U zoneId = 1; - } - - response struct ZoneStatusChangeNotification = 0 { - IasZoneStatus zoneStatus = 0; - BITMAP8 extendedStatus = 1; - INT8U zoneId = 2; - INT16U delay = 3; - } - - response struct ZoneEnrollRequest = 1 { - IasZoneType zoneType = 0; - INT16U manufacturerCode = 1; - } - - command ZoneEnrollResponse(ZoneEnrollResponseRequest): DefaultSuccess = 0; -} - server cluster Identify = 3 { enum IdentifyEffectIdentifier : ENUM8 { kBlink = 0; @@ -2170,6 +2103,7 @@ server cluster ModeSelect = 80 { readonly attribute attrib_id attributeList[] = 65531; readonly attribute bitmap32 featureMap = 65532; readonly attribute int16u clusterRevision = 65533; + readonly attribute int8u manufacturerExtension = 4293984257; request struct ChangeToModeRequest { INT8U newMode = 0; @@ -3431,11 +3365,15 @@ server cluster Thermostat = 513 { attribute access(write: manage) ThermostatControlSequence controlSequenceOfOperation = 27; attribute access(write: manage) enum8 systemMode = 28; readonly attribute enum8 thermostatRunningMode = 30; - readonly attribute enum8 startOfWeek = 32; - readonly attribute int8u numberOfWeeklyTransitions = 33; - readonly attribute int8u numberOfDailyTransitions = 34; readonly attribute bitmap32 featureMap = 65532; readonly attribute int16u clusterRevision = 65533; + + request struct SetpointRaiseLowerRequest { + SetpointAdjustMode mode = 0; + INT8S amount = 1; + } + + command SetpointRaiseLower(SetpointRaiseLowerRequest): DefaultSuccess = 0; } server cluster ThermostatUserInterfaceConfiguration = 516 { @@ -3774,14 +3712,7 @@ server cluster WindowCovering = 258 { kTiltEncoderControlled = 0x40; } - bitmap Mode : BITMAP8 { - kMotorDirectionReversed = 0x1; - kCalibrationMode = 0x2; - kMaintenanceMode = 0x4; - kLedFeedback = 0x8; - } - - bitmap WcFeature : BITMAP32 { + bitmap Feature : BITMAP32 { kLift = 0x1; kTilt = 0x2; kPositionAwareLift = 0x4; @@ -3789,13 +3720,20 @@ server cluster WindowCovering = 258 { kPositionAwareTilt = 0x10; } - bitmap WcOperationalStatus : BITMAP8 { + bitmap Mode : BITMAP8 { + kMotorDirectionReversed = 0x1; + kCalibrationMode = 0x2; + kMaintenanceMode = 0x4; + kLedFeedback = 0x8; + } + + bitmap OperationalStatus : BITMAP8 { kGlobal = 0x3; kLift = 0xC; kTilt = 0x30; } - bitmap WcSafetyStatus : BITMAP16 { + bitmap SafetyStatus : BITMAP16 { kRemoteLockout = 0x1; kTamperDetection = 0x2; kFailedCommunication = 0x4; @@ -3820,7 +3758,7 @@ server cluster WindowCovering = 258 { readonly attribute ConfigStatus configStatus = 7; readonly attribute nullable Percent currentPositionLiftPercentage = 8; readonly attribute nullable Percent currentPositionTiltPercentage = 9; - readonly attribute bitmap8 operationalStatus = 10; + readonly attribute OperationalStatus operationalStatus = 10; readonly attribute nullable Percent100ths targetPositionLiftPercent100ths = 11; readonly attribute nullable Percent100ths targetPositionTiltPercent100ths = 12; readonly attribute EndProductType endProductType = 13; @@ -3831,7 +3769,7 @@ server cluster WindowCovering = 258 { readonly attribute int16u installedOpenLimitTilt = 18; readonly attribute int16u installedClosedLimitTilt = 19; attribute access(write: manage) Mode mode = 23; - readonly attribute bitmap16 safetyStatus = 26; + readonly attribute SafetyStatus safetyStatus = 26; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute attrib_id attributeList[] = 65531; @@ -4290,7 +4228,7 @@ endpoint 1 { ram attribute numberOfPositions default = 2; ram attribute currentPosition; ram attribute multiPressMax default = 2; - ram attribute featureMap; + ram attribute featureMap default = 1; ram attribute clusterRevision default = 1; } @@ -4324,6 +4262,7 @@ endpoint 1 { callback attribute attributeList; ram attribute featureMap default = 1; ram attribute clusterRevision default = 1; + ram attribute manufacturerExtension default = 255; } server cluster DoorLock { @@ -4445,10 +4384,7 @@ endpoint 1 { ram attribute controlSequenceOfOperation default = 0x04; ram attribute systemMode default = 0x01; ram attribute thermostatRunningMode; - ram attribute startOfWeek; - ram attribute numberOfWeeklyTransitions default = 7; - ram attribute numberOfDailyTransitions default = 4; - ram attribute featureMap default = 0x002b; + ram attribute featureMap default = 0x0023; ram attribute clusterRevision default = 5; } @@ -4586,16 +4522,6 @@ endpoint 1 { ram attribute clusterRevision default = 3; } - server cluster IasZone { - ram attribute zoneState; - ram attribute zoneType; - ram attribute zoneStatus; - ram attribute iasCieAddress; - ram attribute zoneId default = 0xff; - ram attribute featureMap; - ram attribute clusterRevision default = 2; - } - server cluster WakeOnLan { ram attribute MACAddress; ram attribute featureMap; diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap index 99d0476bad246e..933f095975a3c4 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap @@ -18,7 +18,7 @@ "package": [ { "pathRelativity": "relativeToZap", - "path": "../../../src/app/zap-templates/zcl/zcl.json", + "path": "../../../src/app/zap-templates/zcl/zcl-with-test-extensions.json", "version": "ZCL Test Data", "type": "zcl-properties" }, @@ -12093,7 +12093,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0", + "defaultValue": "1", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -12664,6 +12664,22 @@ "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 + }, + { + "name": "ManufacturerExtension", + "code": 4293984257, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "255", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 } ] }, @@ -14628,7 +14644,7 @@ "code": 0, "mfgCode": null, "source": "client", - "incoming": 0, + "incoming": 1, "outgoing": 1 }, { @@ -14971,7 +14987,7 @@ "mfgCode": null, "side": "server", "type": "enum8", - "included": 1, + "included": 0, "storageOption": "RAM", "singleton": 0, "bounded": 0, @@ -14987,7 +15003,7 @@ "mfgCode": null, "side": "server", "type": "int8u", - "included": 1, + "included": 0, "storageOption": "RAM", "singleton": 0, "bounded": 0, @@ -15003,7 +15019,7 @@ "mfgCode": null, "side": "server", "type": "int8u", - "included": 1, + "included": 0, "storageOption": "RAM", "singleton": 0, "bounded": 0, @@ -15039,7 +15055,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x002b", + "defaultValue": "0x0023", "reportable": 1, "minInterval": 0, "maxInterval": 65344, diff --git a/examples/all-clusters-app/ameba/chip_main.cmake b/examples/all-clusters-app/ameba/chip_main.cmake index 2e9a5f87f257d1..d15dc800ae26ff 100755 --- a/examples/all-clusters-app/ameba/chip_main.cmake +++ b/examples/all-clusters-app/ameba/chip_main.cmake @@ -18,7 +18,8 @@ set(dir_pw_third_party_nanopb "${chip_dir}/third_party/nanopb/repo" CACHE STRING pw_set_module_config(pw_rpc_CONFIG pw_rpc.disable_global_mutex_config) pw_set_backend(pw_log pw_log_basic) -pw_set_backend(pw_assert pw_assert_log) +pw_set_backend(pw_assert.check pw_assert_log.check_backend) +pw_set_backend(pw_assert.assert pw_assert.assert_compatibility_backend) pw_set_backend(pw_sys_io pw_sys_io.ameba) pw_set_backend(pw_trace pw_trace_tokenized) @@ -36,7 +37,7 @@ pw_proto_library(attributes_service STRIP_PREFIX ${chip_dir}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(button_service @@ -47,7 +48,7 @@ pw_proto_library(button_service STRIP_PREFIX ${chip_dir}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(device_service @@ -60,7 +61,7 @@ pw_proto_library(device_service STRIP_PREFIX ${chip_dir}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(lighting_service @@ -71,7 +72,7 @@ pw_proto_library(lighting_service STRIP_PREFIX ${chip_dir}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(locking_service @@ -82,7 +83,7 @@ pw_proto_library(locking_service STRIP_PREFIX ${chip_dir}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(wifi_service @@ -93,7 +94,7 @@ pw_proto_library(wifi_service PREFIX wifi_service DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto STRIP_PREFIX ${chip_dir}/examples/common/pigweed/protos ) @@ -141,6 +142,8 @@ list( ${chip_dir}/examples/all-clusters-app/ameba/main/Globals.cpp ${chip_dir}/examples/all-clusters-app/ameba/main/LEDWidget.cpp ${chip_dir}/examples/all-clusters-app/ameba/main/DsoHack.cpp + + ${chip_dir}/examples/providers/DeviceInfoProviderImpl.cpp ) add_library( @@ -181,6 +184,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/providers ${chip_dir_output}/gen/include ${chip_dir}/src/include/ ${chip_dir}/src/lib/ diff --git a/examples/all-clusters-app/ameba/main/chipinterface.cpp b/examples/all-clusters-app/ameba/main/chipinterface.cpp index 8dc7e1e9edb1ea..673f4d5238ee23 100644 --- a/examples/all-clusters-app/ameba/main/chipinterface.cpp +++ b/examples/all-clusters-app/ameba/main/chipinterface.cpp @@ -22,6 +22,7 @@ #include "Globals.h" #include "LEDWidget.h" #include "chip_porting.h" +#include #include #include @@ -89,6 +90,7 @@ Identify gIdentify1 = { #endif static DeviceCallbacks EchoCallbacks; +chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider; static void InitServer(intptr_t context) { @@ -96,6 +98,8 @@ static void InitServer(intptr_t context) static chip::CommonCaseDeviceServerInitParams initParams; initParams.InitializeStaticResourcesBeforeServerInit(); chip::Server::GetInstance().Init(initParams); + gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); + chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); // Initialize device attestation config SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); diff --git a/examples/all-clusters-app/cc13x2x7_26x2x7/args.gni b/examples/all-clusters-app/cc13x2x7_26x2x7/args.gni index e7438af247a9c2..bd6e49f7871b4f 100644 --- a/examples/all-clusters-app/cc13x2x7_26x2x7/args.gni +++ b/examples/all-clusters-app/cc13x2x7_26x2x7/args.gni @@ -32,7 +32,7 @@ chip_enable_ota_requestor = false chip_openthread_ftd = false # Disable CHIP Logging -#chip_progress_logging = false +chip_progress_logging = false chip_detail_logging = false chip_automation_logging = false diff --git a/examples/all-clusters-app/esp32/CMakeLists.txt b/examples/all-clusters-app/esp32/CMakeLists.txt index d7907d6ba7762f..0cf459d3e725af 100644 --- a/examples/all-clusters-app/esp32/CMakeLists.txt +++ b/examples/all-clusters-app/esp32/CMakeLists.txt @@ -53,7 +53,8 @@ include(third_party/connectedhomeip/third_party/pigweed/repo/pw_build/pigweed.cm pw_set_module_config(pw_rpc_CONFIG pw_rpc.disable_global_mutex_config) pw_set_backend(pw_log pw_log_basic) -pw_set_backend(pw_assert pw_assert_log) +pw_set_backend(pw_assert.check pw_assert_log.check_backend) +pw_set_backend(pw_assert.assert pw_assert.assert_compatibility_backend) pw_set_backend(pw_sys_io pw_sys_io.esp32) pw_set_backend(pw_trace pw_trace_tokenized) diff --git a/examples/all-clusters-app/esp32/main/CMakeLists.txt b/examples/all-clusters-app/esp32/main/CMakeLists.txt index df3431cd088b9d..4f8db9d121402d 100644 --- a/examples/all-clusters-app/esp32/main/CMakeLists.txt +++ b/examples/all-clusters-app/esp32/main/CMakeLists.txt @@ -78,7 +78,6 @@ set(SRC_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/diagnostic-logs-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/door-lock-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/occupancy-sensor-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ias-zone-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ethernet-network-diagnostics-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/localization-configuration-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/time-format-localization-server" @@ -88,7 +87,6 @@ set(SRC_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/power-source-configuration-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/power-source-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/all-clusters-app/all-clusters-common/src" - #${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ias-zone-client ) if (CONFIG_ENABLE_PW_RPC) @@ -153,7 +151,7 @@ pw_proto_library(attributes_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(button_service @@ -164,7 +162,7 @@ pw_proto_library(button_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(descriptor_service @@ -175,7 +173,7 @@ pw_proto_library(descriptor_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(device_service @@ -188,7 +186,7 @@ pw_proto_library(device_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(lighting_service @@ -199,7 +197,7 @@ pw_proto_library(lighting_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(locking_service @@ -210,7 +208,7 @@ pw_proto_library(locking_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(wifi_service @@ -221,7 +219,7 @@ pw_proto_library(wifi_service PREFIX wifi_service DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos ) diff --git a/examples/all-clusters-app/esp32/main/DeviceWithDisplay.cpp b/examples/all-clusters-app/esp32/main/DeviceWithDisplay.cpp index ef87982f8eb5eb..246825835638eb 100644 --- a/examples/all-clusters-app/esp32/main/DeviceWithDisplay.cpp +++ b/examples/all-clusters-app/esp32/main/DeviceWithDisplay.cpp @@ -301,7 +301,9 @@ class EditAttributeListModel : public TouchesMatterStackModel { // update the operational status here for hardcoded endpoint 1 ESP_LOGI(TAG, "Operational status changed to : %d", n); - app::Clusters::WindowCovering::Attributes::OperationalStatus::Set(1, static_cast(n)); + chip::BitFlags opStatus = + static_cast>(n); + app::Clusters::WindowCovering::Attributes::OperationalStatus::Set(1, opStatus); } else if (name == "Bat remaining") { @@ -676,7 +678,9 @@ void SetupPretendDevices() AddAttribute("Current Tilt", "5"); app::Clusters::WindowCovering::Attributes::CurrentPositionTiltPercent100ths::Set(1, static_cast(5 * 100)); AddAttribute("Opr Status", "0"); - app::Clusters::WindowCovering::Attributes::OperationalStatus::Set(1, static_cast(0)); + chip::BitFlags opStatus = + static_cast>(0); + app::Clusters::WindowCovering::Attributes::OperationalStatus::Set(1, opStatus); AddDevice("Battery"); AddEndpoint("1"); diff --git a/examples/all-clusters-app/linux/AppOptions.cpp b/examples/all-clusters-app/linux/AppOptions.cpp index c3f80a2302a484..ef42660972f8d9 100644 --- a/examples/all-clusters-app/linux/AppOptions.cpp +++ b/examples/all-clusters-app/linux/AppOptions.cpp @@ -21,6 +21,8 @@ #include #include +using namespace chip::ArgParser; + using chip::ArgParser::OptionDef; using chip::ArgParser::OptionSet; using chip::ArgParser::PrintArgError; @@ -55,8 +57,8 @@ bool AppOptions::HandleOptions(const char * program, OptionSet * options, int id OptionSet * AppOptions::GetOptions() { static OptionDef optionsDef[] = { - { "dac_provider", chip::ArgParser::kArgumentRequired, kOptionDacProviderFilePath }, - { "min_commissioning_timeout", chip::ArgParser::kArgumentRequired, kOptionMinCommissioningTimeout }, + { "dac_provider", kArgumentRequired, kOptionDacProviderFilePath }, + { "min_commissioning_timeout", kArgumentRequired, kOptionMinCommissioningTimeout }, {}, }; diff --git a/examples/all-clusters-app/linux/main-common.cpp b/examples/all-clusters-app/linux/main-common.cpp index 129180f7ac1be5..d4d12553df70e7 100644 --- a/examples/all-clusters-app/linux/main-common.cpp +++ b/examples/all-clusters-app/linux/main-common.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -147,6 +148,52 @@ void HandleGeneralFaultEvent(intptr_t arg) } } +/** + * Should be called when a switch operation takes place on the Node. + */ +void HandleSwitchEvent(intptr_t arg) +{ + uint32_t eventId = static_cast(arg); + + EndpointId endpoint = 1; + uint8_t newPosition = 20; + uint8_t previousPosition = 10; + uint8_t count = 3; + + if (eventId == Clusters::Switch::Events::SwitchLatched::Id) + { + Clusters::SwitchServer::Instance().OnSwitchLatch(endpoint, newPosition); + } + else if (eventId == Clusters::Switch::Events::InitialPress::Id) + { + Clusters::SwitchServer::Instance().OnInitialPress(endpoint, newPosition); + } + else if (eventId == Clusters::Switch::Events::LongPress::Id) + { + Clusters::SwitchServer::Instance().OnLongPress(endpoint, newPosition); + } + else if (eventId == Clusters::Switch::Events::ShortRelease::Id) + { + Clusters::SwitchServer::Instance().OnShortRelease(endpoint, previousPosition); + } + else if (eventId == Clusters::Switch::Events::LongRelease::Id) + { + Clusters::SwitchServer::Instance().OnLongRelease(endpoint, previousPosition); + } + else if (eventId == Clusters::Switch::Events::MultiPressOngoing::Id) + { + Clusters::SwitchServer::Instance().OnMultiPressOngoing(endpoint, newPosition, count); + } + else if (eventId == Clusters::Switch::Events::MultiPressComplete::Id) + { + Clusters::SwitchServer::Instance().OnMultiPressComplete(endpoint, newPosition, count); + } + else + { + ChipLogError(DeviceLayer, "Unknow event ID:%d", eventId); + } +} + // when the shell is enabled, don't intercept signals since it prevents the user from // using expected commands like CTRL-C to quit the application. (see issue #17845) // We should stop using signals for those faults, and move to a different notification @@ -223,6 +270,42 @@ void OnGeneralFaultSignalHandler(int signum) PlatformMgr().ScheduleWork(HandleGeneralFaultEvent, static_cast(eventId)); } +void OnSwitchSignalHandler(int signum) +{ + ChipLogDetail(DeviceLayer, "Caught signal %d", signum); + + uint32_t eventId; + switch (signum) + { + case SIGTSTP: + eventId = Clusters::Switch::Events::SwitchLatched::Id; + break; + case SIGSTOP: + eventId = Clusters::Switch::Events::InitialPress::Id; + break; + case SIGTTOU: + eventId = Clusters::Switch::Events::LongPress::Id; + break; + case SIGWINCH: + eventId = Clusters::Switch::Events::ShortRelease::Id; + break; + case SIGQUIT: + eventId = Clusters::Switch::Events::LongRelease::Id; + break; + case SIGFPE: + eventId = Clusters::Switch::Events::MultiPressOngoing::Id; + break; + case SIGPIPE: + eventId = Clusters::Switch::Events::MultiPressComplete::Id; + break; + default: + ChipLogError(NotSpecified, "Unhandled signal: Should never happens"); + chipDie(); + break; + } + + PlatformMgr().ScheduleWork(HandleSwitchEvent, static_cast(eventId)); +} void SetupSignalHandlers() { // sigaction is not used here because Tsan interceptors seems to @@ -238,6 +321,13 @@ void SetupSignalHandlers() signal(SIGUSR2, OnGeneralFaultSignalHandler); signal(SIGHUP, OnGeneralFaultSignalHandler); signal(SIGTTIN, OnGeneralFaultSignalHandler); + signal(SIGTSTP, OnSwitchSignalHandler); + signal(SIGSTOP, OnSwitchSignalHandler); + signal(SIGTTOU, OnSwitchSignalHandler); + signal(SIGWINCH, OnSwitchSignalHandler); + signal(SIGQUIT, OnSwitchSignalHandler); + signal(SIGFPE, OnSwitchSignalHandler); + signal(SIGPIPE, OnSwitchSignalHandler); } #endif // !defined(ENABLE_CHIP_SHELL) diff --git a/examples/all-clusters-app/nrfconnect/README.md b/examples/all-clusters-app/nrfconnect/README.md index 29ca4bcb7e4648..101c286e304088 100644 --- a/examples/all-clusters-app/nrfconnect/README.md +++ b/examples/all-clusters-app/nrfconnect/README.md @@ -14,7 +14,8 @@ certification of a Matter device communicating over a low-power, 802.15.4 Thread network. The example behaves as a Matter accessory, that is a device that can be paired -into an existing Matter network and can be controlled by this network. +into an existing Matter network and can be controlled by this network. The +device works as a Thread Minimal End Device.
@@ -294,22 +295,6 @@ features like logs and command-line interface, run the following command: Remember to replace _build-target_ with the build target name of the Nordic Semiconductor's kit you own. -### Building with low-power configuration - -You can build the example using the low-power configuration, which enables -Thread's Sleepy End Device mode and disables debug features, such as the UART -console or the **LED 1** usage. - -To build for the low-power configuration, run the following command with -_build-target_ replaced with the build target name of the Nordic Semiconductor's -kit you own (for example `nrf52840dk_nrf52840`): - - $ west build -b build-target -- -DOVERLAY_CONFIG=overlay-low_power.conf - -For example, use the following command for `nrf52840dk_nrf52840`: - - $ west build -b nrf52840dk_nrf52840 -- -DOVERLAY_CONFIG=overlay-low_power.conf - ### Building with Device Firmware Upgrade support Support for DFU using Matter OTA is disabled by default. diff --git a/examples/all-clusters-app/nrfconnect/main/AppTask.cpp b/examples/all-clusters-app/nrfconnect/main/AppTask.cpp index 29391063b1eebb..106c3957f4c5af 100644 --- a/examples/all-clusters-app/nrfconnect/main/AppTask.cpp +++ b/examples/all-clusters-app/nrfconnect/main/AppTask.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -63,6 +64,40 @@ k_timer sFunctionTimer; chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider; +constexpr EndpointId kIdentifyEndpointId = 1; + +void OnIdentifyTriggerEffect(Identify * identify) +{ + ChipLogProgress(Zcl, "OnIdentifyTriggerEffect"); + switch (identify->mCurrentEffectIdentifier) + { + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BLINK: + ChipLogProgress(Zcl, "Effect: EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BLINK"); + break; + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BREATHE: + ChipLogProgress(Zcl, "Effect: EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BREATHE"); + break; + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_OKAY: + ChipLogProgress(Zcl, "Effect: EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_OKAY"); + break; + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_CHANNEL_CHANGE: + ChipLogProgress(Zcl, "Effect: EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_CHANNEL_CHANGE"); + break; + default: + ChipLogProgress(Zcl, "Effect: No identifier effect"); + break; + } + return; +} + +Identify sIdentify = { + chip::EndpointId{ kIdentifyEndpointId }, + [](Identify *) { ChipLogProgress(Zcl, "OnIdentifyStart"); }, + [](Identify *) { ChipLogProgress(Zcl, "OnIdentifyStop"); }, + EMBER_ZCL_IDENTIFY_IDENTIFY_TYPE_NONE, + OnIdentifyTriggerEffect, +}; + } // namespace constexpr EndpointId kNetworkCommissioningEndpointSecondary = 0xFFFE; diff --git a/examples/all-clusters-app/nrfconnect/main/include/CHIPProjectConfig.h b/examples/all-clusters-app/nrfconnect/main/include/CHIPProjectConfig.h index 7a2941f28621df..9fea28ec9fde12 100644 --- a/examples/all-clusters-app/nrfconnect/main/include/CHIPProjectConfig.h +++ b/examples/all-clusters-app/nrfconnect/main/include/CHIPProjectConfig.h @@ -29,5 +29,3 @@ // Use a default pairing code if one hasn't been provisioned in flash. #define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021 #define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 - -#define CHIP_DEVICE_CONFIG_SED_IDLE_INTERVAL 2000_ms32 diff --git a/examples/all-clusters-app/nrfconnect/overlay-low_power.conf b/examples/all-clusters-app/nrfconnect/overlay-low_power.conf deleted file mode 100644 index c962425f6ef937..00000000000000 --- a/examples/all-clusters-app/nrfconnect/overlay-low_power.conf +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# Enable MTD Sleepy End Device -CONFIG_CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT=y - -# Disable UART console -CONFIG_SHELL=n -CONFIG_LOG=n -CONFIG_UART_CONSOLE=n -CONFIG_SERIAL=n - -# Suspend devices when the CPU goes to sleep -CONFIG_PM_DEVICE=y - -# Disable auxiliary state LEDs -CONFIG_STATE_LEDS=n diff --git a/examples/all-clusters-app/p6/BUILD.gn b/examples/all-clusters-app/p6/BUILD.gn index 5b99c3f3b3b6f6..59ae7f12293bac 100644 --- a/examples/all-clusters-app/p6/BUILD.gn +++ b/examples/all-clusters-app/p6/BUILD.gn @@ -17,6 +17,7 @@ import("//build_overrides/chip.gni") import("//build_overrides/p6.gni") import("${build_root}/config/defaults.gni") +import("${chip_root}/src/platform/device.gni") import("${p6_sdk_build_root}/p6_executable.gni") import("${p6_sdk_build_root}/p6_sdk.gni") @@ -34,6 +35,50 @@ declare_args() { # Monitor & log memory usage at runtime. enable_heap_monitoring = false + + # Build update app + build_update_image = false +} + +config("p6_ota_config") { + ldflags = [ "-T/" + rebase_path( + "${chip_root}/third_party/p6/p6_sdk/ota/cy8c6xxa_cm4_dual_ota_int.ld", + "/", + "${p6_project_dir}") ] + + ldflags += [ "-Wl,--defsym,MCUBOOT_HEADER_SIZE=0x400,--defsym,MCUBOOT_BOOTLOADER_SIZE=0x18000,--defsym,CY_BOOT_PRIMARY_1_SIZE=0x1C0000" ] + + defines = [ + "P6_OTA", + "OTA_SUPPORT ", + "OTA_USE_EXTERNAL_FLASH", + "CY_BOOT_USE_EXTERNAL_FLASH", + "MCUBOOT_HEADER_SIZE=0x400", + "MCUBOOT_MAX_IMG_SECTORS=3584", + "CY_BOOT_SCRATCH_SIZE=0x00004000", + "MCUBOOT_BOOTLOADER_SIZE=0x00018000", + "CY_BOOT_BOOTLOADER_SIZE=0x00018000", + "CY_BOOT_PRIMARY_1_START=0x00018000", + "CY_BOOT_PRIMARY_1_SIZE=0x1C0000", + "CY_BOOT_SECONDARY_1_START=0x00000000", + "CY_BOOT_SECONDARY_1_SIZE=0x001C0000", + "CY_FLASH_ERASE_VALUE=0xFF", + "MCUBOOT_IMAGE_NUMBER=1", + "MCUBOOT_SLOT_SIZE=0x1C0000", + "MCUBOOT_SCRATCH_SIZE=0x4000", + "MCUBOOT_SECTOR_SIZE = 512", + "APP_VERSION_MAJOR=1", + "APP_VERSION_MINOR=0", + "APP_VERSION_BUILD=0", + "MCUBOOT_OVERWRITE_ONLY", + "CY_ENABLE_XIP_PROGRAM", + ] + + if (build_update_image) { + defines += [ "CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION=2" ] + } else { + defines += [ "CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION=1" ] + } } p6_sdk_sources("all_clusters_app_sdk_sources") { @@ -52,6 +97,27 @@ p6_sdk_sources("all_clusters_app_sdk_sources") { sources = [ "${p6_project_dir}/include/CHIPProjectConfig.h" ] public_configs = [ "${chip_root}/third_party/p6:p6_sdk_config" ] + + if (chip_enable_ota_requestor) { + sources += [ + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/bootutil/src/bootutil_misc.c", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/cy_flash_map.c", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/cy_flash_psoc6.c", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/cy_smif_psoc6.c", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/mem_config/mem_config_sfdp.c", + ] + include_dirs += [ + "${chip_root}/third_party/p6/p6_sdk/ota/config", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/mem_config/", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/include/", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/include/flash_map_backend/", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/sysflash/", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/bootutil/include", + ] + public_configs += [ ":p6_ota_config" ] + } } p6_executable("clusters_app") { diff --git a/examples/all-clusters-app/p6/README.md b/examples/all-clusters-app/p6/README.md index 25b8e53b04d697..1a859b7944dd79 100644 --- a/examples/all-clusters-app/p6/README.md +++ b/examples/all-clusters-app/p6/README.md @@ -12,6 +12,7 @@ An example showing the use of Matter on the Infineon CY8CKIT-062S2-43012 board. - [Setting up chip-tool](#setting-up-chip-tool) - [Commissioning over BLE](#commissioning-over-ble) - [Notes](#notes) + - [OTA Software Update](#ota-software-update)
@@ -134,3 +135,9 @@ commands. These power cycle the BlueTooth hardware and disable BR/EDR mode. sudo btmgmt -i hci0 bredr off sudo btmgmt -i hci0 power on ``` + +## OTA Software Update + +For the description of Software Update process with infineon P6 example +applications see +[Infineon P6 OTA Software Update](../../../docs/guides/infineon_p6_software_update.md) diff --git a/examples/all-clusters-app/p6/include/AppTask.h b/examples/all-clusters-app/p6/include/AppTask.h index a5f606cc451b85..5bb9a9163225bf 100644 --- a/examples/all-clusters-app/p6/include/AppTask.h +++ b/examples/all-clusters-app/p6/include/AppTask.h @@ -46,6 +46,7 @@ class AppTask static void LightActionEventHandler(AppEvent * aEvent); void ButtonEventHandler(uint8_t btnIdx, uint8_t btnAction); void PostEvent(const AppEvent * event); + void InitOTARequestor(); private: friend AppTask & GetAppTask(void); diff --git a/examples/all-clusters-app/p6/ota_base_build.sh b/examples/all-clusters-app/p6/ota_base_build.sh new file mode 100755 index 00000000000000..61bb808e3c1412 --- /dev/null +++ b/examples/all-clusters-app/p6/ota_base_build.sh @@ -0,0 +1,8 @@ +OUT_DIR=out/all-clusters-app/ +ANYCLOUD_DIR=third_party/p6/p6_sdk/libs/anycloud-ota/ + +scripts/examples/gn_p6_example.sh examples/all-clusters-app/p6 "$OUT_DIR" chip_enable_ota_requestor=true + +mv "$OUT_DIR"/chip-p6-clusters-example.hex "$OUT_DIR"/chip-p6-clusters-example.unsigned.hex + +./"$ANYCLOUD_DIR"/scripts/sign_script.bash "$OUT_DIR"/ chip-p6-clusters-example python3 arm-none-eabi-objcopy "-O ihex" "" "$ANYCLOUD_DIR"/source/mcuboot/scripts/ imgtool_v1.7.0/imgtool.py create 0xFF 0x400 3584 1.0.0 0x00018000 0x001C0000 arm-none-eabi-objcopy "" diff --git a/examples/all-clusters-app/p6/ota_update_build.sh b/examples/all-clusters-app/p6/ota_update_build.sh new file mode 100755 index 00000000000000..58f870977fd97b --- /dev/null +++ b/examples/all-clusters-app/p6/ota_update_build.sh @@ -0,0 +1,14 @@ +OUT_DIR=out/all-clusters-app-ota +ANYCLOUD_DIR=third_party/p6/p6_sdk/libs/anycloud-ota/ + +./scripts/examples/gn_p6_example.sh examples/all-clusters-app/p6 "$OUT_DIR" chip_enable_ota_requestor=true build_update_image=true + +mv "$OUT_DIR"/chip-p6-clusters-example.hex "$OUT_DIR"/chip-p6-clusters-example.unsigned.hex + +./"$ANYCLOUD_DIR"/scripts/sign_script.bash "$OUT_DIR"/ chip-p6-clusters-example python3 arm-none-eabi-objcopy "-O ihex" "" "$ANYCLOUD_DIR"/source/mcuboot/scripts/ imgtool_v1.7.0/imgtool.py sign 0xFF 0x400 3584 1.0.0 0x00018000 0x001C0000 arm-none-eabi-objcopy "-k $ANYCLOUD_DIR/source/mcuboot/keys/cypress-test-ec-p256.pem" + +if [ -f "$OUT_DIR"/chip-p6-clusters-example.ota ]; then + rm "$OUT_DIR"/chip-p6-clusters-example.ota +fi + +src/app/ota_image_tool.py create -v 0xFFF1 -p 0x8000 -vn 2 -vs "2.0" -da sha256 "$OUT_DIR"/chip-p6-clusters-example.bin "$OUT_DIR"/chip-p6-clusters-example.ota diff --git a/examples/all-clusters-app/p6/src/AppTask.cpp b/examples/all-clusters-app/p6/src/AppTask.cpp index d58c7a3f108c56..c8717c30740357 100644 --- a/examples/all-clusters-app/p6/src/AppTask.cpp +++ b/examples/all-clusters-app/p6/src/AppTask.cpp @@ -43,6 +43,33 @@ #include #include +/* OTA related includes */ +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR +#include +#include +#include +#include +#include +extern "C" { +#include "cy_smif_psoc6.h" +} +using chip::BDXDownloader; +using chip::CharSpan; +using chip::DefaultOTARequestor; +using chip::FabricIndex; +using chip::GetRequestorInstance; +using chip::NodeId; +using chip::OTADownloader; +using chip::OTAImageProcessorImpl; +using chip::System::Layer; + +using namespace ::chip; +using namespace chip::TLV; +using namespace ::chip::Credentials; +using namespace ::chip::DeviceLayer; +using namespace ::chip::System; + +#endif #define APP_EVENT_QUEUE_SIZE 10 #define APP_TASK_STACK_SIZE (4096) #define APP_WAIT_LOOP 1000 @@ -61,6 +88,15 @@ StaticQueue_t sAppEventQueueStruct; StackType_t appStack[APP_TASK_STACK_SIZE / sizeof(StackType_t)]; StaticTask_t appTaskStruct; + +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR +DefaultOTARequestor gRequestorCore; +DefaultOTARequestorStorage gRequestorStorage; +DefaultOTARequestorDriver gRequestorUser; +BDXDownloader gDownloader; +OTAImageProcessorImpl gImageProcessor; +#endif + } // namespace using namespace ::chip; @@ -96,6 +132,9 @@ static void InitServer(intptr_t context) // Initialize device attestation config SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR + GetAppTask().InitOTARequestor(); +#endif } CHIP_ERROR AppTask::StartAppTask() @@ -114,7 +153,14 @@ CHIP_ERROR AppTask::StartAppTask() CHIP_ERROR AppTask::Init() { CHIP_ERROR err = CHIP_NO_ERROR; - +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR + int rc = boot_set_confirmed(); + if (rc != 0) + { + P6_LOG("boot_set_confirmed failed"); + appError(CHIP_ERROR_WELL_UNINITIALIZED); + } +#endif // Register the callback to init the MDNS server when connectivity is available PlatformMgr().AddEventHandler( [](const ChipDeviceEvent * event, intptr_t arg) { @@ -264,3 +310,39 @@ bool lowPowerClusterSleep() { return true; } + +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR +void AppTask::InitOTARequestor() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + SetRequestorInstance(&gRequestorCore); + gRequestorStorage.Init(chip::Server::GetInstance().GetPersistentStorage()); + gRequestorCore.Init(chip::Server::GetInstance(), gRequestorStorage, gRequestorUser, gDownloader); + gImageProcessor.SetOTADownloader(&gDownloader); + gDownloader.SetImageProcessorDelegate(&gImageProcessor); + gRequestorUser.Init(&gRequestorCore, &gImageProcessor); + + uint32_t savedSoftwareVersion; + err = ConfigurationMgr().GetSoftwareVersion(savedSoftwareVersion); + if (err != CHIP_NO_ERROR) + { + P6_LOG("Can't get saved software version"); + appError(err); + } + + if (savedSoftwareVersion != CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION) + { + ConfigurationMgr().StoreSoftwareVersion(CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION); + + P6_LOG("Confirming update to version: %u", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION); + chip::OTARequestorInterface * requestor = chip::GetRequestorInstance(); + if (requestor != nullptr) + { + requestor->NotifyUpdateApplied(); + } + } + + P6_LOG("Current Software Version: %u", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION); + P6_LOG("Current Firmware Version String: %s", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING); +} +#endif diff --git a/examples/all-clusters-app/p6/src/main.cpp b/examples/all-clusters-app/p6/src/main.cpp index a8f415ffa3744d..d365f9ff8220d4 100644 --- a/examples/all-clusters-app/p6/src/main.cpp +++ b/examples/all-clusters-app/p6/src/main.cpp @@ -35,6 +35,7 @@ #include #include "AppConfig.h" +#include "cyhal_wdt.h" #include "init_p6Platform.h" #include @@ -131,7 +132,12 @@ static void main_task(void * pvParameters) int main(void) { init_p6Platform(); - +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR + // Clear watchdog timer (started by bootloader) so that it doesn't trigger a reset + cyhal_wdt_t wdt_obj; + cyhal_wdt_init(&wdt_obj, cyhal_wdt_get_max_timeout_ms()); + cyhal_wdt_free(&wdt_obj); +#endif #ifdef HEAP_MONITORING MemMonitoring::startHeapMonitoring(); #endif diff --git a/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter b/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter index de169f34582b4d..98c16da49266e7 100644 --- a/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter +++ b/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter @@ -1090,6 +1090,7 @@ server cluster GeneralCommissioning = 48 { struct BasicCommissioningInfo { int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; } attribute access(write: administer) int64u breadcrumb = 0; @@ -3174,14 +3175,7 @@ server cluster WindowCovering = 258 { kTiltEncoderControlled = 0x40; } - bitmap Mode : BITMAP8 { - kMotorDirectionReversed = 0x1; - kCalibrationMode = 0x2; - kMaintenanceMode = 0x4; - kLedFeedback = 0x8; - } - - bitmap WcFeature : BITMAP32 { + bitmap Feature : BITMAP32 { kLift = 0x1; kTilt = 0x2; kPositionAwareLift = 0x4; @@ -3189,13 +3183,20 @@ server cluster WindowCovering = 258 { kPositionAwareTilt = 0x10; } - bitmap WcOperationalStatus : BITMAP8 { + bitmap Mode : BITMAP8 { + kMotorDirectionReversed = 0x1; + kCalibrationMode = 0x2; + kMaintenanceMode = 0x4; + kLedFeedback = 0x8; + } + + bitmap OperationalStatus : BITMAP8 { kGlobal = 0x3; kLift = 0xC; kTilt = 0x30; } - bitmap WcSafetyStatus : BITMAP16 { + bitmap SafetyStatus : BITMAP16 { kRemoteLockout = 0x1; kTamperDetection = 0x2; kFailedCommunication = 0x4; @@ -3212,7 +3213,7 @@ server cluster WindowCovering = 258 { readonly attribute Type type = 0; readonly attribute ConfigStatus configStatus = 7; - readonly attribute bitmap8 operationalStatus = 10; + readonly attribute OperationalStatus operationalStatus = 10; readonly attribute EndProductType endProductType = 13; attribute access(write: manage) Mode mode = 23; readonly attribute bitmap32 featureMap = 65532; diff --git a/examples/all-clusters-minimal-app/ameba/chip_main.cmake b/examples/all-clusters-minimal-app/ameba/chip_main.cmake index 6d40ce5fe09e7c..97884c6d92335f 100755 --- a/examples/all-clusters-minimal-app/ameba/chip_main.cmake +++ b/examples/all-clusters-minimal-app/ameba/chip_main.cmake @@ -17,7 +17,8 @@ include(${pigweed_dir}/pw_protobuf_compiler/proto.cmake) set(dir_pw_third_party_nanopb "${chip_dir}/third_party/nanopb/repo" CACHE STRING "" FORCE) pw_set_backend(pw_log pw_log_basic) -pw_set_backend(pw_assert pw_assert_log) +pw_set_backend(pw_assert.check pw_assert_log.check_backend) +pw_set_backend(pw_assert.assert pw_assert.assert_compatibility_backend) pw_set_backend(pw_sys_io pw_sys_io.ameba) pw_set_backend(pw_trace pw_trace_tokenized) @@ -35,7 +36,7 @@ pw_proto_library(attributes_service STRIP_PREFIX ${chip_dir}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(button_service @@ -46,7 +47,7 @@ pw_proto_library(button_service STRIP_PREFIX ${chip_dir}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(device_service @@ -59,7 +60,7 @@ pw_proto_library(device_service STRIP_PREFIX ${chip_dir}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(lighting_service @@ -70,7 +71,7 @@ pw_proto_library(lighting_service STRIP_PREFIX ${chip_dir}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(locking_service @@ -81,7 +82,7 @@ pw_proto_library(locking_service STRIP_PREFIX ${chip_dir}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(wifi_service @@ -92,7 +93,7 @@ pw_proto_library(wifi_service PREFIX wifi_service DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto STRIP_PREFIX ${chip_dir}/examples/common/pigweed/protos ) diff --git a/examples/all-clusters-minimal-app/esp32/CMakeLists.txt b/examples/all-clusters-minimal-app/esp32/CMakeLists.txt index d6fd8adda8185f..6587b7e6fd7535 100644 --- a/examples/all-clusters-minimal-app/esp32/CMakeLists.txt +++ b/examples/all-clusters-minimal-app/esp32/CMakeLists.txt @@ -51,7 +51,8 @@ get_filename_component(CHIP_ROOT ./third_party/connectedhomeip REALPATH) include(third_party/connectedhomeip/third_party/pigweed/repo/pw_build/pigweed.cmake) pw_set_module_config(pw_rpc_CONFIG pw_rpc.disable_global_mutex_config) pw_set_backend(pw_log pw_log_basic) -pw_set_backend(pw_assert pw_assert_log) +pw_set_backend(pw_assert.check pw_assert_log.check_backend) +pw_set_backend(pw_assert.assert pw_assert.assert_compatibility_backend) pw_set_backend(pw_sys_io pw_sys_io.esp32) pw_set_backend(pw_trace pw_trace_tokenized) diff --git a/examples/all-clusters-minimal-app/esp32/main/CMakeLists.txt b/examples/all-clusters-minimal-app/esp32/main/CMakeLists.txt index 1559ea3d1d60a8..19108d27dab518 100644 --- a/examples/all-clusters-minimal-app/esp32/main/CMakeLists.txt +++ b/examples/all-clusters-minimal-app/esp32/main/CMakeLists.txt @@ -87,7 +87,6 @@ set(SRC_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/power-source-configuration-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/power-source-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/all-clusters-app/all-clusters-common/src" - #${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ias-zone-client ) if (CONFIG_ENABLE_PW_RPC) @@ -152,7 +151,7 @@ pw_proto_library(attributes_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(button_service @@ -163,7 +162,7 @@ pw_proto_library(button_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(descriptor_service @@ -174,7 +173,7 @@ pw_proto_library(descriptor_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(device_service @@ -187,7 +186,7 @@ pw_proto_library(device_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(lighting_service @@ -198,7 +197,7 @@ pw_proto_library(lighting_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(locking_service @@ -209,7 +208,7 @@ pw_proto_library(locking_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(wifi_service @@ -220,7 +219,7 @@ pw_proto_library(wifi_service PREFIX wifi_service DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos ) diff --git a/examples/all-clusters-minimal-app/nrfconnect/README.md b/examples/all-clusters-minimal-app/nrfconnect/README.md index 919fb768d5fd51..909b3d5b8861cd 100644 --- a/examples/all-clusters-minimal-app/nrfconnect/README.md +++ b/examples/all-clusters-minimal-app/nrfconnect/README.md @@ -14,7 +14,8 @@ certification of a Matter device communicating over a low-power, 802.15.4 Thread network. The example behaves as a Matter accessory, that is a device that can be paired -into an existing Matter network and can be controlled by this network. +into an existing Matter network and can be controlled by this network. The +device works as a Thread Minimal End Device.
@@ -294,22 +295,6 @@ features like logs and command-line interface, run the following command: Remember to replace _build-target_ with the build target name of the Nordic Semiconductor's kit you own. -### Building with low-power configuration - -You can build the example using the low-power configuration, which enables -Thread's Sleepy End Device mode and disables debug features, such as the UART -console or the **LED 1** usage. - -To build for the low-power configuration, run the following command with -_build-target_ replaced with the build target name of the Nordic Semiconductor's -kit you own (for example `nrf52840dk_nrf52840`): - - $ west build -b build-target -- -DOVERLAY_CONFIG=overlay-low_power.conf - -For example, use the following command for `nrf52840dk_nrf52840`: - - $ west build -b nrf52840dk_nrf52840 -- -DOVERLAY_CONFIG=overlay-low_power.conf - ### Building with Device Firmware Upgrade support Support for DFU using Matter OTA is disabled by default. diff --git a/examples/all-clusters-minimal-app/nrfconnect/main/include/CHIPProjectConfig.h b/examples/all-clusters-minimal-app/nrfconnect/main/include/CHIPProjectConfig.h index 7a2941f28621df..9fea28ec9fde12 100644 --- a/examples/all-clusters-minimal-app/nrfconnect/main/include/CHIPProjectConfig.h +++ b/examples/all-clusters-minimal-app/nrfconnect/main/include/CHIPProjectConfig.h @@ -29,5 +29,3 @@ // Use a default pairing code if one hasn't been provisioned in flash. #define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021 #define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 - -#define CHIP_DEVICE_CONFIG_SED_IDLE_INTERVAL 2000_ms32 diff --git a/examples/all-clusters-minimal-app/nrfconnect/overlay-low_power.conf b/examples/all-clusters-minimal-app/nrfconnect/overlay-low_power.conf deleted file mode 100644 index c962425f6ef937..00000000000000 --- a/examples/all-clusters-minimal-app/nrfconnect/overlay-low_power.conf +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# Enable MTD Sleepy End Device -CONFIG_CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT=y - -# Disable UART console -CONFIG_SHELL=n -CONFIG_LOG=n -CONFIG_UART_CONSOLE=n -CONFIG_SERIAL=n - -# Suspend devices when the CPU goes to sleep -CONFIG_PM_DEVICE=y - -# Disable auxiliary state LEDs -CONFIG_STATE_LEDS=n diff --git a/examples/all-clusters-minimal-app/p6/BUILD.gn b/examples/all-clusters-minimal-app/p6/BUILD.gn index dabbb1d5bf7a25..a9b88c2125b219 100644 --- a/examples/all-clusters-minimal-app/p6/BUILD.gn +++ b/examples/all-clusters-minimal-app/p6/BUILD.gn @@ -17,6 +17,7 @@ import("//build_overrides/chip.gni") import("//build_overrides/p6.gni") import("${build_root}/config/defaults.gni") +import("${chip_root}/src/platform/device.gni") import("${p6_sdk_build_root}/p6_executable.gni") import("${p6_sdk_build_root}/p6_sdk.gni") @@ -34,6 +35,50 @@ declare_args() { # Monitor & log memory usage at runtime. enable_heap_monitoring = false + + # Build update app + build_update_image = false +} + +config("p6_ota_config") { + ldflags = [ "-T/" + rebase_path( + "${chip_root}/third_party/p6/p6_sdk/ota/cy8c6xxa_cm4_dual_ota_int.ld", + "/", + "${p6_project_dir}") ] + + ldflags += [ "-Wl,--defsym,MCUBOOT_HEADER_SIZE=0x400,--defsym,MCUBOOT_BOOTLOADER_SIZE=0x18000,--defsym,CY_BOOT_PRIMARY_1_SIZE=0x1C0000" ] + + defines = [ + "P6_OTA", + "OTA_SUPPORT ", + "OTA_USE_EXTERNAL_FLASH", + "CY_BOOT_USE_EXTERNAL_FLASH", + "MCUBOOT_HEADER_SIZE=0x400", + "MCUBOOT_MAX_IMG_SECTORS=3584", + "CY_BOOT_SCRATCH_SIZE=0x00004000", + "MCUBOOT_BOOTLOADER_SIZE=0x00018000", + "CY_BOOT_BOOTLOADER_SIZE=0x00018000", + "CY_BOOT_PRIMARY_1_START=0x00018000", + "CY_BOOT_PRIMARY_1_SIZE=0x1C0000", + "CY_BOOT_SECONDARY_1_START=0x00000000", + "CY_BOOT_SECONDARY_1_SIZE=0x001C0000", + "CY_FLASH_ERASE_VALUE=0xFF", + "MCUBOOT_IMAGE_NUMBER=1", + "MCUBOOT_SLOT_SIZE=0x1C0000", + "MCUBOOT_SCRATCH_SIZE=0x4000", + "MCUBOOT_SECTOR_SIZE = 512", + "APP_VERSION_MAJOR=1", + "APP_VERSION_MINOR=0", + "APP_VERSION_BUILD=0", + "MCUBOOT_OVERWRITE_ONLY", + "CY_ENABLE_XIP_PROGRAM", + ] + + if (build_update_image) { + defines += [ "CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION=2" ] + } else { + defines += [ "CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION=1" ] + } } p6_sdk_sources("all_clusters_app_sdk_sources") { @@ -52,6 +97,27 @@ p6_sdk_sources("all_clusters_app_sdk_sources") { sources = [ "${p6_project_dir}/include/CHIPProjectConfig.h" ] public_configs = [ "${chip_root}/third_party/p6:p6_sdk_config" ] + + if (chip_enable_ota_requestor) { + sources += [ + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/bootutil/src/bootutil_misc.c", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/cy_flash_map.c", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/cy_flash_psoc6.c", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/cy_smif_psoc6.c", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/mem_config/mem_config_sfdp.c", + ] + include_dirs += [ + "${chip_root}/third_party/p6/p6_sdk/ota/config", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/mem_config/", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/include/", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/include/flash_map_backend/", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/sysflash/", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/bootutil/include", + ] + public_configs += [ ":p6_ota_config" ] + } } p6_executable("clusters_minimal_app") { diff --git a/examples/all-clusters-minimal-app/p6/README.md b/examples/all-clusters-minimal-app/p6/README.md index a3d673a6f8d615..c6b752d209a6ca 100644 --- a/examples/all-clusters-minimal-app/p6/README.md +++ b/examples/all-clusters-minimal-app/p6/README.md @@ -12,6 +12,7 @@ An example showing the use of Matter on the Infineon CY8CKIT-062S2-43012 board. - [Setting up chip-tool](#setting-up-chip-tool) - [Commissioning over BLE](#commissioning-over-ble) - [Notes](#notes) + - [OTA Software Update](#ota-software-update)
@@ -134,3 +135,9 @@ commands. These power cycle the BlueTooth hardware and disable BR/EDR mode. sudo btmgmt -i hci0 bredr off sudo btmgmt -i hci0 power on ``` + +## OTA Software Update + +For the description of Software Update process with infineon P6 example +applications see +[Infineon P6 OTA Software Update](../../../docs/guides/infineon_p6_software_update.md) diff --git a/examples/all-clusters-minimal-app/p6/include/AppTask.h b/examples/all-clusters-minimal-app/p6/include/AppTask.h index a5f606cc451b85..5bb9a9163225bf 100644 --- a/examples/all-clusters-minimal-app/p6/include/AppTask.h +++ b/examples/all-clusters-minimal-app/p6/include/AppTask.h @@ -46,6 +46,7 @@ class AppTask static void LightActionEventHandler(AppEvent * aEvent); void ButtonEventHandler(uint8_t btnIdx, uint8_t btnAction); void PostEvent(const AppEvent * event); + void InitOTARequestor(); private: friend AppTask & GetAppTask(void); diff --git a/examples/all-clusters-minimal-app/p6/ota_base_build.sh b/examples/all-clusters-minimal-app/p6/ota_base_build.sh new file mode 100755 index 00000000000000..c49fad50303fdf --- /dev/null +++ b/examples/all-clusters-minimal-app/p6/ota_base_build.sh @@ -0,0 +1,8 @@ +OUT_DIR=out/all-clusters-minimal-app/ +ANYCLOUD_DIR=third_party/p6/p6_sdk/libs/anycloud-ota/ + +scripts/examples/gn_p6_example.sh examples/all-clusters-minimal-app/p6 "$OUT_DIR" chip_enable_ota_requestor=true + +mv "$OUT_DIR"/chip-p6-clusters-minimal-example.hex "$OUT_DIR"/chip-p6-clusters-minimal-example.unsigned.hex + +./"$ANYCLOUD_DIR"/scripts/sign_script.bash "$OUT_DIR"/ chip-p6-clusters-minimal-example python3 arm-none-eabi-objcopy "-O ihex" "" "$ANYCLOUD_DIR"/source/mcuboot/scripts/ imgtool_v1.7.0/imgtool.py create 0xFF 0x400 3584 1.0.0 0x00018000 0x001C0000 arm-none-eabi-objcopy "" diff --git a/examples/all-clusters-minimal-app/p6/ota_update_build.sh b/examples/all-clusters-minimal-app/p6/ota_update_build.sh new file mode 100755 index 00000000000000..2aa7902556bd62 --- /dev/null +++ b/examples/all-clusters-minimal-app/p6/ota_update_build.sh @@ -0,0 +1,13 @@ +OUT_DIR=out/all-clusters-minimal-app-ota +ANYCLOUD_DIR=third_party/p6/p6_sdk/libs/anycloud-ota/ + +./scripts/examples/gn_p6_example.sh examples/all-clusters-minimal-app/p6 "$OUT_DIR" chip_enable_ota_requestor=true build_update_image=true + +mv "$OUT_DIR"/chip-p6-clusters-minimal-example.hex "$OUT_DIR"/chip-p6-clusters-minimal-example.unsigned.hex + +./"$ANYCLOUD_DIR"/scripts/sign_script.bash "$OUT_DIR"/ chip-p6-clusters-minimal-example python3 arm-none-eabi-objcopy "-O ihex" "" "$ANYCLOUD_DIR"/source/mcuboot/scripts/ imgtool_v1.7.0/imgtool.py sign 0xFF 0x400 3584 1.0.0 0x00018000 0x001C0000 arm-none-eabi-objcopy "-k $ANYCLOUD_DIR/source/mcuboot/keys/cypress-test-ec-p256.pem" + +if [ -f "$OUT_DIR"/chip-p6-clusters-minimal-example.ota ]; then + rm "$OUT_DIR"/chip-p6-clusters-minimal-example.ota +fi +src/app/ota_image_tool.py create -v 0xFFF1 -p 0x8000 -vn 2 -vs "2.0" -da sha256 "$OUT_DIR"/chip-p6-clusters-minimal-example.bin "$OUT_DIR"/chip-p6-clusters-minimal-example.ota diff --git a/examples/all-clusters-minimal-app/p6/src/AppTask.cpp b/examples/all-clusters-minimal-app/p6/src/AppTask.cpp index d58c7a3f108c56..c8717c30740357 100644 --- a/examples/all-clusters-minimal-app/p6/src/AppTask.cpp +++ b/examples/all-clusters-minimal-app/p6/src/AppTask.cpp @@ -43,6 +43,33 @@ #include #include +/* OTA related includes */ +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR +#include +#include +#include +#include +#include +extern "C" { +#include "cy_smif_psoc6.h" +} +using chip::BDXDownloader; +using chip::CharSpan; +using chip::DefaultOTARequestor; +using chip::FabricIndex; +using chip::GetRequestorInstance; +using chip::NodeId; +using chip::OTADownloader; +using chip::OTAImageProcessorImpl; +using chip::System::Layer; + +using namespace ::chip; +using namespace chip::TLV; +using namespace ::chip::Credentials; +using namespace ::chip::DeviceLayer; +using namespace ::chip::System; + +#endif #define APP_EVENT_QUEUE_SIZE 10 #define APP_TASK_STACK_SIZE (4096) #define APP_WAIT_LOOP 1000 @@ -61,6 +88,15 @@ StaticQueue_t sAppEventQueueStruct; StackType_t appStack[APP_TASK_STACK_SIZE / sizeof(StackType_t)]; StaticTask_t appTaskStruct; + +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR +DefaultOTARequestor gRequestorCore; +DefaultOTARequestorStorage gRequestorStorage; +DefaultOTARequestorDriver gRequestorUser; +BDXDownloader gDownloader; +OTAImageProcessorImpl gImageProcessor; +#endif + } // namespace using namespace ::chip; @@ -96,6 +132,9 @@ static void InitServer(intptr_t context) // Initialize device attestation config SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR + GetAppTask().InitOTARequestor(); +#endif } CHIP_ERROR AppTask::StartAppTask() @@ -114,7 +153,14 @@ CHIP_ERROR AppTask::StartAppTask() CHIP_ERROR AppTask::Init() { CHIP_ERROR err = CHIP_NO_ERROR; - +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR + int rc = boot_set_confirmed(); + if (rc != 0) + { + P6_LOG("boot_set_confirmed failed"); + appError(CHIP_ERROR_WELL_UNINITIALIZED); + } +#endif // Register the callback to init the MDNS server when connectivity is available PlatformMgr().AddEventHandler( [](const ChipDeviceEvent * event, intptr_t arg) { @@ -264,3 +310,39 @@ bool lowPowerClusterSleep() { return true; } + +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR +void AppTask::InitOTARequestor() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + SetRequestorInstance(&gRequestorCore); + gRequestorStorage.Init(chip::Server::GetInstance().GetPersistentStorage()); + gRequestorCore.Init(chip::Server::GetInstance(), gRequestorStorage, gRequestorUser, gDownloader); + gImageProcessor.SetOTADownloader(&gDownloader); + gDownloader.SetImageProcessorDelegate(&gImageProcessor); + gRequestorUser.Init(&gRequestorCore, &gImageProcessor); + + uint32_t savedSoftwareVersion; + err = ConfigurationMgr().GetSoftwareVersion(savedSoftwareVersion); + if (err != CHIP_NO_ERROR) + { + P6_LOG("Can't get saved software version"); + appError(err); + } + + if (savedSoftwareVersion != CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION) + { + ConfigurationMgr().StoreSoftwareVersion(CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION); + + P6_LOG("Confirming update to version: %u", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION); + chip::OTARequestorInterface * requestor = chip::GetRequestorInstance(); + if (requestor != nullptr) + { + requestor->NotifyUpdateApplied(); + } + } + + P6_LOG("Current Software Version: %u", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION); + P6_LOG("Current Firmware Version String: %s", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING); +} +#endif diff --git a/examples/all-clusters-minimal-app/p6/src/main.cpp b/examples/all-clusters-minimal-app/p6/src/main.cpp index a8f415ffa3744d..d365f9ff8220d4 100644 --- a/examples/all-clusters-minimal-app/p6/src/main.cpp +++ b/examples/all-clusters-minimal-app/p6/src/main.cpp @@ -35,6 +35,7 @@ #include #include "AppConfig.h" +#include "cyhal_wdt.h" #include "init_p6Platform.h" #include @@ -131,7 +132,12 @@ static void main_task(void * pvParameters) int main(void) { init_p6Platform(); - +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR + // Clear watchdog timer (started by bootloader) so that it doesn't trigger a reset + cyhal_wdt_t wdt_obj; + cyhal_wdt_init(&wdt_obj, cyhal_wdt_get_max_timeout_ms()); + cyhal_wdt_free(&wdt_obj); +#endif #ifdef HEAP_MONITORING MemMonitoring::startHeapMonitoring(); #endif diff --git a/examples/bridge-app/bridge-common/bridge-app.matter b/examples/bridge-app/bridge-common/bridge-app.matter index 64b03dc44a04ff..f4572fce80c57a 100644 --- a/examples/bridge-app/bridge-common/bridge-app.matter +++ b/examples/bridge-app/bridge-common/bridge-app.matter @@ -415,6 +415,7 @@ server cluster GeneralCommissioning = 48 { struct BasicCommissioningInfo { int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; } attribute access(write: administer) int64u breadcrumb = 0; diff --git a/examples/bridge-app/linux/BUILD.gn b/examples/bridge-app/linux/BUILD.gn index 6860566c5bdba5..3912e887a846be 100644 --- a/examples/bridge-app/linux/BUILD.gn +++ b/examples/bridge-app/linux/BUILD.gn @@ -24,6 +24,7 @@ executable("chip-bridge-app") { "${chip_root}/examples/tv-app/tv-common/include/CHIPProjectAppConfig.h", "Device.cpp", "include/Device.h", + "include/main.h", "main.cpp", ] diff --git a/examples/bridge-app/linux/Device.cpp b/examples/bridge-app/linux/Device.cpp index f726baf06c21c2..e2d2122a49ce25 100644 --- a/examples/bridge-app/linux/Device.cpp +++ b/examples/bridge-app/linux/Device.cpp @@ -22,12 +22,14 @@ #include #include +using namespace chip::app::Clusters::BridgedActions; + // LightingManager LightingManager::sLight; -Device::Device(const char * szDeviceName, const char * szLocation) +Device::Device(const char * szDeviceName, std::string szLocation) { strncpy(mName, szDeviceName, sizeof(mName)); - strncpy(mLocation, szLocation, sizeof(mLocation)); + mLocation = szLocation; mReachable = false; mEndpointId = 0; } @@ -72,13 +74,13 @@ void Device::SetName(const char * szName) } } -void Device::SetLocation(const char * szLocation) +void Device::SetLocation(std::string szLocation) { - bool changed = (strncmp(mLocation, szLocation, sizeof(mLocation)) != 0); + bool changed = (mLocation.compare(szLocation) != 0); - strncpy(mLocation, szLocation, sizeof(mLocation)); + mLocation = szLocation; - ChipLogProgress(DeviceLayer, "Device[%s]: Location=\"%s\"", mName, mLocation); + ChipLogProgress(DeviceLayer, "Device[%s]: Location=\"%s\"", mName, mLocation.c_str()); if (changed) { @@ -86,7 +88,7 @@ void Device::SetLocation(const char * szLocation) } } -DeviceOnOff::DeviceOnOff(const char * szDeviceName, const char * szLocation) : Device(szDeviceName, szLocation) +DeviceOnOff::DeviceOnOff(const char * szDeviceName, std::string szLocation) : Device(szDeviceName, szLocation) { mOn = false; } @@ -129,7 +131,7 @@ void DeviceOnOff::HandleDeviceChange(Device * device, Device::Changed_t changeMa } } -DeviceSwitch::DeviceSwitch(const char * szDeviceName, const char * szLocation, uint32_t aFeatureMap) : +DeviceSwitch::DeviceSwitch(const char * szDeviceName, std::string szLocation, uint32_t aFeatureMap) : Device(szDeviceName, szLocation) { mNumberOfPositions = 2; @@ -231,3 +233,32 @@ void DevicePowerSource::SetDescription(std::string aDescription) mChanged_CB(this, kChanged_Description); } } + +EndpointListInfo::EndpointListInfo(uint16_t endpointListId, std::string name, EndpointListTypeEnum type) +{ + mEndpointListId = endpointListId; + mName = name; + mType = type; +} + +EndpointListInfo::EndpointListInfo(uint16_t endpointListId, std::string name, EndpointListTypeEnum type, + chip::EndpointId endpointId) +{ + mEndpointListId = endpointListId; + mName = name; + mType = type; + mEndpoints.push_back(endpointId); +} + +void EndpointListInfo::AddEndpointId(chip::EndpointId endpointId) +{ + mEndpoints.push_back(endpointId); +} + +Room::Room(std::string name, uint16_t endpointListId, EndpointListTypeEnum type, bool isVisible) +{ + mName = name; + mEndpointListId = endpointListId; + mType = type; + mIsVisible = isVisible; +} diff --git a/examples/bridge-app/linux/bridged-actions-stub.cpp b/examples/bridge-app/linux/bridged-actions-stub.cpp index bade30c1c102cb..21712982dea9f7 100644 --- a/examples/bridge-app/linux/bridged-actions-stub.cpp +++ b/examples/bridge-app/linux/bridged-actions-stub.cpp @@ -24,6 +24,11 @@ #include #include +#include + +#include "Device.h" +#include "main.h" + using namespace chip; using namespace chip::app; using namespace chip::app::Clusters; @@ -58,8 +63,20 @@ CHIP_ERROR BridgedActionsAttrAccess::ReadActionListAttribute(EndpointId endpoint CHIP_ERROR BridgedActionsAttrAccess::ReadEndpointListAttribute(EndpointId endpoint, AttributeValueEncoder & aEncoder) { - // Just return an empty list - return aEncoder.EncodeEmptyList(); + std::vector infoList = GetEndpointListInfo(endpoint); + + CHIP_ERROR err = aEncoder.EncodeList([&infoList](const auto & encoder) -> CHIP_ERROR { + for (auto info : infoList) + { + BridgedActions::Structs::EndpointListStruct::Type endpointListStruct = { + info.GetEndpointListId(), CharSpan::fromCharString(info.GetName().c_str()), info.GetType(), + DataModel::List(info.GetEndpointListData(), info.GetEndpointListSize()) + }; + ReturnErrorOnFailure(encoder.Encode(endpointListStruct)); + } + return CHIP_NO_ERROR; + }); + return err; } CHIP_ERROR BridgedActionsAttrAccess::ReadSetupUrlAttribute(EndpointId endpoint, AttributeValueEncoder & aEncoder) diff --git a/examples/bridge-app/linux/include/Device.h b/examples/bridge-app/linux/include/Device.h index 3bc7a88a47b6ae..b959454e7a8498 100644 --- a/examples/bridge-app/linux/include/Device.h +++ b/examples/bridge-app/linux/include/Device.h @@ -24,12 +24,15 @@ #include #include +#include + +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::BridgedActions; class Device { public: - static const int kDeviceNameSize = 32; - static const int kDeviceLocationSize = 32; + static const int kDeviceNameSize = 32; enum Changed_t { @@ -39,17 +42,21 @@ class Device kChanged_Last = kChanged_Name, } Changed; - Device(const char * szDeviceName, const char * szLocation); + Device(const char * szDeviceName, std::string szLocation); virtual ~Device() {} bool IsReachable(); void SetReachable(bool aReachable); void SetName(const char * szDeviceName); - void SetLocation(const char * szLocation); + void SetLocation(std::string szLocation); inline void SetEndpointId(chip::EndpointId id) { mEndpointId = id; }; inline chip::EndpointId GetEndpointId() { return mEndpointId; }; + inline void SetParentEndpointId(chip::EndpointId id) { mParentEndpointId = id; }; + inline chip::EndpointId GetParentEndpointId() { return mParentEndpointId; }; inline char * GetName() { return mName; }; - inline char * GetLocation() { return mLocation; }; + inline std::string GetLocation() { return mLocation; }; + inline std::string GetZone() { return mZone; }; + inline void SetZone(std::string zone) { mZone = zone; }; private: virtual void HandleDeviceChange(Device * device, Device::Changed_t changeMask) = 0; @@ -57,8 +64,10 @@ class Device protected: bool mReachable; char mName[kDeviceNameSize]; - char mLocation[kDeviceLocationSize]; + std::string mLocation; chip::EndpointId mEndpointId; + chip::EndpointId mParentEndpointId; + std::string mZone; }; class DeviceOnOff : public Device @@ -69,7 +78,7 @@ class DeviceOnOff : public Device kChanged_OnOff = kChanged_Last << 1, } Changed; - DeviceOnOff(const char * szDeviceName, const char * szLocation); + DeviceOnOff(const char * szDeviceName, std::string szLocation); bool IsOn(); void SetOnOff(bool aOn); @@ -96,7 +105,7 @@ class DeviceSwitch : public Device kChanged_MultiPressMax = kChanged_Last << 3, } Changed; - DeviceSwitch(const char * szDeviceName, const char * szLocation, uint32_t aFeatureMap); + DeviceSwitch(const char * szDeviceName, std::string szLocation, uint32_t aFeatureMap); void SetNumberOfPositions(uint8_t aNumberOfPositions); void SetCurrentPosition(uint8_t aCurrentPosition); @@ -124,7 +133,7 @@ class DeviceSwitch : public Device class ComposedDevice : public Device { public: - ComposedDevice(const char * szDeviceName, const char * szLocation) : Device(szDeviceName, szLocation){}; + ComposedDevice(const char * szDeviceName, std::string szLocation) : Device(szDeviceName, szLocation){}; using DeviceCallback_fn = std::function; @@ -146,7 +155,7 @@ class DevicePowerSource : public Device kChanged_Description = kChanged_Last << 2, } Changed; - DevicePowerSource(const char * szDeviceName, const char * szLocation, uint32_t aFeatureMap) : + DevicePowerSource(const char * szDeviceName, std::string szLocation, uint32_t aFeatureMap) : Device(szDeviceName, szLocation), mFeatureMap(aFeatureMap){}; using DeviceCallback_fn = std::function; @@ -172,3 +181,40 @@ class DevicePowerSource : public Device uint32_t mFeatureMap; DeviceCallback_fn mChanged_CB; }; + +class EndpointListInfo +{ +public: + EndpointListInfo(uint16_t endpointListId, std::string name, EndpointListTypeEnum type); + EndpointListInfo(uint16_t endpointListId, std::string name, EndpointListTypeEnum type, chip::EndpointId endpointId); + void AddEndpointId(chip::EndpointId endpointId); + inline uint16_t GetEndpointListId() { return mEndpointListId; }; + std::string GetName() { return mName; }; + inline EndpointListTypeEnum GetType() { return mType; }; + inline chip::EndpointId * GetEndpointListData() { return mEndpoints.data(); }; + inline size_t GetEndpointListSize() { return mEndpoints.size(); }; + +private: + uint16_t mEndpointListId = static_cast(0); + std::string mName; + EndpointListTypeEnum mType = static_cast(0); + std::vector mEndpoints; +}; + +class Room +{ +public: + Room(std::string name, uint16_t endpointListId, EndpointListTypeEnum type, bool isVisible); + inline void setIsVisible(bool isVisible) { mIsVisible = isVisible; }; + inline bool getIsVisible() { return mIsVisible; }; + inline void setName(std::string name) { mName = name; }; + inline std::string getName() { return mName; }; + inline EndpointListTypeEnum getType() { return mType; }; + inline uint16_t getEndpointListId() { return mEndpointListId; }; + +private: + bool mIsVisible; + std::string mName; + uint16_t mEndpointListId; + EndpointListTypeEnum mType; +}; diff --git a/src/lib/shell/tests/TestStreamerStdio.h b/examples/bridge-app/linux/include/main.h similarity index 67% rename from src/lib/shell/tests/TestStreamerStdio.h rename to examples/bridge-app/linux/include/main.h index 64e1904edde935..fe81d30685f7ec 100644 --- a/src/lib/shell/tests/TestStreamerStdio.h +++ b/examples/bridge-app/linux/include/main.h @@ -1,6 +1,7 @@ /* * - * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,23 +16,6 @@ * limitations under the License. */ -/** - * @file - * This file declares test entry points for CHIP system layer - * library unit tests. - * - */ - #pragma once -#include - -#ifdef __cplusplus -extern "C" { -#endif - -int TestStreamerStdio(void); - -#ifdef __cplusplus -} -#endif +std::vector GetEndpointListInfo(chip::EndpointId parentId); diff --git a/examples/bridge-app/linux/main.cpp b/examples/bridge-app/linux/main.cpp index 5709352d28b21e..d069d8ce7a0caf 100644 --- a/examples/bridge-app/linux/main.cpp +++ b/examples/bridge-app/linux/main.cpp @@ -44,16 +44,19 @@ #include "CommissionableInit.h" #include "Device.h" +#include "main.h" #include #include #include +#include using namespace chip; using namespace chip::Credentials; using namespace chip::Inet; using namespace chip::Transport; using namespace chip::DeviceLayer; +using namespace chip::app::Clusters; namespace { @@ -64,6 +67,7 @@ const int kDescriptorAttributeArraySize = 254; EndpointId gCurrentEndpointId; EndpointId gFirstDynamicEndpointId; Device * gDevices[CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT]; +std::vector gRooms; // ENDPOINT DEFINITIONS: // ================================================================================= @@ -149,6 +153,21 @@ DeviceSwitch Switch2("Switch 2", "Office", EMBER_AF_SWITCH_FEATURE_MOMENTARY_SWITCH_LONG_PRESS | EMBER_AF_SWITCH_FEATURE_MOMENTARY_SWITCH_MULTI_PRESS); +// Declare Bridged endpoints used for Action clusters +DataVersion gActionLight1DataVersions[ArraySize(bridgedLightClusters)]; +DataVersion gActionLight2DataVersions[ArraySize(bridgedLightClusters)]; +DataVersion gActionLight3DataVersions[ArraySize(bridgedLightClusters)]; +DataVersion gActionLight4DataVersions[ArraySize(bridgedLightClusters)]; + +DeviceOnOff ActionLight1("Action Light 1", "Room 1"); +DeviceOnOff ActionLight2("Action Light 2", "Room 1"); +DeviceOnOff ActionLight3("Action Light 3", "Room 2"); +DeviceOnOff ActionLight4("Action Light 4", "Room 2"); + +Room room1("Room 1", 0xE001, BridgedActions::EndpointListTypeEnum::kRoom, true); +Room room2("Room 2", 0xE002, BridgedActions::EndpointListTypeEnum::kRoom, true); +Room room3("Zone 3", 0xE003, BridgedActions::EndpointListTypeEnum::kZone, false); + // --------------------------------------------------------------------------- // // SWITCH ENDPOINT: contains the following clusters: @@ -255,6 +274,7 @@ int AddDeviceEndpoint(Device * dev, EmberAfEndpointType * ep, const SpanSetEndpointId(gCurrentEndpointId); + dev->SetParentEndpointId(parentEndpointId); ret = emberAfSetDynamicEndpoint(index, gCurrentEndpointId, ep, dataVersionStorage, deviceTypeList, parentEndpointId); if (ret == EMBER_ZCL_STATUS_SUCCESS) @@ -300,6 +320,46 @@ int RemoveDeviceEndpoint(Device * dev) return -1; } +std::vector GetEndpointListInfo(chip::EndpointId parentId) +{ + std::vector infoList; + + for (auto room : gRooms) + { + if (room->getIsVisible()) + { + EndpointListInfo info(room->getEndpointListId(), room->getName(), room->getType()); + int index = 0; + while (index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) + { + if ((gDevices[index] != nullptr) && (gDevices[index]->GetParentEndpointId() == parentId)) + { + std::string location; + if (room->getType() == BridgedActions::EndpointListTypeEnum::kZone) + { + location = gDevices[index]->GetZone(); + } + else + { + location = gDevices[index]->GetLocation(); + } + if (room->getName().compare(location) == 0) + { + info.AddEndpointId(gDevices[index]->GetEndpointId()); + } + } + index++; + } + if (info.GetEndpointListSize() > 0) + { + infoList.push_back(info); + } + } + } + + return infoList; +} + void HandleDeviceStatusChanged(Device * dev, Device::Changed_t itemChangedMask) { if (itemChangedMask & Device::kChanged_Reachable) @@ -614,25 +674,31 @@ void * bridge_polling_thread(void * context) if (kbhit()) { int ch = getchar(); + + // Commands used for the actions bridge test plan. if (ch == '2' && light2_added == false) { + // TC-BR-2 step 2, Add Light2 AddDeviceEndpoint(&Light2, &bridgedLightEndpoint, Span(gBridgedOnOffDeviceTypes), Span(gLight2DataVersions), 1); light2_added = true; } else if (ch == '4' && light1_added == true) { + // TC-BR-2 step 4, Remove Light 1 RemoveDeviceEndpoint(&Light1); light1_added = false; } if (ch == '5' && light1_added == false) { + // TC-BR-2 step 5, Add Light 1 back AddDeviceEndpoint(&Light1, &bridgedLightEndpoint, Span(gBridgedOnOffDeviceTypes), Span(gLight1DataVersions), 1); light1_added = true; } if (ch == 'b') { + // TC-BR-3 step 1b, rename lights if (light1_added) { Light1.SetName("Light 1b"); @@ -644,6 +710,7 @@ void * bridge_polling_thread(void * context) } if (ch == 'c') { + // TC-BR-3 step 2c, change the state of the lights if (light1_added) { Light1.Toggle(); @@ -653,6 +720,31 @@ void * bridge_polling_thread(void * context) Light2.Toggle(); } } + + // Commands used for the actions cluster test plan. + if (ch == 'r') + { + // TC-ACT-2.2 step 2c, rename "Room 1" + room1.setName("Room 1 renamed"); + ActionLight1.SetLocation(room1.getName()); + ActionLight2.SetLocation(room1.getName()); + } + if (ch == 'f') + { + // TC-ACT-2.2 step 2f, move "Action Light 3" from "Room 2" to "Room 1" + ActionLight3.SetLocation(room1.getName()); + } + if (ch == 'i') + { + // TC-ACT-2.2 step 2i, remove "Room 2" (make it not visible in the endpoint list), do not remove the lights + room2.setIsVisible(false); + } + if (ch == 'l') + { + // TC-ACT-2.2 step 2l, add a new "Zone 3" and add "Action Light 2" to the new zone + room3.setIsVisible(true); + ActionLight2.SetZone("Zone 3"); + } continue; } @@ -669,7 +761,6 @@ int main(int argc, char * argv[]) memset(gDevices, 0, sizeof(gDevices)); // Setup Mock Devices - Light1.SetChangeCallback(&HandleDeviceOnOffStatusChanged); Light2.SetChangeCallback(&HandleDeviceOnOffStatusChanged); @@ -682,6 +773,17 @@ int main(int argc, char * argv[]) Switch1.SetReachable(true); Switch2.SetReachable(true); + // Setup devices for action cluster tests + ActionLight1.SetChangeCallback(&HandleDeviceOnOffStatusChanged); + ActionLight2.SetChangeCallback(&HandleDeviceOnOffStatusChanged); + ActionLight3.SetChangeCallback(&HandleDeviceOnOffStatusChanged); + ActionLight4.SetChangeCallback(&HandleDeviceOnOffStatusChanged); + + ActionLight1.SetReachable(true); + ActionLight2.SetReachable(true); + ActionLight3.SetReachable(true); + ActionLight4.SetReachable(true); + // Define composed device with two switches ComposedDevice ComposedDevice("Composed Switcher", "Bedroom"); DeviceSwitch ComposedSwitch1("Composed Switch 1", "Bedroom", EMBER_AF_SWITCH_FEATURE_LATCHING_SWITCH); @@ -752,6 +854,19 @@ int main(int argc, char * argv[]) Span(gComposedPowerSourceDeviceTypes), Span(gComposedPowerSourceDataVersions), ComposedDevice.GetEndpointId()); + // Add 4 lights for the Action Clusters tests + AddDeviceEndpoint(&ActionLight1, &bridgedLightEndpoint, Span(gBridgedOnOffDeviceTypes), + Span(gActionLight1DataVersions), 1); + AddDeviceEndpoint(&ActionLight2, &bridgedLightEndpoint, Span(gBridgedOnOffDeviceTypes), + Span(gActionLight2DataVersions), 1); + AddDeviceEndpoint(&ActionLight3, &bridgedLightEndpoint, Span(gBridgedOnOffDeviceTypes), + Span(gActionLight3DataVersions), 1); + AddDeviceEndpoint(&ActionLight4, &bridgedLightEndpoint, Span(gBridgedOnOffDeviceTypes), + Span(gActionLight4DataVersions), 1); + gRooms.push_back(&room1); + gRooms.push_back(&room2); + gRooms.push_back(&room3); + { pthread_t poll_thread; int res = pthread_create(&poll_thread, nullptr, bridge_polling_thread, nullptr); diff --git a/examples/build_overrides/mbedtls.gni b/examples/build_overrides/mbedtls.gni index fff24c4f29f01f..7b7bb7346759b4 100644 --- a/examples/build_overrides/mbedtls.gni +++ b/examples/build_overrides/mbedtls.gni @@ -15,4 +15,5 @@ declare_args() { # Root directory for mbedTLS. mbedtls_root = "//third_party/connectedhomeip/third_party/mbedtls" + mbedtls_repo = "//third_party/connectedhomeip/third_party/mbedtls" } diff --git a/examples/chef/BUILD.gn b/examples/chef/BUILD.gn index 5ba346ebe2417a..5c3280c903c485 100644 --- a/examples/chef/BUILD.gn +++ b/examples/chef/BUILD.gn @@ -21,12 +21,23 @@ import("$dir_pw_build/python.gni") pw_python_package("chef") { setup = [ "setup.py" ] + inputs = [ + "sample_app_util/test_files/sample_zap_file.zap", + "sample_app_util/test_files/sample_zap_file_hashmeta.yaml", + ] + sources = [ "__init__.py", "chef.py", "constants.py", + "sample_app_util/__init__.py", + "sample_app_util/sample_app_util.py", + "sample_app_util/zap_file_parser.py", "stateful_shell.py", ] - tests = [ "test_stateful_shell.py" ] + tests = [ + "test_stateful_shell.py", + "sample_app_util/test_zap_file_parser.py", + ] } diff --git a/examples/chef/chef.py b/examples/chef/chef.py index 8b0e56a6145ba4..fcdd5e4f37a777 100755 --- a/examples/chef/chef.py +++ b/examples/chef/chef.py @@ -461,8 +461,8 @@ def main(argv: Sequence[str]) -> None: if options.do_run_zap: flush_print("Running ZAP script to generate artifacts") - shell.run_cmd(f"mkdir -p {gen_dir}/") - shell.run_cmd(f"rm {gen_dir}/*") + shell.run_cmd(f"rm -rf {gen_dir}") + shell.run_cmd(f"mkdir -p {gen_dir}") shell.run_cmd( f"{_REPO_BASE_PATH}/scripts/tools/zap/generate.py {_CHEF_SCRIPT_PATH}/devices/{options.sample_device_type_name}.zap -o {gen_dir}") # af-gen-event.h is not generated @@ -543,6 +543,11 @@ def main(argv: Sequence[str]) -> None: shell.run_cmd(f"rm -rf {_CHEF_SCRIPT_PATH}/esp32/build") shell.run_cmd("idf.py fullclean") shell.run_cmd("idf.py build") + shell.run_cmd("idf.py build flashing_script") + shell.run_cmd( + f"(cd build/ && tar cJvf $(git rev-parse HEAD)-{options.sample_device_type_name}.tar.xz --files-from=chip-shell.flashbundle.txt)") + shell.run_cmd( + f"cp build/$(git rev-parse HEAD)-{options.sample_device_type_name}.tar.xz {_CHEF_SCRIPT_PATH}") elif options.build_target == "nrfconnect": shell.run_cmd(f"cd {_CHEF_SCRIPT_PATH}/nrfconnect") nrf_build_cmds = ["west build -b nrf52840dk_nrf52840"] @@ -567,6 +572,8 @@ def main(argv: Sequence[str]) -> None: import("//build_overrides/chip.gni") import("${{chip_root}}/config/standalone/args.gni") chip_shell_cmd_server = false + chip_build_libshell = true + chip_config_network_layer_ble = false target_defines = ["CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID={options.vid}", "CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID={options.pid}", "CONFIG_ENABLE_PW_RPC={'1' if options.do_rpc else '0'}"] """)) with open(f"{_CHEF_SCRIPT_PATH}/linux/sample.gni", "w") as f: @@ -577,7 +584,8 @@ def main(argv: Sequence[str]) -> None: if options.do_clean: shell.run_cmd(f"rm -rf out") if options.do_rpc: - shell.run_cmd("gn gen out --args='import(\"//with_pw_rpc.gni\")'") + shell.run_cmd( + "gn gen out --args='import(\"//with_pw_rpc.gni\")'") else: shell.run_cmd("gn gen out --args=''") shell.run_cmd("ninja -C out") diff --git a/examples/chef/common/stubs.cpp b/examples/chef/common/stubs.cpp new file mode 100644 index 00000000000000..ecc3ef52766d55 --- /dev/null +++ b/examples/chef/common/stubs.cpp @@ -0,0 +1,16 @@ +#include +#include +#include +#include +#include +#include + +bool emberAfPluginDoorLockOnDoorLockCommand(chip::EndpointId endpointId, chip::Optional pinCode) +{ + return true; +} + +bool emberAfPluginDoorLockOnDoorUnlockCommand(chip::EndpointId endpointId, chip::Optional pinCode) +{ + return true; +} diff --git a/examples/chef/efr32/args.gni b/examples/chef/efr32/args.gni index 96b6262f50b93e..0b7ef403df72cd 100644 --- a/examples/chef/efr32/args.gni +++ b/examples/chef/efr32/args.gni @@ -21,5 +21,5 @@ efr32_sdk_target = get_label_info(":sdk", "label_no_toolchain") chip_enable_ota_requestor = true pw_log_BACKEND = "${chip_root}/src/lib/support/pw_log_chip" -pw_assert_BACKEND = "$dir_pw_assert_log" +pw_assert_BACKEND = "$dir_pw_assert_log:check_backend" chip_enable_openthread = true diff --git a/examples/chef/efr32/build_for_wifi_args.gni b/examples/chef/efr32/build_for_wifi_args.gni index bf21912871e59d..4a3bdfd804ae19 100644 --- a/examples/chef/efr32/build_for_wifi_args.gni +++ b/examples/chef/efr32/build_for_wifi_args.gni @@ -21,4 +21,4 @@ import("${chip_root}/src/platform/EFR32/wifi_args.gni") chip_enable_ota_requestor = true pw_log_BACKEND = "${chip_root}/src/lib/support/pw_log_chip" -pw_assert_BACKEND = "$dir_pw_assert_log" +pw_assert_BACKEND = "$dir_pw_assert_log:check_backend" diff --git a/examples/chef/esp32/CMakeLists.txt b/examples/chef/esp32/CMakeLists.txt index 086f2eed23a846..b03f1e123b88b2 100644 --- a/examples/chef/esp32/CMakeLists.txt +++ b/examples/chef/esp32/CMakeLists.txt @@ -61,7 +61,8 @@ if (CONFIG_ENABLE_PW_RPC) get_filename_component(CHIP_ROOT ./third_party/connectedhomeip REALPATH) include(third_party/connectedhomeip/third_party/pigweed/repo/pw_build/pigweed.cmake) pw_set_backend(pw_log pw_log_basic) -pw_set_backend(pw_assert pw_assert_log) +pw_set_backend(pw_assert.check pw_assert_log.check_backend) +pw_set_backend(pw_assert.assert pw_assert.assert_compatibility_backend) pw_set_backend(pw_sys_io pw_sys_io.esp32) pw_set_backend(pw_trace pw_trace_tokenized) diff --git a/examples/chef/esp32/main/CMakeLists.txt b/examples/chef/esp32/main/CMakeLists.txt index f242768177544e..68f43aece32ea8 100644 --- a/examples/chef/esp32/main/CMakeLists.txt +++ b/examples/chef/esp32/main/CMakeLists.txt @@ -67,6 +67,7 @@ set(SRC_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/util" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/attributes" + "${CMAKE_SOURCE_DIR}/../common" ) if (CONFIG_ENABLE_CHIP_SHELL) @@ -131,7 +132,7 @@ pw_proto_library(attributes_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(button_service @@ -141,6 +142,17 @@ pw_proto_library(button_service button_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos + DEPS + pw_protobuf.common_proto +) + +pw_proto_library(descriptor_service + SOURCES + ${CHIP_ROOT}/examples/common/pigweed/protos/descriptor_service.proto + PREFIX + descriptor_service + STRIP_PREFIX + ${CHIP_ROOT}/examples/common/pigweed/protos DEPS pw_protobuf.common_protos ) @@ -154,13 +166,27 @@ pw_proto_library(device_service device_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos + DEPS + pw_protobuf.common_proto +) + +pw_proto_library(wifi_service + SOURCES + ${CHIP_ROOT}/examples/common/pigweed/protos/wifi_service.proto + INPUTS + ${CHIP_ROOT}/examples/common/pigweed/protos/wifi_service.options + PREFIX + wifi_service DEPS pw_protobuf.common_protos + STRIP_PREFIX + ${CHIP_ROOT}/examples/common/pigweed/protos ) target_link_libraries(${COMPONENT_LIB} PUBLIC attributes_service.nanopb_rpc button_service.nanopb_rpc + descriptor_service.nanopb_rpc device_service.nanopb_rpc pw_checksum pw_hdlc @@ -170,6 +196,7 @@ target_link_libraries(${COMPONENT_LIB} PUBLIC pw_trace_tokenized.trace_buffer pw_trace_tokenized.rpc_service pw_trace_tokenized.protos.nanopb_rpc + wifi_service.nanopb_rpc ) target_link_options(${COMPONENT_LIB} @@ -181,6 +208,8 @@ target_compile_options(${COMPONENT_LIB} PRIVATE "-DPW_RPC_ATTRIBUTE_SERVICE=1" "-DPW_RPC_BUTTON_SERVICE=1" "-DPW_RPC_DEVICE_SERVICE=1" + "-DPW_RPC_DESCRIPTOR_SERVICE=1" + "-DPW_RPC_WIFI_SERVICE=1" "-DPW_RPC_TRACING_SERVICE=1") endif (CONFIG_ENABLE_PW_RPC) diff --git a/examples/chef/esp32/main/main.cpp b/examples/chef/esp32/main/main.cpp index 5fd864313caa8a..92a3af0bd25854 100644 --- a/examples/chef/esp32/main/main.cpp +++ b/examples/chef/esp32/main/main.cpp @@ -29,11 +29,13 @@ #include #include +#include #include #include #include #include +#include #include #include @@ -161,6 +163,9 @@ void printQRCode() } #endif // CONFIG_HAVE_DISPLAY +app::Clusters::NetworkCommissioning::Instance + sWiFiNetworkCommissioningInstance(0 /* Endpoint Id */, &(NetworkCommissioning::ESPWiFiDriver::GetInstance())); + void InitServer(intptr_t) { // Start IM server @@ -170,6 +175,7 @@ void InitServer(intptr_t) // Device Attestation & Onboarding codes chip::Credentials::SetDeviceAttestationCredentialsProvider(chip::Credentials::Examples::GetExampleDACProvider()); + sWiFiNetworkCommissioningInstance.Init(); chip::DeviceLayer::ConfigurationMgr().LogDeviceConfig(); if (chip::Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow() != CHIP_NO_ERROR) diff --git a/examples/chef/linux/BUILD.gn b/examples/chef/linux/BUILD.gn index 9bd88e4b53c03d..769bcef34d5777 100644 --- a/examples/chef/linux/BUILD.gn +++ b/examples/chef/linux/BUILD.gn @@ -33,14 +33,16 @@ project_dir = "./.." chip_data_model("chef-data-model") { zap_file = "${project_dir}/devices/${sample_zap_file}" - zap_pregenerated_dir = "${chip_root}/examples/chef/out/${sample_name}/zap-generated/" is_server = true } executable("${sample_name}") { - sources = [ "${project_dir}/linux/main.cpp" ] + sources = [ + "${project_dir}/common/stubs.cpp", + "${project_dir}/linux/main.cpp", + ] deps = [ ":chef-data-model", diff --git a/examples/chef/linux/with_pw_rpc.gni b/examples/chef/linux/with_pw_rpc.gni index 969b2b88c9b75b..9533565ecf4ce8 100644 --- a/examples/chef/linux/with_pw_rpc.gni +++ b/examples/chef/linux/with_pw_rpc.gni @@ -24,7 +24,7 @@ import("//build_overrides/pigweed.gni") cpp_standard = "gnu++17" pw_log_BACKEND = "$dir_pw_log_basic" -pw_assert_BACKEND = "$dir_pw_assert_log" +pw_assert_BACKEND = "$dir_pw_assert_log:check_backend" pw_sys_io_BACKEND = "$dir_pw_sys_io_stdio" pw_trace_BACKEND = "$dir_pw_trace_tokenized" pw_unit_test_MAIN = "$dir_pw_unit_test:logging_main" diff --git a/examples/chef/nrfconnect/CMakeLists.txt b/examples/chef/nrfconnect/CMakeLists.txt index 483f275bbdf2c8..1a3483c1bb9a23 100644 --- a/examples/chef/nrfconnect/CMakeLists.txt +++ b/examples/chef/nrfconnect/CMakeLists.txt @@ -83,6 +83,7 @@ endif (CONFIG_ENABLE_CHIP_SHELL) target_sources(app PRIVATE ${CHEF}/nrfconnect/main.cpp + ${CHEF}/common/stubs.cpp ${GEN_DIR}/callback-stub.cpp ${GEN_DIR}/IMClusterCommandHandler.cpp ${NRFCONNECT_COMMON}/util/ThreadUtil.cpp @@ -124,7 +125,8 @@ include(${PIGWEED_ROOT}/pw_protobuf_compiler/proto.cmake) pw_set_module_config(pw_rpc_CONFIG pw_rpc.disable_global_mutex_config) pw_set_backend(pw_log pw_log_basic) -pw_set_backend(pw_assert pw_assert_log) +pw_set_backend(pw_assert.check pw_assert_log.check_backend) +pw_set_backend(pw_assert.assert pw_assert.assert_compatibility_backend) pw_set_backend(pw_sys_io pw_sys_io.nrfconnect) pw_set_backend(pw_trace pw_trace_tokenized) set(dir_pw_third_party_nanopb "${CHIP_ROOT}/third_party/nanopb/repo" CACHE STRING "" FORCE) @@ -143,7 +145,7 @@ pw_proto_library(attributes_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(descriptor_service @@ -154,7 +156,7 @@ pw_proto_library(descriptor_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(device_service @@ -167,7 +169,7 @@ pw_proto_library(device_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(ot_cli_service @@ -180,7 +182,7 @@ pw_proto_library(ot_cli_service PREFIX ot_cli_service DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(thread_service @@ -193,7 +195,7 @@ pw_proto_library(thread_service PREFIX thread_service DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) target_sources(app PRIVATE diff --git a/examples/chef/sample_app_util/README.md b/examples/chef/sample_app_util/README.md new file mode 100644 index 00000000000000..041f9462c4232c --- /dev/null +++ b/examples/chef/sample_app_util/README.md @@ -0,0 +1,195 @@ +# Chef Build Conventions + +## Overview + +--- + +It is convenient to follow some naming and build conventions for Chef tool due +to the large volume of sample apps that may be created and the ambiguity that +may result from arbitrary names. + +There are three components to the convention proposed here: + +1. The naming convention for the sample matter device and clusters (referred to + here as the `sample app`). +2. The naming convention to use for the build files which will be flashed on the + devices. +3. The usage of metadata files that shall accompany build files to provide more + detailed information about builds. + +The convention proposed here should be adopted by the zap files provided in +`examples/chef/devices` and the builds generated from Chef tool in CI. + +## Limitations + +--- + +The largest filename that can be used on MacOS and Linux is 255 characters. If a +sample app name would exceed this limit by following this convention, then the +sample app should be given an arbitrary name. + +This limitation is called out, but, with the given naming conventions, this +should rarely happen. + +## Convention + +--- + +### Sample App Naming Convention + +Sample apps should be named by concatenating the name of all endpoints in the +order of their index. Endpoint names are separated by underscores (`_`) and a 10 +character hash[^hash_note] of the sample app metadata is appended to the end. + +Valid sample app names conform to the following format: + +``` +__ +``` + +For example, here are some valid names: + +``` +rootnode_extendedcolorlight_H1l9gnQDYl +rootnode_speaker_8qRQaEj0Hy +rootnode_lightsensor_L6dEbmVDah +rootnode_dimmablelight_rWsDiwzw2t +rootnode_pressuresensor_03quf7tPOL +rootnode_flowsensor_ixbAboycie +rootnode_windowcovering_b9QoiScjOq +rootnode_doorlock_d5wtU7sjFR +rootnode_thermostat_KuQYArmwl7 +rootnode_dimmablelight_7pNE3GVarn +rootnode_temperaturesensor_i0wGnDVUAc +rootnode_occupancysensor_wyGeQSokNp +rootnode_humiditysensor_pv0comNKyT +bridgednode_temperaturesensor_onofflight_onoffpluginunit_MI9DSdkH8H +``` + +[^hash_note]: + + The 10 character hash is a base64 encoding of the md5 hash generated by + digesting the JSON string encoding of the metadata information. The code for + generating the hash can be found in `generate_hash` in + [zap_file_parser](zap_file_parser.py) There are some notable details + here: 1) The full base64 encoded hash is 16 characters, but only 10 are + used. This still gives us a sufficiently low probability of collision (~1.2 + x 10^-8). 2) `_` and `-` are replaced in the base64 encoding because they + have other uses in the naming. 3) Platform specific information is omitted + from the hash. E.g. the networking_commissioning cluster is excluded. This + is to make the hashes platform agnostic. + +### Sample App Build Naming Convention + +The sample app builds formats will be named by pre-pending the zap file name +(described above) with the platform and appending connectivity info. + +Valid build names conform to the following format: + +``` +_ +``` + +Note that `` follows the convention: +`__`. + +Together that is: + +``` +___ +``` + +The list of platforms supported here (as of writing this) are: + +``` +m5stack +brd4161a +nrf52840dk +linux_x86 +``` + +For example, here are some valid names: + +``` +m5stack_rootnode_humiditysensor_pv0comNKyT +brd4161a_rootnode_humiditysensor_pv0comNKyT +nrf52840dk_rootnode_humiditysensor_pv0comNKyT +linux_x86_rootnode_humiditysensor_pv0comNKyT +``` + +### Metadata file convention + +Metadata files are `yaml` files that should accompany build files. + +The metadata files have a structure as follows: + +``` +- : + client_clusters: + : + attributes: + : + ... + commands: + - + - ... + server_clusters: + : + attributes: + : + ... + commands: + - + - ... +- : ... +``` + +For an example, see [sample_zap_file.yaml](test_files/sample_zap_file.yaml) +which was generated from [sample_zap_file.zap](test_files/sample_zap_file.zap). + +Note that it is more readable in `yaml` format. Since hashes are generated from +the metadata info, additional conventions are needed to ensure consistency for +the metadata structure. + +The following conventions are used: + +- All lists are sorted alphabetically. +- If a list contains dictionaries, it will be sorted by the "name" key. If it + does not contain "name" key, it will be sorted by the first key common to + all dictionaries that comes first alphabetically. +- The list of endpoints is excluded from the above conventions. Endpoints are + ordered according to their endpoint number; here, the endpoint number is the + same as the order they are read from the zap file. + +As an example, take a look at +[sample_zap_file.yaml](test_files/sample_zap_file.yaml) + +## Utility Usage + +--- + +There are a few primary usage cases for the utility +[sample_app_util.py](sample_app_util.py). Details are provided by using +`python sample_app_util.py zap --help`. Below is a summary. + +| Command | Description | +| ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `python sample_app_util.py zap --generate-name` | Generates the name for a zap file per the specified convention | +| `python sample_app_util.py zap --rename-file` | Renames the zap file per specified convention | +| `python sample_app_util.py zap --generate-metadata [output_path]` | Generates the metadata file adjacent to the zap file with `.yaml` extension. If `[output_path]` is provided then the metadata file will be stored at the location specified. | + +## Running Tests + +--- + +Navigate to the base directory of this README. + +``` +cd /examples/chef/sample_app_util +``` + +Run unit tests. + +``` +python -m unittest +``` diff --git a/examples/chef/sample_app_util/__init__.py b/examples/chef/sample_app_util/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/examples/chef/sample_app_util/matter_device_types.json b/examples/chef/sample_app_util/matter_device_types.json new file mode 100644 index 00000000000000..a5dd0745b1e312 --- /dev/null +++ b/examples/chef/sample_app_util/matter_device_types.json @@ -0,0 +1,43 @@ +{ + "Root Node": 22, + "Power Source": 17, + "OTA Requestor": 18, + "OTA Provider": 20, + "Aggregator": 14, + "Bridged Node": 19, + "On/Off Light": 256, + "Dimmable Light": 257, + "Color Temperature Light": 268, + "Extended Color Light": 269, + "On/Off Plug-in Unit": 266, + "Dimmable Plug-In Unit": 267, + "Pump": 771, + "On/Off Light Switch": 259, + "Dimmer Switch": 260, + "Color Dimmer Switch": 261, + "Control Bridge": 2112, + "Pump Controller": 772, + "Generic Switch": 15, + "Contact Sensor": 21, + "Light Sensor": 262, + "Occupancy Sensor": 263, + "Temperature Sensor": 770, + "Pressure Sensor": 773, + "Flow Sensor": 774, + "Humidity Sensor": 775, + "On/Off Sensor": 2128, + "Door Lock": 10, + "Door Lock Controller": 11, + "Window Covering": 514, + "Window Covering Controller": 515, + "Heating/Cooling Unit": 768, + "Thermostat": 769, + "Fan": 43, + "Casting Video Player": 35, + "Speaker": 34, + "Content App": 36, + "Basic Video Player": 40, + "Casting Video Client": 41, + "Video Remote Control": 42, + "Mode Select": 39 +} diff --git a/examples/chef/sample_app_util/sample_app_util.py b/examples/chef/sample_app_util/sample_app_util.py new file mode 100644 index 00000000000000..08cfc87de62eda --- /dev/null +++ b/examples/chef/sample_app_util/sample_app_util.py @@ -0,0 +1,71 @@ +"""Utility to work with sample app device files. + +This utility helps with the following: +- Parsing sample app device files. +- Producing metadata files from sample app device files. +- Generating names for sample app device files. + +Usage: + python sample_app_util.py zap [options] + + python sample_app_util.py zap test_files/sample_zap_file.zap --generate-name + python sample_app_util.py zap test_files/sample_zap_file.zap --generate-metadata +""" + +import argparse +import os +import shutil + +import zap_file_parser + + +def zap_cmd_handler(args: argparse.Namespace) -> None: + """Handles args for zap_cmd_parser.""" + zap_file_path = args.zap_file + if args.generate_name: + print(zap_file_parser.generate_name(zap_file_path)) + elif args.rename_file: + name = zap_file_parser.generate_name(zap_file_path) + dirpath = os.path.dirname(zap_file_path) + hash_string = zap_file_parser.generate_hash(zap_file_path) + output_path = os.path.join(dirpath, f"{name}-{hash_string}.zap") + shutil.move(zap_file_path, output_path) + print(f"Renamed from: {zap_file_path} to {output_path}") + elif args.generate_hash_metadata: + created_file = zap_file_parser.generate_hash_metadata_file(zap_file_path) + print(f"Created {created_file}") + + +parser = argparse.ArgumentParser() +subparsers = parser.add_subparsers(dest="command") +subparsers.required = True + +zap_cmd_parser = subparsers.add_parser("zap", help="Command to operate on zap files.") +zap_cmd_parser.add_argument( + "zap_file", metavar="ZAP_FILE", type=str, help="Zap file to generate name for.") + +zap_cmd_group = zap_cmd_parser.add_mutually_exclusive_group() + +zap_cmd_group.add_argument( + "--generate-name", action="store_true", + help="Print the name file name according to the name convention" +) + +zap_cmd_parser.add_argument( + "--generate-hash-metadata", action="store_true", + help=( + "Generate the hash metadata file which provide information about what was included in " + "the hash digest.") +) + +zap_cmd_group.add_argument( + "--rename-file", action='store_true', + help="Rename the target zap file according to name convention." +) + +zap_cmd_parser.set_defaults(func=zap_cmd_handler) + + +if __name__ == "__main__": + args = parser.parse_args() + args.func(args) diff --git a/examples/chef/sample_app_util/test_files/sample_zap_file.zap b/examples/chef/sample_app_util/test_files/sample_zap_file.zap new file mode 100644 index 00000000000000..2868176f0c6b6d --- /dev/null +++ b/examples/chef/sample_app_util/test_files/sample_zap_file.zap @@ -0,0 +1,7698 @@ +{ + "featureLevel": 71, + "creator": "zap", + "keyValuePairs": [ + { + "key": "commandDiscovery", + "value": "1" + }, + { + "key": "defaultResponsePolicy", + "value": "always" + }, + { + "key": "manufacturerCodes", + "value": "0x1002" + } + ], + "package": [ + { + "pathRelativity": "relativeToZap", + "path": "../../../src/app/zap-templates/zcl/zcl.json", + "version": "ZCL Test Data", + "type": "zcl-properties" + }, + { + "pathRelativity": "relativeToZap", + "path": "../../../src/app/zap-templates/app-templates.json", + "version": "chip-v1", + "type": "gen-templates-json" + } + ], + "endpointTypes": [ + { + "name": "MA-rootdevice", + "deviceTypeName": "MA-rootdevice", + "deviceTypeCode": 22, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [], + "attributes": [ + { + "name": "identify time", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Groups", + "code": 4, + "mfgCode": null, + "define": "GROUPS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "AddGroup", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ViewGroup", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "GetGroupMembership", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RemoveGroup", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RemoveAllGroups", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "AddGroupIfIdentifying", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Groups", + "code": 4, + "mfgCode": null, + "define": "GROUPS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "AddGroupResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "ViewGroupResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "GetGroupMembershipResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "RemoveGroupResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "name support", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Scenes", + "code": 5, + "mfgCode": null, + "define": "SCENES_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "AddScene", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ViewScene", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RemoveScene", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RemoveAllScenes", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "StoreScene", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RecallScene", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "GetSceneMembership", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Scenes", + "code": 5, + "mfgCode": null, + "define": "SCENES_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "AddSceneResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "ViewSceneResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "RemoveSceneResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "RemoveAllScenesResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "StoreSceneResponse", + "code": 4, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "GetSceneMembershipResponse", + "code": 6, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "SceneCount", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentScene", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentGroup", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "group_id", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SceneValid", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NameSupport", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "On/Off", + "code": 6, + "mfgCode": null, + "define": "ON_OFF_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "Off", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "On", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "Toggle", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "On/Off", + "code": 6, + "mfgCode": null, + "define": "ON_OFF_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [], + "attributes": [ + { + "name": "OnOff", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "On/off Switch Configuration", + "code": 7, + "mfgCode": null, + "define": "ON_OFF_SWITCH_CONFIG_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "On/off Switch Configuration", + "code": 7, + "mfgCode": null, + "define": "ON_OFF_SWITCH_CONFIG_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [], + "attributes": [ + { + "name": "switch type", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "switch actions", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Level Control", + "code": 8, + "mfgCode": null, + "define": "LEVEL_CONTROL_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "MoveToLevel", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "Move", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "Step", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "Stop", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "MoveToLevelWithOnOff", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "MoveWithOnOff", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "StepWithOnOff", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "StopWithOnOff", + "code": 7, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Level Control", + "code": 8, + "mfgCode": null, + "define": "LEVEL_CONTROL_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [], + "attributes": [ + { + "name": "current level", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "device list", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "server list", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "client list", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "parts list", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Access Control", + "code": 31, + "mfgCode": null, + "define": "ACCESS_CONTROL_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Access Control", + "code": 31, + "mfgCode": null, + "define": "ACCESS_CONTROL_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "ACL", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Extension", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SubjectsPerAccessControlEntry", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TargetsPerAccessControlEntry", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AccessControlEntriesPerFabric", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Basic", + "code": 40, + "mfgCode": null, + "define": "BASIC_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Basic", + "code": 40, + "mfgCode": null, + "define": "BASIC_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "DataModelRevision", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "10", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "VendorName", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "VendorID", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "vendor_id", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductName", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductID", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NodeLabel", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "NVM", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Location", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "XX", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "HardwareVersion", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "HardwareVersionString", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SoftwareVersion", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SoftwareVersionString", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ManufacturingDate", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "20210614123456ZZ", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PartNumber", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductURL", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "long_char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductLabel", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SerialNumber", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LocalConfigDisabled", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "NVM", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Reachable", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UniqueID", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CapabilityMinima", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "CapabilityMinimaStruct", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "OTA Software Update Provider", + "code": 41, + "mfgCode": null, + "define": "OTA_PROVIDER_CLUSTER", + "side": "client", + "enabled": 1, + "commands": [ + { + "name": "QueryImage", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "ApplyUpdateRequest", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "NotifyUpdateApplied", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "OTA Software Update Provider", + "code": 41, + "mfgCode": null, + "define": "OTA_PROVIDER_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "QueryImageResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ApplyUpdateResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "OTA Software Update Requestor", + "code": 42, + "mfgCode": null, + "define": "OTA_REQUESTOR_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "AnnounceOtaProvider", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "OTA Software Update Requestor", + "code": 42, + "mfgCode": null, + "define": "OTA_REQUESTOR_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "DefaultOtaProviders", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "UpdatePossible", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UpdateState", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "OTAUpdateStateEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UpdateStateProgress", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Localization Configuration", + "code": 43, + "mfgCode": null, + "define": "LOCALIZATION_CONFIGURATION_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [], + "attributes": [] + }, + { + "name": "Localization Configuration", + "code": 43, + "mfgCode": null, + "define": "LOCALIZATION_CONFIGURATION_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "ActiveLocale", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "en-US", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SupportedLocales", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Time Format Localization", + "code": 44, + "mfgCode": null, + "define": "TIME_FORMAT_LOCALIZATION_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [], + "attributes": [] + }, + { + "name": "Time Format Localization", + "code": 44, + "mfgCode": null, + "define": "TIME_FORMAT_LOCALIZATION_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "HourFormat", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "HourFormat", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveCalendarType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "CalendarType", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SupportedCalendarTypes", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Unit Localization", + "code": 45, + "mfgCode": null, + "define": "UNIT_LOCALIZATION_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [], + "attributes": [] + }, + { + "name": "Unit Localization", + "code": 45, + "mfgCode": null, + "define": "UNIT_LOCALIZATION_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [], + "attributes": [ + { + "name": "TemperatureUnit", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "TempUnit", + "included": 0, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "General Commissioning", + "code": 48, + "mfgCode": null, + "define": "GENERAL_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ArmFailSafe", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetRegulatoryConfig", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "CommissioningComplete", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "General Commissioning", + "code": 48, + "mfgCode": null, + "define": "GENERAL_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ArmFailSafeResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetRegulatoryConfigResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "CommissioningCompleteResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "Breadcrumb", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "BasicCommissioningInfo", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "BasicCommissioningInfo", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RegulatoryConfig", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "RegulatoryLocationType", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LocationCapability", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "RegulatoryLocationType", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "6", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Network Commissioning", + "code": 49, + "mfgCode": null, + "define": "NETWORK_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ScanNetworks", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "AddOrUpdateWiFiNetwork", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "AddOrUpdateThreadNetwork", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RemoveNetwork", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ConnectNetwork", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ReorderNetwork", + "code": 8, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Network Commissioning", + "code": 49, + "mfgCode": null, + "define": "NETWORK_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ScanNetworksResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "NetworkConfigResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "ConnectNetworkResponse", + "code": 7, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "MaxNetworks", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Networks", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ScanMaxTimeSeconds", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ConnectMaxTimeSeconds", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "InterfaceEnabled", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LastNetworkingStatus", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "NetworkCommissioningStatus", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LastNetworkID", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LastConnectErrorValue", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int32s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Diagnostic Logs", + "code": 50, + "mfgCode": null, + "define": "DIAGNOSTIC_LOGS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "RetrieveLogsRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "General Diagnostics", + "code": 51, + "mfgCode": null, + "define": "GENERAL_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "General Diagnostics", + "code": 51, + "mfgCode": null, + "define": "GENERAL_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "NetworkInterfaces", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RebootCount", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UpTime", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TotalOperationalHours", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BootReasons", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveHardwareFaults", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveRadioFaults", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveNetworkFaults", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Software Diagnostics", + "code": 52, + "mfgCode": null, + "define": "SOFTWARE_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ResetWatermarks", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Software Diagnostics", + "code": 52, + "mfgCode": null, + "define": "SOFTWARE_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "ThreadMetrics", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentHeapFree", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentHeapUsed", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentHeapHighWatermark", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Thread Network Diagnostics", + "code": 53, + "mfgCode": null, + "define": "THREAD_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ResetCounts", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Thread Network Diagnostics", + "code": 53, + "mfgCode": null, + "define": "THREAD_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "channel", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RoutingRole", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NetworkName", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PanId", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ExtendedPanId", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MeshLocalPrefix", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OverrunCount", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NeighborTableList", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RouteTableList", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PartitionId", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "weighting", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "DataVersion", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "StableDataVersion", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LeaderRouterId", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "DetachedRoleCount", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ChildRoleCount", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RouterRoleCount", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LeaderRoleCount", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "AttachAttemptCount", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PartitionIdChangeCount", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "BetterPartitionAttachAttemptCount", + "code": 20, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ParentChangeCount", + "code": 21, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxTotalCount", + "code": 22, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxUnicastCount", + "code": 23, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxBroadcastCount", + "code": 24, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxAckRequestedCount", + "code": 25, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxAckedCount", + "code": 26, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxNoAckRequestedCount", + "code": 27, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxDataCount", + "code": 28, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxDataPollCount", + "code": 29, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxBeaconCount", + "code": 30, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxBeaconRequestCount", + "code": 31, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxOtherCount", + "code": 32, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxRetryCount", + "code": 33, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxDirectMaxRetryExpiryCount", + "code": 34, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxIndirectMaxRetryExpiryCount", + "code": 35, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxErrCcaCount", + "code": 36, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxErrAbortCount", + "code": 37, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxErrBusyChannelCount", + "code": 38, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxTotalCount", + "code": 39, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxUnicastCount", + "code": 40, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxBroadcastCount", + "code": 41, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxDataCount", + "code": 42, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxDataPollCount", + "code": 43, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxBeaconCount", + "code": 44, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxBeaconRequestCount", + "code": 45, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxOtherCount", + "code": 46, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxAddressFilteredCount", + "code": 47, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxDestAddrFilteredCount", + "code": 48, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxDuplicatedCount", + "code": 49, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrNoFrameCount", + "code": 50, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrUnknownNeighborCount", + "code": 51, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrInvalidSrcAddrCount", + "code": 52, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrSecCount", + "code": 53, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrFcsCount", + "code": 54, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrOtherCount", + "code": 55, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ActiveTimestamp", + "code": 56, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PendingTimestamp", + "code": 57, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "delay", + "code": 58, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SecurityPolicy", + "code": 59, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ChannelMask", + "code": 60, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OperationalDatasetComponents", + "code": 61, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ActiveNetworkFaultsList", + "code": 62, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x000F", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "WiFi Network Diagnostics", + "code": 54, + "mfgCode": null, + "define": "WIFI_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ResetCounts", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "WiFi Network Diagnostics", + "code": 54, + "mfgCode": null, + "define": "WIFI_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "bssid", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SecurityType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "SecurityType", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "WiFiVersion", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "WiFiVersionType", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ChannelNumber", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Rssi", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int8s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "BeaconLostCount", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BeaconRxCount", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PacketMulticastRxCount", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PacketMulticastTxCount", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PacketUnicastRxCount", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PacketUnicastTxCount", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentMaxRate", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "OverrunCount", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Ethernet Network Diagnostics", + "code": 55, + "mfgCode": null, + "define": "ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ResetCounts", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Ethernet Network Diagnostics", + "code": 55, + "mfgCode": null, + "define": "ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "PHYRate", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "PHYRateType", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FullDuplex", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PacketRxCount", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PacketTxCount", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxErrCount", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CollisionCount", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OverrunCount", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CarrierDetect", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TimeSinceReset", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Switch", + "code": 59, + "mfgCode": null, + "define": "SWITCH_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [], + "attributes": [] + }, + { + "name": "Switch", + "code": 59, + "mfgCode": null, + "define": "SWITCH_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "AdministratorCommissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "OpenCommissioningWindow", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "OpenBasicCommissioningWindow", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RevokeCommissioning", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "AdministratorCommissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "WindowStatus", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AdminFabricIndex", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "fabric_idx", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AdminVendorId", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Operational Credentials", + "code": 62, + "mfgCode": null, + "define": "OPERATIONAL_CREDENTIALS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "AttestationRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "CertificateChainRequest", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "CSRRequest", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "AddNOC", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "UpdateNOC", + "code": 7, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "UpdateFabricLabel", + "code": 9, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveFabric", + "code": 10, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "AddTrustedRootCertificate", + "code": 11, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveTrustedRootCertificate", + "code": 12, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Operational Credentials", + "code": 62, + "mfgCode": null, + "define": "OPERATIONAL_CREDENTIALS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "AttestationResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "CertificateChainResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "CSRResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "NOCResponse", + "code": 8, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "NOCs", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Fabrics", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SupportedFabrics", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CommissionedFabrics", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TrustedRootCertificates", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentFabricIndex", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "fabric_idx", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Group Key Management", + "code": 63, + "mfgCode": null, + "define": "GROUP_KEY_MANAGEMENT_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "KeySetWrite", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "KeySetRead", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "KeySetRemove", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "KeySetReadAllIndices", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [] + }, + { + "name": "Group Key Management", + "code": 63, + "mfgCode": null, + "define": "GROUP_KEY_MANAGEMENT_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "KeySetReadResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "KeySetReadAllIndicesResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "GroupKeyMap", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GroupTable", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxGroupsPerFabric", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxGroupKeysPerFabric", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Fixed Label", + "code": 64, + "mfgCode": null, + "define": "FIXED_LABEL_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [], + "attributes": [] + }, + { + "name": "Fixed Label", + "code": 64, + "mfgCode": null, + "define": "FIXED_LABEL_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "label list", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "User Label", + "code": 65, + "mfgCode": null, + "define": "USER_LABEL_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [], + "attributes": [] + }, + { + "name": "User Label", + "code": 65, + "mfgCode": null, + "define": "USER_LABEL_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "label list", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + }, + { + "name": "MA-dimmablelight", + "deviceTypeName": "MA-dimmablelight", + "deviceTypeCode": 257, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "TriggerEffect", + "code": 64, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "identify time", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "identify type", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Groups", + "code": 4, + "mfgCode": null, + "define": "GROUPS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "AddGroup", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ViewGroup", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "GetGroupMembership", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RemoveGroup", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RemoveAllGroups", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "AddGroupIfIdentifying", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Groups", + "code": 4, + "mfgCode": null, + "define": "GROUPS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "AddGroupResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "ViewGroupResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "GetGroupMembershipResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "RemoveGroupResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "name support", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Scenes", + "code": 5, + "mfgCode": null, + "define": "SCENES_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "AddScene", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ViewScene", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RemoveScene", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RemoveAllScenes", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "StoreScene", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RecallScene", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "GetSceneMembership", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "EnhancedAddScene", + "code": 64, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "EnhancedViewScene", + "code": 65, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "CopyScene", + "code": 66, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Scenes", + "code": 5, + "mfgCode": null, + "define": "SCENES_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "AddSceneResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "ViewSceneResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "RemoveSceneResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "RemoveAllScenesResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "StoreSceneResponse", + "code": 4, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "GetSceneMembershipResponse", + "code": 6, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "SceneCount", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentScene", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentGroup", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "group_id", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SceneValid", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NameSupport", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "On/Off", + "code": 6, + "mfgCode": null, + "define": "ON_OFF_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "Off", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "On", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "Toggle", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "OffWithEffect", + "code": 64, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "OnWithRecallGlobalScene", + "code": 65, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "OnWithTimedOff", + "code": 66, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "On/Off", + "code": 6, + "mfgCode": null, + "define": "ON_OFF_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "OnOff", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "GlobalSceneControl", + "code": 16384, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x01", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OnTime", + "code": 16385, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OffWaitTime", + "code": 16386, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "StartUpOnOff", + "code": 16387, + "mfgCode": null, + "side": "server", + "type": "OnOffStartUpOnOff", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFF", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Level Control", + "code": 8, + "mfgCode": null, + "define": "LEVEL_CONTROL_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "MoveToLevel", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "Move", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "Step", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "Stop", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "MoveToLevelWithOnOff", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "MoveWithOnOff", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "StepWithOnOff", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "StopWithOnOff", + "code": 7, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Level Control", + "code": 8, + "mfgCode": null, + "define": "LEVEL_CONTROL_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "current level", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x01", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "remaining time", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "min level", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "max level", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFE", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "current frequency", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "min frequency", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "max frequency", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "options", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "on off transition time", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "on level", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFF", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "on transition time", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "off transition time", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "default move rate", + "code": 20, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "start up current level", + "code": 16384, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "255", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "device list", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "server list", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "client list", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "parts list", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Basic", + "code": 40, + "mfgCode": null, + "define": "BASIC_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Basic", + "code": 40, + "mfgCode": null, + "define": "BASIC_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [], + "attributes": [ + { + "name": "DataModelRevision", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "10", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "VendorName", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "VendorID", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "vendor_id", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductName", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductID", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NodeLabel", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "NVM", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Location", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "XX", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "HardwareVersion", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "HardwareVersionString", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SoftwareVersion", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SoftwareVersionString", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ManufacturingDate", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "20210614123456ZZ", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PartNumber", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductURL", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "long_char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductLabel", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SerialNumber", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LocalConfigDisabled", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "NVM", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Reachable", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UniqueID", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CapabilityMinima", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "CapabilityMinimaStruct", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Color Control", + "code": 768, + "mfgCode": null, + "define": "COLOR_CONTROL_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "MoveToHue", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "MoveHue", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "StepHue", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "MoveToSaturation", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "MoveSaturation", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "StepSaturation", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "MoveToHueAndSaturation", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "MoveToColor", + "code": 7, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveColor", + "code": 8, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StepColor", + "code": 9, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "MoveToColorTemperature", + "code": 10, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "EnhancedMoveToHue", + "code": 64, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "EnhancedMoveHue", + "code": 65, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "EnhancedStepHue", + "code": 66, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "EnhancedMoveToHueAndSaturation", + "code": 67, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ColorLoopSet", + "code": 68, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "StopMoveStep", + "code": 71, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "MoveColorTemperature", + "code": 75, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "StepColorTemperature", + "code": 76, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Color Control", + "code": 768, + "mfgCode": null, + "define": "COLOR_CONTROL_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "CurrentHue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentSaturation", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RemainingTime", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentX", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x616B", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentY", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x607D", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "DriftCompensation", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CompensationText", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorTemperature", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00FA", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorMode", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x01", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Options", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NumberOfPrimaries", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EnhancedCurrentHue", + "code": 16384, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "EnhancedColorMode", + "code": 16385, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x01", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorLoopActive", + "code": 16386, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorLoopDirection", + "code": 16387, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorLoopTime", + "code": 16388, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0019", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorLoopStartEnhancedHue", + "code": 16389, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x2300", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorLoopStoredEnhancedHue", + "code": 16390, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorCapabilities", + "code": 16394, + "mfgCode": null, + "side": "server", + "type": "bitmap16", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorTempPhysicalMinMireds", + "code": 16395, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ColorTempPhysicalMaxMireds", + "code": 16396, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFEFF", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CoupleColorTempToLevelMinMireds", + "code": 16397, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "StartUpColorTemperatureMireds", + "code": 16400, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Occupancy Sensing", + "code": 1030, + "mfgCode": null, + "define": "OCCUPANCY_SENSING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Occupancy Sensing", + "code": 1030, + "mfgCode": null, + "define": "OCCUPANCY_SENSING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "occupancy", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "occupancy sensor type", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "occupancy sensor type bitmap", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + } + ] + } + ], + "endpoints": [ + { + "endpointTypeName": "MA-rootdevice", + "endpointTypeIndex": 0, + "profileId": 259, + "endpointId": 0, + "networkId": 0, + "endpointVersion": 1, + "deviceIdentifier": 22 + }, + { + "endpointTypeName": "MA-dimmablelight", + "endpointTypeIndex": 1, + "profileId": 259, + "endpointId": 1, + "networkId": 0, + "endpointVersion": 1, + "deviceIdentifier": 257 + } + ] +} \ No newline at end of file diff --git a/examples/chef/sample_app_util/test_files/sample_zap_file_hashmeta.yaml b/examples/chef/sample_app_util/test_files/sample_zap_file_hashmeta.yaml new file mode 100644 index 00000000000000..b42a98e0d8943a --- /dev/null +++ b/examples/chef/sample_app_util/test_files/sample_zap_file_hashmeta.yaml @@ -0,0 +1,90 @@ +- RootNode/22: + client_clusters: + OtaSoftwareUpdateProvider/41: + attributes: + FeatureMap/65532: '0' + server_clusters: + AccessControl/31: + attributes: + FeatureMap/65532: '0' + AdministratorCommissioning/60: + attributes: + FeatureMap/65532: '0' + Basic/40: + attributes: + FeatureMap/65532: '0' + Descriptor/29: + attributes: + FeatureMap/65532: '0' + DiagnosticLogs/50: + attributes: + FeatureMap/65532: '0' + EthernetNetworkDiagnostics/55: + attributes: + FeatureMap/65532: '3' + FixedLabel/64: + attributes: + FeatureMap/65532: '0' + GeneralCommissioning/48: + attributes: + FeatureMap/65532: '6' + GeneralDiagnostics/51: + attributes: + FeatureMap/65532: '0' + GroupKeyManagement/63: + attributes: + FeatureMap/65532: '0' + Groups/4: + attributes: + FeatureMap/65532: '0' + LocalizationConfiguration/43: + attributes: + FeatureMap/65532: '0' + OperationalCredentials/62: + attributes: + FeatureMap/65532: '0' + OtaSoftwareUpdateRequestor/42: + attributes: + FeatureMap/65532: '0' + SoftwareDiagnostics/52: + attributes: + FeatureMap/65532: '1' + Switch/59: + attributes: + FeatureMap/65532: '0' + ThreadNetworkDiagnostics/53: + attributes: + FeatureMap/65532: '15' + TimeFormatLocalization/44: + attributes: + FeatureMap/65532: '0' + UserLabel/65: + attributes: + FeatureMap/65532: '0' + WiFiNetworkDiagnostics/54: + attributes: + FeatureMap/65532: '3' +- DimmableLight/257: + client_clusters: {} + server_clusters: + ColorControl/768: + attributes: + FeatureMap/65532: '0' + Descriptor/29: + attributes: + FeatureMap/65532: '0' + Groups/4: + attributes: + FeatureMap/65532: '0' + Identify/3: + attributes: + FeatureMap/65532: '0' + LevelControl/8: + attributes: + FeatureMap/65532: '3' + OccupancySensing/1030: + attributes: + FeatureMap/65532: '0' + OnOff/6: + attributes: + FeatureMap/65532: '1' diff --git a/examples/chef/sample_app_util/test_zap_file_parser.py b/examples/chef/sample_app_util/test_zap_file_parser.py new file mode 100644 index 00000000000000..a49345ad128eb1 --- /dev/null +++ b/examples/chef/sample_app_util/test_zap_file_parser.py @@ -0,0 +1,63 @@ +"""Tests for zap_file_parser.py + +Usage: +python -m unittest +""" + +import os +import shutil +import tempfile +import unittest + +try: + import yaml +except ImportError: + print("Missing yaml library. Install with:\npip install pyyaml") + exit(1) + +import zap_file_parser + + +_HERE = os.path.abspath(os.path.dirname(__file__)) +_TEST_FILE = os.path.join(_HERE, "test_files", "sample_zap_file.zap") +_TEST_METADATA = os.path.join(_HERE, "test_files", "sample_zap_file_hashmeta.yaml") + + +class TestZapFileParser(unittest.TestCase): + """Testcases for zap_file_parser.py.""" + + def test_generate_hash(self): + """Tests generate_hash function.""" + hash_string = zap_file_parser.generate_hash(_TEST_FILE) + self.assertEqual(hash_string, "Xir1gEfjij", "Hash is incorrectly generated.") + + def test_generate_metadata(self): + """Tests generate_metadata.""" + generated_metadata = zap_file_parser.generate_hash_metadata(_TEST_FILE) + with open(_TEST_METADATA) as f: + expected_metadata = yaml.load(f.read(), Loader=yaml.FullLoader) + self.assertEqual( + generated_metadata, expected_metadata, "Metadata not generated correctly.") + + def test_generate_metadata_file(self): + """Tests generate_metadata_file.""" + with tempfile.TemporaryDirectory(dir=os.path.dirname(_HERE)) as dir: + zap_file = os.path.join(dir, "test_file.zap") + hashmeta_file = os.path.join(dir, "test_file_hashmeta.yaml") + shutil.copy(_TEST_FILE, zap_file) + zap_file_parser.generate_hash_metadata_file(zap_file) + with open(hashmeta_file) as f: + generated_metadata = yaml.load(f.read(), Loader=yaml.FullLoader) + with open(_TEST_METADATA) as f: + expected_metadata = yaml.load(f.read(), Loader=yaml.FullLoader) + self.assertEqual( + generated_metadata, expected_metadata, "Metadata file not generated correctly.") + + def test_generate_name(self): + """Tests generate_name.""" + name = zap_file_parser.generate_name(_TEST_FILE) + self.assertEqual(name, "rootnode_dimmablelight_Xir1gEfjij", "Name incorrectly generated.") + + +if __name__ == "__main__": + unittest.main() diff --git a/examples/chef/sample_app_util/zap_file_parser.py b/examples/chef/sample_app_util/zap_file_parser.py new file mode 100644 index 00000000000000..66a09c0c70e27a --- /dev/null +++ b/examples/chef/sample_app_util/zap_file_parser.py @@ -0,0 +1,353 @@ +"""Module for parsing zap files for use in sample_app_util.py. + + +Note on generating the hash: + Care must be taken to produce a hash value which is not affected by updates to the zap file. + For this reason, it is necessary to ensure a consistent order for all lists. It is also + necessary to generate a minimum set of parameters that can be used to uniquely identify a + particular build. In this case, the hash is generated from the metadata file data. + + The actual hash is generated by digesting the output from json.dumps() with `sort_keys=True`. + The json lib is a good choice here because it is a Python standard lib and the output is + unlikely to change. Additionally, using `sort_keys=True` provides us with a guaranteed output + for the ordering of dict keys. + + After generating the hash, the hash is converted to base64 and the first 10 characters are used. + The probability of a collision (with 100,000 items) is 1-exp(-100000^2/62^10) ~= 1.2 x 10^-8. + +Conventions used for constructing the metadata file: + - All lists are sorted alphabetically. + - If a list contains dicts, it will be sorted by the "name" key. If it does not contain "name" + key, it will be sorted by the first key common to all dicts that comes first alphabetically. + - The list of endpoints is excluded from the above conventions. Endpoints are ordered according + to their endpoint number; here, the endpoint number is the same as the order they are read + from the zap file. + +Future work: + - _load_matter_device_types should be updated to get the mapping for device type ID and device + name from the matter spec directly. This should be done once the matter spec becomes publicly + available. + - Add support for .matter files. +""" +import copy +import base64 +import hashlib +import json +import os +import re + +from typing import Dict, List, Literal, Optional, Sequence, TypedDict, Union + +try: + import yaml +except ImportError: + print("Missing yaml library. Install with:\npip install pyyaml") + exit(1) + +_NETWORK_COMMISSIONING_CODE = "49" +_FEATURE_MAP_CODE = "65532" + +_ATTRIBUTE_ALLOW_LIST = ( + _FEATURE_MAP_CODE, # Feature Map +) + +_HERE = os.path.abspath(os.path.dirname(__file__)) +_MATTER_DEVICE_LIST = os.path.join(_HERE, "matter_device_types.json") + + +class ClusterType(TypedDict): + commands: List[str] + attributes: Dict[str, str] + + +class EndpointType(TypedDict): + client_clusters: Dict[str, ClusterType] + server_clusters: Dict[str, ClusterType] + + +def _b64encode(input_data: bytes) -> bytes: + """Returns urlsafe base64 encoded with padding removed.""" + return base64.urlsafe_b64encode(input_data).strip(b"=") + + +def _b64decode(input_data: bytes) -> bytes: + """Returns urlsafe base64 decoded with padding added.""" + # "=" is padding character that doesn't carry info. + # Adding 2x "=" will handle all edge cases where there may be + # incorrect number of bytes. + return base64.urlsafe_b64decode(input_data + b"==") + + +def _convert_metadata_name(name: str, code: Union[int, str]) -> str: + """Converts a name for use in a metadata file - CamelCaseName/ID.""" + # Preserve camel case if it's already there + name = re.sub(r"([A-Z]+)", r" \1", name).title() + # Convert to camel case and append ID + return re.sub(r"[^a-zA-Z]+", "", name.title()) + f"/{int(code)}" + + +def _convert_filename(name: str) -> str: + """Converts a pretty name into a file friendly one.""" + return re.sub(r"[^a-zA-Z]+", "", name).lower() + + +def _load_matter_device_types() -> Dict[Union[int, str], Union[int, str]]: + """Load matter device type reversible mapping. + + This function should be updated to pull from the Matter spec once it is available publicly. + + Returns: + A dictionary mapping Matter device type IDs to their proper name and vice versa. + """ + with open(_MATTER_DEVICE_LIST) as f: + mapping = json.loads(f.read()) + reverse_mapping = {} + for key, val in mapping.items(): + reverse_mapping[val] = key + mapping.update(reverse_mapping) + return mapping + + +def _read_value(input_string: str) -> str: + """Convert various numeric forms to regular decimal format if possible.""" + ret_val = "" + if not input_string: + ret_val = "" + if "0x" in input_string: + ret_val = int(input_string, 16) + elif "." in input_string: + try: + ret_val = float(input_string) + except ValueError: + pass + else: + try: + ret_val = int(input_string) + except ValueError: + pass + return str(ret_val) + + +def _convert_metadata_to_hashable_digest(metadata_input: Sequence[Dict[str, EndpointType]]) -> str: + """Converts metadata input into a hashable digest. + + Note that the output produced here is consistent across runs. Lists are sorted and dictionaries + are sorted by their keys. + + Args: + metadata_input: Metadata input produced from a zap file or read in from the hashable file. + + Returns: + Hashable string for digest into a hash algorithm. + """ + metadata = copy.deepcopy(metadata_input) + + # Replace endpoint, cluster, attribute, and commands names with IDs + + # Replace endpoint names + for endpoint in metadata: + endpoint_key = list(endpoint.keys())[0] + endpoint_id = _get_id(endpoint_key) + endpoint[endpoint_id] = endpoint.pop(endpoint_key) + endpoint_obj = endpoint[endpoint_id] + + # Replace cluster names + for cluster_type in ["client_clusters", "server_clusters"]: + for cluster_key in list(endpoint_obj[cluster_type].keys()): + cluster_id = _get_id(cluster_key) + endpoint_obj[cluster_type][cluster_id] = endpoint_obj[cluster_type].pop(cluster_key) + cluster_obj = endpoint_obj[cluster_type][cluster_id] + + # Replace attribute names + attribute_obj = cluster_obj["attributes"] + attribute_keys = list(cluster_obj["attributes"]) + for attribute_key in attribute_keys: + attribute_id = _get_id(attribute_key) + attribute_obj[attribute_id] = attribute_obj.pop(attribute_key) + + # Replace command names + if "commands" in cluster_obj: + command_keys = cluster_obj["commands"] + cluster_obj["commands"] = [_get_id(x) for x in command_keys] + cluster_obj["commands"].sort() + + return json.dumps(metadata, sort_keys=True) + + +def _get_id(name): + """Gets id from a condensed name which is formatted like: name/id.""" + return name.split("/")[-1] + + +def generate_hash(zap_file_path: str) -> str: + """Generates a hash for a zap file. + + Args: + zap_file_path: Path to the zap file. + + Returns: + MD5 hash of the metadata generated from the zap file. + This is converted to base64 and then the first 10 characters are used. + """ + parsed = generate_hash_metadata(zap_file_path) + # Use json.dumps to produce a consistent output for the object passed into it. + digestible_content = _convert_metadata_to_hashable_digest(parsed) + md5_hash = hashlib.md5(digestible_content.encode("utf-8")).digest() + output = str(_b64encode(md5_hash), encoding="utf-8")[:10] + # Replace "-" and "_" with "a" and "b". + # The reason for doing this is to allow the generated name to be parsed by splitting on "_". + # Replacing "-" makes the name easier to parse visually. + # This increases likelihood of hash collisions, but minimally so. See module docstring. + return output.replace("-", "a").replace("_", "b") + + +def generate_hash_metadata(zap_file_path: str) -> List[Dict[str, EndpointType]]: + """Generates metadata for hash digest consumption.""" + return generate_metadata( + zap_file_path=zap_file_path, + attribute_allow_list=_ATTRIBUTE_ALLOW_LIST, + include_commands=False, + include_platform_specific_info=False) + + +def generate_metadata( + zap_file_path: str, + attribute_allow_list: Optional[Sequence[str]] = _ATTRIBUTE_ALLOW_LIST, + include_commands: bool = False, + include_platform_specific_info: bool = False) -> List[Dict[str, EndpointType]]: + """Parses a zap_file and returns structure containing minimal content. + + The lists provided in the returned objects are sorted except for the top level list of endpoints. + Lists containing dicts will be sorted by the "name" key of the individual dicts. + + Args: + zap_file_path: Path to the zap file. + attribute_allow_list: List of attribute IDs which are included in the metadata. + If set to None then all attributes will be included. + include_commands: Whether to include commands in the metadata. + include_platform_specific_info: Whether to include platform specific information. + Omitting this allows us to generate a hash that is agnostic of the platform. + + Returns: + Dictionary containing information about endpoints and clusters. Format will be as follows: + [ + { + /: { + "server_clusters": { + /: { + "commands": [ + / + ], + "attributes": { + /: , + } + } + } + "client_clusters": { ... } + } + /: { ... } + } + ] + """ + endpoint_names = _load_matter_device_types() + with open(zap_file_path) as f: + app_data = json.loads(f.read()) + + return_obj: List[Dict[str, EndpointType]] = [] + + for endpoint in app_data["endpointTypes"]: + device_type_id = endpoint["deviceTypeCode"] + device_type_name = endpoint_names[device_type_id] + + endpoint_ref = _convert_metadata_name(device_type_name, device_type_id) + endpoint_obj: Dict[str, EndpointType] = {endpoint_ref: {}} + return_obj.append(endpoint_obj) + + client_clusters: Dict[str, ClusterType] = {} + server_clusters: Dict[str, ClusterType] = {} + + endpoint_obj[endpoint_ref]["client_clusters"] = client_clusters + endpoint_obj[endpoint_ref]["server_clusters"] = server_clusters + + for cluster in endpoint["clusters"]: + # The network commissioning cluster contains platform specific details + # such as how the platform will be commissioned to the matter fabric. + if (not include_platform_specific_info and + str(cluster["code"]) == _NETWORK_COMMISSIONING_CODE): + continue + if not cluster["enabled"]: + continue + + cluster_ref = _convert_metadata_name(cluster["name"], cluster["code"]) + + if include_commands: + cluster_obj: ClusterType = {"attributes": {}, "commands": []} + else: + cluster_obj: ClusterType = {"attributes": {}} + + for attribute in cluster["attributes"]: + attribute_allowed = ( + attribute_allow_list is None or str(attribute["code"]) in attribute_allow_list) + if attribute["included"] and attribute_allowed: + attribute_ref = _convert_metadata_name(attribute["name"], attribute["code"]) + value = _read_value(attribute["defaultValue"]) + cluster_obj["attributes"][attribute_ref] = value + + # Add a default feature map if none is provided + if "FeatureMap/65532" not in cluster_obj["attributes"]: + cluster_obj["attributes"]["FeatureMap/65532"] = "0" + + if include_commands: + for command in cluster["commands"]: + command_ref = _convert_metadata_name(command["name"], command["code"]) + if cluster["side"] == "client" and command["outgoing"] == 1: + cluster_obj["commands"].append(command_ref) + elif cluster["side"] == "server" and command["incoming"] == 1: + cluster_obj["commands"].append(command_ref) + + cluster_obj["commands"] = sorted(cluster_obj["commands"]) + + if cluster["side"] == "client": + client_clusters[cluster_ref] = cluster_obj + else: + server_clusters[cluster_ref] = cluster_obj + + return return_obj + + +def generate_hash_metadata_file(zap_file_path: str) -> str: + """Generates hash metadata file for a zap file input. + + The purpose of this file is to inform the user what data was included in the hash digest. + + Args: + zap_file_path: Path to the zap file to parse for generating the metadata file. + """ + parsed = generate_hash_metadata(zap_file_path) + output = yaml.dump(parsed, indent=4, sort_keys=True) + + dirname, filename = os.path.split(zap_file_path) + + filename = os.path.splitext(filename)[0] + output_file_path = os.path.join(dirname, f"{filename}_hashmeta.yaml") + with open(output_file_path, "w") as f: + f.write(output) + return output_file_path + + +def generate_name(zap_file_path: str) -> str: + """Generates the name for a zap file following convention. + + Args: + zap_file_path: Path to the zap file to parse for generating the metadata file. + + Returns: + Name of the file generated by following convention. + """ + parsed = generate_metadata(zap_file_path) + names = [] + for endpoint in parsed: + name = next(iter(endpoint)) + names.append(_convert_filename(name)) + hash_string = generate_hash(zap_file_path) + return "_".join(names) + f"_{hash_string}" diff --git a/examples/chip-tool/BUILD.gn b/examples/chip-tool/BUILD.gn index 2da0372fef7458..694d88a7ceadd0 100644 --- a/examples/chip-tool/BUILD.gn +++ b/examples/chip-tool/BUILD.gn @@ -30,6 +30,7 @@ config("config") { ] defines = [ + "CONFIG_USE_LOCAL_STORAGE=${config_use_local_storage}", "CONFIG_USE_SEPARATE_EVENTLOOP=${config_use_separate_eventloop}", "CONFIG_USE_INTERACTIVE_MODE=${config_use_interactive_mode}", "CONFIG_ENABLE_YAML_TESTS=${config_enable_yaml_tests}", @@ -49,10 +50,13 @@ static_library("chip-tool-utils") { "${chip_root}/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.cpp", "${chip_root}/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp", "commands/clusters/ModelCommand.cpp", + "commands/clusters/ModelCommand.h", "commands/common/CHIPCommand.cpp", "commands/common/CHIPCommand.h", "commands/common/Command.cpp", + "commands/common/Command.h", "commands/common/Commands.cpp", + "commands/common/Commands.h", "commands/common/CredentialIssuerCommands.h", "commands/discover/DiscoverCommand.cpp", "commands/discover/DiscoverCommissionablesCommand.cpp", @@ -61,6 +65,8 @@ static_library("chip-tool-utils") { # TODO - enable CommissionedListCommand once DNS Cache is implemented # "commands/pairing/CommissionedListCommand.cpp", # "commands/pairing/CommissionedListCommand.h", + "commands/pairing/CloseSessionCommand.cpp", + "commands/pairing/CloseSessionCommand.h", "commands/pairing/OpenCommissioningWindowCommand.cpp", "commands/pairing/OpenCommissioningWindowCommand.h", "commands/pairing/PairingCommand.cpp", diff --git a/examples/chip-tool/README.md b/examples/chip-tool/README.md index 4b266923782653..3385e7c7c36cdc 100644 --- a/examples/chip-tool/README.md +++ b/examples/chip-tool/README.md @@ -67,9 +67,9 @@ remote device, as well as the network credentials to use. The command below uses the default values hard-coded into the debug versions of the ESP32 all-clusters-app to commission it onto a Wi-Fi network: - ``` - $ chip-tool pairing ble-wifi ${NODE_ID_TO_ASSIGN} ${SSID} ${PASSWORD} 20202021 3840 - ``` +``` +chip-tool pairing ble-wifi ${NODE_ID_TO_ASSIGN} ${SSID} ${PASSWORD} 20202021 3840 +``` where: @@ -81,38 +81,38 @@ where: For example: - ``` - $ chip-tool pairing ble-wifi 0x11 xyz secret 20202021 3840 - ``` +``` +chip-tool pairing ble-wifi 0x11 xyz secret 20202021 3840 +``` or equivalently: - ``` - $ chip-tool pairing ble-wifi 17 hex:787980 hex:736563726574 20202021 3840 - ``` +``` +chip-tool pairing ble-wifi 17 hex:787980 hex:736563726574 20202021 3840 +``` #### Pair a device over IP The command below will discover devices and try to pair with the first one it discovers using the provided setup code. - ``` - $ chip-tool pairing onnetwork ${NODE_ID_TO_ASSIGN} 20202021 - ``` +``` +chip-tool pairing onnetwork ${NODE_ID_TO_ASSIGN} 20202021 +``` The command below will discover devices with long discriminator 3840 and try to pair with the first one it discovers using the provided setup code. - ``` - $ chip-tool pairing onnetwork-long ${NODE_ID_TO_ASSIGN} 20202021 3840 - ``` +``` +chip-tool pairing onnetwork-long ${NODE_ID_TO_ASSIGN} 20202021 3840 +``` The command below will discover devices based on the given QR code (which devices log when they start up) and try to pair with the first one it discovers. - ``` - $ chip-tool pairing code ${NODE_ID_TO_ASSIGN} MT:####### - ``` +``` +chip-tool pairing code ${NODE_ID_TO_ASSIGN} MT:####### +``` In all these cases, the device will be assigned node id `${NODE_ID_TO_ASSIGN}` (which must be a decimal number or a 0x-prefixed hex number). @@ -129,15 +129,15 @@ Attestation Verification. It will also discover devices with long discriminator 3840 and try to pair with the first one it discovers using the provided setup code. - ``` - $ chip-tool pairing onnetwork-long ${NODE_ID_TO_ASSIGN} 20202021 3840 --paa-trust-store-path path/to/PAAs - ``` +``` +chip-tool pairing onnetwork-long ${NODE_ID_TO_ASSIGN} 20202021 3840 --paa-trust-store-path path/to/PAAs +``` ### Forget the currently-commissioned device - ``` - $ chip-tool pairing unpair - ``` +``` +chip-tool pairing unpair +``` ## Using the Client to Send Matter Commands @@ -146,9 +146,9 @@ the target cluster name, the target command name as well as an endpoint id. The endpoint id must be between 1 and 240. - ``` - $ chip-tool onoff on 1 - ``` +``` +chip-tool onoff on 1 +``` The client will send a single command packet and then exit. @@ -158,27 +158,28 @@ The client will send a single command packet and then exit. 2. Add Group to device - ``` - $ chip-tool groups add-group GroupId GroupName node-id endpoint-id - $ chip-tool groups add-group 0x4141 Light 1234 1 - ``` +``` +chip-tool groups add-group GroupId GroupName node-id endpoint-id +chip-tool groups add-group 0x4141 Light 1234 1 +``` 3. Add group Keyset to device - ``` - $ chip-tool groupkeymanagement key-set-write GroupKeySet node-id endpoint-id - $ chip-tool groupkeymanagement key-set-write '{"groupKeySetID": 42, - "groupKeySecurityPolicy": 0, "epochKey0": - "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf", "epochStartTime0": 2220000,"epochKey1": - "d1d1d2d3d4d5d6d7d8d9dadbdcdddedf", "epochStartTime1": 2220001,"epochKey2": +``` +chip-tool groupkeymanagement key-set-write GroupKeySet node-id endpoint-id +chip-tool groupkeymanagement key-set-write '{"groupKeySetID": 42, \ + "groupKeySecurityPolicy": 0, "epochKey0": \ + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf", "epochStartTime0": 2220000,"epochKey1": \ + "d1d1d2d3d4d5d6d7d8d9dadbdcdddedf", "epochStartTime1": 2220001,"epochKey2": \ "d2d1d2d3d4d5d6d7d8d9dadbdcdddedf", "epochStartTime2": 2220002 }' 1234 0 - ``` +``` 4. Bind Key to group - ``` - $ chip-tool groupkeymanagement write group-key-map attr-value node-id endpoint-id - $ chip-tool groupkeymanagement write group-key-map '[{"groupId": 16705, "groupKeySetID": 42}]' 1234 0 - ``` + +``` +chip-tool groupkeymanagement write group-key-map attr-value node-id endpoint-id +chip-tool groupkeymanagement write group-key-map '[{"groupId": 16705, "groupKeySetID": 42}]' 1234 0 +``` ## Configuring the client for Group Commands @@ -187,35 +188,35 @@ must be configured appropriately. To configure the client please use the groupsettings option - ``` - $ chip-tool groupsettings - ``` +``` +chip-tool groupsettings +``` A group with a valid encryption key needs to be set. The groupid and the encryption key must match the one configured on the end device. To add a group - ``` - $ chip-tool groupsettings add-group groupName groupId - $ chip-tool groupsettings add-group TestName 0x4141 - ``` +``` +chip-tool groupsettings add-group groupName groupId +chip-tool groupsettings add-group TestName 0x4141 +``` To add a keyset - ``` - $ chip-tool groupsettings add-keysets keysetId keyPolicy validityTime EpochKey - $ chip-tool groupsettings add-keysets 0xAAAA 0 0x000000000021dfe0 hex:d0d1d2d3d4d5d6d7d8d9dadbdcdddedf - ``` +``` +chip-tool groupsettings add-keysets keysetId keyPolicy validityTime EpochKey +chip-tool groupsettings add-keysets 0xAAAA 0 0x000000000021dfe0 hex:d0d1d2d3d4d5d6d7d8d9dadbdcdddedf +``` Take note that the epoch key must be in hex form with the 'hex:' prefix Finally to bind the keyset to the group - ``` - $ chip-tool groupsettings bind-keyset groupId keysetId - $ chip-tool groupsettings bind-keyset 0x4141 0xAAAA - ``` +``` +chip-tool groupsettings bind-keyset groupId keysetId +chip-tool groupsettings bind-keyset 0x4141 0xAAAA +``` ## Using the Client to Send Group (Multicast) Matter Commands @@ -226,9 +227,9 @@ and attributes write can be send with Group Id. E.G. sending to group Id 0x4141 - ``` - $ chip-tool onoff on 0xffffffffffff4141 1 - ``` +``` +chip-tool onoff on 0xffffffffffff4141 1 +``` The client will send a single multicast command packet and then exit. @@ -237,9 +238,9 @@ The client will send a single multicast command packet and then exit. To get the list of supported clusters, run the built executable without any arguments. - ``` - $ chip-tool - ``` +``` +chip-tool +``` Example output: @@ -271,33 +272,33 @@ Usage: To get the list of commands for a specific cluster, run the built executable with the target cluster name. - ``` - $ chip-tool onoff - ``` +``` +chip-tool onoff +``` ### How to get the list of supported attributes for a specific cluster To the the list of attributes for a specific cluster, run the built executable with the target cluster name and the `read` command name. - ``` - $ chip-tool onoff read - ``` +``` +chip-tool onoff read +``` ### How to get the list of parameters for a command To get the list of parameters for a specific command, run the built executable with the target cluster name and the target command name - ``` - $ chip-tool onoff on - ``` +``` +chip-tool onoff on +``` ### Run a test suite against a paired peer device - ``` - $ chip-tool tests Test_TC_OO_1_1 - ``` +``` +chip-tool tests Test_TC_OO_1_1 +``` ## Using the Client for Setup Payload @@ -306,36 +307,36 @@ with the target cluster name and the target command name To parse a setup code, run the built executable with the `payload` cluster name and the `parse-setup-payload` command - ``` - $ chip-tool payload parse-setup-payload code - ``` +``` +chip-tool payload parse-setup-payload code +``` #### QR Code - ``` - $ chip-tool payload parse-setup-payload "MT:#####" - ``` +``` +chip-tool payload parse-setup-payload "MT:#####" +``` #### QR Code with optional Vendor Info - ``` - $ chip-tool payload parse-setup-payload "MT:#####" - ``` +``` +chip-tool payload parse-setup-payload "MT:#####" +``` #### Manual Setup Code - ``` - $ chip-tool payload parse-setup-payload "#####" - ``` +``` +chip-tool payload parse-setup-payload "#####" +``` # Using the Client for Additional Data Payload To parse an additional data payload, run the built executable with the `payload` cluster name and the `parse-additional-data-payload` command - ``` - $ chip-tool payload parse-additional-data-payload "#####" - ``` +``` +chip-tool payload parse-additional-data-payload "#####" +``` # Command Reference diff --git a/examples/chip-tool/chip-tool.gni b/examples/chip-tool/chip-tool.gni index 4e607dcdd7d6a0..b85f1f32340ed5 100644 --- a/examples/chip-tool/chip-tool.gni +++ b/examples/chip-tool/chip-tool.gni @@ -20,4 +20,5 @@ declare_args() { config_use_separate_eventloop = true config_use_interactive_mode = true config_enable_yaml_tests = true + config_use_local_storage = true } diff --git a/examples/chip-tool/commands/clusters/ComplexArgument.h b/examples/chip-tool/commands/clusters/ComplexArgument.h index 689b2e6f9a217e..4a033870e6c4b3 100644 --- a/examples/chip-tool/commands/clusters/ComplexArgument.h +++ b/examples/chip-tool/commands/clusters/ComplexArgument.h @@ -26,6 +26,8 @@ #include #include +#include "JsonParser.h" + constexpr uint8_t kMaxLabelLength = 100; class ComplexArgumentParser @@ -308,63 +310,23 @@ template class TypedComplexArgument : public ComplexArgument { public: + TypedComplexArgument() {} TypedComplexArgument(T * request) : mRequest(request) {} - ~TypedComplexArgument() { ComplexArgumentParser::Finalize(*mRequest); } + ~TypedComplexArgument() + { + if (mRequest != nullptr) + { + ComplexArgumentParser::Finalize(*mRequest); + } + } + + void SetArgument(T * request) { mRequest = request; }; CHIP_ERROR Parse(const char * label, const char * json) { Json::Value value; - Json::Reader reader; - if (!reader.parse(json, value)) + if (!JsonParser::ParseComplexArgument(label, json, value)) { - std::vector errors = reader.getStructuredErrors(); - ChipLogError(chipTool, "Error parsing JSON for %s:", label); - for (auto & error : errors) - { - ChipLogError(chipTool, " %s", error.message.c_str()); - ptrdiff_t error_start = error.offset_start; - ptrdiff_t error_end = error.offset_limit; - const char * sourceText = json; - // The whole JSON string might be too long to fit in our log - // messages. Just include 30 chars before the error. - constexpr ptrdiff_t kMaxContext = 30; - std::string errorMsg; - if (error_start > kMaxContext) - { - sourceText += (error_start - kMaxContext); - error_end = kMaxContext + (error_end - error_start); - error_start = kMaxContext; - ChipLogError(chipTool, "... %s", sourceText); - // Add markers corresponding to the "... " above. - errorMsg += "----"; - } - else - { - ChipLogError(chipTool, "%s", sourceText); - } - for (ptrdiff_t i = 0; i < error_start; ++i) - { - errorMsg += "-"; - } - errorMsg += "^"; - if (error_start + 1 < error_end) - { - for (ptrdiff_t i = error_start + 1; i < error_end; ++i) - { - errorMsg += "-"; - } - errorMsg += "^"; - } - ChipLogError(chipTool, "%s", errorMsg.c_str()); - - if (error.message == "Missing ',' or '}' in object declaration" && error.offset_start > 0 && - json[error.offset_start - 1] == '0' && (json[error.offset_start] == 'x' || json[error.offset_start] == 'X')) - { - ChipLogError(chipTool, - "NOTE: JSON does not allow hex syntax beginning with 0x for numbers. Try putting the hex number " - "in quotes (like {\"name\": \"0x100\"})."); - } - } return CHIP_ERROR_INVALID_ARGUMENT; } diff --git a/examples/chip-tool/commands/clusters/CustomArgument.h b/examples/chip-tool/commands/clusters/CustomArgument.h index 2362171aa06da9..6755703fa0b7d5 100644 --- a/examples/chip-tool/commands/clusters/CustomArgument.h +++ b/examples/chip-tool/commands/clusters/CustomArgument.h @@ -22,6 +22,8 @@ #include #include +#include "JsonParser.h" + namespace { static constexpr char kPayloadHexPrefix[] = "hex:"; static constexpr char kPayloadSignedPrefix[] = "s:"; @@ -230,9 +232,30 @@ class CustomArgument CHIP_ERROR Parse(const char * label, const char * json) { - Json::Reader reader; Json::Value value; - reader.parse(json, value); + constexpr const char kHexNumPrefix[] = "0x"; + constexpr size_t kHexNumPrefixLen = ArraySize(kHexNumPrefix) - 1; + if (strncmp(json, kPayloadHexPrefix, kPayloadHexPrefixLen) == 0 || + strncmp(json, kPayloadSignedPrefix, kPayloadSignedPrefixLen) == 0 || + strncmp(json, kPayloadUnsignedPrefix, kPayloadUnsignedPrefixLen) == 0 || + strncmp(json, kPayloadFloatPrefix, kPayloadFloatPrefixLen) == 0 || + strncmp(json, kPayloadDoublePrefix, kPayloadDoublePrefixLen) == 0) + { + value = Json::Value(json); + } + else if (strncmp(json, kHexNumPrefix, kHexNumPrefixLen) == 0) + { + // Assume that hex numbers are unsigned. Prepend + // kPayloadUnsignedPrefix and then let the rest of the logic handle + // things. + std::string str(kPayloadUnsignedPrefix); + str += json; + value = Json::Value(str); + } + else if (!JsonParser::ParseCustomArgument(label, json, value)) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } mData = static_cast(chip::Platform::MemoryCalloc(sizeof(uint8_t), mDataMaxLen)); VerifyOrReturnError(mData != nullptr, CHIP_ERROR_NO_MEMORY); diff --git a/examples/chip-tool/commands/clusters/JsonParser.h b/examples/chip-tool/commands/clusters/JsonParser.h new file mode 100644 index 00000000000000..2b74aee6fffb7c --- /dev/null +++ b/examples/chip-tool/commands/clusters/JsonParser.h @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#pragma once + +#include +#include + +#include +#include +#include +#include + +class JsonParser +{ +public: + // Returns whether the parse succeeded. + static bool ParseComplexArgument(const char * label, const char * json, Json::Value & value) + { + return Parse(label, json, /* strictRoot = */ true, value); + } + + // Returns whether the parse succeeded. + static bool ParseCustomArgument(const char * label, const char * json, Json::Value & value) + { + return Parse(label, json, /* strictRoot = */ false, value); + } + +private: + static bool Parse(const char * label, const char * json, bool strictRoot, Json::Value & value) + { + Json::CharReaderBuilder readerBuilder; + readerBuilder.settings_["strictRoot"] = strictRoot; + readerBuilder.settings_["allowSingleQuotes"] = true; + readerBuilder.settings_["failIfExtra"] = true; + readerBuilder.settings_["rejectDupKeys"] = true; + + auto reader = std::unique_ptr(readerBuilder.newCharReader()); + std::string errors; + if (reader->parse(json, json + strlen(json), &value, &errors)) + { + return true; + } + + // The CharReader API allows us to set failIfExtra, unlike Reader, but does + // not allow us to get structured errors. We get to try to manually undo + // the work it did to create a string from the structured errors it had. + ChipLogError(chipTool, "Error parsing JSON for %s:", label); + + // For each error "errors" has the following: + // + // 1) A line starting with "* " that has line/column info + // 2) A line with the error message. + // 3) An optional line with some extra info. + // + // We keep track of the last error column, in case the error message + // reporting needs it. + std::istringstream stream(errors); + std::string error; + chip::Optional errorColumn; + while (getline(stream, error)) + { + if (error.rfind("* ", 0) == 0) + { + // Flush out any pending error location. + LogErrorLocation(errorColumn, json); + + // The format of this line is: + // + // * Line N, Column M + // + // Unfortunately it does not indicate end of error, so we can only + // show its start. + unsigned errorLine; // ignored in practice + if (sscanf(error.c_str(), "* Line %u, Column %u", &errorLine, &errorColumn.Emplace()) != 2) + { + ChipLogError(chipTool, "Unexpected location string: %s\n", error.c_str()); + // We don't know how to make sense of this thing anymore. + break; + } + if (errorColumn.Value() == 0) + { + ChipLogError(chipTool, "Expected error column to be at least 1"); + // We don't know how to make sense of this thing anymore. + break; + } + // We are using our column numbers as offsets, so want them to be + // 0-based. + --errorColumn.Value(); + } + else + { + ChipLogError(chipTool, " %s", error.c_str()); + if (error == " Missing ',' or '}' in object declaration" && errorColumn.HasValue() && errorColumn.Value() > 0 && + json[errorColumn.Value() - 1] == '0' && (json[errorColumn.Value()] == 'x' || json[errorColumn.Value()] == 'X')) + { + // Log the error location marker before showing the NOTE + // message. + LogErrorLocation(errorColumn, json); + ChipLogError(chipTool, + "NOTE: JSON does not allow hex syntax beginning with 0x for numbers. Try putting the hex number " + "in quotes (like {\"name\": \"0x100\"})."); + } + } + } + + // Write out the marker for our last error. + LogErrorLocation(errorColumn, json); + + return false; + } + +private: + static void LogErrorLocation(chip::Optional & errorColumn, const char * json) + { + if (!errorColumn.HasValue()) + { + return; + } + + const char * sourceText = json; + unsigned error_start = errorColumn.Value(); + // The whole JSON string might be too long to fit in our log + // messages. Just include 30 chars before the error. + constexpr ptrdiff_t kMaxContext = 30; + std::string errorMarker; + if (error_start > kMaxContext) + { + sourceText += (error_start - kMaxContext); + error_start = kMaxContext; + ChipLogError(chipTool, "... %s", sourceText); + // Add markers corresponding to the "... " above. + errorMarker += "----"; + } + else + { + ChipLogError(chipTool, "%s", sourceText); + } + for (unsigned i = 0; i < error_start; ++i) + { + errorMarker += "-"; + } + errorMarker += "^"; + ChipLogError(chipTool, "%s", errorMarker.c_str()); + errorColumn.ClearValue(); + } +}; diff --git a/examples/chip-tool/commands/clusters/ModelCommand.h b/examples/chip-tool/commands/clusters/ModelCommand.h index b6fa961bff756d..4a0c2c08f5d469 100644 --- a/examples/chip-tool/commands/clusters/ModelCommand.h +++ b/examples/chip-tool/commands/clusters/ModelCommand.h @@ -18,7 +18,10 @@ #pragma once +#ifdef CONFIG_USE_LOCAL_STORAGE #include "../../config/PersistentStorage.h" +#endif // CONFIG_USE_LOCAL_STORAGE + #include "../common/CHIPCommand.h" #include diff --git a/examples/chip-tool/commands/clusters/SubscriptionsCommands.h b/examples/chip-tool/commands/clusters/SubscriptionsCommands.h index effc9f4edca2b6..207127a39b1031 100644 --- a/examples/chip-tool/commands/clusters/SubscriptionsCommands.h +++ b/examples/chip-tool/commands/clusters/SubscriptionsCommands.h @@ -18,6 +18,11 @@ #pragma once +#include + +#include +#include + class ShutdownSubscription : public CHIPCommand { public: diff --git a/examples/chip-tool/commands/clusters/WriteAttributeCommand.h b/examples/chip-tool/commands/clusters/WriteAttributeCommand.h index 93ca6d167fc41b..57cad5cbf7f0cc 100644 --- a/examples/chip-tool/commands/clusters/WriteAttributeCommand.h +++ b/examples/chip-tool/commands/clusters/WriteAttributeCommand.h @@ -23,23 +23,70 @@ #include "DataModelLogger.h" #include "ModelCommand.h" +template > class WriteAttribute : public InteractionModelWriter, public ModelCommand, public chip::app::WriteClient::Callback { public: WriteAttribute(CredentialIssuerCommands * credsIssuerConfig) : InteractionModelWriter(this), ModelCommand("write-by-id", credsIssuerConfig) { - AddArgument("cluster-id", 0, UINT32_MAX, &mClusterId); - AddArgument("attribute-id", 0, UINT32_MAX, &mAttributeId); - AddArgument("attribute-value", &mAttributeValue); + AddArgumentClusterIds(); + AddArgumentAttributeIds(); + AddArgumentAttributeValues(); AddArguments(); } WriteAttribute(chip::ClusterId clusterId, CredentialIssuerCommands * credsIssuerConfig) : - InteractionModelWriter(this), ModelCommand("write-by-id", credsIssuerConfig), mClusterId(clusterId) + InteractionModelWriter(this), ModelCommand("write-by-id", credsIssuerConfig), mClusterIds(1, clusterId) { - AddArgument("attribute-id", 0, UINT32_MAX, &mAttributeId); - AddArgument("attribute-value", &mAttributeValue); + AddArgumentAttributeIds(); + AddArgumentAttributeValues(); + AddArguments(); + } + + template + WriteAttribute(chip::ClusterId clusterId, const char * attributeName, minType minValue, maxType maxValue, + chip::AttributeId attributeId, CredentialIssuerCommands * credsIssuerConfig) : + WriteAttribute(clusterId, attributeId, credsIssuerConfig) + { + AddArgumentAttributeName(attributeName); + AddArgumentAttributeValues(static_cast(minValue), static_cast(maxValue)); + AddArguments(); + } + + WriteAttribute(chip::ClusterId clusterId, const char * attributeName, float minValue, float maxValue, + chip::AttributeId attributeId, CredentialIssuerCommands * credsIssuerConfig) : + WriteAttribute(clusterId, attributeId, credsIssuerConfig) + { + AddArgumentAttributeName(attributeName); + AddArgumentAttributeValues(minValue, maxValue); + AddArguments(); + } + + WriteAttribute(chip::ClusterId clusterId, const char * attributeName, double minValue, double maxValue, + chip::AttributeId attributeId, CredentialIssuerCommands * credsIssuerConfig) : + WriteAttribute(clusterId, attributeId, credsIssuerConfig) + { + AddArgumentAttributeName(attributeName); + AddArgumentAttributeValues(minValue, maxValue); + AddArguments(); + } + + WriteAttribute(chip::ClusterId clusterId, const char * attributeName, chip::AttributeId attributeId, + CredentialIssuerCommands * credsIssuerConfig) : + WriteAttribute(clusterId, attributeId, credsIssuerConfig) + { + AddArgumentAttributeName(attributeName); + AddArgumentAttributeValues(); + AddArguments(); + } + + WriteAttribute(chip::ClusterId clusterId, const char * attributeName, chip::AttributeId attributeId, + TypedComplexArgument & attributeParser, CredentialIssuerCommands * credsIssuerConfig) : + WriteAttribute(clusterId, attributeId, credsIssuerConfig) + { + AddArgumentAttributeName(attributeName); + AddArgumentAttributeValues(attributeParser); AddArguments(); } @@ -47,12 +94,12 @@ class WriteAttribute : public InteractionModelWriter, public ModelCommand, publi CHIP_ERROR SendCommand(chip::DeviceProxy * device, std::vector endpointIds) override { - return WriteAttribute::SendCommand(device, endpointIds.at(0), mClusterId, mAttributeId, mAttributeValue); + return WriteAttribute::SendCommand(device, endpointIds, mClusterIds, mAttributeIds, mAttributeValues); } CHIP_ERROR SendGroupCommand(chip::GroupId groupId, chip::FabricIndex fabricIndex) override { - return WriteAttribute::SendGroupCommand(groupId, fabricIndex, mClusterId, mAttributeId, mAttributeValue); + return WriteAttribute::SendGroupCommand(groupId, fabricIndex, mClusterIds, mAttributeIds, mAttributeValues); } /////////// WriteClient Callback Interface ///////// @@ -79,23 +126,27 @@ class WriteAttribute : public InteractionModelWriter, public ModelCommand, publi SetCommandExitStatus(mError); } - template - CHIP_ERROR SendCommand(chip::DeviceProxy * device, chip::EndpointId endpointId, chip::ClusterId clusterId, - chip::AttributeId attributeId, const T & value) + CHIP_ERROR SendCommand(chip::DeviceProxy * device, std::vector endpointIds, + std::vector clusterIds, std::vector attributeIds, const T & values) { - ChipLogProgress(chipTool, "Sending WriteAttribute to cluster " ChipLogFormatMEI " on endpoint %u", - ChipLogValueMEI(clusterId), endpointId); - return InteractionModelWriter::WriteAttribute(device, endpointId, clusterId, attributeId, value, mTimedInteractionTimeoutMs, - mSuppressResponse, mDataVersion, mRepeatCount, mRepeatDelayInMs); + return InteractionModelWriter::WriteAttribute(device, endpointIds, clusterIds, attributeIds, values, + mTimedInteractionTimeoutMs, mSuppressResponse, mDataVersions, mRepeatCount, + mRepeatDelayInMs); } - template - CHIP_ERROR SendGroupCommand(chip::GroupId groupId, chip::FabricIndex fabricIndex, chip::ClusterId clusterId, - chip::AttributeId attributeId, const T & value) + CHIP_ERROR SendGroupCommand(chip::GroupId groupId, chip::FabricIndex fabricIndex, std::vector clusterIds, + std::vector attributeIds, const T & value) { ChipLogDetail(chipTool, "Sending Write Attribute to Group %u, on Fabric %x, for cluster %u with attributeId %u", groupId, - fabricIndex, clusterId, attributeId); - return InteractionModelWriter::WriteGroupAttribute(groupId, fabricIndex, clusterId, attributeId, value, mDataVersion); + fabricIndex, clusterIds.at(0), attributeIds.at(0)); + chip::Optional dataVersion = chip::NullOptional; + if (mDataVersions.HasValue()) + { + dataVersion.SetValue(mDataVersions.Value().at(0)); + } + + return InteractionModelWriter::WriteGroupAttribute(groupId, fabricIndex, clusterIds.at(0), attributeIds.at(0), value, + dataVersion); } protected: @@ -105,11 +156,47 @@ class WriteAttribute : public InteractionModelWriter, public ModelCommand, publi // Subclasses are responsible for calling AddArguments. } + void AddArgumentClusterIds() + { + AddArgument("cluster-ids", 0, UINT32_MAX, &mClusterIds, + "Comma-separated list of cluster ids to write to (e.g. \"6\" or \"6,0x201\")."); + } + + void AddArgumentAttributeIds() + { + AddArgument("attribute-ids", 0, UINT32_MAX, &mAttributeIds, + "Comma-separated list of attribute ids to write (e.g. \"16385\" or \"16385,0x4002\")."); + } + + void AddArgumentAttributeName(const char * attributeName) + { + AddArgument("attribute-name", attributeName, "The attribute name to write."); + } + + template + void AddArgumentAttributeValues(minType minValue, maxType maxValue) + { + AddArgument("attribute-values", minValue, maxValue, &mAttributeValues, + "Comma-separated list of attribute values to write."); + } + + void AddArgumentAttributeValues() + { + AddArgument("attribute-values", &mAttributeValues, "Comma-separated list of attribute values to write."); + } + + void AddArgumentAttributeValues(TypedComplexArgument & attributeParser) + { + attributeParser.SetArgument(&mAttributeValues); + AddArgument("attribute-values", &attributeParser, "Comma-separated list of attribute values to write."); + } + void AddArguments() { AddArgument("timedInteractionTimeoutMs", 0, UINT16_MAX, &mTimedInteractionTimeoutMs, "If provided, do a timed write with the given timed interaction timeout."); - AddArgument("data-version", 0, UINT32_MAX, &mDataVersion); + AddArgument("data-version", 0, UINT32_MAX, &mDataVersions, + "Comma-separated list of data versions for the clusters being written."); AddArgument("suppressResponse", 0, 1, &mSuppressResponse); AddArgument("repeat-count", 1, UINT16_MAX, &mRepeatCount); AddArgument("repeat-delay-ms", 0, UINT16_MAX, &mRepeatDelayInMs); @@ -117,13 +204,34 @@ class WriteAttribute : public InteractionModelWriter, public ModelCommand, publi } private: - chip::ClusterId mClusterId; - chip::AttributeId mAttributeId; + // This constructor is private as it is not intended to be used from outside the class. + WriteAttribute(chip::ClusterId clusterId, chip::AttributeId attributeId, CredentialIssuerCommands * credsIssuerConfig) : + InteractionModelWriter(this), ModelCommand("write", credsIssuerConfig), mClusterIds(1, clusterId), + mAttributeIds(1, attributeId) + {} + + std::vector mClusterIds; + std::vector mAttributeIds; + CHIP_ERROR mError = CHIP_NO_ERROR; chip::Optional mTimedInteractionTimeoutMs; - chip::Optional mDataVersion = chip::NullOptional; + chip::Optional> mDataVersions; chip::Optional mSuppressResponse; - CustomArgument mAttributeValue; chip::Optional mRepeatCount; chip::Optional mRepeatDelayInMs; + + T mAttributeValues; +}; + +template +class WriteAttributeAsComplex : public WriteAttribute +{ +public: + WriteAttributeAsComplex(chip::ClusterId clusterId, const char * attributeName, chip::AttributeId attributeId, + CredentialIssuerCommands * credsIssuerConfig) : + WriteAttribute(clusterId, attributeName, attributeId, mAttributeParser, credsIssuerConfig) + {} + +private: + TypedComplexArgument mAttributeParser; }; diff --git a/examples/chip-tool/commands/common/CHIPCommand.cpp b/examples/chip-tool/commands/common/CHIPCommand.cpp index 02194ed59b4096..4e10e67e74b2e8 100644 --- a/examples/chip-tool/commands/common/CHIPCommand.cpp +++ b/examples/chip-tool/commands/common/CHIPCommand.cpp @@ -71,10 +71,12 @@ CHIP_ERROR CHIPCommand::MaybeSetUpStack() #endif ReturnLogErrorOnFailure(mDefaultStorage.Init()); + ReturnLogErrorOnFailure(mOperationalKeystore.Init(&mDefaultStorage)); chip::Controller::FactoryInitParams factoryInitParams; factoryInitParams.fabricIndependentStorage = &mDefaultStorage; + factoryInitParams.operationalKeystore = &mOperationalKeystore; // 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/chip-tool/commands/common/CHIPCommand.h b/examples/chip-tool/commands/common/CHIPCommand.h index 3fbe81781a15f8..e484260a3a4fb1 100644 --- a/examples/chip-tool/commands/common/CHIPCommand.h +++ b/examples/chip-tool/commands/common/CHIPCommand.h @@ -18,16 +18,19 @@ #pragma once +#ifdef CONFIG_USE_LOCAL_STORAGE #include "../../config/PersistentStorage.h" +#endif // CONFIG_USE_LOCAL_STORAGE + #include "Command.h" + #include #include #include +#include #pragma once -class PersistentStorage; - constexpr const char kIdentityAlpha[] = "alpha"; constexpr const char kIdentityBeta[] = "beta"; constexpr const char kIdentityGamma[] = "gamma"; @@ -113,8 +116,12 @@ class CHIPCommand : public Command // Execute any deferred cleanups. Used when exiting interactive mode. void ExecuteDeferredCleanups(); +#ifdef CONFIG_USE_LOCAL_STORAGE PersistentStorage mDefaultStorage; PersistentStorage mCommissionerStorage; +#endif // CONFIG_USE_LOCAL_STORAGE + chip::PersistentStorageOperationalKeystore mOperationalKeystore; + chip::Credentials::GroupDataProviderImpl mGroupDataProvider{ kMaxGroupsPerFabric, kMaxGroupKeysPerFabric }; CredentialIssuerCommands * mCredIssuerCmds; diff --git a/examples/chip-tool/commands/common/Command.cpp b/examples/chip-tool/commands/common/Command.cpp index f5828f2b138326..1931d88e39752f 100644 --- a/examples/chip-tool/commands/common/Command.cpp +++ b/examples/chip-tool/commands/common/Command.cpp @@ -305,6 +305,23 @@ bool Command::InitArgument(size_t argIndex, char * argValue) return true; } + case ArgumentType::VectorCustom: { + auto vectorArgument = static_cast *>(arg.value); + + std::stringstream ss(argValue); + while (ss.good()) + { + std::string valueAsString; + getline(ss, valueAsString, ','); + + CustomArgument * customArgument = new CustomArgument(); + vectorArgument->push_back(customArgument); + VerifyOrReturnError(CHIP_NO_ERROR == vectorArgument->back()->Parse(arg.name, valueAsString.c_str()), false); + } + + return true; + } + case ArgumentType::Attribute: { if (arg.isOptional() || arg.isNullable()) { @@ -695,6 +712,18 @@ size_t Command::AddArgument(const char * name, CustomArgument * value, const cha return AddArgumentToList(std::move(arg)); } +size_t Command::AddArgument(const char * name, std::vector * value, const char * desc) +{ + Argument arg; + arg.type = ArgumentType::VectorCustom; + arg.name = name; + arg.value = static_cast(value); + arg.flags = 0; + arg.desc = desc; + + return AddArgumentToList(std::move(arg)); +} + size_t Command::AddArgument(const char * name, float min, float max, float * out, const char * desc, uint8_t flags) { Argument arg; @@ -855,5 +884,14 @@ void Command::ResetArguments() optionalArgument->Value().clear(); } } + else if (type == ArgumentType::VectorCustom && flags != Argument::kOptional) + { + auto vectorArgument = static_cast *>(arg.value); + for (auto & customArgument : *vectorArgument) + { + delete customArgument; + } + vectorArgument->clear(); + } } } diff --git a/examples/chip-tool/commands/common/Command.h b/examples/chip-tool/commands/common/Command.h index b9a1c2bc1cb972..2a7411cf506854 100644 --- a/examples/chip-tool/commands/common/Command.h +++ b/examples/chip-tool/commands/common/Command.h @@ -73,6 +73,7 @@ enum ArgumentType VectorBool, Vector16, Vector32, + VectorCustom, }; struct Argument @@ -179,6 +180,7 @@ class Command size_t AddArgument(const char * name, int64_t min, uint64_t max, std::vector * value, const char * desc = ""); size_t AddArgument(const char * name, int64_t min, uint64_t max, std::vector * value, const char * desc = ""); + size_t AddArgument(const char * name, std::vector * value, const char * desc = ""); size_t AddArgument(const char * name, int64_t min, uint64_t max, chip::Optional> * value, const char * desc = ""); size_t AddArgument(const char * name, int64_t min, uint64_t max, chip::Optional> * value, diff --git a/examples/chip-tool/commands/common/Commands.cpp b/examples/chip-tool/commands/common/Commands.cpp index 131e66f1c8aa3e..16e188c1dee2ca 100644 --- a/examples/chip-tool/commands/common/Commands.cpp +++ b/examples/chip-tool/commands/common/Commands.cpp @@ -41,10 +41,12 @@ int Commands::Run(int argc, char ** argv) err = chip::Platform::MemoryInit(); VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "Init Memory failure: %s", chip::ErrorStr(err))); +#ifdef CONFIG_USE_LOCAL_STORAGE err = mStorage.Init(); VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "Init Storage failure: %s", chip::ErrorStr(err))); chip::Logging::SetLogFilter(mStorage.GetLoggingLevel()); +#endif // CONFIG_USE_LOCAL_STORAGE err = RunCommand(argc, argv); VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(chipTool, "Run command failure: %s", chip::ErrorStr(err))); @@ -56,7 +58,12 @@ int Commands::Run(int argc, char ** argv) int Commands::RunInteractive(int argc, char ** argv) { CHIP_ERROR err = RunCommand(argc, argv, true); - return (err == CHIP_NO_ERROR) ? EXIT_SUCCESS : EXIT_FAILURE; + if (err == CHIP_NO_ERROR) + { + return EXIT_SUCCESS; + } + ChipLogError(chipTool, "Run command failure: %s", chip::ErrorStr(err)); + return EXIT_FAILURE; } CHIP_ERROR Commands::RunCommand(int argc, char ** argv, bool interactive) diff --git a/examples/chip-tool/commands/common/Commands.h b/examples/chip-tool/commands/common/Commands.h index e70a942779c9e1..a39c984954777e 100644 --- a/examples/chip-tool/commands/common/Commands.h +++ b/examples/chip-tool/commands/common/Commands.h @@ -18,7 +18,10 @@ #pragma once +#ifdef CONFIG_USE_LOCAL_STORAGE #include "../../config/PersistentStorage.h" +#endif // CONFIG_USE_LOCAL_STORAGE + #include "Command.h" #include @@ -48,5 +51,7 @@ class Commands void ShowCommand(std::string executable, std::string clusterName, Command * command); std::map mClusters; +#ifdef CONFIG_USE_LOCAL_STORAGE PersistentStorage mStorage; +#endif // CONFIG_USE_LOCAL_STORAGE }; diff --git a/examples/chip-tool/commands/pairing/CloseSessionCommand.cpp b/examples/chip-tool/commands/pairing/CloseSessionCommand.cpp new file mode 100644 index 00000000000000..b30d0accae1639 --- /dev/null +++ b/examples/chip-tool/commands/pairing/CloseSessionCommand.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "CloseSessionCommand.h" +#include +#include + +using namespace chip; +using namespace chip::Protocols; + +CHIP_ERROR CloseSessionCommand::RunCommand() +{ + CommissioneeDeviceProxy * commissioneeDeviceProxy = nullptr; + if (CHIP_NO_ERROR == CurrentCommissioner().GetDeviceBeingCommissioned(mDestinationId, &commissioneeDeviceProxy)) + { + return CloseSession(commissioneeDeviceProxy); + } + + return CurrentCommissioner().GetConnectedDevice(mDestinationId, &mOnDeviceConnectedCallback, + &mOnDeviceConnectionFailureCallback); +} + +CHIP_ERROR CloseSessionCommand::CloseSession(DeviceProxy * device) +{ + VerifyOrReturnError(device->GetSecureSession().HasValue(), CHIP_ERROR_INCORRECT_STATE); + + // TODO perhaps factor out this code into something on StatusReport that + // takes an exchange and maybe a SendMessageFlags? + SecureChannel::StatusReport statusReport(SecureChannel::GeneralStatusCode::kSuccess, SecureChannel::Id, + SecureChannel::kProtocolCodeCloseSession); + + size_t reportSize = statusReport.Size(); + Encoding::LittleEndian::PacketBufferWriter bbuf(MessagePacketBuffer::New(reportSize), reportSize); + statusReport.WriteToBuffer(bbuf); + + System::PacketBufferHandle msg = bbuf.Finalize(); + VerifyOrReturnError(!msg.IsNull(), CHIP_ERROR_NO_MEMORY); + + auto * exchange = device->GetExchangeManager()->NewContext(device->GetSecureSession().Value(), nullptr); + VerifyOrReturnError(exchange != nullptr, CHIP_ERROR_NO_MEMORY); + + // Per spec, CloseSession reports are always sent with MRP disabled. + CHIP_ERROR err = + exchange->SendMessage(SecureChannel::MsgType::StatusReport, std::move(msg), Messaging::SendMessageFlags::kNoAutoRequestAck); + if (err == CHIP_NO_ERROR) + { + SetCommandExitStatus(CHIP_NO_ERROR); + } + else + { + exchange->Close(); + } + + return err; +} + +void CloseSessionCommand::OnDeviceConnectedFn(void * context, OperationalDeviceProxy * device) +{ + auto * command = reinterpret_cast(context); + VerifyOrReturn(command != nullptr, ChipLogError(chipTool, "OnDeviceConnectedFn: context is null")); + + CHIP_ERROR err = command->CloseSession(device); + VerifyOrReturn(CHIP_NO_ERROR == err, command->SetCommandExitStatus(err)); +} + +void CloseSessionCommand::OnDeviceConnectionFailureFn(void * context, PeerId peerId, CHIP_ERROR err) +{ + LogErrorOnFailure(err); + + auto * command = reinterpret_cast(context); + VerifyOrReturn(command != nullptr, ChipLogError(chipTool, "OnDeviceConnectionFailureFn: context is null")); + command->SetCommandExitStatus(err); +} diff --git a/examples/tv-casting-app/tv-casting-common/commands/clusters/ModelCommand.h b/examples/chip-tool/commands/pairing/CloseSessionCommand.h similarity index 55% rename from examples/tv-casting-app/tv-casting-common/commands/clusters/ModelCommand.h rename to examples/chip-tool/commands/pairing/CloseSessionCommand.h index daab38b420bbdf..782e334ebfe74a 100644 --- a/examples/tv-casting-app/tv-casting-common/commands/clusters/ModelCommand.h +++ b/examples/chip-tool/commands/pairing/CloseSessionCommand.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2022 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,43 +19,39 @@ #pragma once #include "../common/CHIPCommand.h" -#include +#include +#include +#include -class ModelCommand : public CHIPCommand +class CloseSessionCommand : public CHIPCommand { public: - ModelCommand(const char * commandName, CredentialIssuerCommands * credsIssuerConfig) : - CHIPCommand(commandName, credsIssuerConfig), mOnDeviceConnectedCallback(OnDeviceConnectedFn, this), + CloseSessionCommand(CredentialIssuerCommands * credIssuerCommands) : + CHIPCommand("close-session", credIssuerCommands), mOnDeviceConnectedCallback(OnDeviceConnectedFn, this), mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureFn, this) - {} - - void AddArguments() { - AddArgument("node-id/group-id", 0, UINT64_MAX, &mNodeId); - AddArgument("endpoint-id-ignored-for-group-commands", 0, UINT16_MAX, &mEndPointId); - AddArgument("timeout", 0, UINT16_MAX, &mTimeout); + AddArgument("destination-id", 0, UINT64_MAX, &mDestinationId); + AddArgument("timeout", 0, UINT64_MAX, &mTimeoutSecs, + "Time, in seconds, before this command is considered to have timed out."); } /////////// CHIPCommand Interface ///////// CHIP_ERROR RunCommand() override; - chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(mTimeout.ValueOr(10)); } - - virtual CHIP_ERROR SendCommand(chip::DeviceProxy * device, std::vector endPointIds) = 0; - - virtual CHIP_ERROR SendGroupCommand(chip::GroupId groupId, chip::FabricIndex fabricIndex) { return CHIP_ERROR_BAD_REQUEST; }; - - void Shutdown() override; - -protected: - chip::Optional mTimeout; + chip::System::Clock::Timeout GetWaitDuration() const override + { + return chip::System::Clock::Seconds16(mTimeoutSecs.ValueOr(10)); + } private: - chip::NodeId mNodeId; - std::vector mEndPointId; + chip::NodeId mDestinationId; + chip::Optional mTimeoutSecs; static void OnDeviceConnectedFn(void * context, chip::OperationalDeviceProxy * device); static void OnDeviceConnectionFailureFn(void * context, PeerId peerId, CHIP_ERROR error); + // Try to send the action CloseSession status report. + CHIP_ERROR CloseSession(chip::DeviceProxy * device); + chip::Callback::Callback mOnDeviceConnectedCallback; chip::Callback::Callback mOnDeviceConnectionFailureCallback; }; diff --git a/examples/chip-tool/commands/pairing/Commands.h b/examples/chip-tool/commands/pairing/Commands.h index ef06ca2f4dd654..80506e6df0e9e0 100644 --- a/examples/chip-tool/commands/pairing/Commands.h +++ b/examples/chip-tool/commands/pairing/Commands.h @@ -18,6 +18,7 @@ #pragma once +#include "CloseSessionCommand.h" #include "CommissionedListCommand.h" #include "OpenCommissioningWindowCommand.h" #include "PairingCommand.h" @@ -218,6 +219,7 @@ void registerCommandsPairing(Commands & commands, CredentialIssuerCommands * cre // make_unique(), make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), + make_unique(credsIssuerConfig), }; commands.Register(clusterName, clusterCommands); diff --git a/examples/chip-tool/commands/pairing/PairingCommand.cpp b/examples/chip-tool/commands/pairing/PairingCommand.cpp index 1e092c51dcabd7..557f25ad431216 100644 --- a/examples/chip-tool/commands/pairing/PairingCommand.cpp +++ b/examples/chip-tool/commands/pairing/PairingCommand.cpp @@ -144,6 +144,7 @@ void PairingCommand::OnStatusUpdate(DevicePairingDelegate::Status status) { case DevicePairingDelegate::Status::SecurePairingSuccess: ChipLogProgress(chipTool, "Secure Pairing Success"); + ChipLogProgress(chipTool, "CASE establishment successful"); break; case DevicePairingDelegate::Status::SecurePairingFailed: ChipLogError(chipTool, "Secure Pairing Failed"); @@ -157,6 +158,7 @@ void PairingCommand::OnPairingComplete(CHIP_ERROR err) if (err == CHIP_NO_ERROR) { ChipLogProgress(chipTool, "Pairing Success"); + ChipLogProgress(chipTool, "PASE establishment successful"); if (mPairingMode == PairingMode::CodePaseOnly) { SetCommandExitStatus(err); diff --git a/examples/chip-tool/templates/commands.zapt b/examples/chip-tool/templates/commands.zapt index 55939cdbf4411c..25c8a54859f471 100644 --- a/examples/chip-tool/templates/commands.zapt +++ b/examples/chip-tool/templates/commands.zapt @@ -64,45 +64,6 @@ private: {{/zcl_commands_source_client}} -{{#zcl_attributes_server}} -{{#if isWritable}} -class Write{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}: public WriteAttribute -{ -public: - Write{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}(CredentialIssuerCommands * credsIssuerConfig): WriteAttribute("{{asUpperCamelCase name}}", credsIssuerConfig){{#if_chip_complex}}, mComplex(&mValue){{/if_chip_complex}} - { - AddArgument("attr-name", "{{asDelimitedCommand (asUpperCamelCase name)}}"); - {{#if_chip_complex}} - AddArgument("attr-value", &mComplex); - {{else if (isString type)}} - AddArgument("attr-value", &mValue); - {{else}} - AddArgument("attr-value", {{asTypeMinValue type}}, {{asTypeMaxValue type}}, &mValue); - {{/if_chip_complex}} - WriteAttribute::AddArguments(); - } - - ~Write{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}() {} - - CHIP_ERROR SendCommand(chip::DeviceProxy * device, std::vector endpointIds) override - { - return WriteAttribute::SendCommand(device, endpointIds.at(0), {{asHex parent.code 8}}, {{asHex code 8}}, mValue); - } - - CHIP_ERROR SendGroupCommand(chip::GroupId groupId, chip::FabricIndex fabricIndex) override - { - return WriteAttribute::SendGroupCommand(groupId, fabricIndex, {{asHex parent.code 8}}, {{asHex code 8}}, mValue); - } - -private: - {{zapTypeToEncodableClusterObjectType type ns=parent.name forceNotOptional=true}} mValue; -{{#if_chip_complex}} - TypedComplexArgument<{{zapTypeToEncodableClusterObjectType type ns=parent.name forceNotOptional=true}}> mComplex; -{{/if_chip_complex}} -}; - -{{/if}} -{{/zcl_attributes_server}} {{/zcl_clusters}} /*----------------------------------------------------------------------------*\ @@ -130,10 +91,16 @@ void registerCluster{{asUpperCamelCase name}}(Commands & commands, CredentialIss {{#zcl_attributes_server}} make_unique(Id, "{{asDelimitedCommand (asUpperCamelCase name)}}", Attributes::{{asUpperCamelCase name}}::Id, credsIssuerConfig), // {{/zcl_attributes_server}} - make_unique(Id, credsIssuerConfig), // + make_unique>(Id, credsIssuerConfig), // {{#zcl_attributes_server}} {{#if isWritable}} - make_unique(credsIssuerConfig), // + {{#if_chip_complex}} + make_unique>(Id, "{{asDelimitedCommand (asUpperCamelCase name)}}", Attributes::{{asUpperCamelCase name}}::Id, credsIssuerConfig), // + {{else if (isString type)}} + make_unique>(Id, "{{asDelimitedCommand (asUpperCamelCase name)}}", Attributes::{{asUpperCamelCase name}}::Id, credsIssuerConfig), // + {{else}} + make_unique>(Id, "{{asDelimitedCommand (asUpperCamelCase name)}}", {{asTypeMinValue type}}, {{asTypeMaxValue type}}, Attributes::{{asUpperCamelCase name}}::Id, credsIssuerConfig), // + {{/if_chip_complex}} {{/if}} {{/zcl_attributes_server}} make_unique(Id, credsIssuerConfig), // @@ -166,7 +133,7 @@ void registerClusterAny(Commands & commands, CredentialIssuerCommands * credsIss commands_list clusterCommands = { make_unique(credsIssuerConfig), // make_unique(credsIssuerConfig), // - make_unique(credsIssuerConfig), // + make_unique>(credsIssuerConfig), // make_unique(credsIssuerConfig), // make_unique(credsIssuerConfig), // make_unique(credsIssuerConfig), // diff --git a/examples/common/pigweed/protos/attributes_service.proto b/examples/common/pigweed/protos/attributes_service.proto index b5bef8f9eaf47b..4ebb71508d586e 100644 --- a/examples/common/pigweed/protos/attributes_service.proto +++ b/examples/common/pigweed/protos/attributes_service.proto @@ -155,7 +155,6 @@ enum ClusterType { ZCL_CHLORODIBROMOMETHANE_CONCENTRATION_MEASUREMENT_CLUSTER_ID = 0x0427; ZCL_CHLOROFORM_CONCENTRATION_MEASUREMENT_CLUSTER_ID = 0x0428; ZCL_SODIUM_CONCENTRATION_MEASUREMENT_CLUSTER_ID = 0x0429; - ZCL_IAS_ZONE_CLUSTER_ID = 0x0500; ZCL_IAS_ACE_CLUSTER_ID = 0x0501; ZCL_IAS_WD_CLUSTER_ID = 0x0502; ZCL_WAKE_ON_LAN_CLUSTER_ID = 0x0503; diff --git a/examples/common/pigweed/protos/device_service.options b/examples/common/pigweed/protos/device_service.options index 3f0c8f9375bb75..b5f9da673ff778 100644 --- a/examples/common/pigweed/protos/device_service.options +++ b/examples/common/pigweed/protos/device_service.options @@ -1,4 +1,7 @@ -chip.rpc.DeviceInfo.serial_number max_size:32 // length defined in chip spec 8.2.3.1 +chip.rpc.DeviceInfo.serial_number max_size:32 // length defined in chip spec 11.1.6.1 +chip.rpc.DeviceInfo.software_version_string max_size:64 // length defined in chip spec 11.1.6.1 chip.rpc.DeviceState.fabric_info max_count:2 chip.rpc.PairingInfo.qr_code max_size:256 chip.rpc.PairingInfo.qr_code_url max_size:256 +chip.rpc.SpakeInfo.verifier max_size:97 // kSpake2p_VerifierSerialized_Length +chip.rpc.SpakeInfo.salt max_size:32 // kSpake2p_Max_PBKDF_Salt_Length diff --git a/examples/common/pigweed/protos/device_service.proto b/examples/common/pigweed/protos/device_service.proto index 771e4c82efdf4b..1c13d7d7281f14 100644 --- a/examples/common/pigweed/protos/device_service.proto +++ b/examples/common/pigweed/protos/device_service.proto @@ -11,6 +11,12 @@ message PairingInfo { string qr_code_url = 4; } +message SpakeInfo { + optional bytes verifier = 1; + optional bytes salt = 2; + optional uint32 iteration_count = 3; +} + // type lengths defined in chip spec 8.2.3.1 message DeviceInfo { uint32 vendor_id = 1; @@ -18,6 +24,7 @@ message DeviceInfo { uint32 software_version = 3; string serial_number = 4; PairingInfo pairing_info = 5; + string software_version_string = 6; } message FabricInfo { @@ -43,4 +50,6 @@ service Device { rpc SetPairingState(PairingState) returns (pw.protobuf.Empty){} rpc GetPairingState(pw.protobuf.Empty) returns (PairingState){} rpc SetPairingInfo(PairingInfo) returns (pw.protobuf.Empty){} + rpc GetSpakeInfo(pw.protobuf.Empty) returns (SpakeInfo){} + rpc SetSpakeInfo(SpakeInfo) returns (pw.protobuf.Empty){} } diff --git a/examples/common/pigweed/rpc_console/README.md b/examples/common/pigweed/rpc_console/README.md index 09226c2eec1ceb..d433631b9e12d1 100644 --- a/examples/common/pigweed/rpc_console/README.md +++ b/examples/common/pigweed/rpc_console/README.md @@ -15,50 +15,50 @@ files required for CHIP. ## Building - If this is the first time using the checkout the environment must first be - bootstrapped to install all dependencies. +If this is the first time using the checkout the environment must first be +bootstrapped to install all dependencies. - ``` - $ source /scripts/bootstrap.sh - ``` +``` +$ source /scripts/bootstrap.sh +``` - If bootstrap has previously been run, then simply activate. +If bootstrap has previously been run, then simply activate. - ``` - $ source /scripts/activate.sh - ``` +``` +$ source /scripts/activate.sh +``` - The python console is built and installed in the venv using gn: +The python console is built and installed in the venv using gn: - ``` - $ cd /examples/common/pigweed/rpc_console - $ gn gen out/debug - $ ninja -C out/debug - ``` +``` +$ cd /examples/common/pigweed/rpc_console +$ gn gen out/debug +$ ninja -C out/debug +``` - After building the output directory also contains a folder - (chip_rpc_console_wheels), with all the wheels required for the tool. These - can be used to install the console without needing the sdk. Simply install - all the wheels in the folder: +After building the output directory also contains a folder +(chip_rpc_console_wheels), with all the wheels required for the tool. These can +be used to install the console without needing the sdk. Simply install all the +wheels in the folder: - ``` - $ cd /examples/common/pigweed/rpc_console/out/debug - $ pip install chip_rpc_console_wheels/*.whl - ``` +``` +$ cd /examples/common/pigweed/rpc_console/out/debug +$ pip install chip_rpc_console_wheels/*.whl +``` ## Running To start the console provide the path to the device, for example: - ``` - $ chip-console --device /dev/ttyUSB0 - ``` +``` +$ chip-console --device /dev/ttyUSB0 +``` Note that `chip-console` is an entry point for chip_rpc.console and could also be run with `python -m chip_rpc.console`. An example RPC command: - ```python - $ rpcs.chip.rpc.Device.GetDeviceInfo() - ``` +```python +rpcs.chip.rpc.Device.GetDeviceInfo() +``` diff --git a/examples/common/pigweed/rpc_services/Device.h b/examples/common/pigweed/rpc_services/Device.h index b3b7508f70bbed..77ddc530910439 100644 --- a/examples/common/pigweed/rpc_services/Device.h +++ b/examples/common/pigweed/rpc_services/Device.h @@ -26,6 +26,7 @@ #include "app/server/Server.h" #include "credentials/FabricTable.h" #include "device_service/device_service.rpc.pb.h" +#include "platform/CommissionableDataProvider.h" #include "platform/ConfigurationManager.h" #include "platform/DiagnosticDataProvider.h" #include "platform/PlatformManager.h" @@ -35,6 +36,175 @@ namespace chip { namespace rpc { +namespace Internal { +// This class supports changing the commissionable data provider values at +// runtime using the RPCs. +// This class is LazyInit after getting or setting any of it's values. After +// this the class wraps the original CommissionableDataProvider, returning the +// original values for anything which has not been overwritten. +// +// NOTE: Values written do not persist across a reboot. +class CommissionableDataProviderRpcWrapper : public DeviceLayer::CommissionableDataProvider +{ +public: + CHIP_ERROR GetSetupPasscode(uint32_t & setupPasscode) override + { + LazyInit(); + if (mPasscodeOverride.has_value()) + { + setupPasscode = mPasscodeOverride.value(); + return CHIP_NO_ERROR; + } + if (mCommissionableDataProvider) + { + return mCommissionableDataProvider->GetSetupPasscode(setupPasscode); + } + return CHIP_ERROR_INTERNAL; + } + + // NOTE: Changing the passcode will not change the verifier or anything else + // this just changes the value returned from GetSetupPasscode. + // Using this is completely optional, and only really useful for test + // automation which can read the configured passcode for commissioning + // after it is changed. + CHIP_ERROR SetSetupPasscode(uint32_t setupPasscode) override + { + LazyInit(); + mPasscodeOverride = setupPasscode; + return CHIP_NO_ERROR; + } + + CHIP_ERROR GetSetupDiscriminator(uint16_t & setupDiscriminator) override + { + LazyInit(); + if (mDiscriminatorOverride.has_value()) + { + setupDiscriminator = mDiscriminatorOverride.value(); + return CHIP_NO_ERROR; + } + if (mCommissionableDataProvider) + { + return mCommissionableDataProvider->GetSetupDiscriminator(setupDiscriminator); + } + return CHIP_ERROR_INTERNAL; + } + + CHIP_ERROR SetSetupDiscriminator(uint16_t setupDiscriminator) override + { + LazyInit(); + mDiscriminatorOverride = setupDiscriminator; + return CHIP_NO_ERROR; + } + + CHIP_ERROR GetSpake2pIterationCount(uint32_t & iterationCount) override + { + LazyInit(); + if (mIterationCountOverride.has_value()) + { + iterationCount = mIterationCountOverride.value(); + return CHIP_NO_ERROR; + } + if (mCommissionableDataProvider) + { + return mCommissionableDataProvider->GetSpake2pIterationCount(iterationCount); + } + return CHIP_ERROR_INTERNAL; + } + + CHIP_ERROR SetSpake2pIterationCount(uint32_t iterationCount) + { + LazyInit(); + mIterationCountOverride = iterationCount; + return CHIP_NO_ERROR; + } + + CHIP_ERROR GetSpake2pSalt(MutableByteSpan & saltBuf) override + { + LazyInit(); + if (mSaltOverride.has_value()) + { + if (mSaltOverride.value().size() > saltBuf.size()) + { + return CHIP_ERROR_BUFFER_TOO_SMALL; + } + std::copy(mSaltOverride.value().begin(), mSaltOverride.value().end(), saltBuf.begin()); + saltBuf.reduce_size(mSaltOverride.value().size()); + return CHIP_NO_ERROR; + } + if (mCommissionableDataProvider) + { + return mCommissionableDataProvider->GetSpake2pSalt(saltBuf); + } + return CHIP_ERROR_INTERNAL; + } + + CHIP_ERROR SetSpake2pSalt(ByteSpan saltBuf) + { + LazyInit(); + if (sizeof(mSaltBuf) < saltBuf.size()) + { + return CHIP_ERROR_BUFFER_TOO_SMALL; + } + std::copy(saltBuf.begin(), saltBuf.end(), mSaltBuf); + mSaltOverride = ByteSpan(mSaltBuf, saltBuf.size()); + return CHIP_NO_ERROR; + } + + CHIP_ERROR GetSpake2pVerifier(MutableByteSpan & verifierBuf, size_t & outVerifierLen) override + { + LazyInit(); + if (mVerifierOverride.has_value()) + { + outVerifierLen = mVerifierOverride.value().size(); + if (mVerifierOverride.value().size() > verifierBuf.size()) + { + return CHIP_ERROR_BUFFER_TOO_SMALL; + } + std::copy(mVerifierOverride.value().begin(), mVerifierOverride.value().end(), verifierBuf.begin()); + verifierBuf.reduce_size(mVerifierOverride.value().size()); + return CHIP_NO_ERROR; + } + if (mCommissionableDataProvider) + { + return mCommissionableDataProvider->GetSpake2pVerifier(verifierBuf, outVerifierLen); + } + + return CHIP_ERROR_INTERNAL; + } + + CHIP_ERROR SetSpake2pVerifier(ByteSpan verifierBuf) + { + LazyInit(); + if (sizeof(mVerifierBuf) < verifierBuf.size()) + { + return CHIP_ERROR_BUFFER_TOO_SMALL; + } + std::copy(verifierBuf.begin(), verifierBuf.end(), mVerifierBuf); + mVerifierOverride = ByteSpan(mVerifierBuf, verifierBuf.size()); + return CHIP_NO_ERROR; + } + +private: + std::optional mDiscriminatorOverride; + std::optional mPasscodeOverride; + Spake2pVerifierSerialized mVerifierBuf; + std::optional mVerifierOverride; + uint8_t mSaltBuf[kSpake2p_Max_PBKDF_Salt_Length]; + std::optional mSaltOverride; + std::optional mIterationCountOverride; + DeviceLayer::CommissionableDataProvider * mCommissionableDataProvider = nullptr; + + void LazyInit() + { + if (!mCommissionableDataProvider) + { + mCommissionableDataProvider = DeviceLayer::GetCommissionableDataProvider(); + DeviceLayer::SetCommissionableDataProvider(this); + } + } +}; +} // namespace Internal + class Device : public pw_rpc::nanopb::Device::Service { public: @@ -112,7 +282,7 @@ class Device : public pw_rpc::nanopb::Device::Service { uint16_t vendor_id; - if (DeviceLayer::ConfigurationMgr().GetVendorId(vendor_id) == CHIP_NO_ERROR) + if (DeviceLayer::GetDeviceInstanceInfoProvider()->GetVendorId(vendor_id) == CHIP_NO_ERROR) { response.vendor_id = static_cast(vendor_id); } @@ -122,7 +292,7 @@ class Device : public pw_rpc::nanopb::Device::Service } uint16_t product_id; - if (DeviceLayer::ConfigurationMgr().GetProductId(product_id) == CHIP_NO_ERROR) + if (DeviceLayer::GetDeviceInstanceInfoProvider()->GetProductId(product_id) == CHIP_NO_ERROR) { response.product_id = static_cast(product_id); } @@ -141,6 +311,13 @@ class Device : public pw_rpc::nanopb::Device::Service response.software_version = CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION; } + if (DeviceLayer::ConfigurationMgr().GetSoftwareVersionString(response.software_version_string, + sizeof(response.software_version_string)) != CHIP_NO_ERROR) + { + snprintf(response.software_version_string, sizeof(response.software_version_string), + CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING); + } + uint32_t code; if (DeviceLayer::GetCommissionableDataProvider()->GetSetupPasscode(code) == CHIP_NO_ERROR) { @@ -155,7 +332,7 @@ class Device : public pw_rpc::nanopb::Device::Service response.has_pairing_info = true; } - if (DeviceLayer::GetDeviceInstanceInfoProvider()->GetSerialNumber(response.serial_number, sizeof(response.serial_number)) == + if (DeviceLayer::GetDeviceInstanceInfoProvider()->GetSerialNumber(response.serial_number, sizeof(response.serial_number)) != CHIP_NO_ERROR) { snprintf(response.serial_number, sizeof(response.serial_number), CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER); @@ -174,15 +351,65 @@ class Device : public pw_rpc::nanopb::Device::Service return pw::OkStatus(); } + virtual pw::Status GetSpakeInfo(const pw_protobuf_Empty & request, chip_rpc_SpakeInfo & response) + { + size_t serializedVerifierLen = 0; + MutableByteSpan verifierSpan{ response.verifier.bytes }; + if (DeviceLayer::GetCommissionableDataProvider()->GetSpake2pVerifier(verifierSpan, serializedVerifierLen) == CHIP_NO_ERROR) + { + response.verifier.size = verifierSpan.size(); + response.has_verifier = true; + } + + MutableByteSpan saltSpan{ response.salt.bytes }; + if (DeviceLayer::GetCommissionableDataProvider()->GetSpake2pSalt(saltSpan) == CHIP_NO_ERROR) + { + response.salt.size = saltSpan.size(); + response.has_salt = true; + } + + if (DeviceLayer::GetCommissionableDataProvider()->GetSpake2pIterationCount(response.iteration_count) == CHIP_NO_ERROR) + { + response.has_iteration_count = true; + } + + return pw::OkStatus(); + } + + virtual pw::Status SetSpakeInfo(const chip_rpc_SpakeInfo & request, pw_protobuf_Empty & response) + { + if (request.has_salt) + { + mCommissionableDataProvider.SetSpake2pSalt(ByteSpan(request.salt.bytes, request.salt.size)); + } + if (request.has_iteration_count) + { + mCommissionableDataProvider.SetSpake2pIterationCount(request.iteration_count); + } + if (request.has_verifier) + { + mCommissionableDataProvider.SetSpake2pVerifier(ByteSpan(request.verifier.bytes, request.verifier.size)); + } + return pw::OkStatus(); + } + + // NOTE: Changing the passcode will not change the verifier or anything else + // this just changes the value returned from GetSetupPasscode. + // Using this is completely optional, and only really useful for test + // automation which can read the configured passcode for commissioning + // after it is changed. virtual pw::Status SetPairingInfo(const chip_rpc_PairingInfo & request, pw_protobuf_Empty & response) { - if (DeviceLayer::GetCommissionableDataProvider()->SetSetupPasscode(request.code) != CHIP_NO_ERROR || - DeviceLayer::GetCommissionableDataProvider()->SetSetupDiscriminator(request.discriminator) != CHIP_NO_ERROR) + if (mCommissionableDataProvider.SetSetupPasscode(request.code) != CHIP_NO_ERROR || + mCommissionableDataProvider.SetSetupDiscriminator(request.discriminator) != CHIP_NO_ERROR) { return pw::Status::Unknown(); } return pw::OkStatus(); } + +private: + Internal::CommissionableDataProviderRpcWrapper mCommissionableDataProvider; }; } // namespace rpc diff --git a/examples/darwin-framework-tool/BUILD.gn b/examples/darwin-framework-tool/BUILD.gn index ed7486d98609df..f543b83c0c4690 100644 --- a/examples/darwin-framework-tool/BUILD.gn +++ b/examples/darwin-framework-tool/BUILD.gn @@ -27,12 +27,19 @@ config("config") { "${chip_root}/examples/chip-tool/commands/clusters/ComplexArgument.h", ] - defines = [ "CONFIG_ENABLE_YAML_TESTS=${config_enable_yaml_tests}" ] + defines = [ + "CONFIG_ENABLE_YAML_TESTS=${config_enable_yaml_tests}", + "CONFIG_USE_INTERACTIVE_MODE=${config_use_interactive_mode}", + ] cflags = [ "-Wconversion", "-fobjc-arc", ] + + if (config_use_interactive_mode) { + libs = [ "readline" ] + } } executable("darwin-framework-tool") { @@ -55,6 +62,10 @@ executable("darwin-framework-tool") { "main.mm", ] + if (config_use_interactive_mode) { + sources += [ "commands/interactive/InteractiveCommands.mm" ] + } + if (config_enable_yaml_tests) { sources += [ "${chip_root}/zzz_generated/darwin-framework-tool/zap-generated/cluster/CHIPTestClustersObjc.mm" ] } diff --git a/examples/darwin-framework-tool/commands/clusters/ModelCommandBridge.h b/examples/darwin-framework-tool/commands/clusters/ModelCommandBridge.h index 0f7a80f600ea94..adb1d21dece650 100644 --- a/examples/darwin-framework-tool/commands/clusters/ModelCommandBridge.h +++ b/examples/darwin-framework-tool/commands/clusters/ModelCommandBridge.h @@ -34,6 +34,10 @@ class ModelCommand : public CHIPCommandBridge AddArgument("endpoint-id", 0, UINT16_MAX, &mEndPointId); } + void Shutdown() override; + + void Cleanup() override { ModelCommand::Shutdown(); } + /////////// CHIPCommand Interface ///////// CHIP_ERROR RunCommand() override; chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(10); } diff --git a/examples/darwin-framework-tool/commands/clusters/ModelCommandBridge.mm b/examples/darwin-framework-tool/commands/clusters/ModelCommandBridge.mm index 1838033f9f8732..8a27391324cdc5 100644 --- a/examples/darwin-framework-tool/commands/clusters/ModelCommandBridge.mm +++ b/examples/darwin-framework-tool/commands/clusters/ModelCommandBridge.mm @@ -49,3 +49,5 @@ }]; return CHIP_NO_ERROR; } + +void ModelCommand::Shutdown() { ResetArguments(); } diff --git a/examples/darwin-framework-tool/commands/clusters/ReportCommandBridge.h b/examples/darwin-framework-tool/commands/clusters/ReportCommandBridge.h index ceb9a17642dbbd..17baa322ddc581 100644 --- a/examples/darwin-framework-tool/commands/clusters/ReportCommandBridge.h +++ b/examples/darwin-framework-tool/commands/clusters/ReportCommandBridge.h @@ -132,35 +132,50 @@ class SubscribeAttribute : public ModelCommand { params.keepPreviousSubscriptions = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil; [device subscribeAttributeWithEndpointId:[NSNumber numberWithUnsignedShort:endpointId] - clusterId:[NSNumber numberWithUnsignedInteger:mClusterId] - attributeId:[NSNumber numberWithUnsignedInteger:mAttributeId] - minInterval:[NSNumber numberWithUnsignedInteger:mMinInterval] - maxInterval:[NSNumber numberWithUnsignedInteger:mMaxInterval] - params:params - clientQueue:callbackQueue - reportHandler:^( - NSArray *> * _Nullable values, NSError * _Nullable error) { - if (values) { - for (id item in values) { - NSLog(@"Response Item: %@", [item description]); - } - } - if (error || !mWait) { - SetCommandExitStatus(error); - } - } - subscriptionEstablished:nil]; + clusterId:[NSNumber numberWithUnsignedInteger:mClusterId] + attributeId:[NSNumber numberWithUnsignedInteger:mAttributeId] + minInterval:[NSNumber numberWithUnsignedInteger:mMinInterval] + maxInterval:[NSNumber numberWithUnsignedInteger:mMaxInterval] + params:params + clientQueue:callbackQueue + reportHandler:^(NSArray *> * _Nullable values, NSError * _Nullable error) { + if (values) { + for (id item in values) { + NSLog(@"Response Item: %@", [item description]); + } + } + if (error || !mWait) { + SetCommandExitStatus(error); + } + } + subscriptionEstablished:^() { + mSubscriptionEstablished = YES; + }]; return CHIP_NO_ERROR; } + chip::System::Clock::Timeout GetWaitDuration() const override + { + return chip::System::Clock::Seconds16(mWait ? UINT16_MAX : 10); + } + protected: chip::Optional mKeepSubscriptions; chip::Optional mFabricFiltered; + bool mSubscriptionEstablished = NO; uint16_t mMinInterval; uint16_t mMaxInterval; bool mWait; + void Shutdown() override + { + mSubscriptionEstablished = NO; + ModelCommand::Shutdown(); + } + + bool DeferInteractiveCleanup() override { return mSubscriptionEstablished; } + private: chip::ClusterId mClusterId; chip::AttributeId mAttributeId; @@ -211,6 +226,7 @@ class SubscribeEvent : public ModelCommand { } } subscriptionEstablished:^() { + mSubscriptionEstablished = YES; }]; return CHIP_NO_ERROR; @@ -224,6 +240,7 @@ class SubscribeEvent : public ModelCommand { protected: chip::Optional mKeepSubscriptions; chip::Optional mEventNumber; + bool mSubscriptionEstablished = NO; uint16_t mMinInterval; uint16_t mMaxInterval; bool mWait; diff --git a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h index 5557cb66b7a0ca..632f67dfbe0f8f 100644 --- a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h +++ b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h @@ -45,7 +45,6 @@ class CHIPCommandBridge : public Command void SetCommandExitStatus(CHIP_ERROR status) { mCommandExitStatus = status; - ShutdownCommissioner(); StopWaiting(); } @@ -76,6 +75,22 @@ class CHIPCommandBridge : public Command // if failure). void LogNSError(const char * logString, NSError * error); + // Clean up any resources allocated by the command. Some commands may hold + // on to resources after Shutdown(), but Cleanup() will guarantee those are + // cleaned up. + virtual void Cleanup() {} + + // If true, skip calling Cleanup() when in interactive mode, so the command + // can keep doing work as needed. Cleanup() will be called when quitting + // interactive mode. This method will be called before Shutdown, so it can + // use member values that Shutdown will normally reset. + virtual bool DeferInteractiveCleanup() { return NO; } + + // Execute any deferred cleanups. Used when exiting interactive mode. + void ExecuteDeferredCleanups(); + + static std::set sDeferredCleanups; + private: CHIP_ERROR InitializeCommissioner(std::string key, chip::FabricId fabricId, const chip::Credentials::AttestationTrustStore * trustStore); @@ -87,8 +102,11 @@ class CHIPCommandBridge : public Command CHIP_ERROR StartWaiting(chip::System::Clock::Timeout seconds); void StopWaiting(); + CHIP_ERROR MaybeSetUpStack(); + CHIP_ERROR MaybeTearDownStack(); + // Our three controllers: alpha, beta, gamma. - std::map mControllers; + static std::map mControllers; // The current controller; the one the current command should be using. CHIPDeviceController * mCurrentController; diff --git a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm index b5d8a6c1d0051b..551400c4f68bbf 100644 --- a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm +++ b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm @@ -27,10 +27,36 @@ const uint16_t kListenPort = 5541; static CHIPToolPersistentStorageDelegate * storage = nil; +std::set CHIPCommandBridge::sDeferredCleanups; +std::map CHIPCommandBridge::mControllers; CHIP_ERROR CHIPCommandBridge::Run() { ChipLogProgress(chipTool, "Running Command"); + ReturnErrorOnFailure(MaybeSetUpStack()); + SetIdentity(mCommissionerName.HasValue() ? mCommissionerName.Value() : kIdentityAlpha); + ReturnLogErrorOnFailure(RunCommand()); + ReturnLogErrorOnFailure(StartWaiting(GetWaitDuration())); + + bool deferCleanup = (IsInteractive() && DeferInteractiveCleanup()); + + Shutdown(); + + if (deferCleanup) { + sDeferredCleanups.insert(this); + } else { + Cleanup(); + } + ReturnErrorOnFailure(MaybeTearDownStack()); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR CHIPCommandBridge::MaybeSetUpStack() +{ + if (IsInteractive()) { + return CHIP_NO_ERROR; + } NSData * ipk; CHIPToolKeypair * nocSigner = [[CHIPToolKeypair alloc] init]; storage = [[CHIPToolPersistentStorageDelegate alloc] init]; @@ -76,15 +102,19 @@ mControllers[identities[i]] = controller; } - // If no commissioner name passed in, default to alpha. - SetIdentity(mCommissionerName.HasValue() ? mCommissionerName.Value() : kIdentityAlpha); - - ReturnLogErrorOnFailure(RunCommand()); - ReturnLogErrorOnFailure(StartWaiting(GetWaitDuration())); - return CHIP_NO_ERROR; } +CHIP_ERROR CHIPCommandBridge::MaybeTearDownStack() +{ + CHIP_ERROR err; + if (IsInteractive()) { + return CHIP_NO_ERROR; + } + err = ShutdownCommissioner(); + return err; +} + void CHIPCommandBridge::SetIdentity(const char * identity) { std::string name = std::string(identity); @@ -116,7 +146,6 @@ CHIP_ERROR CHIPCommandBridge::StartWaiting(chip::System::Clock::Timeout duration) { - chip::DeviceLayer::PlatformMgr().StartEventLoopTask(); auto waitingUntil = std::chrono::system_clock::now() + std::chrono::duration_cast(duration); { std::unique_lock lk(cvWaitingForResponseMutex); @@ -124,7 +153,6 @@ mCommandExitStatus = CHIP_ERROR_TIMEOUT; } } - LogErrorOnFailure(chip::DeviceLayer::PlatformMgr().StopEventLoopTask()); return mCommandExitStatus; } @@ -133,7 +161,7 @@ { { std::lock_guard lk(cvWaitingForResponseMutex); - mWaitingForResponse = false; + mWaitingForResponse = NO; } cvWaitingForResponse.notify_all(); } @@ -156,3 +184,11 @@ ChipLogError(chipTool, "%s: %s", logString, chip::ErrorStr(err)); } } + +void CHIPCommandBridge::ExecuteDeferredCleanups() +{ + for (auto * cmd : sDeferredCleanups) { + cmd->Cleanup(); + } + sDeferredCleanups.clear(); +} diff --git a/examples/darwin-framework-tool/commands/interactive/Commands.h b/examples/darwin-framework-tool/commands/interactive/Commands.h new file mode 100644 index 00000000000000..59a06b6a60fe5b --- /dev/null +++ b/examples/darwin-framework-tool/commands/interactive/Commands.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#pragma once + +#include "../common/CHIPCommandBridge.h" +#include + +#include "InteractiveCommands.h" + +void registerCommandsInteractive(Commands & commands) +{ + const char * clusterName = "interactive"; + + commands_list clusterCommands = { +#if CONFIG_USE_INTERACTIVE_MODE + make_unique(&commands), +#endif // CONFIG_USE_INTERACTIVE_MODE + }; + + commands.Register(clusterName, clusterCommands); +} diff --git a/examples/darwin-framework-tool/commands/interactive/InteractiveCommands.h b/examples/darwin-framework-tool/commands/interactive/InteractiveCommands.h new file mode 100644 index 00000000000000..98347747f64fc6 --- /dev/null +++ b/examples/darwin-framework-tool/commands/interactive/InteractiveCommands.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#pragma once + +#include "../common/CHIPCommandBridge.h" +#include "commands/common/Commands.h" + +#include "InteractiveCommands.h" + +class Commands; + +class InteractiveStartCommand : public CHIPCommandBridge +{ +public: + InteractiveStartCommand(Commands * commandsHandler) : CHIPCommandBridge("start"), mHandler(commandsHandler) {} + + CHIP_ERROR RunCommand() override; + + chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(0); } + +private: + bool ParseCommand(char * command); + Commands * mHandler = nullptr; +}; diff --git a/examples/darwin-framework-tool/commands/interactive/InteractiveCommands.mm b/examples/darwin-framework-tool/commands/interactive/InteractiveCommands.mm new file mode 100644 index 00000000000000..3ffe41c7744f94 --- /dev/null +++ b/examples/darwin-framework-tool/commands/interactive/InteractiveCommands.mm @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "InteractiveCommands.h" + +#include +#include +#include +#include + +char kInteractiveModeName[] = ""; +constexpr const char * kInteractiveModePrompt = ">>> "; +constexpr uint8_t kInteractiveModeArgumentsMaxLength = 32; +constexpr const char * kInteractiveModeHistoryFilePath = "/tmp/darwin_framework_tool_history"; +constexpr const char * kInteractiveModeStopCommand = "quit()"; + +namespace { + +bool gIsCommandRunning = NO; + +void ClearLine() +{ + printf("\r\x1B[0J"); // Move cursor to the beginning of the line and clear from cursor to end of the screen +} + +void ENFORCE_FORMAT(3, 0) LoggingCallback(const char * module, uint8_t category, const char * msg, va_list args) +{ + ClearLine(); + chip::Logging::Platform::LogV(module, category, msg, args); + ClearLine(); + + if (gIsCommandRunning == NO) { + rl_forced_update_display(); + } +} +} // namespace + +char * GetCommand(char * command) +{ + if (command != nullptr) { + free(command); + command = nullptr; + } + + command = readline(kInteractiveModePrompt); + + // Do not save empty lines + if (command != nullptr && *command) { + add_history(command); + write_history(kInteractiveModeHistoryFilePath); + } + + return command; +} + +CHIP_ERROR InteractiveStartCommand::RunCommand() +{ + read_history(kInteractiveModeHistoryFilePath); + + // Logs needs to be redirected in order to refresh the screen appropriately when something + // is dumped to stdout while the user is typing a command. + chip::Logging::SetLogRedirectCallback(LoggingCallback); + + char * command = nullptr; + while (YES) { + command = GetCommand(command); + if (command != nullptr && !ParseCommand(command)) { + break; + } + } + + SetCommandExitStatus(CHIP_NO_ERROR); + return CHIP_NO_ERROR; +} + +bool InteractiveStartCommand::ParseCommand(char * command) +{ + if (strcmp(command, kInteractiveModeStopCommand) == 0) { + ExecuteDeferredCleanups(); + return NO; + } + + char * args[kInteractiveModeArgumentsMaxLength]; + args[0] = kInteractiveModeName; + int argsCount = 1; + std::string arg; + + std::stringstream ss(command); + while (ss >> std::quoted(arg)) { + if (argsCount == kInteractiveModeArgumentsMaxLength) { + gIsCommandRunning = YES; + ChipLogError(chipTool, "Too many arguments. Ignoring."); + gIsCommandRunning = NO; + return YES; + } + + char * carg = new char[arg.size() + 1]; + strcpy(carg, arg.c_str()); + args[argsCount++] = carg; + } + + ClearLine(); + gIsCommandRunning = YES; + mHandler->RunInteractive(argsCount, args); + gIsCommandRunning = NO; + + // Do not delete arg[0] + while (--argsCount) + delete[] args[argsCount]; + + return YES; +} diff --git a/examples/darwin-framework-tool/commands/pairing/Commands.h b/examples/darwin-framework-tool/commands/pairing/Commands.h index 4dccd6d52f7d28..1fed642addae64 100644 --- a/examples/darwin-framework-tool/commands/pairing/Commands.h +++ b/examples/darwin-framework-tool/commands/pairing/Commands.h @@ -27,6 +27,18 @@ class PairCode : public PairingCommandBridge PairCode() : PairingCommandBridge("code", PairingMode::Code, PairingNetworkType::None) {} }; +class PairCodeWifi : public PairingCommandBridge +{ +public: + PairCodeWifi() : PairingCommandBridge("code-wifi", PairingMode::Code, PairingNetworkType::WiFi) {} +}; + +class PairCodeThread : public PairingCommandBridge +{ +public: + PairCodeThread() : PairingCommandBridge("code-thread", PairingMode::Code, PairingNetworkType::Thread) {} +}; + class PairWithIPAddress : public PairingCommandBridge { public: @@ -56,9 +68,10 @@ void registerCommandsPairing(Commands & commands) const char * clusterName = "Pairing"; commands_list clusterCommands = { - make_unique(), make_unique(), - make_unique(), make_unique(), - make_unique(), make_unique(), + make_unique(), make_unique(), + make_unique(), make_unique(), + make_unique(), make_unique(), + make_unique(), make_unique(), }; commands.Register(clusterName, clusterCommands); diff --git a/examples/darwin-framework-tool/commands/pairing/PairingDelegateBridge.mm b/examples/darwin-framework-tool/commands/pairing/PairingDelegateBridge.mm index 4a10feff9a5dda..64467e476d8f47 100644 --- a/examples/darwin-framework-tool/commands/pairing/PairingDelegateBridge.mm +++ b/examples/darwin-framework-tool/commands/pairing/PairingDelegateBridge.mm @@ -29,6 +29,7 @@ - (void)onStatusUpdate:(CHIPPairingStatus)status switch (status) { case kSecurePairingSuccess: ChipLogProgress(chipTool, "Secure Pairing Success"); + ChipLogProgress(chipTool, "CASE establishment successful"); break; case kSecurePairingFailed: ChipLogError(chipTool, "Secure Pairing Failed"); @@ -42,10 +43,12 @@ - (void)onStatusUpdate:(CHIPPairingStatus)status - (void)onPairingComplete:(NSError *)error { if (error != nil) { + ChipLogProgress(chipTool, "PASE establishment failed"); _commandBridge->SetCommandExitStatus(error); return; } - ChipLogProgress(chipTool, "Pairing Complete"); + ChipLogProgress(chipTool, "Pairing Success"); + ChipLogProgress(chipTool, "PASE establishment successful"); NSError * commissionError; [_commissioner commissionDevice:_deviceID commissioningParams:_params error:&commissionError]; if (commissionError != nil) { diff --git a/examples/darwin-framework-tool/commands/tests/TestCommandBridge.h b/examples/darwin-framework-tool/commands/tests/TestCommandBridge.h index 23d5e9d52db3d6..4e5c870225ae0e 100644 --- a/examples/darwin-framework-tool/commands/tests/TestCommandBridge.h +++ b/examples/darwin-framework-tool/commands/tests/TestCommandBridge.h @@ -250,14 +250,6 @@ class TestCommandBridge : public CHIPCommandBridge, return ConstraintsChecker::CheckConstraintIsHexString(itemName, value, expectHexString); } - bool CheckConstraintNotValue( - const char * _Nonnull itemName, const NSString * _Nonnull current, const NSString * _Nonnull expected) - { - const chip::CharSpan currentValue([current UTF8String], [current lengthOfBytesUsingEncoding:NSUTF8StringEncoding]); - const chip::CharSpan expectedValue([expected UTF8String], [expected lengthOfBytesUsingEncoding:NSUTF8StringEncoding]); - return ConstraintsChecker::CheckConstraintNotValue(itemName, currentValue, expectedValue); - } - template bool CheckConstraintContains(const char * _Nonnull itemName, const NSArray * _Nonnull current, T expected) { for (id currentElement in current) { @@ -283,8 +275,31 @@ class TestCommandBridge : public CHIPCommandBridge, return true; } - bool CheckConstraintNotValue(const char * _Nonnull itemName, const NSData * _Nonnull current, const NSData * _Nonnull expected) + bool CheckConstraintNotValue( + const char * _Nonnull itemName, const NSString * _Nullable current, const NSString * _Nullable expected) { + if (current == nil && expected == nil) { + Exit(std::string(itemName) + " got unexpected value. Both values are nil."); + return false; + } + if ((current == nil) != (expected == nil)) { + return true; + } + const chip::CharSpan currentValue([current UTF8String], [current lengthOfBytesUsingEncoding:NSUTF8StringEncoding]); + const chip::CharSpan expectedValue([expected UTF8String], [expected lengthOfBytesUsingEncoding:NSUTF8StringEncoding]); + return ConstraintsChecker::CheckConstraintNotValue(itemName, currentValue, expectedValue); + } + + bool CheckConstraintNotValue( + const char * _Nonnull itemName, const NSData * _Nullable current, const NSData * _Nullable expected) + { + if (current == nil && expected == nil) { + Exit(std::string(itemName) + " got unexpected value. Both values are nil."); + return false; + } + if ((current == nil) != (expected == nil)) { + return true; + } const chip::ByteSpan currentValue(static_cast([current bytes]), [current length]); const chip::ByteSpan expectedValue(static_cast([expected bytes]), [expected length]); return ConstraintsChecker::CheckConstraintNotValue(itemName, currentValue, expectedValue); @@ -308,7 +323,7 @@ class TestCommandBridge : public CHIPCommandBridge, } template - bool CheckConstraintNotValue(const char * _Nonnull itemName, const NSNumber * _Nonnull current, T expected) + bool CheckConstraintNotValue(const char * _Nonnull itemName, const NSNumber * _Nullable current, T expected) { return CheckConstraintNotValue(itemName, current, @(expected)); } @@ -351,6 +366,21 @@ class TestCommandBridge : public CHIPCommandBridge, return ConstraintsChecker::CheckConstraintMaxValue(itemName, current, [expected unsignedLongLongValue]); } + bool CheckConstraintHasValue(const char * _Nonnull itemName, id _Nullable current, bool shouldHaveValue) + { + if (shouldHaveValue && (current == nil)) { + Exit(std::string(itemName) + " expected to have a value but doesn't"); + return false; + } + + if (!shouldHaveValue && (current != nil)) { + Exit(std::string(itemName) + " not expected to have a value but does"); + return false; + } + + return true; + } + bool CheckValueAsString(const char * _Nonnull itemName, const id _Nonnull current, const NSString * _Nonnull expected) { NSString * data = current; diff --git a/examples/darwin-framework-tool/main.mm b/examples/darwin-framework-tool/main.mm index 1d78c781596fe4..53d12e4b8d9032 100644 --- a/examples/darwin-framework-tool/main.mm +++ b/examples/darwin-framework-tool/main.mm @@ -17,9 +17,8 @@ */ #include "commands/common/Commands.h" - +#include "commands/interactive/Commands.h" #include "commands/pairing/Commands.h" - #include "commands/storage/Commands.h" #include @@ -29,6 +28,7 @@ int main(int argc, const char * argv[]) { Commands commands; registerCommandsPairing(commands); + registerCommandsInteractive(commands); registerCommandsStorage(commands); registerCommandsTests(commands); registerClusters(commands); diff --git a/examples/darwin-framework-tool/templates/commands.zapt b/examples/darwin-framework-tool/templates/commands.zapt index 6ad1b9f1bc3005..55eaf9e419546f 100644 --- a/examples/darwin-framework-tool/templates/commands.zapt +++ b/examples/darwin-framework-tool/templates/commands.zapt @@ -56,7 +56,7 @@ public: uint16_t __block responsesNeeded = repeatCount; while (repeatCount--) { - [cluster {{asLowerCamelCase name}}With{{#if (hasArguments)}}Params:params completionHandler:{{else}}CompletionHandler:{{/if}} + [cluster {{asLowerCamelCase name}}WithParams:params completionHandler: {{#if hasSpecificResponse}} ^(CHIP{{asUpperCamelCase clusterName}}Cluster{{asUpperCamelCase responseName}}Params * _Nullable values, NSError * _Nullable error) { NSLog(@"Values: %@", values); @@ -221,8 +221,9 @@ public: params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil; [cluster subscribe{{>attribute}}WithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval] maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval] - params:params - subscriptionEstablished: nullptr reportHandler:^({{asObjectiveCClass type parent.name}} * _Nullable value, NSError * _Nullable error) { + params:params + subscriptionEstablished:^(){ mSubscriptionEstablished=YES; } + reportHandler:^({{asObjectiveCClass type parent.name}} * _Nullable value, NSError * _Nullable error) { NSLog(@"{{asUpperCamelCase parent.name}}.{{asUpperCamelCase name}} response %@", [value description]); if (error || !mWait){ SetCommandExitStatus(error); @@ -231,12 +232,6 @@ public: return CHIP_NO_ERROR; } - - chip::System::Clock::Timeout GetWaitDuration() const override - { - return chip::System::Clock::Seconds16(mWait ? UINT16_MAX : 10); - } - }; {{/if}} diff --git a/examples/darwin-framework-tool/templates/tests/partials/checks/maybeCheckExpectedConstraints.zapt b/examples/darwin-framework-tool/templates/tests/partials/checks/maybeCheckExpectedConstraints.zapt index 190a0fe5abae49..29a0930f90772b 100644 --- a/examples/darwin-framework-tool/templates/tests/partials/checks/maybeCheckExpectedConstraints.zapt +++ b/examples/darwin-framework-tool/templates/tests/partials/checks/maybeCheckExpectedConstraints.zapt @@ -1,5 +1,13 @@ {{#if hasExpectedConstraints}} {{~#*inline "item"}}{{asLowerCamelCase name}}{{/inline}} + + {{~#if isOptional}} + {{~#if (hasProperty expectedConstraints "hasValue")}}VerifyOrReturn(CheckConstraintHasValue("{{>item}}", {{>actualValue}}, {{expectedConstraints.hasValue}}));{{/if}} + if ({{>actualValue}} != nil) { + {{else if isNullable}} + if ({{>actualValue}} != nil) { + {{/if}} + {{#if (hasProperty expectedConstraints "type")}}VerifyOrReturn(CheckConstraintType("{{>item}}", "", "{{expectedConstraints.type}}"));{{/if}} {{~#if (hasProperty expectedConstraints "format")}}VerifyOrReturn(CheckConstraintFormat("{{>item}}", "", "{{expectedConstraints.format}}"));{{/if}} @@ -19,49 +27,36 @@ {{~#if (hasProperty expectedConstraints "maxLength")}}VerifyOrReturn(CheckConstraintMaxLength("{{>item}}", [{{>actualValue}} length], {{expectedConstraints.maxLength}}));{{/if}} {{~#if (hasProperty expectedConstraints "minValue")}} - if ({{>actualValue}} != nil) - { - VerifyOrReturn(CheckConstraintMinValue<{{chipType}}>("{{>item}}", [{{>actualValue}} {{asObjectiveCNumberType "" type true}}Value], {{asTypedLiteral expectedConstraints.minValue type}})); - } + VerifyOrReturn(CheckConstraintMinValue<{{chipType}}>("{{>item}}", [{{>actualValue}} {{asObjectiveCNumberType "" type true}}Value], {{asTypedLiteral expectedConstraints.minValue type}})); {{/if}} {{~#if (hasProperty expectedConstraints "maxValue")}} - if ({{>actualValue}} != nil) - { - VerifyOrReturn(CheckConstraintMaxValue<{{chipType}}>("{{>item}}", [{{>actualValue}} {{asObjectiveCNumberType "" type true}}Value], {{asTypedLiteral expectedConstraints.maxValue type}})); - } + VerifyOrReturn(CheckConstraintMaxValue<{{chipType}}>("{{>item}}", [{{>actualValue}} {{asObjectiveCNumberType "" type true}}Value], {{asTypedLiteral expectedConstraints.maxValue type}})); {{/if}} {{~#if (hasProperty expectedConstraints "contains")}} - if ({{>actualValue}} != nil) - { - {{#chip_tests_iterate_expected_list expectedConstraints.contains}} - VerifyOrReturn(CheckConstraintContains("{{asLowerCamelCase name}}", {{>actualValue}}, {{asTypedLiteral value type}})); - {{/chip_tests_iterate_expected_list}} - } + {{#chip_tests_iterate_expected_list expectedConstraints.contains}} + VerifyOrReturn(CheckConstraintContains("{{asLowerCamelCase name}}", {{>actualValue}}, {{asTypedLiteral value type}})); + {{/chip_tests_iterate_expected_list}} {{/if}} {{~#if (hasProperty expectedConstraints "excludes")}} - if ({{>actualValue}} != nil) - { - {{#chip_tests_iterate_expected_list expectedConstraints.excludes}} - VerifyOrReturn(CheckConstraintExcludes("{{asLowerCamelCase name}}", {{>actualValue}}, {{asTypedLiteral value type}})); - {{/chip_tests_iterate_expected_list}} - } + {{#chip_tests_iterate_expected_list expectedConstraints.excludes}} + VerifyOrReturn(CheckConstraintExcludes("{{asLowerCamelCase name}}", {{>actualValue}}, {{asTypedLiteral value type}})); + {{/chip_tests_iterate_expected_list}} + {{/if}} + + {{~#if isOptional}} + } + {{else if isNullable}} + } {{/if}} {{~#if (hasProperty expectedConstraints "notValue")}} {{#if (isLiteralNull expectedConstraints.notValue)}} - VerifyOrReturn(CheckValueNonNull("{{>item}}", {{>actualValue}})); + VerifyOrReturn(CheckValueNonNull("{{>item}}", {{>actualValue}})); {{else}} - if ({{>actualValue}} != nil) - { - {{#if (isString type)}} - VerifyOrReturn(CheckConstraintNotValue("{{>item}}", {{>actualValue}}, {{asTypedLiteral expectedConstraints.notValue type}})); - {{else}} - VerifyOrReturn(CheckConstraintNotValue("{{>item}}", {{>actualValue}}, {{asTypedLiteral expectedConstraints.notValue type}})); - {{/if}} - } + VerifyOrReturn(CheckConstraintNotValue("{{>item}}", {{>actualValue}}, {{asTypedLiteral expectedConstraints.notValue type}})); {{/if}} {{/if}} {{/if}} diff --git a/examples/light-switch-app/efr32/args.gni b/examples/light-switch-app/efr32/args.gni index 348e8e012098ae..7df1c5e400f56f 100644 --- a/examples/light-switch-app/efr32/args.gni +++ b/examples/light-switch-app/efr32/args.gni @@ -21,6 +21,6 @@ efr32_sdk_target = get_label_info(":sdk", "label_no_toolchain") chip_enable_ota_requestor = true pw_log_BACKEND = "${chip_root}/src/lib/support/pw_log_chip" -pw_assert_BACKEND = "$dir_pw_assert_log" +pw_assert_BACKEND = "$dir_pw_assert_log:check_backend" chip_enable_openthread = true pw_rpc_CONFIG = "$dir_pw_rpc:disable_global_mutex" diff --git a/examples/light-switch-app/efr32/build_for_wifi_args.gni b/examples/light-switch-app/efr32/build_for_wifi_args.gni index bf21912871e59d..4a3bdfd804ae19 100644 --- a/examples/light-switch-app/efr32/build_for_wifi_args.gni +++ b/examples/light-switch-app/efr32/build_for_wifi_args.gni @@ -21,4 +21,4 @@ import("${chip_root}/src/platform/EFR32/wifi_args.gni") chip_enable_ota_requestor = true pw_log_BACKEND = "${chip_root}/src/lib/support/pw_log_chip" -pw_assert_BACKEND = "$dir_pw_assert_log" +pw_assert_BACKEND = "$dir_pw_assert_log:check_backend" diff --git a/examples/light-switch-app/light-switch-common/light-switch-app.matter b/examples/light-switch-app/light-switch-common/light-switch-app.matter index 5b089349467146..055f1a73ff67a2 100644 --- a/examples/light-switch-app/light-switch-common/light-switch-app.matter +++ b/examples/light-switch-app/light-switch-common/light-switch-app.matter @@ -500,6 +500,7 @@ server cluster GeneralCommissioning = 48 { struct BasicCommissioningInfo { int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; } attribute access(write: administer) int64u breadcrumb = 0; diff --git a/examples/light-switch-app/nrfconnect/README.md b/examples/light-switch-app/nrfconnect/README.md index 0b14393eafe3c1..2b559a38edebd6 100644 --- a/examples/light-switch-app/nrfconnect/README.md +++ b/examples/light-switch-app/nrfconnect/README.md @@ -19,7 +19,8 @@ Semiconductor's nRF Connect SDK, and supports remote access and control of a lighting examples over a low-power, 802.15.4 Thread network. The example behaves as a Matter accessory, that is a device that can be paired -into an existing Matter network and can be controlled by this network. +into an existing Matter network and can be controlled by this network. The +device works as a Thread Sleepy End Device.
@@ -452,22 +453,6 @@ features like logs and command-line interface, run the following command: Remember to replace _build-target_ with the build target name of the Nordic Semiconductor's kit you own. -### Building with low-power configuration - -You can build the example using the low-power configuration, which enables -Thread's Sleepy End Device mode and disables debug features, such as the UART -console or the **LED 1** usage. - -To build for the low-power configuration, run the following command with -_build-target_ replaced with the build target name of the Nordic Semiconductor's -kit you own (for example `nrf52840dk_nrf52840`): - - $ west build -b build-target -- -DOVERLAY_CONFIG=overlay-low_power.conf - -For example, use the following command for `nrf52840dk_nrf52840`: - - $ west build -b nrf52840dk_nrf52840 -- -DOVERLAY_CONFIG=overlay-low_power.conf - ### Building with Device Firmware Upgrade support Support for DFU using Matter OTA is enabled by default. diff --git a/examples/light-switch-app/nrfconnect/main/AppTask.cpp b/examples/light-switch-app/nrfconnect/main/AppTask.cpp index f8dfd2d63d4750..4b98212214a41c 100644 --- a/examples/light-switch-app/nrfconnect/main/AppTask.cpp +++ b/examples/light-switch-app/nrfconnect/main/AppTask.cpp @@ -115,10 +115,8 @@ CHIP_ERROR AppTask::Init() #ifdef CONFIG_OPENTHREAD_MTD_SED err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_SleepyEndDevice); -#elif CONFIG_OPENTHREAD_MTD - err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_MinimalEndDevice); #else - err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_Router); + err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_MinimalEndDevice); #endif if (err != CHIP_NO_ERROR) { diff --git a/examples/light-switch-app/nrfconnect/main/include/CHIPProjectConfig.h b/examples/light-switch-app/nrfconnect/main/include/CHIPProjectConfig.h index 5361319e42ecfe..ffd8d9b208940c 100644 --- a/examples/light-switch-app/nrfconnect/main/include/CHIPProjectConfig.h +++ b/examples/light-switch-app/nrfconnect/main/include/CHIPProjectConfig.h @@ -30,4 +30,3 @@ /* Use a default pairing code if one hasn't been provisioned in flash. */ #define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021 #define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 -#define CHIP_DEVICE_CONFIG_SED_IDLE_INTERVAL 2000_ms32 diff --git a/examples/light-switch-app/nrfconnect/overlay-low_power.conf b/examples/light-switch-app/nrfconnect/overlay-low_power.conf deleted file mode 100644 index c962425f6ef937..00000000000000 --- a/examples/light-switch-app/nrfconnect/overlay-low_power.conf +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# Enable MTD Sleepy End Device -CONFIG_CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT=y - -# Disable UART console -CONFIG_SHELL=n -CONFIG_LOG=n -CONFIG_UART_CONSOLE=n -CONFIG_SERIAL=n - -# Suspend devices when the CPU goes to sleep -CONFIG_PM_DEVICE=y - -# Disable auxiliary state LEDs -CONFIG_STATE_LEDS=n diff --git a/examples/light-switch-app/nrfconnect/prj.conf b/examples/light-switch-app/nrfconnect/prj.conf index ade76cb81238fa..629b5cc693e1d3 100644 --- a/examples/light-switch-app/nrfconnect/prj.conf +++ b/examples/light-switch-app/nrfconnect/prj.conf @@ -29,6 +29,7 @@ CONFIG_OPENTHREAD_THREAD_VERSION_1_2=y CONFIG_OPENTHREAD_NORDIC_LIBRARY_MTD=y CONFIG_OPENTHREAD_MTD=y CONFIG_OPENTHREAD_FTD=n +CONFIG_CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT=y # Bluetooth overrides CONFIG_BT_DEVICE_NAME="MatterSwitch" diff --git a/examples/light-switch-app/nrfconnect/prj_no_dfu.conf b/examples/light-switch-app/nrfconnect/prj_no_dfu.conf index e032d64f912595..d23c1bd2f66f0e 100644 --- a/examples/light-switch-app/nrfconnect/prj_no_dfu.conf +++ b/examples/light-switch-app/nrfconnect/prj_no_dfu.conf @@ -29,6 +29,7 @@ CONFIG_OPENTHREAD_THREAD_VERSION_1_2=y CONFIG_OPENTHREAD_NORDIC_LIBRARY_MTD=y CONFIG_OPENTHREAD_MTD=y CONFIG_OPENTHREAD_FTD=n +CONFIG_CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT=y # Bluetooth overrides CONFIG_BT_DEVICE_NAME="MatterSwitch" diff --git a/examples/light-switch-app/nrfconnect/prj_release.conf b/examples/light-switch-app/nrfconnect/prj_release.conf index 0126f60b948f6f..8766ded201a22d 100644 --- a/examples/light-switch-app/nrfconnect/prj_release.conf +++ b/examples/light-switch-app/nrfconnect/prj_release.conf @@ -29,6 +29,7 @@ CONFIG_OPENTHREAD_THREAD_VERSION_1_2=y CONFIG_OPENTHREAD_NORDIC_LIBRARY_MTD=y CONFIG_OPENTHREAD_MTD=y CONFIG_OPENTHREAD_FTD=n +CONFIG_CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT=y # Bluetooth overrides CONFIG_BT_DEVICE_NAME="MatterSwitch" @@ -41,6 +42,9 @@ CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" # 32772 == 0x8004 (example light-switch-app) CONFIG_CHIP_DEVICE_PRODUCT_ID=32772 +# Suspend devices when the CPU goes into sleep +CONFIG_PM_DEVICE=y + # Disable all debug features CONFIG_SHELL=n CONFIG_OPENTHREAD_SHELL=n diff --git a/examples/light-switch-app/telink/CMakeLists.txt b/examples/light-switch-app/telink/CMakeLists.txt index 3368eb6a9ac567..1b28131ca7b41c 100755 --- a/examples/light-switch-app/telink/CMakeLists.txt +++ b/examples/light-switch-app/telink/CMakeLists.txt @@ -65,7 +65,6 @@ target_sources(app PRIVATE ${CHIP_ROOT}/src/app/util/attribute-storage.cpp ${CHIP_ROOT}/src/app/util/attribute-table.cpp ${CHIP_ROOT}/src/app/util/binding-table.cpp - ${CHIP_ROOT}/src/app/util/client-api.cpp ${CHIP_ROOT}/src/app/util/ember-compatibility-functions.cpp ${CHIP_ROOT}/src/app/util/ember-print.cpp ${CHIP_ROOT}/src/app/util/error-mapping.cpp diff --git a/examples/lighting-app/ameba/chip_main.cmake b/examples/lighting-app/ameba/chip_main.cmake index 3d17b4aebd3194..ecdc70c49c25d2 100755 --- a/examples/lighting-app/ameba/chip_main.cmake +++ b/examples/lighting-app/ameba/chip_main.cmake @@ -37,6 +37,8 @@ list( ${chip_dir}/examples/lighting-app/ameba/main/Globals.cpp ${chip_dir}/examples/lighting-app/ameba/main/LEDWidget.cpp ${chip_dir}/examples/lighting-app/ameba/main/DsoHack.cpp + + ${chip_dir}/examples/providers/DeviceInfoProviderImpl.cpp ) add_library( @@ -61,6 +63,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/providers ${chip_dir_output}/gen/include ${chip_dir}/src/include/ ${chip_dir}/src/lib/ diff --git a/examples/lighting-app/ameba/main/chipinterface.cpp b/examples/lighting-app/ameba/main/chipinterface.cpp index ecede097cb7441..6ba9aa4a21686c 100644 --- a/examples/lighting-app/ameba/main/chipinterface.cpp +++ b/examples/lighting-app/ameba/main/chipinterface.cpp @@ -22,6 +22,7 @@ #include "Globals.h" #include "LEDWidget.h" #include "Server.h" +#include #include "chip_porting.h" #include @@ -74,6 +75,7 @@ void NetWorkCommissioningInstInit() #endif static DeviceCallbacks EchoCallbacks; +chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider; void OnIdentifyStart(Identify *) { @@ -117,6 +119,8 @@ static void InitServer(intptr_t context) static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); chip::Server::GetInstance().Init(initParams); + gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); + chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); // Initialize device attestation config SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); diff --git a/examples/lighting-app/bouffalolab/bl602/args.gni b/examples/lighting-app/bouffalolab/bl602/args.gni index ab5fb2b420693f..3425fc8d0035ba 100644 --- a/examples/lighting-app/bouffalolab/bl602/args.gni +++ b/examples/lighting-app/bouffalolab/bl602/args.gni @@ -18,7 +18,7 @@ import("${chip_root}/src/platform/bouffalolab/BL602/args.gni") bl602_sdk_target = get_label_info(":sdk", "label_no_toolchain") pw_log_BACKEND = "${chip_root}/src/lib/support/pw_log_chip" -pw_assert_BACKEND = "$dir_pw_assert_log" +pw_assert_BACKEND = "$dir_pw_assert_log:check_backend" chip_enable_openthread = false diff --git a/examples/lighting-app/cyw30739/BUILD.gn b/examples/lighting-app/cyw30739/BUILD.gn index 9ebf17650960d3..86d7342430b378 100644 --- a/examples/lighting-app/cyw30739/BUILD.gn +++ b/examples/lighting-app/cyw30739/BUILD.gn @@ -55,6 +55,7 @@ cyw30739_executable("lighting_app") { deps = [ ":sdk", "${chip_root}/examples/lighting-app/lighting-common", + "${chip_root}/examples/providers:device_info_provider", "${chip_root}/examples/shell/shell_common:shell_common", "${chip_root}/src/lib", ] diff --git a/examples/lighting-app/cyw30739/src/ZclCallbacks.cpp b/examples/lighting-app/cyw30739/src/ZclCallbacks.cpp index df3fcf7721d1a4..ba9eb4056d3b72 100644 --- a/examples/lighting-app/cyw30739/src/ZclCallbacks.cpp +++ b/examples/lighting-app/cyw30739/src/ZclCallbacks.cpp @@ -64,9 +64,16 @@ void MatterPostAttributeChangeCallback(const app::ConcreteAttributePath & attrib } break; case Identify::Id: - ChipLogProgress(Zcl, "Identify attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u", - ChipLogValueMEI(attributePath.mClusterId), type, *value, size); - return; + if (attributePath.mAttributeId == Identify::Attributes::IdentifyTime::Id) + { + uint16_t identifyTime; + if (EMBER_ZCL_STATUS_SUCCESS == Identify::Attributes::IdentifyTime::Get(attributePath.mEndpointId, &identifyTime)) + { + ChipLogProgress(Zcl, "IdentifyTime %u", identifyTime); + return; + } + } + break; default: printf("Unhandled cluster ID: 0x%04lx\n", attributePath.mClusterId); return; diff --git a/examples/lighting-app/cyw30739/src/main.cpp b/examples/lighting-app/cyw30739/src/main.cpp index e3ec9dc3d49345..6c606e5c9dc1f2 100644 --- a/examples/lighting-app/cyw30739/src/main.cpp +++ b/examples/lighting-app/cyw30739/src/main.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR #include @@ -42,6 +43,7 @@ using namespace ::chip::Credentials; using namespace ::chip::DeviceLayer; using namespace ::chip::Shell; +static chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider; static void InitApp(intptr_t args); static void EventHandler(const ChipDeviceEvent * event, intptr_t arg); static void HandleThreadStateChangeEvent(const ChipDeviceEvent * event); @@ -153,6 +155,8 @@ void InitApp(intptr_t args) chip::Server::GetInstance().Init(initParams); SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); + gExampleDeviceInfoProvider.SetStorageDelegate(&chip::Server::GetInstance().GetPersistentStorage()); + chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); LightMgr().Init(); LightMgr().SetCallbacks(LightManagerCallback, NULL); diff --git a/examples/lighting-app/efr32/args.gni b/examples/lighting-app/efr32/args.gni index 348e8e012098ae..7df1c5e400f56f 100644 --- a/examples/lighting-app/efr32/args.gni +++ b/examples/lighting-app/efr32/args.gni @@ -21,6 +21,6 @@ efr32_sdk_target = get_label_info(":sdk", "label_no_toolchain") chip_enable_ota_requestor = true pw_log_BACKEND = "${chip_root}/src/lib/support/pw_log_chip" -pw_assert_BACKEND = "$dir_pw_assert_log" +pw_assert_BACKEND = "$dir_pw_assert_log:check_backend" chip_enable_openthread = true pw_rpc_CONFIG = "$dir_pw_rpc:disable_global_mutex" diff --git a/examples/lighting-app/efr32/build_for_wifi_args.gni b/examples/lighting-app/efr32/build_for_wifi_args.gni index bf21912871e59d..4a3bdfd804ae19 100644 --- a/examples/lighting-app/efr32/build_for_wifi_args.gni +++ b/examples/lighting-app/efr32/build_for_wifi_args.gni @@ -21,4 +21,4 @@ import("${chip_root}/src/platform/EFR32/wifi_args.gni") chip_enable_ota_requestor = true pw_log_BACKEND = "${chip_root}/src/lib/support/pw_log_chip" -pw_assert_BACKEND = "$dir_pw_assert_log" +pw_assert_BACKEND = "$dir_pw_assert_log:check_backend" diff --git a/examples/lighting-app/efr32/include/LightingManager.h b/examples/lighting-app/efr32/include/LightingManager.h index 3aa9871e919074..6d286faa30ef96 100644 --- a/examples/lighting-app/efr32/include/LightingManager.h +++ b/examples/lighting-app/efr32/include/LightingManager.h @@ -25,6 +25,7 @@ #include "FreeRTOS.h" #include "timers.h" // provides FreeRTOS timer support +#include #include @@ -58,6 +59,8 @@ class LightingManager typedef void (*Callback_fn_completed)(Action_t); void SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB); + static void OnTriggerOffWithEffect(OnOffEffect * effect); + private: friend LightingManager & LightMgr(void); State_t mState; @@ -68,6 +71,7 @@ class LightingManager bool mAutoTurnOff; uint32_t mAutoTurnOffDuration; bool mAutoTurnOffTimerArmed; + bool mOffEffectArmed; void CancelTimer(void); void StartTimer(uint32_t aTimeoutMs); @@ -75,6 +79,7 @@ class LightingManager static void TimerEventHandler(TimerHandle_t xTimer); static void AutoTurnOffTimerEventHandler(AppEvent * aEvent); static void ActuatorMovementTimerEventHandler(AppEvent * aEvent); + static void OffEffectTimerEventHandler(AppEvent * aEvent); static LightingManager sLight; }; diff --git a/examples/lighting-app/efr32/src/AppTask.cpp b/examples/lighting-app/efr32/src/AppTask.cpp index cf95bdf2c036cd..7e1e8d9a811e82 100644 --- a/examples/lighting-app/efr32/src/AppTask.cpp +++ b/examples/lighting-app/efr32/src/AppTask.cpp @@ -160,52 +160,6 @@ Identify gIdentify = { OnTriggerIdentifyEffect, }; -/********************************************************** - * OffWithEffect Callbacks - *********************************************************/ - -void OnTriggerOffWithEffect(OnOffEffect * effect) -{ - chip::app::Clusters::OnOff::OnOffEffectIdentifier effectId = effect->mEffectIdentifier; - uint8_t effectVariant = effect->mEffectVariant; - - // Uses print outs until we can support the effects - if (effectId == EMBER_ZCL_ON_OFF_EFFECT_IDENTIFIER_DELAYED_ALL_OFF) - { - if (effectVariant == EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_FADE_TO_OFF_IN_0P8_SECONDS) - { - ChipLogProgress(Zcl, "EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_FADE_TO_OFF_IN_0P8_SECONDS"); - } - else if (effectVariant == EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_NO_FADE) - { - ChipLogProgress(Zcl, "EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_NO_FADE"); - } - else if (effectVariant == - EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_50_PERCENT_DIM_DOWN_IN_0P8_SECONDS_THEN_FADE_TO_OFF_IN_12_SECONDS) - { - ChipLogProgress(Zcl, - "EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_50_PERCENT_DIM_DOWN_IN_0P8_SECONDS_THEN_FADE_TO_OFF_" - "IN_12_SECONDS"); - } - } - else if (effectId == EMBER_ZCL_ON_OFF_EFFECT_IDENTIFIER_DYING_LIGHT) - { - if (effectVariant == - EMBER_ZCL_ON_OFF_DYING_LIGHT_EFFECT_VARIANT_20_PERCENTER_DIM_UP_IN_0P5_SECONDS_THEN_FADE_TO_OFF_IN_1_SECOND) - { - ChipLogProgress( - Zcl, "EMBER_ZCL_ON_OFF_DYING_LIGHT_EFFECT_VARIANT_20_PERCENTER_DIM_UP_IN_0P5_SECONDS_THEN_FADE_TO_OFF_IN_1_SECOND"); - } - } -} - -OnOffEffect gEffect = { - chip::EndpointId{ 1 }, - OnTriggerOffWithEffect, - EMBER_ZCL_ON_OFF_EFFECT_IDENTIFIER_DELAYED_ALL_OFF, - static_cast(EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_FADE_TO_OFF_IN_0P8_SECONDS), -}; - } // namespace using namespace chip::TLV; diff --git a/examples/lighting-app/efr32/src/LightingManager.cpp b/examples/lighting-app/efr32/src/LightingManager.cpp index 3857a0d50e7fe5..47791911ea7308 100644 --- a/examples/lighting-app/efr32/src/LightingManager.cpp +++ b/examples/lighting-app/efr32/src/LightingManager.cpp @@ -23,8 +23,6 @@ #include "AppTask.h" #include -#include - using namespace chip; using namespace ::chip::DeviceLayer; @@ -32,6 +30,21 @@ LightingManager LightingManager::sLight; TimerHandle_t sLightTimer; +namespace { + +/********************************************************** + * OffWithEffect Callbacks + *********************************************************/ + +OnOffEffect gEffect = { + chip::EndpointId{ 1 }, + LightMgr().OnTriggerOffWithEffect, + EMBER_ZCL_ON_OFF_EFFECT_IDENTIFIER_DELAYED_ALL_OFF, + static_cast(EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_FADE_TO_OFF_IN_0P8_SECONDS), +}; + +} // namespace + CHIP_ERROR LightingManager::Init() { // Create FreeRTOS sw timer for light timer. @@ -58,6 +71,7 @@ CHIP_ERROR LightingManager::Init() mAutoTurnOffTimerArmed = false; mAutoTurnOff = false; mAutoTurnOffDuration = 0; + mOffEffectArmed = false; return CHIP_NO_ERROR; } @@ -94,13 +108,13 @@ bool LightingManager::InitiateAction(int32_t aActor, Action_t aAction) State_t new_state; // Initiate Turn On/Off Action only when the previous one is complete. - if (mState == kState_OffCompleted && aAction == ON_ACTION) + if (((mState == kState_OffCompleted) || mOffEffectArmed) && aAction == ON_ACTION) { action_initiated = true; new_state = kState_OnInitiated; } - else if (mState == kState_OnCompleted && aAction == OFF_ACTION) + else if (mState == kState_OnCompleted && aAction == OFF_ACTION && mOffEffectArmed == false) { action_initiated = true; @@ -118,6 +132,12 @@ bool LightingManager::InitiateAction(int32_t aActor, Action_t aAction) CancelTimer(); } + if (mOffEffectArmed && new_state == kState_OnInitiated) + { + CancelTimer(); + mOffEffectArmed = false; + } + StartTimer(ACTUATOR_MOVEMENT_PERIOS_MS); // Since the timer started successfully, update the state and trigger callback @@ -174,6 +194,10 @@ void LightingManager::TimerEventHandler(TimerHandle_t xTimer) { event.Handler = AutoTurnOffTimerEventHandler; } + else if (light->mOffEffectArmed) + { + event.Handler = OffEffectTimerEventHandler; + } else { event.Handler = ActuatorMovementTimerEventHandler; @@ -184,7 +208,7 @@ void LightingManager::TimerEventHandler(TimerHandle_t xTimer) void LightingManager::AutoTurnOffTimerEventHandler(AppEvent * aEvent) { LightingManager * light = static_cast(aEvent->TimerEvent.Context); - int32_t actor = 0; + int32_t actor = AppEvent::kEventType_Timer; // Make sure auto turn off timer is still armed. if (!light->mAutoTurnOffTimerArmed) @@ -199,6 +223,24 @@ void LightingManager::AutoTurnOffTimerEventHandler(AppEvent * aEvent) light->InitiateAction(actor, OFF_ACTION); } +void LightingManager::OffEffectTimerEventHandler(AppEvent * aEvent) +{ + LightingManager * light = static_cast(aEvent->TimerEvent.Context); + int32_t actor = AppEvent::kEventType_Timer; + + // Make sure auto turn off timer is still armed. + if (!light->mOffEffectArmed) + { + return; + } + + light->mOffEffectArmed = false; + + EFR32_LOG("OffEffect completed"); + + light->InitiateAction(actor, OFF_ACTION); +} + void LightingManager::ActuatorMovementTimerEventHandler(AppEvent * aEvent) { Action_t actionCompleted = INVALID_ACTION; @@ -234,3 +276,47 @@ void LightingManager::ActuatorMovementTimerEventHandler(AppEvent * aEvent) } } } + +void LightingManager::OnTriggerOffWithEffect(OnOffEffect * effect) +{ + chip::app::Clusters::OnOff::OnOffEffectIdentifier effectId = effect->mEffectIdentifier; + uint8_t effectVariant = effect->mEffectVariant; + uint32_t offEffectDuration = 0; + + // Temporary print outs and delay to test OffEffect behaviour + // Until dimming is supported for dev boards. + if (effectId == EMBER_ZCL_ON_OFF_EFFECT_IDENTIFIER_DELAYED_ALL_OFF) + { + if (effectVariant == EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_FADE_TO_OFF_IN_0P8_SECONDS) + { + offEffectDuration = 800; + ChipLogProgress(Zcl, "EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_FADE_TO_OFF_IN_0P8_SECONDS"); + } + else if (effectVariant == EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_NO_FADE) + { + offEffectDuration = 800; + ChipLogProgress(Zcl, "EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_NO_FADE"); + } + else if (effectVariant == + EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_50_PERCENT_DIM_DOWN_IN_0P8_SECONDS_THEN_FADE_TO_OFF_IN_12_SECONDS) + { + offEffectDuration = 12800; + ChipLogProgress(Zcl, + "EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_50_PERCENT_DIM_DOWN_IN_0P8_SECONDS_THEN_FADE_TO_OFF_" + "IN_12_SECONDS"); + } + } + else if (effectId == EMBER_ZCL_ON_OFF_EFFECT_IDENTIFIER_DYING_LIGHT) + { + if (effectVariant == + EMBER_ZCL_ON_OFF_DYING_LIGHT_EFFECT_VARIANT_20_PERCENTER_DIM_UP_IN_0P5_SECONDS_THEN_FADE_TO_OFF_IN_1_SECOND) + { + offEffectDuration = 1500; + ChipLogProgress( + Zcl, "EMBER_ZCL_ON_OFF_DYING_LIGHT_EFFECT_VARIANT_20_PERCENTER_DIM_UP_IN_0P5_SECONDS_THEN_FADE_TO_OFF_IN_1_SECOND"); + } + } + + LightMgr().mOffEffectArmed = true; + LightMgr().StartTimer(offEffectDuration); +} diff --git a/examples/lighting-app/lighting-common/lighting-app.matter b/examples/lighting-app/lighting-common/lighting-app.matter index 2d2773162d0210..ef2f89ee2ef987 100644 --- a/examples/lighting-app/lighting-common/lighting-app.matter +++ b/examples/lighting-app/lighting-common/lighting-app.matter @@ -513,6 +513,7 @@ server cluster GeneralCommissioning = 48 { struct BasicCommissioningInfo { int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; } attribute access(write: administer) int64u breadcrumb = 0; diff --git a/examples/lighting-app/linux/with_pw_rpc.gni b/examples/lighting-app/linux/with_pw_rpc.gni index 969b2b88c9b75b..9533565ecf4ce8 100644 --- a/examples/lighting-app/linux/with_pw_rpc.gni +++ b/examples/lighting-app/linux/with_pw_rpc.gni @@ -24,7 +24,7 @@ import("//build_overrides/pigweed.gni") cpp_standard = "gnu++17" pw_log_BACKEND = "$dir_pw_log_basic" -pw_assert_BACKEND = "$dir_pw_assert_log" +pw_assert_BACKEND = "$dir_pw_assert_log:check_backend" pw_sys_io_BACKEND = "$dir_pw_sys_io_stdio" pw_trace_BACKEND = "$dir_pw_trace_tokenized" pw_unit_test_MAIN = "$dir_pw_unit_test:logging_main" diff --git a/examples/lighting-app/nrfconnect/CMakeLists.txt b/examples/lighting-app/nrfconnect/CMakeLists.txt index 961ae6ff5afb86..4ef71fea088ba9 100644 --- a/examples/lighting-app/nrfconnect/CMakeLists.txt +++ b/examples/lighting-app/nrfconnect/CMakeLists.txt @@ -93,7 +93,8 @@ include(${PIGWEED_ROOT}/pw_protobuf_compiler/proto.cmake) pw_set_module_config(pw_rpc_CONFIG pw_rpc.disable_global_mutex_config) pw_set_backend(pw_log pw_log_basic) -pw_set_backend(pw_assert pw_assert_log) +pw_set_backend(pw_assert.check pw_assert_log.check_backend) +pw_set_backend(pw_assert.assert pw_assert.assert_compatibility_backend) pw_set_backend(pw_sys_io pw_sys_io.nrfconnect) pw_set_backend(pw_trace pw_trace_tokenized) set(dir_pw_third_party_nanopb "${CHIP_ROOT}/third_party/nanopb/repo" CACHE STRING "" FORCE) @@ -112,7 +113,7 @@ pw_proto_library(attributes_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(button_service @@ -123,7 +124,7 @@ pw_proto_library(button_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(descriptor_service @@ -134,7 +135,7 @@ pw_proto_library(descriptor_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(device_service @@ -147,7 +148,7 @@ pw_proto_library(device_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(lighting_service @@ -158,7 +159,7 @@ pw_proto_library(lighting_service PREFIX lighting_service DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(ot_cli_service @@ -171,7 +172,7 @@ pw_proto_library(ot_cli_service PREFIX ot_cli_service DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(thread_service @@ -184,7 +185,7 @@ pw_proto_library(thread_service PREFIX thread_service DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) target_sources(app PRIVATE diff --git a/examples/lighting-app/nrfconnect/README.md b/examples/lighting-app/nrfconnect/README.md index ff8013e360ad93..408d794b6436d2 100644 --- a/examples/lighting-app/nrfconnect/README.md +++ b/examples/lighting-app/nrfconnect/README.md @@ -14,7 +14,8 @@ Semiconductor's nRF Connect SDK, and supports remote access and control of a lighting over a low-power, 802.15.4 Thread network. The example behaves as a Matter accessory, that is a device that can be paired -into an existing Matter network and can be controlled by this network. +into an existing Matter network and can be controlled by this network. The +device works as a Thread Router.
diff --git a/examples/lighting-app/nrfconnect/main/AppTask.cpp b/examples/lighting-app/nrfconnect/main/AppTask.cpp index a108dc1b4bf89b..46ea48cf6b1a19 100644 --- a/examples/lighting-app/nrfconnect/main/AppTask.cpp +++ b/examples/lighting-app/nrfconnect/main/AppTask.cpp @@ -59,7 +59,6 @@ namespace { constexpr int kFactoryResetTriggerTimeout = 3000; constexpr int kFactoryResetCancelWindowTimeout = 3000; -constexpr int kExtDiscoveryTimeoutSecs = 20; constexpr int kAppEventQueueSize = 10; constexpr uint8_t kButtonPushEvent = 1; constexpr uint8_t kButtonReleaseEvent = 0; @@ -115,11 +114,8 @@ CHIP_ERROR AppTask::Init() return err; } -#ifdef CONFIG_OPENTHREAD_MTD - err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_MinimalEndDevice); -#else err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_Router); -#endif + if (err != CHIP_NO_ERROR) { LOG_ERR("ConnectivityMgr().SetThreadDeviceType() failed"); @@ -170,7 +166,6 @@ CHIP_ERROR AppTask::Init() // Initialize CHIP server SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); - chip::app::DnssdServer::Instance().SetExtendedDiscoveryTimeoutSecs(kExtDiscoveryTimeoutSecs); static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); diff --git a/examples/lighting-app/nxp/k32w/k32w0/README.md b/examples/lighting-app/nxp/k32w/k32w0/README.md index 0667e6ea940b7f..51385c7d0edba2 100644 --- a/examples/lighting-app/nxp/k32w/k32w0/README.md +++ b/examples/lighting-app/nxp/k32w/k32w0/README.md @@ -27,9 +27,16 @@ network. - [Detokenizer script](#detokenizer) - [Notes](#detokenizer-notes) - [Known issues](#detokenizer-known-issues) -- [OTA](#ota) - [Writing the SSBL](#ssbl) - [Writing the PSECT](#psect) - - [Writing the application](#appwrite) - [OTA Testing](#otatesting) - - [Known issues](#otaissues) +- [Tinycrypt ECC operations](#tinycrypt) + - [Building steps](#tinycrypt-building-steps) +- [OTA](#ota) + + - [Writing the SSBL](#ssbl) + - [Writing the PSECT](#psect) + - [Writing the application](#appwrite) + - [OTA Testing](#otatesting) + - [Known issues](#otaissues) + @@ -182,18 +189,17 @@ user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_K32W061_SDK_ROOT=/home/use user@ubuntu:~/Desktop/git/connectedhomeip$ ./third_party/nxp/k32w0_sdk/sdk_fixes/patch_k32w_sdk.sh user@ubuntu:~/Desktop/git/connectedhomeip$ source ./scripts/activate.sh user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/lighting-app/nxp/k32w/k32w0 -user@ubuntu:~/Desktop/git/connectedhomeip/examples/lighting-app/nxp/k32w/k32w0$ gn gen out/debug --args="k32w0_sdk_root=\"${NXP_K32W061_SDK_ROOT}\" chip_with_OM15082=1 chip_with_ot_cli=0 is_debug=false chip_crypto=\"mbedtls\" chip_with_se05x=0" +user@ubuntu:~/Desktop/git/connectedhomeip/examples/lighting-app/nxp/k32w/k32w0$ gn gen out/debug --args="k32w0_sdk_root=\"${NXP_K32W061_SDK_ROOT}\" chip_with_OM15082=1 chip_with_ot_cli=0 is_debug=false chip_crypto=\"mbedtls\" chip_with_se05x=0 mbedtls_use_tinycrypt=true chip_pw_tokenizer_logging=true mbedtls_repo=\"//third_party/connectedhomeip/third_party/nxp/libs/mbedtls\"" user@ubuntu:~/Desktop/git/connectedhomeip/examples/lighting-app/nxp/k32w/k32w0$ ninja -C out/debug user@ubuntu:~/Desktop/git/connectedhomeip/examples/lighting-app/nxp/k32w/k32w0$ $NXP_K32W061_SDK_ROOT/tools/imagetool/sign_images.sh out/debug/ ``` - with Secure element Exactly the same steps as above but set chip_with_se05x=1 in the gn command - and add arguments chip_pw_tokenizer_logging=true chip_enable_ota_requestor=false + and add argument chip_enable_ota_requestor=false -Note that options chip_pw_tokenizer_logging=true and -chip_enable_ota_requestor=false are required for building with Secure Element. -These can be changed if building without Secure Element +Note that option chip_enable_ota_requestor=false are required for building with +Secure Element. These can be changed if building without Secure Element Note that "patch_k32w_sdk.sh" script must be run for patching the K32W061 SDK 2.6.4. @@ -299,6 +305,25 @@ If run, closed and rerun with the serial option on the same serial port, the detokenization script will get stuck and not show any logs. The solution is to unplug and plug the board and then rerun the script. + + +## Tinycrypt ECC operations + + + +### Building steps + +Note: This solution is temporary. + +In order to use the tinycrypt ecc operations, use the following build arguments: + +- Build without Secure element (_chip_with_se05x=0_), with tinycrypt enabled + (_mbedtls_use_tinycrypt=true_) and with the `NXPmicro/mbedtls` library + (_mbedtls_repo=`\"//third_party/connectedhomeip/third_party/nxp/libs/mbedtls\"`_). + +To disable tinycrypt ecc operations, simply build without +_mbedtls_use_tinycrypt=true_ and without _mbedtls_repo_. + ## OTA diff --git a/examples/lighting-app/p6/BUILD.gn b/examples/lighting-app/p6/BUILD.gn index 6af9db2bffd8b8..fddb3e14405e60 100644 --- a/examples/lighting-app/p6/BUILD.gn +++ b/examples/lighting-app/p6/BUILD.gn @@ -17,6 +17,7 @@ import("//build_overrides/chip.gni") import("//build_overrides/p6.gni") import("${build_root}/config/defaults.gni") +import("${chip_root}/src/platform/device.gni") import("${p6_sdk_build_root}/p6_executable.gni") import("${p6_sdk_build_root}/p6_sdk.gni") @@ -34,6 +35,50 @@ declare_args() { # Monitor & log memory usage at runtime. enable_heap_monitoring = false + + # Build update app + build_update_image = false +} + +config("p6_ota_config") { + ldflags = [ "-T/" + rebase_path( + "${chip_root}/third_party/p6/p6_sdk/ota/cy8c6xxa_cm4_dual_ota_int.ld", + "/", + "${p6_project_dir}") ] + + ldflags += [ "-Wl,--defsym,MCUBOOT_HEADER_SIZE=0x400,--defsym,MCUBOOT_BOOTLOADER_SIZE=0x18000,--defsym,CY_BOOT_PRIMARY_1_SIZE=0x1C0000" ] + + defines = [ + "P6_OTA", + "OTA_SUPPORT ", + "OTA_USE_EXTERNAL_FLASH", + "CY_BOOT_USE_EXTERNAL_FLASH", + "MCUBOOT_HEADER_SIZE=0x400", + "MCUBOOT_MAX_IMG_SECTORS=3584", + "CY_BOOT_SCRATCH_SIZE=0x00004000", + "MCUBOOT_BOOTLOADER_SIZE=0x00018000", + "CY_BOOT_BOOTLOADER_SIZE=0x00018000", + "CY_BOOT_PRIMARY_1_START=0x00018000", + "CY_BOOT_PRIMARY_1_SIZE=0x1C0000", + "CY_BOOT_SECONDARY_1_START=0x00000000", + "CY_BOOT_SECONDARY_1_SIZE=0x001C0000", + "CY_FLASH_ERASE_VALUE=0xFF", + "MCUBOOT_IMAGE_NUMBER=1", + "MCUBOOT_SLOT_SIZE=0x1C0000", + "MCUBOOT_SCRATCH_SIZE=0x4000", + "MCUBOOT_SECTOR_SIZE = 512", + "APP_VERSION_MAJOR=1", + "APP_VERSION_MINOR=0", + "APP_VERSION_BUILD=0", + "MCUBOOT_OVERWRITE_ONLY", + "CY_ENABLE_XIP_PROGRAM", + ] + + if (build_update_image) { + defines += [ "CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION=2" ] + } else { + defines += [ "CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION=1" ] + } } p6_sdk_sources("lighting_app_sdk_sources") { @@ -50,8 +95,28 @@ p6_sdk_sources("lighting_app_sdk_sources") { ] sources = [ "${p6_project_dir}/include/CHIPProjectConfig.h" ] - public_configs = [ "${chip_root}/third_party/p6:p6_sdk_config" ] + + if (chip_enable_ota_requestor) { + sources += [ + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/bootutil/src/bootutil_misc.c", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/cy_flash_map.c", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/cy_flash_psoc6.c", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/cy_smif_psoc6.c", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/mem_config/mem_config_sfdp.c", + ] + include_dirs += [ + "${chip_root}/third_party/p6/p6_sdk/ota/config", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/mem_config/", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/include/", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/include/flash_map_backend/", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/sysflash/", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/bootutil/include", + ] + public_configs += [ ":p6_ota_config" ] + } } p6_executable("lighting_app") { diff --git a/examples/lighting-app/p6/README.md b/examples/lighting-app/p6/README.md index c7327703c346fb..45d536e0cc40a7 100644 --- a/examples/lighting-app/p6/README.md +++ b/examples/lighting-app/p6/README.md @@ -13,6 +13,7 @@ An example showing the use of Matter on the Infineon CY8CKIT-062S2-43012 board. - [Commissioning over BLE](#commissioning-over-ble) - [Notes](#notes) - [Cluster control](#cluster-control) + - [OTA Software Update](#ota-software-update)
@@ -134,3 +135,9 @@ commands. These power cycle the BlueTooth hardware and disable BR/EDR mode. Press `USER_BTN1` on the board to toggle between Light ON and OFF states. Light ON and OFF can be observed with 'LED9' on the board. This LED is configured with `LIGHT_LED` in `include/AppConfig.h`. + +## OTA Software Update + +For the description of Software Update process with infineon P6 example +applications see +[Infineon P6 OTA Software Update](../../../docs/guides/infineon_p6_software_update.md) diff --git a/examples/lighting-app/p6/include/AppTask.h b/examples/lighting-app/p6/include/AppTask.h index cf8feffb2c7f08..54345a456d3beb 100644 --- a/examples/lighting-app/p6/include/AppTask.h +++ b/examples/lighting-app/p6/include/AppTask.h @@ -49,6 +49,7 @@ class AppTask void PostEvent(const AppEvent * event); void ButtonEventHandler(uint8_t btnIdx, uint8_t btnAction); + void InitOTARequestor(); private: friend AppTask & GetAppTask(void); diff --git a/examples/lighting-app/p6/include/CHIPProjectConfig.h b/examples/lighting-app/p6/include/CHIPProjectConfig.h index 9e3dca035ea178..885a051297072e 100644 --- a/examples/lighting-app/p6/include/CHIPProjectConfig.h +++ b/examples/lighting-app/p6/include/CHIPProjectConfig.h @@ -66,14 +66,14 @@ #define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_REVISION 1 /** - * CHIP_DEVICE_CONFIG_DEVICE_FIRMWARE_REVISION_STRING + * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING * - * A string identifying the firmware revision running on the device. - * CHIP service currently expects the firmware version to be in the format + * A string identifying the software version running on the device. + * CHIP service currently expects the software version to be in the format * {MAJOR_VERSION}.0d{MINOR_VERSION} */ -#ifndef CHIP_DEVICE_CONFIG_DEVICE_FIRMWARE_REVISION_STRING -#define CHIP_DEVICE_CONFIG_DEVICE_FIRMWARE_REVISION_STRING "0.1ALPHA" +#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING +#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING "0.1ALPHA" #endif /** * CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE diff --git a/examples/lighting-app/p6/ota_base_build.sh b/examples/lighting-app/p6/ota_base_build.sh new file mode 100755 index 00000000000000..5cdaf4d274d11c --- /dev/null +++ b/examples/lighting-app/p6/ota_base_build.sh @@ -0,0 +1,8 @@ +OUT_DIR=out/lighting-app/ +ANYCLOUD_DIR=third_party/p6/p6_sdk/libs/anycloud-ota/ + +scripts/examples/gn_p6_example.sh examples/lighting-app/p6 "$OUT_DIR" chip_enable_ota_requestor=true + +mv "$OUT_DIR"/chip-p6-lighting-example.hex "$OUT_DIR"/chip-p6-lighting-example.unsigned.hex + +./"$ANYCLOUD_DIR"/scripts/sign_script.bash "$OUT_DIR"/ chip-p6-lighting-example python3 arm-none-eabi-objcopy "-O ihex" "" "$ANYCLOUD_DIR"/source/mcuboot/scripts/ imgtool_v1.7.0/imgtool.py create 0xFF 0x400 3584 1.0.0 0x00018000 0x001C0000 arm-none-eabi-objcopy "" diff --git a/examples/lighting-app/p6/ota_update_build.sh b/examples/lighting-app/p6/ota_update_build.sh new file mode 100755 index 00000000000000..1c5c301429b5e0 --- /dev/null +++ b/examples/lighting-app/p6/ota_update_build.sh @@ -0,0 +1,14 @@ +OUT_DIR=out/lighting-app-ota +ANYCLOUD_DIR=third_party/p6/p6_sdk/libs/anycloud-ota/ + +./scripts/examples/gn_p6_example.sh examples/lighting-app/p6 "$OUT_DIR" chip_enable_ota_requestor=true build_update_image=true + +mv "$OUT_DIR"/chip-p6-lighting-example.hex "$OUT_DIR"/chip-p6-lighting-example.unsigned.hex + +./"$ANYCLOUD_DIR"/scripts/sign_script.bash "$OUT_DIR"/ chip-p6-lighting-example python3 arm-none-eabi-objcopy "-O ihex" "" "$ANYCLOUD_DIR"/source/mcuboot/scripts/ imgtool_v1.7.0/imgtool.py sign 0xFF 0x400 3584 1.0.0 0x00018000 0x001C0000 arm-none-eabi-objcopy "-k $ANYCLOUD_DIR/source/mcuboot/keys/cypress-test-ec-p256.pem" + +if [ -f "$OUT_DIR"/chip-p6-lighting-example.ota ]; then + rm "$OUT_DIR"/chip-p6-lighting-example.ota +fi + +src/app/ota_image_tool.py create -v 0xFFF1 -p 0x8000 -vn 2 -vs "2.0" -da sha256 "$OUT_DIR"/chip-p6-lighting-example.bin "$OUT_DIR"/chip-p6-lighting-example.ota diff --git a/examples/lighting-app/p6/src/AppTask.cpp b/examples/lighting-app/p6/src/AppTask.cpp index 55e2aa3ee9cd29..7bbcf55019a710 100644 --- a/examples/lighting-app/p6/src/AppTask.cpp +++ b/examples/lighting-app/p6/src/AppTask.cpp @@ -41,6 +41,33 @@ #include #include +/* OTA related includes */ +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR +#include +#include +#include +#include +#include +extern "C" { +#include "cy_smif_psoc6.h" +} +using chip::BDXDownloader; +using chip::CharSpan; +using chip::DefaultOTARequestor; +using chip::FabricIndex; +using chip::GetRequestorInstance; +using chip::NodeId; +using chip::OTADownloader; +using chip::OTAImageProcessorImpl; +using chip::System::Layer; + +using namespace ::chip; +using namespace chip::TLV; +using namespace ::chip::Credentials; +using namespace ::chip::DeviceLayer; +using namespace ::chip::System; + +#endif #define FACTORY_RESET_TRIGGER_TIMEOUT 3000 #define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 3000 #define APP_TASK_STACK_SIZE (4096) @@ -66,6 +93,15 @@ StaticQueue_t sAppEventQueueStruct; StackType_t appStack[APP_TASK_STACK_SIZE / sizeof(StackType_t)]; StaticTask_t appTaskStruct; + +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR +DefaultOTARequestor gRequestorCore; +DefaultOTARequestorStorage gRequestorStorage; +DefaultOTARequestorDriver gRequestorUser; +BDXDownloader gDownloader; +OTAImageProcessorImpl gImageProcessor; +#endif + } // namespace using namespace ::chip; @@ -94,6 +130,9 @@ static void InitServer(intptr_t context) // Initialize device attestation config SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR + GetAppTask().InitOTARequestor(); +#endif } CHIP_ERROR AppTask::StartAppTask() @@ -113,7 +152,14 @@ CHIP_ERROR AppTask::StartAppTask() CHIP_ERROR AppTask::Init() { CHIP_ERROR err = CHIP_NO_ERROR; - +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR + int rc = boot_set_confirmed(); + if (rc != 0) + { + P6_LOG("boot_set_confirmed failed"); + appError(CHIP_ERROR_WELL_UNINITIALIZED); + } +#endif // Register the callback to init the MDNS server when connectivity is available PlatformMgr().AddEventHandler( [](const ChipDeviceEvent * event, intptr_t arg) { @@ -147,7 +193,7 @@ CHIP_ERROR AppTask::Init() appError(APP_ERROR_CREATE_TIMER_FAILED); } NetWorkCommissioningInstInit(); - P6_LOG("Current Firmware Version: %s", CHIP_DEVICE_CONFIG_DEVICE_FIRMWARE_REVISION_STRING); + P6_LOG("Current Firmware Version: %s", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING); err = LightMgr().Init(); if (err != CHIP_NO_ERROR) { @@ -523,3 +569,38 @@ void AppTask::UpdateClusterState(intptr_t context) P6_LOG("ERR: updating on/off %x", status); } } +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR +void AppTask::InitOTARequestor() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + SetRequestorInstance(&gRequestorCore); + gRequestorStorage.Init(chip::Server::GetInstance().GetPersistentStorage()); + gRequestorCore.Init(chip::Server::GetInstance(), gRequestorStorage, gRequestorUser, gDownloader); + gImageProcessor.SetOTADownloader(&gDownloader); + gDownloader.SetImageProcessorDelegate(&gImageProcessor); + gRequestorUser.Init(&gRequestorCore, &gImageProcessor); + + uint32_t savedSoftwareVersion; + err = ConfigurationMgr().GetSoftwareVersion(savedSoftwareVersion); + if (err != CHIP_NO_ERROR) + { + P6_LOG("Can't get saved software version"); + appError(err); + } + + if (savedSoftwareVersion != CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION) + { + ConfigurationMgr().StoreSoftwareVersion(CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION); + + P6_LOG("Confirming update to version: %u", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION); + chip::OTARequestorInterface * requestor = chip::GetRequestorInstance(); + if (requestor != nullptr) + { + requestor->NotifyUpdateApplied(); + } + } + + P6_LOG("Current Software Version: %u", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION); + P6_LOG("Current Firmware Version String: %s", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING); +} +#endif diff --git a/examples/lighting-app/p6/src/main.cpp b/examples/lighting-app/p6/src/main.cpp index a38d25811c2e1e..8e4105b8f79356 100644 --- a/examples/lighting-app/p6/src/main.cpp +++ b/examples/lighting-app/p6/src/main.cpp @@ -34,6 +34,7 @@ #include #include "AppConfig.h" +#include "cyhal_wdt.h" #include "init_p6Platform.h" #include @@ -98,7 +99,14 @@ static void main_task(void * pvParameters) P6_LOG("PlatformMgr().InitChipStack() failed"); appError(ret); } - chip::DeviceLayer::ConnectivityMgr().SetBLEDeviceName("P6_LIGHT"); + + ret = chip::DeviceLayer::ConnectivityMgr().SetBLEDeviceName("P6_LIGHT"); + if (ret != CHIP_NO_ERROR) + { + P6_LOG("ConnectivityMgr().SetBLEDeviceName() failed"); + appError(ret); + } + P6_LOG("Starting Platform Manager Event Loop"); ret = PlatformMgr().StartEventLoopTask(); if (ret != CHIP_NO_ERROR) @@ -123,7 +131,12 @@ static void main_task(void * pvParameters) int main(void) { init_p6Platform(); - +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR + // Clear watchdog timer (started by bootloader) so that it doesn't trigger a reset + cyhal_wdt_t wdt_obj; + cyhal_wdt_init(&wdt_obj, cyhal_wdt_get_max_timeout_ms()); + cyhal_wdt_free(&wdt_obj); +#endif #ifdef HEAP_MONITORING MemMonitoring::startHeapMonitoring(); #endif diff --git a/examples/lighting-app/qpg/args.gni b/examples/lighting-app/qpg/args.gni index 90189de5731270..3e533b2a6f1751 100644 --- a/examples/lighting-app/qpg/args.gni +++ b/examples/lighting-app/qpg/args.gni @@ -26,4 +26,4 @@ chip_openthread_ftd = true chip_stack_lock_tracking = "none" pw_log_BACKEND = "${chip_root}/src/lib/support/pw_log_chip" -pw_assert_BACKEND = "$dir_pw_assert_log" +pw_assert_BACKEND = "$dir_pw_assert_log:check_backend" diff --git a/examples/lighting-app/telink/CMakeLists.txt b/examples/lighting-app/telink/CMakeLists.txt index 8a0e97020e68fb..bea297558d59f5 100644 --- a/examples/lighting-app/telink/CMakeLists.txt +++ b/examples/lighting-app/telink/CMakeLists.txt @@ -65,7 +65,6 @@ target_sources(app PRIVATE ${CHIP_ROOT}/src/app/util/attribute-storage.cpp ${CHIP_ROOT}/src/app/util/attribute-table.cpp ${CHIP_ROOT}/src/app/util/binding-table.cpp - ${CHIP_ROOT}/src/app/util/client-api.cpp ${CHIP_ROOT}/src/app/util/ember-compatibility-functions.cpp ${CHIP_ROOT}/src/app/util/ember-print.cpp ${CHIP_ROOT}/src/app/util/error-mapping.cpp diff --git a/examples/lighting-app/tizen/README.md b/examples/lighting-app/tizen/README.md index f2707b0e3f318f..4b9eea699f8d9c 100644 --- a/examples/lighting-app/tizen/README.md +++ b/examples/lighting-app/tizen/README.md @@ -12,11 +12,11 @@ Generating tizen-arm-light ```sh gn gen --check \ - --fail-on-unused-args \ - --export-compile-commands \ - --root=$PW_PROJECT_ROOT/examples/lighting-app/tizen \ - "--args=target_os=\"tizen\" target_cpu=\"arm\" tizen_sdk_root=\"$TIZEN_SDK_ROOT\" tizen_sdk_sysroot=\"$TIZEN_SDK_SYSROOT\"" \ - $PW_PROJECT_ROOT/out/tizen-arm-light + --fail-on-unused-args \ + --export-compile-commands \ + --root=$PW_PROJECT_ROOT/examples/lighting-app/tizen \ + "--args=target_os=\"tizen\" target_cpu=\"arm\" tizen_sdk_root=\"$TIZEN_SDK_ROOT\" tizen_sdk_sysroot=\"$TIZEN_SDK_SYSROOT\"" \ + $PW_PROJECT_ROOT/out/tizen-arm-light ``` Building tizen-arm-light @@ -33,16 +33,16 @@ author data as needed. ```sh $TIZEN_SDK_ROOT/tools/ide/bin/tizen certificate \ - --alias=CHIP \ - --name=CHIP \ - --email=chip@tizen.org \ - --password=chiptizen + --alias=CHIP \ + --name=CHIP \ + --email=chip@tizen.org \ + --password=chiptizen $TIZEN_SDK_ROOT/tools/ide/bin/tizen security-profiles add \ - --active \ - --name=CHIP \ - --author=$HOME/tizen-sdk-data/keystore/author/author.p12 \ - --password=chiptizen + --active \ + --name=CHIP \ + --author=$HOME/tizen-sdk-data/keystore/author/author.p12 \ + --password=chiptizen ``` This is only _one-time action_. To regenerate the author certificate and @@ -51,9 +51,9 @@ specified commands: ```sh rm -r \ - $HOME/tizen-sdk-data \ - $HOME/.tizen-cli-config \ - $HOME/.secretsdb + $HOME/tizen-sdk-data \ + $HOME/.tizen-cli-config \ + $HOME/.secretsdb ``` After that, normally call scripts to generate the author certificate and @@ -97,3 +97,50 @@ e.g.: ```sh app_launcher --start=org.tizen.matter.example.lighting discriminator 43 wifi true ``` + +## Vscode support + +To run all commands below `sdb` has to be installed on computer and available in +`PATH`. Also vscode has to have the `augustocdias.tasks-shell-input` extension +installed. + +### Tasks + +1. Build app: + +``` +open the Command Palette (Ctrl+Shift+P) -> + Tasks: Run Task -> + Build LightingApp (Tizen) +``` + +2. SDB connect to device: required to run Tizen commands below if device is + debugged over network + +``` +open the Command Palette (Ctrl+Shift+P) -> + Tasks: Run Task -> Connect to device (Tizen) -> + insert IP address and port +``` + +3. Install app: it is separated from build app step. + +``` +open the Command Palette (Ctrl+Shift+P) -> + Tasks: Run Task -> + Install LightingApp (Tizen) +``` + +4. Launch LightingApp with gdbserver attached: require to install app + previously. + +``` +open the Command Palette (Ctrl+Shift+P) -> + Tasks: Run Task -> + Launch LightingApp with gdbserver attached (Tizen) +``` + +### Debug + +To debug app using vscode gdbserver has to be available on the target device, +run `./scripts/helpers/tizen_gdbserver_run.sh --help` for more information. diff --git a/examples/lock-app/cyw30739/BUILD.gn b/examples/lock-app/cyw30739/BUILD.gn index 3a2b458a3a9e07..87f0e15e92bff3 100644 --- a/examples/lock-app/cyw30739/BUILD.gn +++ b/examples/lock-app/cyw30739/BUILD.gn @@ -55,6 +55,7 @@ cyw30739_executable("lock_app") { deps = [ ":sdk", "${chip_root}/examples/lock-app/lock-common", + "${chip_root}/examples/providers:device_info_provider", "${chip_root}/examples/shell/shell_common:shell_common", "${chip_root}/src/lib", ] diff --git a/examples/lock-app/cyw30739/src/main.cpp b/examples/lock-app/cyw30739/src/main.cpp index 47abd1b802bc3e..61ec55e3ef35a3 100644 --- a/examples/lock-app/cyw30739/src/main.cpp +++ b/examples/lock-app/cyw30739/src/main.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -53,6 +54,7 @@ using namespace ::chip::Shell; wiced_bool_t syncClusterToButtonAction = false; +static chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider; static void InitApp(intptr_t args); static void EventHandler(const ChipDeviceEvent * event, intptr_t arg); static void HandleThreadStateChangeEvent(const ChipDeviceEvent * event); @@ -169,6 +171,8 @@ void InitApp(intptr_t args) chip::Server::GetInstance().Init(initParams); SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); + gExampleDeviceInfoProvider.SetStorageDelegate(&chip::Server::GetInstance().GetPersistentStorage()); + chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); // Initial lock state chip::app::DataModel::Nullable state; diff --git a/examples/lock-app/efr32/args.gni b/examples/lock-app/efr32/args.gni index 66670784404334..b4a0322c442f40 100644 --- a/examples/lock-app/efr32/args.gni +++ b/examples/lock-app/efr32/args.gni @@ -22,5 +22,5 @@ chip_enable_ota_requestor = true chip_enable_openthread = true pw_log_BACKEND = "${chip_root}/src/lib/support/pw_log_chip" -pw_assert_BACKEND = "$dir_pw_assert_log" +pw_assert_BACKEND = "$dir_pw_assert_log:check_backend" pw_rpc_CONFIG = "$dir_pw_rpc:disable_global_mutex" diff --git a/examples/lock-app/efr32/build_for_wifi_args.gni b/examples/lock-app/efr32/build_for_wifi_args.gni index bf21912871e59d..4a3bdfd804ae19 100644 --- a/examples/lock-app/efr32/build_for_wifi_args.gni +++ b/examples/lock-app/efr32/build_for_wifi_args.gni @@ -21,4 +21,4 @@ import("${chip_root}/src/platform/EFR32/wifi_args.gni") chip_enable_ota_requestor = true pw_log_BACKEND = "${chip_root}/src/lib/support/pw_log_chip" -pw_assert_BACKEND = "$dir_pw_assert_log" +pw_assert_BACKEND = "$dir_pw_assert_log:check_backend" diff --git a/examples/lock-app/esp32/CMakeLists.txt b/examples/lock-app/esp32/CMakeLists.txt index 3bcab4dbab199e..63ac7259d0d397 100644 --- a/examples/lock-app/esp32/CMakeLists.txt +++ b/examples/lock-app/esp32/CMakeLists.txt @@ -45,7 +45,8 @@ include(third_party/connectedhomeip/third_party/pigweed/repo/pw_build/pigweed.cm pw_set_module_config(pw_rpc_CONFIG pw_rpc.disable_global_mutex_config) pw_set_backend(pw_log pw_log_basic) -pw_set_backend(pw_assert pw_assert_log) +pw_set_backend(pw_assert.check pw_assert_log.check_backend) +pw_set_backend(pw_assert.assert pw_assert.assert_compatibility_backend) pw_set_backend(pw_sys_io pw_sys_io.esp32) add_subdirectory(third_party/connectedhomeip/third_party/pigweed/repo) diff --git a/examples/lock-app/esp32/main/CMakeLists.txt b/examples/lock-app/esp32/main/CMakeLists.txt index 2b1b8a46ce7aef..24fa3cc6ed70c7 100644 --- a/examples/lock-app/esp32/main/CMakeLists.txt +++ b/examples/lock-app/esp32/main/CMakeLists.txt @@ -81,7 +81,7 @@ pw_proto_library(descriptor_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(device_service @@ -94,7 +94,7 @@ pw_proto_library(device_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(button_service @@ -105,7 +105,7 @@ pw_proto_library(button_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(locking_service @@ -116,7 +116,7 @@ pw_proto_library(locking_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) target_link_libraries(${COMPONENT_LIB} PUBLIC diff --git a/examples/lock-app/lock-common/lock-app.matter b/examples/lock-app/lock-common/lock-app.matter index 5cd6c2ca19741e..d5bd0bf37b4c5f 100644 --- a/examples/lock-app/lock-common/lock-app.matter +++ b/examples/lock-app/lock-common/lock-app.matter @@ -822,6 +822,7 @@ server cluster GeneralCommissioning = 48 { struct BasicCommissioningInfo { int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; } attribute access(write: administer) int64u breadcrumb = 0; diff --git a/examples/lock-app/nrfconnect/README.md b/examples/lock-app/nrfconnect/README.md index ee46aab4ee2560..c1e2a2baf7e065 100644 --- a/examples/lock-app/nrfconnect/README.md +++ b/examples/lock-app/nrfconnect/README.md @@ -16,7 +16,8 @@ Semiconductor's nRF Connect SDK, and supports remote access and control of a simulated door lock over a low-power, 802.15.4 Thread network. The example behaves as a Matter accessory, that is a device that can be paired -into an existing Matter network and can be controlled by this network. +into an existing Matter network and can be controlled by this network. The +device works as a Thread Sleepy End Device.
@@ -381,22 +382,6 @@ features like logs and command-line interface, run the following command: Remember to replace _build-target_ with the build target name of the Nordic Semiconductor's kit you own. -### Building with low-power configuration - -You can build the example using the low-power configuration, which enables -Thread's Sleepy End Device mode and disables debug features, such as the UART -console or the **LED 1** usage. - -To build for the low-power configuration, run the following command with -_build-target_ replaced with the build target name of the Nordic Semiconductor's -kit you own (for example `nrf52840dk_nrf52840`): - - $ west build -b build-target -- -DOVERLAY_CONFIG=overlay-low_power.conf - -For example, use the following command for `nrf52840dk_nrf52840`: - - $ west build -b nrf52840dk_nrf52840 -- -DOVERLAY_CONFIG=overlay-low_power.conf - ### Building with Device Firmware Upgrade support Support for DFU using Matter OTA is enabled by default. diff --git a/examples/lock-app/nrfconnect/main/AppTask.cpp b/examples/lock-app/nrfconnect/main/AppTask.cpp index 5917cfe34a8d95..d1b1e2266810a6 100644 --- a/examples/lock-app/nrfconnect/main/AppTask.cpp +++ b/examples/lock-app/nrfconnect/main/AppTask.cpp @@ -107,10 +107,8 @@ CHIP_ERROR AppTask::Init() #ifdef CONFIG_OPENTHREAD_MTD_SED err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_SleepyEndDevice); -#elif CONFIG_OPENTHREAD_MTD - err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_MinimalEndDevice); #else - err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_Router); + err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_MinimalEndDevice); #endif if (err != CHIP_NO_ERROR) { @@ -168,6 +166,9 @@ CHIP_ERROR AppTask::Init() // between the main and the CHIP threads. PlatformMgr().AddEventHandler(ChipEventHandler, 0); + // Disable auto-relock time feature. + DoorLockServer::Instance().SetAutoRelockTime(kLockEndpointId, 0); + err = PlatformMgr().StartEventLoopTask(); if (err != CHIP_NO_ERROR) { @@ -533,27 +534,38 @@ void AppTask::DispatchEvent(AppEvent * aEvent) void AppTask::UpdateClusterState(BoltLockManager::State state, BoltLockManager::OperationSource source) { - DlLockState lockState; + DlLockState newLockState; switch (state) { case BoltLockManager::State::kLockingCompleted: - lockState = DlLockState::kLocked; + newLockState = DlLockState::kLocked; break; case BoltLockManager::State::kUnlockingCompleted: - lockState = DlLockState::kUnlocked; + newLockState = DlLockState::kUnlocked; break; default: - lockState = DlLockState::kNotFullyLocked; + newLockState = DlLockState::kNotFullyLocked; break; } - SystemLayer().ScheduleLambda([lockState, source] { - LOG_INF("Updating LockState attribute"); + SystemLayer().ScheduleLambda([newLockState, source] { + chip::app::DataModel::Nullable currentLockState; + chip::app::Clusters::DoorLock::Attributes::LockState::Get(kLockEndpointId, currentLockState); - if (!DoorLockServer::Instance().SetLockState(kLockEndpointId, lockState, source)) + if (currentLockState.IsNull()) + { + // Initialize lock state with start value, but not invoke lock/unlock. + chip::app::Clusters::DoorLock::Attributes::LockState::Set(kLockEndpointId, newLockState); + } + else { - LOG_ERR("Failed to update LockState attribute"); + LOG_INF("Updating LockState attribute"); + + if (!DoorLockServer::Instance().SetLockState(kLockEndpointId, newLockState, source)) + { + LOG_ERR("Failed to update LockState attribute"); + } } }); } diff --git a/examples/lock-app/nrfconnect/main/include/CHIPProjectConfig.h b/examples/lock-app/nrfconnect/main/include/CHIPProjectConfig.h index bfa54151bad46d..7f6a313e145f87 100644 --- a/examples/lock-app/nrfconnect/main/include/CHIPProjectConfig.h +++ b/examples/lock-app/nrfconnect/main/include/CHIPProjectConfig.h @@ -30,5 +30,3 @@ // Use a default pairing code if one hasn't been provisioned in flash. #define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021 #define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 - -#define CHIP_DEVICE_CONFIG_SED_IDLE_INTERVAL 20000_ms32 diff --git a/examples/lock-app/nrfconnect/overlay-low_power.conf b/examples/lock-app/nrfconnect/overlay-low_power.conf deleted file mode 100644 index c75bcf53951546..00000000000000 --- a/examples/lock-app/nrfconnect/overlay-low_power.conf +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2021 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. -# - -# Enable MTD Sleepy End Device -CONFIG_CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT=y - -# Disable UART console -CONFIG_SHELL=n -CONFIG_LOG=n -CONFIG_UART_CONSOLE=n -CONFIG_SERIAL=n - -# Suspend devices when the CPU goes to sleep -CONFIG_PM_DEVICE=y - -# Disable auxiliary state LEDs -CONFIG_STATE_LEDS=n diff --git a/examples/lock-app/nrfconnect/prj.conf b/examples/lock-app/nrfconnect/prj.conf index a74e2e254f7303..e42060f48b5639 100644 --- a/examples/lock-app/nrfconnect/prj.conf +++ b/examples/lock-app/nrfconnect/prj.conf @@ -29,6 +29,7 @@ CONFIG_OPENTHREAD_THREAD_VERSION_1_2=y CONFIG_OPENTHREAD_NORDIC_LIBRARY_MTD=y CONFIG_OPENTHREAD_MTD=y CONFIG_OPENTHREAD_FTD=n +CONFIG_CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT=y # Default OpenThread network settings CONFIG_OPENTHREAD_PANID=4660 diff --git a/examples/lock-app/nrfconnect/prj_no_dfu.conf b/examples/lock-app/nrfconnect/prj_no_dfu.conf index 82431c05977810..bd48ff463ddd8a 100644 --- a/examples/lock-app/nrfconnect/prj_no_dfu.conf +++ b/examples/lock-app/nrfconnect/prj_no_dfu.conf @@ -29,6 +29,7 @@ CONFIG_OPENTHREAD_THREAD_VERSION_1_2=y CONFIG_OPENTHREAD_NORDIC_LIBRARY_MTD=y CONFIG_OPENTHREAD_MTD=y CONFIG_OPENTHREAD_FTD=n +CONFIG_CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT=y # Default OpenThread network settings CONFIG_OPENTHREAD_PANID=4660 diff --git a/examples/lock-app/nrfconnect/prj_release.conf b/examples/lock-app/nrfconnect/prj_release.conf index 93d253d3955324..7b1aae9180179f 100644 --- a/examples/lock-app/nrfconnect/prj_release.conf +++ b/examples/lock-app/nrfconnect/prj_release.conf @@ -29,6 +29,7 @@ CONFIG_OPENTHREAD_THREAD_VERSION_1_2=y CONFIG_OPENTHREAD_NORDIC_LIBRARY_MTD=y CONFIG_OPENTHREAD_MTD=y CONFIG_OPENTHREAD_FTD=n +CONFIG_CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT=y # Default OpenThread network settings CONFIG_OPENTHREAD_PANID=4660 @@ -47,6 +48,9 @@ CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" # 32774 == 0x8006 (example lock-app) CONFIG_CHIP_DEVICE_PRODUCT_ID=32774 +# Suspend devices when the CPU goes into sleep +CONFIG_PM_DEVICE=y + # Disable all debug features CONFIG_SHELL=n CONFIG_OPENTHREAD_SHELL=n diff --git a/examples/lock-app/p6/BUILD.gn b/examples/lock-app/p6/BUILD.gn index fe3caebba8fc3e..f7eb7fb05fe233 100644 --- a/examples/lock-app/p6/BUILD.gn +++ b/examples/lock-app/p6/BUILD.gn @@ -17,6 +17,7 @@ import("//build_overrides/chip.gni") import("//build_overrides/p6.gni") import("${build_root}/config/defaults.gni") +import("${chip_root}/src/platform/device.gni") import("${p6_sdk_build_root}/p6_executable.gni") import("${p6_sdk_build_root}/p6_sdk.gni") @@ -31,8 +32,51 @@ declare_args() { # PIN code for PASE session establishment. setup_pin_code = 20202021 + + # Build update app + build_update_image = false } +config("p6_ota_config") { + ldflags = [ "-T/" + rebase_path( + "${chip_root}/third_party/p6/p6_sdk/ota/cy8c6xxa_cm4_dual_ota_int.ld", + "/", + "${p6_project_dir}") ] + + ldflags += [ "-Wl,--defsym,MCUBOOT_HEADER_SIZE=0x400,--defsym,MCUBOOT_BOOTLOADER_SIZE=0x18000,--defsym,CY_BOOT_PRIMARY_1_SIZE=0x1C0000" ] + + defines = [ + "P6_OTA", + "OTA_SUPPORT ", + "OTA_USE_EXTERNAL_FLASH", + "CY_BOOT_USE_EXTERNAL_FLASH", + "MCUBOOT_HEADER_SIZE=0x400", + "MCUBOOT_MAX_IMG_SECTORS=3584", + "CY_BOOT_SCRATCH_SIZE=0x00004000", + "MCUBOOT_BOOTLOADER_SIZE=0x00018000", + "CY_BOOT_BOOTLOADER_SIZE=0x00018000", + "CY_BOOT_PRIMARY_1_START=0x00018000", + "CY_BOOT_PRIMARY_1_SIZE=0x1C0000", + "CY_BOOT_SECONDARY_1_START=0x00000000", + "CY_BOOT_SECONDARY_1_SIZE=0x001C0000", + "CY_FLASH_ERASE_VALUE=0xFF", + "MCUBOOT_IMAGE_NUMBER=1", + "MCUBOOT_SLOT_SIZE=0x1C0000", + "MCUBOOT_SCRATCH_SIZE=0x4000", + "MCUBOOT_SECTOR_SIZE = 512", + "APP_VERSION_MAJOR=1", + "APP_VERSION_MINOR=0", + "APP_VERSION_BUILD=0", + "MCUBOOT_OVERWRITE_ONLY", + "CY_ENABLE_XIP_PROGRAM", + ] + + if (build_update_image) { + defines += [ "CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION=2" ] + } else { + defines += [ "CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION=1" ] + } +} p6_sdk_sources("lock_app_sdk_sources") { include_dirs = [ "${chip_root}/src/platform/P6", @@ -49,6 +93,27 @@ p6_sdk_sources("lock_app_sdk_sources") { sources = [ "${p6_project_dir}/include/CHIPProjectConfig.h" ] public_configs = [ "${chip_root}/third_party/p6:p6_sdk_config" ] + + if (chip_enable_ota_requestor) { + sources += [ + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/bootutil/src/bootutil_misc.c", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/cy_flash_map.c", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/cy_flash_psoc6.c", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/cy_smif_psoc6.c", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/mem_config/mem_config_sfdp.c", + ] + include_dirs += [ + "${chip_root}/third_party/p6/p6_sdk/ota/config", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/mem_config/", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/include/", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/include/flash_map_backend/", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/sysflash/", + "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/bootutil/include", + ] + public_configs += [ ":p6_ota_config" ] + } } p6_executable("lock_app") { diff --git a/examples/lock-app/p6/README.md b/examples/lock-app/p6/README.md index acfa2bb2a37e74..36b1ed1a158ed4 100644 --- a/examples/lock-app/p6/README.md +++ b/examples/lock-app/p6/README.md @@ -13,6 +13,7 @@ An example showing the use of Matter on the Infineon CY8CKIT-062S2-43012 board. - [Commissioning over BLE](#commissioning-over-ble) - [Notes](#notes) - [Cluster control](#cluster-control) + - [OTA Software Update](#ota-software-update)
@@ -134,3 +135,9 @@ commands. These power cycle the BlueTooth hardware and disable BR/EDR mode. Press `USER_BTN1` on the board to toggle between lock and unlock states. The Lock/Unlock status of door can be observed with 'LED9' on the board. This LED is configured with `LOCK_STATE_LED` in `include/AppConfig.h`. + +## OTA Software Update + +For the description of Software Update process with infineon P6 example +applications see +[Infineon P6 OTA Software Update](../../../docs/guides/infineon_p6_software_update.md) diff --git a/examples/lock-app/p6/include/AppTask.h b/examples/lock-app/p6/include/AppTask.h index 854d70efdb9744..3e50921a76cff2 100644 --- a/examples/lock-app/p6/include/AppTask.h +++ b/examples/lock-app/p6/include/AppTask.h @@ -50,6 +50,7 @@ class AppTask void ButtonEventHandler(uint8_t btnIdx, uint8_t btnAction); void UpdateClusterState(void); + void InitOTARequestor(); private: friend AppTask & GetAppTask(void); diff --git a/examples/lock-app/p6/ota_base_build.sh b/examples/lock-app/p6/ota_base_build.sh new file mode 100755 index 00000000000000..7ab6e27ec17fab --- /dev/null +++ b/examples/lock-app/p6/ota_base_build.sh @@ -0,0 +1,8 @@ +OUT_DIR=out/lock-app/ +ANYCLOUD_DIR=third_party/p6/p6_sdk/libs/anycloud-ota/ + +scripts/examples/gn_p6_example.sh examples/lock-app/p6 "$OUT_DIR" chip_enable_ota_requestor=true + +mv "$OUT_DIR"/chip-p6-lock-example.hex "$OUT_DIR"/chip-p6-lock-example.unsigned.hex + +./"$ANYCLOUD_DIR"/scripts/sign_script.bash "$OUT_DIR"/ chip-p6-lock-example python3 arm-none-eabi-objcopy "-O ihex" "" "$ANYCLOUD_DIR"/source/mcuboot/scripts/ imgtool_v1.7.0/imgtool.py create 0xFF 0x400 3584 1.0.0 0x00018000 0x001C0000 arm-none-eabi-objcopy "" diff --git a/examples/lock-app/p6/ota_update_build.sh b/examples/lock-app/p6/ota_update_build.sh new file mode 100755 index 00000000000000..ac5d674cd67115 --- /dev/null +++ b/examples/lock-app/p6/ota_update_build.sh @@ -0,0 +1,14 @@ +OUT_DIR=out/lock-app-ota +ANYCLOUD_DIR=third_party/p6/p6_sdk/libs/anycloud-ota/ + +./scripts/examples/gn_p6_example.sh examples/lock-app/p6 "$OUT_DIR" chip_enable_ota_requestor=true build_update_image=true + +mv "$OUT_DIR"/chip-p6-lock-example.hex "$OUT_DIR"/chip-p6-lock-example.unsigned.hex + +./"$ANYCLOUD_DIR"/scripts/sign_script.bash "$OUT_DIR"/ chip-p6-lock-example python3 arm-none-eabi-objcopy "-O ihex" "" "$ANYCLOUD_DIR"/source/mcuboot/scripts/ imgtool_v1.7.0/imgtool.py sign 0xFF 0x400 3584 1.0.0 0x00018000 0x001C0000 arm-none-eabi-objcopy "-k $ANYCLOUD_DIR/source/mcuboot/keys/cypress-test-ec-p256.pem" + +if [ -f "$OUT_DIR"/chip-p6-lock-example.ota ]; then + rm "$OUT_DIR"/chip-p6-lock-example.ota +fi + +src/app/ota_image_tool.py create -v 0xFFF1 -p 0x8000 -vn 2 -vs "2.0" -da sha256 "$OUT_DIR"/chip-p6-lock-example.bin "$OUT_DIR"/chip-p6-lock-example.ota diff --git a/examples/lock-app/p6/src/AppTask.cpp b/examples/lock-app/p6/src/AppTask.cpp index 3dbff0e7d47b03..fdd6052c39de59 100644 --- a/examples/lock-app/p6/src/AppTask.cpp +++ b/examples/lock-app/p6/src/AppTask.cpp @@ -40,6 +40,33 @@ #include #include +/* OTA related includes */ +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR +#include +#include +#include +#include +#include +extern "C" { +#include "cy_smif_psoc6.h" +} +using chip::BDXDownloader; +using chip::CharSpan; +using chip::DefaultOTARequestor; +using chip::FabricIndex; +using chip::GetRequestorInstance; +using chip::NodeId; +using chip::OTADownloader; +using chip::OTAImageProcessorImpl; +using chip::System::Layer; + +using namespace ::chip; +using namespace chip::TLV; +using namespace ::chip::Credentials; +using namespace ::chip::DeviceLayer; +using namespace ::chip::System; + +#endif #define FACTORY_RESET_TRIGGER_TIMEOUT 3000 #define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 3000 #define APP_TASK_STACK_SIZE (4096) @@ -63,6 +90,15 @@ bool sHaveBLEConnections = false; StackType_t appStack[APP_TASK_STACK_SIZE / sizeof(StackType_t)]; StaticTask_t appTaskStruct; + +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR +DefaultOTARequestor gRequestorCore; +DefaultOTARequestorStorage gRequestorStorage; +DefaultOTARequestorDriver gRequestorUser; +BDXDownloader gDownloader; +OTAImageProcessorImpl gImageProcessor; +#endif + } // namespace using namespace ::chip; @@ -92,6 +128,9 @@ static void InitServer(intptr_t context) // Initialize device attestation config SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR + GetAppTask().InitOTARequestor(); +#endif } CHIP_ERROR AppTask::StartAppTask() @@ -111,7 +150,14 @@ CHIP_ERROR AppTask::StartAppTask() CHIP_ERROR AppTask::Init() { CHIP_ERROR err = CHIP_NO_ERROR; - +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR + int rc = boot_set_confirmed(); + if (rc != 0) + { + P6_LOG("boot_set_confirmed failed"); + appError(CHIP_ERROR_WELL_UNINITIALIZED); + } +#endif // Register the callback to init the MDNS server when connectivity is available PlatformMgr().AddEventHandler( [](const ChipDeviceEvent * event, intptr_t arg) { @@ -524,3 +570,39 @@ void vApplicationStackOverflowHook(TaskHandle_t pxTask, char * pcTaskName) function is called if a stack overflow is detected. */ printf("ERROR: stack overflow with task %s\r\n", pcTaskName); } + +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR +void AppTask::InitOTARequestor() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + SetRequestorInstance(&gRequestorCore); + gRequestorStorage.Init(chip::Server::GetInstance().GetPersistentStorage()); + gRequestorCore.Init(chip::Server::GetInstance(), gRequestorStorage, gRequestorUser, gDownloader); + gImageProcessor.SetOTADownloader(&gDownloader); + gDownloader.SetImageProcessorDelegate(&gImageProcessor); + gRequestorUser.Init(&gRequestorCore, &gImageProcessor); + + uint32_t savedSoftwareVersion; + err = ConfigurationMgr().GetSoftwareVersion(savedSoftwareVersion); + if (err != CHIP_NO_ERROR) + { + P6_LOG("Can't get saved software version"); + appError(err); + } + + if (savedSoftwareVersion != CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION) + { + ConfigurationMgr().StoreSoftwareVersion(CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION); + + P6_LOG("Confirming update to version: %u", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION); + chip::OTARequestorInterface * requestor = chip::GetRequestorInstance(); + if (requestor != nullptr) + { + requestor->NotifyUpdateApplied(); + } + } + + P6_LOG("Current Software Version: %u", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION); + P6_LOG("Current Software Version String: %s", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING); +} +#endif diff --git a/examples/lock-app/p6/src/main.cpp b/examples/lock-app/p6/src/main.cpp index 9c213eeb8137fa..6b4e07c16b30c2 100644 --- a/examples/lock-app/p6/src/main.cpp +++ b/examples/lock-app/p6/src/main.cpp @@ -34,6 +34,7 @@ #include #include "AppConfig.h" +#include "cyhal_wdt.h" #include "init_p6Platform.h" #include @@ -95,7 +96,14 @@ static void main_task(void * pvParameters) P6_LOG("PlatformMgr().InitChipStack() failed"); appError(ret); } - chip::DeviceLayer::ConnectivityMgr().SetBLEDeviceName("P6_LOCK"); + + ret = chip::DeviceLayer::ConnectivityMgr().SetBLEDeviceName("P6_LOCK"); + if (ret != CHIP_NO_ERROR) + { + P6_LOG("ConnectivityMgr().SetBLEDeviceName() failed"); + appError(ret); + } + P6_LOG("Starting Platform Manager Event Loop"); ret = PlatformMgr().StartEventLoopTask(); if (ret != CHIP_NO_ERROR) @@ -120,6 +128,12 @@ static void main_task(void * pvParameters) int main(void) { init_p6Platform(); +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR + // Clear watchdog timer (started by bootloader) so that it doesn't trigger a reset + cyhal_wdt_t wdt_obj; + cyhal_wdt_init(&wdt_obj, cyhal_wdt_get_max_timeout_ms()); + cyhal_wdt_free(&wdt_obj); +#endif P6_LOG("==================================================\r\n"); P6_LOG("chip-p6-lock-example starting\r\n"); diff --git a/examples/lock-app/qpg/args.gni b/examples/lock-app/qpg/args.gni index 03c7000100c47f..26f7455d068eda 100644 --- a/examples/lock-app/qpg/args.gni +++ b/examples/lock-app/qpg/args.gni @@ -26,4 +26,4 @@ chip_openthread_ftd = false chip_stack_lock_tracking = "none" pw_log_BACKEND = "${chip_root}/src/lib/support/pw_log_chip" -pw_assert_BACKEND = "$dir_pw_assert_log" +pw_assert_BACKEND = "$dir_pw_assert_log:check_backend" diff --git a/examples/log-source-app/log-source-common/log-source-app.matter b/examples/log-source-app/log-source-common/log-source-app.matter index 27160f8d1f08c7..df13f0c7ec186d 100644 --- a/examples/log-source-app/log-source-common/log-source-app.matter +++ b/examples/log-source-app/log-source-common/log-source-app.matter @@ -147,6 +147,7 @@ server cluster GeneralCommissioning = 48 { struct BasicCommissioningInfo { int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; } attribute access(write: administer) int64u breadcrumb = 0; diff --git a/examples/ota-provider-app/esp32/main/OTAProviderCommands.cpp b/examples/ota-provider-app/esp32/main/OTAProviderCommands.cpp index 695e9518e699a0..2a722fb179d25e 100644 --- a/examples/ota-provider-app/esp32/main/OTAProviderCommands.cpp +++ b/examples/ota-provider-app/esp32/main/OTAProviderCommands.cpp @@ -21,6 +21,8 @@ #include #include +using namespace chip::app::Clusters::OtaSoftwareUpdateProvider; + namespace chip { namespace Shell { namespace { @@ -39,6 +41,26 @@ CHIP_ERROR DelayedActionTimeHandler(int argc, char ** argv) return CHIP_NO_ERROR; } +CHIP_ERROR ApplyUpdateActionHandler(int argc, char ** argv) +{ + VerifyOrReturnError(argc == 1, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(exampleOTAProvider != nullptr, CHIP_ERROR_INCORRECT_STATE); + + if (strcmp(argv[0], "proceed") == 0) + { + exampleOTAProvider->SetApplyUpdateAction(OTAApplyUpdateAction::kProceed); + } + else if (strcmp(argv[0], "awaitNextAction") == 0) + { + exampleOTAProvider->SetApplyUpdateAction(OTAApplyUpdateAction::kAwaitNextAction); + } + else if (strcmp(argv[0], "discontinue") == 0) + { + exampleOTAProvider->SetApplyUpdateAction(OTAApplyUpdateAction::kDiscontinue); + } + return CHIP_NO_ERROR; +} + CHIP_ERROR OTAProviderHandler(int argc, char ** argv) { if (argc == 0) @@ -68,6 +90,9 @@ void OTAProviderCommands::Register() { &DelayedActionTimeHandler, "delay", "Set delayed action time for QueryImageResponse and ApplyUpdateResponse\n" "Usage: OTAProvider delay " }, + { &ApplyUpdateActionHandler, "applyUpdateAction", + "Set apply update action in the apply ApplyUpdateResponse\n" + "Usage: OTAProvider applyUpdateAction " }, }; sSubShell.RegisterCommands(subCommands, ArraySize(subCommands)); diff --git a/examples/ota-provider-app/ota-provider-common/ota-provider-app.matter b/examples/ota-provider-app/ota-provider-common/ota-provider-app.matter index 80d0c7058f12a4..e8b97b93ae88cf 100644 --- a/examples/ota-provider-app/ota-provider-common/ota-provider-app.matter +++ b/examples/ota-provider-app/ota-provider-common/ota-provider-app.matter @@ -138,6 +138,42 @@ server cluster AccessControl = 31 { readonly attribute int16u clusterRevision = 65533; } +server cluster AdministratorCommissioning = 60 { + enum CommissioningWindowStatus : ENUM8 { + kWindowNotOpen = 0; + kEnhancedWindowOpen = 1; + kBasicWindowOpen = 2; + } + + enum StatusCode : ENUM8 { + kBusy = 1; + kPAKEParameterError = 2; + kWindowNotOpen = 3; + } + + readonly attribute int8u windowStatus = 0; + readonly attribute fabric_idx adminFabricIndex = 1; + readonly attribute int16u adminVendorId = 2; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct OpenCommissioningWindowRequest { + INT16U commissioningTimeout = 0; + OCTET_STRING PAKEVerifier = 1; + INT16U discriminator = 2; + INT32U iterations = 3; + OCTET_STRING salt = 4; + } + + request struct OpenBasicCommissioningWindowRequest { + INT16U commissioningTimeout = 0; + } + + timed command access(invoke: administer) OpenCommissioningWindow(OpenCommissioningWindowRequest): DefaultSuccess = 0; + timed command access(invoke: administer) OpenBasicCommissioningWindow(OpenBasicCommissioningWindowRequest): DefaultSuccess = 1; + timed command access(invoke: administer) RevokeCommissioning(): DefaultSuccess = 2; +} + server cluster Basic = 40 { struct CapabilityMinimaStruct { int16u caseSessionsPerFabric = 0; @@ -205,6 +241,7 @@ server cluster GeneralCommissioning = 48 { struct BasicCommissioningInfo { int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; } attribute access(write: administer) int64u breadcrumb = 0; @@ -246,6 +283,173 @@ server cluster GeneralCommissioning = 48 { command access(invoke: administer) CommissioningComplete(): CommissioningCompleteResponse = 4; } +server cluster GeneralDiagnostics = 51 { + enum BootReasonType : ENUM8 { + kUnspecified = 0; + kPowerOnReboot = 1; + kBrownOutReset = 2; + kSoftwareWatchdogReset = 3; + kHardwareWatchdogReset = 4; + kSoftwareUpdateCompleted = 5; + kSoftwareReset = 6; + } + + enum HardwareFaultType : ENUM8 { + kUnspecified = 0; + kRadio = 1; + kSensor = 2; + kResettableOverTemp = 3; + kNonResettableOverTemp = 4; + kPowerSource = 5; + kVisualDisplayFault = 6; + kAudioOutputFault = 7; + kUserInterfaceFault = 8; + kNonVolatileMemoryError = 9; + kTamperDetected = 10; + } + + enum InterfaceType : ENUM8 { + kUnspecified = 0; + kWiFi = 1; + kEthernet = 2; + kCellular = 3; + kThread = 4; + } + + enum NetworkFaultType : ENUM8 { + kUnspecified = 0; + kHardwareFailure = 1; + kNetworkJammed = 2; + kConnectionFailed = 3; + } + + enum RadioFaultType : ENUM8 { + kUnspecified = 0; + kWiFiFault = 1; + kCellularFault = 2; + kThreadFault = 3; + kNFCFault = 4; + kBLEFault = 5; + kEthernetFault = 6; + } + + struct NetworkInterfaceType { + char_string<32> name = 0; + boolean isOperational = 1; + nullable boolean offPremiseServicesReachableIPv4 = 2; + nullable boolean offPremiseServicesReachableIPv6 = 3; + octet_string<8> hardwareAddress = 4; + octet_string IPv4Addresses[] = 5; + octet_string IPv6Addresses[] = 6; + InterfaceType type = 7; + } + + critical event HardwareFaultChange = 0 { + HardwareFaultType current[] = 0; + HardwareFaultType previous[] = 1; + } + + critical event RadioFaultChange = 1 { + RadioFaultType current[] = 0; + RadioFaultType previous[] = 1; + } + + critical event NetworkFaultChange = 2 { + NetworkFaultType current[] = 0; + NetworkFaultType previous[] = 1; + } + + critical event BootReason = 3 { + BootReasonType bootReason = 0; + } + + readonly attribute NetworkInterfaceType networkInterfaces[] = 0; + readonly attribute int16u rebootCount = 1; + readonly attribute int64u upTime = 2; + readonly attribute int32u totalOperationalHours = 3; + readonly attribute enum8 bootReasons = 4; + readonly attribute ENUM8 activeHardwareFaults[] = 5; + readonly attribute ENUM8 activeRadioFaults[] = 6; + readonly attribute ENUM8 activeNetworkFaults[] = 7; + readonly attribute boolean testEventTriggersEnabled = 8; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct TestEventTriggerRequest { + OCTET_STRING enableKey = 0; + INT64U eventTrigger = 1; + } + + command TestEventTrigger(TestEventTriggerRequest): DefaultSuccess = 0; +} + +server cluster GroupKeyManagement = 63 { + enum GroupKeySecurityPolicy : ENUM8 { + kTrustFirst = 0; + kCacheAndSync = 1; + } + + struct GroupKeyMapStruct { + group_id groupId = 1; + int16u groupKeySetID = 2; + fabric_idx fabricIndex = 254; + } + + struct GroupInfoMapStruct { + group_id groupId = 1; + endpoint_no endpoints[] = 2; + optional char_string<16> groupName = 3; + fabric_idx fabricIndex = 254; + } + + struct GroupKeySetStruct { + int16u groupKeySetID = 0; + GroupKeySecurityPolicy groupKeySecurityPolicy = 1; + nullable octet_string<16> epochKey0 = 2; + nullable epoch_us epochStartTime0 = 3; + nullable octet_string<16> epochKey1 = 4; + nullable epoch_us epochStartTime1 = 5; + nullable octet_string<16> epochKey2 = 6; + nullable epoch_us epochStartTime2 = 7; + } + + attribute access(write: manage) GroupKeyMapStruct groupKeyMap[] = 0; + readonly attribute GroupInfoMapStruct groupTable[] = 1; + readonly attribute int16u maxGroupsPerFabric = 2; + readonly attribute int16u maxGroupKeysPerFabric = 3; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct KeySetWriteRequest { + GroupKeySetStruct groupKeySet = 0; + } + + request struct KeySetReadRequest { + INT16U groupKeySetID = 0; + } + + request struct KeySetRemoveRequest { + INT16U groupKeySetID = 0; + } + + request struct KeySetReadAllIndicesRequest { + INT16U groupKeySetIDs[] = 0; + } + + response struct KeySetReadResponse = 2 { + GroupKeySetStruct groupKeySet = 0; + } + + response struct KeySetReadAllIndicesResponse = 5 { + INT16U groupKeySetIDs[] = 0; + } + + command access(invoke: administer) KeySetWrite(KeySetWriteRequest): DefaultSuccess = 0; + command access(invoke: administer) KeySetRead(KeySetReadRequest): KeySetReadResponse = 1; + command access(invoke: administer) KeySetRemove(KeySetRemoveRequest): DefaultSuccess = 3; + command access(invoke: administer) KeySetReadAllIndices(KeySetReadAllIndicesRequest): KeySetReadAllIndicesResponse = 4; +} + server cluster LocalizationConfiguration = 43 { attribute char_string<35> activeLocale = 0; readonly attribute CHAR_STRING supportedLocales[] = 1; @@ -513,6 +717,11 @@ server cluster OperationalCredentials = 62 { VENDOR_ID adminVendorId = 4; } + request struct UpdateNOCRequest { + OCTET_STRING NOCValue = 0; + optional OCTET_STRING ICACValue = 1; + } + request struct UpdateFabricLabelRequest { CHAR_STRING label = 0; } @@ -549,6 +758,7 @@ server cluster OperationalCredentials = 62 { command access(invoke: administer) CertificateChainRequest(CertificateChainRequestRequest): CertificateChainResponse = 2; command access(invoke: administer) CSRRequest(CSRRequestRequest): CSRResponse = 4; command access(invoke: administer) AddNOC(AddNOCRequest): NOCResponse = 6; + command access(invoke: administer) UpdateNOC(UpdateNOCRequest): NOCResponse = 7; command access(invoke: administer) UpdateFabricLabel(UpdateFabricLabelRequest): NOCResponse = 9; command access(invoke: administer) RemoveFabric(RemoveFabricRequest): NOCResponse = 10; command access(invoke: administer) AddTrustedRootCertificate(AddTrustedRootCertificateRequest): DefaultSuccess = 11; @@ -671,6 +881,28 @@ endpoint 0 { ram attribute clusterRevision default = 1; } + server cluster GeneralDiagnostics { + callback attribute networkInterfaces; + callback attribute rebootCount; + callback attribute upTime; + callback attribute totalOperationalHours; + callback attribute bootReasons; + callback attribute activeHardwareFaults; + callback attribute activeRadioFaults; + callback attribute activeNetworkFaults; + callback attribute testEventTriggersEnabled; + ram attribute featureMap; + ram attribute clusterRevision default = 1; + } + + server cluster AdministratorCommissioning { + callback attribute windowStatus; + callback attribute adminFabricIndex; + callback attribute adminVendorId; + ram attribute featureMap; + ram attribute clusterRevision default = 1; + } + server cluster OperationalCredentials { callback attribute NOCs; callback attribute fabrics; @@ -682,6 +914,15 @@ endpoint 0 { ram attribute clusterRevision default = 1; } + server cluster GroupKeyManagement { + callback attribute groupKeyMap; + callback attribute groupTable; + callback attribute maxGroupsPerFabric; + callback attribute maxGroupKeysPerFabric; + ram attribute featureMap; + ram attribute clusterRevision default = 1; + } + server cluster FixedLabel { callback attribute labelList; ram attribute featureMap; diff --git a/examples/ota-provider-app/ota-provider-common/ota-provider-app.zap b/examples/ota-provider-app/ota-provider-common/ota-provider-app.zap index a47aac9c2b0806..d84c220ba91135 100644 --- a/examples/ota-provider-app/ota-provider-common/ota-provider-app.zap +++ b/examples/ota-provider-app/ota-provider-common/ota-provider-app.zap @@ -267,6 +267,539 @@ } ] }, + { + "name": "Group Key Management", + "code": 63, + "mfgCode": null, + "define": "GROUP_KEY_MANAGEMENT_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "KeySetWrite", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "KeySetRead", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "KeySetRemove", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "KeySetReadAllIndices", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Group Key Management", + "code": 63, + "mfgCode": null, + "define": "GROUP_KEY_MANAGEMENT_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "KeySetReadResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "KeySetReadAllIndicesResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "GroupKeyMap", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "GroupTable", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MaxGroupsPerFabric", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxGroupKeysPerFabric", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "General Diagnostics", + "code": 51, + "mfgCode": null, + "define": "GENERAL_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "General Diagnostics", + "code": 51, + "mfgCode": null, + "define": "GENERAL_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "TestEventTrigger", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "NetworkInterfaces", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RebootCount", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UpTime", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TotalOperationalHours", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BootReasons", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveHardwareFaults", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveRadioFaults", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveNetworkFaults", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TestEventTriggersEnabled", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "false", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "AdministratorCommissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "OpenCommissioningWindow", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "OpenBasicCommissioningWindow", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RevokeCommissioning", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [] + }, + { + "name": "AdministratorCommissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "WindowStatus", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AdminFabricIndex", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "fabric_idx", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AdminVendorId", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, { "name": "Scenes", "code": 5, @@ -2226,6 +2759,14 @@ "incoming": 1, "outgoing": 1 }, + { + "name": "UpdateNOC", + "code": 7, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, { "name": "UpdateFabricLabel", "code": 9, @@ -4397,4 +4938,4 @@ "deviceIdentifier": 22 } ] -} \ No newline at end of file +} diff --git a/examples/ota-requestor-app/ameba/chip_main.cmake b/examples/ota-requestor-app/ameba/chip_main.cmake index 7bd00165edecec..885eaa13f8ddca 100644 --- a/examples/ota-requestor-app/ameba/chip_main.cmake +++ b/examples/ota-requestor-app/ameba/chip_main.cmake @@ -28,6 +28,8 @@ list( ${chip_dir}/src/app/clusters/ota-requestor/DefaultOTARequestorStorage.cpp ${chip_dir}/src/app/clusters/ota-requestor/ota-requestor-server.cpp ${chip_dir}/examples/platform/ameba/ota/OTAInitializer.cpp + + ${chip_dir}/examples/providers/DeviceInfoProviderImpl.cpp ) add_library( @@ -62,6 +64,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/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 89a99340cceda1..76517f6866c976 100644 --- a/examples/ota-requestor-app/ameba/main/chipinterface.cpp +++ b/examples/ota-requestor-app/ameba/main/chipinterface.cpp @@ -20,6 +20,7 @@ #include "CHIPDeviceManager.h" #include "DeviceCallbacks.h" #include "chip_porting.h" +#include #include #include @@ -73,6 +74,7 @@ void NetWorkCommissioningInstInit() } static DeviceCallbacks EchoCallbacks; +chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider; static void InitServer(intptr_t context) { @@ -80,6 +82,8 @@ static void InitServer(intptr_t context) static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); chip::Server::GetInstance().Init(initParams); + gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); + chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); // Initialize device attestation config SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); diff --git a/examples/ota-requestor-app/efr32/args.gni b/examples/ota-requestor-app/efr32/args.gni index fde26ca7395bb4..5d3bf441f0fc19 100644 --- a/examples/ota-requestor-app/efr32/args.gni +++ b/examples/ota-requestor-app/efr32/args.gni @@ -19,7 +19,7 @@ import("${chip_root}/src/platform/EFR32/args.gni") efr32_sdk_target = get_label_info(":sdk", "label_no_toolchain") pw_log_BACKEND = "${chip_root}/src/lib/support/pw_log_chip" -pw_assert_BACKEND = "$dir_pw_assert_log" +pw_assert_BACKEND = "$dir_pw_assert_log:check_backend" chip_enable_openthread = true chip_openthread_ftd = false diff --git a/examples/ota-requestor-app/esp32/CMakeLists.txt b/examples/ota-requestor-app/esp32/CMakeLists.txt index 6768daa80b1651..61ca2167a0bf43 100644 --- a/examples/ota-requestor-app/esp32/CMakeLists.txt +++ b/examples/ota-requestor-app/esp32/CMakeLists.txt @@ -46,7 +46,8 @@ include(third_party/connectedhomeip/third_party/pigweed/repo/pw_build/pigweed.cm pw_set_module_config(pw_rpc_CONFIG pw_rpc.disable_global_mutex_config) pw_set_backend(pw_log pw_log_basic) -pw_set_backend(pw_assert pw_assert_log) +pw_set_backend(pw_assert.check pw_assert_log.check_backend) +pw_set_backend(pw_assert.assert pw_assert.assert_compatibility_backend) pw_set_backend(pw_sys_io pw_sys_io.esp32) add_subdirectory(third_party/connectedhomeip/third_party/pigweed/repo) diff --git a/examples/ota-requestor-app/esp32/main/CMakeLists.txt b/examples/ota-requestor-app/esp32/main/CMakeLists.txt index bd2ac14dfcdd3c..49efad63731dee 100644 --- a/examples/ota-requestor-app/esp32/main/CMakeLists.txt +++ b/examples/ota-requestor-app/esp32/main/CMakeLists.txt @@ -105,7 +105,7 @@ pw_proto_library(attributes_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(button_service @@ -116,7 +116,7 @@ pw_proto_library(button_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(descriptor_service @@ -127,7 +127,7 @@ pw_proto_library(descriptor_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(device_service @@ -140,7 +140,7 @@ pw_proto_library(device_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(wifi_service @@ -151,7 +151,7 @@ pw_proto_library(wifi_service PREFIX wifi_service DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos ) diff --git a/examples/ota-requestor-app/linux/main.cpp b/examples/ota-requestor-app/linux/main.cpp index 10c1c595d6aa67..7507e201646da9 100644 --- a/examples/ota-requestor-app/linux/main.cpp +++ b/examples/ota-requestor-app/linux/main.cpp @@ -17,11 +17,13 @@ */ #include "AppMain.h" +#include #include #include #include #include #include +#include #include using chip::BDXDownloader; @@ -43,7 +45,9 @@ using chip::Callback::Callback; using chip::System::Layer; using chip::Transport::PeerAddress; using namespace chip; +using namespace chip::app; using namespace chip::ArgParser; +using namespace chip::DeviceLayer; using namespace chip::Messaging; using namespace chip::app::Clusters::OtaSoftwareUpdateProvider::Commands; @@ -117,6 +121,33 @@ OptionSet cmdLineOptions = { OptionSet * allOptions[] = { &cmdLineOptions, nullptr }; +// Network commissioning +namespace { +constexpr EndpointId kNetworkCommissioningEndpointMain = 0; +constexpr EndpointId kNetworkCommissioningEndpointSecondary = 0xFFFE; + +// This file is being used by platforms other than Linux, so we need this check to disable related features since we only +// implemented them on linux. +#if CHIP_DEVICE_LAYER_TARGET_LINUX +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD +NetworkCommissioning::LinuxThreadDriver sLinuxThreadDriver; +Clusters::NetworkCommissioning::Instance sThreadNetworkCommissioningInstance(kNetworkCommissioningEndpointMain, + &sLinuxThreadDriver); +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD +#if CHIP_DEVICE_CONFIG_ENABLE_WPA +NetworkCommissioning::LinuxWiFiDriver sLinuxWiFiDriver; +Clusters::NetworkCommissioning::Instance sWiFiNetworkCommissioningInstance(kNetworkCommissioningEndpointSecondary, + &sLinuxWiFiDriver); +#endif // CHIP_DEVICE_CONFIG_ENABLE_WPA +NetworkCommissioning::LinuxEthernetDriver sLinuxEthernetDriver; +Clusters::NetworkCommissioning::Instance sEthernetNetworkCommissioningInstance(kNetworkCommissioningEndpointMain, + &sLinuxEthernetDriver); +#else // CHIP_DEVICE_LAYER_TARGET_LINUX +Clusters::NetworkCommissioning::NullNetworkDriver sNullNetworkDriver; +Clusters::NetworkCommissioning::Instance sNullNetworkCommissioningInstance(kNetworkCommissioningEndpointMain, &sNullNetworkDriver); +#endif // CHIP_DEVICE_LAYER_TARGET_LINUX +} // namespace + bool CustomOTARequestorDriver::CanConsent() { return gRequestorCanConsent.ValueOr(DeviceLayer::ExtendedOTARequestorDriver::CanConsent()); @@ -168,6 +199,68 @@ static void InitOTARequestor(void) } } +static void InitNetworkCommissioning(void) +{ + (void) kNetworkCommissioningEndpointMain; + // Enable secondary endpoint only when we need it, this should be applied to all platforms. + emberAfEndpointEnableDisable(kNetworkCommissioningEndpointSecondary, false); + +#if CHIP_DEVICE_LAYER_TARGET_LINUX + const bool kThreadEnabled = { +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + LinuxDeviceOptions::GetInstance().mThread +#else + false +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD + }; + + const bool kWiFiEnabled = { +#if CHIP_DEVICE_CONFIG_ENABLE_WPA + LinuxDeviceOptions::GetInstance().mWiFi +#else + false +#endif // CHIP_DEVICE_CONFIG_ENABLE_WPA + }; + + if (kThreadEnabled && kWiFiEnabled) + { +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + sThreadNetworkCommissioningInstance.Init(); +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD +#if CHIP_DEVICE_CONFIG_ENABLE_WPA + sWiFiNetworkCommissioningInstance.Init(); +#endif // CHIP_DEVICE_CONFIG_ENABLE_WPA + // Only enable secondary endpoint for network commissioning cluster when both WiFi and Thread are enabled. + emberAfEndpointEnableDisable(kNetworkCommissioningEndpointSecondary, true); + } + else if (kThreadEnabled) + { +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + sThreadNetworkCommissioningInstance.Init(); +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD + } + else if (kWiFiEnabled) + { +#if CHIP_DEVICE_CONFIG_ENABLE_WPA + // If we only enable WiFi on this device, "move" WiFi instance to main NetworkCommissioning cluster endpoint. + sWiFiNetworkCommissioningInstance.~Instance(); + new (&sWiFiNetworkCommissioningInstance) + Clusters::NetworkCommissioning::Instance(kNetworkCommissioningEndpointMain, &sLinuxWiFiDriver); + sWiFiNetworkCommissioningInstance.Init(); +#endif // CHIP_DEVICE_CONFIG_ENABLE_WPA + } + else +#endif // CHIP_DEVICE_LAYER_TARGET_LINUX + { +#if CHIP_DEVICE_LAYER_TARGET_LINUX + sEthernetNetworkCommissioningInstance.Init(); +#else + // Use NullNetworkCommissioningInstance to disable the network commissioning functions. + sNullNetworkCommissioningInstance.Init(); +#endif // CHIP_DEVICE_LAYER_TARGET_LINUX + } +} + bool HandleOptions(const char * aProgram, OptionSet * aOptions, int aIdentifier, const char * aName, const char * aValue) { bool retval = true; @@ -233,6 +326,8 @@ void ApplicationInit() { // Initialize all OTA download components InitOTARequestor(); + // Initialize Network Commissioning instances + InitNetworkCommissioning(); } int main(int argc, char * argv[]) diff --git a/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.matter b/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.matter index 9c0b8b7f18f6de..09184a341332a4 100644 --- a/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.matter +++ b/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.matter @@ -175,6 +175,7 @@ server cluster GeneralCommissioning = 48 { struct BasicCommissioningInfo { int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; } attribute access(write: administer) int64u breadcrumb = 0; @@ -216,6 +217,173 @@ server cluster GeneralCommissioning = 48 { command access(invoke: administer) CommissioningComplete(): CommissioningCompleteResponse = 4; } +server cluster GeneralDiagnostics = 51 { + enum BootReasonType : ENUM8 { + kUnspecified = 0; + kPowerOnReboot = 1; + kBrownOutReset = 2; + kSoftwareWatchdogReset = 3; + kHardwareWatchdogReset = 4; + kSoftwareUpdateCompleted = 5; + kSoftwareReset = 6; + } + + enum HardwareFaultType : ENUM8 { + kUnspecified = 0; + kRadio = 1; + kSensor = 2; + kResettableOverTemp = 3; + kNonResettableOverTemp = 4; + kPowerSource = 5; + kVisualDisplayFault = 6; + kAudioOutputFault = 7; + kUserInterfaceFault = 8; + kNonVolatileMemoryError = 9; + kTamperDetected = 10; + } + + enum InterfaceType : ENUM8 { + kUnspecified = 0; + kWiFi = 1; + kEthernet = 2; + kCellular = 3; + kThread = 4; + } + + enum NetworkFaultType : ENUM8 { + kUnspecified = 0; + kHardwareFailure = 1; + kNetworkJammed = 2; + kConnectionFailed = 3; + } + + enum RadioFaultType : ENUM8 { + kUnspecified = 0; + kWiFiFault = 1; + kCellularFault = 2; + kThreadFault = 3; + kNFCFault = 4; + kBLEFault = 5; + kEthernetFault = 6; + } + + struct NetworkInterfaceType { + char_string<32> name = 0; + boolean isOperational = 1; + nullable boolean offPremiseServicesReachableIPv4 = 2; + nullable boolean offPremiseServicesReachableIPv6 = 3; + octet_string<8> hardwareAddress = 4; + octet_string IPv4Addresses[] = 5; + octet_string IPv6Addresses[] = 6; + InterfaceType type = 7; + } + + critical event HardwareFaultChange = 0 { + HardwareFaultType current[] = 0; + HardwareFaultType previous[] = 1; + } + + critical event RadioFaultChange = 1 { + RadioFaultType current[] = 0; + RadioFaultType previous[] = 1; + } + + critical event NetworkFaultChange = 2 { + NetworkFaultType current[] = 0; + NetworkFaultType previous[] = 1; + } + + critical event BootReason = 3 { + BootReasonType bootReason = 0; + } + + readonly attribute NetworkInterfaceType networkInterfaces[] = 0; + readonly attribute int16u rebootCount = 1; + readonly attribute int64u upTime = 2; + readonly attribute int32u totalOperationalHours = 3; + readonly attribute enum8 bootReasons = 4; + readonly attribute ENUM8 activeHardwareFaults[] = 5; + readonly attribute ENUM8 activeRadioFaults[] = 6; + readonly attribute ENUM8 activeNetworkFaults[] = 7; + readonly attribute boolean testEventTriggersEnabled = 8; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct TestEventTriggerRequest { + OCTET_STRING enableKey = 0; + INT64U eventTrigger = 1; + } + + command TestEventTrigger(TestEventTriggerRequest): DefaultSuccess = 0; +} + +server cluster GroupKeyManagement = 63 { + enum GroupKeySecurityPolicy : ENUM8 { + kTrustFirst = 0; + kCacheAndSync = 1; + } + + struct GroupKeyMapStruct { + group_id groupId = 1; + int16u groupKeySetID = 2; + fabric_idx fabricIndex = 254; + } + + struct GroupInfoMapStruct { + group_id groupId = 1; + endpoint_no endpoints[] = 2; + optional char_string<16> groupName = 3; + fabric_idx fabricIndex = 254; + } + + struct GroupKeySetStruct { + int16u groupKeySetID = 0; + GroupKeySecurityPolicy groupKeySecurityPolicy = 1; + nullable octet_string<16> epochKey0 = 2; + nullable epoch_us epochStartTime0 = 3; + nullable octet_string<16> epochKey1 = 4; + nullable epoch_us epochStartTime1 = 5; + nullable octet_string<16> epochKey2 = 6; + nullable epoch_us epochStartTime2 = 7; + } + + attribute access(write: manage) GroupKeyMapStruct groupKeyMap[] = 0; + readonly attribute GroupInfoMapStruct groupTable[] = 1; + readonly attribute int16u maxGroupsPerFabric = 2; + readonly attribute int16u maxGroupKeysPerFabric = 3; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct KeySetWriteRequest { + GroupKeySetStruct groupKeySet = 0; + } + + request struct KeySetReadRequest { + INT16U groupKeySetID = 0; + } + + request struct KeySetRemoveRequest { + INT16U groupKeySetID = 0; + } + + request struct KeySetReadAllIndicesRequest { + INT16U groupKeySetIDs[] = 0; + } + + response struct KeySetReadResponse = 2 { + GroupKeySetStruct groupKeySet = 0; + } + + response struct KeySetReadAllIndicesResponse = 5 { + INT16U groupKeySetIDs[] = 0; + } + + command access(invoke: administer) KeySetWrite(KeySetWriteRequest): DefaultSuccess = 0; + command access(invoke: administer) KeySetRead(KeySetReadRequest): KeySetReadResponse = 1; + command access(invoke: administer) KeySetRemove(KeySetRemoveRequest): DefaultSuccess = 3; + command access(invoke: administer) KeySetReadAllIndices(KeySetReadAllIndicesRequest): KeySetReadAllIndicesResponse = 4; +} + server cluster LocalizationConfiguration = 43 { attribute char_string<35> activeLocale = 0; readonly attribute CHAR_STRING supportedLocales[] = 1; @@ -720,6 +888,20 @@ endpoint 0 { ram attribute clusterRevision default = 1; } + server cluster GeneralDiagnostics { + callback attribute networkInterfaces; + callback attribute rebootCount; + callback attribute upTime; + callback attribute totalOperationalHours; + callback attribute bootReasons; + callback attribute activeHardwareFaults; + callback attribute activeRadioFaults; + callback attribute activeNetworkFaults; + callback attribute testEventTriggersEnabled; + ram attribute featureMap; + ram attribute clusterRevision default = 1; + } + server cluster AdministratorCommissioning { callback attribute windowStatus; callback attribute adminFabricIndex; @@ -739,6 +921,15 @@ endpoint 0 { ram attribute clusterRevision default = 1; } + server cluster GroupKeyManagement { + callback attribute groupKeyMap; + callback attribute groupTable; + callback attribute maxGroupsPerFabric; + callback attribute maxGroupKeysPerFabric; + ram attribute featureMap; + ram attribute clusterRevision default = 1; + } + server cluster FixedLabel { callback attribute labelList; ram attribute featureMap; @@ -751,5 +942,21 @@ endpoint 0 { ram attribute clusterRevision default = 1; } } +endpoint 65534 { + device type anonymousEndpointType = 61442; + + server cluster NetworkCommissioning { + callback attribute maxNetworks; + callback attribute networks; + callback attribute scanMaxTimeSeconds; + callback attribute connectMaxTimeSeconds; + callback attribute interfaceEnabled; + callback attribute lastNetworkingStatus; + callback attribute lastNetworkID; + callback attribute lastConnectErrorValue; + callback attribute featureMap; + callback attribute clusterRevision default = 1; + } +} diff --git a/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.zap b/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.zap index aea3c9e627a2f4..0eb046b497c634 100644 --- a/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.zap +++ b/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.zap @@ -2241,6 +2241,229 @@ } ] }, + { + "name": "General Diagnostics", + "code": 51, + "mfgCode": null, + "define": "GENERAL_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "General Diagnostics", + "code": 51, + "mfgCode": null, + "define": "GENERAL_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "TestEventTrigger", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "NetworkInterfaces", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RebootCount", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UpTime", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TotalOperationalHours", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BootReasons", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveHardwareFaults", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveRadioFaults", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveNetworkFaults", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TestEventTriggersEnabled", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "false", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, { "name": "AdministratorCommissioning", "code": 60, @@ -2632,59 +2855,243 @@ ] }, { - "name": "Fixed Label", - "code": 64, + "name": "Group Key Management", + "code": 63, "mfgCode": null, - "define": "FIXED_LABEL_CLUSTER", + "define": "GROUP_KEY_MANAGEMENT_CLUSTER", "side": "client", "enabled": 0, - "commands": [], - "attributes": [] - }, - { - "name": "Fixed Label", - "code": 64, - "mfgCode": null, - "define": "FIXED_LABEL_CLUSTER", - "side": "server", - "enabled": 1, - "commands": [], - "attributes": [ + "commands": [ { - "name": "label list", + "name": "KeySetWrite", "code": 0, "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 + "source": "client", + "incoming": 1, + "outgoing": 0 }, { - "name": "FeatureMap", - "code": 65532, + "name": "KeySetRead", + "code": 1, "mfgCode": null, - "side": "server", - "type": "bitmap32", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 + "source": "client", + "incoming": 1, + "outgoing": 0 }, { - "name": "ClusterRevision", - "code": 65533, + "name": "KeySetRemove", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "KeySetReadAllIndices", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Group Key Management", + "code": 63, + "mfgCode": null, + "define": "GROUP_KEY_MANAGEMENT_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "KeySetReadResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "KeySetReadAllIndicesResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "GroupKeyMap", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "GroupTable", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MaxGroupsPerFabric", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxGroupKeysPerFabric", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Fixed Label", + "code": 64, + "mfgCode": null, + "define": "FIXED_LABEL_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [], + "attributes": [] + }, + { + "name": "Fixed Label", + "code": 64, + "mfgCode": null, + "define": "FIXED_LABEL_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "label list", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, "mfgCode": null, "side": "server", "type": "int16u", @@ -4573,17 +4980,371 @@ ] } ] - } - ], - "endpoints": [ + }, { - "endpointTypeName": "MA-rootdevice", - "endpointTypeIndex": 0, - "profileId": 259, - "endpointId": 0, - "networkId": 0, - "endpointVersion": 1, - "deviceIdentifier": 22 - } - ] + "name": "Anonymous Endpoint Type", + "deviceTypeName": "MA-secondary-network-commissioning", + "deviceTypeCode": 61442, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Network Commissioning", + "code": 49, + "mfgCode": null, + "define": "NETWORK_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ScanNetworks", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "AddOrUpdateWiFiNetwork", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "AddOrUpdateThreadNetwork", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RemoveNetwork", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ConnectNetwork", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ReorderNetwork", + "code": 8, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Network Commissioning", + "code": 49, + "mfgCode": null, + "define": "NETWORK_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ScanNetworksResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "NetworkConfigResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "ConnectNetworkResponse", + "code": 7, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "MaxNetworks", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Networks", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ScanMaxTimeSeconds", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ConnectMaxTimeSeconds", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "InterfaceEnabled", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LastNetworkingStatus", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "NetworkCommissioningStatus", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LastNetworkID", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LastConnectErrorValue", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int32s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 0, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + } + ], + "endpoints": [ + { + "endpointTypeName": "MA-rootdevice", + "endpointTypeIndex": 0, + "profileId": 259, + "endpointId": 0, + "networkId": 0, + "endpointVersion": 1, + "deviceIdentifier": 22 + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 1, + "profileId": 259, + "endpointId": 65534, + "networkId": 0, + "endpointVersion": 1, + "deviceIdentifier": 61442 + } + ], + "log": [] } \ No newline at end of file diff --git a/examples/ota-requestor-app/p6/BUILD.gn b/examples/ota-requestor-app/p6/BUILD.gn index f628f7780c0748..7701ca1c5e8a41 100644 --- a/examples/ota-requestor-app/p6/BUILD.gn +++ b/examples/ota-requestor-app/p6/BUILD.gn @@ -40,9 +40,10 @@ declare_args() { } config("p6_ota_config") { - ldflags = [ "-T/" + rebase_path("src/cy8c6xxa_cm4_dual_ota_int.ld", - "/", - "${p6_project_dir}") ] + ldflags = [ "-T/" + rebase_path( + "${chip_root}/third_party/p6/p6_sdk/ota/cy8c6xxa_cm4_dual_ota_int.ld", + "/", + "${p6_project_dir}") ] ldflags += [ "-Wl,--defsym,MCUBOOT_HEADER_SIZE=0x400,--defsym,MCUBOOT_BOOTLOADER_SIZE=0x18000,--defsym,CY_BOOT_PRIMARY_1_SIZE=0x1C0000" ] @@ -87,7 +88,7 @@ p6_sdk_sources("ota_requestor_app_sdk_sources") { "${chip_root}/src/platform/P6", "${p6_project_dir}/include", "${examples_plat_dir}", - "${p6_project_dir}/config", + "${chip_root}/third_party/p6/p6_sdk/ota/config", "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/", "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/mem_config/", "${chip_root}/third_party/p6/p6_sdk/libs/anycloud-ota/source/mcuboot/cy_flash_pal/include/", diff --git a/examples/ota-requestor-app/p6/README.md b/examples/ota-requestor-app/p6/README.md index e63b3a5842444f..dc58d3da7bc4b1 100644 --- a/examples/ota-requestor-app/p6/README.md +++ b/examples/ota-requestor-app/p6/README.md @@ -71,7 +71,7 @@ will then join the network. * Additionally a pre-compiled bootloader must be flashed to the board. This can be found at: - $ ./examples/ota-requestor-app/p6/matter-psoc6-mcuboot-bootloader.hex + $ ./third_party/p6/p6_sdk/ota/matter-psoc6-mcuboot-bootloader.hex diff --git a/examples/ota-requestor-app/p6/include/AppTask.h b/examples/ota-requestor-app/p6/include/AppTask.h index 43d448ed06b51c..c460807f997c84 100644 --- a/examples/ota-requestor-app/p6/include/AppTask.h +++ b/examples/ota-requestor-app/p6/include/AppTask.h @@ -47,6 +47,7 @@ class AppTask void PostEvent(const AppEvent * event); void ButtonEventHandler(uint8_t btnIdx, uint8_t btnAction); + void InitOTARequestor(); private: friend AppTask & GetAppTask(void); diff --git a/examples/ota-requestor-app/p6/include/CHIPProjectConfig.h b/examples/ota-requestor-app/p6/include/CHIPProjectConfig.h index 30140dc83620d7..c3ef134be2a110 100644 --- a/examples/ota-requestor-app/p6/include/CHIPProjectConfig.h +++ b/examples/ota-requestor-app/p6/include/CHIPProjectConfig.h @@ -66,14 +66,14 @@ #define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_REVISION 1 /** - * CHIP_DEVICE_CONFIG_DEVICE_FIRMWARE_REVISION_STRING + * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING * - * A string identifying the firmware revision running on the device. - * CHIP service currently expects the firmware version to be in the format + * A string identifying the software version running on the device. + * CHIP service currently expects the software version to be in the format * {MAJOR_VERSION}.0d{MINOR_VERSION} */ -#ifndef CHIP_DEVICE_CONFIG_DEVICE_FIRMWARE_REVISION_STRING -#define CHIP_DEVICE_CONFIG_DEVICE_FIRMWARE_REVISION_STRING "0.1ALPHA" +#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING +#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING "0.1ALPHA" #endif /** * CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE diff --git a/examples/ota-requestor-app/p6/ota_update_build.sh b/examples/ota-requestor-app/p6/ota_update_build.sh index 8dbe33869b2ed8..825b1db6457318 100755 --- a/examples/ota-requestor-app/p6/ota_update_build.sh +++ b/examples/ota-requestor-app/p6/ota_update_build.sh @@ -6,3 +6,9 @@ ANYCLOUD_DIR=third_party/p6/p6_sdk/libs/anycloud-ota/ mv "$OUT_DIR"/chip-p6-ota-requestor-example.hex "$OUT_DIR"/chip-p6-ota-requestor-example.unsigned.hex ./"$ANYCLOUD_DIR"/scripts/sign_script.bash "$OUT_DIR" chip-p6-ota-requestor-example python3 arm-none-eabi-objcopy "-O ihex" "" "$ANYCLOUD_DIR"/source/mcuboot/scripts/ imgtool_v1.7.0/imgtool.py sign 0xFF 0x400 3584 1.0.0 0x00018000 0x001C0000 arm-none-eabi-objcopy "-k $ANYCLOUD_DIR/source/mcuboot/keys/cypress-test-ec-p256.pem" + +if [ -f "$OUT_DIR"/chip-p6-ota-requestor-example.ota ]; then + rm "$OUT_DIR"/chip-p6-ota-requestor-example.ota +fi + +src/app/ota_image_tool.py create -v 0xFFF1 -p 0x8000 -vn 2 -vs "2.0" -da sha256 "$OUT_DIR"/chip-p6-ota-requestor-example.bin "$OUT_DIR"/chip-p6-ota-requestor-example.ota diff --git a/examples/ota-requestor-app/p6/src/AppTask.cpp b/examples/ota-requestor-app/p6/src/AppTask.cpp index 6eeb14cf3e10f5..a0507142cf0af4 100644 --- a/examples/ota-requestor-app/p6/src/AppTask.cpp +++ b/examples/ota-requestor-app/p6/src/AppTask.cpp @@ -121,6 +121,7 @@ static void InitServer(intptr_t context) // Initialize device attestation config SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); + GetAppTask().InitOTARequestor(); } CHIP_ERROR AppTask::StartAppTask() @@ -188,36 +189,6 @@ CHIP_ERROR AppTask::Init() ConfigurationMgr().LogDeviceConfig(); - SetRequestorInstance(&gRequestorCore); - gRequestorStorage.Init(chip::Server::GetInstance().GetPersistentStorage()); - gRequestorCore.Init(chip::Server::GetInstance(), gRequestorStorage, gRequestorUser, gDownloader); - gImageProcessor.SetOTADownloader(&gDownloader); - gDownloader.SetImageProcessorDelegate(&gImageProcessor); - gRequestorUser.Init(&gRequestorCore, &gImageProcessor); - - uint32_t savedSoftwareVersion; - err = ConfigurationMgr().GetSoftwareVersion(savedSoftwareVersion); - if (err != CHIP_NO_ERROR) - { - P6_LOG("Can't get saved software version"); - appError(err); - } - - if (savedSoftwareVersion != CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION) - { - ConfigurationMgr().StoreSoftwareVersion(CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION); - - P6_LOG("Confirming update to version: %u", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION); - chip::OTARequestorInterface * requestor = chip::GetRequestorInstance(); - if (requestor != nullptr) - { - requestor->NotifyUpdateApplied(); - } - } - - P6_LOG("Current Software Version: %u", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION); - P6_LOG("Current Firmware Version: %s", CHIP_DEVICE_CONFIG_DEVICE_FIRMWARE_REVISION_STRING); - // Print setup info PrintOnboardingCodes(chip::RendezvousInformationFlag(chip::RendezvousInformationFlag::kBLE)); @@ -473,3 +444,37 @@ void OnTriggerUpdateTimerHandler(Layer * systemLayer, void * appState) DefaultOTARequestor * req = static_cast(GetRequestorInstance()); req->TriggerImmediateQuery(); } + +void AppTask::InitOTARequestor() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + SetRequestorInstance(&gRequestorCore); + gRequestorStorage.Init(chip::Server::GetInstance().GetPersistentStorage()); + gRequestorCore.Init(chip::Server::GetInstance(), gRequestorStorage, gRequestorUser, gDownloader); + gImageProcessor.SetOTADownloader(&gDownloader); + gDownloader.SetImageProcessorDelegate(&gImageProcessor); + gRequestorUser.Init(&gRequestorCore, &gImageProcessor); + + uint32_t savedSoftwareVersion; + err = ConfigurationMgr().GetSoftwareVersion(savedSoftwareVersion); + if (err != CHIP_NO_ERROR) + { + P6_LOG("Can't get saved software version"); + appError(err); + } + + if (savedSoftwareVersion != CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION) + { + ConfigurationMgr().StoreSoftwareVersion(CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION); + + P6_LOG("Confirming update to version: %u", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION); + chip::OTARequestorInterface * requestor = chip::GetRequestorInstance(); + if (requestor != nullptr) + { + requestor->NotifyUpdateApplied(); + } + } + + P6_LOG("Current Software Version: %u", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION); + P6_LOG("Current Firmware Version String: %s", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING); +} diff --git a/examples/persistent-storage/efr32/args.gni b/examples/persistent-storage/efr32/args.gni index 86fbf759d00d08..9c2f04d2324347 100644 --- a/examples/persistent-storage/efr32/args.gni +++ b/examples/persistent-storage/efr32/args.gni @@ -19,4 +19,4 @@ import("${chip_root}/src/platform/EFR32/args.gni") efr32_sdk_target = get_label_info(":sdk", "label_no_toolchain") pw_log_BACKEND = "${chip_root}/src/lib/support/pw_log_chip" -pw_assert_BACKEND = "$dir_pw_assert_log" +pw_assert_BACKEND = "$dir_pw_assert_log:check_backend" diff --git a/examples/pigweed-app/ameba/chip_main.cmake b/examples/pigweed-app/ameba/chip_main.cmake index 8ece704a50ae56..e585c1fdcc0067 100644 --- a/examples/pigweed-app/ameba/chip_main.cmake +++ b/examples/pigweed-app/ameba/chip_main.cmake @@ -18,7 +18,8 @@ set(dir_pw_third_party_nanopb "${chip_dir}/third_party/nanopb/repo" CACHE STRING pw_set_module_config(pw_rpc_CONFIG pw_rpc.disable_global_mutex_config) pw_set_backend(pw_log pw_log_basic) -pw_set_backend(pw_assert pw_assert_log) +pw_set_backend(pw_assert.check pw_assert_log.check_backend) +pw_set_backend(pw_assert.assert pw_assert.assert_compatibility_backend) pw_set_backend(pw_sys_io pw_sys_io.ameba) add_subdirectory(${chip_dir}/third_party/pigweed/repo ${chip_dir}/examples/pigweed-app/ameba/out/pigweed) diff --git a/examples/pigweed-app/esp32/CMakeLists.txt b/examples/pigweed-app/esp32/CMakeLists.txt index b28ce191bf3312..d47b2b29062aa1 100644 --- a/examples/pigweed-app/esp32/CMakeLists.txt +++ b/examples/pigweed-app/esp32/CMakeLists.txt @@ -46,7 +46,8 @@ include(${PIGWEED_ROOT}/pw_protobuf_compiler/proto.cmake) pw_set_module_config(pw_rpc_CONFIG pw_rpc.disable_global_mutex_config) pw_set_backend(pw_log pw_log_basic) -pw_set_backend(pw_assert pw_assert_log) +pw_set_backend(pw_assert.check pw_assert_log.check_backend) +pw_set_backend(pw_assert.assert pw_assert.assert_compatibility_backend) pw_set_backend(pw_sys_io pw_sys_io.esp32) add_subdirectory(third_party/connectedhomeip/third_party/pigweed/repo) diff --git a/examples/pigweed-app/nrfconnect/CMakeLists.txt b/examples/pigweed-app/nrfconnect/CMakeLists.txt index d3fd816033eb4f..90d53ea9ad0d38 100644 --- a/examples/pigweed-app/nrfconnect/CMakeLists.txt +++ b/examples/pigweed-app/nrfconnect/CMakeLists.txt @@ -52,7 +52,8 @@ include(${PIGWEED_ROOT}/pw_protobuf_compiler/proto.cmake) pw_set_module_config(pw_rpc_CONFIG pw_rpc.disable_global_mutex_config) pw_set_backend(pw_log pw_log_basic) -pw_set_backend(pw_assert pw_assert_log) +pw_set_backend(pw_assert.check pw_assert_log.check_backend) +pw_set_backend(pw_assert.assert pw_assert.assert_compatibility_backend) pw_set_backend(pw_sys_io pw_sys_io.nrfconnect) set(dir_pw_third_party_nanopb "${CHIP_ROOT}/third_party/nanopb/repo" CACHE STRING "" FORCE) diff --git a/examples/placeholder/linux/apps/app1/config.matter b/examples/placeholder/linux/apps/app1/config.matter index 832f9ca426152c..a43b8cc48939bd 100644 --- a/examples/placeholder/linux/apps/app1/config.matter +++ b/examples/placeholder/linux/apps/app1/config.matter @@ -608,6 +608,7 @@ client cluster GeneralCommissioning = 48 { struct BasicCommissioningInfo { int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; } attribute access(write: administer) int64u breadcrumb = 0; @@ -654,6 +655,7 @@ server cluster GeneralCommissioning = 48 { struct BasicCommissioningInfo { int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; } attribute access(write: administer) int64u breadcrumb = 0; @@ -2496,14 +2498,7 @@ server cluster WindowCovering = 258 { kTiltEncoderControlled = 0x40; } - bitmap Mode : BITMAP8 { - kMotorDirectionReversed = 0x1; - kCalibrationMode = 0x2; - kMaintenanceMode = 0x4; - kLedFeedback = 0x8; - } - - bitmap WcFeature : BITMAP32 { + bitmap Feature : BITMAP32 { kLift = 0x1; kTilt = 0x2; kPositionAwareLift = 0x4; @@ -2511,13 +2506,20 @@ server cluster WindowCovering = 258 { kPositionAwareTilt = 0x10; } - bitmap WcOperationalStatus : BITMAP8 { + bitmap Mode : BITMAP8 { + kMotorDirectionReversed = 0x1; + kCalibrationMode = 0x2; + kMaintenanceMode = 0x4; + kLedFeedback = 0x8; + } + + bitmap OperationalStatus : BITMAP8 { kGlobal = 0x3; kLift = 0xC; kTilt = 0x30; } - bitmap WcSafetyStatus : BITMAP16 { + bitmap SafetyStatus : BITMAP16 { kRemoteLockout = 0x1; kTamperDetection = 0x2; kFailedCommunication = 0x4; @@ -2538,7 +2540,7 @@ server cluster WindowCovering = 258 { readonly attribute ConfigStatus configStatus = 7; readonly attribute nullable Percent currentPositionLiftPercentage = 8; readonly attribute nullable Percent currentPositionTiltPercentage = 9; - readonly attribute bitmap8 operationalStatus = 10; + readonly attribute OperationalStatus operationalStatus = 10; readonly attribute nullable Percent100ths targetPositionLiftPercent100ths = 11; readonly attribute nullable Percent100ths targetPositionTiltPercent100ths = 12; readonly attribute EndProductType endProductType = 13; @@ -2549,7 +2551,7 @@ server cluster WindowCovering = 258 { readonly attribute int16u installedOpenLimitTilt = 18; readonly attribute int16u installedClosedLimitTilt = 19; attribute access(write: manage) Mode mode = 23; - readonly attribute bitmap16 safetyStatus = 26; + readonly attribute SafetyStatus safetyStatus = 26; readonly attribute bitmap32 featureMap = 65532; readonly attribute int16u clusterRevision = 65533; diff --git a/examples/placeholder/linux/apps/app2/config.matter b/examples/placeholder/linux/apps/app2/config.matter index 832f9ca426152c..a43b8cc48939bd 100644 --- a/examples/placeholder/linux/apps/app2/config.matter +++ b/examples/placeholder/linux/apps/app2/config.matter @@ -608,6 +608,7 @@ client cluster GeneralCommissioning = 48 { struct BasicCommissioningInfo { int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; } attribute access(write: administer) int64u breadcrumb = 0; @@ -654,6 +655,7 @@ server cluster GeneralCommissioning = 48 { struct BasicCommissioningInfo { int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; } attribute access(write: administer) int64u breadcrumb = 0; @@ -2496,14 +2498,7 @@ server cluster WindowCovering = 258 { kTiltEncoderControlled = 0x40; } - bitmap Mode : BITMAP8 { - kMotorDirectionReversed = 0x1; - kCalibrationMode = 0x2; - kMaintenanceMode = 0x4; - kLedFeedback = 0x8; - } - - bitmap WcFeature : BITMAP32 { + bitmap Feature : BITMAP32 { kLift = 0x1; kTilt = 0x2; kPositionAwareLift = 0x4; @@ -2511,13 +2506,20 @@ server cluster WindowCovering = 258 { kPositionAwareTilt = 0x10; } - bitmap WcOperationalStatus : BITMAP8 { + bitmap Mode : BITMAP8 { + kMotorDirectionReversed = 0x1; + kCalibrationMode = 0x2; + kMaintenanceMode = 0x4; + kLedFeedback = 0x8; + } + + bitmap OperationalStatus : BITMAP8 { kGlobal = 0x3; kLift = 0xC; kTilt = 0x30; } - bitmap WcSafetyStatus : BITMAP16 { + bitmap SafetyStatus : BITMAP16 { kRemoteLockout = 0x1; kTamperDetection = 0x2; kFailedCommunication = 0x4; @@ -2538,7 +2540,7 @@ server cluster WindowCovering = 258 { readonly attribute ConfigStatus configStatus = 7; readonly attribute nullable Percent currentPositionLiftPercentage = 8; readonly attribute nullable Percent currentPositionTiltPercentage = 9; - readonly attribute bitmap8 operationalStatus = 10; + readonly attribute OperationalStatus operationalStatus = 10; readonly attribute nullable Percent100ths targetPositionLiftPercent100ths = 11; readonly attribute nullable Percent100ths targetPositionTiltPercent100ths = 12; readonly attribute EndProductType endProductType = 13; @@ -2549,7 +2551,7 @@ server cluster WindowCovering = 258 { readonly attribute int16u installedOpenLimitTilt = 18; readonly attribute int16u installedClosedLimitTilt = 19; attribute access(write: manage) Mode mode = 23; - readonly attribute bitmap16 safetyStatus = 26; + readonly attribute SafetyStatus safetyStatus = 26; readonly attribute bitmap32 featureMap = 65532; readonly attribute int16u clusterRevision = 65533; diff --git a/examples/platform/efr32/OTAConfig.cpp b/examples/platform/efr32/OTAConfig.cpp index f3601247f4d2ee..8f42f6951e1cdc 100644 --- a/examples/platform/efr32/OTAConfig.cpp +++ b/examples/platform/efr32/OTAConfig.cpp @@ -21,19 +21,6 @@ #include "platform/bootloader/api/application_properties.h" #include -#define BOOTLOADER_SUPPORT_CERTIFICATES 1 -#define APPLICATION_CERTIFICATE_VERSION (1UL) - -#if defined(BOOTLOADER_SUPPORT_CERTIFICATES) -const ApplicationCertificate_t sl_app_certificate = { - .structVersion = APPLICATION_CERTIFICATE_VERSION, - .flags = { 0U }, - .key = { 0U }, - .version = 0, - .signature = { 0U }, -}; -#endif - // Header used for building the image GBL file #define APP_PROPERTIES_VERSION 1 #define APP_PROPERTIES_ID \ @@ -71,15 +58,11 @@ __attribute__((used)) ApplicationProperties_t sl_app_properties = { /// Unique ID (e.g. UUID/GUID) for the product this application is built for .productId = APP_PROPERTIES_ID, }, -#if defined(BOOTLOADER_SUPPORT_CERTIFICATES) - // If certificate based boot chain is enabled, the bootloader binary will be provided with - // a certificate that does not contain any key. - // A valid certificate needs to be injected to the bootloader images using Simplicity Commander. - // Simplicity Commander will replace this certificate. - .cert = (ApplicationCertificate_t *)&sl_app_certificate, -#else + + /// Pointer to information about the certificate .cert = NULL, -#endif + + /// Pointer to Long Token Data Section .longTokenSectionAddress = NULL, }; diff --git a/examples/platform/efr32/ldscripts/efr32mg12.ld b/examples/platform/efr32/ldscripts/efr32mg12.ld index 9dba3e1ded84e2..0851b5ffdf6a60 100644 --- a/examples/platform/efr32/ldscripts/efr32mg12.ld +++ b/examples/platform/efr32/ldscripts/efr32mg12.ld @@ -255,6 +255,7 @@ SECTIONS KEEP(*(.simee*)) } > FLASH + /* Last page of flash is reserved for the manufacturing token space */ linker_nvm_end = __main_flash_end__ - 2048; linker_nvm_begin = linker_nvm_end - SIZEOF(.nvm); linker_nvm_size = SIZEOF(.nvm); diff --git a/examples/platform/efr32/ldscripts/efr32mg24.ld b/examples/platform/efr32/ldscripts/efr32mg24.ld index 06bfc7c1842170..7b19dbea1bc03f 100644 --- a/examples/platform/efr32/ldscripts/efr32mg24.ld +++ b/examples/platform/efr32/ldscripts/efr32mg24.ld @@ -255,7 +255,8 @@ SECTIONS KEEP(*(.simee*)) } > FLASH - linker_nvm_end = __main_flash_end__; + /* Last page of flash is reserved for the manufacturing token space */ + linker_nvm_end = __main_flash_end__ - 8192; linker_nvm_begin = linker_nvm_end - SIZEOF(.nvm); linker_nvm_size = SIZEOF(.nvm); __nvm3Base = linker_nvm_begin; diff --git a/examples/platform/linux/AppMain.cpp b/examples/platform/linux/AppMain.cpp index bfbc9cab2727a5..15acc38f3a5c0e 100644 --- a/examples/platform/linux/AppMain.cpp +++ b/examples/platform/linux/AppMain.cpp @@ -182,6 +182,11 @@ int ChipLinuxAppInit(int argc, char * const argv[], OptionSet * customOptions) LinuxDeviceOptions::GetInstance()); SuccessOrExit(err); + if (LinuxDeviceOptions::GetInstance().payload.rendezvousInformation.HasAny()) + { + rendezvousFlags = LinuxDeviceOptions::GetInstance().payload.rendezvousInformation; + } + err = GetPayloadContents(LinuxDeviceOptions::GetInstance().payload, rendezvousFlags); SuccessOrExit(err); @@ -289,11 +294,17 @@ void ChipLinuxAppMainLoop() // use a different service port to make testing possible with other sample devices running on same host initParams.operationalServicePort = LinuxDeviceOptions::GetInstance().securedDevicePort; initParams.userDirectedCommissioningPort = LinuxDeviceOptions::GetInstance().unsecuredCommissionerPort; - ; #endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE initParams.interfaceId = LinuxDeviceOptions::GetInstance().interfaceId; + if (LinuxDeviceOptions::GetInstance().mCSRResponseOptions.csrExistingKeyPair) + { + LinuxDeviceOptions::GetInstance().mCSRResponseOptions.badCsrOperationalKeyStoreForTest.Init( + initParams.persistentStorageDelegate); + initParams.operationalKeystore = &LinuxDeviceOptions::GetInstance().mCSRResponseOptions.badCsrOperationalKeyStoreForTest; + } + // Init ZCL Data Model and CHIP App Server Server::GetInstance().Init(initParams); diff --git a/examples/platform/linux/BUILD.gn b/examples/platform/linux/BUILD.gn index 001abb074bd530..d806ca2c6587aa 100644 --- a/examples/platform/linux/BUILD.gn +++ b/examples/platform/linux/BUILD.gn @@ -39,6 +39,10 @@ source_set("app-main") { "LinuxCommissionableDataProvider.h", "Options.cpp", "Options.h", + "testing/CustomCSRResponse.cpp", + "testing/CustomCSRResponse.h", + "testing/CustomCSRResponseOperationalKeyStore.cpp", + "testing/CustomCSRResponseOperationalKeyStore.h", ] defines = [] diff --git a/examples/platform/linux/Options.cpp b/examples/platform/linux/Options.cpp index 03b355c23735a5..6d74aa1dcc0451 100644 --- a/examples/platform/linux/Options.cpp +++ b/examples/platform/linux/Options.cpp @@ -39,29 +39,37 @@ LinuxDeviceOptions gDeviceOptions; // Follow the code style of command line arguments in case we need to add more options in the future. enum { - kDeviceOption_BleDevice = 0x1000, - kDeviceOption_WiFi = 0x1001, - kDeviceOption_Thread = 0x1002, - kDeviceOption_Version = 0x1003, - kDeviceOption_VendorID = 0x1004, - kDeviceOption_ProductID = 0x1005, - kDeviceOption_CustomFlow = 0x1006, - kDeviceOption_Capabilities = 0x1007, - kDeviceOption_Discriminator = 0x1008, - kDeviceOption_Passcode = 0x1009, - kDeviceOption_SecuredDevicePort = 0x100a, - kDeviceOption_SecuredCommissionerPort = 0x100b, - kDeviceOption_UnsecuredCommissionerPort = 0x100c, - kDeviceOption_Command = 0x100d, - kDeviceOption_PICS = 0x100e, - kDeviceOption_KVS = 0x100f, - kDeviceOption_InterfaceId = 0x1010, - kDeviceOption_Spake2pVerifierBase64 = 0x1011, - kDeviceOption_Spake2pSaltBase64 = 0x1012, - kDeviceOption_Spake2pIterations = 0x1013, - kDeviceOption_TraceFile = 0x1014, - kDeviceOption_TraceLog = 0x1015, - kDeviceOption_TraceDecode = 0x1016, + kDeviceOption_BleDevice = 0x1000, + kDeviceOption_WiFi = 0x1001, + kDeviceOption_Thread = 0x1002, + kDeviceOption_Version = 0x1003, + kDeviceOption_VendorID = 0x1004, + kDeviceOption_ProductID = 0x1005, + kDeviceOption_CustomFlow = 0x1006, + kDeviceOption_Capabilities = 0x1007, + kDeviceOption_Discriminator = 0x1008, + kDeviceOption_Passcode = 0x1009, + kDeviceOption_SecuredDevicePort = 0x100a, + kDeviceOption_SecuredCommissionerPort = 0x100b, + kDeviceOption_UnsecuredCommissionerPort = 0x100c, + kDeviceOption_Command = 0x100d, + kDeviceOption_PICS = 0x100e, + kDeviceOption_KVS = 0x100f, + kDeviceOption_InterfaceId = 0x1010, + kDeviceOption_Spake2pVerifierBase64 = 0x1011, + kDeviceOption_Spake2pSaltBase64 = 0x1012, + kDeviceOption_Spake2pIterations = 0x1013, + kDeviceOption_TraceFile = 0x1014, + kDeviceOption_TraceLog = 0x1015, + kDeviceOption_TraceDecode = 0x1016, + kOptionCSRResponseCSRIncorrectType = 0x1017, + kOptionCSRResponseCSRNonceIncorrectType = 0x1018, + kOptionCSRResponseCSRNonceTooLong = 0x1019, + kOptionCSRResponseCSRNonceInvalid = 0x101a, + kOptionCSRResponseNOCSRElementsTooLong = 0x101b, + kOptionCSRResponseAttestationSignatureIncorrectType = 0x101c, + kOptionCSRResponseAttestationSignatureInvalid = 0x101d, + kOptionCSRResponseCSRExistingKeyPair = 0x101e, }; constexpr unsigned kAppUsageLength = 64; @@ -98,6 +106,14 @@ OptionDef sDeviceOptionDefs[] = { { "trace_log", kArgumentRequired, kDeviceOption_TraceLog }, { "trace_decode", kArgumentRequired, kDeviceOption_TraceDecode }, #endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED + { "cert_error_csr_incorrect_type", kNoArgument, kOptionCSRResponseCSRIncorrectType }, + { "cert_error_csr_existing_keypair", kNoArgument, kOptionCSRResponseCSRExistingKeyPair }, + { "cert_error_csr_nonce_incorrect_type", kNoArgument, kOptionCSRResponseCSRNonceIncorrectType }, + { "cert_error_csr_nonce_too_long", kNoArgument, kOptionCSRResponseCSRNonceTooLong }, + { "cert_error_csr_nonce_invalid", kNoArgument, kOptionCSRResponseCSRNonceInvalid }, + { "cert_error_nocsrelements_too_long", kNoArgument, kOptionCSRResponseNOCSRElementsTooLong }, + { "cert_error_attestation_signature_incorrect_type", kNoArgument, kOptionCSRResponseAttestationSignatureIncorrectType }, + { "cert_error_attestation_signature_invalid", kNoArgument, kOptionCSRResponseAttestationSignatureInvalid }, {} }; @@ -183,6 +199,22 @@ const char * sDeviceOptionHelp = " --trace_decode <1/0>\n" " A value of 1 enables traces decoding, 0 disables this (default 0).\n" #endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED + " --cert_error_csr_incorrect_type\n" + " Configure the CSRResponse to be built with an invalid CSR type.\n" + " --cert_error_csr_existing_keypair\n" + " Configure the CSRResponse to be built with a CSR where the keypair already exists.\n" + " --cert_error_csr_nonce_incorrect_type\n" + " Configure the CSRResponse to be built with an invalid CSRNonce type.\n" + " --cert_error_csr_nonce_too_long\n" + " Configure the CSRResponse to be built with a CSRNonce that is longer than expected.\n" + " --cert_error_csr_nonce_invalid\n" + " Configure the CSRResponse to be built with a CSRNonce that does not match the CSRNonce from the CSRRequest.\n" + " --cert_error_nocsrelements_too_long\n" + " Configure the CSRResponse to contains an NOCSRElements larger than the allowed RESP_MAX.\n" + " --cert_error_attestation_signature_incorrect_type\n" + " Configure the CSRResponse to be build with an invalid AttestationSignature type.\n" + " --cert_error_attestation_signature_invalid\n" + " Configure the CSRResponse to be build with an AttestationSignature that does not match what is expected.\n" "\n"; bool Base64ArgToVector(const char * arg, size_t maxSize, std::vector & outVector) @@ -386,6 +418,31 @@ bool HandleOption(const char * aProgram, OptionSet * aOptions, int aIdentifier, break; #endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED + case kOptionCSRResponseCSRIncorrectType: + LinuxDeviceOptions::GetInstance().mCSRResponseOptions.csrIncorrectType = true; + break; + case kOptionCSRResponseCSRExistingKeyPair: + LinuxDeviceOptions::GetInstance().mCSRResponseOptions.csrExistingKeyPair = true; + break; + case kOptionCSRResponseCSRNonceIncorrectType: + LinuxDeviceOptions::GetInstance().mCSRResponseOptions.csrNonceIncorrectType = true; + break; + case kOptionCSRResponseCSRNonceTooLong: + LinuxDeviceOptions::GetInstance().mCSRResponseOptions.csrNonceTooLong = true; + break; + case kOptionCSRResponseCSRNonceInvalid: + LinuxDeviceOptions::GetInstance().mCSRResponseOptions.csrNonceInvalid = true; + break; + case kOptionCSRResponseNOCSRElementsTooLong: + LinuxDeviceOptions::GetInstance().mCSRResponseOptions.nocsrElementsTooLong = true; + break; + case kOptionCSRResponseAttestationSignatureIncorrectType: + LinuxDeviceOptions::GetInstance().mCSRResponseOptions.attestationSignatureIncorrectType = true; + break; + case kOptionCSRResponseAttestationSignatureInvalid: + LinuxDeviceOptions::GetInstance().mCSRResponseOptions.attestationSignatureInvalid = true; + break; + default: PrintArgError("%s: INTERNAL ERROR: Unhandled option: %s\n", aProgram, aName); retval = false; diff --git a/examples/platform/linux/Options.h b/examples/platform/linux/Options.h index ca588dc6e54a5b..56a95b772cafd8 100644 --- a/examples/platform/linux/Options.h +++ b/examples/platform/linux/Options.h @@ -35,6 +35,7 @@ #include #include +#include struct LinuxDeviceOptions { @@ -57,6 +58,7 @@ struct LinuxDeviceOptions bool traceStreamToLogEnabled = false; chip::Optional traceStreamFilename; chip::Credentials::DeviceAttestationCredentialsProvider * dacProvider = nullptr; + chip::CSRResponseOptions mCSRResponseOptions; static LinuxDeviceOptions & GetInstance(); }; diff --git a/examples/platform/linux/testing/CustomCSRResponse.cpp b/examples/platform/linux/testing/CustomCSRResponse.cpp new file mode 100644 index 00000000000000..f5009375f1dcd5 --- /dev/null +++ b/examples/platform/linux/testing/CustomCSRResponse.cpp @@ -0,0 +1,165 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Options.h" + +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters::OperationalCredentials::Commands; + +constexpr size_t kMaxResponseLength = 900; +constexpr size_t kCSRNonceLength = 32; + +namespace { + +CHIP_ERROR ConstructCustomNOCSRElements(TLV::TLVWriter & writer, TLV::Tag tag, const ByteSpan & nocsrElements, + CSRResponseOptions & options) +{ + ByteSpan csr; + ByteSpan csrNonce; + ByteSpan vendorReserved1; + ByteSpan vendorReserved2; + ByteSpan vendorReserved3; + ReturnErrorOnFailure( + Credentials::DeconstructNOCSRElements(nocsrElements, csr, csrNonce, vendorReserved1, vendorReserved2, vendorReserved3)); + + // Add 10 bytes of possible overhead to allow the generation of content longer than the allowed maximum of RESP_MAX. + // 10 has been choosen to leave enough space for the possible TLV overhead when adding the additional data. + uint8_t nocsrElementsData[kMaxResponseLength + 10]; + MutableByteSpan nocsrElementsSpan(nocsrElementsData); + + TLV::TLVType outerContainerType = TLV::kTLVType_NotSpecified; + TLV::TLVWriter tlvWriter; + tlvWriter.Init(nocsrElementsSpan); + + ReturnErrorOnFailure(tlvWriter.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType)); + + // Update CSR + if (options.csrIncorrectType) + { + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(1), true)); + } + else + { + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(1), csr)); + } + + // Update CSRNonce + if (options.csrNonceIncorrectType) + { + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(2), true)); + } + else if (options.csrNonceInvalid) + { + uint8_t csrNonceInvalid[kCSRNonceLength] = {}; + memcpy(csrNonceInvalid, csrNonce.data(), csrNonce.size()); + std::reverse(csrNonceInvalid, csrNonceInvalid + sizeof(csrNonceInvalid)); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(2), ByteSpan(csrNonceInvalid))); + } + else if (options.csrNonceTooLong) + { + uint8_t csrNonceTooLong[kCSRNonceLength + 1] = {}; + memcpy(csrNonceTooLong, csrNonce.data(), csrNonce.size()); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(2), ByteSpan(csrNonceTooLong))); + } + else + { + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(2), csrNonce)); + } + + // Add vendorReserved1 if present + if (!vendorReserved1.empty()) + { + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(3), vendorReserved1)); + } + + // Add vendorReserved2 if present + if (!vendorReserved2.empty()) + { + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(4), vendorReserved2)); + } + + // Add vendorReserved3 if present + if (!vendorReserved3.empty()) + { + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(5), vendorReserved3)); + } + + // Add additional data + if (options.nocsrElementsTooLong) + { + size_t len = kMaxResponseLength - tlvWriter.GetLengthWritten(); + ReturnLogErrorOnFailure(tlvWriter.Put(TLV::ContextTag(6), ByteSpan(nocsrElementsData, len))); + } + + ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType)); + ReturnErrorOnFailure(tlvWriter.Finalize()); + + return DataModel::Encode(writer, tag, nocsrElementsSpan.SubSpan(0, tlvWriter.GetLengthWritten())); +} + +CHIP_ERROR ConstructCustomAttestationSignature(TLV::TLVWriter & writer, TLV::Tag tag, const ByteSpan & attestationSignature, + CSRResponseOptions & options) +{ + if (options.attestationSignatureIncorrectType) + { + return DataModel::Encode(writer, tag, true); + } + + if (options.attestationSignatureInvalid) + { + uint8_t invalidAttestationSignature[Crypto::kP256_ECDSA_Signature_Length_Raw] = {}; + memcpy(invalidAttestationSignature, attestationSignature.data(), attestationSignature.size()); + std::reverse(invalidAttestationSignature, invalidAttestationSignature + sizeof(invalidAttestationSignature)); + return DataModel::Encode(writer, tag, ByteSpan(invalidAttestationSignature)); + } + + return DataModel::Encode(writer, tag, attestationSignature); +} + +} // namespace + +namespace chip { +namespace app { +namespace DataModel { + +template <> +CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag, const CSRResponse::Type & responseData) +{ + auto tag1 = TLV::ContextTag(to_underlying(CSRResponse::Fields::kNOCSRElements)); + auto tag2 = TLV::ContextTag(to_underlying(CSRResponse::Fields::kAttestationSignature)); + auto & options = LinuxDeviceOptions::GetInstance().mCSRResponseOptions; + + TLV::TLVType outer; + ReturnErrorOnFailure(writer.StartContainer(tag, TLV::kTLVType_Structure, outer)); + ReturnErrorOnFailure(ConstructCustomNOCSRElements(writer, tag1, responseData.NOCSRElements, options)); + ReturnErrorOnFailure(ConstructCustomAttestationSignature(writer, tag2, responseData.attestationSignature, options)); + ReturnErrorOnFailure(writer.EndContainer(outer)); + + return CHIP_NO_ERROR; +} + +} // namespace DataModel +} // namespace app +} // namespace chip diff --git a/examples/platform/linux/testing/CustomCSRResponse.h b/examples/platform/linux/testing/CustomCSRResponse.h new file mode 100644 index 00000000000000..2027a9223e3915 --- /dev/null +++ b/examples/platform/linux/testing/CustomCSRResponse.h @@ -0,0 +1,36 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CustomCSRResponseOperationalKeyStore.h" + +namespace chip { + +struct CSRResponseOptions +{ + bool csrIncorrectType = false; + bool csrExistingKeyPair = false; + bool csrNonceIncorrectType = false; + bool csrNonceTooLong = false; + bool csrNonceInvalid = false; + bool nocsrElementsTooLong = false; + bool attestationSignatureIncorrectType = false; + bool attestationSignatureInvalid = false; + CustomCSRResponseOperationalKeyStore badCsrOperationalKeyStoreForTest; +}; + +} // namespace chip diff --git a/examples/platform/linux/testing/CustomCSRResponseOperationalKeyStore.cpp b/examples/platform/linux/testing/CustomCSRResponseOperationalKeyStore.cpp new file mode 100644 index 00000000000000..cbdb3802f80813 --- /dev/null +++ b/examples/platform/linux/testing/CustomCSRResponseOperationalKeyStore.cpp @@ -0,0 +1,131 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CustomCSRResponseOperationalKeyStore.h" + +#include +#include +#include + +namespace chip { + +namespace { +// Tags for our operational keypair storage. +constexpr TLV::Tag kOpKeyVersionTag = TLV::ContextTag(0); +constexpr TLV::Tag kOpKeyDataTag = TLV::ContextTag(1); + +constexpr size_t OpKeyTLVMaxSize() +{ + // Version and serialized key + return TLV::EstimateStructOverhead(sizeof(uint16_t), Crypto::P256SerializedKeypair::Capacity()); +} +} // namespace + +CHIP_ERROR CustomCSRResponseOperationalKeyStore::NewOpKeypairForFabric(FabricIndex fabricIndex, + MutableByteSpan & outCertificateSigningRequest) +{ + if (fabricIndex == 1) + { + return PersistentStorageOperationalKeystore::NewOpKeypairForFabric(fabricIndex, outCertificateSigningRequest); + } + + return ReuseOpKeypair(fabricIndex, outCertificateSigningRequest); +} + +CHIP_ERROR CustomCSRResponseOperationalKeyStore::ReuseOpKeypair(FabricIndex fabricIndex, MutableByteSpan & outCSR) +{ + // + // DO NOT COPY THIS METHOD - IT IS FOR TESTING PURPOSES ONLY + // + + VerifyOrReturnError(mStorage != nullptr, CHIP_ERROR_INCORRECT_STATE); + + // Replace previous pending keypair, if any was previously allocated + ResetPendingKey(); + + mPendingKeypair = Platform::New(); + VerifyOrReturnError(mPendingKeypair != nullptr, CHIP_ERROR_NO_MEMORY); + + // Scope 1: Load up the keypair data from storage + { + // Use a CapacityBoundBuffer to get RAII secret data clearing on scope exit. + Crypto::CapacityBoundBuffer buf; + + // Load up the operational key structure from storage + uint16_t size = static_cast(buf.Capacity()); + DefaultStorageKeyAllocator keyAlloc; + + // In order to retrieve a keypair that has already been registered, assume the device + // as already been commissioned and fabric index 1 is the registered fabric. + CHIP_ERROR err = mStorage->SyncGetKeyValue(keyAlloc.FabricOpKey(1 /* fabricIndex */), buf.Bytes(), size); + if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) + { + err = CHIP_ERROR_INVALID_FABRIC_INDEX; + } + ReturnErrorOnFailure(err); + buf.SetLength(static_cast(size)); + + // Read-out the operational key TLV entry. + TLV::ContiguousBufferTLVReader reader; + reader.Init(buf.Bytes(), buf.Length()); + + ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag())); + TLV::TLVType containerType; + ReturnErrorOnFailure(reader.EnterContainer(containerType)); + + ReturnErrorOnFailure(reader.Next(kOpKeyVersionTag)); + uint16_t opKeyVersion; + ReturnErrorOnFailure(reader.Get(opKeyVersion)); + + ReturnErrorOnFailure(reader.Next(kOpKeyDataTag)); + { + ByteSpan keyData; + Crypto::P256SerializedKeypair serializedOpKey; + ReturnErrorOnFailure(reader.GetByteView(keyData)); + + // Unfortunately, we have to copy the data into a P256SerializedKeypair. + VerifyOrReturnError(keyData.size() <= serializedOpKey.Capacity(), CHIP_ERROR_BUFFER_TOO_SMALL); + + // Before doing anything with the key, validate format further. + ReturnErrorOnFailure(reader.ExitContainer(containerType)); + ReturnErrorOnFailure(reader.VerifyEndOfContainer()); + + memcpy(serializedOpKey.Bytes(), keyData.data(), keyData.size()); + serializedOpKey.SetLength(keyData.size()); + + // Load-up key material + // WARNING: This makes use of the raw key bits + ReturnErrorOnFailure(mPendingKeypair->Deserialize(serializedOpKey)); + } + } + + size_t outCSRLength = outCSR.size(); + CHIP_ERROR err = mPendingKeypair->NewCertificateSigningRequest(outCSR.data(), outCSRLength); + if (CHIP_NO_ERROR != err) + { + ResetPendingKey(); + return err; + } + + outCSR.reduce_size(outCSRLength); + mPendingFabricIndex = fabricIndex; + + return CHIP_NO_ERROR; +} + +} // namespace chip diff --git a/examples/platform/linux/testing/CustomCSRResponseOperationalKeyStore.h b/examples/platform/linux/testing/CustomCSRResponseOperationalKeyStore.h new file mode 100644 index 00000000000000..4da015f110ab63 --- /dev/null +++ b/examples/platform/linux/testing/CustomCSRResponseOperationalKeyStore.h @@ -0,0 +1,34 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +namespace chip { + +class CustomCSRResponseOperationalKeyStore : public PersistentStorageOperationalKeystore +{ +public: + CHIP_ERROR NewOpKeypairForFabric(FabricIndex fabricIndex, MutableByteSpan & outCertificateSigningRequest) override; + +private: + CHIP_ERROR ReuseOpKeypair(FabricIndex fabricIndex, MutableByteSpan & outCertificateSigningRequest); +}; + +} // namespace chip diff --git a/examples/platform/nrfconnect/pw_sys_io/CMakeLists.txt b/examples/platform/nrfconnect/pw_sys_io/CMakeLists.txt index 466168e405d097..9e3a33c158b099 100644 --- a/examples/platform/nrfconnect/pw_sys_io/CMakeLists.txt +++ b/examples/platform/nrfconnect/pw_sys_io/CMakeLists.txt @@ -14,4 +14,5 @@ pw_add_module_library(pw_sys_io.nrfconnect PRIVATE_DEPS pw_sys_io suppress_zephyr_warnings + pw_sys_io.default_putget_bytes ) diff --git a/examples/pump-app/nrfconnect/README.md b/examples/pump-app/nrfconnect/README.md index 515c64272e0d1d..94df485f7afe4a 100644 --- a/examples/pump-app/nrfconnect/README.md +++ b/examples/pump-app/nrfconnect/README.md @@ -17,7 +17,8 @@ Semiconductor's nRF Connect SDK, and supports remote access and control of a simulated pump over a low-power, 802.15.4 Thread network. The example behaves as a Matter accessory, that is a device that can be paired -into an existing Matter network and can be controlled by this network. +into an existing Matter network and can be controlled by this network. The +device works as a Thread Minimal End Device.
diff --git a/examples/pump-app/pump-common/pump-app.matter b/examples/pump-app/pump-common/pump-app.matter index f9f71aafd60633..4e1febd4c9a69f 100644 --- a/examples/pump-app/pump-common/pump-app.matter +++ b/examples/pump-app/pump-common/pump-app.matter @@ -215,6 +215,7 @@ server cluster GeneralCommissioning = 48 { struct BasicCommissioningInfo { int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; } attribute access(write: administer) int64u breadcrumb = 0; diff --git a/examples/pump-controller-app/nrfconnect/README.md b/examples/pump-controller-app/nrfconnect/README.md index b3e9c279e36d11..81e5e23b1f81d9 100644 --- a/examples/pump-controller-app/nrfconnect/README.md +++ b/examples/pump-controller-app/nrfconnect/README.md @@ -18,7 +18,8 @@ Semiconductor's nRF Connect SDK, and supports remote access and control of a simulated pump over a low-power, 802.15.4 Thread network. The example behaves as a Matter accessory, that is a device that can be paired -into an existing Matter network and can be controlled by this network. +into an existing Matter network and can be controlled by this network. The +device works as a Thread Minimal End Device.
diff --git a/examples/pump-controller-app/pump-controller-common/pump-controller-app.matter b/examples/pump-controller-app/pump-controller-common/pump-controller-app.matter index bd4f0b6618d76a..5c9fd57944fd1b 100644 --- a/examples/pump-controller-app/pump-controller-common/pump-controller-app.matter +++ b/examples/pump-controller-app/pump-controller-common/pump-controller-app.matter @@ -238,6 +238,7 @@ server cluster GeneralCommissioning = 48 { struct BasicCommissioningInfo { int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; } attribute access(write: administer) int64u breadcrumb = 0; diff --git a/examples/shell/efr32/args.gni b/examples/shell/efr32/args.gni index 9d49561c413334..a80bfb32a7e784 100644 --- a/examples/shell/efr32/args.gni +++ b/examples/shell/efr32/args.gni @@ -19,7 +19,7 @@ import("${chip_root}/src/platform/EFR32/args.gni") efr32_sdk_target = get_label_info(":sdk", "label_no_toolchain") pw_log_BACKEND = "${chip_root}/src/lib/support/pw_log_chip" -pw_assert_BACKEND = "$dir_pw_assert_log" +pw_assert_BACKEND = "$dir_pw_assert_log:check_backend" chip_enable_openthread = true chip_openthread_ftd = true chip_build_libshell = true diff --git a/examples/shell/qpg/args.gni b/examples/shell/qpg/args.gni index aa5f8f16d9ed27..46bcd2aa1b8297 100644 --- a/examples/shell/qpg/args.gni +++ b/examples/shell/qpg/args.gni @@ -19,7 +19,7 @@ import("${chip_root}/examples/platform/qpg/args.gni") qpg_sdk_target = get_label_info(":sdk", "label_no_toolchain") pw_log_BACKEND = "${chip_root}/src/lib/support/pw_log_chip" -pw_assert_BACKEND = "$dir_pw_assert_log" +pw_assert_BACKEND = "$dir_pw_assert_log:check_backend" chip_build_libshell = true # Disable lock tracking, since our FreeRTOS configuration does not set diff --git a/examples/temperature-measurement-app/esp32/CMakeLists.txt b/examples/temperature-measurement-app/esp32/CMakeLists.txt index aacc392404c4ea..6bd79c439c876a 100644 --- a/examples/temperature-measurement-app/esp32/CMakeLists.txt +++ b/examples/temperature-measurement-app/esp32/CMakeLists.txt @@ -50,8 +50,10 @@ flashing_script() if (CONFIG_ENABLE_PW_RPC) get_filename_component(CHIP_ROOT ./third_party/connectedhomeip REALPATH) include(third_party/connectedhomeip/third_party/pigweed/repo/pw_build/pigweed.cmake) +pw_set_module_config(pw_rpc_CONFIG pw_rpc.disable_global_mutex_config) pw_set_backend(pw_log pw_log_basic) -pw_set_backend(pw_assert pw_assert_log) +pw_set_backend(pw_assert.check pw_assert_log.check_backend) +pw_set_backend(pw_assert.assert pw_assert.assert_compatibility_backend) pw_set_backend(pw_sys_io pw_sys_io.esp32) add_subdirectory(third_party/connectedhomeip/third_party/pigweed/repo) diff --git a/examples/temperature-measurement-app/esp32/main/CMakeLists.txt b/examples/temperature-measurement-app/esp32/main/CMakeLists.txt index 1eca5dec454e18..f8a313a8e632df 100644 --- a/examples/temperature-measurement-app/esp32/main/CMakeLists.txt +++ b/examples/temperature-measurement-app/esp32/main/CMakeLists.txt @@ -101,7 +101,7 @@ pw_proto_library(attributes_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(button_service @@ -112,7 +112,7 @@ pw_proto_library(button_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(descriptor_service @@ -123,7 +123,7 @@ pw_proto_library(descriptor_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(device_service @@ -136,7 +136,7 @@ pw_proto_library(device_service STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto ) pw_proto_library(wifi_service @@ -147,7 +147,7 @@ pw_proto_library(wifi_service PREFIX wifi_service DEPS - pw_protobuf.common_protos + pw_protobuf.common_proto STRIP_PREFIX ${CHIP_ROOT}/examples/common/pigweed/protos ) diff --git a/examples/temperature-measurement-app/esp32/main/temperature-measurement.matter b/examples/temperature-measurement-app/esp32/main/temperature-measurement.matter index c16c8aad728bde..335c0909c0729b 100644 --- a/examples/temperature-measurement-app/esp32/main/temperature-measurement.matter +++ b/examples/temperature-measurement-app/esp32/main/temperature-measurement.matter @@ -223,6 +223,8 @@ server cluster EthernetNetworkDiagnostics = 55 { readonly attribute int64u timeSinceReset = 8; readonly attribute bitmap32 featureMap = 65532; readonly attribute int16u clusterRevision = 65533; + + command ResetCounts(): DefaultSuccess = 0; } server cluster FixedLabel = 64 { @@ -248,6 +250,7 @@ server cluster GeneralCommissioning = 48 { struct BasicCommissioningInfo { int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; } attribute access(write: administer) int64u breadcrumb = 0; @@ -389,6 +392,73 @@ server cluster GeneralDiagnostics = 51 { command TestEventTrigger(TestEventTriggerRequest): DefaultSuccess = 0; } +server cluster GroupKeyManagement = 63 { + enum GroupKeySecurityPolicy : ENUM8 { + kTrustFirst = 0; + kCacheAndSync = 1; + } + + struct GroupKeyMapStruct { + group_id groupId = 1; + int16u groupKeySetID = 2; + fabric_idx fabricIndex = 254; + } + + struct GroupInfoMapStruct { + group_id groupId = 1; + endpoint_no endpoints[] = 2; + optional char_string<16> groupName = 3; + fabric_idx fabricIndex = 254; + } + + struct GroupKeySetStruct { + int16u groupKeySetID = 0; + GroupKeySecurityPolicy groupKeySecurityPolicy = 1; + nullable octet_string<16> epochKey0 = 2; + nullable epoch_us epochStartTime0 = 3; + nullable octet_string<16> epochKey1 = 4; + nullable epoch_us epochStartTime1 = 5; + nullable octet_string<16> epochKey2 = 6; + nullable epoch_us epochStartTime2 = 7; + } + + attribute access(write: manage) GroupKeyMapStruct groupKeyMap[] = 0; + readonly attribute GroupInfoMapStruct groupTable[] = 1; + readonly attribute int16u maxGroupsPerFabric = 2; + readonly attribute int16u maxGroupKeysPerFabric = 3; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct KeySetWriteRequest { + GroupKeySetStruct groupKeySet = 0; + } + + request struct KeySetReadRequest { + INT16U groupKeySetID = 0; + } + + request struct KeySetRemoveRequest { + INT16U groupKeySetID = 0; + } + + request struct KeySetReadAllIndicesRequest { + INT16U groupKeySetIDs[] = 0; + } + + response struct KeySetReadResponse = 2 { + GroupKeySetStruct groupKeySet = 0; + } + + response struct KeySetReadAllIndicesResponse = 5 { + INT16U groupKeySetIDs[] = 0; + } + + command access(invoke: administer) KeySetWrite(KeySetWriteRequest): DefaultSuccess = 0; + command access(invoke: administer) KeySetRead(KeySetReadRequest): KeySetReadResponse = 1; + command access(invoke: administer) KeySetRemove(KeySetRemoveRequest): DefaultSuccess = 3; + command access(invoke: administer) KeySetReadAllIndices(KeySetReadAllIndicesRequest): KeySetReadAllIndicesResponse = 4; +} + server cluster LocalizationConfiguration = 43 { attribute char_string<35> activeLocale = 0; readonly attribute CHAR_STRING supportedLocales[] = 1; @@ -932,6 +1002,15 @@ endpoint 0 { ram attribute clusterRevision default = 1; } + server cluster GroupKeyManagement { + callback attribute groupKeyMap; + callback attribute groupTable; + callback attribute maxGroupsPerFabric; + callback attribute maxGroupKeysPerFabric; + ram attribute featureMap; + ram attribute clusterRevision default = 1; + } + server cluster FixedLabel { callback attribute labelList; ram attribute featureMap; diff --git a/examples/temperature-measurement-app/esp32/main/temperature-measurement.zap b/examples/temperature-measurement-app/esp32/main/temperature-measurement.zap index 4cba0333374e3d..eb56cfbf3dfac0 100644 --- a/examples/temperature-measurement-app/esp32/main/temperature-measurement.zap +++ b/examples/temperature-measurement-app/esp32/main/temperature-measurement.zap @@ -2494,7 +2494,7 @@ "code": 0, "mfgCode": null, "source": "client", - "incoming": 0, + "incoming": 1, "outgoing": 1 } ], @@ -3111,6 +3111,190 @@ } ] }, + { + "name": "Group Key Management", + "code": 63, + "mfgCode": null, + "define": "GROUP_KEY_MANAGEMENT_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "KeySetWrite", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "KeySetRead", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "KeySetRemove", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "KeySetReadAllIndices", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Group Key Management", + "code": 63, + "mfgCode": null, + "define": "GROUP_KEY_MANAGEMENT_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "KeySetReadResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "KeySetReadAllIndicesResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "GroupKeyMap", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "GroupTable", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MaxGroupsPerFabric", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxGroupKeysPerFabric", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, { "name": "Fixed Label", "code": 64, @@ -4389,4 +4573,4 @@ "deviceIdentifier": 770 } ] -} \ No newline at end of file +} diff --git a/examples/thermostat/thermostat-common/thermostat.matter b/examples/thermostat/thermostat-common/thermostat.matter index 6dcea48abc753b..a86aad69a981d9 100644 --- a/examples/thermostat/thermostat-common/thermostat.matter +++ b/examples/thermostat/thermostat-common/thermostat.matter @@ -262,6 +262,7 @@ server cluster GeneralCommissioning = 48 { struct BasicCommissioningInfo { int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; } attribute access(write: administer) int64u breadcrumb = 0; diff --git a/examples/tv-app/android/App/common-api/src/main/java/com/matter/tv/app/api/MatterIntentConstants.java b/examples/tv-app/android/App/common-api/src/main/java/com/matter/tv/app/api/MatterIntentConstants.java index 4ee15e4a84c496..d5e95061b6f6c5 100644 --- a/examples/tv-app/android/App/common-api/src/main/java/com/matter/tv/app/api/MatterIntentConstants.java +++ b/examples/tv-app/android/App/common-api/src/main/java/com/matter/tv/app/api/MatterIntentConstants.java @@ -17,4 +17,7 @@ public class MatterIntentConstants { public static final String EXTRA_DIRECTIVE_RESPONSE_PENDING_INTENT = "EXTRA_DIRECTIVE_RESPONSE_PENDING_INTENT"; + + public static final String EXTRA_COMMAND_ID = "EXTRA_COMMAND_ID"; + public static final String EXTRA_CLUSTER_ID = "EXTRA_CLUSTER_ID"; } diff --git a/examples/tv-app/android/App/content-app/src/main/AndroidManifest.xml b/examples/tv-app/android/App/content-app/src/main/AndroidManifest.xml index 9ba74639750d1d..e9fa3b028f6f58 100644 --- a/examples/tv-app/android/App/content-app/src/main/AndroidManifest.xml +++ b/examples/tv-app/android/App/content-app/src/main/AndroidManifest.xml @@ -18,7 +18,7 @@ android:theme="@style/Theme.ContentApp"> - + - diff --git a/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/handlers/ContentAppEndpointManagerImpl.java b/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/handlers/ContentAppEndpointManagerImpl.java index 035e7cd84e8c44..56575545883a32 100644 --- a/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/handlers/ContentAppEndpointManagerImpl.java +++ b/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/handlers/ContentAppEndpointManagerImpl.java @@ -16,14 +16,15 @@ public ContentAppEndpointManagerImpl(Context context) { this.context = context; } - public String sendCommand(int endpointId, String commandPayload) { + public String sendCommand(int endpointId, int clusterId, int commandId, String commandPayload) { Log.d(TAG, "Received a command for endpointId " + endpointId + ". Message " + commandPayload); for (ContentApp app : ContentAppDiscoveryService.getReceiverInstance().getDiscoveredContentApps().values()) { if (app.getEndpointId() == endpointId) { Log.d( TAG, "Sending a command for endpointId " + endpointId + ". Message " + commandPayload); - ContentAppAgentService.sendCommand(context, app.getAppName(), commandPayload); + return ContentAppAgentService.sendCommand( + context, app.getAppName(), clusterId, commandId, commandPayload); } } return "Success"; diff --git a/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/service/ContentAppAgentService.java b/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/service/ContentAppAgentService.java index b1799990f99575..ccc72e4a9221b2 100644 --- a/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/service/ContentAppAgentService.java +++ b/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/service/ContentAppAgentService.java @@ -11,6 +11,7 @@ import androidx.annotation.Nullable; import com.matter.tv.app.api.IMatterAppAgent; import com.matter.tv.app.api.MatterIntentConstants; +import java.util.concurrent.TimeUnit; public class ContentAppAgentService extends Service { @@ -20,6 +21,8 @@ public class ContentAppAgentService extends Service { public static final String EXTRA_RESPONSE_RECEIVING_PACKAGE = "EXTRA_RESPONSE_RECEIVING_PACKAGE"; public static final String EXTRA_RESPONSE_ID = "EXTRA_RESPONSE_ID"; + private static ResponseRegistry responseRegistry = new ResponseRegistry(); + private final IBinder appAgentBinder = new IMatterAppAgent.Stub() { @Override @@ -51,23 +54,34 @@ public IBinder onBind(final Intent intent) { return null; } - public static void sendCommand(Context context, String packageName, String payload) { + public static String sendCommand( + Context context, String packageName, int clusterId, int commandId, String payload) { Intent in = new Intent(MatterIntentConstants.ACTION_MATTER_COMMAND); Bundle extras = new Bundle(); extras.putByteArray(MatterIntentConstants.EXTRA_COMMAND_PAYLOAD, payload.getBytes()); + extras.putInt(MatterIntentConstants.EXTRA_COMMAND_ID, commandId); + extras.putInt(MatterIntentConstants.EXTRA_CLUSTER_ID, clusterId); in.putExtras(extras); in.setPackage(packageName); int flags = Intent.FLAG_INCLUDE_STOPPED_PACKAGES; flags |= Intent.FLAG_RECEIVER_FOREGROUND; in.setFlags(flags); + int messageId = responseRegistry.getNextMessageCounter(); in.putExtra( MatterIntentConstants.EXTRA_DIRECTIVE_RESPONSE_PENDING_INTENT, - getPendingIntentForResponse(context, packageName, "0")); + getPendingIntentForResponse(context, packageName, messageId)); context.sendBroadcast(in); + responseRegistry.waitForMessage(messageId, 10, TimeUnit.SECONDS); + String response = responseRegistry.readAndRemoveResponse(messageId); + if (response == null) { + response = ""; + } + Log.d(TAG, "Response " + response + " being returned for message " + messageId); + return response; } private static PendingIntent getPendingIntentForResponse( - final Context context, final String targetPackage, final String responseId) { + final Context context, final String targetPackage, final int responseId) { Intent ackBackIntent = new Intent(ACTION_MATTER_RESPONSE); ackBackIntent.setClass(context, ContentAppAgentService.class); ackBackIntent.putExtra(EXTRA_RESPONSE_RECEIVING_PACKAGE, targetPackage); @@ -78,16 +92,13 @@ private static PendingIntent getPendingIntentForResponse( @Override public int onStartCommand(final Intent intent, final int flags, final int startId) { - Log.d(TAG, "onStartCommand"); - if (intent != null && ACTION_MATTER_RESPONSE.equals(intent.getAction())) { - Log.d( - TAG, - "Command response " - + new String(intent.getByteArrayExtra(MatterIntentConstants.EXTRA_RESPONSE_PAYLOAD))); - // Send the response back to the client. + String response = + new String(intent.getByteArrayExtra(MatterIntentConstants.EXTRA_RESPONSE_PAYLOAD)); + int messageId = intent.getIntExtra(EXTRA_RESPONSE_ID, Integer.MAX_VALUE); + Log.d(TAG, "Response " + response + " received for message " + messageId); + responseRegistry.receivedMessageResponse(messageId, response); } - return START_NOT_STICKY; } } diff --git a/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/service/MatterServant.java b/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/service/MatterServant.java index 06fa8fdd06fc82..bd11cb5c525d8f 100644 --- a/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/service/MatterServant.java +++ b/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/service/MatterServant.java @@ -26,6 +26,7 @@ import chip.platform.AndroidChipPlatform; import chip.platform.ChipMdnsCallbackImpl; import chip.platform.DiagnosticDataProviderImpl; +import chip.platform.NsdManagerServiceBrowser; import chip.platform.NsdManagerServiceResolver; import chip.platform.PreferencesConfigurationManager; import chip.platform.PreferencesKeyValueStoreManager; @@ -132,6 +133,7 @@ public void onCommissioningComplete() { new PreferencesKeyValueStoreManager(applicationContext), new PreferencesConfigurationManager(applicationContext), new NsdManagerServiceResolver(applicationContext), + new NsdManagerServiceBrowser(applicationContext), new ChipMdnsCallbackImpl(), new DiagnosticDataProviderImpl(applicationContext)); @@ -143,7 +145,7 @@ public void onCommissioningComplete() { chipAppServer = new ChipAppServer(); chipAppServer.startApp(); - mTvApp.postServerInit(); + mTvApp.postServerInit(new ContentAppEndpointManagerImpl(context)); } public void restart() { diff --git a/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/service/ResponseRegistry.java b/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/service/ResponseRegistry.java new file mode 100644 index 00000000000000..9c1ebc0c0b6031 --- /dev/null +++ b/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/service/ResponseRegistry.java @@ -0,0 +1,58 @@ +package com.matter.tv.server.service; + +import android.util.Log; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +public class ResponseRegistry { + + private static final String TAG = "ResponseRegistry"; + + private AtomicInteger messageCounter = new AtomicInteger(); + + private Map responses = new ConcurrentHashMap<>(); + + private Map latches = new ConcurrentHashMap<>(); + + public int getNextMessageCounter() { + int counter = messageCounter.incrementAndGet(); + // MAX_VALUE used for error scenarios + if (counter == Integer.MAX_VALUE) { + counter = messageCounter.incrementAndGet(); + } + latches.put(counter, new CountDownLatch(1)); + return counter; + } + + public void waitForMessage(int counter, long timeout, TimeUnit unit) { + CountDownLatch latch = latches.get(counter); + if (latch == null) { + return; + } + try { + if (!latch.await(timeout, unit)) { + Log.i(TAG, "Timed out while waiting for response for message " + counter); + } + } catch (InterruptedException e) { + Log.i(TAG, "Interrupted while waiting for response for message " + counter); + } + } + + public void receivedMessageResponse(int counter, String response) { + CountDownLatch latch = latches.remove(counter); + if (latch == null) { + // no point adding response to memory if no one is going to read it. + return; + } + responses.put(counter, response); + latch.countDown(); + } + + public String readAndRemoveResponse(int counter) { + // caller should manage null values + return responses.remove(counter); + } +} diff --git a/examples/tv-app/android/BUILD.gn b/examples/tv-app/android/BUILD.gn index b227f97fe47101..e478c946d3b9d7 100644 --- a/examples/tv-app/android/BUILD.gn +++ b/examples/tv-app/android/BUILD.gn @@ -78,6 +78,7 @@ shared_library("jni") { "${chip_root}/examples/tv-app/tv-common", "${chip_root}/src/app/server/java:jni", "${chip_root}/src/lib", + "${chip_root}/src/lib/support/jsontlv", "${chip_root}/third_party/inipp", ] @@ -108,7 +109,6 @@ android_library("java") { "java/src/com/tcl/chip/tvapp/ChannelManagerStub.java", "java/src/com/tcl/chip/tvapp/Clusters.java", "java/src/com/tcl/chip/tvapp/ContentAppEndpointManager.java", - "java/src/com/tcl/chip/tvapp/ContentAppEndpointManagerStub.java", "java/src/com/tcl/chip/tvapp/ContentLaunchBrandingInformation.java", "java/src/com/tcl/chip/tvapp/ContentLaunchManager.java", "java/src/com/tcl/chip/tvapp/ContentLaunchManagerStub.java", diff --git a/examples/tv-app/android/java/AppImpl.cpp b/examples/tv-app/android/java/AppImpl.cpp index 61f770a4c09383..a0564d2efc3832 100644 --- a/examples/tv-app/android/java/AppImpl.cpp +++ b/examples/tv-app/android/java/AppImpl.cpp @@ -21,11 +21,13 @@ #include "AppImpl.h" +#include "ContentAppCommandDelegate.h" #include #include #include #include #include +#include #include #include #include @@ -328,12 +330,12 @@ ContentApp * ContentAppFactoryImpl::LoadContentApp(const CatalogVendorApp & vend { auto & app = mContentApps.at(i); - ChipLogProgress(DeviceLayer, " Looking next=%s ", app.GetApplicationBasicDelegate()->GetCatalogVendorApp()->applicationId); - if (app.GetApplicationBasicDelegate()->GetCatalogVendorApp()->Matches(vendorApp)) + ChipLogProgress(DeviceLayer, " Looking next=%s ", app->GetApplicationBasicDelegate()->GetCatalogVendorApp()->applicationId); + if (app->GetApplicationBasicDelegate()->GetCatalogVendorApp()->Matches(vendorApp)) { - ContentAppPlatform::GetInstance().AddContentApp(&app, &contentAppEndpoint, Span(gDataVersions[i]), + ContentAppPlatform::GetInstance().AddContentApp(app, &contentAppEndpoint, Span(gDataVersions[i]), Span(gContentAppDeviceType)); - return &app; + return app; } } ChipLogProgress(DeviceLayer, "LoadContentAppByAppId NOT FOUND catalogVendorId=%d applicationId=%s ", vendorApp.catalogVendorId, @@ -342,13 +344,13 @@ ContentApp * ContentAppFactoryImpl::LoadContentApp(const CatalogVendorApp & vend return nullptr; } -EndpointId ContentAppFactoryImpl::AddContentApp(ContentAppImpl & app) +EndpointId ContentAppFactoryImpl::AddContentApp(ContentAppImpl * app) { DataVersion dataVersionBuf[ArraySize(contentAppClusters)]; - EndpointId epId = ContentAppPlatform::GetInstance().AddContentApp(&app, &contentAppEndpoint, Span(dataVersionBuf), + EndpointId epId = ContentAppPlatform::GetInstance().AddContentApp(app, &contentAppEndpoint, Span(dataVersionBuf), Span(gContentAppDeviceType)); ChipLogProgress(DeviceLayer, "ContentAppFactoryImpl AddContentApp endpoint returned %d. Endpoint set %d", epId, - app.GetEndpointId()); + app->GetEndpointId()); mContentApps.push_back(app); return epId; } @@ -380,9 +382,9 @@ void ContentAppFactoryImpl::SendTestMessage(EndpointId epId, const char * messag ChipLogProgress(DeviceLayer, "ContentAppFactoryImpl SendTestMessage called with message %s & endpointId %d", message, epId); for (size_t i = 0; i < mContentApps.size(); ++i) { - ContentAppImpl app = mContentApps.at(i); - ChipLogProgress(DeviceLayer, "ContentAppFactoryImpl checking app with endpointId %d", app.ContentApp::GetEndpointId()); - if (app.GetEndpointId() == epId) + ContentAppImpl * app = mContentApps.at(i); + ChipLogProgress(DeviceLayer, "ContentAppFactoryImpl checking app with endpointId %d", app->GetEndpointId()); + if (app->GetEndpointId() == epId) { ChipLogProgress(DeviceLayer, "ContentAppFactoryImpl SendTestMessage endpoint found"); app::ConcreteCommandPath commandPath(epId, app::Clusters::ContentLauncher::Id, @@ -391,8 +393,8 @@ void ContentAppFactoryImpl::SendTestMessage(EndpointId epId, const char * messag app::CommandHandler commandHandler(&callback); CommandResponseHelper helper(&commandHandler, commandPath); chip::app::Clusters::ContentLauncher::Structs::BrandingInformation::Type branding; - app.GetContentLauncherDelegate()->HandleLaunchUrl(helper, CharSpan::fromCharString(message), - CharSpan::fromCharString("Temp Display"), branding); + app->GetContentLauncherDelegate()->HandleLaunchUrl(helper, CharSpan::fromCharString(message), + CharSpan::fromCharString("Temp Display"), branding); } } } @@ -402,11 +404,21 @@ void ContentAppFactoryImpl::SendTestMessage(EndpointId epId, const char * messag #endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED -CHIP_ERROR InitVideoPlayerPlatform(JNIMyUserPrompter * userPrompter) +CHIP_ERROR InitVideoPlayerPlatform(JNIMyUserPrompter * userPrompter, jobject contentAppEndpointManager) { #if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED ContentAppPlatform::GetInstance().SetupAppPlatform(); ContentAppPlatform::GetInstance().SetContentAppFactory(&gFactory); + + ChipLogProgress(AppServer, "Starting registration of command handler delegates"); + for (size_t i = 0; i < ArraySize(contentAppClusters); i++) + { + ContentAppCommandDelegate * delegate = + new ContentAppCommandDelegate(contentAppEndpointManager, contentAppClusters[i].clusterId); + chip::app::InteractionModelEngine::GetInstance()->RegisterCommandHandler(delegate); + ChipLogProgress(AppServer, "Registered command handler delegate for cluster %d", contentAppClusters[i].clusterId); + } + #endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE @@ -443,8 +455,8 @@ EndpointId AddContentApp(const char * szVendorName, uint16_t vendorId, const cha const char * szApplicationVersion, jobject manager) { #if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED - ContentAppImpl app = - ContentAppImpl(szVendorName, vendorId, szApplicationName, productId, szApplicationVersion, "34567890", manager); + ContentAppImpl * app = + new ContentAppImpl(szVendorName, vendorId, szApplicationName, productId, szApplicationVersion, "20202021", manager); ChipLogProgress(DeviceLayer, "AppImpl: AddContentApp vendorId=%d applicationName=%s ", vendorId, szApplicationName); return gFactory.AddContentApp(app); #endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED diff --git a/examples/tv-app/android/java/AppImpl.h b/examples/tv-app/android/java/AppImpl.h index bcd31ccd061fb9..98a6d61798bc07 100644 --- a/examples/tv-app/android/java/AppImpl.h +++ b/examples/tv-app/android/java/AppImpl.h @@ -52,7 +52,7 @@ #include #include -CHIP_ERROR InitVideoPlayerPlatform(JNIMyUserPrompter * userPrompter); +CHIP_ERROR InitVideoPlayerPlatform(JNIMyUserPrompter * userPrompter, jobject contentAppEndpointManager); CHIP_ERROR PreServerInit(); EndpointId AddContentApp(const char * szVendorName, uint16_t vendorId, const char * szApplicationName, uint16_t productId, const char * szApplicationVersion, jobject manager); @@ -131,7 +131,7 @@ class DLL_EXPORT ContentAppFactoryImpl : public ContentAppFactory // Lookup ContentApp for this catalog id / app id and load it ContentApp * LoadContentApp(const CatalogVendorApp & vendorApp) override; - EndpointId AddContentApp(ContentAppImpl & app); + EndpointId AddContentApp(ContentAppImpl * app); void SendTestMessage(EndpointId epID, const char * message); @@ -143,11 +143,11 @@ class DLL_EXPORT ContentAppFactoryImpl : public ContentAppFactory CHIP_ERROR ConvertToPlatformCatalogVendorApp(const CatalogVendorApp & sourceApp, CatalogVendorApp * destinationApp) override; protected: - std::vector mContentApps{ - ContentAppImpl("Vendor1", 1, "exampleid", 11, "Version1", "34567890", nullptr), - ContentAppImpl("Vendor2", 65521, "exampleString", 32768, "Version2", "20202021", nullptr), - ContentAppImpl("Vendor3", 9050, "App3", 22, "Version3", "20202021", nullptr), - ContentAppImpl("TestSuiteVendor", 1111, "applicationId", 22, "v2", "20202021", nullptr) + std::vector mContentApps{ + new ContentAppImpl("Vendor1", 1, "exampleid", 11, "Version1", "20202021", nullptr), + new ContentAppImpl("Vendor2", 65520, "exampleString", 32768, "Version2", "20202021", nullptr), + new ContentAppImpl("Vendor3", 9050, "App3", 22, "Version3", "20202021", nullptr), + new ContentAppImpl("TestSuiteVendor", 1111, "applicationId", 22, "v2", "20202021", nullptr) }; }; diff --git a/examples/tv-app/android/java/ContentAppCommandDelegate.cpp b/examples/tv-app/android/java/ContentAppCommandDelegate.cpp index a4d23881b6be3f..1cc25f57ee6098 100644 --- a/examples/tv-app/android/java/ContentAppCommandDelegate.cpp +++ b/examples/tv-app/android/java/ContentAppCommandDelegate.cpp @@ -22,14 +22,21 @@ #include "ContentAppCommandDelegate.h" +#include +#include #include #include #include #include +#include +#include namespace chip { namespace AppPlatform { +using CommandHandlerInterface = chip::app::CommandHandlerInterface; +using LaunchResponseType = chip::app::Clusters::ContentLauncher::Commands::LaunchResponse::Type; + const char * ContentAppCommandDelegate::sendCommand(chip::EndpointId epID, std::string commandPayload) { // to support the hardcoded sample apps. @@ -55,5 +62,91 @@ const char * ContentAppCommandDelegate::sendCommand(chip::EndpointId epID, std:: return ret; } +void ContentAppCommandDelegate::InvokeCommand(CommandHandlerInterface::HandlerContext & handlerContext) +{ + if (handlerContext.mRequestPath.mEndpointId >= FIXED_ENDPOINT_COUNT) + { + TLV::TLVReader readerForJson; + readerForJson.Init(handlerContext.mPayload); + + CHIP_ERROR err = CHIP_NO_ERROR; + Json::Value json; + err = TlvToJson(readerForJson, json); + if (err != CHIP_NO_ERROR) + { + // TODO : Add an interface to let the apps know a message came but there was a serialization error. + handlerContext.SetCommandNotHandled(); + return; + } + + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + UtfString jsonString(env, JsonToString(json).c_str()); + + ChipLogProgress(Zcl, "ContentAppCommandDelegate::InvokeCommand send command being called with payload %s", + JsonToString(json).c_str()); + + jstring resp = (jstring) env->CallObjectMethod( + mContentAppEndpointManager, mSendCommandMethod, static_cast(handlerContext.mRequestPath.mEndpointId), + static_cast(handlerContext.mRequestPath.mClusterId), static_cast(handlerContext.mRequestPath.mCommandId), + jsonString.jniValue()); + if (env->ExceptionCheck()) + { + ChipLogError(Zcl, "Java exception in ContentAppCommandDelegate::sendCommand"); + env->ExceptionDescribe(); + env->ExceptionClear(); + FormatResponseData(handlerContext, "{\"value\":{}}"); + return; + } + const char * respStr = env->GetStringUTFChars(resp, 0); + ChipLogProgress(Zcl, "ContentAppCommandDelegate::InvokeCommand got response %s", respStr); + FormatResponseData(handlerContext, respStr); + } + else + { + handlerContext.SetCommandNotHandled(); + } +} + +void ContentAppCommandDelegate::FormatResponseData(CommandHandlerInterface::HandlerContext & handlerContext, const char * response) +{ + Json::Reader reader; + Json::Value resJson; + reader.parse(response, resJson); + Json::Value value = resJson["value"]; + + switch (handlerContext.mRequestPath.mClusterId) + { + case app::Clusters::ContentLauncher::Id: { + LaunchResponseType launchResponse; + if (value["0"].empty()) + { + launchResponse.status = chip::app::Clusters::ContentLauncher::ContentLaunchStatusEnum::kAuthFailed; + } + else + { + launchResponse.status = static_cast(value["0"].asInt()); + if (!value["1"].empty()) + { + launchResponse.data = chip::MakeOptional(CharSpan::fromCharString(value["1"].asCString())); + } + } + handlerContext.mCommandHandler.AddResponseData(handlerContext.mRequestPath, launchResponse); + handlerContext.SetCommandHandled(); + break; + } + + // case app::Clusters::TargetNavigator::Id: + // break; + + // case app::Clusters::MediaPlayback::Id: + // break; + + // case app::Clusters::AccountLogin::Id: + // break; + default: + handlerContext.SetCommandNotHandled(); + } +} + } // namespace AppPlatform } // namespace chip diff --git a/examples/tv-app/android/java/ContentAppCommandDelegate.h b/examples/tv-app/android/java/ContentAppCommandDelegate.h index 2d45906c51049b..908b2e4d1cc0e9 100644 --- a/examples/tv-app/android/java/ContentAppCommandDelegate.h +++ b/examples/tv-app/android/java/ContentAppCommandDelegate.h @@ -22,6 +22,8 @@ #pragma once +#include +#include #include #include #include @@ -29,10 +31,22 @@ namespace chip { namespace AppPlatform { -class ContentAppCommandDelegate +using CommandHandlerInterface = chip::app::CommandHandlerInterface; + +class ContentAppCommandDelegate : public CommandHandlerInterface { public: - ContentAppCommandDelegate(jobject manager) + ContentAppCommandDelegate(jobject manager, ClusterId aClusterId) : CommandHandlerInterface(Optional(), aClusterId) + { + if (manager == nullptr) + { + // To support the existing hardcoded sample apps. + return; + } + InitializeJNIObjects(manager); + }; + + ContentAppCommandDelegate(jobject manager) : CommandHandlerInterface(Optional(), app::Clusters::ContentLauncher::Id) { if (manager == nullptr) @@ -40,7 +54,16 @@ class ContentAppCommandDelegate // To support the existing hardcoded sample apps. return; } + InitializeJNIObjects(manager); + }; + + void InvokeCommand(CommandHandlerInterface::HandlerContext & handlerContext) override; + const char * sendCommand(chip::EndpointId epID, std::string commandPayload); + +private: + void InitializeJNIObjects(jobject manager) + { JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Failed to GetEnvForCurrentThread for ContentAppEndpointManager")); @@ -53,17 +76,16 @@ class ContentAppCommandDelegate ChipLogError(Zcl, "Failed to get ContentAppEndpointManager Java class")); mSendCommandMethod = - env->GetMethodID(ContentAppEndpointManagerClass, "sendCommand", "(ILjava/lang/String;)Ljava/lang/String;"); + env->GetMethodID(ContentAppEndpointManagerClass, "sendCommand", "(IIILjava/lang/String;)Ljava/lang/String;"); if (mSendCommandMethod == nullptr) { ChipLogError(Zcl, "Failed to access ContentAppEndpointManager 'sendCommand' method"); env->ExceptionClear(); } - }; + } - const char * sendCommand(chip::EndpointId epID, std::string commandPayload); + void FormatResponseData(CommandHandlerInterface::HandlerContext & handlerContext, const char * response); -private: jobject mContentAppEndpointManager = nullptr; jmethodID mSendCommandMethod = nullptr; }; diff --git a/examples/tv-app/android/java/TVApp-JNI.cpp b/examples/tv-app/android/java/TVApp-JNI.cpp index 9043a66864ff47..455f1d9da19eab 100644 --- a/examples/tv-app/android/java/TVApp-JNI.cpp +++ b/examples/tv-app/android/java/TVApp-JNI.cpp @@ -157,12 +157,12 @@ JNI_METHOD(void, preServerInit)(JNIEnv *, jobject app) PreServerInit(); } -JNI_METHOD(void, postServerInit)(JNIEnv *, jobject app) +JNI_METHOD(void, postServerInit)(JNIEnv *, jobject app, jobject contentAppEndpointManager) { chip::DeviceLayer::StackLock lock; ChipLogProgress(Zcl, "TvAppJNI::postServerInit"); - InitVideoPlayerPlatform(userPrompter); + InitVideoPlayerPlatform(userPrompter, contentAppEndpointManager); } JNI_METHOD(void, setOnOffManager)(JNIEnv *, jobject, jint endpoint, jobject manager) diff --git a/examples/tv-app/android/java/src/com/tcl/chip/tvapp/ContentAppEndpointManager.java b/examples/tv-app/android/java/src/com/tcl/chip/tvapp/ContentAppEndpointManager.java index 09bf1f0a0f8b54..119ff8bd231f5f 100644 --- a/examples/tv-app/android/java/src/com/tcl/chip/tvapp/ContentAppEndpointManager.java +++ b/examples/tv-app/android/java/src/com/tcl/chip/tvapp/ContentAppEndpointManager.java @@ -2,5 +2,5 @@ public interface ContentAppEndpointManager { - public String sendCommand(int endpointId, String commandPayload); + public String sendCommand(int endpointId, int clusterId, int commandId, String commandPayload); } diff --git a/examples/tv-app/android/java/src/com/tcl/chip/tvapp/ContentAppEndpointManagerStub.java b/examples/tv-app/android/java/src/com/tcl/chip/tvapp/ContentAppEndpointManagerStub.java deleted file mode 100644 index 3de920ef95f938..00000000000000 --- a/examples/tv-app/android/java/src/com/tcl/chip/tvapp/ContentAppEndpointManagerStub.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.tcl.chip.tvapp; - -public class ContentAppEndpointManagerStub implements ContentAppEndpointManager { - - ContentAppEndpointManager delegate; - - public ContentAppEndpointManagerStub(ContentAppEndpointManager delegate) { - this.delegate = delegate; - } - - @Override - public String sendCommand(int endpointId, String commandPayload) { - return delegate.sendCommand(endpointId, commandPayload); - } -} diff --git a/examples/tv-app/android/java/src/com/tcl/chip/tvapp/MediaPlaybackManagerStub.java b/examples/tv-app/android/java/src/com/tcl/chip/tvapp/MediaPlaybackManagerStub.java index 1c6a003c31d72e..f7b5962e84b391 100755 --- a/examples/tv-app/android/java/src/com/tcl/chip/tvapp/MediaPlaybackManagerStub.java +++ b/examples/tv-app/android/java/src/com/tcl/chip/tvapp/MediaPlaybackManagerStub.java @@ -32,6 +32,9 @@ public class MediaPlaybackManagerStub implements MediaPlaybackManager { private long playbackDuration = 5 * 60 * 1000; private long startTime = 100; + private static int playbackMaxForwardSpeed = 10; + private static int playbackMaxRewindSpeed = -10; + public MediaPlaybackManagerStub(int endpoint) { this.endpoint = endpoint; } @@ -116,15 +119,23 @@ public int request(int cmd, long parameter) { case REQUEST_REWIND: Log.d(TAG, "request rewind at " + endpoint); + if (playbackSpeed == playbackMaxRewindSpeed) { + return RESPONSE_STATUS_SPEED_OUT_OF_RANGE; + } playbackState = PLAYBACK_STATE_PLAYING; - playbackSpeed = (playbackSpeed >= 0 ? -1 : playbackSpeed * 2); + playbackSpeed = + (playbackSpeed >= 0 ? -1 : Math.min(playbackSpeed * 2, playbackMaxRewindSpeed)); return RESPONSE_STATUS_SUCCESS; case REQUEST_FAST_FORWARD: Log.d(TAG, "request fast forward at " + endpoint); + if (playbackSpeed == playbackMaxForwardSpeed) { + return RESPONSE_STATUS_SPEED_OUT_OF_RANGE; + } playbackState = PLAYBACK_STATE_PLAYING; - playbackSpeed = (playbackSpeed <= 0 ? 1 : playbackSpeed * 2); + playbackSpeed = + (playbackSpeed <= 0 ? 1 : Math.max(playbackSpeed * 2, playbackMaxForwardSpeed)); return RESPONSE_STATUS_SUCCESS; diff --git a/examples/tv-app/android/java/src/com/tcl/chip/tvapp/TvApp.java b/examples/tv-app/android/java/src/com/tcl/chip/tvapp/TvApp.java index d79e760f18c05d..a7cf235ca46265 100644 --- a/examples/tv-app/android/java/src/com/tcl/chip/tvapp/TvApp.java +++ b/examples/tv-app/android/java/src/com/tcl/chip/tvapp/TvApp.java @@ -41,7 +41,7 @@ private void postClusterInit(int clusterId, int endpoint) { public native void preServerInit(); // called after Matter server is inited - public native void postServerInit(); + public native void postServerInit(ContentAppEndpointManager manager); public native void setKeypadInputManager(int endpoint, KeypadInputManager manager); diff --git a/examples/tv-app/linux/include/media-playback/MediaPlaybackManager.cpp b/examples/tv-app/linux/include/media-playback/MediaPlaybackManager.cpp index cac5c4c846cd04..9e26f9af2bfa29 100644 --- a/examples/tv-app/linux/include/media-playback/MediaPlaybackManager.cpp +++ b/examples/tv-app/linux/include/media-playback/MediaPlaybackManager.cpp @@ -98,8 +98,23 @@ void MediaPlaybackManager::HandleStop(CommandResponseHelper & helper) { // TODO: Insert code here + if (mPlaybackSpeed == kPlaybackMaxForwardSpeed) + { + // if already at max speed, return error + Commands::PlaybackResponse::Type response; + response.data = chip::MakeOptional(CharSpan::fromCharString("data response")); + response.status = MediaPlaybackStatusEnum::kSpeedOutOfRange; + helper.Success(response); + return; + } + mCurrentState = PlaybackStateEnum::kPlaying; mPlaybackSpeed = (mPlaybackSpeed <= 0 ? 1 : mPlaybackSpeed * 2); + if (mPlaybackSpeed > kPlaybackMaxForwardSpeed) + { + // don't exceed max speed + mPlaybackSpeed = kPlaybackMaxForwardSpeed; + } Commands::PlaybackResponse::Type response; response.data = chip::MakeOptional(CharSpan::fromCharString("data response")); @@ -123,8 +138,23 @@ void MediaPlaybackManager::HandlePrevious(CommandResponseHelper & helper) { // TODO: Insert code here + if (mPlaybackSpeed == kPlaybackMaxRewindSpeed) + { + // if already at max speed in reverse, return error + Commands::PlaybackResponse::Type response; + response.data = chip::MakeOptional(CharSpan::fromCharString("data response")); + response.status = MediaPlaybackStatusEnum::kSpeedOutOfRange; + helper.Success(response); + return; + } + mCurrentState = PlaybackStateEnum::kPlaying; mPlaybackSpeed = (mPlaybackSpeed >= 0 ? -1 : mPlaybackSpeed * 2); + if (mPlaybackSpeed < kPlaybackMaxRewindSpeed) + { + // don't exceed max rewind speed + mPlaybackSpeed = kPlaybackMaxRewindSpeed; + } Commands::PlaybackResponse::Type response; response.data = chip::MakeOptional(CharSpan::fromCharString("data response")); diff --git a/examples/tv-app/linux/include/media-playback/MediaPlaybackManager.h b/examples/tv-app/linux/include/media-playback/MediaPlaybackManager.h index 78bfb127c72e7a..1c35764e666e74 100644 --- a/examples/tv-app/linux/include/media-playback/MediaPlaybackManager.h +++ b/examples/tv-app/linux/include/media-playback/MediaPlaybackManager.h @@ -61,4 +61,7 @@ class MediaPlaybackManager : public MediaPlaybackDelegate uint64_t mStartTime = 0; // Magic number for testing. uint64_t mDuration = 80000; + + static const int kPlaybackMaxForwardSpeed = 10; + static const int kPlaybackMaxRewindSpeed = -10; }; diff --git a/examples/tv-app/tv-common/tv-app.matter b/examples/tv-app/tv-common/tv-app.matter index 4759b9fbe1cfd9..7654b8170e0789 100644 --- a/examples/tv-app/tv-common/tv-app.matter +++ b/examples/tv-app/tv-common/tv-app.matter @@ -575,6 +575,7 @@ client cluster GeneralCommissioning = 48 { struct BasicCommissioningInfo { int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; } attribute access(write: administer) int64u breadcrumb = 0; @@ -633,6 +634,7 @@ server cluster GeneralCommissioning = 48 { struct BasicCommissioningInfo { int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; } attribute access(write: administer) int64u breadcrumb = 0; diff --git a/examples/tv-casting-app/android/App/app/src/main/java/com/chip/casting/app/MainActivity.java b/examples/tv-casting-app/android/App/app/src/main/java/com/chip/casting/app/MainActivity.java index 55f3d9b4e2b7b6..afd768a1a20679 100644 --- a/examples/tv-casting-app/android/App/app/src/main/java/com/chip/casting/app/MainActivity.java +++ b/examples/tv-casting-app/android/App/app/src/main/java/com/chip/casting/app/MainActivity.java @@ -11,6 +11,7 @@ import chip.platform.AndroidChipPlatform; import chip.platform.ChipMdnsCallbackImpl; import chip.platform.DiagnosticDataProviderImpl; +import chip.platform.NsdManagerServiceBrowser; import chip.platform.NsdManagerServiceResolver; import chip.platform.PreferencesConfigurationManager; import chip.platform.PreferencesKeyValueStoreManager; @@ -67,6 +68,7 @@ private void initJni() { new PreferencesKeyValueStoreManager(applicationContext), new PreferencesConfigurationManager(applicationContext), new NsdManagerServiceResolver(applicationContext), + new NsdManagerServiceBrowser(applicationContext), new ChipMdnsCallbackImpl(), new DiagnosticDataProviderImpl(applicationContext)); diff --git a/examples/tv-casting-app/darwin/TvCasting/MatterBridge/CastingServerBridge.h b/examples/tv-casting-app/darwin/TvCasting/MatterBridge/CastingServerBridge.h index 712128353db3cb..5e2587416e8eeb 100644 --- a/examples/tv-casting-app/darwin/TvCasting/MatterBridge/CastingServerBridge.h +++ b/examples/tv-casting-app/darwin/TvCasting/MatterBridge/CastingServerBridge.h @@ -15,6 +15,7 @@ * limitations under the License. */ +#import "DiscoveredNodeData.h" #import #ifndef CastingServerBridge_h @@ -22,10 +23,20 @@ @interface CastingServerBridge : NSObject -+ (CastingServerBridge *)getSharedInstance; ++ (CastingServerBridge * _Nullable)getSharedInstance; -// TBD: placeholder will be replaced with true CastingServer functions -- (int)add:(int)a secondNum:(int)b; +- (void)discoverCommissioners:(dispatch_queue_t _Nonnull)clientQueue + discoveryRequestSentHandler:(nullable void (^)(bool))discoveryRequestSentHandler; + +- (void)getDiscoveredCommissioner:(int)index + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + discoveredCommissionerHandler:(nullable void (^)(DiscoveredNodeData * _Nullable))discoveredCommissionerHandler; + +- (void)sendUserDirectedCommissioningRequest:(NSString * _Nonnull)commissionerIpAddress + commissionerPort:(uint16_t)commissionerPort + platformInterface:(unsigned int)platformInterface + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + udcRequestSentHandler:(nullable void (^)(bool))udcRequestSentHandler; @end diff --git a/examples/tv-casting-app/darwin/TvCasting/MatterBridge/CastingServerBridge.mm b/examples/tv-casting-app/darwin/TvCasting/MatterBridge/CastingServerBridge.mm index 05635ac19caf26..33678347bd3ed6 100644 --- a/examples/tv-casting-app/darwin/TvCasting/MatterBridge/CastingServerBridge.mm +++ b/examples/tv-casting-app/darwin/TvCasting/MatterBridge/CastingServerBridge.mm @@ -18,12 +18,21 @@ #import "CastingServerBridge.h" #import "CastingServer.h" +#import "DiscoveredNodeDataConverter.hpp" + #include #include +@interface CastingServerBridge () + +// queue used to serialize all work performed by the CastingServerBridge +@property (atomic, readonly) dispatch_queue_t chipWorkQueue; + +@end + @implementation CastingServerBridge -+ (CastingServerBridge *)getSharedInstance ++ (CastingServerBridge * _Nullable)getSharedInstance { static CastingServerBridge * instance = nil; static dispatch_once_t onceToken; @@ -48,15 +57,100 @@ - (instancetype)init return nil; } + // init app Server + static chip::CommonCaseDeviceServerInitParams initParams; + err = initParams.InitializeStaticResourcesBeforeServerInit(); + if (err != CHIP_NO_ERROR) { + ChipLogError(AppServer, "InitializeStaticResourcesBeforeServerInit failed: %s", ErrorStr(err)); + return nil; + } + err = chip::Server::GetInstance().Init(initParams); + if (err != CHIP_NO_ERROR) { + ChipLogError(AppServer, "chip::Server init failed: %s", ErrorStr(err)); + return nil; + } + + _chipWorkQueue = chip::DeviceLayer::PlatformMgrImpl().GetWorkQueue(); + + chip::DeviceLayer::PlatformMgrImpl().StartEventLoopTask(); + CastingServer::GetInstance()->Init(); } return self; } -// TBD: placeholder will be replaced with true CastingServer functions -- (int)add:(int)a secondNum:(int)b +- (void)discoverCommissioners:(dispatch_queue_t _Nonnull)clientQueue + discoveryRequestSentHandler:(nullable void (^)(bool))discoveryRequestSentHandler { - return a + b; + ChipLogProgress(AppServer, "CastingServerBridge().discoverCommissioners() called"); + dispatch_async(_chipWorkQueue, ^{ + bool discoveryRequestStatus = true; + CHIP_ERROR err = CastingServer::GetInstance()->DiscoverCommissioners(); + if (err != CHIP_NO_ERROR) { + ChipLogError(AppServer, "CastingServerBridge().discoverCommissioners() failed: %" CHIP_ERROR_FORMAT, err.Format()); + discoveryRequestStatus = false; + } + + dispatch_async(clientQueue, ^{ + discoveryRequestSentHandler(discoveryRequestStatus); + }); + }); +} + +- (void)getDiscoveredCommissioner:(int)index + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + discoveredCommissionerHandler:(nullable void (^)(DiscoveredNodeData * _Nullable))discoveredCommissionerHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().getDiscoveredCommissioner() called"); + + dispatch_async(_chipWorkQueue, ^{ + DiscoveredNodeData * commissioner = nil; + const chip::Dnssd::DiscoveredNodeData * chipDiscoveredNodeData + = CastingServer::GetInstance()->GetDiscoveredCommissioner(index); + if (chipDiscoveredNodeData != nullptr) { + commissioner = [DiscoveredNodeDataConverter convertToObjC:chipDiscoveredNodeData]; + } + + dispatch_async(clientQueue, ^{ + discoveredCommissionerHandler(commissioner); + }); + }); } +- (void)sendUserDirectedCommissioningRequest:(NSString * _Nonnull)commissionerIpAddress + commissionerPort:(uint16_t)commissionerPort + platformInterface:(unsigned int)platformInterface + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + udcRequestSentHandler:(nullable void (^)(bool))udcRequestSentHandler +{ + ChipLogProgress( + AppServer, "CastingServerBridge().sendUserDirectedCommissioningRequest() called with port %d", commissionerPort); + + dispatch_async(chip::DeviceLayer::PlatformMgrImpl().GetWorkQueue(), ^{ + bool udcRequestStatus; + chip::Inet::IPAddress commissionerAddrInet; + if (chip::Inet::IPAddress::FromString([commissionerIpAddress UTF8String], commissionerAddrInet) == false) { + ChipLogError(AppServer, "CastingServerBridge().sendUserDirectedCommissioningRequest() failed to parse IP address"); + udcRequestStatus = false; + } else { + chip::Inet::InterfaceId interfaceId = chip::Inet::InterfaceId(platformInterface); + + chip::Transport::PeerAddress commissionerPeerAddress + = chip::Transport::PeerAddress::UDP(commissionerAddrInet, commissionerPort, interfaceId); + + CHIP_ERROR err = CastingServer::GetInstance()->SendUserDirectedCommissioningRequest(commissionerPeerAddress); + if (err != CHIP_NO_ERROR) { + ChipLogError(AppServer, "CastingServerBridge().sendUserDirectedCommissioningRequest() failed: %" CHIP_ERROR_FORMAT, + err.Format()); + udcRequestStatus = false; + } else { + udcRequestStatus = true; + } + } + + dispatch_async(clientQueue, ^{ + udcRequestSentHandler(udcRequestStatus); + }); + }); +} @end diff --git a/examples/tv-casting-app/darwin/TvCasting/MatterBridge/DiscoveredNodeData.h b/examples/tv-casting-app/darwin/TvCasting/MatterBridge/DiscoveredNodeData.h new file mode 100644 index 00000000000000..24240cc4a4acda --- /dev/null +++ b/examples/tv-casting-app/darwin/TvCasting/MatterBridge/DiscoveredNodeData.h @@ -0,0 +1,59 @@ +/** + * + * Copyright (c) 2020-2022 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#ifndef DiscoveredNodeData_h +#define DiscoveredNodeData_h + +@interface DiscoveredNodeData : NSObject + +@property NSString * deviceName; + +@property uint16_t vendorId; + +@property uint16_t productId; + +@property uint16_t deviceType; + +@property uint16_t longDiscriminator; + +@property uint8_t commissioningMode; + +@property uint16_t pairingHint; + +@property const uint8_t * rotatingId; + +@property size_t rotatingIdLen; + +@property NSString * instanceName; + +@property uint16_t port; + +@property NSString * hostName; + +@property unsigned int platformInterface; + +@property NSMutableArray * ipAddresses; + +@property size_t numIPs; + +- (DiscoveredNodeData *)initWithDeviceName:(NSString *)deviceName vendorId:(uint16_t)vendorId productId:(uint16_t)productId; + +@end + +#endif /* DiscoveredNodeData_h */ diff --git a/examples/tv-casting-app/darwin/TvCasting/MatterBridge/DiscoveredNodeData.mm b/examples/tv-casting-app/darwin/TvCasting/MatterBridge/DiscoveredNodeData.mm new file mode 100644 index 00000000000000..541352b3d31bf9 --- /dev/null +++ b/examples/tv-casting-app/darwin/TvCasting/MatterBridge/DiscoveredNodeData.mm @@ -0,0 +1,73 @@ +/** + * + * Copyright (c) 2020-2022 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "DiscoveredNodeData.h" +#include + +@implementation DiscoveredNodeData + +- (DiscoveredNodeData *)initWithDeviceName:(NSString *)deviceName vendorId:(uint16_t)vendorId productId:(uint16_t)productId +{ + self = [super init]; + if (self) { + _deviceName = deviceName; + _vendorId = vendorId; + _productId = productId; + } + return self; +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@ with Product ID: %d and Vendor ID: %d", _deviceName, _productId, _vendorId]; +} + +- (BOOL)isEqualToDiscoveredNodeData:(DiscoveredNodeData *)other +{ + return [self.instanceName isEqualToString:other.instanceName]; +} + +- (BOOL)isEqual:(id)other +{ + if (other == nil) { + return NO; + } + + if (self == other) { + return YES; + } + + if (![other isKindOfClass:[DiscoveredNodeData class]]) { + return NO; + } + + return [self isEqualToDiscoveredNodeData:(DiscoveredNodeData *) other]; +} + +- (NSUInteger)hash +{ + const NSUInteger prime = 31; + NSUInteger result = 1; + + result = prime * result + [self.instanceName hash]; + + return result; +} + +@end diff --git a/src/transport/MessageCounter.cpp b/examples/tv-casting-app/darwin/TvCasting/MatterBridge/DiscoveredNodeDataConverter.hpp similarity index 58% rename from src/transport/MessageCounter.cpp rename to examples/tv-casting-app/darwin/TvCasting/MatterBridge/DiscoveredNodeDataConverter.hpp index 99930cfd47c46f..3833767bcae2c4 100644 --- a/src/transport/MessageCounter.cpp +++ b/examples/tv-casting-app/darwin/TvCasting/MatterBridge/DiscoveredNodeDataConverter.hpp @@ -1,5 +1,6 @@ -/* - * Copyright (c) 2021 Project CHIP Authors +/** + * + * Copyright (c) 2020-2022 Project CHIP Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,22 +15,18 @@ * limitations under the License. */ -/** - * @file - * This file defines the CHIP message counters. - * - */ +#import + +#import "DiscoveredNodeData.h" +#include -#include +#ifndef DiscoveredNodeDataConverter_h +#define DiscoveredNodeDataConverter_h -#include -#include +@interface DiscoveredNodeDataConverter : NSObject -namespace chip { ++ (DiscoveredNodeData *)convertToObjC:(const chip::Dnssd::DiscoveredNodeData *)chipDiscoveredNodedata; -void GlobalUnencryptedMessageCounter::Init() -{ - mLastUsedValue = Crypto::GetRandU32(); -} +@end -} // namespace chip +#endif /* DiscoveredNodeDataConverter_h */ diff --git a/examples/tv-casting-app/darwin/TvCasting/MatterBridge/DiscoveredNodeDataConverter.mm b/examples/tv-casting-app/darwin/TvCasting/MatterBridge/DiscoveredNodeDataConverter.mm new file mode 100644 index 00000000000000..2c96ca48cb95ab --- /dev/null +++ b/examples/tv-casting-app/darwin/TvCasting/MatterBridge/DiscoveredNodeDataConverter.mm @@ -0,0 +1,58 @@ +/** + * + * Copyright (c) 2020-2022 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import + +#import "DiscoveredNodeDataConverter.hpp" + +@implementation DiscoveredNodeDataConverter + ++ (DiscoveredNodeData *)convertToObjC:(const chip::Dnssd::DiscoveredNodeData *)chipDiscoveredNodeData +{ + DiscoveredNodeData * objCDiscoveredNodeData = [DiscoveredNodeData new]; + + // from CommissionNodeData + objCDiscoveredNodeData.deviceType = chipDiscoveredNodeData->commissionData.deviceType; + objCDiscoveredNodeData.vendorId = chipDiscoveredNodeData->commissionData.vendorId; + objCDiscoveredNodeData.productId = chipDiscoveredNodeData->commissionData.productId; + objCDiscoveredNodeData.longDiscriminator = chipDiscoveredNodeData->commissionData.longDiscriminator; + objCDiscoveredNodeData.commissioningMode = chipDiscoveredNodeData->commissionData.commissioningMode; + objCDiscoveredNodeData.pairingHint = chipDiscoveredNodeData->commissionData.pairingHint; + objCDiscoveredNodeData.deviceName = [NSString stringWithCString:chipDiscoveredNodeData->commissionData.deviceName + encoding:NSASCIIStringEncoding]; + objCDiscoveredNodeData.rotatingIdLen = chipDiscoveredNodeData->commissionData.rotatingIdLen; + objCDiscoveredNodeData.rotatingId = chipDiscoveredNodeData->commissionData.rotatingId; + objCDiscoveredNodeData.instanceName = [NSString stringWithCString:chipDiscoveredNodeData->commissionData.instanceName + encoding:NSASCIIStringEncoding]; + + // from CommonResolutionData + objCDiscoveredNodeData.port = chipDiscoveredNodeData->resolutionData.port; + objCDiscoveredNodeData.hostName = [NSString stringWithCString:chipDiscoveredNodeData->resolutionData.hostName + encoding:NSASCIIStringEncoding]; + objCDiscoveredNodeData.platformInterface = chipDiscoveredNodeData->resolutionData.interfaceId.GetPlatformInterface(); + objCDiscoveredNodeData.numIPs = chipDiscoveredNodeData->resolutionData.numIPs; + if (chipDiscoveredNodeData->resolutionData.numIPs > 0) { + objCDiscoveredNodeData.ipAddresses = [NSMutableArray new]; + } + for (int i = 0; i < chipDiscoveredNodeData->resolutionData.numIPs; i++) { + char addrCString[chip::Inet::IPAddress::kMaxStringLength]; + chipDiscoveredNodeData->resolutionData.ipAddress->ToString(addrCString, chip::Inet::IPAddress::kMaxStringLength); + objCDiscoveredNodeData.ipAddresses[i] = [NSString stringWithCString:addrCString encoding:NSASCIIStringEncoding]; + } + return objCDiscoveredNodeData; +} + +@end diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting.xcodeproj/project.pbxproj b/examples/tv-casting-app/darwin/TvCasting/TvCasting.xcodeproj/project.pbxproj index a417f366f7203f..179a71f9ac2275 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting.xcodeproj/project.pbxproj +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting.xcodeproj/project.pbxproj @@ -8,6 +8,12 @@ /* Begin PBXBuildFile section */ 3C75075C284B080900D7DB3A /* libmbedtls.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C75075B284B07E800D7DB3A /* libmbedtls.a */; settings = {ATTRIBUTES = (Required, ); }; }; + 3C7507A72851188500D7DB3A /* DiscoveredNodeData.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3C7507A62851188500D7DB3A /* DiscoveredNodeData.mm */; }; + 3C7507AD285299DF00D7DB3A /* CommissionerDiscoveryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C7507AC285299DF00D7DB3A /* CommissionerDiscoveryView.swift */; }; + 3C7507AF28529A5F00D7DB3A /* CommissioningView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C7507AE28529A5F00D7DB3A /* CommissioningView.swift */; }; + 3C7507B72853A3AD00D7DB3A /* CommissionerDiscoveryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C7507B62853A3AD00D7DB3A /* CommissionerDiscoveryViewModel.swift */; }; + 3C7507B92853EFF000D7DB3A /* CommissioningViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C7507B82853EFF000D7DB3A /* CommissioningViewModel.swift */; }; + 3C7507BC2857A6EE00D7DB3A /* DiscoveredNodeDataConverter.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3C7507BB2857A6EE00D7DB3A /* DiscoveredNodeDataConverter.mm */; }; 3C9ACC05284ABF4000718B2D /* libTvCastingCommon.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C9ACC04284ABF2F00718B2D /* libTvCastingCommon.a */; }; 3CC0E8FA2841DD3400EC6A18 /* TvCastingApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CC0E8F92841DD3400EC6A18 /* TvCastingApp.swift */; }; 3CC0E8FC2841DD3400EC6A18 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CC0E8FB2841DD3400EC6A18 /* ContentView.swift */; }; @@ -19,6 +25,14 @@ /* Begin PBXFileReference section */ 3C75075B284B07E800D7DB3A /* libmbedtls.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libmbedtls.a; path = lib/libmbedtls.a; sourceTree = BUILT_PRODUCTS_DIR; }; 3C75075E284C1DF800D7DB3A /* TvCasting.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = TvCasting.entitlements; sourceTree = ""; }; + 3C7507A52851187500D7DB3A /* DiscoveredNodeData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DiscoveredNodeData.h; sourceTree = ""; }; + 3C7507A62851188500D7DB3A /* DiscoveredNodeData.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = DiscoveredNodeData.mm; sourceTree = ""; }; + 3C7507AC285299DF00D7DB3A /* CommissionerDiscoveryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommissionerDiscoveryView.swift; sourceTree = ""; }; + 3C7507AE28529A5F00D7DB3A /* CommissioningView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommissioningView.swift; sourceTree = ""; }; + 3C7507B62853A3AD00D7DB3A /* CommissionerDiscoveryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommissionerDiscoveryViewModel.swift; sourceTree = ""; }; + 3C7507B82853EFF000D7DB3A /* CommissioningViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommissioningViewModel.swift; sourceTree = ""; }; + 3C7507BB2857A6EE00D7DB3A /* DiscoveredNodeDataConverter.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = DiscoveredNodeDataConverter.mm; sourceTree = ""; }; + 3C7507BD2857A72A00D7DB3A /* DiscoveredNodeDataConverter.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DiscoveredNodeDataConverter.hpp; sourceTree = ""; }; 3C9ACC04284ABF2F00718B2D /* libTvCastingCommon.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libTvCastingCommon.a; path = lib/libTvCastingCommon.a; sourceTree = BUILT_PRODUCTS_DIR; }; 3CC0E8F62841DD3400EC6A18 /* TvCasting.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TvCasting.app; sourceTree = BUILT_PRODUCTS_DIR; }; 3CC0E8F92841DD3400EC6A18 /* TvCastingApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TvCastingApp.swift; sourceTree = ""; }; @@ -80,6 +94,10 @@ 3CC0E8FB2841DD3400EC6A18 /* ContentView.swift */, 3CC0E8FD2841DD3500EC6A18 /* Assets.xcassets */, 3CC0E8FF2841DD3500EC6A18 /* Preview Content */, + 3C7507AC285299DF00D7DB3A /* CommissionerDiscoveryView.swift */, + 3C7507B62853A3AD00D7DB3A /* CommissionerDiscoveryViewModel.swift */, + 3C7507AE28529A5F00D7DB3A /* CommissioningView.swift */, + 3C7507B82853EFF000D7DB3A /* CommissioningViewModel.swift */, ); path = TvCasting; sourceTree = ""; @@ -95,9 +113,13 @@ 3CC0E9072841DD4B00EC6A18 /* MatterBridge */ = { isa = PBXGroup; children = ( - 3CC0E9092841DD7000EC6A18 /* CastingServerBridge.mm */, 3CC0E9082841DD6F00EC6A18 /* TvCasting-Bridging-Header.h */, 3CC0E90B2841DD8500EC6A18 /* CastingServerBridge.h */, + 3CC0E9092841DD7000EC6A18 /* CastingServerBridge.mm */, + 3C7507A52851187500D7DB3A /* DiscoveredNodeData.h */, + 3C7507A62851188500D7DB3A /* DiscoveredNodeData.mm */, + 3C7507BB2857A6EE00D7DB3A /* DiscoveredNodeDataConverter.mm */, + 3C7507BD2857A72A00D7DB3A /* DiscoveredNodeDataConverter.hpp */, ); path = MatterBridge; sourceTree = ""; @@ -206,9 +228,15 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 3C7507AF28529A5F00D7DB3A /* CommissioningView.swift in Sources */, 3CC0E90A2841DD7000EC6A18 /* CastingServerBridge.mm in Sources */, + 3C7507B72853A3AD00D7DB3A /* CommissionerDiscoveryViewModel.swift in Sources */, 3CC0E8FC2841DD3400EC6A18 /* ContentView.swift in Sources */, + 3C7507AD285299DF00D7DB3A /* CommissionerDiscoveryView.swift in Sources */, 3CC0E8FA2841DD3400EC6A18 /* TvCastingApp.swift in Sources */, + 3C7507B92853EFF000D7DB3A /* CommissioningViewModel.swift in Sources */, + 3C7507BC2857A6EE00D7DB3A /* DiscoveredNodeDataConverter.mm in Sources */, + 3C7507A72851188500D7DB3A /* DiscoveredNodeData.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissionerDiscoveryView.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissionerDiscoveryView.swift new file mode 100644 index 00000000000000..b49e774164ad94 --- /dev/null +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissionerDiscoveryView.swift @@ -0,0 +1,80 @@ +/** + * + * Copyright (c) 2020-2022 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import SwiftUI + +extension DiscoveredNodeData : Identifiable { + public var id: String { + instanceName + } +} + +struct CommissionerDiscoveryView: View { + @StateObject var viewModel = CommissionerDiscoveryViewModel() + + var body: some View { + VStack(alignment: .leading) { + NavigationLink( + destination: CommissioningView(_selectedCommissioner: nil), + label: { + Text("Skip to manual commissioning >>") + .frame(width: 300, height: 30, alignment: .center) + .border(Color.black, width: 1) + } + ).background(Color.blue) + .foregroundColor(Color.white) + .padding() + + Button("Discover commissioners", action: viewModel.discoverAndUpdate) + .frame(width: 200, height: 30, alignment: .center) + .border(Color.black, width: 1) + .background(Color.blue) + .foregroundColor(Color.white) + .padding() + + if(viewModel.discoveryRequestStatus == false) + { + Text("Failed to send discovery request") + } + else if(!viewModel.commissioners.isEmpty) + { + Text("Select a commissioner TV...") + ForEach(viewModel.commissioners) { commissioner in + NavigationLink( + destination: CommissioningView(_selectedCommissioner: commissioner), + label: { + Text(commissioner.description) + } + ) + .frame(width: 350, height: 50, alignment: .center) + .border(Color.black, width: 1) + .background(Color.blue) + .foregroundColor(Color.white) + .padding(1) + } + } + } + .navigationTitle("TV Discovery") + .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .top) + } +} + +struct CommissionerDiscoveryView_Previews: PreviewProvider { + static var previews: some View { + CommissionerDiscoveryView() + } +} diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissionerDiscoveryViewModel.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissionerDiscoveryViewModel.swift new file mode 100644 index 00000000000000..5defa202520d7a --- /dev/null +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissionerDiscoveryViewModel.swift @@ -0,0 +1,66 @@ +/** + * + * Copyright (c) 2020-2022 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Foundation +import os.log + +class CommissionerDiscoveryViewModel: ObservableObject { + let Log = Logger(subsystem: "com.matter.casting", + category: "CommissionerDiscoveryViewModel") + + @Published var commissioners: [DiscoveredNodeData] = [] + + @Published var discoveryRequestStatus: Bool?; + + func discoverAndUpdate() { + if let castingServerBridge = CastingServerBridge.getSharedInstance() + { + castingServerBridge.discoverCommissioners(DispatchQueue.main, discoveryRequestSentHandler: { (result: Bool) -> () in + self.discoveryRequestStatus = result + }) + } + + Task { + try? await Task.sleep(nanoseconds: 5_000_000_000) // Wait for commissioners to respond + updateCommissioners() + } + } + + private func updateCommissioners() { + if let castingServerBridge = CastingServerBridge.getSharedInstance() + { + var i: Int32 = 0 + var commissioner: DiscoveredNodeData?; + repeat { + castingServerBridge.getDiscoveredCommissioner(i, clientQueue: DispatchQueue.main, discoveredCommissionerHandler: { (result: DiscoveredNodeData?) -> () in + commissioner = result; + if(commissioner != nil){ + if(self.commissioners.contains(commissioner!)) + { + self.Log.info("Skipping previously discovered commissioner \(commissioner!.description)") + } + else + { + self.commissioners.append(commissioner!) + } + } + }) + i += 1 + } while(commissioner != nil) + } + } +} diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissioningView.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissioningView.swift new file mode 100644 index 00000000000000..fee82a9c9cfacd --- /dev/null +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissioningView.swift @@ -0,0 +1,75 @@ +/** + * + * Copyright (c) 2020-2022 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import SwiftUI + +struct CommissioningView: View { + var selectedCommissioner: DiscoveredNodeData? + + @StateObject var viewModel = CommissioningViewModel(); + + init(_selectedCommissioner: DiscoveredNodeData?) { + self.selectedCommissioner = _selectedCommissioner + } + + var body: some View { + VStack(alignment: .leading) { + if(viewModel.commisisoningWindowOpened == true) { + Text("Commissioning window opened.") + + if(self.selectedCommissioner != nil) + { + if(viewModel.udcRequestSent == true) + { + Text("Complete commissioning on " + (selectedCommissioner?.deviceName)!) + } + else if(viewModel.udcRequestSent == false) { + Text("Could not send user directed commissioning request to " + (selectedCommissioner?.deviceName)! + "! Complete commissioning manually!") + .foregroundColor(Color.red) + } + } + else{ + Text("Complete commissioning with a commissioner manually!") + } + + // TBD: actual values + Text("Onboarding PIN: ") + .padding() + .border(Color.black, width: 1) + Text("Discriminator: ") + .padding() + .border(Color.black, width: 1) + } + else if(viewModel.commisisoningWindowOpened == false) { + Text("Failed to open Commissioning window!") + .foregroundColor(Color.red) + } + } + .navigationTitle("Commissioning...") + .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .top) + .onAppear(perform: { + viewModel.prepareForCommissioning(selectedCommissioner: self.selectedCommissioner) + }) + } +} + +struct CommissioningView_Previews: PreviewProvider { + static var previews: some View { + CommissioningView(_selectedCommissioner: nil) + } +} diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissioningViewModel.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissioningViewModel.swift new file mode 100644 index 00000000000000..6e8a030a065c1d --- /dev/null +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissioningViewModel.swift @@ -0,0 +1,48 @@ +/** + * + * Copyright (c) 2020-2022 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import Foundation + +class CommissioningViewModel: ObservableObject { + @Published var udcRequestSent: Bool?; + + @Published var commisisoningWindowOpened: Bool?; + + func prepareForCommissioning(selectedCommissioner: DiscoveredNodeData?) { + // TBD: Call openBasicCommissioningWindow() and get Onboarding payload + + // Send User directed commissioning request if a commissioner with a known IP addr was selected + if(selectedCommissioner != nil && selectedCommissioner!.numIPs > 0) + { + sendUserDirectedCommissioningRequest(selectedCommissioner: selectedCommissioner) + } + } + + private func sendUserDirectedCommissioningRequest(selectedCommissioner: DiscoveredNodeData?) { + let ipAddress: String = selectedCommissioner!.ipAddresses[0] as! String + let port: UInt16 = selectedCommissioner!.port + let platformInterface: UInt32 = selectedCommissioner!.platformInterface + + if let castingServerBridge = CastingServerBridge.getSharedInstance() + { + castingServerBridge.sendUserDirectedCommissioningRequest(ipAddress, commissionerPort: port, platformInterface: platformInterface, clientQueue: DispatchQueue.main, udcRequestSentHandler: { (result: Bool) -> () in + self.udcRequestSent = result + }) + } + } +} diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/ContentView.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/ContentView.swift index 737ea26a856383..13d7255a3d0838 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/ContentView.swift +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/ContentView.swift @@ -19,8 +19,9 @@ import SwiftUI struct ContentView: View { var body: some View { - Text("Hello tv-casting-common C++, from Objective-C, from Swift! Sum: " + String(CastingServerBridge.getSharedInstance().add(5, secondNum: 6))) - .padding() + NavigationView { + CommissionerDiscoveryView() + } } } diff --git a/examples/tv-casting-app/darwin/TvCasting/chip_xcode_build_connector.sh b/examples/tv-casting-app/darwin/TvCasting/chip_xcode_build_connector.sh index d5ec1edcb4c206..3d0f82ed0d2e39 100755 --- a/examples/tv-casting-app/darwin/TvCasting/chip_xcode_build_connector.sh +++ b/examples/tv-casting-app/darwin/TvCasting/chip_xcode_build_connector.sh @@ -107,7 +107,7 @@ declare -a args=( [[ $PLATFORM_FAMILY_NAME != macOS ]] && { args+=( 'target_os="ios"' - 'import("//config/ios/args.gni")' + 'import("//examples/tv-casting-app/darwin/args.gni")' ) } diff --git a/examples/tv-casting-app/darwin/args.gni b/examples/tv-casting-app/darwin/args.gni new file mode 100644 index 00000000000000..1171f4d8398a89 --- /dev/null +++ b/examples/tv-casting-app/darwin/args.gni @@ -0,0 +1,31 @@ +# Copyright (c) 2020-2022 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/chip.gni") + +import("${chip_root}/config/ios/args.gni") + +chip_device_project_config_include = "" +chip_project_config_include = "" +chip_system_project_config_include = "" + +chip_project_config_include_dirs += + [ "${chip_root}/examples/tv-casting-app/tv-casting-common/include" ] +chip_project_config_include_dirs += [ "${chip_root}/config/ios" ] + +chip_build_libshell = true + +chip_enable_additional_data_advertising = true + +chip_enable_rotating_device_id = true diff --git a/examples/tv-casting-app/tv-casting-common/BUILD.gn b/examples/tv-casting-app/tv-casting-common/BUILD.gn index 10ef81c9104434..fc3135ab8d263a 100644 --- a/examples/tv-casting-app/tv-casting-common/BUILD.gn +++ b/examples/tv-casting-app/tv-casting-common/BUILD.gn @@ -20,6 +20,7 @@ import("${chip_root}/src/lib/lib.gni") config("config") { include_dirs = [ ".", + "${chip_root}/examples/chip-tool", "${chip_root}/zzz_generated/chip-tool", "${chip_root}/zzz_generated/tv-casting-app", "${chip_root}/src/lib", @@ -35,14 +36,17 @@ chip_data_model("tv-casting-common") { "${chip_root}/zzz_generated/tv-casting-app/zap-generated" sources = [ + "${chip_root}/examples/chip-tool/commands/clusters/ModelCommand.h", + "${chip_root}/examples/chip-tool/commands/common/CHIPCommand.h", + "${chip_root}/examples/chip-tool/commands/common/Command.cpp", + "${chip_root}/examples/chip-tool/commands/common/Command.h", + "${chip_root}/examples/chip-tool/commands/common/Commands.cpp", + "${chip_root}/examples/chip-tool/commands/common/Commands.h", + "${chip_root}/examples/chip-tool/commands/common/CredentialIssuerCommands.h", "${chip_root}/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.cpp", "${chip_root}/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp", "commands/clusters/ModelCommand.cpp", "commands/common/CHIPCommand.cpp", - "commands/common/CHIPCommand.h", - "commands/common/Command.cpp", - "commands/common/Commands.cpp", - "commands/common/CredentialIssuerCommands.h", "include/CastingServer.h", "include/TargetEndpointInfo.h", "include/TargetVideoPlayerInfo.h", @@ -51,7 +55,10 @@ chip_data_model("tv-casting-common") { "src/TargetVideoPlayerInfo.cpp", ] - deps = [ "${chip_root}/third_party/jsoncpp" ] + deps = [ + "${chip_root}/src/app/tests/suites/commands/interaction_model", + "${chip_root}/third_party/jsoncpp", + ] if (chip_enable_transport_trace) { public_deps = diff --git a/examples/tv-casting-app/tv-casting-common/commands/clusters/ClusterCommand.h b/examples/tv-casting-app/tv-casting-common/commands/clusters/ClusterCommand.h deleted file mode 100644 index 24db51b5d1b4d9..00000000000000 --- a/examples/tv-casting-app/tv-casting-common/commands/clusters/ClusterCommand.h +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (c) 2022 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#pragma once - -#include -#include - -#include "DataModelLogger.h" -#include "ModelCommand.h" - -class ClusterCommand : public ModelCommand, public chip::app::CommandSender::Callback -{ -public: - ClusterCommand(CredentialIssuerCommands * credsIssuerConfig) : ModelCommand("command-by-id", credsIssuerConfig) - { - AddArgument("cluster-id", 0, UINT32_MAX, &mClusterId); - AddArgument("command-id", 0, UINT32_MAX, &mCommandId); - AddArgument("payload", &mPayload); - AddArgument("timedInteractionTimeoutMs", 0, UINT16_MAX, &mTimedInteractionTimeoutMs); - AddArgument("suppressResponse", 0, 1, &mSuppressResponse); - AddArgument("repeat-count", 1, UINT16_MAX, &mRepeatCount); - AddArgument("repeat-delay-ms", 0, UINT16_MAX, &mRepeatDelayInMs); - ModelCommand::AddArguments(); - } - - ClusterCommand(chip::ClusterId clusterId, CredentialIssuerCommands * credsIssuerConfig) : - ModelCommand("command-by-id", credsIssuerConfig), mClusterId(clusterId) - { - AddArgument("command-id", 0, UINT32_MAX, &mCommandId); - AddArgument("payload", &mPayload); - AddArgument("timedInteractionTimeoutMs", 0, UINT16_MAX, &mTimedInteractionTimeoutMs); - AddArgument("suppressResponse", 0, 1, &mSuppressResponse); - AddArgument("repeat-count", 1, UINT16_MAX, &mRepeatCount); - AddArgument("repeat-delay-ms", 0, UINT16_MAX, &mRepeatDelayInMs); - ModelCommand::AddArguments(); - } - - ClusterCommand(const char * commandName, CredentialIssuerCommands * credsIssuerConfig) : - ModelCommand(commandName, credsIssuerConfig) - { - AddArgument("timedInteractionTimeoutMs", 0, UINT16_MAX, &mTimedInteractionTimeoutMs); - AddArgument("suppressResponse", 0, 1, &mSuppressResponse); - AddArgument("repeat-count", 1, UINT16_MAX, &mRepeatCount); - AddArgument("repeat-delay-ms", 0, UINT16_MAX, &mRepeatDelayInMs); - } - - ~ClusterCommand() {} - - CHIP_ERROR SendCommand(chip::DeviceProxy * device, std::vector endpointIds) override - { - return ClusterCommand::SendCommand(device, endpointIds.at(0), mClusterId, mCommandId, mPayload); - } - - CHIP_ERROR SendGroupCommand(chip::GroupId groupId, chip::FabricIndex fabricIndex) override - { - return ClusterCommand::SendGroupCommand(groupId, fabricIndex, mClusterId, mCommandId, mPayload); - } - - /////////// CommandSender Callback Interface ///////// - virtual void OnResponse(chip::app::CommandSender * client, const chip::app::ConcreteCommandPath & path, - const chip::app::StatusIB & status, chip::TLV::TLVReader * data) override - { - CHIP_ERROR error = status.ToChipError(); - if (CHIP_NO_ERROR != error) - { - ChipLogError(chipTool, "Response Failure: %s", chip::ErrorStr(error)); - mError = error; - return; - } - - if (data != nullptr) - { - error = DataModelLogger::LogCommand(path, data); - if (CHIP_NO_ERROR != error) - { - ChipLogError(chipTool, "Response Failure: Can not decode Data"); - mError = error; - return; - } - } - } - - virtual void OnError(const chip::app::CommandSender * client, CHIP_ERROR error) override - { - ChipLogProgress(chipTool, "Error: %s", chip::ErrorStr(error)); - mError = error; - } - - virtual void OnDone(chip::app::CommandSender * client) override - { - mCommandSender.front().reset(); - mCommandSender.erase(mCommandSender.begin()); - - // If the command is repeated N times, wait for all the responses to comes in - // before exiting. - bool shouldStop = true; - if (mRepeatCount.HasValue()) - { - mRepeatCount.SetValue(static_cast(mRepeatCount.Value() - 1)); - shouldStop = mRepeatCount.Value() == 0; - } - - if (shouldStop) - { - SetCommandExitStatus(mError); - } - } - - template - CHIP_ERROR SendCommand(chip::DeviceProxy * device, chip::EndpointId endpointId, chip::ClusterId clusterId, - chip::CommandId commandId, const T & value) - { - uint16_t repeatCount = mRepeatCount.ValueOr(1); - while (repeatCount--) - { - chip::app::CommandPathParams commandPath = { endpointId, 0 /* groupId */, clusterId, commandId, - (chip::app::CommandPathFlags::kEndpointIdValid) }; - - auto commandSender = std::make_unique(this, device->GetExchangeManager(), - mTimedInteractionTimeoutMs.HasValue()); - VerifyOrReturnError(commandSender != nullptr, CHIP_ERROR_NO_MEMORY); - ReturnErrorOnFailure(commandSender->AddRequestDataNoTimedCheck(commandPath, value, mTimedInteractionTimeoutMs, - mSuppressResponse.ValueOr(false))); - - ReturnErrorOnFailure(commandSender->SendCommandRequest(device->GetSecureSession().Value())); - mCommandSender.push_back(std::move(commandSender)); - - if (mRepeatDelayInMs.HasValue()) - { - chip::test_utils::SleepMillis(mRepeatDelayInMs.Value()); - } - } - return CHIP_NO_ERROR; - } - - template - CHIP_ERROR SendGroupCommand(chip::GroupId groupId, chip::FabricIndex fabricIndex, chip::ClusterId clusterId, - chip::CommandId commandId, const T & value) - { - chip::app::CommandPathParams commandPath = { 0 /* endpoint */, groupId, clusterId, commandId, - (chip::app::CommandPathFlags::kGroupIdValid) }; - - chip::Messaging::ExchangeManager * exchangeManager = chip::app::InteractionModelEngine::GetInstance()->GetExchangeManager(); - - auto commandSender = - chip::Platform::MakeUnique(this, exchangeManager, mTimedInteractionTimeoutMs.HasValue()); - VerifyOrReturnError(commandSender != nullptr, CHIP_ERROR_NO_MEMORY); - ReturnErrorOnFailure(commandSender->AddRequestDataNoTimedCheck(commandPath, value, mTimedInteractionTimeoutMs)); - - chip::Transport::OutgoingGroupSession session(groupId, fabricIndex); - ReturnErrorOnFailure(commandSender->SendGroupCommandRequest(chip::SessionHandle(session))); - commandSender.release(); - - return CHIP_NO_ERROR; - } - -private: - chip::ClusterId mClusterId; - chip::CommandId mCommandId; - chip::Optional mTimedInteractionTimeoutMs; - chip::Optional mSuppressResponse; - chip::Optional mRepeatCount; - chip::Optional mRepeatDelayInMs; - - CHIP_ERROR mError = CHIP_NO_ERROR; - CustomArgument mPayload; - std::vector> mCommandSender; -}; diff --git a/examples/tv-casting-app/tv-casting-common/commands/clusters/ComplexArgument.h b/examples/tv-casting-app/tv-casting-common/commands/clusters/ComplexArgument.h deleted file mode 100644 index aafc18d68d7591..00000000000000 --- a/examples/tv-casting-app/tv-casting-common/commands/clusters/ComplexArgument.h +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright (c) 2022 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -constexpr uint8_t kMaxLabelLength = 100; - -class ComplexArgumentParser -{ -public: - ComplexArgumentParser() {} - - template ::value && !std::is_signed::value && - !std::is_same>, bool>::value, - int> = 0> - static CHIP_ERROR Setup(const char * label, T & request, Json::Value value) - { - if (value.isNumeric()) - { - if (chip::CanCastTo(value.asLargestUInt())) - { - request = static_cast(value.asLargestUInt()); - return CHIP_NO_ERROR; - } - } - else if (value.isString()) - { - // Check for a hex number; JSON does not support those as numbers, - // so they have to be done as strings. And we might as well support - // string-encoded unsigned numbers in general if we're doing that. - bool isHexNotation = strncmp(value.asCString(), "0x", 2) == 0 || strncmp(value.asCString(), "0X", 2) == 0; - - std::stringstream str; - isHexNotation ? str << std::hex << value.asCString() : str << value.asCString(); - uint64_t val; - str >> val; - if (!str.fail() && str.eof() && chip::CanCastTo(val)) - { - request = static_cast(val); - return CHIP_NO_ERROR; - } - } - - ChipLogError(chipTool, "Error while encoding %s as an unsigned integer.", label); - return CHIP_ERROR_INVALID_ARGUMENT; - } - - template ::value, bool> = true> - static CHIP_ERROR Setup(const char * label, T & request, Json::Value value) - { - if (!value.isNumeric() || !chip::CanCastTo(value.asLargestInt())) - { - ChipLogError(chipTool, "Error while encoding %s as an unsigned integer.", label); - return CHIP_ERROR_INVALID_ARGUMENT; - } - - request = static_cast(value.asLargestInt()); - return CHIP_NO_ERROR; - } - - template ::value, int> = 0> - static CHIP_ERROR Setup(const char * label, T & request, Json::Value value) - { - std::underlying_type_t requestValue; - ReturnErrorOnFailure(ComplexArgumentParser::Setup(label, requestValue, value)); - - request = static_cast(requestValue); - return CHIP_NO_ERROR; - } - - template - static CHIP_ERROR Setup(const char * label, chip::BitFlags & request, Json::Value & value) - { - T requestValue; - ReturnErrorOnFailure(ComplexArgumentParser::Setup(label, requestValue, value)); - - request = chip::BitFlags(requestValue); - return CHIP_NO_ERROR; - } - - template - static CHIP_ERROR Setup(const char * label, chip::Optional & request, Json::Value & value) - { - T requestValue; - ReturnErrorOnFailure(ComplexArgumentParser::Setup(label, requestValue, value)); - - request = chip::Optional(requestValue); - return CHIP_NO_ERROR; - } - - template - static CHIP_ERROR Setup(const char * label, chip::app::DataModel::Nullable & request, Json::Value & value) - { - if (value.isNull()) - { - request.SetNull(); - return CHIP_NO_ERROR; - } - - T requestValue; - ReturnErrorOnFailure(ComplexArgumentParser::Setup(label, requestValue, value)); - - request = chip::app::DataModel::Nullable(requestValue); - return CHIP_NO_ERROR; - } - - template - static CHIP_ERROR Setup(const char * label, chip::app::DataModel::List & request, Json::Value & value) - { - if (!value.isArray()) - { - ChipLogError(chipTool, "Error while encoding %s as an array.", label); - return CHIP_ERROR_INVALID_ARGUMENT; - } - - auto content = static_cast::type *>(chip::Platform::MemoryCalloc(value.size(), sizeof(T))); - - Json::ArrayIndex size = value.size(); - for (Json::ArrayIndex i = 0; i < size; i++) - { - char labelWithIndex[kMaxLabelLength]; - snprintf(labelWithIndex, sizeof(labelWithIndex), "%s[%d]", label, i); - ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithIndex, content[i], value[i])); - } - - request = chip::app::DataModel::List(content, value.size()); - return CHIP_NO_ERROR; - } - - static CHIP_ERROR Setup(const char * label, chip::ByteSpan & request, Json::Value & value) - { - if (!value.isString()) - { - ChipLogError(chipTool, "Error while encoding %s as an octet string: Not a string.", label); - return CHIP_ERROR_INVALID_ARGUMENT; - } - - if (strlen(value.asCString()) % 2 != 0) - { - ChipLogError(chipTool, "Error while encoding %s as an octet string: Odd number of characters.", label); - return CHIP_ERROR_INVALID_STRING_LENGTH; - } - - size_t size = strlen(value.asCString()); - auto buffer = static_cast(chip::Platform::MemoryCalloc(size / 2, sizeof(uint8_t))); - size_t octetCount = chip::Encoding::HexToBytes(value.asCString(), size, buffer, size / 2); - - request = chip::ByteSpan(buffer, octetCount); - return CHIP_NO_ERROR; - } - - static CHIP_ERROR Setup(const char * label, chip::CharSpan & request, Json::Value & value) - { - if (!value.isString()) - { - ChipLogError(chipTool, "Error while encoding %s as a string: Not a string.", label); - return CHIP_ERROR_INVALID_ARGUMENT; - } - - size_t size = strlen(value.asCString()); - auto buffer = static_cast(chip::Platform::MemoryCalloc(size, sizeof(char))); - strncpy(buffer, value.asCString(), size); - - request = chip::CharSpan(buffer, size); - return CHIP_NO_ERROR; - } - - static CHIP_ERROR Setup(const char * label, float & request, Json::Value & value) - { - if (!value.isNumeric()) - { - ChipLogError(chipTool, "Error while encoding %s as a float: Not a number.", label); - return CHIP_ERROR_INVALID_ARGUMENT; - } - - request = static_cast(value.asFloat()); - return CHIP_NO_ERROR; - } - - static CHIP_ERROR Setup(const char * label, double & request, Json::Value & value) - { - if (!value.isNumeric()) - { - ChipLogError(chipTool, "Error while encoding %s as a double: Not a number.", label); - return CHIP_ERROR_INVALID_ARGUMENT; - } - - request = static_cast(value.asDouble()); - return CHIP_NO_ERROR; - } - - static CHIP_ERROR Setup(const char * label, bool & request, Json::Value & value) - { - if (!value.isBool()) - { - ChipLogError(chipTool, "Error while encoding %s as a boolean: Not a boolean.", label); - return CHIP_ERROR_INVALID_ARGUMENT; - } - - request = value.asBool(); - return CHIP_NO_ERROR; - } - - static CHIP_ERROR EnsureMemberExist(const char * label, const char * memberName, bool hasMember) - { - if (hasMember) - { - return CHIP_NO_ERROR; - } - - ChipLogError(chipTool, "%s is required. Should be provided as {\"%s\": value}", label, memberName); - return CHIP_ERROR_INVALID_ARGUMENT; - } - - template - static void Finalize(T & request) - { - // Nothing to do - } - - template - static void Finalize(chip::Optional & request) - { - VerifyOrReturn(request.HasValue()); - ComplexArgumentParser::Finalize(request.Value()); - } - - template - static void Finalize(chip::app::DataModel::Nullable & request) - { - VerifyOrReturn(!request.IsNull()); - ComplexArgumentParser::Finalize(request.Value()); - } - - static void Finalize(chip::ByteSpan & request) - { - VerifyOrReturn(request.data() != nullptr); - chip::Platform::MemoryFree(reinterpret_cast(const_cast(request.data()))); - } - - static void Finalize(chip::CharSpan & request) - { - VerifyOrReturn(request.data() != nullptr); - chip::Platform::MemoryFree(reinterpret_cast(const_cast(request.data()))); - } - - template - static void Finalize(chip::app::DataModel::List & request) - { - VerifyOrReturn(request.data() != nullptr); - - size_t size = request.size(); - auto data = const_cast::type *>(request.data()); - for (size_t i = 0; i < size; i++) - { - Finalize(data[i]); - } - - chip::Platform::MemoryFree(reinterpret_cast(data)); - } - -#include -}; - -class ComplexArgument -{ -public: - virtual ~ComplexArgument() {} - - virtual CHIP_ERROR Parse(const char * label, const char * json) = 0; -}; - -template -class TypedComplexArgument : public ComplexArgument -{ -public: - TypedComplexArgument(T * request) : mRequest(request) {} - ~TypedComplexArgument() { ComplexArgumentParser::Finalize(*mRequest); } - - CHIP_ERROR Parse(const char * label, const char * json) - { - Json::Value value; - Json::Reader reader; - if (!reader.parse(json, value)) - { - std::vector errors = reader.getStructuredErrors(); - ChipLogError(chipTool, "Error parsing JSON for %s:", label); - for (auto & error : errors) - { - ChipLogError(chipTool, " %s", error.message.c_str()); - ptrdiff_t error_start = error.offset_start; - ptrdiff_t error_end = error.offset_limit; - const char * sourceText = json; - // The whole JSON string might be too long to fit in our log - // messages. Just include 30 chars before the error. - constexpr ptrdiff_t kMaxContext = 30; - std::string errorMsg; - if (error_start > kMaxContext) - { - sourceText += (error_start - kMaxContext); - error_end = kMaxContext + (error_end - error_start); - error_start = kMaxContext; - ChipLogError(chipTool, "... %s", sourceText); - // Add markers corresponding to the "... " above. - errorMsg += "----"; - } - else - { - ChipLogError(chipTool, "%s", sourceText); - } - for (ptrdiff_t i = 0; i < error_start; ++i) - { - errorMsg += "-"; - } - errorMsg += "^"; - if (error_start + 1 < error_end) - { - for (ptrdiff_t i = error_start + 1; i < error_end; ++i) - { - errorMsg += "-"; - } - errorMsg += "^"; - } - ChipLogError(chipTool, "%s", errorMsg.c_str()); - - if (error.message == "Missing ',' or '}' in object declaration" && error.offset_start > 0 && - json[error.offset_start - 1] == '0' && (json[error.offset_start] == 'x' || json[error.offset_start] == 'X')) - { - ChipLogError(chipTool, - "NOTE: JSON does not allow hex syntax beginning with 0x for numbers. Try putting the hex number " - "in quotes (like {\"name\": \"0x100\"})."); - } - } - return CHIP_ERROR_INVALID_ARGUMENT; - } - - return ComplexArgumentParser::Setup(label, *mRequest, value); - } - -private: - T * mRequest; -}; diff --git a/examples/tv-casting-app/tv-casting-common/commands/clusters/CustomArgument.h b/examples/tv-casting-app/tv-casting-common/commands/clusters/CustomArgument.h deleted file mode 100644 index 2362171aa06da9..00000000000000 --- a/examples/tv-casting-app/tv-casting-common/commands/clusters/CustomArgument.h +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (c) 2022 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#pragma once - -#include -#include -#include - -namespace { -static constexpr char kPayloadHexPrefix[] = "hex:"; -static constexpr char kPayloadSignedPrefix[] = "s:"; -static constexpr char kPayloadUnsignedPrefix[] = "u:"; -static constexpr char kPayloadFloatPrefix[] = "f:"; -static constexpr char kPayloadDoublePrefix[] = "d:"; -static constexpr size_t kPayloadHexPrefixLen = ArraySize(kPayloadHexPrefix) - 1; // ignore null character -static constexpr size_t kPayloadSignedPrefixLen = ArraySize(kPayloadSignedPrefix) - 1; // ignore null character -static constexpr size_t kPayloadUnsignedPrefixLen = ArraySize(kPayloadUnsignedPrefix) - 1; // ignore null character -static constexpr size_t kPayloadFloatPrefixLen = ArraySize(kPayloadFloatPrefix) - 1; // ignore null character -static constexpr size_t kPayloadDoublePrefixLen = ArraySize(kPayloadDoublePrefix) - 1; // ignore null character -} // namespace - -class CustomArgumentParser -{ -public: - static CHIP_ERROR Put(chip::TLV::TLVWriter * writer, chip::TLV::Tag tag, Json::Value & value) - { - if (value.isObject()) - { - return CustomArgumentParser::PutObject(writer, tag, value); - } - - if (value.isArray()) - { - return CustomArgumentParser::PutArray(writer, tag, value); - } - - if (value.isString()) - { - if (IsOctetString(value)) - { - return CustomArgumentParser::PutOctetString(writer, tag, value); - } - if (IsUnsignedNumberPrefix(value)) - { - return CustomArgumentParser::PutUnsignedFromString(writer, tag, value); - } - if (IsSignedNumberPrefix(value)) - { - return CustomArgumentParser::PutSignedFromString(writer, tag, value); - } - if (IsFloatNumberPrefix(value)) - { - return CustomArgumentParser::PutFloatFromString(writer, tag, value); - } - if (IsDoubleNumberPrefix(value)) - { - return CustomArgumentParser::PutDoubleFromString(writer, tag, value); - } - - return CustomArgumentParser::PutCharString(writer, tag, value); - } - - if (value.isNull()) - { - return chip::app::DataModel::Encode(*writer, tag, chip::app::DataModel::Nullable()); - } - - if (value.isBool()) - { - return chip::app::DataModel::Encode(*writer, tag, value.asBool()); - } - - if (value.isUInt()) - { - return chip::app::DataModel::Encode(*writer, tag, value.asLargestUInt()); - } - - if (value.isInt()) - { - return chip::app::DataModel::Encode(*writer, tag, value.asLargestInt()); - } - - if (value.isNumeric()) - { - return chip::app::DataModel::Encode(*writer, tag, value.asDouble()); - } - - return CHIP_ERROR_NOT_IMPLEMENTED; - } - -private: - static CHIP_ERROR PutArray(chip::TLV::TLVWriter * writer, chip::TLV::Tag tag, Json::Value & value) - { - chip::TLV::TLVType outer; - ReturnErrorOnFailure(writer->StartContainer(tag, chip::TLV::kTLVType_Array, outer)); - - Json::ArrayIndex size = value.size(); - - for (Json::ArrayIndex i = 0; i < size; i++) - { - ReturnErrorOnFailure(CustomArgumentParser::Put(writer, chip::TLV::AnonymousTag(), value[i])); - } - - return writer->EndContainer(outer); - } - - static CHIP_ERROR PutObject(chip::TLV::TLVWriter * writer, chip::TLV::Tag tag, Json::Value & value) - { - chip::TLV::TLVType outer; - ReturnErrorOnFailure(writer->StartContainer(tag, chip::TLV::kTLVType_Structure, outer)); - - for (auto const & id : value.getMemberNames()) - { - auto index = std::stoul(id, nullptr, 0); - VerifyOrReturnError(chip::CanCastTo(index), CHIP_ERROR_INVALID_ARGUMENT); - ReturnErrorOnFailure(CustomArgumentParser::Put(writer, chip::TLV::ContextTag(static_cast(index)), value[id])); - } - - return writer->EndContainer(outer); - } - - static CHIP_ERROR PutOctetString(chip::TLV::TLVWriter * writer, chip::TLV::Tag tag, Json::Value & value) - { - size_t size = strlen(value.asCString()); - VerifyOrReturnError(size % 2 == 0, CHIP_ERROR_INVALID_STRING_LENGTH); - - chip::Platform::ScopedMemoryBuffer buffer; - VerifyOrReturnError(buffer.Calloc(size / 2), CHIP_ERROR_NO_MEMORY); - size_t octetCount = chip::Encoding::HexToBytes(value.asCString() + kPayloadHexPrefixLen, size - kPayloadHexPrefixLen, - buffer.Get(), (size - kPayloadHexPrefixLen) / 2); - VerifyOrReturnError(octetCount != 0, CHIP_ERROR_NO_MEMORY); - - return chip::app::DataModel::Encode(*writer, tag, chip::ByteSpan(buffer.Get(), octetCount)); - } - - static CHIP_ERROR PutCharString(chip::TLV::TLVWriter * writer, chip::TLV::Tag tag, Json::Value & value) - { - size_t size = strlen(value.asCString()); - return chip::app::DataModel::Encode(*writer, tag, chip::CharSpan(value.asCString(), size)); - } - - static CHIP_ERROR PutUnsignedFromString(chip::TLV::TLVWriter * writer, chip::TLV::Tag tag, Json::Value & value) - { - char numberAsString[21]; - chip::Platform::CopyString(numberAsString, value.asCString() + kPayloadUnsignedPrefixLen); - - auto number = std::stoull(numberAsString, nullptr, 0); - return chip::app::DataModel::Encode(*writer, tag, static_cast(number)); - } - - static CHIP_ERROR PutSignedFromString(chip::TLV::TLVWriter * writer, chip::TLV::Tag tag, Json::Value & value) - { - char numberAsString[21]; - chip::Platform::CopyString(numberAsString, value.asCString() + kPayloadSignedPrefixLen); - - auto number = std::stoll(numberAsString, nullptr, 0); - return chip::app::DataModel::Encode(*writer, tag, static_cast(number)); - } - - static CHIP_ERROR PutFloatFromString(chip::TLV::TLVWriter * writer, chip::TLV::Tag tag, Json::Value & value) - { - char numberAsString[21]; - chip::Platform::CopyString(numberAsString, value.asCString() + kPayloadFloatPrefixLen); - - auto number = std::stof(numberAsString); - return chip::app::DataModel::Encode(*writer, tag, number); - } - - static CHIP_ERROR PutDoubleFromString(chip::TLV::TLVWriter * writer, chip::TLV::Tag tag, Json::Value & value) - { - char numberAsString[21]; - chip::Platform::CopyString(numberAsString, value.asCString() + kPayloadDoublePrefixLen); - - auto number = std::stod(numberAsString); - return chip::app::DataModel::Encode(*writer, tag, number); - } - - static bool IsOctetString(Json::Value & value) - { - return (strncmp(value.asCString(), kPayloadHexPrefix, kPayloadHexPrefixLen) == 0); - } - - static bool IsUnsignedNumberPrefix(Json::Value & value) - { - return (strncmp(value.asCString(), kPayloadUnsignedPrefix, kPayloadUnsignedPrefixLen) == 0); - } - - static bool IsSignedNumberPrefix(Json::Value & value) - { - return (strncmp(value.asCString(), kPayloadSignedPrefix, kPayloadSignedPrefixLen) == 0); - } - - static bool IsFloatNumberPrefix(Json::Value & value) - { - return (strncmp(value.asCString(), kPayloadFloatPrefix, kPayloadFloatPrefixLen) == 0); - } - - static bool IsDoubleNumberPrefix(Json::Value & value) - { - return (strncmp(value.asCString(), kPayloadDoublePrefix, kPayloadDoublePrefixLen) == 0); - } -}; - -class CustomArgument -{ -public: - ~CustomArgument() - { - if (mData != nullptr) - { - chip::Platform::MemoryFree(mData); - } - } - - CHIP_ERROR Parse(const char * label, const char * json) - { - Json::Reader reader; - Json::Value value; - reader.parse(json, value); - - mData = static_cast(chip::Platform::MemoryCalloc(sizeof(uint8_t), mDataMaxLen)); - VerifyOrReturnError(mData != nullptr, CHIP_ERROR_NO_MEMORY); - - chip::TLV::TLVWriter writer; - writer.Init(mData, mDataMaxLen); - - ReturnErrorOnFailure(CustomArgumentParser::Put(&writer, chip::TLV::AnonymousTag(), value)); - - mDataLen = writer.GetLengthWritten(); - return writer.Finalize(); - } - - CHIP_ERROR Encode(chip::TLV::TLVWriter & writer, chip::TLV::Tag tag) const - { - chip::TLV::TLVReader reader; - reader.Init(mData, mDataLen); - reader.Next(); - - return writer.CopyElement(tag, reader); - } - - // We trust our consumers to do the encoding of our data correctly, so don't - // need to know whether we are being encoded for a write. - static constexpr bool kIsFabricScoped = false; - -private: - uint8_t * mData = nullptr; - uint32_t mDataLen = 0; - static constexpr uint32_t mDataMaxLen = 4096; -}; diff --git a/examples/tv-casting-app/tv-casting-common/commands/clusters/DataModelLogger.h b/examples/tv-casting-app/tv-casting-common/commands/clusters/DataModelLogger.h deleted file mode 100644 index 7d725cf0a8b5ab..00000000000000 --- a/examples/tv-casting-app/tv-casting-common/commands/clusters/DataModelLogger.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2022 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#pragma once - -#include - -#include -#include -#include -#include -#include -#include - -class DataModelLogger -{ -public: - static CHIP_ERROR LogAttribute(const chip::app::ConcreteDataAttributePath & path, chip::TLV::TLVReader * data); - static CHIP_ERROR LogCommand(const chip::app::ConcreteCommandPath & path, chip::TLV::TLVReader * data); - static CHIP_ERROR LogEvent(const chip::app::EventHeader & header, chip::TLV::TLVReader * data); - -private: - static CHIP_ERROR LogValue(const char * label, size_t indent, bool value) - { - DataModelLogger::LogString(label, indent, value ? "TRUE" : "FALSE"); - return CHIP_NO_ERROR; - } - - static CHIP_ERROR LogValue(const char * label, size_t indent, chip::CharSpan value) - { - DataModelLogger::LogString(label, indent, std::string(value.data(), value.size())); - return CHIP_NO_ERROR; - } - - static CHIP_ERROR LogValue(const char * label, size_t indent, chip::ByteSpan value) - { - char buffer[CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE]; - if (CHIP_NO_ERROR == - chip::Encoding::BytesToUppercaseHexString(value.data(), value.size(), &buffer[0], CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE)) - { - DataModelLogger::LogString(label, indent, buffer); - } - else - { - DataModelLogger::LogString(label, indent, - std::string("Elided value too large of size ") + std::to_string(value.size())); - } - - return CHIP_NO_ERROR; - } - - template ::value && !std::is_same>, bool>::value, int> = 0> - static CHIP_ERROR LogValue(const char * label, size_t indent, X value) - { - DataModelLogger::LogString(label, indent, std::to_string(value)); - return CHIP_NO_ERROR; - } - - template ::value, int> = 0> - static CHIP_ERROR LogValue(const char * label, size_t indent, X value) - { - DataModelLogger::LogString(label, indent, std::to_string(value)); - return CHIP_NO_ERROR; - } - - template ::value, int> = 0> - static CHIP_ERROR LogValue(const char * label, size_t indent, X value) - { - DataModelLogger::LogValue(label, indent, chip::to_underlying(value)); - return CHIP_NO_ERROR; - } - - template - static CHIP_ERROR LogValue(const char * label, size_t indent, chip::BitFlags value) - { - DataModelLogger::LogValue(label, indent, value.Raw()); - return CHIP_NO_ERROR; - } - - template - static CHIP_ERROR LogValue(const char * label, size_t indent, const chip::app::DataModel::DecodableList & value) - { - size_t count = 0; - CHIP_ERROR err = value.ComputeSize(&count); - if (err != CHIP_NO_ERROR) - { - return err; - } - DataModelLogger::LogString(label, indent, std::to_string(count) + " entries"); - - auto iter = value.begin(); - size_t i = 0; - while (iter.Next()) - { - ++i; - std::string itemLabel = std::string("[") + std::to_string(i) + "]"; - ReturnErrorOnFailure(DataModelLogger::LogValue(itemLabel.c_str(), indent + 1, iter.GetValue())); - } - if (iter.GetStatus() != CHIP_NO_ERROR) - { - DataModelLogger::LogString(indent + 1, "List truncated due to invalid value"); - } - return iter.GetStatus(); - } - - template - static CHIP_ERROR LogValue(const char * label, size_t indent, const chip::app::DataModel::Nullable & value) - { - if (value.IsNull()) - { - DataModelLogger::LogString(label, indent, "null"); - } - else - { - DataModelLogger::LogValue(label, indent, value.Value()); - } - - return CHIP_NO_ERROR; - } - - template - static CHIP_ERROR LogValue(const char * label, size_t indent, const chip::Optional & value) - { - if (value.HasValue()) - { - DataModelLogger::LogValue(label, indent, value.Value()); - } - - return CHIP_NO_ERROR; - } - -#include - - static void LogString(size_t indent, const std::string string) { LogString("", indent, string); } - - static void LogString(const std::string label, size_t indent, const std::string string) - { - std::string indentation; - for (size_t i = 0; i < indent; ++i) - { - indentation.append(" "); - } - - ChipLogProgress(chipTool, "%s%s%s %s", indentation.c_str(), label.c_str(), label.size() ? ":" : "", string.c_str()); - } -}; diff --git a/examples/tv-casting-app/tv-casting-common/commands/clusters/ModelCommand.cpp b/examples/tv-casting-app/tv-casting-common/commands/clusters/ModelCommand.cpp index c886c04cf7bce7..bacbcfe98d6464 100644 --- a/examples/tv-casting-app/tv-casting-common/commands/clusters/ModelCommand.cpp +++ b/examples/tv-casting-app/tv-casting-common/commands/clusters/ModelCommand.cpp @@ -16,7 +16,7 @@ * */ -#include "ModelCommand.h" +#include #include #include @@ -28,23 +28,23 @@ CHIP_ERROR ModelCommand::RunCommand() { FabricIndex fabricIndex = CastingServer::GetInstance()->CurrentFabricIndex(); - if (mNodeId == 0) + if (mDestinationId == 0) { ChipLogProgress(chipTool, "nodeId set to 0, using default for fabric %d", fabricIndex); - mNodeId = CastingServer::GetInstance()->GetVideoPlayerNodeForFabricIndex(fabricIndex); + mDestinationId = CastingServer::GetInstance()->GetVideoPlayerNodeForFabricIndex(fabricIndex); } else { // potentially change fabric index if this is not the right one for the given nodeId - fabricIndex = CastingServer::GetInstance()->GetVideoPlayerFabricIndexForNode(mNodeId); + fabricIndex = CastingServer::GetInstance()->GetVideoPlayerFabricIndexForNode(mDestinationId); } - ChipLogProgress(chipTool, "Sending command to node 0x%" PRIx64, mNodeId); + ChipLogProgress(chipTool, "Sending command to node 0x%" PRIx64, mDestinationId); - if (IsGroupId(mNodeId)) + if (IsGroupId(mDestinationId)) { - ChipLogProgress(chipTool, "Sending command to group 0x%x", GroupIdFromNodeId(mNodeId)); + ChipLogProgress(chipTool, "Sending command to group 0x%x", GroupIdFromNodeId(mDestinationId)); - return SendGroupCommand(GroupIdFromNodeId(mNodeId), fabricIndex); + return SendGroupCommand(GroupIdFromNodeId(mDestinationId), fabricIndex); } Server * server = &(chip::Server::GetInstance()); @@ -55,7 +55,7 @@ CHIP_ERROR ModelCommand::RunCommand() return CHIP_ERROR_INVALID_FABRIC_INDEX; } - PeerId peerID = fabric->GetPeerIdForNode(mNodeId); + PeerId peerID = fabric->GetPeerIdForNode(mDestinationId); server->GetCASESessionManager()->FindOrEstablishSession(peerID, &mOnDeviceConnectedCallback, &mOnDeviceConnectionFailureCallback); return CHIP_NO_ERROR; diff --git a/examples/tv-casting-app/tv-casting-common/commands/clusters/ReportCommand.h b/examples/tv-casting-app/tv-casting-common/commands/clusters/ReportCommand.h deleted file mode 100644 index f99c5528892162..00000000000000 --- a/examples/tv-casting-app/tv-casting-common/commands/clusters/ReportCommand.h +++ /dev/null @@ -1,576 +0,0 @@ -/* - * Copyright (c) 2020 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#pragma once - -#include - -#include "DataModelLogger.h" -#include "ModelCommand.h" - -constexpr uint8_t kMaxAllowedPaths = 10; - -class ReportCommand : public ModelCommand, public chip::app::ReadClient::Callback -{ -public: - ReportCommand(const char * commandName, CredentialIssuerCommands * credsIssuerConfig) : - ModelCommand(commandName, credsIssuerConfig), mBufferedReadAdapter(*this) - {} - - virtual void OnAttributeSubscription(){}; - virtual void OnEventSubscription(){}; - - /////////// ReadClient Callback Interface ///////// - void OnAttributeData(const chip::app::ConcreteDataAttributePath & path, chip::TLV::TLVReader * data, - const chip::app::StatusIB & status) override - { - CHIP_ERROR error = status.ToChipError(); - if (CHIP_NO_ERROR != error) - { - ChipLogError(chipTool, "Response Failure: %s", chip::ErrorStr(error)); - mError = error; - return; - } - - if (data == nullptr) - { - ChipLogError(chipTool, "Response Failure: No Data"); - mError = CHIP_ERROR_INTERNAL; - return; - } - - error = DataModelLogger::LogAttribute(path, data); - if (CHIP_NO_ERROR != error) - { - ChipLogError(chipTool, "Response Failure: Can not decode Data"); - mError = error; - return; - } - } - - void OnEventData(const chip::app::EventHeader & eventHeader, chip::TLV::TLVReader * data, - const chip::app::StatusIB * status) override - { - if (status != nullptr) - { - CHIP_ERROR error = status->ToChipError(); - if (CHIP_NO_ERROR != error) - { - ChipLogError(chipTool, "Response Failure: %s", chip::ErrorStr(error)); - mError = error; - return; - } - } - - if (data == nullptr) - { - ChipLogError(chipTool, "Response Failure: No Data"); - mError = CHIP_ERROR_INTERNAL; - return; - } - - CHIP_ERROR error = DataModelLogger::LogEvent(eventHeader, data); - if (CHIP_NO_ERROR != error) - { - ChipLogError(chipTool, "Response Failure: Can not decode Data"); - mError = error; - return; - } - } - - void OnError(CHIP_ERROR error) override - { - ChipLogProgress(chipTool, "Error: %s", chip::ErrorStr(error)); - mError = error; - } - - void OnDone(chip::app::ReadClient *) override - { - mReadClient.reset(); - SetCommandExitStatus(mError); - } - - void OnSubscriptionEstablished(chip::SubscriptionId subscriptionId) override { OnAttributeSubscription(); } - -protected: - CHIP_ERROR ReportAttribute(chip::DeviceProxy * device, std::vector endpointIds, - std::vector clusterIds, std::vector attributeIds, - chip::app::ReadClient::InteractionType interactionType, uint16_t minInterval = 0, - uint16_t maxInterval = 0, - const chip::Optional> & dataVersions = chip::NullOptional) - { - const size_t clusterCount = clusterIds.size(); - const size_t attributeCount = attributeIds.size(); - const size_t endpointCount = endpointIds.size(); - const size_t dataVersionsCount = dataVersions.HasValue() ? dataVersions.Value().size() : 0; - - VerifyOrReturnError(clusterCount > 0 && clusterCount <= kMaxAllowedPaths, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(attributeCount > 0 && attributeCount <= kMaxAllowedPaths, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(endpointCount > 0 && endpointCount <= kMaxAllowedPaths, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(dataVersionsCount <= kMaxAllowedPaths, CHIP_ERROR_INVALID_ARGUMENT); - - const bool hasSameIdsCount = (clusterCount == attributeCount) && (clusterCount == endpointCount) && - (dataVersionsCount == 0 || clusterCount == dataVersionsCount); - const bool multipleClusters = - clusterCount > 1 && attributeCount == 1 && endpointCount == 1 && (dataVersionsCount == 0 || dataVersionsCount == 1); - const bool multipleAttributes = - attributeCount > 1 && clusterCount == 1 && endpointCount == 1 && (dataVersionsCount == 0 || dataVersionsCount == 1); - const bool multipleEndpoints = - endpointCount > 1 && clusterCount == 1 && attributeCount == 1 && (dataVersionsCount == 0 || dataVersionsCount == 1); - const bool multipleDataVersions = dataVersionsCount > 1 && clusterCount == 1 && attributeCount == 1 && endpointCount == 1; - - size_t pathsCount = 0; - if (hasSameIdsCount) - { - pathsCount = clusterCount; - } - else if (multipleClusters) - { - pathsCount = clusterCount; - } - else if (multipleAttributes) - { - pathsCount = attributeCount; - } - else if (multipleEndpoints) - { - pathsCount = endpointCount; - } - else if (multipleDataVersions) - { - pathsCount = dataVersionsCount; - } - else - { - ChipLogError( - chipTool, - "\n%sAttribute commands targeting multiple paths needs to have: \n \t * One element with multiple ids (for " - "example 1 cluster id, 1 attribute id, 2 endpoint ids)\n\t * Or the same " - "number of ids (for examples 2 cluster ids, 2 attribute ids and 2 endpoint ids).\n The current command has %u " - "cluster ids, %u attribute ids, %u endpoint ids.", - interactionType == chip::app::ReadClient::InteractionType::Subscribe ? "Subscribe" : "Read", - static_cast(clusterCount), static_cast(attributeCount), - static_cast(endpointCount)); - return CHIP_ERROR_INVALID_ARGUMENT; - } - - ChipLogProgress(chipTool, "Sending %sAttribute to:", - interactionType == chip::app::ReadClient::InteractionType::Subscribe ? "Subscribe" : "Read"); - - chip::app::AttributePathParams attributePathParams[kMaxAllowedPaths]; - chip::app::DataVersionFilter dataVersionFilter[kMaxAllowedPaths]; - for (size_t i = 0; i < pathsCount; i++) - { - chip::ClusterId clusterId = clusterIds.at((hasSameIdsCount || multipleClusters) ? i : 0); - chip::AttributeId attributeId = attributeIds.at((hasSameIdsCount || multipleAttributes) ? i : 0); - chip::EndpointId endpointId = endpointIds.at((hasSameIdsCount || multipleEndpoints) ? i : 0); - - ChipLogProgress(chipTool, "\tcluster " ChipLogFormatMEI ", attribute: " ChipLogFormatMEI ", endpoint %u", - ChipLogValueMEI(clusterId), ChipLogValueMEI(attributeId), endpointId); - attributePathParams[i].mClusterId = clusterId; - attributePathParams[i].mAttributeId = attributeId; - attributePathParams[i].mEndpointId = endpointId; - - if (dataVersions.HasValue()) - { - chip::DataVersion dataVersion = dataVersions.Value().at((hasSameIdsCount || multipleDataVersions) ? i : 0); - dataVersionFilter[i].mEndpointId = endpointId; - dataVersionFilter[i].mClusterId = clusterId; - dataVersionFilter[i].mDataVersion.SetValue(dataVersion); - } - } - - chip::app::ReadPrepareParams params(device->GetSecureSession().Value()); - params.mpEventPathParamsList = nullptr; - params.mEventPathParamsListSize = 0; - params.mpAttributePathParamsList = attributePathParams; - params.mAttributePathParamsListSize = pathsCount; - - if (mFabricFiltered.HasValue()) - { - params.mIsFabricFiltered = mFabricFiltered.Value(); - } - - if (dataVersions.HasValue()) - { - params.mpDataVersionFilterList = dataVersionFilter; - params.mDataVersionFilterListSize = pathsCount; - } - - if (interactionType == chip::app::ReadClient::InteractionType::Subscribe) - { - params.mMinIntervalFloorSeconds = minInterval; - params.mMaxIntervalCeilingSeconds = maxInterval; - if (mKeepSubscriptions.HasValue()) - { - params.mKeepSubscriptions = mKeepSubscriptions.Value(); - } - } - - mReadClient = std::make_unique(chip::app::InteractionModelEngine::GetInstance(), - device->GetExchangeManager(), mBufferedReadAdapter, interactionType); - return mReadClient->SendRequest(params); - } - - CHIP_ERROR ReportEvent(chip::DeviceProxy * device, std::vector endpointIds, - std::vector clusterIds, std::vector eventIds, - chip::app::ReadClient::InteractionType interactionType, uint16_t minInterval = 0, - uint16_t maxInterval = 0) - { - const size_t clusterCount = clusterIds.size(); - const size_t eventCount = eventIds.size(); - const size_t endpointCount = endpointIds.size(); - - VerifyOrReturnError(clusterCount > 0 && clusterCount <= kMaxAllowedPaths, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(eventCount > 0 && eventCount <= kMaxAllowedPaths, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(endpointCount > 0 && endpointCount <= kMaxAllowedPaths, CHIP_ERROR_INVALID_ARGUMENT); - - const bool hasSameIdsCount = (clusterCount == eventCount) && (clusterCount == endpointCount); - const bool multipleClusters = clusterCount > 1 && eventCount == 1 && endpointCount == 1; - const bool multipleEvents = eventCount > 1 && clusterCount == 1 && endpointCount == 1; - const bool multipleEndpoints = endpointCount > 1 && clusterCount == 1 && eventCount == 1; - - size_t pathsCount = 0; - if (hasSameIdsCount) - { - pathsCount = clusterCount; - } - else if (multipleClusters) - { - pathsCount = clusterCount; - } - else if (multipleEvents) - { - pathsCount = eventCount; - } - else if (multipleEndpoints) - { - pathsCount = endpointCount; - } - else - { - ChipLogError(chipTool, - "\n%sEvent command targeting multiple paths needs to have: \n \t * One element with multiple ids (for " - "example 1 cluster id, 1 event id, 2 endpoint ids)\n\t * Or the same " - "number of ids (for examples 2 cluster ids, 2 event ids and 2 endpoint ids).\n The current command has %u " - "cluster ids, %u event ids, %u endpoint ids.", - interactionType == chip::app::ReadClient::InteractionType::Subscribe ? "Subscribe" : "Read", - static_cast(clusterCount), static_cast(eventCount), - static_cast(endpointCount)); - return CHIP_ERROR_INVALID_ARGUMENT; - } - - chip::app::EventPathParams eventPathParams[kMaxAllowedPaths]; - - ChipLogProgress(chipTool, "Sending %sEvent to:", - interactionType == chip::app::ReadClient::InteractionType::Subscribe ? "Subscribe" : "Read"); - for (size_t i = 0; i < pathsCount; i++) - { - chip::ClusterId clusterId = clusterIds.at((hasSameIdsCount || multipleClusters) ? i : 0); - chip::EventId eventId = eventIds.at((hasSameIdsCount || multipleEvents) ? i : 0); - chip::EndpointId endpointId = endpointIds.at((hasSameIdsCount || multipleEndpoints) ? i : 0); - - ChipLogProgress(chipTool, "\tcluster " ChipLogFormatMEI ", event: " ChipLogFormatMEI ", endpoint %u", - ChipLogValueMEI(clusterId), ChipLogValueMEI(eventId), endpointId); - eventPathParams[i].mClusterId = clusterId; - eventPathParams[i].mEventId = eventId; - eventPathParams[i].mEndpointId = endpointId; - } - - chip::app::ReadPrepareParams params(device->GetSecureSession().Value()); - params.mpEventPathParamsList = eventPathParams; - params.mEventPathParamsListSize = pathsCount; - params.mEventNumber = mEventNumber; - params.mpAttributePathParamsList = nullptr; - params.mAttributePathParamsListSize = 0; - - if (interactionType == chip::app::ReadClient::InteractionType::Subscribe) - { - params.mMinIntervalFloorSeconds = minInterval; - params.mMaxIntervalCeilingSeconds = maxInterval; - if (mKeepSubscriptions.HasValue()) - { - params.mKeepSubscriptions = mKeepSubscriptions.Value(); - } - } - - mReadClient = std::make_unique(chip::app::InteractionModelEngine::GetInstance(), - device->GetExchangeManager(), mBufferedReadAdapter, interactionType); - return mReadClient->SendRequest(params); - } - - // Use a 3x-longer-than-default timeout because wildcard reads can take a - // while. - chip::System::Clock::Timeout GetWaitDuration() const override - { - return mTimeout.HasValue() ? chip::System::Clock::Seconds16(mTimeout.Value()) : (ModelCommand::GetWaitDuration() * 3); - } - - std::unique_ptr mReadClient; - chip::app::BufferedReadCallback mBufferedReadAdapter; - - // mFabricFiltered is really only used by the attribute commands, but we end - // up needing it in our class's shared code. - chip::Optional mFabricFiltered; - - // mKeepSubscriptions is really only used by the subscribe commands, but we end - // up needing it in our class's shared code. - chip::Optional mKeepSubscriptions; - chip::Optional mEventNumber; - - CHIP_ERROR mError = CHIP_NO_ERROR; -}; - -class ReadAttribute : public ReportCommand -{ -public: - ReadAttribute(CredentialIssuerCommands * credsIssuerConfig) : ReportCommand("read-by-id", credsIssuerConfig) - { - AddArgument("cluster-id", 0, UINT32_MAX, &mClusterIds); - AddArgument("attribute-id", 0, UINT32_MAX, &mAttributeIds); - AddArgument("data-version", 0, UINT32_MAX, &mDataVersion); - AddArgument("fabric-filtered", 0, 1, &mFabricFiltered); - ReportCommand::AddArguments(); - } - - ReadAttribute(chip::ClusterId clusterId, CredentialIssuerCommands * credsIssuerConfig) : - ReportCommand("read-by-id", credsIssuerConfig), mClusterIds(1, clusterId) - { - AddArgument("attribute-id", 0, UINT32_MAX, &mAttributeIds); - AddArgument("data-version", 0, UINT32_MAX, &mDataVersion); - AddArgument("fabric-filtered", 0, 1, &mFabricFiltered); - ReportCommand::AddArguments(); - } - - ReadAttribute(chip::ClusterId clusterId, const char * attributeName, chip::AttributeId attributeId, - CredentialIssuerCommands * credsIssuerConfig) : - ReportCommand("read", credsIssuerConfig), - mClusterIds(1, clusterId), mAttributeIds(1, attributeId) - { - AddArgument("attr-name", attributeName); - AddArgument("data-version", 0, UINT32_MAX, &mDataVersion); - AddArgument("fabric-filtered", 0, 1, &mFabricFiltered); - ReportCommand::AddArguments(); - } - - ~ReadAttribute() {} - - CHIP_ERROR SendCommand(chip::DeviceProxy * device, std::vector endpointIds) override - { - return ReportCommand::ReportAttribute(device, endpointIds, mClusterIds, mAttributeIds, - chip::app::ReadClient::InteractionType::Read, 0, 0, mDataVersion); - } - -private: - std::vector mClusterIds; - std::vector mAttributeIds; - chip::Optional> mDataVersion; -}; - -class SubscribeAttribute : public ReportCommand -{ -public: - SubscribeAttribute(CredentialIssuerCommands * credsIssuerConfig) : ReportCommand("subscribe-by-id", credsIssuerConfig) - { - AddArgument("cluster-id", 0, UINT32_MAX, &mClusterIds); - AddArgument("attribute-id", 0, UINT32_MAX, &mAttributeIds); - AddArgument("min-interval", 0, UINT16_MAX, &mMinInterval); - AddArgument("max-interval", 0, UINT16_MAX, &mMaxInterval); - AddArgument("data-version", 0, UINT32_MAX, &mDataVersion); - AddArgument("fabric-filtered", 0, 1, &mFabricFiltered); - AddArgument("keepSubscriptions", 0, 1, &mKeepSubscriptions); - ReportCommand::AddArguments(); - } - - SubscribeAttribute(chip::ClusterId clusterId, CredentialIssuerCommands * credsIssuerConfig) : - ReportCommand("subscribe-by-id", credsIssuerConfig), mClusterIds(1, clusterId) - { - AddArgument("attribute-id", 0, UINT32_MAX, &mAttributeIds); - AddArgument("min-interval", 0, UINT16_MAX, &mMinInterval); - AddArgument("max-interval", 0, UINT16_MAX, &mMaxInterval); - AddArgument("data-version", 0, UINT32_MAX, &mDataVersion); - AddArgument("fabric-filtered", 0, 1, &mFabricFiltered); - AddArgument("keepSubscriptions", 0, 1, &mKeepSubscriptions); - ReportCommand::AddArguments(); - } - - SubscribeAttribute(chip::ClusterId clusterId, const char * attributeName, chip::AttributeId attributeId, - CredentialIssuerCommands * credsIssuerConfig) : - ReportCommand("subscribe", credsIssuerConfig), - mClusterIds(1, clusterId), mAttributeIds(1, attributeId) - { - AddArgument("attr-name", attributeName); - AddArgument("min-interval", 0, UINT16_MAX, &mMinInterval); - AddArgument("max-interval", 0, UINT16_MAX, &mMaxInterval); - AddArgument("data-version", 0, UINT32_MAX, &mDataVersion); - AddArgument("fabric-filtered", 0, 1, &mFabricFiltered); - AddArgument("keepSubscriptions", 0, 1, &mKeepSubscriptions); - ReportCommand::AddArguments(); - } - - ~SubscribeAttribute() {} - - CHIP_ERROR SendCommand(chip::DeviceProxy * device, std::vector endpointIds) override - { - return ReportCommand::ReportAttribute(device, endpointIds, mClusterIds, mAttributeIds, - chip::app::ReadClient::InteractionType::Subscribe, mMinInterval, mMaxInterval, - mDataVersion); - } - - chip::System::Clock::Timeout GetWaitDuration() const override { return ReportCommand::GetWaitDuration(); } - - void OnAttributeSubscription() override - { - // The ReadClient instance can not be released directly into the OnAttributeSubscription - // callback since it happens to be called by ReadClient itself which is doing additional - // work after that. - chip::DeviceLayer::PlatformMgr().ScheduleWork( - [](intptr_t arg) { - auto * command = reinterpret_cast(arg); - if (!command->IsInteractive()) - { - command->mReadClient.reset(); - } - command->SetCommandExitStatus(CHIP_NO_ERROR); - }, - reinterpret_cast(this)); - } - -private: - std::vector mClusterIds; - std::vector mAttributeIds; - - uint16_t mMinInterval; - uint16_t mMaxInterval; - chip::Optional> mDataVersion; -}; - -class ReadEvent : public ReportCommand -{ -public: - ReadEvent(CredentialIssuerCommands * credsIssuerConfig) : ReportCommand("read-event-by-id", credsIssuerConfig) - { - AddArgument("cluster-id", 0, UINT32_MAX, &mClusterIds); - AddArgument("event-id", 0, UINT32_MAX, &mEventIds); - AddArgument("event-min", 0, UINT64_MAX, &mEventNumber); - ReportCommand::AddArguments(); - } - - ReadEvent(chip::ClusterId clusterId, CredentialIssuerCommands * credsIssuerConfig) : - ReportCommand("read-event-by-id", credsIssuerConfig), mClusterIds(1, clusterId) - { - AddArgument("event-id", 0, UINT32_MAX, &mEventIds); - AddArgument("event-min", 0, UINT64_MAX, &mEventNumber); - ReportCommand::AddArguments(); - } - - ReadEvent(chip::ClusterId clusterId, const char * eventName, chip::EventId eventId, - CredentialIssuerCommands * credsIssuerConfig) : - ReportCommand("read-event", credsIssuerConfig), - mClusterIds(1, clusterId), mEventIds(1, eventId) - { - AddArgument("event-name", eventName); - AddArgument("event-min", 0, UINT64_MAX, &mEventNumber); - ReportCommand::AddArguments(); - } - - ~ReadEvent() {} - - CHIP_ERROR SendCommand(chip::DeviceProxy * device, std::vector endpointIds) override - { - return ReportCommand::ReportEvent(device, endpointIds, mClusterIds, mEventIds, - chip::app::ReadClient::InteractionType::Read); - } - -private: - std::vector mClusterIds; - std::vector mEventIds; -}; - -class SubscribeEvent : public ReportCommand -{ -public: - SubscribeEvent(CredentialIssuerCommands * credsIssuerConfig) : ReportCommand("subscribe-event-by-id", credsIssuerConfig) - { - AddArgument("cluster-id", 0, UINT32_MAX, &mClusterIds); - AddArgument("event-id", 0, UINT32_MAX, &mEventIds); - AddArgument("min-interval", 0, UINT16_MAX, &mMinInterval); - AddArgument("max-interval", 0, UINT16_MAX, &mMaxInterval); - AddArgument("keepSubscriptions", 0, 1, &mKeepSubscriptions); - AddArgument("event-min", 0, UINT64_MAX, &mEventNumber); - ReportCommand::AddArguments(); - } - - SubscribeEvent(chip::ClusterId clusterId, CredentialIssuerCommands * credsIssuerConfig) : - ReportCommand("subscribe-event-by-id", credsIssuerConfig), mClusterIds(1, clusterId) - { - AddArgument("event-id", 0, UINT32_MAX, &mEventIds); - AddArgument("min-interval", 0, UINT16_MAX, &mMinInterval); - AddArgument("max-interval", 0, UINT16_MAX, &mMaxInterval); - AddArgument("keepSubscriptions", 0, 1, &mKeepSubscriptions); - AddArgument("event-min", 0, UINT64_MAX, &mEventNumber); - ReportCommand::AddArguments(); - } - - SubscribeEvent(chip::ClusterId clusterId, const char * eventName, chip::EventId eventId, - CredentialIssuerCommands * credsIssuerConfig) : - ReportCommand("subscribe-event", credsIssuerConfig), - mClusterIds(1, clusterId), mEventIds(1, eventId) - { - AddArgument("attr-name", eventName); - AddArgument("min-interval", 0, UINT16_MAX, &mMinInterval); - AddArgument("max-interval", 0, UINT16_MAX, &mMaxInterval); - AddArgument("keepSubscriptions", 0, 1, &mKeepSubscriptions); - AddArgument("event-min", 0, UINT64_MAX, &mEventNumber); - ReportCommand::AddArguments(); - } - - ~SubscribeEvent() {} - - CHIP_ERROR SendCommand(chip::DeviceProxy * device, std::vector endpointIds) override - { - return ReportCommand::ReportEvent(device, endpointIds, mClusterIds, mEventIds, - chip::app::ReadClient::InteractionType::Subscribe, mMinInterval, mMaxInterval); - } - - chip::System::Clock::Timeout GetWaitDuration() const override { return ReportCommand::GetWaitDuration(); } - - void OnEventSubscription() override - { - // The ReadClient instance can not be released directly into the OnEventSubscription - // callback since it happens to be called by ReadClient itself which is doing additional - // work after that. - chip::DeviceLayer::PlatformMgr().ScheduleWork( - [](intptr_t arg) { - auto * command = reinterpret_cast(arg); - if (!command->IsInteractive()) - { - command->mReadClient.reset(); - } - command->SetCommandExitStatus(CHIP_NO_ERROR); - }, - reinterpret_cast(this)); - } - -private: - std::vector mClusterIds; - std::vector mEventIds; - - uint16_t mMinInterval; - uint16_t mMaxInterval; -}; diff --git a/examples/tv-casting-app/tv-casting-common/commands/clusters/SubscriptionsCommands.h b/examples/tv-casting-app/tv-casting-common/commands/clusters/SubscriptionsCommands.h deleted file mode 100644 index b1bada5c17a280..00000000000000 --- a/examples/tv-casting-app/tv-casting-common/commands/clusters/SubscriptionsCommands.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2022 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#pragma once - -#include "../common/CHIPCommand.h" -#include "../common/Commands.h" - -class ShutdownSubscription : public CHIPCommand -{ -public: - ShutdownSubscription(CredentialIssuerCommands * credsIssuerConfig) : CHIPCommand("shutdown-subscription", credsIssuerConfig) - { - AddArgument("subscription-id", 0, UINT64_MAX, &mSubscriptionId); - } - - /////////// CHIPCommand Interface ///////// - CHIP_ERROR RunCommand() override - { - CHIP_ERROR err = chip::app::InteractionModelEngine::GetInstance()->ShutdownSubscription(mSubscriptionId); - SetCommandExitStatus(err); - return CHIP_NO_ERROR; - } - chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(10); } - -private: - chip::SubscriptionId mSubscriptionId; -}; - -class ShutdownSubscriptions : public CHIPCommand -{ -public: - ShutdownSubscriptions(CredentialIssuerCommands * credsIssuerConfig) : CHIPCommand("shutdown-subscriptions", credsIssuerConfig) - { - AddArgument("fabric-index", 0, UINT64_MAX, &mFabricIndex); - AddArgument("node-id", 0, UINT64_MAX, &mNodeId); - } - - /////////// CHIPCommand Interface ///////// - CHIP_ERROR RunCommand() override - { - CHIP_ERROR err = chip::app::InteractionModelEngine::GetInstance()->ShutdownSubscriptions(mFabricIndex, mNodeId); - SetCommandExitStatus(err); - return CHIP_NO_ERROR; - } - chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(10); } - -private: - chip::FabricIndex mFabricIndex; - chip::NodeId mNodeId; -}; - -void registerClusterSubscriptions(Commands & commands, CredentialIssuerCommands * credsIssuerConfig) -{ - const char * clusterName = "Subscriptions"; - - commands_list clusterCommands = { - make_unique(credsIssuerConfig), // - make_unique(credsIssuerConfig), // - }; - - commands.Register(clusterName, clusterCommands); -} diff --git a/examples/tv-casting-app/tv-casting-common/commands/clusters/WriteAttributeCommand.h b/examples/tv-casting-app/tv-casting-common/commands/clusters/WriteAttributeCommand.h deleted file mode 100644 index dea6b9c5e159ee..00000000000000 --- a/examples/tv-casting-app/tv-casting-common/commands/clusters/WriteAttributeCommand.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) 2022 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#pragma once - -#include - -#include "DataModelLogger.h" -#include "ModelCommand.h" - -class WriteAttribute : public ModelCommand, public chip::app::WriteClient::Callback -{ -public: - WriteAttribute(CredentialIssuerCommands * credsIssuerConfig) : ModelCommand("write-by-id", credsIssuerConfig) - { - AddArgument("cluster-id", 0, UINT32_MAX, &mClusterId); - AddArgument("attribute-id", 0, UINT32_MAX, &mAttributeId); - AddArgument("attribute-value", &mAttributeValue); - AddArgument("timedInteractionTimeoutMs", 0, UINT16_MAX, &mTimedInteractionTimeoutMs); - AddArgument("data-version", 0, UINT32_MAX, &mDataVersion); - AddArgument("suppressResponse", 0, 1, &mSuppressResponse); - ModelCommand::AddArguments(); - } - - WriteAttribute(chip::ClusterId clusterId, CredentialIssuerCommands * credsIssuerConfig) : - ModelCommand("write-by-id", credsIssuerConfig), mClusterId(clusterId) - { - AddArgument("attribute-id", 0, UINT32_MAX, &mAttributeId); - AddArgument("attribute-value", &mAttributeValue); - AddArgument("timedInteractionTimeoutMs", 0, UINT16_MAX, &mTimedInteractionTimeoutMs); - AddArgument("data-version", 0, UINT32_MAX, &mDataVersion); - AddArgument("suppressResponse", 0, 1, &mSuppressResponse); - ModelCommand::AddArguments(); - } - - WriteAttribute(const char * attributeName, CredentialIssuerCommands * credsIssuerConfig) : - ModelCommand("write", credsIssuerConfig) - { - AddArgument("timedInteractionTimeoutMs", 0, UINT16_MAX, &mTimedInteractionTimeoutMs); - AddArgument("data-version", 0, UINT32_MAX, &mDataVersion); - AddArgument("suppressResponse", 0, 1, &mSuppressResponse); - } - - ~WriteAttribute() {} - - CHIP_ERROR SendCommand(chip::DeviceProxy * device, std::vector endpointIds) override - { - return WriteAttribute::SendCommand(device, endpointIds.at(0), mClusterId, mAttributeId, mAttributeValue); - } - - CHIP_ERROR SendGroupCommand(chip::GroupId groupId, chip::FabricIndex fabricIndex) override - { - return WriteAttribute::SendGroupCommand(groupId, fabricIndex, mClusterId, mAttributeId, mAttributeValue); - } - - /////////// WriteClient Callback Interface ///////// - void OnResponse(const chip::app::WriteClient * client, const chip::app::ConcreteDataAttributePath & path, - chip::app::StatusIB status) override - { - CHIP_ERROR error = status.ToChipError(); - if (CHIP_NO_ERROR != error) - { - ChipLogError(chipTool, "Response Failure: %s", chip::ErrorStr(error)); - mError = error; - } - } - - void OnError(const chip::app::WriteClient * client, CHIP_ERROR error) override - { - ChipLogProgress(chipTool, "Error: %s", chip::ErrorStr(error)); - mError = error; - } - - void OnDone(chip::app::WriteClient * client) override - { - mWriteClient.reset(); - SetCommandExitStatus(mError); - } - - template - CHIP_ERROR SendCommand(chip::DeviceProxy * device, chip::EndpointId endpointId, chip::ClusterId clusterId, - chip::AttributeId attributeId, const T & value) - { - ChipLogProgress(chipTool, "Sending WriteAttribute to cluster " ChipLogFormatMEI " on endpoint %u", - ChipLogValueMEI(clusterId), endpointId); - chip::app::AttributePathParams attributePathParams; - if (!device->GetSecureSession().Value()->IsGroupSession()) - { - attributePathParams.mEndpointId = endpointId; - } - attributePathParams.mClusterId = clusterId; - attributePathParams.mAttributeId = attributeId; - - mWriteClient = std::make_unique(device->GetExchangeManager(), this, mTimedInteractionTimeoutMs, - mSuppressResponse.ValueOr(false)); - - ReturnErrorOnFailure(mWriteClient->EncodeAttribute(attributePathParams, value, mDataVersion)); - - return mWriteClient->SendWriteRequest(device->GetSecureSession().Value()); - } - - template - CHIP_ERROR SendGroupCommand(chip::GroupId groupId, chip::FabricIndex fabricIndex, chip::ClusterId clusterId, - chip::AttributeId attributeId, const T & value) - { - - chip::app::AttributePathParams attributePathParams; - attributePathParams.mClusterId = clusterId; - attributePathParams.mAttributeId = attributeId; - - chip::Messaging::ExchangeManager * exchangeManager = chip::app::InteractionModelEngine::GetInstance()->GetExchangeManager(); - - ChipLogDetail(chipTool, "Sending Write Attribute to Group %u, on Fabric %x, for cluster %u with attributeId %u", groupId, - fabricIndex, clusterId, attributeId); - - auto writeClient = chip::Platform::MakeUnique(exchangeManager, this, mTimedInteractionTimeoutMs); - VerifyOrReturnError(writeClient != nullptr, CHIP_ERROR_NO_MEMORY); - ReturnErrorOnFailure(writeClient->EncodeAttribute(attributePathParams, value, mDataVersion)); - - chip::Transport::OutgoingGroupSession session(groupId, fabricIndex); - ReturnErrorOnFailure(writeClient->SendWriteRequest(chip::SessionHandle(session))); - writeClient.release(); - - return CHIP_NO_ERROR; - } - -private: - chip::ClusterId mClusterId; - chip::AttributeId mAttributeId; - CHIP_ERROR mError = CHIP_NO_ERROR; - chip::Optional mTimedInteractionTimeoutMs; - chip::Optional mDataVersion = chip::NullOptional; - chip::Optional mSuppressResponse; - CustomArgument mAttributeValue; - std::unique_ptr mWriteClient; -}; diff --git a/examples/tv-casting-app/tv-casting-common/commands/common/CHIPCommand.cpp b/examples/tv-casting-app/tv-casting-common/commands/common/CHIPCommand.cpp index a6034cb1969686..3a3995484e6e75 100644 --- a/examples/tv-casting-app/tv-casting-common/commands/common/CHIPCommand.cpp +++ b/examples/tv-casting-app/tv-casting-common/commands/common/CHIPCommand.cpp @@ -16,7 +16,7 @@ * */ -#include "CHIPCommand.h" +#include #include #include diff --git a/examples/tv-casting-app/tv-casting-common/commands/common/CHIPCommand.h b/examples/tv-casting-app/tv-casting-common/commands/common/CHIPCommand.h deleted file mode 100644 index 7d8f6d09f30371..00000000000000 --- a/examples/tv-casting-app/tv-casting-common/commands/common/CHIPCommand.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2021 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#pragma once - -#include "Command.h" -#include -#include -#include - -#pragma once - -class PersistentStorage; - -constexpr const char kIdentityAlpha[] = "alpha"; -constexpr const char kIdentityBeta[] = "beta"; -constexpr const char kIdentityGamma[] = "gamma"; -// The null fabric commissioner is a commissioner that isn't on a fabric. -// This is a legal configuration in which the commissioner delegates -// operational communication and invocation of the commssioning complete -// command to a separate on-fabric administrator node. -// -// The null-fabric-commissioner identity is provided here to demonstrate the -// commissioner portion of such an architecture. The null-fabric-commissioner -// can carry a commissioning flow up until the point of operational channel -// (CASE) communcation. -constexpr const char kIdentityNull[] = "null-fabric-commissioner"; - -class CHIPCommand : public Command -{ -public: - using ChipDeviceCommissioner = ::chip::Controller::DeviceCommissioner; - using ChipDeviceController = ::chip::Controller::DeviceController; - using IPAddress = ::chip::Inet::IPAddress; - using NodeId = ::chip::NodeId; - using PeerId = ::chip::PeerId; - using PeerAddress = ::chip::Transport::PeerAddress; - - static constexpr uint16_t kMaxGroupsPerFabric = 5; - static constexpr uint16_t kMaxGroupKeysPerFabric = 8; - - CHIPCommand(const char * commandName, CredentialIssuerCommands * credIssuerCmds) : - Command(commandName) // , mCredIssuerCmds(credIssuerCmds) - { -#if CHIP_CONFIG_TRANSPORT_TRACE_ENABLED - AddArgument("trace_file", &mTraceFile); - AddArgument("trace_log", 0, 1, &mTraceLog); -#endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED - } - - /////////// Command Interface ///////// - CHIP_ERROR Run() override; - - void SetCommandExitStatus(CHIP_ERROR status) - { - mCommandExitStatus = status; - StopWaiting(); - } - -protected: - // Will be called in a setting in which it's safe to touch the CHIP - // stack. The rules for Run() are as follows: - // - // 1) If error is returned, Run() must not call SetCommandExitStatus. - // 2) If success is returned Run() must either have called - // SetCommandExitStatus() or scheduled async work that will do that. - virtual CHIP_ERROR RunCommand() = 0; - - // Get the wait duration, in seconds, before the command times out. - virtual chip::System::Clock::Timeout GetWaitDuration() const = 0; - - // Shut down the command, in case any work needs to be done after the event - // loop has been stopped. - virtual void Shutdown() {} - -private: - static void RunQueuedCommand(intptr_t commandArg); - - CHIP_ERROR mCommandExitStatus = CHIP_ERROR_INTERNAL; - - CHIP_ERROR StartWaiting(chip::System::Clock::Timeout seconds); - void StopWaiting(); - - void StartTracing(); - void StopTracing(); - -#if CHIP_CONFIG_TRANSPORT_TRACE_ENABLED - chip::Optional mTraceFile; - chip::Optional mTraceLog; -#endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED -}; diff --git a/examples/tv-casting-app/tv-casting-common/commands/common/Command.cpp b/examples/tv-casting-app/tv-casting-common/commands/common/Command.cpp deleted file mode 100644 index b67880b2f2f38e..00000000000000 --- a/examples/tv-casting-app/tv-casting-common/commands/common/Command.cpp +++ /dev/null @@ -1,747 +0,0 @@ -/* - * Copyright (c) 2020 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "Command.h" -#include "platform/PlatformManager.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -constexpr const char * kOptionalArgumentPrefix = "--"; -constexpr size_t kOptionalArgumentPrefixLength = 2; - -bool Command::InitArguments(int argc, char ** argv) -{ - bool isValidCommand = false; - - size_t argvExtraArgsCount = (size_t) argc; - size_t mandatoryArgsCount = 0; - size_t optionalArgsCount = 0; - for (size_t i = 0; i < mArgs.size(); i++) - { - if (mArgs[i].isOptional()) - { - optionalArgsCount++; - } - else - { - mandatoryArgsCount++; - argvExtraArgsCount--; - } - } - - VerifyOrExit((size_t)(argc) >= mandatoryArgsCount && (argvExtraArgsCount == 0 || (argvExtraArgsCount && optionalArgsCount)), - ChipLogError(chipTool, "InitArgs: Wrong arguments number: %d instead of %u", argc, - static_cast(mandatoryArgsCount))); - - // Initialize mandatory arguments - for (size_t i = 0; i < mandatoryArgsCount; i++) - { - char * arg = argv[i]; - if (!InitArgument(i, arg)) - { - ExitNow(); - } - } - - // Initialize optional arguments - // Optional arguments expect a name and a value, so i is increased by 2 on every step. - for (size_t i = mandatoryArgsCount; i < (size_t) argc; i += 2) - { - bool found = false; - for (size_t j = mandatoryArgsCount; j < mandatoryArgsCount + optionalArgsCount; j++) - { - // optional arguments starts with kOptionalArgumentPrefix - if (strlen(argv[i]) <= kOptionalArgumentPrefixLength && - strncmp(argv[i], kOptionalArgumentPrefix, kOptionalArgumentPrefixLength) != 0) - { - continue; - } - - if (strcmp(argv[i] + strlen(kOptionalArgumentPrefix), mArgs[j].name) == 0) - { - found = true; - - VerifyOrExit((size_t) argc > (i + 1), - ChipLogError(chipTool, "InitArgs: Optional argument %s missing value.", argv[i])); - if (!InitArgument(j, argv[i + 1])) - { - ExitNow(); - } - } - } - VerifyOrExit(found, ChipLogError(chipTool, "InitArgs: Optional argument %s does not exist.", argv[i])); - } - - isValidCommand = true; - -exit: - return isValidCommand; -} - -static bool ParseAddressWithInterface(const char * addressString, Command::AddressWithInterface * address) -{ - struct addrinfo hints; - struct addrinfo * result; - int ret; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_DGRAM; - ret = getaddrinfo(addressString, nullptr, &hints, &result); - if (ret < 0) - { - ChipLogError(chipTool, "Invalid address: %s", addressString); - return false; - } - - if (result->ai_family == AF_INET6) - { - struct sockaddr_in6 * addr = reinterpret_cast(result->ai_addr); - address->address = ::chip::Inet::IPAddress::FromSockAddr(*addr); - address->interfaceId = ::chip::Inet::InterfaceId(addr->sin6_scope_id); - } -#if INET_CONFIG_ENABLE_IPV4 - else if (result->ai_family == AF_INET) - { - address->address = ::chip::Inet::IPAddress::FromSockAddr(*reinterpret_cast(result->ai_addr)); - address->interfaceId = chip::Inet::InterfaceId::Null(); - } -#endif // INET_CONFIG_ENABLE_IPV4 - else - { - ChipLogError(chipTool, "Unsupported address: %s", addressString); - return false; - } - - return true; -} - -// The callback should return whether the argument is valid, for the non-null -// case. It can't directly write to isValidArgument (by closing over it) -// because in the nullable-and-null case we need to do that from this function, -// via the return value. -template -bool HandleNullableOptional(Argument & arg, char * argValue, std::function callback) -{ - if (arg.isOptional()) - { - if (arg.isNullable()) - { - arg.value = &(reinterpret_cast> *>(arg.value)->Emplace()); - } - else - { - arg.value = &(reinterpret_cast *>(arg.value)->Emplace()); - } - } - - if (arg.isNullable()) - { - auto * nullable = reinterpret_cast *>(arg.value); - if (strcmp(argValue, "null") == 0) - { - nullable->SetNull(); - return true; - } - - arg.value = &(nullable->SetNonNull()); - } - - return callback(reinterpret_cast(arg.value)); -} - -bool Command::InitArgument(size_t argIndex, char * argValue) -{ - bool isValidArgument = false; - bool isHexNotation = strncmp(argValue, "0x", 2) == 0 || strncmp(argValue, "0X", 2) == 0; - - Argument arg = mArgs.at(argIndex); - switch (arg.type) - { - case ArgumentType::Complex: { - auto complexArgument = static_cast(arg.value); - return CHIP_NO_ERROR == complexArgument->Parse(arg.name, argValue); - } - - case ArgumentType::Custom: { - auto customArgument = static_cast(arg.value); - return CHIP_NO_ERROR == customArgument->Parse(arg.name, argValue); - } - - case ArgumentType::Vector16: - case ArgumentType::Vector32: { - std::vector values; - uint64_t min = chip::CanCastTo(arg.min) ? static_cast(arg.min) : 0; - uint64_t max = arg.max; - - std::stringstream ss(argValue); - while (ss.good()) - { - std::string valueAsString; - getline(ss, valueAsString, ','); - isHexNotation = strncmp(valueAsString.c_str(), "0x", 2) == 0 || strncmp(valueAsString.c_str(), "0X", 2) == 0; - - std::stringstream subss; - isHexNotation ? subss << std::hex << valueAsString : subss << valueAsString; - - uint64_t value; - subss >> value; - VerifyOrReturnError(!subss.fail() && subss.eof() && value >= min && value <= max, false); - values.push_back(value); - } - - if (arg.type == ArgumentType::Vector16) - { - auto vectorArgument = static_cast *>(arg.value); - for (uint64_t v : values) - { - vectorArgument->push_back(static_cast(v)); - } - } - else if (arg.type == ArgumentType::Vector32 && arg.flags != Argument::kOptional) - { - auto vectorArgument = static_cast *>(arg.value); - for (uint64_t v : values) - { - vectorArgument->push_back(static_cast(v)); - } - } - else if (arg.type == ArgumentType::Vector32 && arg.flags == Argument::kOptional) - { - std::vector vectorArgument; - for (uint64_t v : values) - { - vectorArgument.push_back(static_cast(v)); - } - - auto optionalArgument = static_cast> *>(arg.value); - optionalArgument->SetValue(vectorArgument); - } - else - { - return false; - } - - return true; - } - - case ArgumentType::Attribute: { - if (arg.isOptional() || arg.isNullable()) - { - isValidArgument = false; - } - else - { - char * value = reinterpret_cast(arg.value); - isValidArgument = (strcmp(argValue, value) == 0); - } - break; - } - - case ArgumentType::String: { - isValidArgument = HandleNullableOptional(arg, argValue, [&](auto * value) { - *value = argValue; - return true; - }); - break; - } - - case ArgumentType::CharString: { - isValidArgument = HandleNullableOptional(arg, argValue, [&](auto * value) { - *value = chip::Span(argValue, strlen(argValue)); - return true; - }); - break; - } - - case ArgumentType::OctetString: { - isValidArgument = HandleNullableOptional(arg, argValue, [&](auto * value) { - // We support two ways to pass an octet string argument. If it happens - // to be all-ASCII, you can just pass it in. Otherwise you can pass in - // 0x followed by the hex-encoded bytes. - size_t argLen = strlen(argValue); - static constexpr char hexPrefix[] = "hex:"; - constexpr size_t prefixLen = ArraySize(hexPrefix) - 1; // Don't count the null - if (strncmp(argValue, hexPrefix, prefixLen) == 0) - { - // Hex-encoded. Decode it into a temporary buffer first, so if we - // run into errors we can do correct "argument is not valid" logging - // that actually shows the value that was passed in. After we - // determine it's valid, modify the passed-in value to hold the - // right bytes, so we don't need to worry about allocating storage - // for this somewhere else. This works because the hex - // representation is always longer than the octet string it encodes, - // so we have enough space in argValue for the decoded version. - chip::Platform::ScopedMemoryBuffer buffer; - if (!buffer.Calloc(argLen)) // Bigger than needed, but it's fine. - { - return false; - } - - size_t octetCount = chip::Encoding::HexToBytes(argValue + prefixLen, argLen - prefixLen, buffer.Get(), argLen); - if (octetCount == 0) - { - return false; - } - - memcpy(argValue, buffer.Get(), octetCount); - *value = chip::ByteSpan(chip::Uint8::from_char(argValue), octetCount); - return true; - } - - // Just ASCII. Check for the "str:" prefix. - static constexpr char strPrefix[] = "str:"; - constexpr size_t strPrefixLen = ArraySize(strPrefix) - 1; // Don't count the null - if (strncmp(argValue, strPrefix, strPrefixLen) == 0) - { - // Skip the prefix - argValue += strPrefixLen; - argLen -= strPrefixLen; - } - *value = chip::ByteSpan(chip::Uint8::from_char(argValue), argLen); - return true; - }); - break; - } - - case ArgumentType::Bool: - case ArgumentType::Number_uint8: { - isValidArgument = HandleNullableOptional(arg, argValue, [&](auto * value) { - // stringstream treats uint8_t as char, which is not what we want here. - uint16_t tmpValue; - std::stringstream ss; - isHexNotation ? ss << std::hex << argValue : ss << argValue; - ss >> tmpValue; - if (chip::CanCastTo(tmpValue)) - { - *value = static_cast(tmpValue); - - uint64_t min = chip::CanCastTo(arg.min) ? static_cast(arg.min) : 0; - uint64_t max = arg.max; - return (!ss.fail() && ss.eof() && *value >= min && *value <= max); - } - - return false; - }); - break; - } - - case ArgumentType::Number_uint16: { - isValidArgument = HandleNullableOptional(arg, argValue, [&](auto * value) { - std::stringstream ss; - isHexNotation ? ss << std::hex << argValue : ss << argValue; - ss >> *value; - - uint64_t min = chip::CanCastTo(arg.min) ? static_cast(arg.min) : 0; - uint64_t max = arg.max; - return (!ss.fail() && ss.eof() && *value >= min && *value <= max); - }); - break; - } - - case ArgumentType::Number_uint32: { - isValidArgument = HandleNullableOptional(arg, argValue, [&](auto * value) { - std::stringstream ss; - isHexNotation ? ss << std::hex << argValue : ss << argValue; - ss >> *value; - - uint64_t min = chip::CanCastTo(arg.min) ? static_cast(arg.min) : 0; - uint64_t max = arg.max; - return (!ss.fail() && ss.eof() && *value >= min && *value <= max); - }); - break; - } - - case ArgumentType::Number_uint64: { - isValidArgument = HandleNullableOptional(arg, argValue, [&](auto * value) { - std::stringstream ss; - isHexNotation ? ss << std::hex << argValue : ss << argValue; - ss >> *value; - - uint64_t min = chip::CanCastTo(arg.min) ? static_cast(arg.min) : 0; - uint64_t max = arg.max; - return (!ss.fail() && ss.eof() && *value >= min && *value <= max); - }); - break; - } - - case ArgumentType::Number_int8: { - isValidArgument = HandleNullableOptional(arg, argValue, [&](auto * value) { - // stringstream treats int8_t as char, which is not what we want here. - int16_t tmpValue; - std::stringstream ss; - isHexNotation ? ss << std::hex << argValue : ss << argValue; - ss >> tmpValue; - if (chip::CanCastTo(tmpValue)) - { - *value = static_cast(tmpValue); - - int64_t min = arg.min; - int64_t max = chip::CanCastTo(arg.max) ? static_cast(arg.max) : INT64_MAX; - return (!ss.fail() && ss.eof() && *value >= min && *value <= max); - } - - return false; - }); - break; - } - - case ArgumentType::Number_int16: { - isValidArgument = HandleNullableOptional(arg, argValue, [&](auto * value) { - std::stringstream ss; - isHexNotation ? ss << std::hex << argValue : ss << argValue; - ss >> *value; - - int64_t min = arg.min; - int64_t max = chip::CanCastTo(arg.max) ? static_cast(arg.max) : INT64_MAX; - return (!ss.fail() && ss.eof() && *value >= min && *value <= max); - }); - break; - } - - case ArgumentType::Number_int32: { - isValidArgument = HandleNullableOptional(arg, argValue, [&](auto * value) { - std::stringstream ss; - isHexNotation ? ss << std::hex << argValue : ss << argValue; - ss >> *value; - - int64_t min = arg.min; - int64_t max = chip::CanCastTo(arg.max) ? static_cast(arg.max) : INT64_MAX; - return (!ss.fail() && ss.eof() && *value >= min && *value <= max); - }); - break; - } - - case ArgumentType::Number_int64: { - isValidArgument = HandleNullableOptional(arg, argValue, [&](auto * value) { - std::stringstream ss; - isHexNotation ? ss << std::hex << argValue : ss << argValue; - ss >> *value; - - int64_t min = arg.min; - int64_t max = chip::CanCastTo(arg.max) ? static_cast(arg.max) : INT64_MAX; - return (!ss.fail() && ss.eof() && *value >= min && *value <= max); - }); - break; - } - - case ArgumentType::Float: { - isValidArgument = HandleNullableOptional(arg, argValue, [&](auto * value) { - std::stringstream ss; - ss << argValue; - ss >> *value; - return (!ss.fail() && ss.eof()); - }); - break; - } - - case ArgumentType::Double: { - isValidArgument = HandleNullableOptional(arg, argValue, [&](auto * value) { - std::stringstream ss; - ss << argValue; - ss >> *value; - return (!ss.fail() && ss.eof()); - }); - break; - } - - case ArgumentType::Address: { - isValidArgument = HandleNullableOptional( - arg, argValue, [&](auto * value) { return ParseAddressWithInterface(argValue, value); }); - break; - } - } - - if (!isValidArgument) - { - ChipLogError(chipTool, "InitArgs: Invalid argument %s: %s", arg.name, argValue); - } - - return isValidArgument; -} - -size_t Command::AddArgument(const char * name, const char * value, uint8_t flags) -{ - Argument arg; - arg.type = ArgumentType::Attribute; - arg.name = name; - arg.value = const_cast(reinterpret_cast(value)); - arg.flags = flags; - - return AddArgumentToList(std::move(arg)); -} - -size_t Command::AddArgument(const char * name, char ** value, uint8_t flags) -{ - Argument arg; - arg.type = ArgumentType::String; - arg.name = name; - arg.value = reinterpret_cast(value); - arg.flags = flags; - - return AddArgumentToList(std::move(arg)); -} - -size_t Command::AddArgument(const char * name, chip::CharSpan * value, uint8_t flags) -{ - Argument arg; - arg.type = ArgumentType::CharString; - arg.name = name; - arg.value = reinterpret_cast(value); - arg.flags = flags; - - return AddArgumentToList(std::move(arg)); -} - -size_t Command::AddArgument(const char * name, chip::ByteSpan * value, uint8_t flags) -{ - Argument arg; - arg.type = ArgumentType::OctetString; - arg.name = name; - arg.value = reinterpret_cast(value); - arg.flags = flags; - - return AddArgumentToList(std::move(arg)); -} - -size_t Command::AddArgument(const char * name, AddressWithInterface * out, uint8_t flags) -{ - Argument arg; - arg.type = ArgumentType::Address; - arg.name = name; - arg.value = reinterpret_cast(out); - arg.flags = flags; - - return AddArgumentToList(std::move(arg)); -} - -size_t Command::AddArgument(const char * name, int64_t min, uint64_t max, std::vector * value) -{ - Argument arg; - arg.type = ArgumentType::Vector16; - arg.name = name; - arg.value = static_cast(value); - arg.min = min; - arg.max = max; - arg.flags = 0; - - return AddArgumentToList(std::move(arg)); -} - -size_t Command::AddArgument(const char * name, int64_t min, uint64_t max, std::vector * value) -{ - Argument arg; - arg.type = ArgumentType::Vector32; - arg.name = name; - arg.value = static_cast(value); - arg.min = min; - arg.max = max; - arg.flags = 0; - - return AddArgumentToList(std::move(arg)); -} - -size_t Command::AddArgument(const char * name, int64_t min, uint64_t max, chip::Optional> * value) -{ - Argument arg; - arg.type = ArgumentType::Vector32; - arg.name = name; - arg.value = static_cast(value); - arg.min = min; - arg.max = max; - arg.flags = Argument::kOptional; - - return AddArgumentToList(std::move(arg)); -} - -size_t Command::AddArgument(const char * name, ComplexArgument * value) -{ - Argument arg; - arg.type = ArgumentType::Complex; - arg.name = name; - arg.value = static_cast(value); - arg.flags = 0; - - return AddArgumentToList(std::move(arg)); -} - -size_t Command::AddArgument(const char * name, CustomArgument * value) -{ - Argument arg; - arg.type = ArgumentType::Custom; - arg.name = name; - arg.value = const_cast(reinterpret_cast(value)); - arg.flags = 0; - - return AddArgumentToList(std::move(arg)); -} - -size_t Command::AddArgument(const char * name, float min, float max, float * out, uint8_t flags) -{ - Argument arg; - arg.type = ArgumentType::Float; - arg.name = name; - arg.value = reinterpret_cast(out); - arg.flags = flags; - // Ignore min/max for now; they're always +-Infinity anyway. - - return AddArgumentToList(std::move(arg)); -} - -size_t Command::AddArgument(const char * name, double min, double max, double * out, uint8_t flags) -{ - Argument arg; - arg.type = ArgumentType::Double; - arg.name = name; - arg.value = reinterpret_cast(out); - arg.flags = flags; - // Ignore min/max for now; they're always +-Infinity anyway. - - return AddArgumentToList(std::move(arg)); -} - -size_t Command::AddArgument(const char * name, int64_t min, uint64_t max, void * out, ArgumentType type, uint8_t flags) -{ - Argument arg; - arg.type = type; - arg.name = name; - arg.value = out; - arg.min = min; - arg.max = max; - arg.flags = flags; - - return AddArgumentToList(std::move(arg)); -} - -size_t Command::AddArgument(const char * name, int64_t min, uint64_t max, void * out, uint8_t flags) -{ - Argument arg; - arg.type = ArgumentType::Number_uint8; - arg.name = name; - arg.value = out; - arg.min = min; - arg.max = max; - arg.flags = flags; - - return AddArgumentToList(std::move(arg)); -} - -const char * Command::GetArgumentName(size_t index) const -{ - if (index < mArgs.size()) - { - return mArgs.at(index).name; - } - - return nullptr; -} - -const char * Command::GetAttribute(void) const -{ - size_t argsCount = mArgs.size(); - for (size_t i = 0; i < argsCount; i++) - { - Argument arg = mArgs.at(i); - if (arg.type == ArgumentType::Attribute) - { - return reinterpret_cast(arg.value); - } - } - - return nullptr; -} - -const char * Command::GetEvent(void) const -{ - size_t argsCount = mArgs.size(); - for (size_t i = 0; i < argsCount; i++) - { - Argument arg = mArgs.at(i); - if (arg.type == ArgumentType::Attribute) - { - return reinterpret_cast(arg.value); - } - } - - return nullptr; -} - -size_t Command::AddArgumentToList(Argument && argument) -{ - if (argument.isOptional() || mArgs.empty() || !mArgs.back().isOptional()) - { - // Safe to just append. - mArgs.emplace_back(std::move(argument)); - return mArgs.size(); - } - - // We're inserting a non-optional arg but we already have something optional - // in the list. Insert before the first optional arg. - for (auto cur = mArgs.cbegin(), end = mArgs.cend(); cur != end; ++cur) - { - if ((*cur).isOptional()) - { - mArgs.emplace(cur, std::move(argument)); - return mArgs.size(); - } - } - - // Never reached. - VerifyOrDie(false); - return 0; -} - -void Command::ResetArguments() -{ - ChipLogError(AppServer, " -- Command::ResetArguments"); - for (size_t i = 0; i < mArgs.size(); i++) - { - const Argument arg = mArgs[i]; - const ArgumentType type = arg.type; - const uint8_t flags = arg.flags; - if (type == ArgumentType::Vector16 && flags != Argument::kOptional) - { - auto vectorArgument = static_cast *>(arg.value); - vectorArgument->clear(); - } - else if (type == ArgumentType::Vector32 && flags != Argument::kOptional) - { - auto vectorArgument = static_cast *>(arg.value); - vectorArgument->clear(); - } - else if (type == ArgumentType::Vector32 && flags == Argument::kOptional) - { - auto optionalArgument = static_cast> *>(arg.value); - if (optionalArgument->HasValue()) - { - optionalArgument->Value().clear(); - } - } - } -} diff --git a/examples/tv-casting-app/tv-casting-common/commands/common/Command.h b/examples/tv-casting-app/tv-casting-common/commands/common/Command.h deleted file mode 100644 index 975c90297affc4..00000000000000 --- a/examples/tv-casting-app/tv-casting-common/commands/common/Command.h +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright (c) 2020 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#pragma once - -#include "../clusters/ComplexArgument.h" -#include "../clusters/CustomArgument.h" -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -class Command; - -template -std::unique_ptr make_unique(Args &&... args) -{ - return std::unique_ptr(new T(std::forward(args)...)); -} - -struct movable_initializer_list -{ - movable_initializer_list(std::unique_ptr && in) : item(std::move(in)) {} - operator std::unique_ptr() const && { return std::move(item); } - mutable std::unique_ptr item; -}; - -typedef std::initializer_list commands_list; - -enum ArgumentType -{ - Number_uint8, - Number_uint16, - Number_uint32, - Number_uint64, - Number_int8, - Number_int16, - Number_int32, - Number_int64, - Float, - Double, - Bool, - String, - CharString, - OctetString, - Attribute, - Address, - Complex, - Custom, - Vector16, - Vector32, -}; - -struct Argument -{ - const char * name; - ArgumentType type; - int64_t min; - uint64_t max; - void * value; - uint8_t flags; - - enum - { - kOptional = (1 << 0), - kNullable = (1 << 1), - }; - - bool isOptional() const { return flags & kOptional; } - bool isNullable() const { return flags & kNullable; } -}; - -class Command -{ -public: - struct AddressWithInterface - { - ::chip::Inet::IPAddress address; - ::chip::Inet::InterfaceId interfaceId; - }; - - Command(const char * commandName) : mName(commandName) {} - virtual ~Command() {} - - const char * GetName(void) const { return mName; } - const char * GetAttribute(void) const; - const char * GetEvent(void) const; - const char * GetArgumentName(size_t index) const; - bool GetArgumentIsOptional(size_t index) const { return mArgs[index].isOptional(); } - size_t GetArgumentsCount(void) const { return mArgs.size(); } - - bool InitArguments(int argc, char ** argv); - size_t AddArgument(const char * name, const char * value, uint8_t flags = 0); - /** - * @brief - * Add a char string command argument - * - * @param name The name that will be displayed in the command help - * @param value A pointer to a `char *` where the argv value will be stored - * @returns The number of arguments currently added to the command - */ - size_t AddArgument(const char * name, char ** value, uint8_t flags = 0); - - /** - * Add an octet string command argument - */ - size_t AddArgument(const char * name, chip::ByteSpan * value, uint8_t flags = 0); - size_t AddArgument(const char * name, chip::Span * value, uint8_t flags = 0); - size_t AddArgument(const char * name, AddressWithInterface * out, uint8_t flags = 0); - size_t AddArgument(const char * name, ComplexArgument * value); - size_t AddArgument(const char * name, CustomArgument * value); - size_t AddArgument(const char * name, int64_t min, uint64_t max, bool * out, uint8_t flags = 0) - { - return AddArgument(name, min, max, reinterpret_cast(out), Bool, flags); - } - size_t AddArgument(const char * name, int64_t min, uint64_t max, int8_t * out, uint8_t flags = 0) - { - return AddArgument(name, min, max, reinterpret_cast(out), Number_int8, flags); - } - size_t AddArgument(const char * name, int64_t min, uint64_t max, int16_t * out, uint8_t flags = 0) - { - return AddArgument(name, min, max, reinterpret_cast(out), Number_int16, flags); - } - size_t AddArgument(const char * name, int64_t min, uint64_t max, int32_t * out, uint8_t flags = 0) - { - return AddArgument(name, min, max, reinterpret_cast(out), Number_int32, flags); - } - size_t AddArgument(const char * name, int64_t min, uint64_t max, int64_t * out, uint8_t flags = 0) - { - return AddArgument(name, min, max, reinterpret_cast(out), Number_int64, flags); - } - size_t AddArgument(const char * name, int64_t min, uint64_t max, uint8_t * out, uint8_t flags = 0) - { - return AddArgument(name, min, max, reinterpret_cast(out), Number_uint8, flags); - } - size_t AddArgument(const char * name, int64_t min, uint64_t max, uint16_t * out, uint8_t flags = 0) - { - return AddArgument(name, min, max, reinterpret_cast(out), Number_uint16, flags); - } - size_t AddArgument(const char * name, int64_t min, uint64_t max, uint32_t * out, uint8_t flags = 0) - { - return AddArgument(name, min, max, reinterpret_cast(out), Number_uint32, flags); - } - size_t AddArgument(const char * name, int64_t min, uint64_t max, uint64_t * out, uint8_t flags = 0) - { - return AddArgument(name, min, max, reinterpret_cast(out), Number_uint64, flags); - } - - size_t AddArgument(const char * name, float min, float max, float * out, uint8_t flags = 0); - size_t AddArgument(const char * name, double min, double max, double * out, uint8_t flags = 0); - - size_t AddArgument(const char * name, int64_t min, uint64_t max, std::vector * value); - size_t AddArgument(const char * name, int64_t min, uint64_t max, std::vector * value); - size_t AddArgument(const char * name, int64_t min, uint64_t max, chip::Optional> * value); - - template ::value>> - size_t AddArgument(const char * name, int64_t min, uint64_t max, T * out, uint8_t flags = 0) - { - return AddArgument(name, min, max, reinterpret_cast *>(out), flags); - } - - template - size_t AddArgument(const char * name, int64_t min, uint64_t max, chip::BitFlags * out, uint8_t flags = 0) - { - // This is a terrible hack that relies on BitFlags only having the one - // mValue member. - return AddArgument(name, min, max, reinterpret_cast(out), flags); - } - - template - size_t AddArgument(const char * name, chip::Optional * value) - { - return AddArgument(name, reinterpret_cast(value), Argument::kOptional); - } - - template - size_t AddArgument(const char * name, int64_t min, uint64_t max, chip::Optional * value) - { - return AddArgument(name, min, max, reinterpret_cast(value), Argument::kOptional); - } - - template - size_t AddArgument(const char * name, chip::app::DataModel::Nullable * value, uint8_t flags = 0) - { - return AddArgument(name, reinterpret_cast(value), flags | Argument::kNullable); - } - - template - size_t AddArgument(const char * name, int64_t min, uint64_t max, chip::app::DataModel::Nullable * value, uint8_t flags = 0) - { - return AddArgument(name, min, max, reinterpret_cast(value), flags | Argument::kNullable); - } - - size_t AddArgument(const char * name, float min, float max, chip::app::DataModel::Nullable * value, uint8_t flags = 0) - { - return AddArgument(name, min, max, reinterpret_cast(value), flags | Argument::kNullable); - } - - size_t AddArgument(const char * name, double min, double max, chip::app::DataModel::Nullable * value, uint8_t flags = 0) - { - return AddArgument(name, min, max, reinterpret_cast(value), flags | Argument::kNullable); - } - - void ResetArguments(); - - virtual CHIP_ERROR Run() = 0; - - bool IsInteractive() { return mIsInteractive; } - - CHIP_ERROR RunAsInteractive() - { - mIsInteractive = true; - return Run(); - } - -private: - bool InitArgument(size_t argIndex, char * argValue); - size_t AddArgument(const char * name, int64_t min, uint64_t max, void * out, ArgumentType type, uint8_t flags); - size_t AddArgument(const char * name, int64_t min, uint64_t max, void * out, uint8_t flags); - - /** - * Add the Argument to our list. This preserves the property that all - * optional arguments come at the end of the list. - */ - size_t AddArgumentToList(Argument && argument); - - const char * mName = nullptr; - bool mIsInteractive = false; - std::vector mArgs; -}; diff --git a/examples/tv-casting-app/tv-casting-common/commands/common/Commands.cpp b/examples/tv-casting-app/tv-casting-common/commands/common/Commands.cpp deleted file mode 100644 index 0fbaeeefe7b199..00000000000000 --- a/examples/tv-casting-app/tv-casting-common/commands/common/Commands.cpp +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright (c) 2020 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "Commands.h" - -#include "Command.h" - -#include -#include - -#include -#include - -void Commands::Register(const char * clusterName, commands_list commandsList) -{ - for (auto & command : commandsList) - { - mClusters[clusterName].push_back(std::move(command)); - } -} - -int Commands::Run(int argc, char ** argv) -{ - CHIP_ERROR err = CHIP_NO_ERROR; - - err = chip::Platform::MemoryInit(); - VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "Init Memory failure: %s", chip::ErrorStr(err))); - - // err = mStorage.Init(); - // VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "Init Storage failure: %s", chip::ErrorStr(err))); - - // chip::Logging::SetLogFilter(mStorage.GetLoggingLevel()); - - err = RunCommand(argc, argv); - VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(chipTool, "Run command failure: %s", chip::ErrorStr(err))); - -exit: - return (err == CHIP_NO_ERROR) ? EXIT_SUCCESS : EXIT_FAILURE; -} - -int Commands::RunInteractive(int argc, char ** argv) -{ - CHIP_ERROR err = RunCommand(argc, argv, true); - return (err == CHIP_NO_ERROR) ? EXIT_SUCCESS : EXIT_FAILURE; -} - -CHIP_ERROR Commands::RunCommand(int argc, char ** argv, bool interactive) -{ - std::map::iterator cluster; - Command * command = nullptr; - - if (argc <= 1) - { - ChipLogError(chipTool, "Missing cluster name"); - ShowClusters(argv[0]); - return CHIP_ERROR_INVALID_ARGUMENT; - } - - cluster = GetCluster(argv[1]); - if (cluster == mClusters.end()) - { - ChipLogError(chipTool, "Unknown cluster: %s", argv[1]); - ShowClusters(argv[0]); - return CHIP_ERROR_INVALID_ARGUMENT; - } - - if (argc <= 2) - { - ChipLogError(chipTool, "Missing command name"); - ShowCluster(argv[0], argv[1], cluster->second); - return CHIP_ERROR_INVALID_ARGUMENT; - } - - if (!IsGlobalCommand(argv[2])) - { - command = GetCommand(cluster->second, argv[2]); - if (command == nullptr) - { - ChipLogError(chipTool, "Unknown command: %s", argv[2]); - ShowCluster(argv[0], argv[1], cluster->second); - return CHIP_ERROR_INVALID_ARGUMENT; - } - } - else if (IsEventCommand(argv[2])) - { - if (argc <= 3) - { - ChipLogError(chipTool, "Missing event name"); - ShowClusterEvents(argv[0], argv[1], argv[2], cluster->second); - return CHIP_ERROR_INVALID_ARGUMENT; - } - - command = GetGlobalCommand(cluster->second, argv[2], argv[3]); - if (command == nullptr) - { - ChipLogError(chipTool, "Unknown event: %s", argv[3]); - ShowClusterEvents(argv[0], argv[1], argv[2], cluster->second); - return CHIP_ERROR_INVALID_ARGUMENT; - } - } - else - { - if (argc <= 3) - { - ChipLogError(chipTool, "Missing attribute name"); - ShowClusterAttributes(argv[0], argv[1], argv[2], cluster->second); - return CHIP_ERROR_INVALID_ARGUMENT; - } - - command = GetGlobalCommand(cluster->second, argv[2], argv[3]); - if (command == nullptr) - { - ChipLogError(chipTool, "Unknown attribute: %s", argv[3]); - ShowClusterAttributes(argv[0], argv[1], argv[2], cluster->second); - return CHIP_ERROR_INVALID_ARGUMENT; - } - } - - if (!command->InitArguments(argc - 3, &argv[3])) - { - ShowCommand(argv[0], argv[1], command); - return CHIP_ERROR_INVALID_ARGUMENT; - } - - return interactive ? command->RunAsInteractive() : command->Run(); -} - -std::map::iterator Commands::GetCluster(std::string clusterName) -{ - for (auto & cluster : mClusters) - { - std::string key(cluster.first); - std::transform(key.begin(), key.end(), key.begin(), ::tolower); - if (key.compare(clusterName) == 0) - { - return mClusters.find(cluster.first); - } - } - - return mClusters.end(); -} - -Command * Commands::GetCommand(CommandsVector & commands, std::string commandName) -{ - for (auto & command : commands) - { - if (commandName.compare(command->GetName()) == 0) - { - return command.get(); - } - } - - return nullptr; -} - -Command * Commands::GetGlobalCommand(CommandsVector & commands, std::string commandName, std::string attributeName) -{ - for (auto & command : commands) - { - if (commandName.compare(command->GetName()) == 0 && attributeName.compare(command->GetAttribute()) == 0) - { - return command.get(); - } - } - - return nullptr; -} - -bool Commands::IsAttributeCommand(std::string commandName) const -{ - return commandName.compare("read") == 0 || commandName.compare("write") == 0 || commandName.compare("subscribe") == 0; -} - -bool Commands::IsEventCommand(std::string commandName) const -{ - return commandName.compare("read-event") == 0 || commandName.compare("subscribe-event") == 0; -} - -bool Commands::IsGlobalCommand(std::string commandName) const -{ - return IsAttributeCommand(commandName) || IsEventCommand(commandName); -} - -void Commands::ShowClusters(std::string executable) -{ - fprintf(stderr, "Usage:\n"); - fprintf(stderr, " %s cluster_name command_name [param1 param2 ...]\n", executable.c_str()); - fprintf(stderr, "\n"); - fprintf(stderr, " +-------------------------------------------------------------------------------------+\n"); - fprintf(stderr, " | Clusters: |\n"); - fprintf(stderr, " +-------------------------------------------------------------------------------------+\n"); - for (auto & cluster : mClusters) - { - std::string clusterName(cluster.first); - std::transform(clusterName.begin(), clusterName.end(), clusterName.begin(), - [](unsigned char c) { return std::tolower(c); }); - fprintf(stderr, " | * %-82s|\n", clusterName.c_str()); - } - fprintf(stderr, " +-------------------------------------------------------------------------------------+\n"); -} - -void Commands::ShowCluster(std::string executable, std::string clusterName, CommandsVector & commands) -{ - fprintf(stderr, "Usage:\n"); - fprintf(stderr, " %s %s command_name [param1 param2 ...]\n", executable.c_str(), clusterName.c_str()); - fprintf(stderr, "\n"); - fprintf(stderr, " +-------------------------------------------------------------------------------------+\n"); - fprintf(stderr, " | Commands: |\n"); - fprintf(stderr, " +-------------------------------------------------------------------------------------+\n"); - bool readCommand = false; - bool writeCommand = false; - bool subscribeCommand = false; - bool readEventCommand = false; - bool subscribeEventCommand = false; - for (auto & command : commands) - { - bool shouldPrint = true; - - if (IsGlobalCommand(command->GetName())) - { - if (strcmp(command->GetName(), "read") == 0 && !readCommand) - { - readCommand = true; - } - else if (strcmp(command->GetName(), "write") == 0 && !writeCommand) - { - writeCommand = true; - } - else if (strcmp(command->GetName(), "subscribe") == 0 && !subscribeCommand) - { - subscribeCommand = true; - } - else if (strcmp(command->GetName(), "read-event") == 0 && !readEventCommand) - { - readEventCommand = true; - } - else if (strcmp(command->GetName(), "subscribe-event") == 0 && !subscribeEventCommand) - { - subscribeEventCommand = true; - } - else - { - shouldPrint = false; - } - } - - if (shouldPrint) - { - fprintf(stderr, " | * %-82s|\n", command->GetName()); - } - } - fprintf(stderr, " +-------------------------------------------------------------------------------------+\n"); -} - -void Commands::ShowClusterAttributes(std::string executable, std::string clusterName, std::string commandName, - CommandsVector & commands) -{ - fprintf(stderr, "Usage:\n"); - fprintf(stderr, " %s %s %s attribute-name [param1 param2 ...]\n", executable.c_str(), clusterName.c_str(), - commandName.c_str()); - fprintf(stderr, "\n"); - fprintf(stderr, " +-------------------------------------------------------------------------------------+\n"); - fprintf(stderr, " | Attributes: |\n"); - fprintf(stderr, " +-------------------------------------------------------------------------------------+\n"); - for (auto & command : commands) - { - if (commandName.compare(command->GetName()) == 0) - { - fprintf(stderr, " | * %-82s|\n", command->GetAttribute()); - } - } - fprintf(stderr, " +-------------------------------------------------------------------------------------+\n"); -} - -void Commands::ShowClusterEvents(std::string executable, std::string clusterName, std::string commandName, - CommandsVector & commands) -{ - fprintf(stderr, "Usage:\n"); - fprintf(stderr, " %s %s %s event-name [param1 param2 ...]\n", executable.c_str(), clusterName.c_str(), commandName.c_str()); - fprintf(stderr, "\n"); - fprintf(stderr, " +-------------------------------------------------------------------------------------+\n"); - fprintf(stderr, " | Events: |\n"); - fprintf(stderr, " +-------------------------------------------------------------------------------------+\n"); - for (auto & command : commands) - { - if (commandName.compare(command->GetName()) == 0) - { - fprintf(stderr, " | * %-82s|\n", command->GetEvent()); - } - } - fprintf(stderr, " +-------------------------------------------------------------------------------------+\n"); -} - -void Commands::ShowCommand(std::string executable, std::string clusterName, Command * command) -{ - fprintf(stderr, "Usage:\n"); - - std::string arguments; - arguments += command->GetName(); - - size_t argumentsCount = command->GetArgumentsCount(); - for (size_t i = 0; i < argumentsCount; i++) - { - arguments += " "; - bool isOptional = command->GetArgumentIsOptional(i); - if (isOptional) - { - arguments += "[--"; - } - arguments += command->GetArgumentName(i); - if (isOptional) - { - arguments += "]"; - } - } - fprintf(stderr, " %s %s %s\n", executable.c_str(), clusterName.c_str(), arguments.c_str()); -} diff --git a/examples/tv-casting-app/tv-casting-common/commands/common/Commands.h b/examples/tv-casting-app/tv-casting-common/commands/common/Commands.h deleted file mode 100644 index a179bc33e53ff7..00000000000000 --- a/examples/tv-casting-app/tv-casting-common/commands/common/Commands.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2020 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#pragma once - -// #include "../../config/PersistentStorage.h" -#include "Command.h" -#include - -class Commands -{ -public: - using CommandsVector = ::std::vector>; - - void Register(const char * clusterName, commands_list commandsList); - int Run(int argc, char ** argv); - int RunInteractive(int argc, char ** argv); - -private: - CHIP_ERROR RunCommand(int argc, char ** argv, bool interactive = false); - - std::map::iterator GetCluster(std::string clusterName); - Command * GetCommand(CommandsVector & commands, std::string commandName); - Command * GetGlobalCommand(CommandsVector & commands, std::string commandName, std::string attributeName); - bool IsAttributeCommand(std::string commandName) const; - bool IsEventCommand(std::string commandName) const; - bool IsGlobalCommand(std::string commandName) const; - - void ShowClusters(std::string executable); - void ShowCluster(std::string executable, std::string clusterName, CommandsVector & commands); - void ShowClusterAttributes(std::string executable, std::string clusterName, std::string commandName, CommandsVector & commands); - void ShowClusterEvents(std::string executable, std::string clusterName, std::string commandName, CommandsVector & commands); - void ShowCommand(std::string executable, std::string clusterName, Command * command); - - std::map mClusters; - // PersistentStorage mStorage; -}; diff --git a/examples/tv-casting-app/tv-casting-common/commands/common/CredentialIssuerCommands.h b/examples/tv-casting-app/tv-casting-common/commands/common/CredentialIssuerCommands.h deleted file mode 100644 index 951ef86efceb40..00000000000000 --- a/examples/tv-casting-app/tv-casting-common/commands/common/CredentialIssuerCommands.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2021-2022 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#pragma once - -#include -#include -#include -#include -#include - -class CredentialIssuerCommands -{ -public: - virtual ~CredentialIssuerCommands() {} - - /** - * @brief - * This function is used to initialize the Credentials Issuer, if needed. - * - * @param[in] storage A reference to the storage, where the Credentials Issuer can optionally use to access the keypair in - * storage. - * - * @return CHIP_ERROR CHIP_NO_ERROR on success, or corresponding error code. - */ - virtual CHIP_ERROR InitializeCredentialsIssuer(chip::PersistentStorageDelegate & storage) = 0; - - /** - * @brief - * This function is used to setup Device Attestation Singletons and intialize Setup/Commissioning Parameters with a custom - * Device Attestation Verifier object. - * - * @param[in] setupParams A reference to the Setup/Commissioning Parameters, to be initialized with custom Device Attestation - * Verifier. - * @param[in] trustStore A pointer to the PAA trust store to use to find valid PAA roots. - * - * @return CHIP_ERROR CHIP_NO_ERROR on success, or corresponding error code. - */ - virtual CHIP_ERROR SetupDeviceAttestation(chip::Controller::SetupParams & setupParams, - const chip::Credentials::AttestationTrustStore * trustStore) = 0; - - virtual chip::Controller::OperationalCredentialsDelegate * GetCredentialIssuer() = 0; - - /** - * @brief - * This function is used to Generate NOC Chain for the Controller/Commissioner. Parameters follow the example implementation, - * so some parameters may not translate to the real remote Credentials Issuer policy. - * - * @param[in] nodeId The desired NodeId for the generated NOC Chain - May be optional/unused in some implementations. - * @param[in] fabricId The desired FabricId for the generated NOC Chain - May be optional/unused in some implementations. - * @param[in] cats The desired CATs for the generated NOC Chain - May be optional/unused in some implementations. - * @param[in] keypair The desired Keypair for the generated NOC Chain - May be optional/unused in some implementations. - * @param[in,out] rcac Buffer to hold the Root Certificate of the generated NOC Chain. - * @param[in,out] icac Buffer to hold the Intermediate Certificate of the generated NOC Chain. - * @param[in,out] noc Buffer to hold the Leaf Certificate of the generated NOC Chain. - * - * @return CHIP_ERROR CHIP_NO_ERROR on success, or corresponding error code. - */ - virtual CHIP_ERROR GenerateControllerNOCChain(chip::NodeId nodeId, chip::FabricId fabricId, const chip::CATValues & cats, - chip::Crypto::P256Keypair & keypair, chip::MutableByteSpan & rcac, - chip::MutableByteSpan & icac, chip::MutableByteSpan & noc) = 0; -}; diff --git a/examples/tv-casting-app/tv-casting-common/commands/example/ExampleCredentialIssuerCommands.h b/examples/tv-casting-app/tv-casting-common/commands/example/ExampleCredentialIssuerCommands.h deleted file mode 100644 index 74646c8b5f10ba..00000000000000 --- a/examples/tv-casting-app/tv-casting-common/commands/example/ExampleCredentialIssuerCommands.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2021-2022 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#pragma once - -#include -#include -#include -#include -#include -#include - -class ExampleCredentialIssuerCommands : public CredentialIssuerCommands -{ -public: - CHIP_ERROR InitializeCredentialsIssuer(chip::PersistentStorageDelegate & storage) override - { - return mOpCredsIssuer.Initialize(storage); - } - CHIP_ERROR SetupDeviceAttestation(chip::Controller::SetupParams & setupParams, - const chip::Credentials::AttestationTrustStore * trustStore) override - { - chip::Credentials::SetDeviceAttestationCredentialsProvider(chip::Credentials::Examples::GetExampleDACProvider()); - - setupParams.deviceAttestationVerifier = chip::Credentials::GetDefaultDACVerifier(trustStore); - - return CHIP_NO_ERROR; - } - chip::Controller::OperationalCredentialsDelegate * GetCredentialIssuer() override { return &mOpCredsIssuer; } - CHIP_ERROR GenerateControllerNOCChain(chip::NodeId nodeId, chip::FabricId fabricId, const chip::CATValues & cats, - chip::Crypto::P256Keypair & keypair, chip::MutableByteSpan & rcac, - chip::MutableByteSpan & icac, chip::MutableByteSpan & noc) override - { - return mOpCredsIssuer.GenerateNOCChainAfterValidation(nodeId, fabricId, cats, keypair.Pubkey(), rcac, icac, noc); - } - -private: - chip::Controller::ExampleOperationalCredentialsIssuer mOpCredsIssuer; -}; diff --git a/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter b/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter index b91d285c9f8c2e..f2af646689e52e 100644 --- a/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter +++ b/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter @@ -555,6 +555,7 @@ server cluster GeneralCommissioning = 48 { struct BasicCommissioningInfo { int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; } attribute access(write: administer) int64u breadcrumb = 0; @@ -777,74 +778,6 @@ server cluster Groups = 4 { command access(invoke: manage) AddGroupIfIdentifying(AddGroupIfIdentifyingRequest): DefaultSuccess = 5; } -server cluster IasZone = 1280 { - enum IasEnrollResponseCode : ENUM8 { - kSuccess = 0; - kNotSupported = 1; - kNoEnrollPermit = 2; - kTooManyZones = 3; - } - - enum IasZoneType : ENUM16 { - kStandardCie = 0; - kMotionSensor = 13; - kContactSwitch = 21; - kFireSensor = 40; - kWaterSensor = 42; - kGasSensor = 43; - kPersonalEmergencyDevice = 44; - kVibrationMovementSensor = 45; - kRemoteControl = 271; - kKeyFob = 277; - kKeypad = 541; - kStandardWarningDevice = 549; - kGlassBreakSensor = 550; - kCarbonMonoxideSensor = 551; - kSecurityRepeater = 553; - kInvalidZoneType = 65535; - } - - bitmap IasZoneStatus : BITMAP16 { - kAlarm1 = 0x1; - kAlarm2 = 0x2; - kTamper = 0x4; - kBattery = 0x8; - kSupervisionReports = 0x10; - kRestoreReports = 0x20; - kTrouble = 0x40; - kAc = 0x80; - kTest = 0x100; - kBatteryDefect = 0x200; - } - - readonly attribute enum8 zoneState = 0; - readonly attribute enum16 zoneType = 1; - readonly attribute bitmap16 zoneStatus = 2; - attribute node_id iasCieAddress = 16; - readonly attribute int8u zoneId = 17; - readonly attribute bitmap32 featureMap = 65532; - readonly attribute int16u clusterRevision = 65533; - - request struct ZoneEnrollResponseRequest { - IasEnrollResponseCode enrollResponseCode = 0; - INT8U zoneId = 1; - } - - response struct ZoneStatusChangeNotification = 0 { - IasZoneStatus zoneStatus = 0; - BITMAP8 extendedStatus = 1; - INT8U zoneId = 2; - INT16U delay = 3; - } - - response struct ZoneEnrollRequest = 1 { - IasZoneType zoneType = 0; - INT16U manufacturerCode = 1; - } - - command ZoneEnrollResponse(ZoneEnrollResponseRequest): DefaultSuccess = 0; -} - server cluster Identify = 3 { enum IdentifyEffectIdentifier : ENUM8 { kBlink = 0; @@ -2594,16 +2527,6 @@ endpoint 1 { ram attribute clusterRevision default = 1; } - server cluster IasZone { - ram attribute zoneState; - ram attribute zoneType; - ram attribute zoneStatus; - ram attribute iasCieAddress; - ram attribute zoneId default = 0xff; - ram attribute featureMap; - ram attribute clusterRevision default = 2; - } - server cluster WakeOnLan { ram attribute MACAddress; ram attribute featureMap; diff --git a/examples/window-app/common/include/WindowApp.h b/examples/window-app/common/include/WindowApp.h index 22a7c66ad924e1..210af1bf1a5b71 100644 --- a/examples/window-app/common/include/WindowApp.h +++ b/examples/window-app/common/include/WindowApp.h @@ -112,12 +112,14 @@ class WindowApp void LiftContinueToTarget() { LiftUpdate(false); } void LiftStepToward(OperationalState direction); void LiftSchedulePositionSet(chip::Percent100ths position) { SchedulePositionSet(position, false); } + void LiftScheduleOperationalStateSet(OperationalState opState) { ScheduleOperationalStateSet(opState, false); } void TiltUpdate(bool newTarget); void TiltGoToTarget() { TiltUpdate(true); } void TiltContinueToTarget() { TiltUpdate(false); } void TiltStepToward(OperationalState direction); void TiltSchedulePositionSet(chip::Percent100ths position) { SchedulePositionSet(position, true); } + void TiltScheduleOperationalStateSet(OperationalState opState) { ScheduleOperationalStateSet(opState, true); } void StepToward(OperationalState direction, bool isTilt); @@ -128,11 +130,6 @@ class WindowApp chip::EndpointId mEndpoint = 0; - // Attribute: Id 10 OperationalStatus - OperationalStatus mOperationalStatus = { .global = OperationalState::Stall, - .lift = OperationalState::Stall, - .tilt = OperationalState::Stall }; - Timer * mLiftTimer = nullptr; Timer * mTiltTimer = nullptr; OperationalState mLiftOpState = OperationalState::Stall; @@ -146,14 +143,14 @@ class WindowApp union { chip::Percent100ths percent100ths; - OperationalStatus opStatus; + OperationalState opState; }; }; void SchedulePositionSet(chip::Percent100ths position, bool isTilt); static void CallbackPositionSet(intptr_t arg); - void ScheduleOperationalStatusSetWithGlobalUpdate(OperationalStatus opStatus); - static void CallbackOperationalStatusSetWithGlobalUpdate(intptr_t arg); + void ScheduleOperationalStateSet(OperationalState opState, bool isTilt); + static void CallbackOperationalStateSet(intptr_t arg); }; static WindowApp & Instance(); diff --git a/examples/window-app/common/src/WindowApp.cpp b/examples/window-app/common/src/WindowApp.cpp index 0cada84b7b046c..4c846ecf6a8c05 100644 --- a/examples/window-app/common/src/WindowApp.cpp +++ b/examples/window-app/common/src/WindowApp.cpp @@ -296,6 +296,7 @@ void WindowApp::DispatchEventAttributeChange(chip::EndpointId endpoint, chip::At Cover * cover = GetCover(endpoint); chip::BitMask mode; chip::BitMask configStatus; + chip::BitMask opStatus; if (nullptr == cover) { @@ -316,7 +317,8 @@ void WindowApp::DispatchEventAttributeChange(chip::EndpointId endpoint, chip::At /* RO OperationalStatus */ case Attributes::OperationalStatus::Id: chip::DeviceLayer::PlatformMgr().LockChipStack(); - emberAfWindowCoveringClusterPrint("Global OpState: %02X\n", (unsigned int) OperationalStatusGet(endpoint).global); + opStatus = OperationalStatusGet(endpoint); + OperationalStatusPrint(opStatus); chip::DeviceLayer::PlatformMgr().UnlockChipStack(); break; /* RW Mode */ @@ -432,8 +434,6 @@ void WindowApp::Cover::Init(chip::EndpointId endpoint) configStatus.Set(ConfigStatus::kOnlineReserved); ConfigStatusSet(endpoint, configStatus); - OperationalStatusSetWithGlobalUpdated(endpoint, mOperationalStatus); - // Attribute: Id 13 EndProductType EndProductTypeSet(endpoint, EndProductType::kInteriorBlind); @@ -448,8 +448,7 @@ void WindowApp::Cover::Init(chip::EndpointId endpoint) ModeSet(endpoint, mode); // Attribute: Id 27 SafetyStatus (Optional) - SafetyStatus safetyStatus = { 0x00 }; // 0 is no issues; - SafetyStatusSet(endpoint, safetyStatus); + chip::BitFlags safetyStatus(0x00); // 0 is no issues; } void WindowApp::Cover::Finish() @@ -489,8 +488,7 @@ void WindowApp::Cover::LiftUpdate(bool newTarget) Attributes::TargetPositionLiftPercent100ths::Get(mEndpoint, target); Attributes::CurrentPositionLiftPercent100ths::Get(mEndpoint, current); - OperationalStatus opStatus = OperationalStatusGet(mEndpoint); - OperationalState opState = ComputeOperationalState(target, current); + OperationalState opState = ComputeOperationalState(target, current); chip::DeviceLayer::PlatformMgr().UnlockChipStack(); @@ -514,9 +512,8 @@ void WindowApp::Cover::LiftUpdate(bool newTarget) mLiftOpState = OperationalState::Stall; } - opStatus.lift = mLiftOpState; - ScheduleOperationalStatusSetWithGlobalUpdate(opStatus); + LiftScheduleOperationalStateSet(mLiftOpState); if ((OperationalState::Stall != mLiftOpState) && mLiftTimer) { @@ -555,8 +552,7 @@ void WindowApp::Cover::TiltUpdate(bool newTarget) Attributes::TargetPositionTiltPercent100ths::Get(mEndpoint, target); Attributes::CurrentPositionTiltPercent100ths::Get(mEndpoint, current); - OperationalStatus opStatus = OperationalStatusGet(mEndpoint); - OperationalState opState = ComputeOperationalState(target, current); + OperationalState opState = ComputeOperationalState(target, current); chip::DeviceLayer::PlatformMgr().UnlockChipStack(); @@ -580,9 +576,8 @@ void WindowApp::Cover::TiltUpdate(bool newTarget) mTiltOpState = OperationalState::Stall; } - opStatus.tilt = mTiltOpState; - ScheduleOperationalStatusSetWithGlobalUpdate(opStatus); + TiltScheduleOperationalStateSet(mTiltOpState); if ((OperationalState::Stall != mTiltOpState) && mTiltTimer) { @@ -676,21 +671,23 @@ void WindowApp::Cover::CallbackPositionSet(intptr_t arg) chip::Platform::Delete(data); } -void WindowApp::Cover::ScheduleOperationalStatusSetWithGlobalUpdate(OperationalStatus opStatus) +void WindowApp::Cover::ScheduleOperationalStateSet(OperationalState opState, bool isTilt) { CoverWorkData * data = chip::Platform::New(); VerifyOrReturn(data != nullptr, emberAfWindowCoveringClusterPrint("Cover::OperationalStatusSet - Out of Memory for WorkData")); data->mEndpointId = mEndpoint; - data->opStatus = opStatus; + data->opState = opState; + data->isTilt = isTilt; - chip::DeviceLayer::PlatformMgr().ScheduleWork(CallbackOperationalStatusSetWithGlobalUpdate, reinterpret_cast(data)); + chip::DeviceLayer::PlatformMgr().ScheduleWork(CallbackOperationalStateSet, reinterpret_cast(data)); } -void WindowApp::Cover::CallbackOperationalStatusSetWithGlobalUpdate(intptr_t arg) +void WindowApp::Cover::CallbackOperationalStateSet(intptr_t arg) { WindowApp::Cover::CoverWorkData * data = reinterpret_cast(arg); - OperationalStatusSetWithGlobalUpdated(data->mEndpointId, data->opStatus); + + OperationalStateSet(data->mEndpointId, data->isTilt ? OperationalStatus::kTilt : OperationalStatus::kLift, data->opState); chip::Platform::Delete(data); } diff --git a/examples/window-app/common/window-app.matter b/examples/window-app/common/window-app.matter index e60eb56acf245a..20c5a7e539dc90 100644 --- a/examples/window-app/common/window-app.matter +++ b/examples/window-app/common/window-app.matter @@ -227,6 +227,7 @@ server cluster GeneralCommissioning = 48 { struct BasicCommissioningInfo { int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; } attribute access(write: administer) int64u breadcrumb = 0; @@ -1468,14 +1469,7 @@ server cluster WindowCovering = 258 { kTiltEncoderControlled = 0x40; } - bitmap Mode : BITMAP8 { - kMotorDirectionReversed = 0x1; - kCalibrationMode = 0x2; - kMaintenanceMode = 0x4; - kLedFeedback = 0x8; - } - - bitmap WcFeature : BITMAP32 { + bitmap Feature : BITMAP32 { kLift = 0x1; kTilt = 0x2; kPositionAwareLift = 0x4; @@ -1483,13 +1477,20 @@ server cluster WindowCovering = 258 { kPositionAwareTilt = 0x10; } - bitmap WcOperationalStatus : BITMAP8 { + bitmap Mode : BITMAP8 { + kMotorDirectionReversed = 0x1; + kCalibrationMode = 0x2; + kMaintenanceMode = 0x4; + kLedFeedback = 0x8; + } + + bitmap OperationalStatus : BITMAP8 { kGlobal = 0x3; kLift = 0xC; kTilt = 0x30; } - bitmap WcSafetyStatus : BITMAP16 { + bitmap SafetyStatus : BITMAP16 { kRemoteLockout = 0x1; kTamperDetection = 0x2; kFailedCommunication = 0x4; @@ -1514,7 +1515,7 @@ server cluster WindowCovering = 258 { readonly attribute ConfigStatus configStatus = 7; readonly attribute nullable Percent currentPositionLiftPercentage = 8; readonly attribute nullable Percent currentPositionTiltPercentage = 9; - readonly attribute bitmap8 operationalStatus = 10; + readonly attribute OperationalStatus operationalStatus = 10; readonly attribute nullable Percent100ths targetPositionLiftPercent100ths = 11; readonly attribute nullable Percent100ths targetPositionTiltPercent100ths = 12; readonly attribute EndProductType endProductType = 13; @@ -1525,7 +1526,7 @@ server cluster WindowCovering = 258 { readonly attribute int16u installedOpenLimitTilt = 18; readonly attribute int16u installedClosedLimitTilt = 19; attribute access(write: manage) Mode mode = 23; - readonly attribute bitmap16 safetyStatus = 26; + readonly attribute SafetyStatus safetyStatus = 26; readonly attribute bitmap32 featureMap = 65532; readonly attribute int16u clusterRevision = 65533; diff --git a/examples/window-app/efr32/args.gni b/examples/window-app/efr32/args.gni index 96b6262f50b93e..0b7ef403df72cd 100644 --- a/examples/window-app/efr32/args.gni +++ b/examples/window-app/efr32/args.gni @@ -21,5 +21,5 @@ efr32_sdk_target = get_label_info(":sdk", "label_no_toolchain") chip_enable_ota_requestor = true pw_log_BACKEND = "${chip_root}/src/lib/support/pw_log_chip" -pw_assert_BACKEND = "$dir_pw_assert_log" +pw_assert_BACKEND = "$dir_pw_assert_log:check_backend" chip_enable_openthread = true diff --git a/examples/window-app/efr32/build_for_wifi_args.gni b/examples/window-app/efr32/build_for_wifi_args.gni index bf21912871e59d..4a3bdfd804ae19 100644 --- a/examples/window-app/efr32/build_for_wifi_args.gni +++ b/examples/window-app/efr32/build_for_wifi_args.gni @@ -21,4 +21,4 @@ import("${chip_root}/src/platform/EFR32/wifi_args.gni") chip_enable_ota_requestor = true pw_log_BACKEND = "${chip_root}/src/lib/support/pw_log_chip" -pw_assert_BACKEND = "$dir_pw_assert_log" +pw_assert_BACKEND = "$dir_pw_assert_log:check_backend" diff --git a/examples/window-app/nrfconnect/README.md b/examples/window-app/nrfconnect/README.md index 4f6ce47c8f74cb..8fbabd6f23f2b5 100644 --- a/examples/window-app/nrfconnect/README.md +++ b/examples/window-app/nrfconnect/README.md @@ -62,7 +62,8 @@ configuration from it. Some actions required before establishing full communication are described below. The example can be configured to use the secure bootloader and utilize it for -performing over-the-air Device Firmware Upgrade using Bluetooth LE. +performing over-the-air Device Firmware Upgrade using Bluetooth LE. The device +works as a Thread Synchronized Sleepy End Device. ### Bluetooth LE advertising @@ -388,22 +389,6 @@ features like logs and command-line interface, run the following command: Remember to replace _build-target_ with the build target name of the Nordic Semiconductor's kit you own. -### Building with low-power configuration - -You can build the example using the low-power configuration, which enables -Thread's Synchronized Sleepy End Device mode and disables debug features, such -as the UART console or the **LED 1** usage. - -To build for the low-power configuration, run the following command with -_build-target_ replaced with the build target name of the Nordic Semiconductor's -kit you own (for example `nrf52840dk_nrf52840`): - - $ west build -b build-target -- -DOVERLAY_CONFIG=overlay-low_power.conf - -For example, use the following command for `nrf52840dk_nrf52840`: - - $ west build -b nrf52840dk_nrf52840 -- -DOVERLAY_CONFIG=overlay-low_power.conf - ### Building with Device Firmware Upgrade support Support for DFU using Matter OTA is enabled by default. diff --git a/examples/window-app/nrfconnect/main/AppTask.cpp b/examples/window-app/nrfconnect/main/AppTask.cpp index 01055a4935f54d..f62b096c61d878 100644 --- a/examples/window-app/nrfconnect/main/AppTask.cpp +++ b/examples/window-app/nrfconnect/main/AppTask.cpp @@ -107,10 +107,10 @@ CHIP_ERROR AppTask::Init() return err; } -#ifdef CONFIG_OPENTHREAD_MTD_SED - err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_SleepyEndDevice); -#elif CONFIG_CHIP_THREAD_SSED +#if CONFIG_CHIP_THREAD_SSED err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_SynchronizedSleepyEndDevice); +#elif CONFIG_OPENTHREAD_MTD_SED + err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_SleepyEndDevice); #else err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_MinimalEndDevice); #endif diff --git a/examples/window-app/nrfconnect/main/WindowCovering.cpp b/examples/window-app/nrfconnect/main/WindowCovering.cpp index cd4dc07fc127eb..f1fd5a7059cadb 100644 --- a/examples/window-app/nrfconnect/main/WindowCovering.cpp +++ b/examples/window-app/nrfconnect/main/WindowCovering.cpp @@ -91,17 +91,15 @@ chip::Percent100ths WindowCovering::CalculateSingleStep(MoveType aMoveType) NPercent100ths current{}; OperationalState opState{}; - OperationalStatus opStatus = OperationalStatusGet(Endpoint()); - if (aMoveType == MoveType::LIFT) { status = Attributes::CurrentPositionLiftPercent100ths::Get(Endpoint(), current); - opState = opStatus.lift; + opState = OperationalStateGet(Endpoint(), OperationalStatus::kLift); } else if (aMoveType == MoveType::TILT) { status = Attributes::CurrentPositionTiltPercent100ths::Get(Endpoint(), current); - opState = opStatus.tilt; + opState = OperationalStateGet(Endpoint(), OperationalStatus::kTilt); } if ((status == EMBER_ZCL_STATUS_SUCCESS) && !current.IsNull()) @@ -119,26 +117,7 @@ chip::Percent100ths WindowCovering::CalculateSingleStep(MoveType aMoveType) bool WindowCovering::TargetCompleted(MoveType aMoveType, NPercent100ths aCurrent, NPercent100ths aTarget) { - OperationalStatus currentOpStatus = OperationalStatusGet(Endpoint()); - OperationalState currentOpState = (aMoveType == MoveType::LIFT) ? currentOpStatus.lift : currentOpStatus.tilt; - - if (!aCurrent.IsNull() && !aTarget.IsNull()) - { - switch (currentOpState) - { - case OperationalState::MovingDownOrClose: - return (aCurrent.Value() >= aTarget.Value()); - case OperationalState::MovingUpOrOpen: - return (aCurrent.Value() <= aTarget.Value()); - default: - return true; - } - } - else - { - LOG_ERR("Invalid target/current positions"); - } - return false; + return (OperationalState::Stall == ComputeOperationalState(aTarget, aCurrent)); } void WindowCovering::StartTimer(MoveType aMoveType, uint32_t aTimeoutMs) @@ -230,23 +209,19 @@ void WindowCovering::SetSingleStepTarget(OperationalState aDirection) void WindowCovering::UpdateOperationalStatus(MoveType aMoveType, OperationalState aDirection) { - OperationalStatus currentOpStatus = OperationalStatusGet(Endpoint()); - switch (aMoveType) { case MoveType::LIFT: - currentOpStatus.lift = aDirection; + OperationalStateSet(Endpoint(), OperationalStatus::kLift, aDirection); break; case MoveType::TILT: - currentOpStatus.tilt = aDirection; + OperationalStateSet(Endpoint(), OperationalStatus::kTilt, aDirection); break; case MoveType::NONE: break; default: break; } - - OperationalStatusSetWithGlobalUpdated(Endpoint(), currentOpStatus); } void WindowCovering::SetTargetPosition(OperationalState aDirection, chip::Percent100ths aPosition) diff --git a/examples/window-app/nrfconnect/main/include/CHIPProjectConfig.h b/examples/window-app/nrfconnect/main/include/CHIPProjectConfig.h index de64851584ba9d..9fea28ec9fde12 100644 --- a/examples/window-app/nrfconnect/main/include/CHIPProjectConfig.h +++ b/examples/window-app/nrfconnect/main/include/CHIPProjectConfig.h @@ -29,10 +29,3 @@ // Use a default pairing code if one hasn't been provisioned in flash. #define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021 #define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 - -#ifdef CONFIG_CHIP_THREAD_SSED -#define CHIP_DEVICE_CONFIG_SED_ACTIVE_INTERVAL 500_ms32 -#define CHIP_DEVICE_CONFIG_SED_IDLE_INTERVAL 500_ms32 -#else -#define CHIP_DEVICE_CONFIG_SED_IDLE_INTERVAL 2000_ms32 -#endif diff --git a/examples/window-app/nrfconnect/overlay-low_power.conf b/examples/window-app/nrfconnect/overlay-low_power.conf deleted file mode 100644 index 602eb4f76784e2..00000000000000 --- a/examples/window-app/nrfconnect/overlay-low_power.conf +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# Enable MTD Sleepy End Device -CONFIG_CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT=y - -# Enable Thread CSL to support Synchronized SED -CONFIG_CHIP_THREAD_SSED=y - -# Disable UART console -CONFIG_SHELL=n -CONFIG_LOG=n -CONFIG_UART_CONSOLE=n -CONFIG_SERIAL=n - -# Suspend devices when the CPU goes to sleep -CONFIG_PM_DEVICE=y - -# Disable auxiliary state LEDs -CONFIG_STATE_LEDS=n diff --git a/examples/window-app/nrfconnect/prj.conf b/examples/window-app/nrfconnect/prj.conf index 1ffcaee2b430a4..9595ec207e8582 100644 --- a/examples/window-app/nrfconnect/prj.conf +++ b/examples/window-app/nrfconnect/prj.conf @@ -30,6 +30,10 @@ CONFIG_OPENTHREAD_THREAD_VERSION_1_2=y CONFIG_OPENTHREAD_NORDIC_LIBRARY_MTD=y CONFIG_OPENTHREAD_MTD=y CONFIG_OPENTHREAD_FTD=n +CONFIG_CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT=y +CONFIG_CHIP_THREAD_SSED=y +CONFIG_CHIP_SED_IDLE_INTERVAL=500 +CONFIG_CHIP_SED_ACTIVE_INTERVAL=500 # Default OpenThread network settings CONFIG_OPENTHREAD_PANID=4660 diff --git a/examples/window-app/nrfconnect/prj_no_dfu.conf b/examples/window-app/nrfconnect/prj_no_dfu.conf index 1bb9717bae150f..680894d3cbb4e5 100644 --- a/examples/window-app/nrfconnect/prj_no_dfu.conf +++ b/examples/window-app/nrfconnect/prj_no_dfu.conf @@ -29,6 +29,10 @@ CONFIG_OPENTHREAD_THREAD_VERSION_1_2=y CONFIG_OPENTHREAD_NORDIC_LIBRARY_MTD=y CONFIG_OPENTHREAD_MTD=y CONFIG_OPENTHREAD_FTD=n +CONFIG_CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT=y +CONFIG_CHIP_THREAD_SSED=y +CONFIG_CHIP_SED_IDLE_INTERVAL=500 +CONFIG_CHIP_SED_ACTIVE_INTERVAL=500 # Default OpenThread network settings CONFIG_OPENTHREAD_PANID=4660 diff --git a/examples/window-app/nrfconnect/prj_release.conf b/examples/window-app/nrfconnect/prj_release.conf index dcc71d6d218c46..2278618efca3fa 100644 --- a/examples/window-app/nrfconnect/prj_release.conf +++ b/examples/window-app/nrfconnect/prj_release.conf @@ -29,6 +29,10 @@ CONFIG_OPENTHREAD_THREAD_VERSION_1_2=y CONFIG_OPENTHREAD_NORDIC_LIBRARY_MTD=y CONFIG_OPENTHREAD_MTD=y CONFIG_OPENTHREAD_FTD=n +CONFIG_CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT=y +CONFIG_CHIP_THREAD_SSED=y +CONFIG_CHIP_SED_IDLE_INTERVAL=500 +CONFIG_CHIP_SED_ACTIVE_INTERVAL=500 # Default OpenThread network settings CONFIG_OPENTHREAD_PANID=4660 @@ -47,6 +51,9 @@ CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" # 32784 == 0x8010 (example window-app) CONFIG_CHIP_DEVICE_PRODUCT_ID=32784 +# Suspend devices when the CPU goes into sleep +CONFIG_PM_DEVICE=y + # Disable all debug features CONFIG_SHELL=n CONFIG_OPENTHREAD_SHELL=n diff --git a/integrations/cloudbuild/build-all.yaml b/integrations/cloudbuild/build-all.yaml index 01abb43a458c9b..78e54030c635c2 100644 --- a/integrations/cloudbuild/build-all.yaml +++ b/integrations/cloudbuild/build-all.yaml @@ -1,5 +1,5 @@ steps: - - name: "connectedhomeip/chip-build-vscode:0.5.77" + - name: "connectedhomeip/chip-build-vscode:0.5.79" env: - PW_ENVIRONMENT_ROOT=/pwenv args: @@ -12,13 +12,13 @@ steps: path: /pwenv timeout: 900s - - name: "connectedhomeip/chip-build-vscode:0.5.77" + - name: "connectedhomeip/chip-build-vscode:0.5.79" env: - PW_ENVIRONMENT_ROOT=/pwenv args: - >- ./scripts/build/build_examples.py --enable-flashbundle - --target-glob '*' --skip-target-glob '*-tests' build + --target-glob '*' --skip-target-glob '{tizen-*,*-tests}' build --create-archives /workspace/artifacts/ id: CompileAll waitFor: diff --git a/integrations/cloudbuild/chef.yaml b/integrations/cloudbuild/chef.yaml index f70c63976217dd..26f3123cc8588b 100644 --- a/integrations/cloudbuild/chef.yaml +++ b/integrations/cloudbuild/chef.yaml @@ -1,5 +1,5 @@ steps: - - name: "connectedhomeip/chip-build-vscode:0.5.75" + - name: "connectedhomeip/chip-build-vscode:0.5.79" env: - PW_ENVIRONMENT_ROOT=/pwenv args: @@ -12,7 +12,7 @@ steps: path: /pwenv timeout: 900s - - name: "connectedhomeip/chip-build-vscode:0.5.75" + - name: "connectedhomeip/chip-build-vscode:0.5.79" env: - PW_ENVIRONMENT_ROOT=/pwenv args: diff --git a/integrations/cloudbuild/smoke-test.yaml b/integrations/cloudbuild/smoke-test.yaml index 12325b791124cf..2101356729c7c5 100644 --- a/integrations/cloudbuild/smoke-test.yaml +++ b/integrations/cloudbuild/smoke-test.yaml @@ -1,5 +1,5 @@ steps: - - name: "connectedhomeip/chip-build-vscode:0.5.77" + - name: "connectedhomeip/chip-build-vscode:0.5.79" env: - PW_ENVIRONMENT_ROOT=/pwenv args: @@ -12,7 +12,7 @@ steps: path: /pwenv timeout: 900s - - name: "connectedhomeip/chip-build-vscode:0.5.77" + - name: "connectedhomeip/chip-build-vscode:0.5.79" id: ESP32 env: - PW_ENVIRONMENT_ROOT=/pwenv @@ -28,7 +28,7 @@ steps: - name: pwenv path: /pwenv - - name: "connectedhomeip/chip-build-vscode:0.5.77" + - name: "connectedhomeip/chip-build-vscode:0.5.79" id: NRFConnect env: - PW_ENVIRONMENT_ROOT=/pwenv @@ -45,7 +45,7 @@ steps: - name: pwenv path: /pwenv - - name: "connectedhomeip/chip-build-vscode:0.5.77" + - name: "connectedhomeip/chip-build-vscode:0.5.79" id: EFR32 env: - PW_ENVIRONMENT_ROOT=/pwenv @@ -62,7 +62,7 @@ steps: - name: pwenv path: /pwenv - - name: "connectedhomeip/chip-build-vscode:0.5.77" + - name: "connectedhomeip/chip-build-vscode:0.5.79" id: Linux env: - PW_ENVIRONMENT_ROOT=/pwenv @@ -79,7 +79,7 @@ steps: - name: pwenv path: /pwenv - - name: "connectedhomeip/chip-build-vscode:0.5.77" + - name: "connectedhomeip/chip-build-vscode:0.5.79" id: Android env: - PW_ENVIRONMENT_ROOT=/pwenv diff --git a/integrations/docker/images/chip-build-ameba/Dockerfile b/integrations/docker/images/chip-build-ameba/Dockerfile index 0539b55a1007d7..edf73bd120c59d 100644 --- a/integrations/docker/images/chip-build-ameba/Dockerfile +++ b/integrations/docker/images/chip-build-ameba/Dockerfile @@ -3,7 +3,7 @@ FROM connectedhomeip/chip-build:${VERSION} # Setup Ameba ARG AMEBA_DIR=/opt/ameba -ARG TAG_NAME=ameba_update_2022_05_20 +ARG TAG_NAME=ameba_update_2022_06_06 RUN set -x \ && apt-get update \ && mkdir ${AMEBA_DIR} \ diff --git a/integrations/docker/images/chip-build-tizen/Dockerfile b/integrations/docker/images/chip-build-tizen/Dockerfile index cd3915b3b0e5d3..3ae8192ec138c9 100644 --- a/integrations/docker/images/chip-build-tizen/Dockerfile +++ b/integrations/docker/images/chip-build-tizen/Dockerfile @@ -44,6 +44,7 @@ RUN set -x \ http://download.tizen.org/sdk/tizenstudio/official/binary/certificate-generator_0.1.3_ubuntu-64.zip \ http://download.tizen.org/sdk/tizenstudio/official/binary/new-common-cli_2.5.7_ubuntu-64.zip \ http://download.tizen.org/sdk/tizenstudio/official/binary/new-native-cli_2.5.7_ubuntu-64.zip \ + http://download.tizen.org/sdk/tizenstudio/official/binary/sdb_4.2.23_ubuntu-64.zip \ # Install tizen studio CLI && unzip -o '*.zip' \ && cp -rf data/* $TIZEN_SDK_ROOT \ @@ -56,7 +57,7 @@ RUN set -x \ COPY secret-tool.py $TIZEN_SDK_ROOT/tools/certificate-encryptor/secret-tool RUN chmod 0755 $TIZEN_SDK_ROOT/tools/certificate-encryptor/secret-tool -ENV PATH="$TIZEN_SDK_ROOT/tools/ide/bin:$PATH" +ENV PATH="$TIZEN_SDK_ROOT/tools/ide/bin:$TIZEN_SDK_ROOT/tools:$PATH" # ------------------------------------------------------------------------------ # Get toolchain @@ -94,8 +95,11 @@ RUN set -x \ -A 'libffi-devel-*.armv7l.rpm' \ -A 'liblzma-*.armv7l.rpm' \ -A 'libmount-devel-*.armv7l.rpm' \ + -A 'libncurses6-*.armv7l.rpm' \ + -A 'libreadline-*.armv7l.rpm' \ -A 'libuuid-*.armv7l.rpm' \ -A 'pcre-devel-*.armv7l.rpm' \ + -A 'readline-devel-*.armv7l.rpm' \ -A 'xdgmime-*.armv7l.rpm' \ # Unified packages && wget --progress=dot:mega -r -nd --no-parent \ @@ -115,6 +119,7 @@ RUN set -x \ -A 'libcynara-commons-*.armv7l.rpm' \ -A 'libdns_sd-*.armv7l.rpm' \ -A 'libjson-glib-*.armv7l.rpm' \ + -A 'libsessiond-0*.armv7l.rpm' \ -A 'libsystemd-*.armv7l.rpm' \ -A 'libtzplatform-config-*.armv7l.rpm' \ -A 'parcel-0*.armv7l.rpm' \ @@ -134,10 +139,10 @@ RUN set -x \ # Install packages && unrpm *.rpm \ && cp -rf lib usr $TIZEN_SDK_SYSROOT \ - # Fix some symbolic links - && ln -sf libcap.so.2 $TIZEN_SDK_SYSROOT/usr/lib/libcap.so \ - && ln -sf libdns_sd.so.878.70.2 $TIZEN_SDK_SYSROOT/usr/lib/libdns_sd.so \ - && ln -sf libdns_sd.so.878.70.2 $TIZEN_SDK_SYSROOT/usr/lib/libdns_sd.so.878 \ + # Make symbolic links relative + && for LNK in $(find $TIZEN_SDK_SYSROOT/usr/lib -maxdepth 1 -type l); \ + do ln -sf $(basename $(readlink "$LNK")) "$LNK" ; done \ + && ln -sf ../../lib/libcap.so.2 $TIZEN_SDK_SYSROOT/usr/lib/libcap.so \ && ln -sf openssl1.1.pc $TIZEN_SDK_SYSROOT/usr/lib/pkgconfig/openssl.pc \ # Cleanup && rm -rf /tmp/workdir \ diff --git a/integrations/docker/images/chip-build/version b/integrations/docker/images/chip-build/version index 0e06a183605c22..37c987396c50b9 100644 --- a/integrations/docker/images/chip-build/version +++ b/integrations/docker/images/chip-build/version @@ -1 +1 @@ -0.5.78 Version bump reason: [Tizen] Fix environment variable order, add missing tizen dependencies +0.5.80 Version bump reason: [Tizen] Add vscode debug support diff --git a/scripts/build/builders/imx.py b/scripts/build/builders/imx.py index 9118066f5d0d05..e748144edc21a1 100644 --- a/scripts/build/builders/imx.py +++ b/scripts/build/builders/imx.py @@ -13,6 +13,8 @@ # limitations under the License. import os +import re +import shlex from enum import Enum, auto from .gn import GnBuilder @@ -74,30 +76,101 @@ def __init__(self, self.release = release self.app = app - def GnBuildEnv(self): - return { - 'PKG_CONFIG_PATH': self.SysRootPath('IMX_SDK_ROOT') + '/sysroots/cortexa53-crypto-poky-linux/lib/aarch64-linux-gnu/pkgconfig', - } - def GnBuildArgs(self): + try: + entries = os.listdir(self.SysRootPath('IMX_SDK_ROOT')) + except FileNotFoundError: + if self.SysRootPath('IMX_SDK_ROOT') == 'IMX_SDK_ROOT': + # CI test, use default value + target_cpu = 'arm64' + arm_arch = 'armv8-a' + sdk_target_sysroot = os.path.join(self.SysRootPath('IMX_SDK_ROOT'), 'sysroots/cortexa53-crypto-poky-linux') + cross_compile = 'aarch64-poky-linux' + cc = 'aarch64-poky-linux-gcc' + cxx = 'aarch64-poky-linux-g++' + else: + raise Exception('the value of env IMX_SDK_ROOT is not a valid path.') + else: + for entry in entries: + if entry.startswith(r'environment-setup-'): + env_setup_script = entry + break + + try: + env_setup_script + except NameError: + raise Exception('The SDK environment setup script is not found, make sure the env IMX_SDK_ROOT is correctly set.') + else: + + with open(os.path.join(self.SysRootPath('IMX_SDK_ROOT'), env_setup_script), 'r') as env_setup_script_fd: + lines = env_setup_script_fd.readlines() + for line in lines: + line = line.strip('\n') + m = re.match(r'^\s*export\s+SDKTARGETSYSROOT=(.*)', line) + if m: + sdk_target_sysroot = shlex.split(m.group(1))[0] + + m = re.match(r'^\s*export\s+CC=(.*)', line) + if m: + cc = shlex.split(m.group(1))[0] + m = re.match(r'^\s*export\s+CXX=(.*)', line) + if m: + cxx = shlex.split(m.group(1))[0] + + m = re.match(r'^\s*export\s+ARCH=(.*)', line) + if m: + target_cpu = shlex.split(m.group(1))[0] + if target_cpu == 'arm64': + arm_arch = 'armv8-a' + elif target_cpu == 'arm': + arm_arch = 'armv7ve' + else: + raise Exception('ARCH should be arm64 or arm in the SDK environment setup script.') + + m = re.match(r'^\s*export\s+CROSS_COMPILE=(.*)', line) + if m: + cross_compile = shlex.split(m.group(1))[0][:-1] + + try: + sdk_target_sysroot + except NameError: + raise Exception('SDKTARGETSYSROOT is not found in the SDK environment setup script.') + else: + try: + cc + cxx + except NameError: + raise Exception('CC and/or CXX are not found in the SDK environment setup script.') + else: + cc = cc.replace('$SDKTARGETSYSROOT', sdk_target_sysroot) + cxx = cxx.replace('$SDKTARGETSYSROOT', sdk_target_sysroot) + try: + target_cpu + cross_compile + except NameError: + raise Exception('ARCH and/or CROSS_COMPILE are not found in the SDK environment setup script.') + args = [ + 'treat_warnings_as_errors=false', 'target_os="linux"', - 'target_cpu="arm64"', - 'arm_arch="armv8-a"', + 'target_cpu="%s"' % target_cpu, + 'arm_arch="%s"' % arm_arch, 'import(\"//build_overrides/build.gni\")', 'custom_toolchain=\"${build_root}/toolchain/custom\"', - 'sysroot="%s/sysroots/cortexa53-crypto-poky-linux"' % self.SysRootPath('IMX_SDK_ROOT'), + 'sysroot="%s"' % sdk_target_sysroot, 'target_cflags=[ "-DCHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME=\\"mlan0\\"", "-DCHIP_DEVICE_CONFIG_LINUX_DHCPC_CMD=\\"udhcpc -b -i %s \\"" ]', - 'target_cc="%s/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc"' % self.SysRootPath( - 'IMX_SDK_ROOT'), - 'target_cxx="%s/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++"' % self.SysRootPath( - 'IMX_SDK_ROOT'), - 'target_ar="%s/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-ar"' % self.SysRootPath( - 'IMX_SDK_ROOT'), + 'target_cc="%s/sysroots/x86_64-pokysdk-linux/usr/bin/%s/%s"' % (self.SysRootPath('IMX_SDK_ROOT'), cross_compile, + cc), + 'target_cxx="%s/sysroots/x86_64-pokysdk-linux/usr/bin/%s/%s"' % (self.SysRootPath('IMX_SDK_ROOT'), cross_compile, + cxx), + 'target_ar="%s/sysroots/x86_64-pokysdk-linux/usr/bin/%s/%s-ar"' % (self.SysRootPath('IMX_SDK_ROOT'), cross_compile, + cross_compile), ] if self.release: args.append('is_debug=false') + else: + args.append('optimize_debug=true') return args diff --git a/scripts/build/testdata/build_all_except_host.txt b/scripts/build/testdata/build_all_except_host.txt index 12ee5aa27f27f5..e4c888fed81d1c 100644 --- a/scripts/build/testdata/build_all_except_host.txt +++ b/scripts/build/testdata/build_all_except_host.txt @@ -786,64 +786,40 @@ export SDKCONFIG_DEFAULTS={out}/esp32-qemu-tests/sdkconfig.defaults idf.py -C src/test_driver/esp32 -B {out}/esp32-qemu-tests reconfigure' # Generating imx-all-clusters-app -bash -c ' -PKG_CONFIG_PATH="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux/lib/aarch64-linux-gnu/pkgconfig" \ - gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/all-clusters-app/linux '"'"'--args=target_os="linux" target_cpu="arm64" arm_arch="armv8-a" import("//build_overrides/build.gni") custom_toolchain="${build_root}/toolchain/custom" sysroot="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux" target_cflags=[ "-DCHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME=\"mlan0\"", "-DCHIP_DEVICE_CONFIG_LINUX_DHCPC_CMD=\"udhcpc -b -i %s \"" ] target_cc="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc" target_cxx="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++" target_ar="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-ar"'"'"' {out}/imx-all-clusters-app' +gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/all-clusters-app/linux '--args=treat_warnings_as_errors=false target_os="linux" target_cpu="arm64" arm_arch="armv8-a" import("//build_overrides/build.gni") custom_toolchain="${build_root}/toolchain/custom" sysroot="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux" target_cflags=[ "-DCHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME=\"mlan0\"", "-DCHIP_DEVICE_CONFIG_LINUX_DHCPC_CMD=\"udhcpc -b -i %s \"" ] target_cc="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc" target_cxx="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++" target_ar="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-ar" optimize_debug=true' {out}/imx-all-clusters-app # Generating imx-all-clusters-app-release -bash -c ' -PKG_CONFIG_PATH="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux/lib/aarch64-linux-gnu/pkgconfig" \ - gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/all-clusters-app/linux '"'"'--args=target_os="linux" target_cpu="arm64" arm_arch="armv8-a" import("//build_overrides/build.gni") custom_toolchain="${build_root}/toolchain/custom" sysroot="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux" target_cflags=[ "-DCHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME=\"mlan0\"", "-DCHIP_DEVICE_CONFIG_LINUX_DHCPC_CMD=\"udhcpc -b -i %s \"" ] target_cc="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc" target_cxx="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++" target_ar="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-ar" is_debug=false'"'"' {out}/imx-all-clusters-app-release' +gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/all-clusters-app/linux '--args=treat_warnings_as_errors=false target_os="linux" target_cpu="arm64" arm_arch="armv8-a" import("//build_overrides/build.gni") custom_toolchain="${build_root}/toolchain/custom" sysroot="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux" target_cflags=[ "-DCHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME=\"mlan0\"", "-DCHIP_DEVICE_CONFIG_LINUX_DHCPC_CMD=\"udhcpc -b -i %s \"" ] target_cc="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc" target_cxx="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++" target_ar="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-ar" is_debug=false' {out}/imx-all-clusters-app-release # Generating imx-all-clusters-minimal-app -bash -c ' -PKG_CONFIG_PATH="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux/lib/aarch64-linux-gnu/pkgconfig" \ - gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/all-clusters-minimal-app/linux '"'"'--args=target_os="linux" target_cpu="arm64" arm_arch="armv8-a" import("//build_overrides/build.gni") custom_toolchain="${build_root}/toolchain/custom" sysroot="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux" target_cflags=[ "-DCHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME=\"mlan0\"", "-DCHIP_DEVICE_CONFIG_LINUX_DHCPC_CMD=\"udhcpc -b -i %s \"" ] target_cc="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc" target_cxx="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++" target_ar="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-ar"'"'"' {out}/imx-all-clusters-minimal-app' +gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/all-clusters-minimal-app/linux '--args=treat_warnings_as_errors=false target_os="linux" target_cpu="arm64" arm_arch="armv8-a" import("//build_overrides/build.gni") custom_toolchain="${build_root}/toolchain/custom" sysroot="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux" target_cflags=[ "-DCHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME=\"mlan0\"", "-DCHIP_DEVICE_CONFIG_LINUX_DHCPC_CMD=\"udhcpc -b -i %s \"" ] target_cc="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc" target_cxx="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++" target_ar="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-ar" optimize_debug=true' {out}/imx-all-clusters-minimal-app # Generating imx-all-clusters-minimal-app-release -bash -c ' -PKG_CONFIG_PATH="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux/lib/aarch64-linux-gnu/pkgconfig" \ - gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/all-clusters-minimal-app/linux '"'"'--args=target_os="linux" target_cpu="arm64" arm_arch="armv8-a" import("//build_overrides/build.gni") custom_toolchain="${build_root}/toolchain/custom" sysroot="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux" target_cflags=[ "-DCHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME=\"mlan0\"", "-DCHIP_DEVICE_CONFIG_LINUX_DHCPC_CMD=\"udhcpc -b -i %s \"" ] target_cc="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc" target_cxx="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++" target_ar="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-ar" is_debug=false'"'"' {out}/imx-all-clusters-minimal-app-release' +gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/all-clusters-minimal-app/linux '--args=treat_warnings_as_errors=false target_os="linux" target_cpu="arm64" arm_arch="armv8-a" import("//build_overrides/build.gni") custom_toolchain="${build_root}/toolchain/custom" sysroot="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux" target_cflags=[ "-DCHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME=\"mlan0\"", "-DCHIP_DEVICE_CONFIG_LINUX_DHCPC_CMD=\"udhcpc -b -i %s \"" ] target_cc="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc" target_cxx="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++" target_ar="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-ar" is_debug=false' {out}/imx-all-clusters-minimal-app-release # Generating imx-chip-tool -bash -c ' -PKG_CONFIG_PATH="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux/lib/aarch64-linux-gnu/pkgconfig" \ - gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/chip-tool '"'"'--args=target_os="linux" target_cpu="arm64" arm_arch="armv8-a" import("//build_overrides/build.gni") custom_toolchain="${build_root}/toolchain/custom" sysroot="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux" target_cflags=[ "-DCHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME=\"mlan0\"", "-DCHIP_DEVICE_CONFIG_LINUX_DHCPC_CMD=\"udhcpc -b -i %s \"" ] target_cc="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc" target_cxx="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++" target_ar="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-ar"'"'"' {out}/imx-chip-tool' +gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/chip-tool '--args=treat_warnings_as_errors=false target_os="linux" target_cpu="arm64" arm_arch="armv8-a" import("//build_overrides/build.gni") custom_toolchain="${build_root}/toolchain/custom" sysroot="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux" target_cflags=[ "-DCHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME=\"mlan0\"", "-DCHIP_DEVICE_CONFIG_LINUX_DHCPC_CMD=\"udhcpc -b -i %s \"" ] target_cc="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc" target_cxx="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++" target_ar="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-ar" optimize_debug=true' {out}/imx-chip-tool # Generating imx-chip-tool-release -bash -c ' -PKG_CONFIG_PATH="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux/lib/aarch64-linux-gnu/pkgconfig" \ - gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/chip-tool '"'"'--args=target_os="linux" target_cpu="arm64" arm_arch="armv8-a" import("//build_overrides/build.gni") custom_toolchain="${build_root}/toolchain/custom" sysroot="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux" target_cflags=[ "-DCHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME=\"mlan0\"", "-DCHIP_DEVICE_CONFIG_LINUX_DHCPC_CMD=\"udhcpc -b -i %s \"" ] target_cc="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc" target_cxx="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++" target_ar="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-ar" is_debug=false'"'"' {out}/imx-chip-tool-release' +gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/chip-tool '--args=treat_warnings_as_errors=false target_os="linux" target_cpu="arm64" arm_arch="armv8-a" import("//build_overrides/build.gni") custom_toolchain="${build_root}/toolchain/custom" sysroot="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux" target_cflags=[ "-DCHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME=\"mlan0\"", "-DCHIP_DEVICE_CONFIG_LINUX_DHCPC_CMD=\"udhcpc -b -i %s \"" ] target_cc="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc" target_cxx="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++" target_ar="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-ar" is_debug=false' {out}/imx-chip-tool-release # Generating imx-lighting-app -bash -c ' -PKG_CONFIG_PATH="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux/lib/aarch64-linux-gnu/pkgconfig" \ - gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/lighting-app/linux '"'"'--args=target_os="linux" target_cpu="arm64" arm_arch="armv8-a" import("//build_overrides/build.gni") custom_toolchain="${build_root}/toolchain/custom" sysroot="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux" target_cflags=[ "-DCHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME=\"mlan0\"", "-DCHIP_DEVICE_CONFIG_LINUX_DHCPC_CMD=\"udhcpc -b -i %s \"" ] target_cc="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc" target_cxx="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++" target_ar="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-ar"'"'"' {out}/imx-lighting-app' +gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/lighting-app/linux '--args=treat_warnings_as_errors=false target_os="linux" target_cpu="arm64" arm_arch="armv8-a" import("//build_overrides/build.gni") custom_toolchain="${build_root}/toolchain/custom" sysroot="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux" target_cflags=[ "-DCHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME=\"mlan0\"", "-DCHIP_DEVICE_CONFIG_LINUX_DHCPC_CMD=\"udhcpc -b -i %s \"" ] target_cc="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc" target_cxx="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++" target_ar="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-ar" optimize_debug=true' {out}/imx-lighting-app # Generating imx-lighting-app-release -bash -c ' -PKG_CONFIG_PATH="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux/lib/aarch64-linux-gnu/pkgconfig" \ - gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/lighting-app/linux '"'"'--args=target_os="linux" target_cpu="arm64" arm_arch="armv8-a" import("//build_overrides/build.gni") custom_toolchain="${build_root}/toolchain/custom" sysroot="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux" target_cflags=[ "-DCHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME=\"mlan0\"", "-DCHIP_DEVICE_CONFIG_LINUX_DHCPC_CMD=\"udhcpc -b -i %s \"" ] target_cc="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc" target_cxx="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++" target_ar="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-ar" is_debug=false'"'"' {out}/imx-lighting-app-release' +gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/lighting-app/linux '--args=treat_warnings_as_errors=false target_os="linux" target_cpu="arm64" arm_arch="armv8-a" import("//build_overrides/build.gni") custom_toolchain="${build_root}/toolchain/custom" sysroot="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux" target_cflags=[ "-DCHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME=\"mlan0\"", "-DCHIP_DEVICE_CONFIG_LINUX_DHCPC_CMD=\"udhcpc -b -i %s \"" ] target_cc="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc" target_cxx="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++" target_ar="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-ar" is_debug=false' {out}/imx-lighting-app-release # Generating imx-ota-provider-app -bash -c ' -PKG_CONFIG_PATH="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux/lib/aarch64-linux-gnu/pkgconfig" \ - gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/ota-provider-app/linux '"'"'--args=target_os="linux" target_cpu="arm64" arm_arch="armv8-a" import("//build_overrides/build.gni") custom_toolchain="${build_root}/toolchain/custom" sysroot="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux" target_cflags=[ "-DCHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME=\"mlan0\"", "-DCHIP_DEVICE_CONFIG_LINUX_DHCPC_CMD=\"udhcpc -b -i %s \"" ] target_cc="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc" target_cxx="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++" target_ar="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-ar"'"'"' {out}/imx-ota-provider-app' +gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/ota-provider-app/linux '--args=treat_warnings_as_errors=false target_os="linux" target_cpu="arm64" arm_arch="armv8-a" import("//build_overrides/build.gni") custom_toolchain="${build_root}/toolchain/custom" sysroot="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux" target_cflags=[ "-DCHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME=\"mlan0\"", "-DCHIP_DEVICE_CONFIG_LINUX_DHCPC_CMD=\"udhcpc -b -i %s \"" ] target_cc="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc" target_cxx="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++" target_ar="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-ar" optimize_debug=true' {out}/imx-ota-provider-app # Generating imx-ota-provider-app-release -bash -c ' -PKG_CONFIG_PATH="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux/lib/aarch64-linux-gnu/pkgconfig" \ - gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/ota-provider-app/linux '"'"'--args=target_os="linux" target_cpu="arm64" arm_arch="armv8-a" import("//build_overrides/build.gni") custom_toolchain="${build_root}/toolchain/custom" sysroot="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux" target_cflags=[ "-DCHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME=\"mlan0\"", "-DCHIP_DEVICE_CONFIG_LINUX_DHCPC_CMD=\"udhcpc -b -i %s \"" ] target_cc="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc" target_cxx="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++" target_ar="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-ar" is_debug=false'"'"' {out}/imx-ota-provider-app-release' +gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/ota-provider-app/linux '--args=treat_warnings_as_errors=false target_os="linux" target_cpu="arm64" arm_arch="armv8-a" import("//build_overrides/build.gni") custom_toolchain="${build_root}/toolchain/custom" sysroot="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux" target_cflags=[ "-DCHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME=\"mlan0\"", "-DCHIP_DEVICE_CONFIG_LINUX_DHCPC_CMD=\"udhcpc -b -i %s \"" ] target_cc="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc" target_cxx="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++" target_ar="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-ar" is_debug=false' {out}/imx-ota-provider-app-release # Generating imx-thermostat -bash -c ' -PKG_CONFIG_PATH="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux/lib/aarch64-linux-gnu/pkgconfig" \ - gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/thermostat/linux '"'"'--args=target_os="linux" target_cpu="arm64" arm_arch="armv8-a" import("//build_overrides/build.gni") custom_toolchain="${build_root}/toolchain/custom" sysroot="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux" target_cflags=[ "-DCHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME=\"mlan0\"", "-DCHIP_DEVICE_CONFIG_LINUX_DHCPC_CMD=\"udhcpc -b -i %s \"" ] target_cc="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc" target_cxx="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++" target_ar="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-ar"'"'"' {out}/imx-thermostat' +gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/thermostat/linux '--args=treat_warnings_as_errors=false target_os="linux" target_cpu="arm64" arm_arch="armv8-a" import("//build_overrides/build.gni") custom_toolchain="${build_root}/toolchain/custom" sysroot="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux" target_cflags=[ "-DCHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME=\"mlan0\"", "-DCHIP_DEVICE_CONFIG_LINUX_DHCPC_CMD=\"udhcpc -b -i %s \"" ] target_cc="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc" target_cxx="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++" target_ar="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-ar" optimize_debug=true' {out}/imx-thermostat # Generating imx-thermostat-release -bash -c ' -PKG_CONFIG_PATH="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux/lib/aarch64-linux-gnu/pkgconfig" \ - gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/thermostat/linux '"'"'--args=target_os="linux" target_cpu="arm64" arm_arch="armv8-a" import("//build_overrides/build.gni") custom_toolchain="${build_root}/toolchain/custom" sysroot="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux" target_cflags=[ "-DCHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME=\"mlan0\"", "-DCHIP_DEVICE_CONFIG_LINUX_DHCPC_CMD=\"udhcpc -b -i %s \"" ] target_cc="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc" target_cxx="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++" target_ar="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-ar" is_debug=false'"'"' {out}/imx-thermostat-release' +gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/thermostat/linux '--args=treat_warnings_as_errors=false target_os="linux" target_cpu="arm64" arm_arch="armv8-a" import("//build_overrides/build.gni") custom_toolchain="${build_root}/toolchain/custom" sysroot="IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux" target_cflags=[ "-DCHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME=\"mlan0\"", "-DCHIP_DEVICE_CONFIG_LINUX_DHCPC_CMD=\"udhcpc -b -i %s \"" ] target_cc="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc" target_cxx="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++" target_ar="IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-ar" is_debug=false' {out}/imx-thermostat-release # Generating infineon-p6-all-clusters gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/all-clusters-app/p6 '--args=p6_board="CY8CKIT-062S2-43012"' {out}/infineon-p6-all-clusters diff --git a/scripts/examples/imxlinux_example.sh b/scripts/examples/imxlinux_example.sh index e0ac39bd13c289..36ad7923d8c706 100755 --- a/scripts/examples/imxlinux_example.sh +++ b/scripts/examples/imxlinux_example.sh @@ -18,27 +18,103 @@ set -e set -x -if [ "$#" != 2 ]; then +if [ "$#" != 2 && "$#" != 3 ]; then exit -1 fi source "$(dirname "$0")/../../scripts/activate.sh" -if [ "$IMX_SDK_ROOT" = "" ]; then - echo "the Yocto SDK path is not specified with the shell env IMX_SDK_ROOT" +if [ "$IMX_SDK_ROOT" = "" -o ! -d "$IMX_SDK_ROOT" ]; then + echo "the Yocto SDK path is not specified with the shell env IMX_SDK_ROOT or an invalid path is specified" exit -1 fi env +entries="$(echo "$(ls "$IMX_SDK_ROOT")" | tr -s '\n' ',')" +IFS=',' read -ra entry_array <<<"$entries" +for entry in "${entry_array[@]}"; do + if [ "$(echo "$entry" | grep -E "^environment-setup-")" != "" ]; then + env_setup_script=$entry + break + fi +done + +if [ -z "$env_setup_script" ]; then + echo "The SDK environment setup script is not found, make sure the env IMX_SDK_ROOT is correctly set." + exit 1 +fi + +while read line; do + # trim the potential whitespaces + line=$(echo "$line" | xargs) + + if [ "$(echo "$line" | grep -E "^export SDKTARGETSYSROOT=")" != "" ]; then + sdk_target_sysroot=${line#"export SDKTARGETSYSROOT="} + fi + + if [ "$(echo "$line" | grep -E "^export CC=")" != "" ]; then + cc=${line#"export CC="} + cc=${cc#"\""} + cc=${cc%"\""} + cc=${cc/"\$SDKTARGETSYSROOT"/$sdk_target_sysroot} + fi + + if [ "$(echo "$line" | grep -E "^export CXX=")" != "" ]; then + cxx=${line#"export CXX="} + cxx=${cxx#"\""} + cxx=${cxx%"\""} + cxx=${cxx/"\$SDKTARGETSYSROOT"/$sdk_target_sysroot} + fi + + if [ "$(echo "$line" | grep -E "^export ARCH=")" != "" ]; then + target_cpu=${line#"export ARCH="} + + if [ "$target_cpu" = "arm64" ]; then + arm_arch="armv8-a" + elif [ "$target_cpu" = "arm" ]; then + arm_arch="armv7ve" + else + echo "ARCH should be arm64 or arm in the SDK environment setup script." + exit 1 + fi + fi + + if [ "$(echo "$line" | grep -E "^export CROSS_COMPILE=")" != "" ]; then + cross_compile=${line#"export CROSS_COMPILE="} + cross_compile=${cross_compile%"-"} + fi +done <"$IMX_SDK_ROOT/$env_setup_script" + +if [ -z "$sdk_target_sysroot" ]; then + echo "SDKTARGETSYSROOT is not found in the SDK environment setup script." + exit 1 +fi + +if [ -z "$cc" -o -z "$cxx" ]; then + echo "CC and/or CXX are not found in the SDK environment setup script." + exit 1 +fi + +if [ -z "$target_cpu" -o -z "$cross_compile" ]; then + echo "ARCH and/or CROSS_COMPILE are not found in the SDK environment setup script." + exit 1 +fi + +release_build=true +if [ "$3" = "debug" ]; then + release_build=false +fi + PLATFORM_CFLAGS='-DCHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME=\"mlan0\"", "-DCHIP_DEVICE_CONFIG_LINUX_DHCPC_CMD=\"udhcpc -b -i %s \"' -PKG_CONFIG_PATH=$IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux/lib/aarch64-linux-gnu/pkgconfig \ - gn gen --check --fail-on-unused-args --root="$1" "$2" --args="target_os=\"linux\" target_cpu=\"arm64\" arm_arch=\"armv8-a\" +gn gen --check --fail-on-unused-args --root="$1" "$2" --args="target_os=\"linux\" target_cpu=\"$target_cpu\" arm_arch=\"$arm_arch\" +treat_warnings_as_errors=false import(\"//build_overrides/build.gni\") -sysroot=\"$IMX_SDK_ROOT/sysroots/cortexa53-crypto-poky-linux\" +sysroot=\"$sdk_target_sysroot\" target_cflags=[ \"$PLATFORM_CFLAGS\" ] custom_toolchain=\"\${build_root}/toolchain/custom\" -target_cc=\"$IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc\" -target_cxx=\"$IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-g++\" -target_ar=\"$IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-ar\"" +target_cc=\"$IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/$cross_compile/$cc\" +target_cxx=\"$IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/$cross_compile/$cxx\" +target_ar=\"$IMX_SDK_ROOT/sysroots/x86_64-pokysdk-linux/usr/bin/$cross_compile/$cross_compile-ar\" +$(if [ "$release_build" = "true" ]; then echo "is_debug=false"; else echo "optimize_debug=true"; fi)" ninja -C "$2" diff --git a/scripts/helpers/tizen_gdbserver_run.sh b/scripts/helpers/tizen_gdbserver_run.sh new file mode 100755 index 00000000000000..e1fb8fa62a19ce --- /dev/null +++ b/scripts/helpers/tizen_gdbserver_run.sh @@ -0,0 +1,111 @@ +#!/bin/bash + +set -e + +GDBSERVER_DEFAULT_PORT=9999 +GDBSERVER_TARGET_PATH="/opt/usr/home/owner/share/tmp/sdk_tools/gdbserver" +RESULT_MODE="debug" +USAGE_INFO_MSG="See: $0 --help" + +function help() { + + cat < dict: + """ Generate spake2 params using external spake2p script + + Args: + spake2p_path (str): path to spake2 executable + passcode (int): Pairing passcode using in SPAKE 2 + it (int): Iteration counter for SPAKE2 Verifier generation + salt (str): Salt used to generate SPAKE2 password + + Returns: + dict: dictionary containing passcode, it, salt, and generated Verifier + """ + cmd = [ spake2p_path, 'gen-verifier', '--iteration-count', str(it), @@ -52,8 +90,8 @@ class FactoryDataGenerator: def __init__(self, arguments) -> None: """ - :param arguments: All input arguments parsed using ArgParse - + Args: + arguments (any):All input arguments parsed using ArgParse """ self._args = arguments self._factory_data = list() @@ -104,9 +142,18 @@ def generate_json(self): else: rd_uid = self._args.rd_uid if not self._args.spake2_verifier: - spake_2_verifier = base64.b64decode(self._generate_spake2_verifier()).hex() + spake_2_verifier = base64.b64decode(self._generate_spake2_verifier()) else: - spake_2_verifier = base64.b64decode(self._args.spake2_verifier).hex() + spake_2_verifier = base64.b64decode(self._args.spake2_verifier) + + # convert salt to bytestring to be coherent with spake2 verifier type + spake_2_salt = base64.b64decode(self._args.spake2_salt) + + # try to read DAC public and private keys + dac_priv_key = get_raw_private_key_der(self._args.dac_key, self._args.dac_key_password) + if dac_priv_key is None: + log.error("Can not read DAC keys from : {}".format(self._args.dac_key)) + sys.exit(-1) try: json_file = open(self._args.output, "w+") @@ -124,16 +171,16 @@ def generate_json(self): self._add_entry("hw_ver", self._args.hw_ver) self._add_entry("hw_ver_str", self._args.hw_ver_str) self._add_entry("dac_cert", self._process_der(self._args.dac_cert)) - self._add_entry("dac_key", self._process_der(self._args.dac_key)) + self._add_entry("dac_key", dac_priv_key) self._add_entry("pai_cert", self._process_der(self._args.pai_cert)) if self._args.include_passcode: self._add_entry("passcode", self._args.passcode) self._add_entry("spake2_it", self._args.spake2_it) - self._add_entry("spake2_salt", self._args.spake2_salt) - self._add_entry("spake2_verifier", HEX_PREFIX + spake_2_verifier) + self._add_entry("spake2_salt", spake_2_salt) + self._add_entry("spake2_verifier", spake_2_verifier) self._add_entry("discriminator", self._args.discriminator) if rd_uid: - self._add_entry("rd_uid", HEX_PREFIX + rd_uid) + self._add_entry("rd_uid", rd_uid) # add user-specific data self._add_entry("user", self._args.user) @@ -154,6 +201,8 @@ def generate_json(self): def _add_entry(self, name: str, value: any): """ Add single entry to list of tuples ("key", "value") """ + if(isinstance(value, bytes) or isinstance(value, bytearray)): + value = HEX_PREFIX + value.hex() if value or (isinstance(value, int) and value == 0): log.debug("Adding entry '{}' with size {} and type {}".format(name, sys.getsizeof(value), type(value))) self._factory_data.append((name, value)) @@ -168,8 +217,8 @@ def _generate_rotating_device_uid(self): """ If rotating device unique ID has not been provided it should be generated """ log.warning("Can not find rotating device UID in provided arguments list. A new one will be generated.") rdu = secrets.token_bytes(16) - log.info("\n\nThe new rotate device UID: {}\n".format(rdu.hex())) - return rdu.hex() + log.info("\n\nThe new rotate device UID: {}\n".format(rdu).hex()) + return rdu def _validate_output_json(self, output_json: str): """ @@ -194,7 +243,7 @@ def _process_der(self, path: str): log.debug("Processing der file...") try: with open(path, 'rb') as f: - data = HEX_PREFIX + f.read().hex() + data = f.read() return data except IOError as e: log.error(e) @@ -250,6 +299,7 @@ def allow_any_int(i): return int(i, 0) help="[int] Provide BLE pairing discriminator. \ A 12-bit value matching the field of the same name in \ the setup code. Discriminator is used during a discovery process.") + # optional keys optional_arguments.add_argument("--chip_cert_path", type=str, help="Generate DAC and PAI certificates instead giving a path to .der files. This option requires a path to chip-cert executable." @@ -258,10 +308,12 @@ def allow_any_int(i): return int(i, 0) help="[.der] Provide the path to .der file containing DAC certificate.") optional_arguments.add_argument("--dac_key", type=str, help="[.der] Provide the path to .der file containing DAC keys.") - optional_arguments.add_argument("--pai_cert", type=str, - help="[.der] Provide the path to .der file containing PAI certificate.") optional_arguments.add_argument("--generate_rd_uid", action="store_true", help="Generate a new rotating device unique ID, print it out to console output and store it in factory data.") + optional_arguments.add_argument("--dac_key_password", type=str, + help="Provide a password to decode dac key. If dac key is not encrypted do not provide this argument.") + optional_arguments.add_argument("--pai_cert", type=str, + help="[.der] Provide the path to .der file containing PAI certificate.") optional_arguments.add_argument("--rd_uid", type=str, help="[hex string] Provide the rotating device unique ID. If this argument is not provided a new rotating device id unique id will be generated.") optional_arguments.add_argument("--passcode", type=allow_any_int, @@ -280,7 +332,11 @@ def allow_any_int(i): return int(i, 0) if args.verbose: log.basicConfig(format='[%(asctime)s][%(levelname)s] %(message)s', level=log.DEBUG) else: - log.basicConfig(format='[%(asctime)s] %(message)s', level=log.INFO) + log.basicConfig(format='[%(levelname)s] %(message)s', level=log.INFO) + + if(args.chip_cert_path): + log.error("Generating DAC and PAI certificates is not supported yet") + return # check if json file already exist if(exists(args.output) and not args.overwrite): diff --git a/scripts/tools/nrfconnect/nrfconnect_factory_data.schema b/scripts/tools/nrfconnect/nrfconnect_factory_data.schema index 393c2b152b66b3..6d61795f0bc9e1 100644 --- a/scripts/tools/nrfconnect/nrfconnect_factory_data.schema +++ b/scripts/tools/nrfconnect/nrfconnect_factory_data.schema @@ -73,15 +73,19 @@ }, "dac_cert": { "description": "DAC certificate in hex-string format", - "type": "string" + "type": "string", + "maxLength": 1204 }, "dac_key": { "description": "DAC Private Key in hex-string format", - "type": "string" + "type": "string", + "minLength": 68, + "maxLength": 68 }, "pai_cert": { "description": "PAI certificate in hex-string format", - "type": "string" + "type": "string", + "maxLength": 1204 }, "passcode": { "description": "A default PASE session passcode", @@ -98,8 +102,8 @@ "spake2_salt": { "description": "A key-derivation function for the Symmetric Password-Authenticated Key Exchange.", "type": "string", - "minLength": 16, - "maxLength": 32 + "minLength": 36, + "maxLength": 68 }, "spake2_verifier": { "description": "A verifier for the Symmetric Password-Authenticated Key Exchange", @@ -112,10 +116,6 @@ "minimum": 0, "maximum": 4095 }, - "fw_info": { - "description": "Information about programmed firmware in TLV format", - "type": "string" - }, "user": { "description": "A user-specific additional data which should be added to factory data. This should be a Json format.", "type": "object" diff --git a/scripts/tools/zap/convert.py b/scripts/tools/zap/convert.py index 143bd104d91ea1..1181ebe17d989f 100755 --- a/scripts/tools/zap/convert.py +++ b/scripts/tools/zap/convert.py @@ -16,6 +16,7 @@ # import argparse +import json import os import subprocess import sys @@ -66,9 +67,28 @@ def runArgumentsParser(): return zap_file +def detectZclFile(zapFile): + print(f"Searching for zcl file from {zapFile}") + + path = 'src/app/zap-templates/zcl/zcl.json' + + data = json.load(open(zapFile)) + for package in data["package"]: + if package["type"] != "zcl-properties": + continue + + # found the right path, try to figure out the actual path + if package["pathRelativity"] == "relativeToZap": + path = os.path.abspath(os.path.join(os.path.dirname(zapFile), package["path"])) + else: + path = package["path"] + + return getFilePath(path) + + def runConversion(zap_file): templates_file = getFilePath('src/app/zap-templates/app-templates.json') - zcl_file = getFilePath('src/app/zap-templates/zcl/zcl.json') + zcl_file = detectZclFile(zap_file) generator_dir = getDirPath('third_party/zap/repo') os.chdir(generator_dir) diff --git a/scripts/tools/zap/generate.py b/scripts/tools/zap/generate.py index 6d6b0848e3d1ed..72b63a1c7fbb6c 100755 --- a/scripts/tools/zap/generate.py +++ b/scripts/tools/zap/generate.py @@ -58,9 +58,27 @@ def getDirPath(name): return fullpath +def detectZclFile(zapFile): + print(f"Searching for zcl file from {zapFile}") + + path = 'src/app/zap-templates/zcl/zcl.json' + + data = json.load(open(zapFile)) + for package in data["package"]: + if package["type"] != "zcl-properties": + continue + + # found the right path, try to figure out the actual path + if package["pathRelativity"] == "relativeToZap": + path = os.path.abspath(os.path.join(os.path.dirname(zapFile), package["path"])) + else: + path = package["path"] + + return getFilePath(path) + + def runArgumentsParser(): default_templates = 'src/app/zap-templates/app-templates.json' - default_zcl = 'src/app/zap-templates/zcl/zcl.json' default_output_dir = 'zap-generated/' parser = argparse.ArgumentParser( @@ -68,8 +86,8 @@ def runArgumentsParser(): parser.add_argument('zap', help='Path to the application .zap file') parser.add_argument('-t', '--templates', default=default_templates, help='Path to the .zapt templates records to use for generating artifacts (default: "' + default_templates + '")') - parser.add_argument('-z', '--zcl', default=default_zcl, - help='Path to the zcl templates records to use for generating artifacts (default: "' + default_zcl + '")') + parser.add_argument('-z', '--zcl', + help='Path to the zcl templates records to use for generating artifacts (default: autodetect read from zap file)') parser.add_argument('-o', '--output-dir', default=None, help='Output directory for the generated files (default: automatically selected)') args = parser.parse_args() @@ -86,7 +104,12 @@ def runArgumentsParser(): output_dir = '' zap_file = getFilePath(args.zap) - zcl_file = getFilePath(args.zcl) + + if args.zcl: + zcl_file = getFilePath(args.zcl) + else: + zcl_file = detectZclFile(zap_file) + templates_file = getFilePath(args.templates) output_dir = getDirPath(output_dir) diff --git a/scripts/tools/zap/run_zaptool.sh b/scripts/tools/zap/run_zaptool.sh index c219a6cc560339..62a9d3de514bca 100755 --- a/scripts/tools/zap/run_zaptool.sh +++ b/scripts/tools/zap/run_zaptool.sh @@ -45,9 +45,16 @@ CHIP_ROOT="${SCRIPT_PATH%/scripts/tools/zap/run_zaptool.sh}" npm install fi + echo "ARGS: ${ZAP_ARGS[@]}" + + if [[ "${ZAP_ARGS[@]}" == *"/all-clusters-app.zap"* ]]; then + ZCL_FILE="$CHIP_ROOT/src/app/zap-templates/zcl/zcl-with-test-extensions.json" + else + ZCL_FILE="$CHIP_ROOT/src/app/zap-templates/zcl/zcl.json" + fi + node src-script/zap-start.js --logToStdout \ --gen "$CHIP_ROOT/src/app/zap-templates/app-templates.json" \ - --zcl "$CHIP_ROOT/src/app/zap-templates/zcl/zcl.json" \ + --zcl "$ZCL_FILE" \ "${ZAP_ARGS[@]}" - ) diff --git a/src/android/CHIPTest/app/src/main/java/com/tcl/chip/chiptest/MainActivity.kt b/src/android/CHIPTest/app/src/main/java/com/tcl/chip/chiptest/MainActivity.kt index b969cb9fce1eac..0b914a1745fe99 100644 --- a/src/android/CHIPTest/app/src/main/java/com/tcl/chip/chiptest/MainActivity.kt +++ b/src/android/CHIPTest/app/src/main/java/com/tcl/chip/chiptest/MainActivity.kt @@ -53,6 +53,6 @@ class MainActivity : AppCompatActivity() { }.start() } - AndroidChipPlatform(AndroidBleManager(), PreferencesKeyValueStoreManager(this), PreferencesConfigurationManager(this), NsdManagerServiceResolver(this), ChipMdnsCallbackImpl(), DiagnosticDataProviderImpl(this)) + AndroidChipPlatform(AndroidBleManager(), PreferencesKeyValueStoreManager(this), PreferencesConfigurationManager(this), NsdManagerServiceResolver(this), NsdManagerServiceBrowser(this), ChipMdnsCallbackImpl(), DiagnosticDataProviderImpl(this)) } } diff --git a/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/ChipClient.kt b/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/ChipClient.kt index d4ed41a5347f66..53d62c1b4f39e3 100644 --- a/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/ChipClient.kt +++ b/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/ChipClient.kt @@ -25,6 +25,7 @@ import chip.platform.AndroidBleManager import chip.platform.AndroidChipPlatform import chip.platform.ChipMdnsCallbackImpl import chip.platform.DiagnosticDataProviderImpl +import chip.platform.NsdManagerServiceBrowser import chip.platform.NsdManagerServiceResolver import chip.platform.PreferencesConfigurationManager import chip.platform.PreferencesKeyValueStoreManager @@ -51,7 +52,7 @@ object ChipClient { if (!this::androidPlatform.isInitialized && context != null) { //force ChipDeviceController load jni ChipDeviceController.loadJni() - androidPlatform = AndroidChipPlatform(AndroidBleManager(), PreferencesKeyValueStoreManager(context), PreferencesConfigurationManager(context), NsdManagerServiceResolver(context), ChipMdnsCallbackImpl(), DiagnosticDataProviderImpl(context)) + androidPlatform = AndroidChipPlatform(AndroidBleManager(), PreferencesKeyValueStoreManager(context), PreferencesConfigurationManager(context), NsdManagerServiceResolver(context), NsdManagerServiceBrowser(context), ChipMdnsCallbackImpl(), DiagnosticDataProviderImpl(context)) } return androidPlatform } diff --git a/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/MultiAdminClientFragment.kt b/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/MultiAdminClientFragment.kt index 240553514740ff..ff61638b9bac0b 100644 --- a/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/MultiAdminClientFragment.kt +++ b/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/MultiAdminClientFragment.kt @@ -9,16 +9,17 @@ import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope import chip.devicecontroller.ChipClusters import chip.devicecontroller.ChipDeviceController +import chip.devicecontroller.OpenCommissioningCallback import com.google.chip.chiptool.ChipClient import com.google.chip.chiptool.GenericChipDeviceListener import com.google.chip.chiptool.R import kotlinx.android.synthetic.main.multi_admin_client_fragment.discriminatorEd +import kotlinx.android.synthetic.main.multi_admin_client_fragment.timeoutEd import kotlinx.android.synthetic.main.multi_admin_client_fragment.multiAdminClusterCommandStatus import kotlinx.android.synthetic.main.multi_admin_client_fragment.setupPinCodeEd import kotlinx.android.synthetic.main.multi_admin_client_fragment.view.basicCommissioningMethodBtn import kotlinx.android.synthetic.main.multi_admin_client_fragment.view.enhancedCommissioningMethodBtn import kotlinx.android.synthetic.main.multi_admin_client_fragment.view.revokeBtn -import kotlinx.android.synthetic.main.on_off_client_fragment.* import kotlinx.coroutines.* class MultiAdminClientFragment : Fragment() { @@ -53,8 +54,10 @@ class MultiAdminClientFragment : Fragment() { // TODO: use the discriminator and setupPinCode that was used to commission the device val testDiscriminator = "3840" val testSetupPinCode = 20202021L + val testDuration = 180 discriminatorEd.setText(testDiscriminator) setupPinCodeEd.setText(testSetupPinCode.toString()) + timeoutEd.setText(testDuration.toString()) } inner class ChipControllerCallback : GenericChipDeviceListener() { @@ -78,23 +81,41 @@ class MultiAdminClientFragment : Fragment() { } private suspend fun sendBasicCommissioningCommandClick() { - val testDuration = 100 - deviceController.openPairingWindow( + val testDuration = timeoutEd.text.toString().toInt() + deviceController.openPairingWindowCallback( ChipClient.getConnectedDevicePointer( requireContext(), addressUpdateFragment.deviceId - ), testDuration + ), testDuration, + object:OpenCommissioningCallback { + override fun onError(status: Int, deviceId: Long) { + showMessage("OpenBasicCommissioning Fail! \nDevice ID : $deviceId\nErrorCode : $status") + } + + override fun onSuccess(deviceId: Long, manualPairingCode: String?, qrCode: String?) { + showMessage("OpenBasicCommissioning Success! \n Node ID: $deviceId") + } + } ) } private suspend fun sendEnhancedCommissioningCommandClick() { - val testDuration = 100 + val testDuration = timeoutEd.text.toString().toInt() val testIteration = 1000 val devicePointer = ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) - deviceController.openPairingWindowWithPIN( + deviceController.openPairingWindowWithPINCallback( devicePointer, testDuration, testIteration.toLong(), - discriminatorEd.text.toString().toInt(), setupPinCodeEd.text.toString().toULong().toLong() + discriminatorEd.text.toString().toInt(), setupPinCodeEd.text.toString().toULong().toLong(), + object:OpenCommissioningCallback { + override fun onError(status: Int, deviceId: Long) { + showMessage("OpenCommissioning Fail! \nDevice ID : $deviceId\nErrorCode : $status") + } + + override fun onSuccess(deviceId: Long, manualPairingCode: String?, qrCode: String?) { + showMessage("OpenCommissioning Success! \n Node ID: $deviceId\n\tManual : $manualPairingCode\n\tQRCode : $qrCode") + } + } ) } diff --git a/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/provisioning/AddressCommissioningFragment.kt b/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/provisioning/AddressCommissioningFragment.kt index 23232bd8b15fc1..9bac357a8900c3 100644 --- a/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/provisioning/AddressCommissioningFragment.kt +++ b/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/provisioning/AddressCommissioningFragment.kt @@ -5,17 +5,30 @@ import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.AdapterView +import android.widget.ArrayAdapter import androidx.fragment.app.Fragment +import com.google.chip.chiptool.ChipClient import com.google.chip.chiptool.R import com.google.chip.chiptool.setuppayloadscanner.BarcodeFragment import com.google.chip.chiptool.setuppayloadscanner.CHIPDeviceInfo import com.google.chip.chiptool.util.FragmentUtil import kotlinx.android.synthetic.main.address_commissioning_fragment.addressEditText import kotlinx.android.synthetic.main.address_commissioning_fragment.commissionBtn +import kotlinx.android.synthetic.main.address_commissioning_fragment.discoverBtn +import kotlinx.android.synthetic.main.address_commissioning_fragment.discoverListSpinner import kotlinx.android.synthetic.main.address_commissioning_fragment.discriminatorEditText import kotlinx.android.synthetic.main.address_commissioning_fragment.pincodeEditText +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch class AddressCommissioningFragment : Fragment() { + private val ipAddressList = ArrayList() + private val scope = CoroutineScope(Dispatchers.Main + Job()) + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -45,6 +58,39 @@ class AddressCommissioningFragment : Fragment() { ) ) } + + discoverBtn.setOnClickListener { _ -> + discoverBtn.isEnabled = false + val deviceController = ChipClient.getDeviceController(requireContext()) + deviceController.discoverCommissionableNodes() + scope.launch { + delay(7000) + updateSpinner() + discoverBtn.isEnabled = true + } + } + } + + private fun updateSpinner() { + val deviceController = ChipClient.getDeviceController(requireContext()) + for(i in 0..10) { + val device = deviceController.getDiscoveredDevice(i) ?: break + ipAddressList.add("${device.ipAddress}, ${device.discriminator}") + } + requireActivity().runOnUiThread { + discoverListSpinner.adapter = + ArrayAdapter(requireContext(), android.R.layout.simple_spinner_dropdown_item, ipAddressList) + discoverListSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) { + val address = ipAddressList[position].split(",")[0].trim() + val discriminator = ipAddressList[position].split(",")[1].trim() + addressEditText.setText(address) + discriminatorEditText.setText(discriminator) + } + + override fun onNothingSelected(parent: AdapterView<*>) {} + } + } } companion object { diff --git a/src/android/CHIPTool/app/src/main/res/layout/address_commissioning_fragment.xml b/src/android/CHIPTool/app/src/main/res/layout/address_commissioning_fragment.xml index 21fafbd3ff9edf..4ff57d1767d7ed 100644 --- a/src/android/CHIPTool/app/src/main/res/layout/address_commissioning_fragment.xml +++ b/src/android/CHIPTool/app/src/main/res/layout/address_commissioning_fragment.xml @@ -16,6 +16,7 @@ app:layout_constraintTop_toTopOf="parent" /> + + +