diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 4c8a11fd42f7f1..da4e2c4171171e 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -43,7 +43,7 @@ RUN apt-get update \ && : RUN groupadd -g $USER_GID $USERNAME \ - && useradd -s /bin/bash -u $USER_UID -g $USER_GID -G docker,sudo -m $USERNAME \ + && useradd --no-log-init -s /bin/bash -u $USER_UID -g $USER_GID -G docker,sudo -m $USERNAME \ && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \ && chmod 0440 /etc/sudoers.d/$USERNAME \ && : diff --git a/.github/dependabot.yml b/.github/dependabot.yml index b55417cdba78ed..8c618416fba4c1 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -54,7 +54,6 @@ updates: - dependency-name: "third_party/open-iot-sdk/repo" - dependency-name: "third_party/ot-br-posix/repo" - dependency-name: "third_party/perfetto/repo" - - dependency-name: "third_party/pybind11/repo" - dependency-name: "third_party/qpg_sdk/repo" - dependency-name: "third_party/silabs/repo" - dependency-name: "third_party/simw-top-mini/repo" diff --git a/.github/stale.yml b/.github/stale.yml deleted file mode 100644 index 4f6adeea522da6..00000000000000 --- a/.github/stale.yml +++ /dev/null @@ -1,42 +0,0 @@ -# Stale config for https://github.com/marketplace/stale -# Issues with these labels will never be considered stale -exemptLabels: - - security - - blocked - -# Label to use when marking a pull request as stale -staleLabel: stale - -pulls: - # Number of days of inactivity before a pull request becomes stale - daysUntilStale: 60 - - # Number of days of inactivity before a stale pull request is closed - daysUntilClose: 30 - - # Comment to post when marking a pull request as stale. Set to `false` to disable - markComment: > - This pull request has been automatically marked as stale because it has not had - recent activity. It will be closed if no further activity occurs. - - # Comment to post when closing a stale pull request. Set to `false` to disable - closeComment: > - This stale pull request has been automatically closed. - Thank you for your contributions. - -issues: - # Number of days of inactivity before a issue becomes stale - daysUntilStale: 180 - - # Number of days of inactivity before a stale issue is closed - daysUntilClose: 7 - - # Comment to post when marking a issue as stale. Set to `false` to disable - markComment: > - This issue has been automatically marked as stale because it has not had - recent activity. It will be closed if no further activity occurs. - - # Comment to post when closing a stale issue. Set to `false` to disable - closeComment: > - This stale issue has been automatically closed. - Thank you for your contributions. diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 3ec8fd379c3fe7..58e6d14cd8bb0e 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -308,7 +308,7 @@ jobs: - name: Setup Build, Run Build and Run Tests run: | - scripts/build/gn_gen.sh --args="enable_rtti=true enable_pylib=true chip_config_memory_debug_checks=false chip_config_memory_debug_dmalloc=false chip_generate_link_map_file=false" + scripts/build/gn_gen.sh --args="enable_rtti=true chip_config_memory_debug_checks=false chip_config_memory_debug_dmalloc=false chip_generate_link_map_file=false" scripts/run_in_build_env.sh "ninja -C ./out" scripts/tests/gn_tests.sh - name: Setup test python environment @@ -414,7 +414,6 @@ jobs: # "host clang" build, which uses the pigweed # clang. "default") GN_ARGS='target_os="all" is_asan=true enable_host_clang_build=false';; - "python_lib") GN_ARGS='enable_rtti=true enable_pylib=true';; esac BUILD_TYPE=$BUILD_TYPE scripts/build/gn_gen.sh --args="$GN_ARGS" --export-compile-commands scripts/run_in_build_env.sh "ninja -C ./out/$BUILD_TYPE" diff --git a/.github/workflows/docker_img.yaml b/.github/workflows/docker_img.yaml index 5a8b9e104dc41b..05594606a610c7 100644 --- a/.github/workflows/docker_img.yaml +++ b/.github/workflows/docker_img.yaml @@ -102,7 +102,6 @@ jobs: # - "-imx" - "-java" - "-k32w" - - "-mbed-os" - "-nrf-platform" - "-telink" - "-ti" diff --git a/.github/workflows/examples-ameba.yaml b/.github/workflows/examples-ameba.yaml index 7c098ea57f2403..93ae9ce31ddee1 100644 --- a/.github/workflows/examples-ameba.yaml +++ b/.github/workflows/examples-ameba.yaml @@ -38,7 +38,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-ameba:54 + image: ghcr.io/project-chip/chip-build-ameba:68 options: --user root steps: diff --git a/.github/workflows/examples-bouffalolab.yaml b/.github/workflows/examples-bouffalolab.yaml index 12b033b791f900..933a9b60361eb3 100644 --- a/.github/workflows/examples-bouffalolab.yaml +++ b/.github/workflows/examples-bouffalolab.yaml @@ -37,7 +37,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-bouffalolab:54 + image: ghcr.io/project-chip/chip-build-bouffalolab:68 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-mbed.yaml b/.github/workflows/examples-mbed.yaml deleted file mode 100644 index 5b39c51e8fa0a8..00000000000000 --- a/.github/workflows/examples-mbed.yaml +++ /dev/null @@ -1,170 +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. - -name: Build example - Mbed OS - -on: - push: - branches-ignore: - - 'dependabot/**' - pull_request: - merge_group: - workflow_dispatch: - -concurrency: - group: ${{ github.ref }}-${{ github.workflow }}-${{ (github.event_name == 'pull_request' && github.event.number) || (github.event_name == 'workflow_dispatch' && github.run_number) || github.sha }} - cancel-in-progress: true - -env: - CHIP_NO_LOG_TIMESTAMPS: true - -jobs: - mbedos: - name: Mbed OS examples building - - env: - PLATFORM_NAME: mbed - APP_PROFILE: release - APP_TARGET: cy8cproto_062_4343w - - runs-on: ubuntu-latest - if: github.actor != 'restyled-io[bot]' - - container: - image: ghcr.io/project-chip/chip-build-mbed-os:66 - volumes: - - "/tmp/bloat_reports:/tmp/bloat_reports" - - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Checkout submodules & Bootstrap - uses: ./.github/actions/checkout-submodules-and-bootstrap - with: - platform: mbed - - - name: Set up environment for size reports - uses: ./.github/actions/setup-size-reports - if: ${{ !env.ACT }} - with: - gh-context: ${{ toJson(github) }} - - - name: Build lock-app example - run: | - ./scripts/run_in_build_env.sh \ - "./scripts/build/build_examples.py \ - --target $PLATFORM_NAME-$APP_TARGET-lock-$APP_PROFILE \ - build \ - " - .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ - $PLATFORM_NAME $APP_TARGET lock-app-$APP_PROFILE \ - out/$PLATFORM_NAME-$APP_TARGET-lock-$APP_PROFILE/chip-mbed-lock-app-example.elf \ - /tmp/bloat_reports/ - rm -rf ./out - - - name: Build lighting-app example - if: github.event_name == 'push' - run: | - ./scripts/run_in_build_env.sh \ - "./scripts/build/build_examples.py \ - --target $PLATFORM_NAME-$APP_TARGET-light-$APP_PROFILE \ - build \ - " - .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ - $PLATFORM_NAME $APP_TARGET lighting-app-$APP_PROFILE \ - out/$PLATFORM_NAME-$APP_TARGET-light-$APP_PROFILE/chip-mbed-lighting-app-example.elf \ - /tmp/bloat_reports/ - rm -rf ./out - - - name: Build pigweed-app example - if: github.event_name == 'push' - run: | - ./scripts/run_in_build_env.sh \ - "./scripts/build/build_examples.py \ - --target $PLATFORM_NAME-$APP_TARGET-pigweed-$APP_PROFILE \ - build \ - " - .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ - $PLATFORM_NAME $APP_TARGET pigweed-app-$APP_PROFILE \ - out/$PLATFORM_NAME-$APP_TARGET-pigweed-$APP_PROFILE/chip-mbed-pigweed-app-example.elf \ - /tmp/bloat_reports/ - rm -rf ./out - - - name: Build all-clusters-app example - if: github.event_name == 'push' - run: | - ./scripts/run_in_build_env.sh \ - "./scripts/build/build_examples.py \ - --target $PLATFORM_NAME-$APP_TARGET-all-clusters-$APP_PROFILE \ - build \ - " - .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ - $PLATFORM_NAME $APP_TARGET all-clusters-app-$APP_PROFILE \ - out/$PLATFORM_NAME-$APP_TARGET-all-clusters-$APP_PROFILE/chip-mbed-all-clusters-app-example.elf \ - /tmp/bloat_reports/ - rm -rf ./out - - - name: Build all-clusters-minimal-app example - if: github.event_name == 'push' - run: | - ./scripts/run_in_build_env.sh \ - "./scripts/build/build_examples.py \ - --target $PLATFORM_NAME-$APP_TARGET-all-clusters-minimal-$APP_PROFILE \ - build \ - " - .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ - $PLATFORM_NAME $APP_TARGET all-clusters-minimal-app-$APP_PROFILE \ - out/$PLATFORM_NAME-$APP_TARGET-all-clusters-minimal-$APP_PROFILE/chip-mbed-all-clusters-minimal-app-example.elf \ - /tmp/bloat_reports/ - rm -rf ./out - - - name: Build shell example - if: github.event_name == 'push' - run: | - ./scripts/run_in_build_env.sh \ - "./scripts/build/build_examples.py \ - --target $PLATFORM_NAME-$APP_TARGET-shell-$APP_PROFILE \ - build \ - " - .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ - $PLATFORM_NAME $APP_TARGET shell-app-$APP_PROFILE \ - out/$PLATFORM_NAME-$APP_TARGET-shell-$APP_PROFILE/chip-mbed-shell-example.elf \ - /tmp/bloat_reports/ - rm -rf ./out - - - name: Build ota-requestor-app example - if: github.event_name == 'push' - run: | - ./scripts/run_in_build_env.sh \ - "./scripts/build/build_examples.py \ - --target $PLATFORM_NAME-$APP_TARGET-ota-requestor-$APP_PROFILE \ - build \ - " - .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ - $PLATFORM_NAME $APP_TARGET ota-requestor-app-$APP_PROFILE \ - out/$PLATFORM_NAME-$APP_TARGET-ota-requestor-$APP_PROFILE/chip-mbed-ota-requestor-app-example.elf \ - /tmp/bloat_reports/ - rm -rf ./out - - - name: Build unit tests - # Temporarily disabled build due to running out of flash space - # TODO Issue #33978: re-enable unit testing after split of unit tests is done - if: false - run: scripts/tests/mbed/mbed_unit_tests.sh -b=$APP_TARGET -p=$APP_PROFILE - - - name: Uploading Size Reports - uses: ./.github/actions/upload-size-reports - if: ${{ !env.ACT }} - with: - platform-name: Mbed diff --git a/.github/workflows/examples-nxp.yaml b/.github/workflows/examples-nxp.yaml index 747813d6aa1037..975d9292a18941 100644 --- a/.github/workflows/examples-nxp.yaml +++ b/.github/workflows/examples-nxp.yaml @@ -29,8 +29,8 @@ env: CHIP_NO_LOG_TIMESTAMPS: true jobs: - k32w: - name: K32W + k32w0: + name: K32W0 env: BUILD_TYPE: gn_k32w @@ -39,7 +39,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-k32w:66 + image: ghcr.io/project-chip/chip-build-k32w:71 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: @@ -66,8 +66,6 @@ jobs: --target nxp-k32w0-freertos-contact-sensor \ --target nxp-k32w0-freertos-contact-sensor-low-power \ --target nxp-k32w0-freertos-contact-sensor-low-power-factory \ - --target nxp-k32w1-freertos-lighting \ - --target nxp-k32w1-freertos-contact-sensor-low-power \ build \ --copy-artifacts-to out/artifacts \ " @@ -77,16 +75,62 @@ jobs: nxp k32w0+release light \ out/artifacts/nxp-k32w0-freertos-lighting/chip-k32w0x-light-example.elf \ /tmp/bloat_reports/ - .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ - nxp k32w1+release light \ - out/artifacts/nxp-k32w1-freertos-lighting/chip-k32w1-light-example.elf \ - /tmp/bloat_reports/ - name: Get contact sensor size stats run: | .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ nxp k32w0+release contact \ out/artifacts/nxp-k32w0-freertos-contact-sensor-low-power/chip-k32w0x-contact-example.elf \ /tmp/bloat_reports/ + - name: Uploading Size Reports + uses: ./.github/actions/upload-size-reports + if: ${{ !env.ACT }} + with: + platform-name: K32W0 + k32w1: + name: K32W1 + + env: + BUILD_TYPE: gn_k32w + + runs-on: ubuntu-latest + if: github.actor != 'restyled-io[bot]' + + container: + image: ghcr.io/project-chip/chip-build-nxp:71 + volumes: + - "/tmp/bloat_reports:/tmp/bloat_reports" + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Checkout submodules & Bootstrap + uses: ./.github/actions/checkout-submodules-and-bootstrap + with: + platform: nxp + extra-submodule-parameters: --recursive + + - name: Set up environment for size reports + uses: ./.github/actions/setup-size-reports + if: ${{ !env.ACT }} + with: + gh-context: ${{ toJson(github) }} + + - name: Build examples + run: | + scripts/run_in_build_env.sh "\ + ./scripts/build/build_examples.py \ + --target nxp-k32w1-freertos-lighting \ + --target nxp-k32w1-freertos-contact-sensor-low-power \ + build \ + --copy-artifacts-to out/artifacts \ + " + - name: Get lighting app size stats + run: | + .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ + nxp k32w1+release light \ + out/artifacts/nxp-k32w1-freertos-lighting/chip-k32w1-light-example.elf \ + /tmp/bloat_reports/ + - name: Get contact sensor size stats + run: | .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ nxp k32w1+release contact \ out/artifacts/nxp-k32w1-freertos-contact-sensor-low-power/chip-k32w1-contact-example.elf \ @@ -95,7 +139,7 @@ jobs: uses: ./.github/actions/upload-size-reports if: ${{ !env.ACT }} with: - platform-name: K32W + platform-name: K32W1 rw61x: name: RW61X diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml new file mode 100644 index 00000000000000..a9953e69b08ac1 --- /dev/null +++ b/.github/workflows/stale.yaml @@ -0,0 +1,42 @@ +name: "Process Stale Issues and PRs" +on: + workflow_dispatch: + schedule: + - cron: "30 1 * * *" + +permissions: + issues: write + pull-requests: write + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v9 + with: + stale-issue-message: + "This issue has been automatically marked as stale because + it has not had recent activity. It will be closed if no + further activity occurs. Remove stale label or comment or + this will be closed in 30 days." + stale-pr-message: + "This pull request has been automatically marked as stale + because it has not had recent activity. It will be closed + if no further activity occurs. Remove stale label or + comment or this will be closed in 10 days." + close-issue-message: + "This stale issue has been automatically closed. Thank you + for your contributions." + close-pr-message: + "This stale pull request has been automatically closed. + Thank you for your contributions." + days-before-issue-stale: 30 + days-before-issue-close: -1 # Don't close them for now + days-before-pr-stale: 90 + days-before-pr-close: 10 + exempt-issue-labels: + "security,blocked,cert blocker,build issue,Spec XML + align,CI/CD improvements,memory" + exempt-pr-labels: + "security,blocked,cert blocker,build issue,Spec XML + align,CI/CD improvements,memory" diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 72080ea65ad772..6974999d0d134f 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -506,6 +506,7 @@ jobs: run: | mkdir -p out/trace_data scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/controller/python/test/test_scripts/mobile-device-test.py' + scripts/run_in_python_env.sh out/venv 'python3 ./src/python_testing/execute_python_tests.py --env-file /tmp/test_env.yaml --search-directory src/python_testing' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --script "src/python_testing/TestMatterTestingSupport.py" --script-args "--trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --script "src/python_testing/TestSpecParsingSupport.py" --script-args "--trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' scripts/run_in_python_env.sh out/venv './scripts/tests/TestTimeSyncTrustedTimeSourceRunner.py' diff --git a/.github/workflows/third-party-check.yaml b/.github/workflows/third-party-check.yaml index 575e7e3c9c7137..beda0af41b0622 100644 --- a/.github/workflows/third-party-check.yaml +++ b/.github/workflows/third-party-check.yaml @@ -17,7 +17,7 @@ name: Check for Unintentional Submodule Updates on: pull_request: branches-ignore: - - 'dependabot/**' + - "dependabot/**" paths: - "third_party/**" - ".gitmodules" @@ -26,9 +26,14 @@ jobs: check-submodule-update-label: name: Check For Submodule Update Label runs-on: ubuntu-latest - if: "!contains(github.event.pull_request.labels.*.name, 'changing-submodules-on-purpose')" steps: - - name: Error Message - run: echo This pull request attempts to update submodules without the changing-submodules-on-purpose label. Please apply that label if the changes are intentional, or remove those changes. - - name: Fail Job - run: exit 1 + - if: ${{ !contains(github.event.pull_request.labels.*.name, 'changing-submodules-on-purpose') }} + name: Fail + run: | + echo This pull request attempts to update submodules without the changing-submodules-on-purpose label. Please apply that label if the changes are intentional, or remove those changes. + exit 1 + - if: ${{ contains(github.event.pull_request.labels.*.name, 'changing-submodules-on-purpose') }} + name: Success + run: | + echo PR looks good. + exit 0 diff --git a/.gitmodules b/.gitmodules index 1f4129f9f2df9d..0b015f8d14cd16 100644 --- a/.gitmodules +++ b/.gitmodules @@ -165,10 +165,6 @@ path = third_party/infineon/psoc6/psoc6_sdk/libs/recipe-make-cat1a url = https://github.com/Infineon/recipe-make-cat1a platforms = infineon -[submodule "third_party/pybind11/repo"] - path = third_party/pybind11/repo - url = https://github.com/pybind/pybind11 - branch = stable [submodule "p6/lwip"] path = third_party/infineon/psoc6/psoc6_sdk/libs/lwip url = https://github.com/lwip-tcpip/lwip.git diff --git a/.mergify.yml b/.mergify.yml index c27419c8d0fc3e..77530c4521b676 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -1,20 +1,29 @@ pull_request_rules: + - name: Label conflicting pull requests + description: Add a label to a pull request with conflict to spot it easily + conditions: + - conflict + - '-closed' + actions: + label: + toggle: + - conflict - name: Automatic merge on PullApprove conditions: - or: - - "check-success=pullapprove" - - label="fast track" - - "#approved-reviews-by>=1" - - "#review-threads-unresolved=0" - - "-draft" - - "label!=docker" # Don't auto merge docker images - - "#check-failure=0" # Don't auto merge with a failure - - "#check-pending=0" # Don't auto merge with anything pending - - "check-success~=Build" # Don't auto merge unless a build has succeeded, needed because above is true on a fresh PR before builds + - check-success=pullapprove + - label="fast track" + - '#approved-reviews-by>=1' + - '#review-threads-unresolved=0' + - '-draft' + - label!=docker + - '#check-failure=0' + - '#check-pending=0' + - check-success~=Build - or: - - "check-success=pullapprove" - - "check-skipped=pullapprove" - - "check-neutral=pullapprove" + - check-success=pullapprove + - check-skipped=pullapprove + - check-neutral=pullapprove actions: merge: method: squash diff --git a/BUILD.gn b/BUILD.gn index 8a78d8f55f3bd0..c8e41976599173 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -44,7 +44,6 @@ if (current_toolchain != "${dir_pw_toolchain}/default:default") { chip_enable_python_modules = (current_os == "mac" || current_os == "linux") && (host_cpu == "x64" || host_cpu == "arm64" || host_cpu == "arm") - enable_pylib = false # Build the Linux all clusters app example with default group chip_build_all_clusters_app = false @@ -112,9 +111,6 @@ if (current_toolchain != "${dir_pw_toolchain}/default:default") { "${chip_root}/src/controller/python:chip-repl", "${chip_root}/src/python_testing/matter_testing_infrastructure:metadata_parser.wheel", ] - if (enable_pylib) { - deps += [ "${chip_root}/src/pybindings/pycontroller" ] - } } } @@ -214,9 +210,6 @@ if (current_toolchain != "${dir_pw_toolchain}/default:default") { data_deps = [ "${chip_root}/examples/chip-tool" ] if (chip_enable_python_modules) { - if (enable_pylib) { - data_deps += [ "${chip_root}/src/pybindings/pycontroller" ] - } data_deps += [ "${chip_root}/src/controller/python:chip-repl" ] } diff --git a/config/beken/BUILD.gn b/config/beken/BUILD.gn index 3a0de665887e0b..35e5175a89f7cd 100644 --- a/config/beken/BUILD.gn +++ b/config/beken/BUILD.gn @@ -21,10 +21,7 @@ import("//build_overrides/chip.gni") #import("${chip_root}/build/chip/tests.gni") group("beken") { - deps = [ - "${chip_root}/examples/lighting-app/beken:MatterApp", - "${chip_root}/src/lib", - ] + deps = [ "${chip_root}/src/lib" ] } group("default") { deps = [ ":beken" ] diff --git a/config/esp32/components/chip/CMakeLists.txt b/config/esp32/components/chip/CMakeLists.txt index 7929e8bbbd14aa..7e9894a8d66065 100644 --- a/config/esp32/components/chip/CMakeLists.txt +++ b/config/esp32/components/chip/CMakeLists.txt @@ -467,6 +467,13 @@ if(NOT CONFIG_USE_MINIMAL_MDNS) endif() endif() +if(CONFIG_OPENTHREAD_BORDER_ROUTER) + idf_component_get_property(rcp_update_lib espressif__esp_rcp_update COMPONENT_LIB) + list(APPEND chip_libraries $) + idf_component_get_property(serial_flasher_lib espressif__esp-serial-flasher COMPONENT_LIB) + list(APPEND chip_libraries $) +endif() + if (CONFIG_ENABLE_ENCRYPTED_OTA) idf_component_get_property(esp_encrypted_img_lib espressif__esp_encrypted_img COMPONENT_LIB) list(APPEND chip_libraries $) @@ -476,6 +483,12 @@ endif() if (NOT EXECUTABLE_COMPONENT_NAME) set(EXECUTABLE_COMPONENT_NAME "main") endif() + +if (CONFIG_ENABLE_DELTA_OTA) + idf_component_get_property(esp_delta_ota_lib espressif__esp_delta_ota COMPONENT_LIB) + list(APPEND chip_libraries $) +endif() + idf_component_get_property(main_lib ${EXECUTABLE_COMPONENT_NAME} COMPONENT_LIB) list(APPEND chip_libraries $) diff --git a/config/esp32/components/chip/Kconfig b/config/esp32/components/chip/Kconfig index 5cd2700bb972b6..d3f621f98f4024 100644 --- a/config/esp32/components/chip/Kconfig +++ b/config/esp32/components/chip/Kconfig @@ -256,6 +256,15 @@ menu "CHIP Core" help Enable this option to use the pre encrypted OTA image + config ENABLE_DELTA_OTA + bool "Enable delta OTA" + depends on ENABLE_OTA_REQUESTOR + default n + help + Enable this option for delta OTA image updates. + Delta OTA updates allow for smaller, more efficient updates by only + sending the changes between the current and new firmware versions. + config OTA_AUTO_REBOOT_ON_APPLY bool "Reboot the device after applying the OTA image" depends on ENABLE_OTA_REQUESTOR diff --git a/config/esp32/components/chip/idf_component.yml b/config/esp32/components/chip/idf_component.yml index f4b130c7402af5..b56040ea3aaa07 100644 --- a/config/esp32/components/chip/idf_component.yml +++ b/config/esp32/components/chip/idf_component.yml @@ -25,3 +25,14 @@ dependencies: rules: - if: "idf_version >=5.0" - if: "target != esp32h2" + + espressif/esp_rcp_update: + version: "1.0.3" + rules: + - if: "idf_version >=5.0" + + espressif/esp_delta_ota: + version: "^1.1.0" + require: public + rules: + - if: "idf_version >=4.3" diff --git a/config/nxp/chip-cmake-freertos/CMakeLists.txt b/config/nxp/chip-cmake-freertos/CMakeLists.txt new file mode 100644 index 00000000000000..b639e23ff65034 --- /dev/null +++ b/config/nxp/chip-cmake-freertos/CMakeLists.txt @@ -0,0 +1,62 @@ +# +# Copyright (c) 2024 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +include(ExternalProject) + +if(NOT CHIP_ROOT) + get_filename_component(CHIP_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../.. REALPATH) +endif() + +get_filename_component(GN_ROOT_TARGET ${CHIP_ROOT}/config/nxp/chip-gn-freertos REALPATH) + +include(${CHIP_ROOT}/config/nxp/cmake/common.cmake) +include(${CHIP_ROOT}/src/app/chip_data_model.cmake) + +# Prepare compiler flags +matter_add_cflags(${CMAKE_C_FLAGS}) +matter_add_cxxflags(${CMAKE_CXX_FLAGS}) + +matter_get_compiler_flags_from_targets("${CONFIG_CHIP_EXTERNAL_TARGETS}") + +# ============================================================================== +# Generate configuration for CHIP GN build system +# ============================================================================== +matter_add_gn_arg_string("nxp_nvm_component" ${CONFIG_CHIP_NVM_COMPONENT}) +matter_add_gn_arg_string("nxp_platform" ${CONFIG_CHIP_NXP_PLATFORM}) +matter_add_gn_arg("chip_with_factory_data" ${CONFIG_CHIP_FACTORY_DATA}) +matter_add_gn_arg("chip_enable_secure_dac_private_key_storage" ${CONFIG_CHIP_SECURE_DAC_PRIVATE_KEY_STORAGE}) +matter_add_gn_arg("chip_enable_secure_whole_factory_data" ${CONFIG_CHIP_ENABLE_SECURE_WHOLE_FACTORY_DATA}) + +matter_common_gn_args( + DEBUG CONFIG_DEBUG + LIB_SHELL CONFIG_CHIP_LIB_SHELL + LIB_TESTS CONFIG_CHIP_BUILD_TESTS + PROJECT_CONFIG ${CONFIG_CHIP_PROJECT_CONFIG} + PROJECT_CONFIG_INC_DIR ${CONFIG_CHIP_PROJECT_CONFIG_INCLUDE_DIRS} + DEVICE_INFO_EXAMPLE_PROVIDER CONFIG_CHIP_EXAMPLE_DEVICE_INFO_PROVIDER +) + +matter_generate_args_tmp_file() + +# ============================================================================== +# Build chip library +# ============================================================================== +matter_build(chip + LIB_SHELL ${CONFIG_CHIP_LIB_SHELL} + LIB_TESTS ${CONFIG_CHIP_BUILD_TESTS} + DEVICE_INFO_EXAMPLE_PROVIDER ${CONFIG_CHIP_EXAMPLE_DEVICE_INFO_PROVIDER} + GN_DEPENDENCIES ${CONFIG_GN_DEPENDENCIES} +) diff --git a/config/nxp/chip-gn-freertos/.gn b/config/nxp/chip-gn-freertos/.gn new file mode 100644 index 00000000000000..15dde062d89de3 --- /dev/null +++ b/config/nxp/chip-gn-freertos/.gn @@ -0,0 +1,29 @@ +# Copyright (c) 2024 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/build.gni") +import("//build_overrides/chip.gni") + +# The location of the build configuration file. +buildconfig = "//build/config/BUILDCONFIG.gn" + +# CHIP uses angle bracket includes. +check_system_includes = true + +default_args = { + target_cpu = "arm" + target_os = "freertos" + + import("${chip_root}/config/nxp/chip-gn-freertos/args.gni") +} diff --git a/config/nxp/chip-gn-freertos/BUILD.gn b/config/nxp/chip-gn-freertos/BUILD.gn new file mode 100644 index 00000000000000..3c508666c833d1 --- /dev/null +++ b/config/nxp/chip-gn-freertos/BUILD.gn @@ -0,0 +1,42 @@ +# Copyright (c) 2024 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/build.gni") +import("//build_overrides/chip.gni") + +import("${chip_root}/build/chip/tests.gni") + +assert(current_os == "freertos") + +declare_args() { + chip_build_example_providers = false + chip_enable_ethernet = false + chip_malloc_sys_heap = false +} + +group("nxp_freertos") { + 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 = [ ":nxp_freertos" ] +} diff --git a/examples/platform/nxp/k32w/k32w1/BUILD.gn b/config/nxp/chip-gn-freertos/args.gni similarity index 52% rename from examples/platform/nxp/k32w/k32w1/BUILD.gn rename to config/nxp/chip-gn-freertos/args.gni index 5cd2a8b31392c2..be31f22fcbdcf1 100644 --- a/examples/platform/nxp/k32w/k32w1/BUILD.gn +++ b/config/nxp/chip-gn-freertos/args.gni @@ -1,4 +1,4 @@ -# Copyright (c) 2020 Project CHIP Authors +# Copyright (c) 2024 Project CHIP Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,21 +15,17 @@ import("//build_overrides/chip.gni") import("//build_overrides/nxp_sdk.gni") -import("${nxp_sdk_build_root}/nxp_sdk.gni") +nxp_external_sdk = true +nxp_build_matter_standalone_lib = true +chip_device_platform = "nxp" +lwip_platform = "nxp" -import("${nxp_sdk_build_root}/${nxp_sdk_name}/${nxp_sdk_name}.gni") +# project config files +chip_device_project_config_include = "" +chip_project_config_include = "" +chip_inet_project_config_include = "" +chip_system_project_config_include = "" +chip_ble_project_config_include = "" -config("chip_examples_project_config") { - include_dirs = [ - "app/project_include", - "${chip_root}", - ] -} - -source_set("openthread_core_config_k32w1_chip_examples") { - sources = [ "app/project_include/OpenThreadConfig.h" ] - - public_deps = [ "${chip_root}/third_party/openthread/platforms/nxp/k32w/k32w1:openthread_core_config_k32w1" ] - - public_configs = [ ":chip_examples_project_config" ] -} +# mbedtls is built as part of the NXP SDK build process +mbedtls_target = "${nxp_sdk_build_root}:nxp_mbedtls" diff --git a/config/nxp/chip-module/CMakeLists.txt b/config/nxp/chip-module/CMakeLists.txt index 6b8266970dc883..32a85a606c71e0 100644 --- a/config/nxp/chip-module/CMakeLists.txt +++ b/config/nxp/chip-module/CMakeLists.txt @@ -42,12 +42,8 @@ if (NOT CHIP_ROOT) get_filename_component(CHIP_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../.. REALPATH) endif() get_filename_component(GN_ROOT_TARGET ${CHIP_ROOT}/config/nxp/chip-gn REALPATH) -get_filename_component(COMMON_CMAKE_SOURCE_DIR ${CHIP_ROOT}/config/common/cmake REALPATH) -# Get common Cmake sources - -include(${COMMON_CMAKE_SOURCE_DIR}/chip_gn_args.cmake) -include(${COMMON_CMAKE_SOURCE_DIR}/chip_gn.cmake) +include(${CHIP_ROOT}/config/nxp/cmake/common.cmake) # Prepare compiler flags if (CHIP_CFLAGS) @@ -109,30 +105,6 @@ matter_common_gn_args( matter_add_gn_arg_string("zephyr_ar" ${CMAKE_AR}) matter_add_gn_arg_string("zephyr_cc" ${CMAKE_C_COMPILER}) matter_add_gn_arg_string("zephyr_cxx" ${CMAKE_CXX_COMPILER}) -matter_add_gn_arg_bool ("chip_logging" CONFIG_LOG) -matter_add_gn_arg_bool ("chip_enable_openthread" CONFIG_NET_L2_OPENTHREAD) -matter_add_gn_arg_bool ("chip_openthread_ftd" CONFIG_OPENTHREAD_FTD) -matter_add_gn_arg_bool ("chip_config_network_layer_ble" CONFIG_BT) -matter_add_gn_arg_bool ("chip_inet_config_enable_ipv4" CONFIG_CHIP_IPV4) -matter_add_gn_arg_bool ("chip_persist_subscriptions" CONFIG_CHIP_PERSISTENT_SUBSCRIPTIONS) -matter_add_gn_arg_bool ("chip_monolithic_tests" CONFIG_CHIP_BUILD_TESTS) -matter_add_gn_arg_bool ("chip_inet_config_enable_tcp_endpoint" CONFIG_CHIP_BUILD_TESTS) -matter_add_gn_arg_bool ("chip_error_logging" CONFIG_MATTER_LOG_LEVEL GREATER_EQUAL 1) -matter_add_gn_arg_bool ("chip_progress_logging" CONFIG_MATTER_LOG_LEVEL GREATER_EQUAL 3) -matter_add_gn_arg_bool ("chip_detail_logging" CONFIG_MATTER_LOG_LEVEL GREATER_EQUAL 4) -matter_add_gn_arg_bool ("chip_automation_logging" FALSE) -matter_add_gn_arg_bool ("chip_malloc_sys_heap" CONFIG_CHIP_MALLOC_SYS_HEAP) -matter_add_gn_arg_bool ("chip_enable_wifi" CONFIG_CHIP_WIFI) -matter_add_gn_arg_bool ("chip_system_config_provide_statistics" CONFIG_CHIP_STATISTICS) -matter_add_gn_arg_bool ("chip_enable_icd_server" CONFIG_CHIP_ENABLE_ICD_SUPPORT) -matter_add_gn_arg_bool ("enable_eventlist_attribute" TRUE) -matter_add_gn_arg_bool ("chip_enable_ota_requestor" CONFIG_CHIP_OTA_REQUESTOR) - -if(CONFIG_DEBUG) - matter_add_gn_arg_bool("optimize_debug" true) - matter_add_gn_arg_string("optimize_debug_level" "0") - matter_add_gn_arg_string("symbol_level" "2") -endif() if (CONFIG_CHIP_FACTORY_DATA) matter_add_gn_arg_bool("chip_use_transitional_commissionable_data_provider" FALSE) @@ -141,11 +113,6 @@ elseif (CONFIG_CHIP_FACTORY_DATA_CUSTOM_BACKEND) matter_add_gn_arg_bool("chip_use_transitional_commissionable_data_provider" FALSE) endif() -if (CONFIG_CHIP_ROTATING_DEVICE_ID) - matter_add_gn_arg_bool("chip_enable_rotating_device_id" TRUE) - matter_add_gn_arg_bool("chip_enable_additional_data_advertising" TRUE) -endif() - if (CONFIG_NET_L2_OPENTHREAD) matter_add_gn_arg_string("chip_mdns" "platform") elseif(CONFIG_WIFI_NXP) @@ -154,9 +121,6 @@ else() matter_add_gn_arg_string("chip_mdns" "none") endif() -if (CONFIG_CHIP_CRYPTO_PSA) - matter_add_gn_arg_string("chip_crypto" "psa") -endif() # if (BOARD STREQUAL "native_posix") # matter_add_gn_arg_string("target_cpu" "x86") @@ -164,10 +128,6 @@ endif() # matter_add_gn_arg_string("target_cpu" "x64") # endif() -if (NOT CONFIG_CHIP_DEBUG_SYMBOLS) - matter_add_gn_arg_string("symbol_level" "0") -endif() - # if (CHIP_COMPILER_LAUNCHER) # matter_add_gn_arg_string("pw_command_launcher" ${CHIP_COMPILER_LAUNCHER}) # endif() diff --git a/config/nxp/cmake/common.cmake b/config/nxp/cmake/common.cmake new file mode 100644 index 00000000000000..8b0f379f502d09 --- /dev/null +++ b/config/nxp/cmake/common.cmake @@ -0,0 +1,69 @@ +# +# Copyright (c) 2024 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# +# @file +# CMake for CHIP library configuration common to NXP platforms +# + +include(${CHIP_ROOT}/config/nxp/chip-module/generate_factory_data.cmake) + +get_filename_component(COMMON_CMAKE_SOURCE_DIR ${CHIP_ROOT}/config/common/cmake REALPATH) + +# Get common Cmake sources +include(${COMMON_CMAKE_SOURCE_DIR}/chip_gn_args.cmake) +include(${COMMON_CMAKE_SOURCE_DIR}/chip_gn.cmake) + +# ============================================================================== +# Generate configuration for CHIP GN build system +# ============================================================================== +matter_add_gn_arg_bool ("chip_logging" CONFIG_LOG) +matter_add_gn_arg_bool ("chip_enable_openthread" CONFIG_NET_L2_OPENTHREAD) +matter_add_gn_arg_bool ("chip_openthread_ftd" CONFIG_OPENTHREAD_FTD) +matter_add_gn_arg_bool ("chip_config_network_layer_ble" CONFIG_BT) +matter_add_gn_arg_bool ("chip_inet_config_enable_ipv4" CONFIG_CHIP_IPV4) +matter_add_gn_arg_bool ("chip_persist_subscriptions" CONFIG_CHIP_PERSISTENT_SUBSCRIPTIONS) +matter_add_gn_arg_bool ("chip_monolithic_tests" CONFIG_CHIP_BUILD_TESTS) +matter_add_gn_arg_bool ("chip_inet_config_enable_tcp_endpoint" CONFIG_CHIP_BUILD_TESTS) +matter_add_gn_arg_bool ("chip_error_logging" CONFIG_MATTER_LOG_LEVEL GREATER_EQUAL 1) +matter_add_gn_arg_bool ("chip_progress_logging" CONFIG_MATTER_LOG_LEVEL GREATER_EQUAL 3) +matter_add_gn_arg_bool ("chip_detail_logging" CONFIG_MATTER_LOG_LEVEL GREATER_EQUAL 4) +matter_add_gn_arg_bool ("chip_automation_logging" FALSE) +matter_add_gn_arg_bool ("chip_malloc_sys_heap" CONFIG_CHIP_MALLOC_SYS_HEAP) +matter_add_gn_arg_bool ("chip_enable_wifi" CONFIG_CHIP_WIFI) +matter_add_gn_arg_bool ("chip_system_config_provide_statistics" CONFIG_CHIP_STATISTICS) +matter_add_gn_arg_bool ("chip_enable_icd_server" CONFIG_CHIP_ENABLE_ICD_SUPPORT) +matter_add_gn_arg_bool ("enable_eventlist_attribute" TRUE) +matter_add_gn_arg_bool ("chip_enable_ota_requestor" CONFIG_CHIP_OTA_REQUESTOR) + +if(CONFIG_DEBUG) + matter_add_gn_arg_bool("optimize_debug" true) + matter_add_gn_arg_string("optimize_debug_level" "0") + matter_add_gn_arg_string("symbol_level" "2") +endif() + +if (CONFIG_CHIP_ROTATING_DEVICE_ID) + matter_add_gn_arg_bool("chip_enable_rotating_device_id" TRUE) + matter_add_gn_arg_bool("chip_enable_additional_data_advertising" TRUE) +endif() + +if (CONFIG_CHIP_CRYPTO_PSA) + matter_add_gn_arg_string("chip_crypto" "psa") +endif() + +if (NOT CONFIG_CHIP_DEBUG_SYMBOLS) + matter_add_gn_arg_string("symbol_level" "0") +endif() diff --git a/config/telink/chip-module/CMakeLists.txt b/config/telink/chip-module/CMakeLists.txt index f8986e7a954fb4..7b58f5c4b6fc05 100644 --- a/config/telink/chip-module/CMakeLists.txt +++ b/config/telink/chip-module/CMakeLists.txt @@ -125,7 +125,7 @@ if (CONFIG_CHIP_ROTATING_DEVICE_ID) matter_add_gn_arg_bool("chip_enable_additional_data_advertising" TRUE) endif() -if(CONFIG_WIFI_W91) +if (CONFIG_WIFI_W91) matter_add_gn_arg_string("chip_mdns" "minimal") elseif (CONFIG_NET_L2_OPENTHREAD) matter_add_gn_arg_string("chip_mdns" "platform") @@ -160,12 +160,11 @@ include(${TELINK_COMMON}/common.cmake) set(BLOCK_SIZE "1024") -# get code-partition mcuboot_partition size -dt_nodelabel(dts_partition_path NODELABEL "boot_partition") -dt_reg_size(mcuboot_size PATH ${dts_partition_path}) -math(EXPR boot_blocks "${mcuboot_size} / ${BLOCK_SIZE}" OUTPUT_FORMAT DECIMAL) - if (CONFIG_BOOTLOADER_MCUBOOT) + dt_nodelabel(dts_partition_path NODELABEL "boot_partition") + dt_reg_size(mcuboot_size PATH ${dts_partition_path}) + math(EXPR boot_blocks "${mcuboot_size} / ${BLOCK_SIZE}" OUTPUT_FORMAT DECIMAL) + add_custom_target(build_mcuboot ALL COMMAND west build -b ${BASE_BOARD} -d build_mcuboot ${ZEPHYR_BASE}/../bootloader/mcuboot/boot/zephyr @@ -183,31 +182,30 @@ if (CONFIG_BOOTLOADER_MCUBOOT) add_dependencies(merge_mcuboot ${ZEPHYR_FINAL_EXECUTABLE}) -if (CONFIG_CHIP_OTA_IMAGE_BUILD) - chip_ota_image(chip-ota-image - INPUT_FILES ${PROJECT_BINARY_DIR}/zephyr.signed.bin - OUTPUT_FILE ${PROJECT_BINARY_DIR}/zephyr-ota.bin - ) + if (CONFIG_CHIP_OTA_IMAGE_BUILD) + chip_ota_image(chip-ota-image + INPUT_FILES ${PROJECT_BINARY_DIR}/zephyr.signed.bin + OUTPUT_FILE ${PROJECT_BINARY_DIR}/zephyr-ota.bin + ) - add_dependencies(chip-ota-image ${ZEPHYR_FINAL_EXECUTABLE}) -endif() + add_dependencies(chip-ota-image ${ZEPHYR_FINAL_EXECUTABLE}) + endif() endif() -# get code-partition factory_partition address -dt_nodelabel(dts_partition_path NODELABEL "factory_partition") -dt_reg_addr(factory_size PATH ${dts_partition_path}) -math(EXPR factory_blocks "${factory_size} / ${BLOCK_SIZE}" OUTPUT_FORMAT DECIMAL) - if (CONFIG_CHIP_FACTORY_DATA_MERGE_WITH_FIRMWARE) - add_custom_target(merge_factory_data ALL - COMMAND - dd if=${PROJECT_BINARY_DIR}/factory/factory_data.bin of=${PROJECT_BINARY_DIR}/zephyr.bin bs=${BLOCK_SIZE} seek=${factory_blocks} - ) - if (CONFIG_CHIP_OTA_IMAGE_BUILD) - add_dependencies(merge_factory_data merge_mcuboot) - else() - add_dependencies(merge_factory_data ${ZEPHYR_FINAL_EXECUTABLE}) - endif() + dt_nodelabel(dts_partition_path NODELABEL "factory_partition") + dt_reg_addr(factory_size PATH ${dts_partition_path}) + math(EXPR factory_blocks "${factory_size} / ${BLOCK_SIZE}" OUTPUT_FORMAT DECIMAL) + + add_custom_target(merge_factory_data ALL + COMMAND + dd if=${PROJECT_BINARY_DIR}/factory/factory_data.bin of=${PROJECT_BINARY_DIR}/zephyr.bin bs=${BLOCK_SIZE} seek=${factory_blocks} + ) + if (CONFIG_CHIP_OTA_IMAGE_BUILD) + add_dependencies(merge_factory_data merge_mcuboot) + else() + add_dependencies(merge_factory_data ${ZEPHYR_FINAL_EXECUTABLE}) + endif() endif() # ============================================================================== @@ -218,4 +216,27 @@ if (CONFIG_CHIP_FACTORY_DATA_BUILD) telink_generate_factory_data() endif() +if (CONFIG_SOC_SERIES_RISCV_TELINK_W91 AND CONFIG_TELINK_W91_FETCH_N22_BIN) + dt_nodelabel(flash_path NODELABEL "flash") + dt_reg_size(flash_size PATH ${flash_path}) + math(EXPR flash_blocks "${flash_size} / ${BLOCK_SIZE}" OUTPUT_FORMAT DECIMAL) + + add_custom_target(merge_n22 ALL + COMMAND + [ -f ${PROJECT_BINARY_DIR}/n22.bin ] && ( + dd if=/dev/zero bs=${BLOCK_SIZE} count=${flash_blocks} | tr '\\000' '\\377' > ${PROJECT_BINARY_DIR}/merged.bin && + dd if=${PROJECT_BINARY_DIR}/zephyr.bin of=${PROJECT_BINARY_DIR}/merged.bin conv=notrunc && + dd if=${PROJECT_BINARY_DIR}/n22.bin of=${PROJECT_BINARY_DIR}/merged.bin bs=${BLOCK_SIZE} seek=${flash_blocks} conv=notrunc + ) || true + ) + + if (CONFIG_CHIP_FACTORY_DATA_MERGE_WITH_FIRMWARE) + add_dependencies(merge_n22 merge_factory_data) + elseif (CONFIG_CHIP_OTA_IMAGE_BUILD) + add_dependencies(merge_n22 merge_mcuboot) + else() + add_dependencies(merge_n22 ${ZEPHYR_FINAL_EXECUTABLE}) + endif() +endif() + endif() # CONFIG_CHIP diff --git a/docs/cluster_and_device_type_dev/cluster_and_device_type_dev.md b/docs/cluster_and_device_type_dev/cluster_and_device_type_dev.md index e016ea78b7b7bf..e2460ff5a0a2b2 100644 --- a/docs/cluster_and_device_type_dev/cluster_and_device_type_dev.md +++ b/docs/cluster_and_device_type_dev/cluster_and_device_type_dev.md @@ -107,9 +107,9 @@ ending in the cluster initialization code. EmberAfInitializeAttributes - ember attribute storage - for all attributes marked as “RAM” in the zap, sets defaults in the storage MatterPluginServerCallback - .h is a generated file, .cpp impl is done -in the server cluster code. Use this to setup the cluster and do attribute -overrides registerAttributeAccessOverride - use this if you want to handle -attribute reads and writes externally +in the server cluster code. Use this to setup the cluster and setup overrides in +chip::app::AttributeAccessInterfaceRegistry::Instance().Register - use this if +you want to handle attribute reads and writes externally Blue sections can be overridden. diff --git a/docs/examples/index.md b/docs/examples/index.md index 446c94f6f61f3b..9dbb0a5aa4e940 100644 --- a/docs/examples/index.md +++ b/docs/examples/index.md @@ -370,3 +370,12 @@ network-manager-app/README lit-icd-app/**/README ``` + +## Thread Border Router example + +```{toctree} +:glob: +:maxdepth: 1 + +thread-br-app/**/README +``` diff --git a/docs/guides/darwin.md b/docs/guides/darwin.md index 2a84067da92ed0..d44e44cc04afd9 100644 --- a/docs/guides/darwin.md +++ b/docs/guides/darwin.md @@ -1,8 +1,21 @@ -# Testing with Apple Devices +# Matter Development and Testing with/on Apple Devices -### Matter is the foundation for connected things. +### Overview + +- To develop a Matter Application, learn more about how to develop with Matter + on Apple's platforms [here](https://developer.apple.com/apple-home/matter/) + + - Additional documentation about the Matter Support API is + [here](https://developer.apple.com/documentation/mattersupport) -Learn more about Matter [here](https://buildwithmatter.com/) +### Filing Issues + +- An issues related to Apple Home, or Development on Apple's Platforms should + be reported using Feedback Assistant as described + [below](#providing-feedback-to-apple) + +- Any issues related to the Matter SDK should be reported to the project + [here](https://github.com/project-chip/connectedhomeip/issues) ## Source Compatibility @@ -12,20 +25,18 @@ changes are present in the release for testing. Listed are the Current SHAs: -- iOS/iPadOS/tvOS 16.1: - [`33f6a910cd9a8a0cfdd7088e2f43efd2f7f566a7`](https://github.com/project-chip/connectedhomeip/commits/33f6a910cd9a8a0cfdd7088e2f43efd2f7f566a7) - -- iOS/iPadOS/tvOS 16.2 and 16.3: - [`c279578c5bc37f117335aa96cec6c5552f070cc0`](https://github.com/project-chip/connectedhomeip/commits/c279578c5bc37f117335aa96cec6c5552f070cc0) +- Latest macOS/tvOS/iOS/iPadOS: + [`2ee90eba27676950fa2f4ef96597d9696f510d5d`](https://github.com/project-chip/connectedhomeip/commits/2ee90eba27676950fa2f4ef96597d9696f510d5d) +- Larger list of SHAs are [here](#release-to-sha-mappings) ## Supported Platforms for Matter Device Testing - Matter is supported by iOS/tvOS/iPadOS/watchOS/HomePod/AppleTV starting with 16.1 - - To test your Matter device with Apple's platforms, all you need is a device with a supported OS -- Pairing via QR Code or Setup Code is supported directly from the Home App +- Pairing via QR Code or Setup Code is supported directly from the Home App, + or any third party Application - Please proceed to [this section](#testing-your-matter-device-with-apple-home) if you're developing a new device @@ -46,14 +57,6 @@ For Context: This is a mapping of platform to OS - HomePod _(tvOS)_ - Apple Watch _(watchOS)_ -### Overview - -- To develop a Matter Application, learn more about how to develop with Matter - on Apple's platforms [here](https://developer.apple.com/apple-home/matter/) - - - Additional documentation about the Matter Support API is - [here](https://developer.apple.com/documentation/mattersupport) - ### Setup Requirements for Application Development - Devices must support BLE pairing, and have it enabled @@ -122,9 +125,7 @@ For Context: This is a mapping of platform to OS ### Enable Developer Mode on your Apple Device -##### Note: Developer mode is a great way to get logs from your device as well as - -enables other useful developer tools +##### Note: Developer mode is a great way to get logs from your device as well as enable other useful developer tools To enable developer mode, please follow the instructions [here](https://developer.apple.com/documentation/xcode/enabling-developer-mode-on-a-device) @@ -137,30 +138,96 @@ chip-tool will require installing the on MacOS or iOS/iPadOS. - Download the Bluetooth Central Matter Client Developer Mode profile and - install it on a iOS/iPadOS 16.1 beta 3 and MacOS 13.1 beta 3 or later - system. + install it on a supported system. - For _macOS_, Profile can be installed via Settings->Privacy & Security->Profiles - For _iOS/iPadOS_, If necessary, email the profile or use AirDrop to - transfer the profile to the _iOS/iPadOS 16 beta 3_ device. + transfer the profile to the _iOS/iPadOS_ device. - Restart your system - For _iOS/iPadOS_, enable Developer Mode. Refer to [this developer page](https://developer.apple.com/documentation/xcode/enabling-developer-mode-on-a-device) - Compile chip-tool for macOS or CHIP Tool for iOS +## Supported Device Types in Apple Home + +##### Note: Not exhaustive, and may be out of date, see [below](#apple-home-development-guide) for more information + +| Type | Decimal | HEX | Notes | +| ----------------------- | ------- | ---- | ------------------------------------------------ | +| On/Off Light | 256 | 0100 | | +| Dimming Light | 257 | 0101 | | +| On/Off Plug-In Unit | 266 | 010A | | +| Dimmable Plug-In Unit | 267 | 010B | | +| On/Off Light Switch | 259 | 0103 | Requires both On/Off Client and Server | +| Dimmer Switch | 260 | 0104 | Requires both On/Off Client and Server | +| Generic Switch (button) | 15 | 000F | Supports momentary switch only, and not latching | +| Contact Sensor | 21 | 0015 | | +| Light Sensor | 262 | 0106 | | +| Occupancy Sensor | 263 | 0107 | | +| Temperature Sensor | 770 | 0302 | | +| Humidity Sensor | 775 | 0307 | | +| Air Quality Sensor | 44 | 002C | | +| Door Lock | 10 | 000A | | +| Window Covering | 514 | 0202 | | +| Heating/Cooling Unit | 768 | 0300 | | +| Thermostat | 769 | 0301 | | +| Fan | 43 | 002B | | +| Air Purifier | 45 | 002D | | +| Temperature Color Light | 268 | 010C | | +| Enhanced Color Light | 269 | 010D | | +| Bridges | 14 | 000E | | +| Robot Vacuum Cleaner | 116 | 0074 | Announced, not yet supported | + +## Additional Device Type Support on Apple's Platforms + +Apple's platforms support all device types available in the Matter SDK, so +developers can use Matter.framework to develop their own applications that can +add devices to Apple Home, or create their own Fabric to manage devices as well. + +Please see documentation about `-[HMAccessory matterNodeID]` +[here](https://developer.apple.com/documentation/homekit/hmaccessory/matternodeid-5zfqo) +which allows you to use Matter.framework to interact with Matter Devices +directly that are paired into Apple Home. + +## Apple Home Development Guide + +Please see [here](https://developer.apple.com/apple-home/) for more general +information about developing an Application or a Device for Apple Home. This +includes information about +[best practices](https://developer.apple.com/apple-home/downloads/Matter-Accessory-Best-Practices-for-Apple-Home.pdf), +[platform developer API](https://developer.apple.com/apple-home/matter/), +[OTA Updates](https://developer.apple.com/accessories/Apple-Matter-OTA-User-Guide.pdf), +general adoption Q&A, and the "Works with Apple Home" badge. + +## General Matter Platform Development Guide + +##### Getting the SDK Ready + +##### Note: Most platforms have very similar, if not the same configuration requirements + +1. Checkout and setup + [Matter repo](https://github.com/project-chip/connectedhomeip.git) as per the + instructions above. +2. Find and edit one of the platform + [examples](https://github.com/project-chip/connectedhomeip/tree/master/examples) + to support the fixed device types above. +3. Read the [platform guides](README.md) on how set up the hardware + - There is a list of more detailed guides [here](#platform-guides) + ## Testing your Matter Device with Apple Home -1. Clone the [Matter repo](https://github.com/project-chip/connectedhomeip.git) +1. Clone the + [Matter repository](https://github.com/project-chip/connectedhomeip.git) 2. Checkout the specific commit hash (from [above](#source-compatibility)) for maximum compatibility with your installed release: - - Example command for SHA `c279578c5bc37f117335aa96cec6c5552f070cc0`: - `$ git checkout c279578c5bc37f117335aa96cec6c5552f070cc0` + - Example command for SHA `2ee90eba27676950fa2f4ef96597d9696f510d5d`: + `$ git checkout 2ee90eba27676950fa2f4ef96597d9696f510d5d` -In order to work with iOS/iPadOS/tvOS 16.1 or greater, device types as defined -in the Matter Device Library spec are used to determine accessory categories. -Ensure the right device type is set for each endpoint. +In order to work with iOS/iPadOS/tvOS, device types as defined in the Matter +Device Library spec are used to determine accessory categories. Ensure the right +device type is set for each endpoint. - For the `all-clusters-app` as an example, this can be set in `FIXED_DEVICE_TYPES`, `FIXED_DEVICE_TYPE_OFFSETS`, and @@ -190,29 +257,11 @@ Example: } ``` -- Supported device types are (not exhaustive): - -| Type | Decimal | HEX | -| ------------------ | ------- | ---- | -| Lightbulb | 256 | 0100 | -| Lightbulb + Dimmer | 257 | 0101 | -| Switch | 259 | 0103 | -| Contact Sensor | 21 | 0015 | -| Door Lock | 10 | 000A | -| Light Sensor | 262 | 0106 | -| Occupancy Sensor | 263 | 0107 | -| Outlet | 266 | 010A | -| Color Bulb | 268 | 010C | -| Window Covering | 514 | 0202 | -| Thermostat | 769 | 0301 | -| Temperature Sensor | 770 | 0302 | -| Flow Sensor | 774 | 0306 | - -#### Examples of how to setup devices +### Examples of how to setup devices ##### Case study 1: Configuring a development M5Stack, as a multi-device to work with iOS/iPadOS/tvOS -##### Note: These instructions are specific to getting started with the (Matter-provided) `all-clusters-app` on an ESP32-based M5Stack, however can be generalised to work on most platforms ([more listed below](#guides)) +##### Note: These instructions are specific to getting started with the (Matter-provided) `all-clusters-app` on an ESP32-based M5Stack, however can be generalised to work on most platforms ([more listed below](#platform-guides)) 1. Checkout and setup [Matter repo](https://github.com/project-chip/connectedhomeip.git) as per the @@ -235,21 +284,7 @@ Example: initialize your development environment, compile the firmware and flash your hardware. -#### General Matter Platform Development Guide - -##### Getting the SDK Ready - -##### Note: Most platforms have very similar, if not the same configuration requirements - -1. Checkout and setup - [Matter repo](https://github.com/project-chip/connectedhomeip.git) as per the - instructions above. -2. Find and edit one of the platform - [examples](https://github.com/project-chip/connectedhomeip/tree/master/examples) - to support the fixed device types above. -3. Read the [platform guides](README.md) on how set up the hardware - -##### Guides +### Platform Guides - [Bouffalo Lab](/examples/lighting-app/bouffalolab/README.md) - [EFR32 Window Covering](/examples/window-app/silabs/README.md) @@ -300,26 +335,20 @@ Example: - [Apple Home Profile](https://developer.apple.com/bug-reporting/profiles-and-logs/?platform=tvos&name=homekit) - [Network Profile](https://developer.apple.com/bug-reporting/profiles-and-logs/?platform=tvos&name=network) - [mDNS Profile](https://developer.apple.com/bug-reporting/profiles-and-logs/?platform=tvos&name=mdns) - -### Release Notes & Known Issues - -- Please refer to the iOS/iPadOS 16.1 - [Release Notes](https://developer.apple.com/documentation/ios-ipados-release-notes/ios-16_1-release-notes) - for currently known issues. -- Please refer to the iOS/iPadOS 16.2 - [Release Notes](https://developer.apple.com/documentation/ios-ipados-release-notes/ios-ipados-16_2-release-notes) - for currently known issues -- Please refer to the iOS & iPadOS 16.3 - [Release Notes](https://developer.apple.com/documentation/ios-ipados-release-notes/ios-ipados-16_3-release-notes) - for currently known issues -- Please refer to the iOS & iPadOS 16.4 - [Release Notes](https://developer.apple.com/documentation/ios-ipados-release-notes/ios-ipados-16_4-release-notes) - for currently known issues -- Please refer to the iOS & iPadOS 16.5 - [Release Notes](https://developer.apple.com/documentation/ios-ipados-release-notes/ios-ipados-16_5-release-notes) - for currently known issues -- An issues related to Apple Home integration should be reported - [feedback](#providing-feedback-to-apple) as described in this section - -- Any issues related to the Matter SDK should be reported to the project - [here](https://github.com/project-chip/connectedhomeip/issues) + - Any Thread device: + [Thread Profile](https://developer.apple.com/bug-reporting/profiles-and-logs/?name=HomeThread) + +### Release to SHA Mappings + +| Platform | Release Version | SHA | +| -------- | --------------- | ------------------------------------------ | +| iOS | 17.6.1 | `2ee90eba27676950fa2f4ef96597d9696f510d5d` | +| iPadOS | 17.6.1 | `2ee90eba27676950fa2f4ef96597d9696f510d5d` | +| tvOS | 17.6 | `2ee90eba27676950fa2f4ef96597d9696f510d5d` | +| macOS | 14.6.1 | `2ee90eba27676950fa2f4ef96597d9696f510d5d` | +| iOS | 17.5.1 | `d09b5ac98f4d7d8b9f2c307f55ab5462576623a5` | +| iPadOS | 17.5.1 | `d09b5ac98f4d7d8b9f2c307f55ab5462576623a5` | +| tvOS | 17.5.1 | `d09b5ac98f4d7d8b9f2c307f55ab5462576623a5` | +| macOS | 14.5 | `d09b5ac98f4d7d8b9f2c307f55ab5462576623a5` | +| iOS | 16.7.8 | `83f7a2fe136e0b746db09f1d19e36c693a634b66` | +| iPadOS | 16.7.8 | `83f7a2fe136e0b746db09f1d19e36c693a634b66` | diff --git a/docs/guides/esp32/build_app_and_commission.md b/docs/guides/esp32/build_app_and_commission.md index 959a0e90173c74..942cb6add83bdc 100644 --- a/docs/guides/esp32/build_app_and_commission.md +++ b/docs/guides/esp32/build_app_and_commission.md @@ -168,9 +168,9 @@ $ out/debug/chip-tool pairing ble-wifi 12345 MY_SSID MY_PASSWORD 20202021 3840 #### Commissioning the Thread device (ESP32H2) - For ESP32-H2, firstly start OpenThread Border Router, you can either use - [Raspberry Pi OpenThread Border Router](https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/openthread_border_router_pi.md) + [Raspberry Pi OpenThread Border Router](../openthread_border_router_pi.md) OR - [ESP32 OpenThread Border Router](https://github.com/espressif/esp-idf/tree/master/examples/openthread/ot_br) + [ESP32 OpenThread Border Router](../../../examples/thread-br-app/esp32/README.md) - Get the active operational dataset. diff --git a/docs/guides/esp32/ota.md b/docs/guides/esp32/ota.md index 7c9c388b422cb9..ae43e09bc08264 100644 --- a/docs/guides/esp32/ota.md +++ b/docs/guides/esp32/ota.md @@ -121,3 +121,66 @@ Please follow the steps below to generate an application image for OTA upgrades: ``` 3. Use the `lighting-app-encrypted-ota.bin` file with the OTA Provider app. + +## Delta OTA + +Delta OTA Updates is a feature that enables Over-the-Air (OTA) firmware update +with compressed delta binaries. Patch files have smaller size than the original +firmware file, which reduces the time and network usage to download the file +from the server. Also, no additional storage partition is required for the +"patch". + +### Firmware Changes + +- Enable configuration options for OTA requestor and Delta OTA: + + ``` + CONFIG_ENABLE_OTA_REQUESTOR=y + CONFIG_ENABLE_DELTA_OTA=y + ``` + +Please follow the steps below to generate an application image for OTA upgrades: + +1. Delta binary needs to be generated using binary delta encoding in Python + 3.6+. You can install `detools` using the following command. + + ``` + pip install detools>=0.49.0 + ``` + +2. Generate delta binary. + + ``` + python managed_components/espressif__esp_delta_ota/examples/https_delta_ota/tools/esp_delta_ota_patch_gen.py --chip --base_binary --new_binary --patch_file_name + ``` + +3. Append the Matter OTA header: + `src/app/ota_image_tool.py create --vendor-id 0xFFF1 --product-id 0x8000 --version 2 --version-str "v2.0" -da sha256 lighting-app-delta-ota.bin` + +4. Use the `lighting-app-delta-ota.bin` file with the OTA Provider app. + +## Encrypted Delta OTA + +To use encrypted delta OTA, follow the below steps. + +### Firmware Changes + +- Enable configuration options for OTA requestor, Delta OTA and Encrypted OTA: + + ``` + CONFIG_ENABLE_OTA_REQUESTOR=y + CONFIG_ENABLE_DELTA_OTA=y + CONFIG_ENABLE_ENCRYPTED_OTA=y + ``` + +1. Follow the step of `Generate a new RSA-3072 key pair or use an existing one` + of + [Encrypted OTA](https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/esp32/ota.md#encrypted-ota) + to build your binary. + +2. Create delta binary as shown in `Generate delta binary` of + [Delta OTA](https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/esp32/ota.md#delta-ota) + +3. Encrypt the application binary. + +4. Append the Matter OTA header. diff --git a/docs/guides/fabric_synchronization_guide.md b/docs/guides/fabric_synchronization_guide.md index 1b545ce36ead27..b2cfd26d9f439e 100644 --- a/docs/guides/fabric_synchronization_guide.md +++ b/docs/guides/fabric_synchronization_guide.md @@ -2,7 +2,9 @@ - [Fabric Synchronization Guide](#fabric-synchronization-guide) - [Fabric Sync Example Applications](#fabric-sync-example-applications) - - [Run Fabric Sync Demo on RP4](#run-fabric-sync-demo-on-rp4) + - [Bootstrap Fabric Sync Demo on Linux](#bootstrap-fabric-sync-demo-on-linux) + - [Bootstrap Fabric Sync Demo on RP4](#bootstrap-fabric-sync-demo-on-rp4) + - [Run Fabric Sync Demo](#run-fabric-sync-demo) ## Fabric Sync Example Applications @@ -38,27 +40,29 @@ enables a seamless and efficient synchronization process. [Fabric-Bridge](https://github.com/project-chip/connectedhomeip/tree/master/examples/fabric-bridge-app/linux/README.md) -## Run Fabric Sync Demo on RP4 +## Bootstrap Fabric Sync Demo on Linux -### Setup Fabric Source +### Start Fabric Synchronization on Ecosystem 1 -Connect to the Fabric Source server: +Run the Fabric Synchronization script: ``` -ssh ubuntu@xxx.xxx.xxx.xxx +./examples/fabric-admin/scripts/run_fabric_sync.sh ``` -Password: +### Start Fabric Synchronization on Ecosystem 2 -Run the Fabric Source script: +Run the Fabric Synchronization script: ``` -./run_fabric_source.sh +./examples/fabric-admin/scripts/run_fabric_sync.sh ``` -### Setup Fabric Sink +## Bootstrap Fabric Sync Demo on RP4 -Connect to the Fabric Sink server: +### Start Fabric Synchronization on Ecosystem 1 + +Connect to the Ecosystem 1 server: ``` ssh ubuntu@xxx.xxx.xxx.xxx @@ -66,29 +70,41 @@ ssh ubuntu@xxx.xxx.xxx.xxx Password: -Run the Fabric Sink script: +Run the Fabric Synchronization script: ``` -./run_fabric_sink.sh +./run_fabric_sync.sh ``` -### Fabric Sync Setup +### Start Fabric Synchronization on Ecosystem 2 + +Connect to the Ecosystem 2 server: + +``` +ssh ubuntu@xxx.xxx.xxx.xxx +``` -Enable Fabric Auto Sync: +Password: -In Fabric-Sync console: +Run the Fabric Synchronization script: ``` -fabricsync enable-auto-sync 1 +./run_fabric_sync.sh ``` -Pair the Fabric-Source bridge to Fabric-Sync with node ID 1: +## Run Fabric Sync Demo + +### Fabric Sync Setup + +In Ecosystem 1 Fabric-Admin console: + +Pair the Ecosystem 2 bridge to Ecosystem 1 with node ID 2: ``` -fabricsync add-bridge 1 +fabricsync add-bridge 2 ``` -### Pair Light Example to Fabric-Source +### Pair Light Example to Ecosystem 2 Since Fabric-Bridge also functions as a Matter server, running it alongside the Light Example app on the same machine would cause conflicts. Therefore, you need @@ -114,26 +130,47 @@ Pair the Light Example with node ID 3 using its payload number: pairing already-discovered 3 20202021 5540 ``` -After the Light Example is successfully paired in Fabric-Source, it will be -synced to Fabric-Sink with a new assigned node ID. +After the device is successfully added, you will observe the following on +Ecosystem 2 with the newly assigned Node ID: + +``` +>>> New device with Node ID: 0x3 has been successfully added. +``` + +Additionally, you should also get notified when a new device is added to +Ecosystem 2 from the Ecosystem 1: + +``` +>>> A new device is added on Endpoint 3. +``` + +### Synchronize Light Example to Ecosystem 1 + +After the Light Example is successfully paired in Ecosystem 2, we can start to +synchronize the light device to Ecosystem 1 using the new assigned dynamic +endpointid on Ecosystem 2. + +``` +fabricsync sync-device +``` Toggle the Light Example: -From Fabric-Source: +From Ecosystem 1: ``` onoff on 1 onoff off 1 ``` -From Fabric-Sink: (Use the node ID assigned) +From Ecosystem 2: (Use the node ID assigned) ``` onoff on x 1 onoff off x 1 ``` -### Remove Light Example from Fabric-Source +### Remove Light Example from Ecosystem Unpair the Light Example: @@ -141,9 +178,6 @@ Unpair the Light Example: pairing unpair ``` -After the Light Example is successfully unpaired from Fabric-Source, it will -also be removed from the Fabric-Sink. - ### Pair Commercial Switch to Fabric-Source Pair the switch using its payload number: @@ -154,32 +188,36 @@ In Fabric-Source console: pairing code-wifi ``` -After the switch is successfully paired in Fabric-Source, it will be synced to -Fabric-Sink with a new assigned node ID. +### Synchronize Switch to Ecosystem 1 + +After the switch is successfully paired in Ecosystem 2, we can start to +synchronize it to Ecosystem 1 using the new assigned dynamic endpointid on +Ecosystem 2.. + +``` +fabricsync sync-device +``` Toggle the switch: -From Fabric-Source: +From Ecosystem 1: ``` onoff on 1 onoff off 1 ``` -From Fabric-Sink: (Use the node ID assigned) +From Ecosystem 2: (Use the node ID assigned) ``` onoff on 1 onoff off 1 ``` -### Remove Switch from Fabric-Source +### Remove Switch from Ecosystem Unpair the switch: ``` pairing unpair ``` - -After the switch is successfully unpaired from Fabric-Source, it will also be -removed from the Fabric-Sink. diff --git a/docs/guides/mbedos_add_new_target.md b/docs/guides/mbedos_add_new_target.md index 8ea7c35c7049d2..ef9b7c403249eb 100644 --- a/docs/guides/mbedos_add_new_target.md +++ b/docs/guides/mbedos_add_new_target.md @@ -2,6 +2,8 @@ # Mbed-OS add new hardware target +### WARNING, MbedOS is deprecated and support for it will be removed from the connectedhomeip project + ## Overview This document shows how to add the new Mbed OS hardware target to Matter diff --git a/docs/testing/yaml_schema.md b/docs/testing/yaml_schema.md index 8a4846bde5e4f1..292da55e0cd728 100644 --- a/docs/testing/yaml_schema.md +++ b/docs/testing/yaml_schema.md @@ -62,6 +62,7 @@ YAML schema |      hasMasksClear |list|| |      notValue |NoneType,bool,int,float,list,dict|Y| |      anyOf |list|| +|      python |str|Y| |    saveAs |str|| |    saveDataVersschemaionAs |str|| |  saveResponseAs |str|| diff --git a/docs/upgrading.md b/docs/upgrading.md index 9a8c68987bec3b..5640c925aca5ec 100644 --- a/docs/upgrading.md +++ b/docs/upgrading.md @@ -69,10 +69,26 @@ independent of the InteractionModelEngine class. The following replacements exist: - `chip::app::InteractionModelEngine::RegisterCommandHandler` replaced by - `chip::app::CommandHandlerInterfaceRegistry::RegisterCommandHandler` + `chip::app::CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler` - `chip::app::InteractionModelEngine::UnregisterCommandHandler` replaced by - `chip::app::CommandHandlerInterfaceRegistry::UnregisterCommandHandler` + `chip::app::CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler` - `chip::app::InteractionModelEngine::FindCommandHandler` replaced by - `chip::app::CommandHandlerInterfaceRegistry::GetCommandHandler` + `chip::app::CommandHandlerInterfaceRegistry::Instance().GetCommandHandler` - `chip::app::InteractionModelEngine::UnregisterCommandHandlers` replaced by - `chip::app::CommandHandlerInterfaceRegistry::UnregisterAllCommandHandlersForEndpoint` + `chip::app::CommandHandlerInterfaceRegistry::Instance().UnregisterAllCommandHandlersForEndpoint` + +### AttributeAccessInterface registration and removal + +A new object exists for the attribute access interface registry, accessible as +`chip::app::AttributeHandlerInterfaceRegistry::Instance()` + +Replacements for methods are: + +- `registerAttributeAccessOverride` replaced by + `chip::app::AttributeAccessInterfaceRegistry::Instance().Register` +- `unregisterAttributeAccessOverride` replaced by + `chip::app::AttributeAccessInterfaceRegistry::Instance().Unregister` +- `unregisterAllAttributeAccessOverridesForEndpoint` replaced by + `chip::app::AttributeAccessInterfaceRegistry::Instance().UnregisterAllForEndpoint` +- `chip::app::GetAttributeAccessOverride` replaced by + `chip::app::AttributeAccessInterfaceRegistry::Instance().Get` 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 76c150be26d933..46debb8a6cd363 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 @@ -4386,7 +4386,7 @@ cluster ElectricalEnergyMeasurement = 145 { /** This cluster is used to allow clients to control the operation of a hot water heating appliance so that it can be used with energy management. */ provisional cluster WaterHeaterManagement = 148 { - revision 1; + revision 2; enum BoostStateEnum : enum8 { kInactive = 0; @@ -4398,7 +4398,7 @@ provisional cluster WaterHeaterManagement = 148 { kTankPercent = 0x2; } - bitmap WaterHeaterDemandBitmap : bitmap8 { + bitmap WaterHeaterHeatSourceBitmap : bitmap8 { kImmersionElement1 = 0x1; kImmersionElement2 = 0x2; kHeatPump = 0x4; @@ -4406,16 +4406,24 @@ provisional cluster WaterHeaterManagement = 148 { kOther = 0x10; } - bitmap WaterHeaterTypeBitmap : bitmap8 { - kImmersionElement1 = 0x1; - kImmersionElement2 = 0x2; - kHeatPump = 0x4; - kBoiler = 0x8; - kOther = 0x10; + struct WaterHeaterBoostInfoStruct { + elapsed_s duration = 0; + optional boolean oneShot = 1; + optional boolean emergencyBoost = 2; + optional temperature temporarySetpoint = 3; + optional percent targetPercentage = 4; + optional percent targetReheat = 5; } - readonly attribute WaterHeaterTypeBitmap heaterTypes = 0; - readonly attribute WaterHeaterDemandBitmap heatDemand = 1; + info event BoostStarted = 0 { + WaterHeaterBoostInfoStruct boostInfo = 0; + } + + info event BoostEnded = 1 { + } + + readonly attribute WaterHeaterHeatSourceBitmap heaterTypes = 0; + readonly attribute WaterHeaterHeatSourceBitmap heatDemand = 1; readonly attribute optional int16u tankVolume = 2; readonly attribute optional energy_mwh estimatedHeatRequired = 3; readonly attribute optional percent tankPercentage = 4; @@ -4428,12 +4436,7 @@ provisional cluster WaterHeaterManagement = 148 { readonly attribute int16u clusterRevision = 65533; request struct BoostRequest { - elapsed_s duration = 0; - optional boolean oneShot = 1; - optional boolean emergencyBoost = 2; - optional temperature temporarySetpoint = 3; - optional percent targetPercentage = 4; - optional percent targetReheat = 5; + WaterHeaterBoostInfoStruct boostInfo = 0; } /** Allows a client to request that the water heater is put into a Boost state. */ @@ -9068,7 +9071,7 @@ endpoint 1 { callback attribute eventList; callback attribute attributeList; ram attribute featureMap default = 0x0123; - ram attribute clusterRevision default = 6; + ram attribute clusterRevision default = 7; handle command SetpointRaiseLower; handle command SetActiveScheduleRequest; @@ -9252,10 +9255,10 @@ endpoint 1 { ram attribute occupancy; ram attribute occupancySensorType; ram attribute occupancySensorTypeBitmap default = 1; - ram attribute holdTime default = 10; + callback attribute holdTime; callback attribute holdTimeLimits; ram attribute PIROccupiedToUnoccupiedDelay default = 10; - ram attribute featureMap default = 0x02; + callback attribute featureMap; ram attribute clusterRevision default = 5; } @@ -9730,10 +9733,10 @@ endpoint 2 { ram attribute occupancy; ram attribute occupancySensorType; ram attribute occupancySensorTypeBitmap default = 1; - ram attribute holdTime default = 20; + callback attribute holdTime; callback attribute holdTimeLimits; ram attribute PIROccupiedToUnoccupiedDelay default = 10; - ram attribute featureMap default = 0x02; + callback attribute featureMap; ram attribute clusterRevision default = 5; } } 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 7d0a13ade18778..9a736eea56fa30 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 @@ -16918,7 +16918,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "6", + "defaultValue": "7", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -19196,10 +19196,10 @@ "side": "server", "type": "int16u", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "10", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -19244,10 +19244,10 @@ "side": "server", "type": "bitmap32", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "0x02", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -25353,10 +25353,10 @@ "side": "server", "type": "int16u", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "20", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -25401,10 +25401,10 @@ "side": "server", "type": "bitmap32", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "0x02", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, diff --git a/examples/all-clusters-app/all-clusters-common/include/WhmDelegate.h b/examples/all-clusters-app/all-clusters-common/include/WhmDelegate.h index ad73239e77990d..27d8cd7cd96ecf 100644 --- a/examples/all-clusters-app/all-clusters-common/include/WhmDelegate.h +++ b/examples/all-clusters-app/all-clusters-common/include/WhmDelegate.h @@ -56,30 +56,52 @@ class WaterHeaterManagementDelegate : public WaterHeaterManagement::Delegate *********************************************************************************/ /** - * @brief Delegate should implement a handler to start boosting the water temperature as required. - * Upon receipt, the Water Heater SHALL transition into the BOOST state, which SHALL cause the - * water in the tank (or the TargetPercentage of the water, if included) to be heated towards - * the set point (or the TemporarySetpoint, if included), which in turn may cause a call for heat, - * even if the mode is OFF, or is TIMED and it is during one of the Off periods. + * @brief Delegate should implement a handler to start boosting the water + * temperature as required. Upon receipt, the Water Heater SHALL + * transition into the BOOST state, which SHALL cause the water in + * the tank (or the TargetPercentage of the water, if included) to be + * heated towards the set point (or the TemporarySetpoint, if + * included), which in turn may cause a call for heat, even if the + * mode is OFF, or is TIMED and it is during one of the Off periods. * - * @param duration Indicates the time period in seconds for which the BOOST state is activated before it - * automatically reverts to the previous mode (e.g. OFF, MANUAL or TIMED). - * @param oneShot Indicates whether the BOOST state should be automatically canceled once the hot water has - * first reached the set point temperature (or the TemporarySetpoint temperature, if specified) - * for the TargetPercentage (if specified). - * @param emergencyBoost Indicates that the consumer wants the water to be heated as quickly as practicable. - * This MAY cause multiple heat sources to be activated (e.g. a heat pump and direct - * electric heating element). - * @param temporarySetpoint Indicates the target temperature to which to heat the hot water for this Boost command. - * It SHALL be used instead of the normal set point temperature whilst the BOOST state is active. - * @param targetPercentage If the tank supports the TankPercent feature, this field indicates the amount of water - * that SHALL be heated by this Boost command before the heater is switched off. - * @param targetReheat If the tank supports the TankPercent feature, and the heating by this Boost command has ceased - * because the TargetPercentage of the water in the tank has been heated to the set point (or - * TemporarySetpoint if included), this field indicates the percentage to which the hot water in - * the tank SHALL be allowed to fall before again beginning to reheat it. + * @param duration Indicates the time period in seconds for which + * the BOOST state is activated before it + * automatically reverts to the previous mode + * (e.g. OFF, MANUAL or TIMED). * - * @return Success if the boost command is accepted; otherwise the command SHALL be rejected with appropriate error. + * @param oneShot Indicates whether the BOOST state should be + * automatically canceled once the hot water has + * first reached the set point temperature (or the + * TemporarySetpoint temperature, if specified) + * for the TargetPercentage (if specified). + * + * @param emergencyBoost Indicates that the consumer wants the water to + * be heated as quickly as practicable. This MAY + * cause multiple heat sources to be activated + * (e.g. a heat pump and direct electric heating + * element). + * + * @param temporarySetpoint Indicates the target temperature to which to + * heat the hot water for this Boost command. It + * SHALL be used instead of the normal set point + * temperature whilst the BOOST state is active. + * + * @param targetPercentage If the tank supports the TankPercent feature, + * this field indicates the amount of water that + * SHALL be heated by this Boost command before + * the heater is switched off. + * + * @param targetReheat If the tank supports the TankPercent feature, + * and the heating by this Boost command has + * ceased because the TargetPercentage of the + * water in the tank has been heated to the set + * point (or TemporarySetpoint if included), this + * field indicates the percentage to which the hot + * water in the tank SHALL be allowed to fall + * before again beginning to reheat it. + * + * @return Success if the boost command is accepted; otherwise the command + * SHALL be rejected with appropriate error. */ Protocols::InteractionModel::Status HandleBoost(uint32_t duration, Optional oneShot, Optional emergencyBoost, Optional temporarySetpoint, Optional targetPercentage, @@ -87,8 +109,8 @@ class WaterHeaterManagementDelegate : public WaterHeaterManagement::Delegate /** * @brief Delegate should implement a handler to cancel a boost command. - * Upon receipt, the Water Heater SHALL transition back from the BOOST state to the previous mode - * (e.g. OFF, MANUAL or TIMED). + * Upon receipt, the Water Heater SHALL transition back from the + * BOOST state to the previous mode (e.g. OFF, MANUAL or TIMED). * * @return It should report SUCCESS if successful and FAILURE otherwise. */ @@ -96,8 +118,8 @@ class WaterHeaterManagementDelegate : public WaterHeaterManagement::Delegate // ------------------------------------------------------------------ // Get attribute methods - BitMask GetHeaterTypes() override; - BitMask GetHeatDemand() override; + BitMask GetHeaterTypes() override; + BitMask GetHeatDemand() override; uint16_t GetTankVolume() override; int64_t GetEstimatedHeatRequired() override; Percent GetTankPercentage() override; @@ -105,18 +127,18 @@ class WaterHeaterManagementDelegate : public WaterHeaterManagement::Delegate // ------------------------------------------------------------------ // Set attribute methods - void SetHeaterTypes(BitMask heaterTypes); - void SetHeatDemand(BitMask heatDemand); + void SetHeaterTypes(BitMask heaterTypes); + void SetHeatDemand(BitMask heatDemand); void SetTankVolume(uint16_t tankVolume); void SetEstimatedHeatRequired(int64_t estimatedHeatRequired); void SetTankPercentage(Percent tankPercentage); void SetBoostState(BoostStateEnum boostState); - /********************************************************************************* + /*************************************************************************** * * WaterHeaterManagementDelegate specific methods * - *********************************************************************************/ + ***************************************************************************/ /** * @brief Set the Water Header Mode and act accordingly. @@ -155,36 +177,44 @@ class WaterHeaterManagementDelegate : public WaterHeaterManagement::Delegate void HandleBoostTimerExpiry(); /** - * Determines whether the tank water temperature has reached the target temperature. + * Determines whether the tank water temperature has reached the target + * temperature. * - * @return Returns True is tank water temperature has reached the target temperature, False otherwise. + * @return Returns True is tank water temperature has reached the target + * temperature, False otherwise. */ bool HasWaterTemperatureReachedTarget() const; /** * Simulates water being drawn from the water tank. * - * @param percentageReplaced The % of water being replaced with water with a temperature of replacedWaterTemperature. - * @param replacedWaterTemperature The temperature of the percentageReplaced water. + * @param percentageReplaced The % of water being replaced with water with + * a temperature of replacedWaterTemperature. + * + * @param replacedWaterTemperature The temperature of the + * percentageReplaced water. */ void DrawOffHotWater(chip::Percent percentageReplaced, uint16_t replacedWaterTemperature); private: /** - * @brief Determine whether heating needs to be turned on or off or left as is. + * @brief Determine whether heating needs to be turned on or off or left as + * is. * - * @param heatingOp[out] Set as determined whether heating needs to be turned on/off or left unchanged. + * @param heatingOp[out] Set as determined whether heating needs to be + * turned on/off or left unchanged. * - * @return Success if the heating operation could be determined otherwise returns with appropriate error. + * @return Success if the heating operation could be determined otherwise + * returns with appropriate error. */ Protocols::InteractionModel::Status DetermineIfChangingHeatingState(HeatingOp & heatingOp); private: - /********************************************************************************* + /*************************************************************************** * * WaterHeaterManagementDelegate specific attributes * - *********************************************************************************/ + ***************************************************************************/ // Need the following so can determine which features are supported WaterHeaterManagement::Instance * mpWhmInstance; @@ -203,34 +233,44 @@ class WaterHeaterManagementDelegate : public WaterHeaterManagement::Delegate // Boost command parameters - // This field SHALL indicate whether the BOOST state should be automatically canceled once the hot water has first reached the - // set point temperature (or the TemporarySetpoint temperature, if specified) for the TargetPercentage (if specified). + // This field SHALL indicate whether the BOOST state should be automatically + // canceled once the hot water has first reached the set point temperature + // (or the TemporarySetpoint temperature, if specified) for the + // TargetPercentage (if specified). Optional mBoostOneShot; - // This field indicates that the consumer wants the water to be heated as quickly as practicable. This MAY cause multiple heat - // sources to be activated (e.g. a heat pump and direct electric heating element). + // This field indicates that the consumer wants the water to be heated as + // quickly as practicable. This MAY cause multiple heat sources to be + // activated (e.g. a heat pump and direct electric heating element). Optional mBoostEmergencyBoost; - // This field indicates the target temperature to which to heat the hot water for this Boost command. It SHALL be used instead - // of the normal set point temperature whilst the BOOST state is active. + // This field indicates the target temperature to which to heat the hot + // water for this Boost command. It SHALL be used instead of the normal set + // point temperature whilst the BOOST state is active. Optional mBoostTemporarySetpoint; - // If the tank supports the TankPercent feature, this field indicates the amount of water that SHALL be heated by this Boost - // command before the heater is switched off. This field is optional, however it SHALL be included if the TargetReheat field is - // included. + // If the tank supports the TankPercent feature, this field indicates the + // amount of water that SHALL be heated by this Boost command before the + // heater is switched off. This field is optional, however it SHALL be + // included if the TargetReheat field is included. Optional mBoostTargetPercentage; - // If the tank supports the TankPercent feature, and the heating by this Boost command has ceased because the TargetPercentage - // of the water in the tank has been heated to the set point (or TemporarySetpoint if included), this field indicates the - // percentage to which the hot water in the tank SHALL be allowed to fall before again beginning to reheat it. For example if - // the TargetPercentage was 80%, and the TargetReheat was 40%, then after initial heating to 80% hot water, the tank may have - // hot water drawn off until only 40% hot water remains. At this point the heater will begin to heat back up to 80% of hot - // water. If this field and the OneShot field were both omitted, heating would begin again after any water draw which reduced - // the TankPercentage below 80%. + // If the tank supports the TankPercent feature, and the heating by this + // Boost command has ceased because the TargetPercentage of the water in the + // tank has been heated to the set point (or TemporarySetpoint if included), + // this field indicates the percentage to which the hot water in the tank + // SHALL be allowed to fall before again beginning to reheat it. For example + // if the TargetPercentage was 80%, and the TargetReheat was 40%, then after + // initial heating to 80% hot water, the tank may have hot water drawn off + // until only 40% hot water remains. At this point the heater will begin to + // heat back up to 80% of hot water. If this field and the OneShot field + // were both omitted, heating would begin again after any water draw which + // reduced the TankPercentage below 80%. Optional mBoostTargetReheat; - // Track whether the water temperature has reached the water temperature specified in the boost command. Used in conjunction - // with the boost command boostTargetReheat parameter + // Track whether the water temperature has reached the water temperature + // specified in the boost command. Used in conjunction with the boost + // command boostTargetReheat parameter bool mBoostTargetTemperatureReached; /********************************************************************************* @@ -239,28 +279,35 @@ class WaterHeaterManagementDelegate : public WaterHeaterManagement::Delegate * *********************************************************************************/ - // This attribute SHALL indicate the methods to call for heat that the controller supports. If a bit is set then the controller - // supports the corresponding method. - BitMask mHeaterTypes; + // This attribute SHALL indicate the methods to call for heat that the + // controller supports. If a bit is set then the controller supports the + // corresponding method. + BitMask mHeaterTypes; - // This attribute SHALL indicate if the controller is asking for heat. If a bit is set then the corresponding call for heat is - // active. - BitMask mHeatDemand; + // This attribute SHALL indicate if the controller is asking for heat. If a + // bit is set then the corresponding call for heat is active. + BitMask mHeatDemand; - // This attribute SHALL indicate the volume of water that the hot water tank can hold (in units of Litres). This allows an - // energy management system to estimate the required heating energy needed to reach the target temperature. + // This attribute SHALL indicate the volume of water that the hot water tank + // can hold (in units of Litres). This allows an energy management system to + // estimate the required heating energy needed to reach the target + // temperature. uint16_t mTankVolume; - // This attribute SHALL indicate the estimated heat energy needed to raise the water temperature to the target setpoint. This - // can be computed by taking the specific heat capacity of water (4182 J/kg °C) and by knowing the current temperature of the - // water, the tank volume and target temperature. + // This attribute SHALL indicate the estimated heat energy needed to raise + // the water temperature to the target setpoint. This can be computed by + // taking the specific heat capacity of water (4182 J/kg °C) and by knowing + // the current temperature of the water, the tank volume and target + // temperature. int64_t mEstimatedHeatRequired; - // This attribute SHALL indicate an approximate level of hot water stored in the tank, which may help consumers understand the - // amount of hot water remaining in the tank. + // This attribute SHALL indicate an approximate level of hot water stored in + // the tank, which may help consumers understand the amount of hot water + // remaining in the tank. Percent mTankPercentage; - // This attribute SHALL indicate if the BOOST state, as triggered by a Boost command, is currently active. + // This attribute SHALL indicate if the BOOST state, as triggered by a Boost + // command, is currently active. BoostStateEnum mBoostState; }; diff --git a/examples/all-clusters-app/all-clusters-common/include/WhmManufacturer.h b/examples/all-clusters-app/all-clusters-common/include/WhmManufacturer.h index d51e6a62f2021c..b56aa24abf491f 100644 --- a/examples/all-clusters-app/all-clusters-common/include/WhmManufacturer.h +++ b/examples/all-clusters-app/all-clusters-common/include/WhmManufacturer.h @@ -62,7 +62,7 @@ class WhmManufacturer /** * @brief Called to determine which heating sources to use, */ - BitMask DetermineHeatingSources(); + BitMask DetermineHeatingSources(); /** * @brief Turn the heating of the water tank on. @@ -83,23 +83,44 @@ class WhmManufacturer /** * @brief Called to handle a boost command. * - * @param duration Indicates the time period in seconds for which the BOOST state is activated before it automatically reverts - * to the previous mode (e.g. OFF, MANUAL or TIMED). - * @param oneShot Indicates whether the BOOST state should be automatically canceled once the hot water has first reached the - * set point temperature (or the TemporarySetpoint temperature, if specified) for the TargetPercentage (if - * specified). - * @param emergencyBoost Indicates that the consumer wants the water to be heated as quickly as practicable. This MAY cause - * multiple heat sources to be activated (e.g. a heat pump and direct electric heating element). - * @param temporarySetpoint Indicates the target temperature to which to heat the hot water for this Boost command. It SHALL be - * used instead of the normal set point temperature whilst the BOOST state is active. - * @param targetPercentage If the tank supports the TankPercent feature, this field indicates the amount of water that SHALL be - * heated by this Boost command before the heater is switched off. - * @param targetReheat If the tank supports the TankPercent feature, and the heating by this Boost command has ceased because - * the TargetPercentage of the water in the tank has been heated to the set point (or TemporarySetpoint if - * included), this field indicates the percentage to which the hot water in the tank SHALL be allowed to fall before again - * beginning to reheat it. + * @param duration Indicates the time period in seconds for which + * the BOOST state is activated before it + * automatically reverts to the previous mode + * (e.g. OFF, MANUAL or TIMED). * - * @return Success if the boost command is successful; otherwise return the appropriate error. + * @param oneShot Indicates whether the BOOST state should be + * automatically canceled once the hot water has + * first reached the set point temperature (or the + * TemporarySetpoint temperature, if specified) + * for the TargetPercentage (if specified). + * + * @param emergencyBoost Indicates that the consumer wants the water to + * be heated as quickly as practicable. This MAY + * cause multiple heat sources to be activated + * (e.g. a heat pump and direct electric heating + * element). + * + * @param temporarySetpoint Indicates the target temperature to which to + * heat the hot water for this Boost command. It + * SHALL be used instead of the normal set point + * temperature whilst the BOOST state is active. + * + * @param targetPercentage If the tank supports the TankPercent feature, + * this field indicates the amount of water that + * SHALL be heated by this Boost command before + * the heater is switched off. + * + * @param targetReheat If the tank supports the TankPercent feature, + * and the heating by this Boost command has + * ceased because the TargetPercentage of the + * water in the tank has been heated to the set + * point (or TemporarySetpoint if included), this + * field indicates the percentage to which the hot + * water in the tank SHALL be allowed to fall + * before again beginning to reheat it. + * + * @return Success if the boost command is successful; otherwise return the + * appropriate error. */ Protocols::InteractionModel::Status BoostCommandStarted(uint32_t duration, Optional oneShot, Optional emergencyBoost, Optional temporarySetpoint, diff --git a/examples/all-clusters-app/all-clusters-common/src/WhmDelegateImpl.cpp b/examples/all-clusters-app/all-clusters-common/src/WhmDelegateImpl.cpp index 0568e5c9c7d002..af09a13a0dab2d 100644 --- a/examples/all-clusters-app/all-clusters-common/src/WhmDelegateImpl.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/WhmDelegateImpl.cpp @@ -50,12 +50,12 @@ void WaterHeaterManagementDelegate::SetWhmManufacturer(WhmManufacturer & whmManu * *********************************************************************************/ -BitMask WaterHeaterManagementDelegate::GetHeaterTypes() +BitMask WaterHeaterManagementDelegate::GetHeaterTypes() { return mHeaterTypes; } -BitMask WaterHeaterManagementDelegate::GetHeatDemand() +BitMask WaterHeaterManagementDelegate::GetHeatDemand() { return mHeatDemand; } @@ -80,7 +80,7 @@ BoostStateEnum WaterHeaterManagementDelegate::GetBoostState() return mBoostState; } -void WaterHeaterManagementDelegate::SetHeaterTypes(BitMask heaterTypes) +void WaterHeaterManagementDelegate::SetHeaterTypes(BitMask heaterTypes) { if (mHeaterTypes != heaterTypes) { @@ -90,7 +90,7 @@ void WaterHeaterManagementDelegate::SetHeaterTypes(BitMask heatDemand) +void WaterHeaterManagementDelegate::SetHeatDemand(BitMask heatDemand) { if (mHeatDemand != heatDemand) { diff --git a/examples/all-clusters-app/all-clusters-common/src/WhmManufacturer.cpp b/examples/all-clusters-app/all-clusters-common/src/WhmManufacturer.cpp index dd8452a5c816ca..8865501fcca6fe 100644 --- a/examples/all-clusters-app/all-clusters-common/src/WhmManufacturer.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/WhmManufacturer.cpp @@ -43,8 +43,8 @@ CHIP_ERROR WhmManufacturer::Init() return CHIP_ERROR_UNINITIALIZED; } - dg->SetHeaterTypes(BitMask(WaterHeaterTypeBitmap::kImmersionElement1)); - dg->SetHeatDemand(BitMask(WaterHeaterDemandBitmap::kImmersionElement1)); + dg->SetHeaterTypes(BitMask(WaterHeaterHeatSourceBitmap::kImmersionElement1)); + dg->SetHeatDemand(BitMask(WaterHeaterHeatSourceBitmap::kImmersionElement1)); dg->SetEstimatedHeatRequired(10000); return CHIP_NO_ERROR; @@ -55,36 +55,36 @@ CHIP_ERROR WhmManufacturer::Shutdown() return CHIP_NO_ERROR; } -BitMask WhmManufacturer::DetermineHeatingSources() +BitMask WhmManufacturer::DetermineHeatingSources() { WaterHeaterManagementDelegate * dg = GetWhmManufacturer()->GetWhmDelegate(); if (dg == nullptr) { ChipLogError(AppServer, "WhmDelegate is not initialized"); - return BitMask(0); + return BitMask(0); } // A list of valid heaterTypes uint8_t waterHeaterTypeValues[] = { - static_cast(WaterHeaterTypeBitmap::kImmersionElement1), - static_cast(WaterHeaterTypeBitmap::kImmersionElement2), - static_cast(WaterHeaterTypeBitmap::kHeatPump), - static_cast(WaterHeaterTypeBitmap::kBoiler), - static_cast(WaterHeaterTypeBitmap::kOther), + static_cast(WaterHeaterHeatSourceBitmap::kImmersionElement1), + static_cast(WaterHeaterHeatSourceBitmap::kImmersionElement2), + static_cast(WaterHeaterHeatSourceBitmap::kHeatPump), + static_cast(WaterHeaterHeatSourceBitmap::kBoiler), + static_cast(WaterHeaterHeatSourceBitmap::kOther), }; // The corresponding list of valid headerDemands uint8_t waterHeaterDemandValues[] = { - static_cast(WaterHeaterDemandBitmap::kImmersionElement1), - static_cast(WaterHeaterDemandBitmap::kImmersionElement2), - static_cast(WaterHeaterDemandBitmap::kHeatPump), - static_cast(WaterHeaterDemandBitmap::kBoiler), - static_cast(WaterHeaterDemandBitmap::kOther), + static_cast(WaterHeaterHeatSourceBitmap::kImmersionElement1), + static_cast(WaterHeaterHeatSourceBitmap::kImmersionElement2), + static_cast(WaterHeaterHeatSourceBitmap::kHeatPump), + static_cast(WaterHeaterHeatSourceBitmap::kBoiler), + static_cast(WaterHeaterHeatSourceBitmap::kOther), }; // Iterate across the valid waterHeaterTypes seeing which heating sources are available based on heaterTypes. // Set the corresponding bit in the heaterDemand bitmap. - BitMask heaterTypes = dg->GetHeaterTypes(); + BitMask heaterTypes = dg->GetHeaterTypes(); uint8_t heaterDemandMask = 0; for (uint16_t idx = 0; idx < static_cast(sizeof(waterHeaterTypeValues) / sizeof(waterHeaterTypeValues[0])); idx++) @@ -96,7 +96,7 @@ BitMask WhmManufacturer::DetermineHeatingSources() } } - return BitMask(heaterDemandMask); + return BitMask(heaterDemandMask); } Status WhmManufacturer::TurnHeatingOn(bool emergencyBoost) @@ -111,12 +111,12 @@ Status WhmManufacturer::TurnHeatingOn(bool emergencyBoost) { // emergencyBoost that the consumer wants the water to be heated as quickly as practicable. // Thus, cause multiple heat sources to be activated - dg->SetHeatDemand(BitMask(WaterHeaterDemandBitmap::kImmersionElement1, - WaterHeaterDemandBitmap::kImmersionElement2)); + dg->SetHeatDemand(BitMask(WaterHeaterHeatSourceBitmap::kImmersionElement1, + WaterHeaterHeatSourceBitmap::kImmersionElement2)); } else { - dg->SetHeatDemand(BitMask(WaterHeaterDemandBitmap::kImmersionElement1)); + dg->SetHeatDemand(BitMask(WaterHeaterHeatSourceBitmap::kImmersionElement1)); } return status; @@ -130,7 +130,7 @@ Status WhmManufacturer::TurnHeatingOff() WaterHeaterManagementDelegate * dg = GetWhmDelegate(); - dg->SetHeatDemand(BitMask(0)); + dg->SetHeatDemand(BitMask(0)); return status; } @@ -167,7 +167,7 @@ void SetTestEventTrigger_BasicInstallationTestEvent() // Simulate installation in a 100L tank full of water at 20C, with a target temperature of 60C, in OFF mode dg->SetTankVolume(100); dg->SetTargetWaterTemperature(6000); - dg->SetHeaterTypes(BitMask(WaterHeaterTypeBitmap::kImmersionElement1)); + dg->SetHeaterTypes(BitMask(WaterHeaterHeatSourceBitmap::kImmersionElement1)); dg->DrawOffHotWater(100, 2000); } diff --git a/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp b/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp index 41171d760d0048..90d1b9ebd115b0 100644 --- a/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp @@ -98,5 +98,5 @@ CHIP_ERROR ActionsAttrAccess::Read(const ConcreteReadAttributePath & aPath, Attr void MatterActionsPluginServerInitCallback() { - registerAttributeAccessOverride(&gAttrAccess); + AttributeAccessInterfaceRegistry::Instance().Register(&gAttrAccess); } diff --git a/examples/all-clusters-app/all-clusters-common/src/fan-stub.cpp b/examples/all-clusters-app/all-clusters-common/src/fan-stub.cpp index 9309b597db434f..e0fb68c95f647c 100644 --- a/examples/all-clusters-app/all-clusters-common/src/fan-stub.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/fan-stub.cpp @@ -173,6 +173,6 @@ void emberAfFanControlClusterInitCallback(EndpointId endpoint) { VerifyOrDie(mFanControlManager == nullptr); mFanControlManager = new FanControlManager(endpoint); - registerAttributeAccessOverride(mFanControlManager); + AttributeAccessInterfaceRegistry::Instance().Register(mFanControlManager); FanControl::SetDefaultDelegate(endpoint, mFanControlManager); } diff --git a/examples/all-clusters-app/all-clusters-common/src/occupancy-sensing-stub.cpp b/examples/all-clusters-app/all-clusters-common/src/occupancy-sensing-stub.cpp index 776e108911aaef..1ac4c40ef184aa 100644 --- a/examples/all-clusters-app/all-clusters-common/src/occupancy-sensing-stub.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/occupancy-sensing-stub.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include using namespace chip; @@ -28,30 +29,48 @@ using namespace chip::DeviceLayer; using chip::Protocols::InteractionModel::Status; -static std::unique_ptr - gAttrAccess[MATTER_DM_OCCUPANCY_SENSING_CLUSTER_SERVER_ENDPOINT_COUNT + CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT]; +namespace { + +static constexpr size_t kOccupancySensingClusterTableSize = + MATTER_DM_OCCUPANCY_SENSING_CLUSTER_SERVER_ENDPOINT_COUNT + CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT; + +static_assert(kOccupancySensingClusterTableSize <= kEmberInvalidEndpointIndex, "Occupancy Sensing Cluster table size error"); + +static std::unique_ptr gOccupancySensingClusterInstances[kOccupancySensingClusterTableSize]; + +} // namespace void emberAfOccupancySensingClusterInitCallback(EndpointId endpointId) { - VerifyOrDie(!gAttrAccess[endpointId]); + uint16_t epIndex = emberAfGetClusterServerEndpointIndex(endpointId, chip::app::Clusters::OccupancySensing::Id, + MATTER_DM_OCCUPANCY_SENSING_CLUSTER_SERVER_ENDPOINT_COUNT); - gAttrAccess[endpointId] = std::make_unique( - BitMask(OccupancySensing::Feature::kPassiveInfrared)); + if (epIndex < kOccupancySensingClusterTableSize) + { + VerifyOrDie(!gOccupancySensingClusterInstances[epIndex]); - OccupancySensing::Structs::HoldTimeLimitsStruct::Type holdTimeLimits = { - .holdTimeMin = 1, - .holdTimeMax = 300, - .holdTimeDefault = 10, - }; + gOccupancySensingClusterInstances[epIndex] = + std::make_unique(BitMask(OccupancySensing::Feature::kPassiveInfrared)); - uint16_t holdTime = 10; + OccupancySensing::Structs::HoldTimeLimitsStruct::Type holdTimeLimits = { + .holdTimeMin = 1, + .holdTimeMax = 300, + .holdTimeDefault = 10, + }; - if (gAttrAccess[endpointId]) - { - gAttrAccess[endpointId]->Init(); + uint16_t holdTime = 10; + + if (gOccupancySensingClusterInstances[epIndex]) + { + gOccupancySensingClusterInstances[epIndex]->Init(); - SetHoldTimeLimits(endpointId, holdTimeLimits); + SetHoldTimeLimits(endpointId, holdTimeLimits); - SetHoldTime(endpointId, holdTime); + SetHoldTime(endpointId, holdTime); + } + } + else + { + ChipLogError(AppServer, "Error: invalid/unexpected OccupancySensing Cluster endpoint index."); } } diff --git a/examples/all-clusters-app/ameba/chip_main.cmake b/examples/all-clusters-app/ameba/chip_main.cmake index e6e9ee19a87394..363b01e05ac2de 100644 --- a/examples/all-clusters-app/ameba/chip_main.cmake +++ b/examples/all-clusters-app/ameba/chip_main.cmake @@ -187,15 +187,15 @@ list( ${chip_dir}/examples/microwave-oven-app/microwave-oven-common/src/microwave-oven-device.cpp - ${chip_dir}/examples/energy-management-app/energy-management-common/src/ChargingTargetsMemMgr.cpp - ${chip_dir}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp - ${chip_dir}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp - ${chip_dir}/examples/energy-management-app/energy-management-common/src/EVSEManufacturerImpl.cpp - ${chip_dir}/examples/energy-management-app/energy-management-common/src/ElectricalPowerMeasurementDelegate.cpp - ${chip_dir}/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp - ${chip_dir}/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp - ${chip_dir}/examples/energy-management-app/energy-management-common/src/EnergyEvseTargetsStore.cpp - ${chip_dir}/examples/energy-management-app/energy-management-common/src/EnergyTimeUtils.cpp + ${chip_dir}/examples/energy-management-app/energy-management-common/common/src/EnergyTimeUtils.cpp + ${chip_dir}/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementDelegateImpl.cpp + ${chip_dir}/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementManager.cpp + ${chip_dir}/examples/energy-management-app/energy-management-common/energy-evse/src/ChargingTargetsMemMgr.cpp + ${chip_dir}/examples/energy-management-app/energy-management-common/energy-evse/src/EVSEManufacturerImpl.cpp + ${chip_dir}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseDelegateImpl.cpp + ${chip_dir}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseManager.cpp + ${chip_dir}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseTargetsStore.cpp + ${chip_dir}/examples/energy-management-app/energy-management-common/energy-reporting/src/ElectricalPowerMeasurementDelegate.cpp ${chip_dir}/examples/platform/ameba/route_hook/ameba_route_hook.c ${chip_dir}/examples/platform/ameba/route_hook/ameba_route_table.c @@ -243,7 +243,10 @@ target_include_directories( ${chip_dir}/examples/all-clusters-app/all-clusters-common/include ${chip_dir}/examples/microwave-oven-app/microwave-oven-common ${chip_dir}/examples/microwave-oven-app/microwave-oven-common/include - ${chip_dir}/examples/energy-management-app/energy-management-common/include + ${chip_dir}/examples/energy-management-app/energy-management-common/common/include + ${chip_dir}/examples/energy-management-app/energy-management-common/device-energy-management/include + ${chip_dir}/examples/energy-management-app/energy-management-common/energy-evse/include + ${chip_dir}/examples/energy-management-app/energy-management-common/energy-reporting/include ${chip_dir}/examples/all-clusters-app/ameba/main/include ${chip_dir}/examples/platform/ameba ${chip_dir}/examples/platform/ameba/route_hook diff --git a/examples/all-clusters-app/asr/BUILD.gn b/examples/all-clusters-app/asr/BUILD.gn index fc7ad9037b99de..e27884810cbd8f 100644 --- a/examples/all-clusters-app/asr/BUILD.gn +++ b/examples/all-clusters-app/asr/BUILD.gn @@ -82,15 +82,15 @@ asr_executable("clusters_app") { "${chip_root}/examples/all-clusters-app/all-clusters-common/src/smco-stub.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-temperature-levels.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/ChargingTargetsMemMgr.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EVSEManufacturerImpl.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/ElectricalPowerMeasurementDelegate.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseTargetsStore.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyTimeUtils.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/common/src/EnergyTimeUtils.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementDelegateImpl.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementManager.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/ChargingTargetsMemMgr.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EVSEManufacturerImpl.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseDelegateImpl.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseManager.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseTargetsStore.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/src/ElectricalPowerMeasurementDelegate.cpp", "${examples_plat_dir}/ButtonHandler.cpp", "${examples_plat_dir}/CHIPDeviceManager.cpp", "${examples_plat_dir}/LEDWidget.cpp", @@ -121,7 +121,10 @@ asr_executable("clusters_app") { "${examples_plat_dir}", "${asr_project_dir}/include", "${chip_root}/examples/all-clusters-app/all-clusters-common/include", - "${chip_root}/examples/energy-management-app/energy-management-common/include", + "${chip_root}/examples/energy-management-app/energy-management-common/common/include", + "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/include", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/include", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/include", "${chip_root}/src", "${chip_root}/src/lib", "${chip_root}/src/lib/support", diff --git a/examples/all-clusters-app/cc13x4_26x4/BUILD.gn b/examples/all-clusters-app/cc13x4_26x4/BUILD.gn index c1cb81a9722f7d..bda63caa38dff5 100644 --- a/examples/all-clusters-app/cc13x4_26x4/BUILD.gn +++ b/examples/all-clusters-app/cc13x4_26x4/BUILD.gn @@ -72,15 +72,15 @@ ti_simplelink_executable("all-clusters-app") { "${chip_root}/examples/all-clusters-app/all-clusters-common/src/smco-stub.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-temperature-levels.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/ChargingTargetsMemMgr.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EVSEManufacturerImpl.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/ElectricalPowerMeasurementDelegate.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseTargetsStore.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyTimeUtils.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/common/src/EnergyTimeUtils.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementDelegateImpl.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementManager.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/ChargingTargetsMemMgr.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EVSEManufacturerImpl.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseDelegateImpl.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseManager.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseTargetsStore.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/src/ElectricalPowerMeasurementDelegate.cpp", "${chip_root}/examples/providers/DeviceInfoProviderImpl.cpp", "${chip_root}/src/app/clusters/general-diagnostics-server/GenericFaultTestEventTriggerHandler.cpp", "${project_dir}/main/AppTask.cpp", @@ -116,7 +116,10 @@ ti_simplelink_executable("all-clusters-app") { "${project_dir}", "${project_dir}/main", "${chip_root}/examples/all-clusters-app/all-clusters-common/include", - "${chip_root}/examples/energy-management-app/energy-management-common/include", + "${chip_root}/examples/energy-management-app/energy-management-common/common/include", + "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/include", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/include", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/include", "${chip_root}/examples/providers/", ] diff --git a/examples/all-clusters-app/esp32/main/CMakeLists.txt b/examples/all-clusters-app/esp32/main/CMakeLists.txt index 7fd1d548609257..3e80b995c55b5f 100644 --- a/examples/all-clusters-app/esp32/main/CMakeLists.txt +++ b/examples/all-clusters-app/esp32/main/CMakeLists.txt @@ -18,7 +18,10 @@ # The list of src and include dirs must be in sync with that in all-clusters-app/esp32/main/component.mk set(PRIV_INCLUDE_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/all-clusters-app/all-clusters-common/include" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/include" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/common/include" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/device-energy-management/include" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/energy-evse/include" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/energy-reporting/include" "${CMAKE_CURRENT_LIST_DIR}/include" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32" @@ -29,7 +32,10 @@ set(SRC_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/attributes" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/all-clusters-app/all-clusters-common/src" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/src" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/common/src" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/device-energy-management/src" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/energy-evse/src" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/energy-reporting/src" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/ota" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/common" diff --git a/examples/all-clusters-app/infineon/psoc6/BUILD.gn b/examples/all-clusters-app/infineon/psoc6/BUILD.gn index 9be06891342d7c..aeb1fa0b6feb4d 100644 --- a/examples/all-clusters-app/infineon/psoc6/BUILD.gn +++ b/examples/all-clusters-app/infineon/psoc6/BUILD.gn @@ -124,15 +124,16 @@ psoc6_executable("clusters_app") { "${chip_root}/examples/all-clusters-app/all-clusters-common/src/smco-stub.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-temperature-levels.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/ChargingTargetsMemMgr.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EVSEManufacturerImpl.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/ElectricalPowerMeasurementDelegate.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseTargetsStore.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyTimeUtils.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/common/src/EnergyTimeUtils.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementDelegateImpl.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementManager.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/ChargingTargetsMemMgr.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EVSEManufacturerImpl.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseDelegateImpl.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseManager.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseTargetsStore.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/energy-evse-mode.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/src/ElectricalPowerMeasurementDelegate.cpp", "${examples_plat_dir}/LEDWidget.cpp", "${examples_plat_dir}/init_psoc6Platform.cpp", "src/AppTask.cpp", @@ -157,7 +158,10 @@ psoc6_executable("clusters_app") { "${examples_plat_dir}", "${psoc6_project_dir}/include", "${chip_root}/examples/all-clusters-app/all-clusters-common/include", - "${chip_root}/examples/energy-management-app/energy-management-common/include", + "${chip_root}/examples/energy-management-app/energy-management-common/common/include", + "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/include", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/include", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/include", ] defines = [] diff --git a/examples/all-clusters-app/infineon/psoc6/README.md b/examples/all-clusters-app/infineon/psoc6/README.md index 75a01995d8c9e4..138f132f7a0dba 100644 --- a/examples/all-clusters-app/infineon/psoc6/README.md +++ b/examples/all-clusters-app/infineon/psoc6/README.md @@ -30,10 +30,11 @@ will then join the network. ## Building -- [Modustoolbox Software](https://www.cypress.com/products/modustoolbox) +- Download and install + [Modustoolbox Software v3.2](https://www.infineon.com/modustoolbox) - Refer to `integrations/docker/images/chip-build-infineon/Dockerfile` or - `scripts/examples/gn_psoc6_example.sh` for downloading the Software and + Refer to `integrations/docker/images/stage-2/chip-build-infineon/Dockerfile` + or `scripts/examples/gn_psoc6_example.sh` for downloading the Software and related tools. - Install some additional tools (likely already present for Matter @@ -62,11 +63,12 @@ will then join the network. - Put CY8CKIT-062S2-43012 board on KitProg3 CMSIS-DAP Mode by pressing the `MODE SELECT` button. `KITPROG3 STATUS` LED is ON confirms board is in - proper mode. + proper mode. (Modustoolbox Software needs to be installed) - On the command line: $ cd ~/connectedhomeip + $ export CY_TOOLS_PATHS=/tools_3.2 $ python3 out/infineon-psoc6-all-clusters/chip-psoc6-clusters-example.flash.py ## Commissioning and cluster control diff --git a/examples/all-clusters-app/linux/BUILD.gn b/examples/all-clusters-app/linux/BUILD.gn index c7c5fb0f14ecd3..ed228b51b2cb32 100644 --- a/examples/all-clusters-app/linux/BUILD.gn +++ b/examples/all-clusters-app/linux/BUILD.gn @@ -64,17 +64,17 @@ source_set("chip-all-clusters-common") { "${chip_root}/examples/all-clusters-app/all-clusters-common/src/tcc-mode.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/water-heater-mode.cpp", "${chip_root}/examples/all-clusters-app/linux/diagnostic-logs-provider-delegate-impl.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/ChargingTargetsMemMgr.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EVSEManufacturerImpl.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/ElectricalPowerMeasurementDelegate.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseTargetsStore.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyTimeUtils.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/device-energy-management-mode.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/energy-evse-mode.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/common/src/EnergyTimeUtils.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementDelegateImpl.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementManager.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/src/device-energy-management-mode.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/ChargingTargetsMemMgr.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EVSEManufacturerImpl.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseDelegateImpl.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseManager.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseTargetsStore.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/energy-evse-mode.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/src/ElectricalPowerMeasurementDelegate.cpp", "${chip_root}/examples/thermostat/linux/thermostat-delegate-impl.cpp", "AllClustersCommandDelegate.cpp", "AllClustersCommandDelegate.h", @@ -98,7 +98,10 @@ source_set("chip-all-clusters-common") { include_dirs = [ "${chip_root}/examples/all-clusters-app/all-clusters-common/include", - "${chip_root}/examples/energy-management-app/energy-management-common/include", + "${chip_root}/examples/energy-management-app/energy-management-common/common/include", + "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/include", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/include", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/include", "${chip_root}/examples/thermostat/linux/include", ] diff --git a/examples/all-clusters-app/linux/ValveControlDelegate.cpp b/examples/all-clusters-app/linux/ValveControlDelegate.cpp index d0ce1b4ab3a980..29c744257fbabe 100644 --- a/examples/all-clusters-app/linux/ValveControlDelegate.cpp +++ b/examples/all-clusters-app/linux/ValveControlDelegate.cpp @@ -33,7 +33,7 @@ DataModel::Nullable ValveControlDelegate::HandleOpenValve(DataMod chip::Percent currentLevel = sLevel; sLevel = level.IsNull() ? 100 : level.Value(); sLastOpenDuration = 0; - ChipLogProgress(NotSpecified, "Valve openinig from level: %d to %d", currentLevel, sLevel); + ChipLogProgress(NotSpecified, "Valve opening from level: %d to %d", currentLevel, sLevel); // In this demo application, the trasition is considered instant, // so current level is set to the requested level and current state is set to kOpen. diff --git a/examples/all-clusters-app/mbed/CMakeLists.txt b/examples/all-clusters-app/mbed/CMakeLists.txt index 427517aff9f8e1..b2e54ed28a78d6 100644 --- a/examples/all-clusters-app/mbed/CMakeLists.txt +++ b/examples/all-clusters-app/mbed/CMakeLists.txt @@ -50,7 +50,10 @@ target_include_directories(${APP_TARGET} PRIVATE main/include/ ${MBED_COMMON}/util/include ${ALL_CLUSTERS_COMMON}/include - ${ENERGY_MANAGEMENT_COMMON}/include + ${ENERGY_MANAGEMENT_COMMON}/common/include + ${ENERGY_MANAGEMENT_COMMON}/device-energy-management/include + ${ENERGY_MANAGEMENT_COMMON}/energy-evse/include + ${ENERGY_MANAGEMENT_COMMON}/energy-reporting/include ${GEN_DIR}/app-common ${GEN_DIR}/all-clusters-app ${NLIO_ROOT} @@ -72,15 +75,15 @@ target_sources(${APP_TARGET} PRIVATE ${ALL_CLUSTERS_COMMON}/src/smco-stub.cpp ${ALL_CLUSTERS_COMMON}/src/static-supported-modes-manager.cpp ${ALL_CLUSTERS_COMMON}/src/static-supported-temperature-levels.cpp - ${ENERGY_MANAGEMENT_COMMON}/src/ChargingTargetsMemMgr.cpp - ${ENERGY_MANAGEMENT_COMMON}/src/DeviceEnergyManagementDelegateImpl.cpp - ${ENERGY_MANAGEMENT_COMMON}/src/DeviceEnergyManagementManager.cpp - ${ENERGY_MANAGEMENT_COMMON}/src/EVSEManufacturerImpl.cpp - ${ENERGY_MANAGEMENT_COMMON}/src/ElectricalPowerMeasurementDelegate.cpp - ${ENERGY_MANAGEMENT_COMMON}/src/EnergyEvseDelegateImpl.cpp - ${ENERGY_MANAGEMENT_COMMON}/src/EnergyEvseManager.cpp - ${ENERGY_MANAGEMENT_COMMON}/src/EnergyEvseTargetsStore.cpp - ${ENERGY_MANAGEMENT_COMMON}/src/EnergyTimeUtils.cpp + ${ENERGY_MANAGEMENT_COMMON}/common/src/EnergyTimeUtils.cpp + ${ENERGY_MANAGEMENT_COMMON}/device-energy-management/src/DeviceEnergyManagementDelegateImpl.cpp + ${ENERGY_MANAGEMENT_COMMON}/device-energy-management/src/DeviceEnergyManagementManager.cpp + ${ENERGY_MANAGEMENT_COMMON}/energy-evse/src/ChargingTargetsMemMgr.cpp + ${ENERGY_MANAGEMENT_COMMON}/energy-evse/src/EVSEManufacturerImpl.cpp + ${ENERGY_MANAGEMENT_COMMON}/energy-evse/src/EnergyEvseDelegateImpl.cpp + ${ENERGY_MANAGEMENT_COMMON}/energy-evse/src/EnergyEvseManager.cpp + ${ENERGY_MANAGEMENT_COMMON}/energy-evse/src/EnergyEvseTargetsStore.cpp + ${ENERGY_MANAGEMENT_COMMON}/energy-reporting/src/ElectricalPowerMeasurementDelegate.cpp ) chip_configure_data_model(${APP_TARGET} diff --git a/examples/all-clusters-app/nrfconnect/CMakeLists.txt b/examples/all-clusters-app/nrfconnect/CMakeLists.txt index e11dcbd14356fc..bed8169e40bd92 100644 --- a/examples/all-clusters-app/nrfconnect/CMakeLists.txt +++ b/examples/all-clusters-app/nrfconnect/CMakeLists.txt @@ -42,7 +42,10 @@ include(${CHIP_ROOT}/src/app/chip_data_model.cmake) target_include_directories(app PRIVATE main/include ${ALL_CLUSTERS_COMMON_DIR}/include - ${ENERGY_MANAGEMENT_COMMON_DIR}/include + ${ENERGY_MANAGEMENT_COMMON_DIR}/common/include + ${ENERGY_MANAGEMENT_COMMON_DIR}/device-energy-management/include + ${ENERGY_MANAGEMENT_COMMON_DIR}/energy-evse/include + ${ENERGY_MANAGEMENT_COMMON_DIR}/energy-reporting/include ${GEN_DIR}/app-common ${GEN_DIR}/all-clusters-app ${NRFCONNECT_COMMON}/util/include) @@ -62,15 +65,15 @@ target_sources(app PRIVATE ${ALL_CLUSTERS_COMMON_DIR}/src/air-quality-instance.cpp ${ALL_CLUSTERS_COMMON_DIR}/src/concentration-measurement-instances.cpp ${ALL_CLUSTERS_COMMON_DIR}/src/resource-monitoring-delegates.cpp - ${ENERGY_MANAGEMENT_COMMON_DIR}/src/ChargingTargetsMemMgr.cpp - ${ENERGY_MANAGEMENT_COMMON_DIR}/src/DeviceEnergyManagementDelegateImpl.cpp - ${ENERGY_MANAGEMENT_COMMON_DIR}/src/DeviceEnergyManagementManager.cpp - ${ENERGY_MANAGEMENT_COMMON_DIR}/src/EVSEManufacturerImpl.cpp - ${ENERGY_MANAGEMENT_COMMON_DIR}/src/ElectricalPowerMeasurementDelegate.cpp - ${ENERGY_MANAGEMENT_COMMON_DIR}/src/EnergyEvseDelegateImpl.cpp - ${ENERGY_MANAGEMENT_COMMON_DIR}/src/EnergyEvseManager.cpp - ${ENERGY_MANAGEMENT_COMMON_DIR}/src/EnergyEvseTargetsStore.cpp - ${ENERGY_MANAGEMENT_COMMON_DIR}/src/EnergyTimeUtils.cpp + ${ENERGY_MANAGEMENT_COMMON_DIR}/common/src/EnergyTimeUtils.cpp + ${ENERGY_MANAGEMENT_COMMON_DIR}/device-energy-management/src/DeviceEnergyManagementDelegateImpl.cpp + ${ENERGY_MANAGEMENT_COMMON_DIR}/device-energy-management/src/DeviceEnergyManagementManager.cpp + ${ENERGY_MANAGEMENT_COMMON_DIR}/energy-evse/src/ChargingTargetsMemMgr.cpp + ${ENERGY_MANAGEMENT_COMMON_DIR}/energy-evse/src/EVSEManufacturerImpl.cpp + ${ENERGY_MANAGEMENT_COMMON_DIR}/energy-evse/src/EnergyEvseDelegateImpl.cpp + ${ENERGY_MANAGEMENT_COMMON_DIR}/energy-evse/src/EnergyEvseManager.cpp + ${ENERGY_MANAGEMENT_COMMON_DIR}/energy-evse/src/EnergyEvseTargetsStore.cpp + ${ENERGY_MANAGEMENT_COMMON_DIR}/energy-reporting/src/ElectricalPowerMeasurementDelegate.cpp ${NRFCONNECT_COMMON}/util/LEDWidget.cpp) chip_configure_data_model(app diff --git a/examples/all-clusters-app/nxp/mw320/BUILD.gn b/examples/all-clusters-app/nxp/mw320/BUILD.gn index e5e3671143ee99..89ba7f249719cc 100644 --- a/examples/all-clusters-app/nxp/mw320/BUILD.gn +++ b/examples/all-clusters-app/nxp/mw320/BUILD.gn @@ -74,7 +74,10 @@ mw320_executable("shell_mw320") { "${chip_root}/src", "${chip_root}/src/app/util", "${chip_root}/examples/all-clusters-app/all-clusters-common/include", - "${chip_root}/examples/energy-management-app/energy-management-common/include", + "${chip_root}/examples/energy-management-app/energy-management-common/common/include", + "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/include", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/include", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/include", "${chip_root}/examples/all-clusters-app/nxp/mw320/include", ] sources = [ @@ -89,15 +92,16 @@ mw320_executable("shell_mw320") { "${chip_root}/examples/all-clusters-app/all-clusters-common/src/smco-stub.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-temperature-levels.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/ChargingTargetsMemMgr.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EVSEManufacturerImpl.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/ElectricalPowerMeasurementDelegate.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseTargetsStore.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyTimeUtils.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/common/src/EnergyTimeUtils.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementDelegateImpl.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementManager.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/ChargingTargetsMemMgr.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EVSEManufacturerImpl.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseDelegateImpl.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseManager.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseTargetsStore.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/energy-evse-mode.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/src/ElectricalPowerMeasurementDelegate.cpp", "${chip_root}/src/lib/shell/streamer_mw320.cpp", "binding-handler.cpp", "include/CHIPProjectConfig.h", diff --git a/examples/all-clusters-app/openiotsdk/CMakeLists.txt b/examples/all-clusters-app/openiotsdk/CMakeLists.txt index 9db62a3df783a1..c568ec2b19e66d 100644 --- a/examples/all-clusters-app/openiotsdk/CMakeLists.txt +++ b/examples/all-clusters-app/openiotsdk/CMakeLists.txt @@ -48,7 +48,10 @@ target_include_directories(${APP_TARGET} PRIVATE main/include ${ALL_CLUSTERS_COMMON}/include - ${ENERGY_MANAGEMENT_COMMON}/include + ${ENERGY_MANAGEMENT_COMMON}/common/include + ${ENERGY_MANAGEMENT_COMMON}/device-energy-management/include + ${ENERGY_MANAGEMENT_COMMON}/energy-evse/include + ${ENERGY_MANAGEMENT_COMMON}/energy-reporting/include ) target_sources(${APP_TARGET} @@ -65,15 +68,15 @@ target_sources(${APP_TARGET} ${ALL_CLUSTERS_COMMON}/src/resource-monitoring-delegates.cpp ${ALL_CLUSTERS_COMMON}/src/static-supported-modes-manager.cpp ${ALL_CLUSTERS_COMMON}/src/binding-handler.cpp - ${ENERGY_MANAGEMENT_COMMON}/src/ChargingTargetsMemMgr.cpp - ${ENERGY_MANAGEMENT_COMMON}/src/DeviceEnergyManagementDelegateImpl.cpp - ${ENERGY_MANAGEMENT_COMMON}/src/DeviceEnergyManagementManager.cpp - ${ENERGY_MANAGEMENT_COMMON}/src/EVSEManufacturerImpl.cpp - ${ENERGY_MANAGEMENT_COMMON}/src/ElectricalPowerMeasurementDelegate.cpp - ${ENERGY_MANAGEMENT_COMMON}/src/EnergyEvseDelegateImpl.cpp - ${ENERGY_MANAGEMENT_COMMON}/src/EnergyEvseManager.cpp - ${ENERGY_MANAGEMENT_COMMON}/src/EnergyEvseTargetsStore.cpp - ${ENERGY_MANAGEMENT_COMMON}/src/EnergyTimeUtils.cpp + ${ENERGY_MANAGEMENT_COMMON}/common/src/EnergyTimeUtils.cpp + ${ENERGY_MANAGEMENT_COMMON}/device-energy-management/src/DeviceEnergyManagementDelegateImpl.cpp + ${ENERGY_MANAGEMENT_COMMON}/device-energy-management/src/DeviceEnergyManagementManager.cpp + ${ENERGY_MANAGEMENT_COMMON}/energy-evse/src/ChargingTargetsMemMgr.cpp + ${ENERGY_MANAGEMENT_COMMON}/energy-evse/src/EVSEManufacturerImpl.cpp + ${ENERGY_MANAGEMENT_COMMON}/energy-evse/src/EnergyEvseDelegateImpl.cpp + ${ENERGY_MANAGEMENT_COMMON}/energy-evse/src/EnergyEvseManager.cpp + ${ENERGY_MANAGEMENT_COMMON}/energy-evse/src/EnergyEvseTargetsStore.cpp + ${ENERGY_MANAGEMENT_COMMON}/energy-reporting/src/ElectricalPowerMeasurementDelegate.cpp ) target_link_libraries(${APP_TARGET} diff --git a/examples/all-clusters-app/telink/CMakeLists.txt b/examples/all-clusters-app/telink/CMakeLists.txt index 675ea4d9eb7e74..1eba5072690a6d 100644 --- a/examples/all-clusters-app/telink/CMakeLists.txt +++ b/examples/all-clusters-app/telink/CMakeLists.txt @@ -31,7 +31,10 @@ project(chip-telink-all-clusters-app-example) target_include_directories(app PRIVATE include ${ALL_CLUSTERS_COMMON_DIR}/include - ${ENERGY_MANAGEMENT_COMMON_DIR}/include + ${ENERGY_MANAGEMENT_COMMON_DIR}/common/include + ${ENERGY_MANAGEMENT_COMMON_DIR}/device-energy-management/include + ${ENERGY_MANAGEMENT_COMMON_DIR}/energy-evse/include + ${ENERGY_MANAGEMENT_COMMON_DIR}/energy-reporting/include ${GEN_DIR}/app-common ${GEN_DIR}/all-clusters-app ${TELINK_COMMON}/common/include @@ -51,15 +54,15 @@ target_sources(app PRIVATE ${ALL_CLUSTERS_COMMON_DIR}/src/device-energy-management-stub.cpp ${ALL_CLUSTERS_COMMON_DIR}/src/energy-evse-stub.cpp ${ALL_CLUSTERS_COMMON_DIR}/src/resource-monitoring-delegates.cpp - ${ENERGY_MANAGEMENT_COMMON_DIR}/src/ChargingTargetsMemMgr.cpp - ${ENERGY_MANAGEMENT_COMMON_DIR}/src/DeviceEnergyManagementDelegateImpl.cpp - ${ENERGY_MANAGEMENT_COMMON_DIR}/src/DeviceEnergyManagementManager.cpp - ${ENERGY_MANAGEMENT_COMMON_DIR}/src/EVSEManufacturerImpl.cpp - ${ENERGY_MANAGEMENT_COMMON_DIR}/src/ElectricalPowerMeasurementDelegate.cpp - ${ENERGY_MANAGEMENT_COMMON_DIR}/src/EnergyEvseDelegateImpl.cpp - ${ENERGY_MANAGEMENT_COMMON_DIR}/src/EnergyEvseManager.cpp - ${ENERGY_MANAGEMENT_COMMON_DIR}/src/EnergyEvseTargetsStore.cpp - ${ENERGY_MANAGEMENT_COMMON_DIR}/src/EnergyTimeUtils.cpp + ${ENERGY_MANAGEMENT_COMMON_DIR}/common/src/EnergyTimeUtils.cpp + ${ENERGY_MANAGEMENT_COMMON_DIR}/device-energy-management/src/DeviceEnergyManagementDelegateImpl.cpp + ${ENERGY_MANAGEMENT_COMMON_DIR}/device-energy-management/src/DeviceEnergyManagementManager.cpp + ${ENERGY_MANAGEMENT_COMMON_DIR}/energy-evse/src/ChargingTargetsMemMgr.cpp + ${ENERGY_MANAGEMENT_COMMON_DIR}/energy-evse/src/EVSEManufacturerImpl.cpp + ${ENERGY_MANAGEMENT_COMMON_DIR}/energy-evse/src/EnergyEvseDelegateImpl.cpp + ${ENERGY_MANAGEMENT_COMMON_DIR}/energy-evse/src/EnergyEvseManager.cpp + ${ENERGY_MANAGEMENT_COMMON_DIR}/energy-evse/src/EnergyEvseTargetsStore.cpp + ${ENERGY_MANAGEMENT_COMMON_DIR}/energy-reporting/src/ElectricalPowerMeasurementDelegate.cpp ${TELINK_COMMON}/common/src/mainCommon.cpp ${TELINK_COMMON}/common/src/AppTaskCommon.cpp ${TELINK_COMMON}/util/src/LEDManager.cpp diff --git a/examples/all-clusters-app/tizen/BUILD.gn b/examples/all-clusters-app/tizen/BUILD.gn index 855416c0446923..332b03cbebaf00 100644 --- a/examples/all-clusters-app/tizen/BUILD.gn +++ b/examples/all-clusters-app/tizen/BUILD.gn @@ -38,15 +38,16 @@ source_set("chip-all-clusters-common") { "${chip_root}/examples/all-clusters-app/all-clusters-common/src/smco-stub.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-temperature-levels.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/ChargingTargetsMemMgr.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EVSEManufacturerImpl.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/ElectricalPowerMeasurementDelegate.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseTargetsStore.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyTimeUtils.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/common/src/EnergyTimeUtils.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementDelegateImpl.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementManager.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/ChargingTargetsMemMgr.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EVSEManufacturerImpl.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseDelegateImpl.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseManager.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseTargetsStore.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/energy-evse-mode.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/src/ElectricalPowerMeasurementDelegate.cpp", ] deps = [ @@ -57,7 +58,10 @@ source_set("chip-all-clusters-common") { include_dirs = [ "${chip_root}/examples/all-clusters-app/all-clusters-common/include", - "${chip_root}/examples/energy-management-app/energy-management-common/include", + "${chip_root}/examples/energy-management-app/energy-management-common/common/include", + "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/include", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/include", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/include", ] } diff --git a/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter b/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter index fcb987edb574aa..1444915c368b6b 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 @@ -5583,6 +5583,9 @@ cluster ApplicationLauncher = 1292 { kSuccess = 0; kAppNotAvailable = 1; kSystemBusy = 2; + kPendingUserApproval = 3; + kDownloading = 4; + kInstalling = 5; } bitmap Feature : bitmap32 { @@ -6922,7 +6925,7 @@ endpoint 1 { ram attribute occupancy; ram attribute occupancySensorType; ram attribute occupancySensorTypeBitmap; - ram attribute featureMap default = 0; + callback attribute featureMap; ram attribute clusterRevision default = 5; } @@ -7275,7 +7278,7 @@ endpoint 2 { ram attribute occupancy; ram attribute occupancySensorType; ram attribute occupancySensorTypeBitmap; - ram attribute featureMap default = 0; + callback attribute featureMap; ram attribute clusterRevision default = 5; } } diff --git a/examples/all-clusters-minimal-app/esp32/main/CMakeLists.txt b/examples/all-clusters-minimal-app/esp32/main/CMakeLists.txt index 7178945c7eb21c..06916c32c6670d 100644 --- a/examples/all-clusters-minimal-app/esp32/main/CMakeLists.txt +++ b/examples/all-clusters-minimal-app/esp32/main/CMakeLists.txt @@ -19,7 +19,10 @@ # The list of src and include dirs must be in sync with that in all-clusters-minimal-app/esp32/main/component.mk set(PRIV_INCLUDE_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/all-clusters-app/all-clusters-common/include" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/include" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/common/include" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/device-energy-management/include" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/energy-evse/include" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/energy-reporting/include" "${CMAKE_CURRENT_LIST_DIR}/include" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32" diff --git a/examples/all-clusters-minimal-app/infineon/psoc6/README.md b/examples/all-clusters-minimal-app/infineon/psoc6/README.md index 4ebd3832f43de6..80b8e1ceb66791 100644 --- a/examples/all-clusters-minimal-app/infineon/psoc6/README.md +++ b/examples/all-clusters-minimal-app/infineon/psoc6/README.md @@ -30,10 +30,11 @@ will then join the network. ## Building -- [Modustoolbox Software](https://www.cypress.com/products/modustoolbox) +- Download and install + [Modustoolbox Software v3.2](https://www.infineon.com/modustoolbox) - Refer to `integrations/docker/images/chip-build-infineon/Dockerfile` or - `scripts/examples/gn_psoc6_example.sh` for downloading the Software and + Refer to `integrations/docker/images/stage-2/chip-build-infineon/Dockerfile` + or `scripts/examples/gn_psoc6_example.sh` for downloading the Software and related tools. - Install some additional tools (likely already present for Matter @@ -62,11 +63,12 @@ will then join the network. - Put CY8CKIT-062S2-43012 board on KitProg3 CMSIS-DAP Mode by pressing the `MODE SELECT` button. `KITPROG3 STATUS` LED is ON confirms board is in - proper mode. + proper mode. (Modustoolbox Software needs to be installed) - On the command line: $ cd ~/connectedhomeip + $ export CY_TOOLS_PATHS=/tools_3.2 $ python3 out/infineon-psoc6-all-clusters-minimal/chip-psoc6-clusters-minimal-example.flash.py ## Commissioning and cluster control diff --git a/examples/bridge-app/asr/src/bridged-actions-stub.cpp b/examples/bridge-app/asr/src/bridged-actions-stub.cpp index 9e26bae9803fa1..73b7e8dd9877a0 100755 --- a/examples/bridge-app/asr/src/bridged-actions-stub.cpp +++ b/examples/bridge-app/asr/src/bridged-actions-stub.cpp @@ -97,5 +97,5 @@ CHIP_ERROR ActionsAttrAccess::Read(const ConcreteReadAttributePath & aPath, Attr void MatterActionsPluginServerInitCallback(void) { - registerAttributeAccessOverride(&gAttrAccess); + AttributeAccessInterfaceRegistry::Instance().Register(&gAttrAccess); } diff --git a/examples/bridge-app/esp32/main/DeviceCallbacks.cpp b/examples/bridge-app/esp32/main/DeviceCallbacks.cpp index 13ced6a2e1c7c6..768771555f3252 100644 --- a/examples/bridge-app/esp32/main/DeviceCallbacks.cpp +++ b/examples/bridge-app/esp32/main/DeviceCallbacks.cpp @@ -113,5 +113,5 @@ CHIP_ERROR ActionsAttrAccess::Read(const ConcreteReadAttributePath & aPath, Attr void MatterActionsPluginServerInitCallback(void) { - registerAttributeAccessOverride(&gAttrAccess); + AttributeAccessInterfaceRegistry::Instance().Register(&gAttrAccess); } diff --git a/examples/bridge-app/linux/bridged-actions-stub.cpp b/examples/bridge-app/linux/bridged-actions-stub.cpp index 00f6913b8012c5..580f4f2239bd1a 100644 --- a/examples/bridge-app/linux/bridged-actions-stub.cpp +++ b/examples/bridge-app/linux/bridged-actions-stub.cpp @@ -133,5 +133,5 @@ CHIP_ERROR ActionsAttrAccess::Read(const ConcreteReadAttributePath & aPath, Attr void MatterActionsPluginServerInitCallback() { - registerAttributeAccessOverride(&gAttrAccess); + AttributeAccessInterfaceRegistry::Instance().Register(&gAttrAccess); } diff --git a/examples/bridge-app/linux/main.cpp b/examples/bridge-app/linux/main.cpp index c7e1dfb5a9c50b..d8446088a960a0 100644 --- a/examples/bridge-app/linux/main.cpp +++ b/examples/bridge-app/linux/main.cpp @@ -998,7 +998,7 @@ void ApplicationInit() } } - registerAttributeAccessOverride(&gPowerAttrAccess); + AttributeAccessInterfaceRegistry::Instance().Register(&gPowerAttrAccess); } void ApplicationShutdown() {} diff --git a/examples/bridge-app/telink/src/DeviceCallbacks.cpp b/examples/bridge-app/telink/src/DeviceCallbacks.cpp index b0657e586fabc2..9e3273e7107472 100644 --- a/examples/bridge-app/telink/src/DeviceCallbacks.cpp +++ b/examples/bridge-app/telink/src/DeviceCallbacks.cpp @@ -101,5 +101,5 @@ CHIP_ERROR ActionsAttrAccess::Read(const ConcreteReadAttributePath & aPath, Attr void MatterActionsPluginServerInitCallback(void) { - registerAttributeAccessOverride(&gAttrAccess); + AttributeAccessInterfaceRegistry::Instance().Register(&gAttrAccess); } diff --git a/examples/chef/common/chef-concentration-measurement.cpp b/examples/chef/common/chef-concentration-measurement.cpp index f0b8109bdf9eda..d168b797b929ac 100644 --- a/examples/chef/common/chef-concentration-measurement.cpp +++ b/examples/chef/common/chef-concentration-measurement.cpp @@ -91,7 +91,7 @@ Protocols::InteractionModel::Status chefConcentrationMeasurementWriteCallback( CHIP_ERROR err = clusterInstance->SetMeasuredValue(MakeNullable(newValue)); if (CHIP_NO_ERROR == err) { - ChipLogDetail(DeviceLayer, "Updated EP:%d, Cluster: 0x%04x to MeasuredValue: %f", endpoint, clusterId, newValue); + ChipLogDetail(DeviceLayer, "Updated EP:%d, Cluster: 0x%04x MeasuredValue", endpoint, clusterId); } else { diff --git a/examples/chef/common/chef-fan-control-manager.cpp b/examples/chef/common/chef-fan-control-manager.cpp index 899892501bf4f1..b30f58db27aee7 100644 --- a/examples/chef/common/chef-fan-control-manager.cpp +++ b/examples/chef/common/chef-fan-control-manager.cpp @@ -141,6 +141,6 @@ void emberAfFanControlClusterInitCallback(EndpointId endpoint) { VerifyOrDie(!mFanControlManager); mFanControlManager = std::make_unique(endpoint); - registerAttributeAccessOverride(mFanControlManager.get()); + AttributeAccessInterfaceRegistry::Instance().Register(mFanControlManager.get()); FanControl::SetDefaultDelegate(endpoint, mFanControlManager.get()); } diff --git a/examples/chef/common/chef-rpc-actions-worker.cpp b/examples/chef/common/chef-rpc-actions-worker.cpp index 98bba768e7f4d8..28413f098b6bcc 100644 --- a/examples/chef/common/chef-rpc-actions-worker.cpp +++ b/examples/chef/common/chef-rpc-actions-worker.cpp @@ -147,7 +147,9 @@ void ChefRpcActionsWorker::RegisterRpcActionsDelegate(ClusterId clusterId, Actio ChefRpcActionsWorker::ChefRpcActionsWorker() { +#if CONFIG_ENABLE_PW_RPC chip::rpc::SubscribeActions(ChefRpcActionsCallback); +#endif } static ChefRpcActionsWorker instance; diff --git a/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.matter b/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.matter index 1369028c39df4f..71f96dbdf077d3 100644 --- a/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.matter +++ b/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.matter @@ -2726,7 +2726,7 @@ endpoint 1 { ram attribute credentialRulesSupport default = 1; ram attribute numberOfCredentialsSupportedPerUser default = 5; ram attribute language default = "en"; - ram attribute autoRelockTime default = 5; + ram attribute autoRelockTime default = 0; ram attribute soundVolume default = 0; ram attribute operatingMode default = 0; ram attribute supportedOperatingModes default = 0xFFFF; diff --git a/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.zap b/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.zap index 339fe71d2631a3..50e1a4bf1da25c 100644 --- a/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.zap +++ b/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.zap @@ -3665,7 +3665,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "5", + "defaultValue": "0", "reportable": 1, "minInterval": 1, "maxInterval": 65534, diff --git a/examples/chef/devices/rootnode_occupancysensor_iHyVgifZuo.matter b/examples/chef/devices/rootnode_occupancysensor_iHyVgifZuo.matter index c12fe40a360ea7..146cc74bf0526f 100644 --- a/examples/chef/devices/rootnode_occupancysensor_iHyVgifZuo.matter +++ b/examples/chef/devices/rootnode_occupancysensor_iHyVgifZuo.matter @@ -1932,7 +1932,7 @@ endpoint 1 { callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute attributeList; - ram attribute featureMap default = 0; + callback attribute featureMap; ram attribute clusterRevision default = 5; } } diff --git a/examples/chip-tool/commands/pairing/OpenCommissioningWindowCommand.h b/examples/chip-tool/commands/pairing/OpenCommissioningWindowCommand.h index 3a199745601c93..9da6e937ee5e2b 100644 --- a/examples/chip-tool/commands/pairing/OpenCommissioningWindowCommand.h +++ b/examples/chip-tool/commands/pairing/OpenCommissioningWindowCommand.h @@ -38,7 +38,7 @@ class OpenCommissioningWindowCommand : public CHIPCommand "Time, in seconds, before the commissioning window closes."); AddArgument("iteration", chip::Crypto::kSpake2p_Min_PBKDF_Iterations, chip::Crypto::kSpake2p_Max_PBKDF_Iterations, &mIteration, "Number of PBKDF iterations to use to derive the verifier. Ignored if 'option' is 0."); - AddArgument("discriminator", 0, 4096, &mDiscriminator, "Discriminator to use for advertising. Ignored if 'option' is 0."); + AddArgument("discriminator", 0, 4095, &mDiscriminator, "Discriminator to use for advertising. Ignored if 'option' is 0."); AddArgument("timeout", 0, UINT16_MAX, &mTimeout, "Time, in seconds, before this command is considered to have timed out."); } diff --git a/examples/common/pigweed/BUILD.gn b/examples/common/pigweed/BUILD.gn index 6252f86e637890..a7b7d97da32ba6 100644 --- a/examples/common/pigweed/BUILD.gn +++ b/examples/common/pigweed/BUILD.gn @@ -90,6 +90,7 @@ pw_proto_library("fabric_admin_service") { pw_proto_library("fabric_bridge_service") { sources = [ "protos/fabric_bridge_service.proto" ] + inputs = [ "protos/fabric_bridge_service.options" ] deps = [ "$dir_pw_protobuf:common_protos" ] strip_prefix = "protos" prefix = "fabric_bridge_service" diff --git a/examples/common/pigweed/protos/fabric_admin_service.proto b/examples/common/pigweed/protos/fabric_admin_service.proto index 7f6ec4f4995b12..b2c81d5ee0eaae 100644 --- a/examples/common/pigweed/protos/fabric_admin_service.proto +++ b/examples/common/pigweed/protos/fabric_admin_service.proto @@ -14,6 +14,11 @@ message DeviceCommissioningWindowInfo { bytes verifier = 6; } +message KeepActiveParameters { + uint64 node_id = 1; + uint32 stay_active_duration_ms = 2; +} + // Define the response message to convey the status of the operation message OperationStatus { bool success = 1; @@ -21,4 +26,5 @@ message OperationStatus { service FabricAdmin { rpc OpenCommissioningWindow(DeviceCommissioningWindowInfo) returns (OperationStatus){} + rpc KeepActive(KeepActiveParameters) returns (pw.protobuf.Empty){} } diff --git a/examples/common/pigweed/protos/fabric_bridge_service.options b/examples/common/pigweed/protos/fabric_bridge_service.options new file mode 100644 index 00000000000000..a095d85788eb1c --- /dev/null +++ b/examples/common/pigweed/protos/fabric_bridge_service.options @@ -0,0 +1,6 @@ +chip.rpc.SynchronizedDevice.unique_id max_size:33 +chip.rpc.SynchronizedDevice.vendor_name max_size:33 +chip.rpc.SynchronizedDevice.product_name max_size:33 +chip.rpc.SynchronizedDevice.node_label max_size:33 +chip.rpc.SynchronizedDevice.hardware_version_string max_size:65 +chip.rpc.SynchronizedDevice.software_version_string max_size:65 diff --git a/examples/common/pigweed/protos/fabric_bridge_service.proto b/examples/common/pigweed/protos/fabric_bridge_service.proto index 10e5ccf888583d..0de3b3fa243d77 100644 --- a/examples/common/pigweed/protos/fabric_bridge_service.proto +++ b/examples/common/pigweed/protos/fabric_bridge_service.proto @@ -7,10 +7,27 @@ package chip.rpc; // Define the message for a synchronized end device with necessary fields message SynchronizedDevice { uint64 node_id = 1; + + optional string unique_id = 2; + optional string vendor_name = 3; + optional uint32 vendor_id = 4; + optional string product_name = 5; + optional uint32 product_id = 6; + optional string node_label = 7; + optional uint32 hardware_version = 8; + optional string hardware_version_string = 9; + optional uint32 software_version = 10; + optional string software_version_string = 11; + optional bool is_icd = 12; +} + +message KeepActiveChanged { + uint64 node_id = 1; + uint32 promised_active_duration_ms = 2; } service FabricBridge { rpc AddSynchronizedDevice(SynchronizedDevice) returns (pw.protobuf.Empty){} - rpc RemoveSynchronizedDevice(SynchronizedDevice) returns (pw.protobuf.Empty){} + rpc RemoveSynchronizedDevice(SynchronizedDevice) returns (pw.protobuf.Empty){} + rpc ActiveChanged(KeepActiveChanged) returns (pw.protobuf.Empty){} } - diff --git a/examples/common/pigweed/rpc_services/FabricAdmin.h b/examples/common/pigweed/rpc_services/FabricAdmin.h index 14de9d50f60673..125d322e3ab8bf 100644 --- a/examples/common/pigweed/rpc_services/FabricAdmin.h +++ b/examples/common/pigweed/rpc_services/FabricAdmin.h @@ -39,6 +39,11 @@ class FabricAdmin : public pw_rpc::nanopb::FabricAdmin::Service { return pw::Status::Unimplemented(); } + + virtual pw::Status KeepActive(const chip_rpc_KeepActiveParameters & request, pw_protobuf_Empty & response) + { + return pw::Status::Unimplemented(); + } }; } // namespace rpc diff --git a/examples/common/pigweed/rpc_services/FabricBridge.h b/examples/common/pigweed/rpc_services/FabricBridge.h index 4b9c4d93f1eb51..aab714223968df 100644 --- a/examples/common/pigweed/rpc_services/FabricBridge.h +++ b/examples/common/pigweed/rpc_services/FabricBridge.h @@ -43,6 +43,11 @@ class FabricBridge : public pw_rpc::nanopb::FabricBridge::Service { return pw::Status::Unimplemented(); } + + virtual pw::Status ActiveChanged(const chip_rpc_KeepActiveChanged & request, pw_protobuf_Empty & response) + { + return pw::Status::Unimplemented(); + } }; } // namespace rpc diff --git a/examples/contact-sensor-app/contact-sensor-common/contact-sensor-app.matter b/examples/contact-sensor-app/contact-sensor-common/contact-sensor-app.matter index 4baa8d22887c32..bb1c2827a8d609 100644 --- a/examples/contact-sensor-app/contact-sensor-common/contact-sensor-app.matter +++ b/examples/contact-sensor-app/contact-sensor-common/contact-sensor-app.matter @@ -2369,7 +2369,7 @@ endpoint 1 { ram attribute occupancy; ram attribute occupancySensorType; ram attribute occupancySensorTypeBitmap; - ram attribute featureMap default = 0; + callback attribute featureMap; ram attribute clusterRevision default = 5; } } diff --git a/examples/contact-sensor-app/nxp/common/AppTask.cpp b/examples/contact-sensor-app/nxp/common/AppTask.cpp new file mode 100644 index 00000000000000..f49c603cbb16a6 --- /dev/null +++ b/examples/contact-sensor-app/nxp/common/AppTask.cpp @@ -0,0 +1,53 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "AppTask.h" + +#if CONFIG_LOW_POWER +#include "PWR_Interface.h" +#endif + +#include + +void ContactSensorApp::AppTask::PreInitMatterStack() +{ + ChipLogProgress(DeviceLayer, "Welcome to NXP Contact Sensor Demo App"); +} + +#if CONFIG_LOW_POWER +void ContactSensorApp::AppTask::AppMatter_DisallowDeviceToSleep() +{ + PWR_DisallowDeviceToSleep(); +} + +void ContactSensorApp::AppTask::AppMatter_AllowDeviceToSleep() +{ + PWR_AllowDeviceToSleep(); +} +#endif + +ContactSensorApp::AppTask & ContactSensorApp::AppTask::GetDefaultInstance() +{ + static ContactSensorApp::AppTask sAppTask; + return sAppTask; +} + +chip::NXP::App::AppTaskBase & chip::NXP::App::GetAppTask() +{ + return ContactSensorApp::AppTask::GetDefaultInstance(); +} diff --git a/examples/contact-sensor-app/nxp/common/DeviceCallbacks.cpp b/examples/contact-sensor-app/nxp/common/DeviceCallbacks.cpp new file mode 100644 index 00000000000000..8cd301d81f5aa6 --- /dev/null +++ b/examples/contact-sensor-app/nxp/common/DeviceCallbacks.cpp @@ -0,0 +1,69 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "DeviceCallbacks.h" +#if CONFIG_ENABLE_FEEDBACK +#include "UserInterfaceFeedback.h" +#endif + +#include +#include +#include + +using namespace ::chip; +using namespace ::chip::app::Clusters; + +void logBooleanStateEvent(bool state) +{ + chip::EventNumber eventNumber; + chip::app::Clusters::BooleanState::Events::StateChange::Type event{ state }; + if (CHIP_NO_ERROR != chip::app::LogEvent(event, 1, eventNumber)) + { + ChipLogProgress(Zcl, "booleanstate: failed to reacord state-change event"); + } +} + +void ContactSensorApp::DeviceCallbacks::PostAttributeChangeCallback(chip::EndpointId endpoint, chip::ClusterId clusterId, + chip::AttributeId attributeId, uint8_t type, uint16_t size, + uint8_t * value) +{ + if (clusterId == BooleanState::Id) + { + if (attributeId != BooleanState::Attributes::StateValue::Id) + { + ChipLogProgress(Zcl, "Unknown attribute ID: " ChipLogFormatMEI, ChipLogValueMEI(attributeId)); + return; + } +#if CONFIG_ENABLE_FEEDBACK + FeedbackMgr().RestoreState(); +#endif + logBooleanStateEvent(static_cast(*value)); + } + else + { + ChipLogProgress(Zcl, "Unknown attribute ID: " ChipLogFormatMEI, ChipLogValueMEI(attributeId)); + } +} + +chip::DeviceManager::CHIPDeviceManagerCallbacks & chip::NXP::App::GetDeviceCallbacks() +{ + static ContactSensorApp::DeviceCallbacks sDeviceCallbacks; + return sDeviceCallbacks; +} diff --git a/examples/contact-sensor-app/nxp/common/ZclCallbacks.cpp b/examples/contact-sensor-app/nxp/common/ZclCallbacks.cpp new file mode 100644 index 00000000000000..cbadc5510d27aa --- /dev/null +++ b/examples/contact-sensor-app/nxp/common/ZclCallbacks.cpp @@ -0,0 +1,38 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#if CONFIG_ENABLE_FEEDBACK +#include "UserInterfaceFeedback.h" +#endif + +/** @brief BooleanState Cluster Init + * + * This function is called when a specific cluster is initialized. It gives the + * application an opportunity to take care of cluster initialization procedures. + * It is called exactly once for each endpoint where cluster is present. + */ +void emberAfBooleanStateClusterInitCallback(chip::EndpointId endpoint) +{ + ChipLogProgress(Zcl, "emberAfBooleanStateClusterInitCallback\n"); +#if CONFIG_ENABLE_FEEDBACK + FeedbackMgr().RestoreState(); +#endif +} diff --git a/src/platform/nxp/k32w/k32w1/DefaultTestEventTriggerDelegate.cpp b/examples/contact-sensor-app/nxp/common/include/AppEvent.h similarity index 62% rename from src/platform/nxp/k32w/k32w1/DefaultTestEventTriggerDelegate.cpp rename to examples/contact-sensor-app/nxp/common/include/AppEvent.h index 69935bb024559d..b292afaddf8c18 100644 --- a/src/platform/nxp/k32w/k32w1/DefaultTestEventTriggerDelegate.cpp +++ b/examples/contact-sensor-app/nxp/common/include/AppEvent.h @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2022 Project CHIP Authors + * Copyright (c) 2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,16 +16,12 @@ * limitations under the License. */ -#include "DefaultTestEventTriggerDelegate.h" +#pragma once -#include -#include +struct AppEvent; +typedef void (*EventHandler)(const AppEvent &); -namespace chip { - -bool DefaultTestEventTriggerDelegate::DoesEnableKeyMatch(const ByteSpan & enableKey) const +struct AppEvent { - return !mEnableKey.empty() && mEnableKey.data_equal(enableKey); -} - -} // namespace chip + EventHandler Handler; +}; diff --git a/examples/contact-sensor-app/nxp/common/include/AppTask.h b/examples/contact-sensor-app/nxp/common/include/AppTask.h new file mode 100644 index 00000000000000..69b3ffc8200804 --- /dev/null +++ b/examples/contact-sensor-app/nxp/common/include/AppTask.h @@ -0,0 +1,50 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "AppConfig.h" +#include "AppTaskFreeRTOS.h" + +#include + +namespace ContactSensorApp { + +class AppTask : public chip::NXP::App::AppTaskFreeRTOS +{ +public: + // AppTaskFreeRTOS virtual methods + void PreInitMatterStack() override; +#if CONFIG_LOW_POWER + void AppMatter_DisallowDeviceToSleep() override; + void AppMatter_AllowDeviceToSleep() override; +#endif + + // This returns an instance of this class. + static AppTask & GetDefaultInstance(); +}; + +} // namespace ContactSensorApp + +/** + * Returns the application-specific implementation of the AppTaskBase object. + * + * Applications can use this to gain access to features of the AppTaskBase + * that are specific to the selected application. + */ +chip::NXP::App::AppTaskBase & GetAppTask(); diff --git a/examples/contact-sensor-app/nxp/common/include/DeviceCallbacks.h b/examples/contact-sensor-app/nxp/common/include/DeviceCallbacks.h new file mode 100644 index 00000000000000..7234c2b8c74f53 --- /dev/null +++ b/examples/contact-sensor-app/nxp/common/include/DeviceCallbacks.h @@ -0,0 +1,51 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file DeviceCallbacks.h + * + * Lighting app implementation for the DeviceManager callbacks for all applications + * + **/ + +#pragma once + +#include "CHIPDeviceManager.h" +#include "CommonDeviceCallbacks.h" + +namespace ContactSensorApp { + +class DeviceCallbacks : public chip::NXP::App::CommonDeviceCallbacks +{ +public: + void PostAttributeChangeCallback(chip::EndpointId endpoint, chip::ClusterId clusterId, chip::AttributeId attributeId, + uint8_t type, uint16_t size, uint8_t * value) override; +}; + +} // namespace ContactSensorApp + +namespace chip::NXP::App { +/** + * Returns the application-specific implementation of the CommonDeviceCallbacks object. + * + * Applications can use this to gain access to features of the CommonDeviceCallbacks + * that are specific to the selected application. + */ +chip::DeviceManager::CHIPDeviceManagerCallbacks & GetDeviceCallbacks(); + +} // namespace chip::NXP::App diff --git a/examples/contact-sensor-app/nxp/common/main.cpp b/examples/contact-sensor-app/nxp/common/main.cpp new file mode 100644 index 00000000000000..d9672b5402c867 --- /dev/null +++ b/examples/contact-sensor-app/nxp/common/main.cpp @@ -0,0 +1,39 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "AppTask.h" +#include "FreeRTOS.h" + +#if configAPPLICATION_ALLOCATED_HEAP +uint8_t __attribute__((section(".heap"))) ucHeap[configTOTAL_HEAP_SIZE]; +#endif + +#if FSL_OSA_MAIN_FUNC_ENABLE +extern "C" void main_task(void const * argument) +{ + chip::DeviceLayer::PlatformMgrImpl().HardwareInit(); + chip::NXP::App::GetAppTask().Start(); +} +#else +extern "C" int main(int argc, char * argv[]) +{ + chip::DeviceLayer::PlatformMgrImpl().HardwareInit(); + chip::NXP::App::GetAppTask().Start(); + vTaskStartScheduler(); +} +#endif diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/BUILD.gn b/examples/contact-sensor-app/nxp/k32w/k32w1/BUILD.gn deleted file mode 100644 index f4ccc1ec4d8c39..00000000000000 --- a/examples/contact-sensor-app/nxp/k32w/k32w1/BUILD.gn +++ /dev/null @@ -1,186 +0,0 @@ -# Copyright (c) 2021-2023 Project CHIP Authors -# Copyright (c) 2023 NXP -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//build_overrides/chip.gni") -import("//build_overrides/nxp_sdk.gni") -import("//build_overrides/openthread.gni") - -import("${nxp_sdk_build_root}/nxp_sdk.gni") - -import("${nxp_sdk_build_root}/${nxp_sdk_name}/nxp_executable.gni") - -import("${nxp_sdk_build_root}/${nxp_sdk_name}/${nxp_sdk_name}.gni") - -import("${chip_root}/src/app/icd/icd.gni") -import("${chip_root}/src/crypto/crypto.gni") -import("${chip_root}/src/lib/core/core.gni") -import("${chip_root}/src/platform/device.gni") -import("${chip_root}/src/platform/nxp/${nxp_platform}/args.gni") - -declare_args() { - chip_software_version = 0 - - # Setup discriminator as argument - setup_discriminator = 3840 - chip_with_diag_logs_demo = true -} - -assert(current_os == "freertos") - -common_example_dir = "${chip_root}/examples/platform/nxp/common" -k32w1_platform_dir = "${chip_root}/examples/platform/nxp/k32w/k32w1" -k32w1_sdk_root = getenv("NXP_K32W1_SDK_ROOT") - -k32w1_sdk("sdk") { - sources = [ - "${k32w1_platform_dir}/app/project_include/OpenThreadConfig.h", - "include/CHIPProjectConfig.h", - "include/FreeRTOSConfig.h", - "main/include/app_config.h", - ] - - public_deps = - [ "${chip_root}/third_party/openthread/platforms:libopenthread-platform" ] - - include_dirs = [ - "main/include", - "main", - "include", - "${k32w1_platform_dir}/app/project_include", - "${k32w1_platform_dir}/app/support", - "${k32w1_platform_dir}/util/include", - ] - - defines = [] - if (is_debug) { - defines += [ "BUILD_RELEASE=0" ] - } else { - defines += [ "BUILD_RELEASE=1" ] - } - - if (chip_software_version != 0) { - defines += [ - "CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION=${chip_software_version}", - ] - } - - defines += [ - "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR=${setup_discriminator}", - ] - - if (chip_with_diag_logs_demo) { - defines += [ "CONFIG_DIAG_LOGS_DEMO=1" ] - } -} - -k32w1_executable("contact_sensor_app") { - output_name = "chip-k32w1-contact-example" - - defines = [] - - sources = [ - "${k32w1_platform_dir}/util/LEDWidget.cpp", - "${k32w1_platform_dir}/util/include/LEDWidget.h", - "main/AppTask.cpp", - "main/ContactSensorManager.cpp", - "main/ZclCallbacks.cpp", - "main/include/AppEvent.h", - "main/include/AppTask.h", - "main/include/ContactSensorManager.h", - "main/main.cpp", - ] - - include_dirs = [ "${common_example_dir}/diagnostic_logs" ] - - deps = [ - ":sdk", - "${chip_root}/examples/common/QRCode", - "${chip_root}/examples/providers:device_info_provider", - "${chip_root}/src/lib", - "${chip_root}/src/platform:syscalls_stub", - "${chip_root}/src/platform/logging:default", - "${chip_root}/third_party/mbedtls:mbedtls", - "${k32w1_platform_dir}/app/support:freertos_mbedtls_utils", - ] - - #lit and sit are using different zap files - if (chip_enable_icd_lit) { - deps += [ "${chip_root}/examples/contact-sensor-app/nxp/zap-lit/" ] - - defines += [ "CHIP_ENABLE_LIT=1" ] - } else { - deps += [ "${chip_root}/examples/contact-sensor-app/nxp/zap-sit/" ] - } - - if (chip_openthread_ftd) { - deps += [ - "${openthread_root}:libopenthread-cli-ftd", - "${openthread_root}:libopenthread-ftd", - ] - } else { - deps += [ - "${openthread_root}:libopenthread-cli-mtd", - "${openthread_root}:libopenthread-mtd", - ] - } - - #lit and sit are using different zap files - if (chip_enable_icd_lit) { - deps += [ "${chip_root}/examples/contact-sensor-app/nxp/zap-lit/" ] - - defines += [ "CHIP_ENABLE_LIT=1" ] - } else { - deps += [ "${chip_root}/examples/contact-sensor-app/nxp/zap-sit/" ] - } - - cflags = [ "-Wconversion" ] - - output_dir = root_out_dir - - ldscript = "${k32w1_sdk_root}/middleware/wireless/framework/Common/devices/kw45_k32w1/gcc/connectivity.ld" - - inputs = [ ldscript ] - - ldflags = [ - "-Wl,--defsym=__heap_size__=0", - "-Wl,--defsym=__stack_size__=0x480", - "-Wl,--defsym=lp_ram_lower_limit=0x04000000", - "-Wl,--defsym=lp_ram_upper_limit=0x2001C000", - "-Wl,-print-memory-usage", - "-Wl,--no-warn-rwx-segments", - "-T" + rebase_path(ldscript, root_build_dir), - ] - - if (chip_with_factory_data == 1) { - ldflags += [ "-Wl,--defsym=gUseFactoryData_d=1" ] - } - - if (chip_with_diag_logs_demo) { - sources += [ - "${common_example_dir}/diagnostic_logs/DiagnosticLogsProviderDelegateImpl.cpp", - "${common_example_dir}/diagnostic_logs/DiagnosticLogsProviderDelegateImpl.h", - ] - } - - output_dir = root_out_dir -} - -group("k32w1") { - deps = [ ":contact_sensor_app" ] -} - -group("default") { - deps = [ ":k32w1" ] -} diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/build_overrides b/examples/contact-sensor-app/nxp/k32w/k32w1/build_overrides deleted file mode 120000 index ad07557834803a..00000000000000 --- a/examples/contact-sensor-app/nxp/k32w/k32w1/build_overrides +++ /dev/null @@ -1 +0,0 @@ -../../../../build_overrides/ \ No newline at end of file diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/main/AppTask.cpp b/examples/contact-sensor-app/nxp/k32w/k32w1/main/AppTask.cpp deleted file mode 100644 index 6f0459178cd173..00000000000000 --- a/examples/contact-sensor-app/nxp/k32w/k32w1/main/AppTask.cpp +++ /dev/null @@ -1,908 +0,0 @@ -/* - * - * Copyright (c) 2022-2023 Project CHIP Authors - * Copyright (c) 2022 Google LLC. - * Copyright (c) 2023 NXP - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "AppTask.h" -#include "AppEvent.h" -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#if CONFIG_DIAG_LOGS_DEMO -#include "DiagnosticLogsProviderDelegateImpl.h" -#endif - -#include -#include -#include -#include - -/* OTA related includes */ -#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR -#include "OtaSupport.h" -#include -#include -#include -#include -#include -#endif - -#include - -#include "K32W1PersistentStorageOpKeystore.h" - -#include "LEDWidget.h" -#include "app.h" -#include "app_config.h" -#include "fsl_component_button.h" -#include "fwk_platform.h" - -#define FACTORY_RESET_TRIGGER_TIMEOUT 6000 -#define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 3000 -#define APP_TASK_PRIORITY 2 -#define APP_EVENT_QUEUE_SIZE 10 - -TimerHandle_t sFunctionTimer; // FreeRTOS app sw timer. - -static QueueHandle_t sAppEventQueue; - -#if !defined(chip_with_low_power) || (chip_with_low_power == 0) -/* - * The status LED and the external flash CS pin are wired together. - * The OTA image writing may fail if used together. - */ -#ifndef CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR -static LEDWidget sStatusLED; -#endif -static LEDWidget sContactSensorLED; -#endif - -static bool sIsThreadProvisioned = false; -static bool sHaveBLEConnections = false; -#if CHIP_ENABLE_LIT -static bool sIsDeviceCommissioned = false; -#endif - -static uint32_t eventMask = 0; - -#if CHIP_DEVICE_CONFIG_THREAD_ENABLE_CLI -extern "C" void otPlatUartProcess(void); -#endif - -extern "C" void PWR_DisallowDeviceToSleep(void); -extern "C" void PWR_AllowDeviceToSleep(void); - -using namespace ::chip::Credentials; -using namespace ::chip::DeviceLayer; -using namespace chip; -using namespace chip::app; -#if CONFIG_DIAG_LOGS_DEMO -using namespace chip::app::Clusters::DiagnosticLogs; -#endif - -AppTask AppTask::sAppTask; -#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA -static AppTask::FactoryDataProvider sFactoryDataProvider; -#endif - -static Identify gIdentify = { chip::EndpointId{ 1 }, AppTask::OnIdentifyStart, AppTask::OnIdentifyStop, - Clusters::Identify::IdentifyTypeEnum::kVisibleIndicator }; - -/* OTA related variables */ -#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR -static DefaultOTARequestor gRequestorCore __attribute__((section(".data"))); -static DefaultOTARequestorStorage gRequestorStorage __attribute__((section(".data"))); -static DeviceLayer::DefaultOTARequestorDriver gRequestorUser __attribute__((section(".data"))); -static BDXDownloader gDownloader __attribute__((section(".data"))); - -constexpr uint16_t requestedOtaBlockSize = 1024; -#endif - -static pm_notify_element_t appNotifyElement = { - .notifyCallback = AppTask::LowPowerCallback, - .data = NULL, -}; - -static void app_gap_callback(gapGenericEvent_t * event) -{ - /* This callback is called in the context of BLE task, so event processing - * should be posted to app task. */ -} - -static void app_gatt_callback(deviceId_t id, gattServerEvent_t * event) -{ - /* This callback is called in the context of BLE task, so event processing - * should be posted to app task. */ -} - -CHIP_ERROR AppTask::StartAppTask() -{ - CHIP_ERROR err = CHIP_NO_ERROR; - - sAppEventQueue = xQueueCreate(APP_EVENT_QUEUE_SIZE, sizeof(AppEvent)); - if (sAppEventQueue == NULL) - { - err = APP_ERROR_EVENT_QUEUE_FAILED; - K32W_LOG("Failed to allocate app event queue"); - assert(err == CHIP_NO_ERROR); - } - - return err; -} - -CHIP_ERROR AppTask::Init() -{ - CHIP_ERROR err = CHIP_NO_ERROR; - - if (ContactSensorMgr().Init() != 0) - { - K32W_LOG("ContactSensorMgr().Init() failed"); - assert(0); - } - - // Register enter/exit low power application callback. - status_t status = PM_RegisterNotify(kPM_NotifyGroup2, &appNotifyElement); - if (status != kStatus_Success) - { - K32W_LOG("Failed to register low power app callback.") - return APP_ERROR_PM_REGISTER_LP_CALLBACK_FAILED; - } - - PlatformMgr().AddEventHandler(MatterEventHandler, 0); - - // Init ZCL Data Model and start server - PlatformMgr().ScheduleWork(InitServer, 0); - -#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA - ReturnErrorOnFailure(sFactoryDataProvider.Init()); - SetDeviceInstanceInfoProvider(&sFactoryDataProvider); - SetDeviceAttestationCredentialsProvider(&sFactoryDataProvider); - SetCommissionableDataProvider(&sFactoryDataProvider); -#else - SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); -#endif // CONFIG_CHIP_LOAD_REAL_FACTORY_DATA - - // QR code will be used with CHIP Tool - AppTask::PrintOnboardingInfo(); - -#if !defined(chip_with_low_power) || (chip_with_low_power == 0) - /* start with all LEDS turnedd off */ -#ifndef CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR - sStatusLED.Init(SYSTEM_STATE_LED, false); -#endif - - sContactSensorLED.Init(CONTACT_SENSOR_STATE_LED, false); - sContactSensorLED.Set(ContactSensorMgr().IsContactClosed()); -#endif - - UpdateDeviceState(); - - /* intialize the Keyboard and button press callback */ - BUTTON_InstallCallback((button_handle_t) g_buttonHandle[0], KBD_Callback, (void *) BLE_BUTTON); - BUTTON_InstallCallback((button_handle_t) g_buttonHandle[1], KBD_Callback, (void *) CONTACT_SENSOR_BUTTON); - - // Create FreeRTOS sw timer for Function Selection. - sFunctionTimer = xTimerCreate("FnTmr", // Just a text name, not used by the RTOS kernel - 1, // == default timer period (mS) - false, // no timer reload (==one-shot) - (void *) this, // init timer id = app task obj context - TimerEventHandler // timer callback handler - ); - if (sFunctionTimer == NULL) - { - err = APP_ERROR_CREATE_TIMER_FAILED; - K32W_LOG("app_timer_create() failed"); - assert(err == CHIP_NO_ERROR); - } - - ContactSensorMgr().SetCallback(OnStateChanged); - - // Print the current software version - char currentSoftwareVer[ConfigurationManager::kMaxSoftwareVersionStringLength + 1] = { 0 }; - err = ConfigurationMgr().GetSoftwareVersionString(currentSoftwareVer, sizeof(currentSoftwareVer)); - if (err != CHIP_NO_ERROR) - { - K32W_LOG("Get version error"); - assert(err == CHIP_NO_ERROR); - } - - uint32_t currentVersion; - err = ConfigurationMgr().GetSoftwareVersion(currentVersion); - - K32W_LOG("Current Software Version: %s, %d", currentSoftwareVer, currentVersion); - - auto & bleManager = chip::DeviceLayer::Internal::BLEMgrImpl(); - bleManager.RegisterAppCallbacks(app_gap_callback, app_gatt_callback); - - return err; -} - -void LockOpenThreadTask(void) -{ - PWR_DisallowDeviceToSleep(); - chip::DeviceLayer::ThreadStackMgr().LockThreadStack(); -} - -void UnlockOpenThreadTask(void) -{ - chip::DeviceLayer::ThreadStackMgr().UnlockThreadStack(); - PWR_AllowDeviceToSleep(); -} - -void AppTask::InitServer(intptr_t arg) -{ - static chip::CommonCaseDeviceServerInitParams initParams; - (void) initParams.InitializeStaticResourcesBeforeServerInit(); - -#if CHIP_CRYPTO_PLATFORM - static chip::K32W1PersistentStorageOpKeystore sK32W1PersistentStorageOpKeystore; - VerifyOrDie((sK32W1PersistentStorageOpKeystore.Init(initParams.persistentStorageDelegate)) == CHIP_NO_ERROR); - initParams.operationalKeystore = &sK32W1PersistentStorageOpKeystore; -#endif - - // Init ZCL Data Model and start server - chip::Inet::EndPointStateOpenThread::OpenThreadEndpointInitParam nativeParams; - nativeParams.lockCb = LockOpenThreadTask; - nativeParams.unlockCb = UnlockOpenThreadTask; - nativeParams.openThreadInstancePtr = chip::DeviceLayer::ThreadStackMgrImpl().OTInstance(); - initParams.endpointNativeParams = static_cast(&nativeParams); - VerifyOrDie((chip::Server::GetInstance().Init(initParams)) == CHIP_NO_ERROR); - -#if CONFIG_DIAG_LOGS_DEMO - char diagLog[CHIP_DEVICE_CONFIG_MAX_DIAG_LOG_SIZE]; - uint16_t diagLogSize = CHIP_DEVICE_CONFIG_MAX_DIAG_LOG_SIZE; - - StorageKeyName keyUser = LogProvider::GetKeyDiagUserSupport(); - StorageKeyName keyNwk = LogProvider::GetKeyDiagNetwork(); - StorageKeyName keyCrash = LogProvider::GetKeyDiagCrashLog(); - - memset(diagLog, 0, diagLogSize); - Server::GetInstance().GetPersistentStorage().SyncSetKeyValue(keyUser.KeyName(), diagLog, diagLogSize); - - memset(diagLog, 1, diagLogSize); - Server::GetInstance().GetPersistentStorage().SyncSetKeyValue(keyNwk.KeyName(), diagLog, diagLogSize); - - memset(diagLog, 2, diagLogSize); - Server::GetInstance().GetPersistentStorage().SyncSetKeyValue(keyCrash.KeyName(), diagLog, diagLogSize); -#endif -} - -void AppTask::PrintOnboardingInfo() -{ - chip::PayloadContents payload; - CHIP_ERROR err = GetPayloadContents(payload, chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE)); - if (err != CHIP_NO_ERROR) - { - ChipLogError(AppServer, "GetPayloadContents() failed: %" CHIP_ERROR_FORMAT, err.Format()); - } - payload.commissioningFlow = chip::CommissioningFlow::kUserActionRequired; - PrintOnboardingCodes(payload); -} - -#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR -void AppTask::InitOTA(intptr_t arg) -{ - // Initialize and interconnect the Requestor and Image Processor objects -- START - SetRequestorInstance(&gRequestorCore); - - gRequestorStorage.Init(chip::Server::GetInstance().GetPersistentStorage()); - gRequestorCore.Init(chip::Server::GetInstance(), gRequestorStorage, gRequestorUser, gDownloader); - gRequestorUser.SetMaxDownloadBlockSize(requestedOtaBlockSize); - auto & imageProcessor = OTAImageProcessorImpl::GetDefaultInstance(); - gRequestorUser.Init(&gRequestorCore, &imageProcessor); - CHIP_ERROR err = imageProcessor.Init(&gDownloader); - if (err != CHIP_NO_ERROR) - { - K32W_LOG("Image processor init failed"); - assert(err == CHIP_NO_ERROR); - } - - // Connect the gDownloader and Image Processor objects - gDownloader.SetImageProcessorDelegate(&imageProcessor); - // Initialize and interconnect the Requestor and Image Processor objects -- END -} -#endif - -void AppTask::AppTaskMain(void * pvParameter) -{ - AppEvent event; - - CHIP_ERROR err = sAppTask.Init(); - if (err != CHIP_NO_ERROR) - { - K32W_LOG("AppTask.Init() failed"); - assert(err == CHIP_NO_ERROR); - } - - while (true) - { - TickType_t xTicksToWait = pdMS_TO_TICKS(10); - -#if defined(chip_with_low_power) && (chip_with_low_power == 1) - xTicksToWait = portMAX_DELAY; -#endif - - BaseType_t eventReceived = xQueueReceive(sAppEventQueue, &event, xTicksToWait); - while (eventReceived == pdTRUE) - { - sAppTask.DispatchEvent(&event); - eventReceived = xQueueReceive(sAppEventQueue, &event, 0); - } - - // Collect connectivity and configuration state from the CHIP stack. Because the - // CHIP event loop is being run in a separate task, the stack must be locked - // while these values are queried. However we use a non-blocking lock request - // (TryLockChipStack()) to avoid blocking other UI activities when the CHIP - // task is busy (e.g. with a long crypto operation). - if (PlatformMgr().TryLockChipStack()) - { -#if CHIP_DEVICE_CONFIG_THREAD_ENABLE_CLI - otPlatUartProcess(); -#endif - - sHaveBLEConnections = (ConnectivityMgr().NumBLEConnections() != 0); - PlatformMgr().UnlockChipStack(); - } - - // Update the status LED if factory reset or identify process have not been initiated. - // - // If system has "full connectivity", keep the LED On constantly. - // - // If thread and service provisioned, but not attached to the thread network yet OR no - // connectivity to the service OR subscriptions are not fully established - // THEN blink the LED Off for a short period of time. - // - // If the system has ble connection(s) uptill the stage above, THEN blink the LEDs at an even - // rate of 100ms. - // - // Otherwise, blink the LED ON for a very short time. - -#if !defined(chip_with_low_power) || (chip_with_low_power == 0) -#ifndef CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR - if (sAppTask.mFunction != Function::kFactoryReset && sAppTask.mFunction != Function::kIdentify) - { - if (sIsThreadProvisioned) - { - sStatusLED.Blink(950, 50); - } - else if (sHaveBLEConnections) - { - sStatusLED.Blink(100, 100); - } - else - { - sStatusLED.Blink(50, 950); - } - } - - sStatusLED.Animate(); -#endif - - sContactSensorLED.Animate(); -#endif - } -} - -void AppTask::ButtonEventHandler(uint8_t pin_no, uint8_t button_action) -{ - if ((pin_no != RESET_BUTTON) && (pin_no != CONTACT_SENSOR_BUTTON) && (pin_no != SOFT_RESET_BUTTON) && (pin_no != BLE_BUTTON)) - { - return; - } - - AppEvent button_event; - button_event.Type = AppEvent::kButton; - button_event.ButtonEvent.PinNo = pin_no; - button_event.ButtonEvent.Action = button_action; - - if (pin_no == RESET_BUTTON) - { - button_event.Handler = ResetActionEventHandler; - } - else if (pin_no == CONTACT_SENSOR_BUTTON) - { - button_event.Handler = ContactActionEventHandler; - } - else if (pin_no == SOFT_RESET_BUTTON) - { - // Soft reset ensures that platform manager shutdown procedure is called. - button_event.Handler = SoftResetHandler; - } - else if (pin_no == BLE_BUTTON) - { - button_event.Handler = BleHandler; - - if (button_action == RESET_BUTTON_PUSH) - { - button_event.Handler = ResetActionEventHandler; - } -#if CHIP_ENABLE_LIT - else if (button_action == USER_ACTIVE_MODE_TRIGGER_PUSH) - { - button_event.Handler = UserActiveModeHandler; - } -#endif - } - - sAppTask.PostEvent(&button_event); -} - -button_status_t AppTask::KBD_Callback(void * buttonHandle, button_callback_message_t * message, void * callbackParam) -{ - uint32_t pinNb = (uint32_t) callbackParam; - switch (message->event) - { - case kBUTTON_EventOneClick: - case kBUTTON_EventShortPress: - switch (pinNb) - { - case BLE_BUTTON: - K32W_LOG("pb1 short press"); - if (sAppTask.mResetTimerActive) - { - ButtonEventHandler(BLE_BUTTON, RESET_BUTTON_PUSH); - } -#if CHIP_ENABLE_LIT - else if (sIsDeviceCommissioned) - { - ButtonEventHandler(BLE_BUTTON, USER_ACTIVE_MODE_TRIGGER_PUSH); - } -#endif - else - { - ButtonEventHandler(BLE_BUTTON, BLE_BUTTON_PUSH); - } - break; - - case CONTACT_SENSOR_BUTTON: - K32W_LOG("pb2 short press"); - ButtonEventHandler(CONTACT_SENSOR_BUTTON, CONTACT_SENSOR_BUTTON_PUSH); - break; - } - break; - - case kBUTTON_EventLongPress: - switch (pinNb) - { - case BLE_BUTTON: - K32W_LOG("pb1 long press"); - ButtonEventHandler(BLE_BUTTON, RESET_BUTTON_PUSH); - break; - - case CONTACT_SENSOR_BUTTON: - K32W_LOG("pb2 long press"); - ButtonEventHandler(SOFT_RESET_BUTTON, SOFT_RESET_BUTTON_PUSH); - break; - } - break; - - default: - /* No action required */ - break; - } - return kStatus_BUTTON_Success; -} - -void AppTask::TimerEventHandler(TimerHandle_t xTimer) -{ - AppEvent event; - event.Type = AppEvent::kTimer; - event.TimerEvent.Context = (void *) xTimer; - event.Handler = FunctionTimerEventHandler; - sAppTask.PostEvent(&event); -} - -void AppTask::FunctionTimerEventHandler(void * aGenericEvent) -{ - AppEvent * aEvent = (AppEvent *) aGenericEvent; - - if (aEvent->Type != AppEvent::kTimer) - return; - - K32W_LOG("Device will factory reset..."); - - // Actually trigger Factory Reset - chip::Server::GetInstance().ScheduleFactoryReset(); -} - -void AppTask::ResetActionEventHandler(void * aGenericEvent) -{ - AppEvent * aEvent = (AppEvent *) aGenericEvent; - - if (aEvent->ButtonEvent.PinNo != RESET_BUTTON && aEvent->ButtonEvent.PinNo != BLE_BUTTON) - return; - - if (sAppTask.mResetTimerActive) - { - sAppTask.CancelTimer(); - sAppTask.mFunction = Function::kNoneSelected; - -#if !defined(chip_with_low_power) || (chip_with_low_power == 0) - /* restore initial state for the LED indicating contact state */ - if (!ContactSensorMgr().IsContactClosed()) - { - sContactSensorLED.Set(false); - } - else - { - sContactSensorLED.Set(true); - } -#endif - - K32W_LOG("Factory Reset was cancelled!"); - } - else - { - uint32_t resetTimeout = FACTORY_RESET_TRIGGER_TIMEOUT; - - if (sAppTask.mFunction != Function::kNoneSelected) - { - K32W_LOG("Another function is scheduled. Could not initiate Factory Reset!"); - return; - } - - K32W_LOG("Factory Reset Triggered. Push the RESET button within %lu ms to cancel!", resetTimeout); - sAppTask.mFunction = Function::kFactoryReset; - - /* LEDs will start blinking to signal that a Factory Reset was scheduled */ -#if !defined(chip_with_low_power) || (chip_with_low_power == 0) -#ifndef CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR - sStatusLED.Set(false); - sStatusLED.Blink(500); -#endif - sContactSensorLED.Set(false); - sContactSensorLED.Blink(500); -#endif - - sAppTask.StartTimer(FACTORY_RESET_TRIGGER_TIMEOUT); - } -} - -void AppTask::ContactActionEventHandler(void * aGenericEvent) -{ - AppEvent * aEvent = (AppEvent *) aGenericEvent; - ContactSensorManager::Action action = ContactSensorManager::Action::kInvalid; - CHIP_ERROR err = CHIP_NO_ERROR; - bool state_changed = false; - - if (sAppTask.mFunction != Function::kNoneSelected) - { - K32W_LOG("Another function is scheduled. Could not change contact state."); - return; - } - - if (aEvent->Type == AppEvent::kContact) - { - action = static_cast(aEvent->ContactEvent.Action); - } - else if (aEvent->Type == AppEvent::kButton) - { - if (ContactSensorMgr().IsContactClosed()) - { - action = ContactSensorManager::Action::kSignalLost; - } - else - { - action = ContactSensorManager::Action::kSignalDetected; - } - - sAppTask.SetSyncClusterToButtonAction(true); - } - else - { - err = APP_ERROR_UNHANDLED_EVENT; - action = ContactSensorManager::Action::kInvalid; - } - - if (err == CHIP_NO_ERROR) - { - ContactSensorMgr().InitiateAction(action); - } -} - -void AppTask::SoftResetHandler(void * aGenericEvent) -{ - AppEvent * aEvent = (AppEvent *) aGenericEvent; - if (aEvent->ButtonEvent.PinNo != SOFT_RESET_BUTTON) - return; - - PlatformMgrImpl().CleanReset(); -} - -void AppTask::BleHandler(void * aGenericEvent) -{ - AppEvent * aEvent = (AppEvent *) aGenericEvent; - - if (aEvent->ButtonEvent.PinNo != BLE_BUTTON) - return; - - if (sAppTask.mFunction != Function::kNoneSelected) - { - K32W_LOG("Another function is scheduled. Could not toggle BLE state!"); - return; - } - PlatformMgr().ScheduleWork(AppTask::BleStartAdvertising, 0); -} - -void AppTask::BleStartAdvertising(intptr_t arg) -{ - if (ConnectivityMgr().IsBLEAdvertisingEnabled()) - { - ConnectivityMgr().SetBLEAdvertisingEnabled(false); - K32W_LOG("Stopped BLE Advertising!"); - } - else - { - ConnectivityMgr().SetBLEAdvertisingEnabled(true); - - if (chip::Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow() == CHIP_NO_ERROR) - { - K32W_LOG("Started BLE Advertising!"); - } - else - { - K32W_LOG("OpenBasicCommissioningWindow() failed"); - } - } -} - -#if CHIP_ENABLE_LIT -void AppTask::UserActiveModeHandler(void * aGenericEvent) -{ - AppEvent * aEvent = (AppEvent *) aGenericEvent; - - if (aEvent->ButtonEvent.PinNo != BLE_BUTTON) - return; - - if (sAppTask.mFunction != Function::kNoneSelected) - { - K32W_LOG("Another function is scheduled. Could not request ICD Active Mode!"); - return; - } - PlatformMgr().ScheduleWork(AppTask::UserActiveModeTrigger, 0); -} - -void AppTask::UserActiveModeTrigger(intptr_t arg) -{ - ICDNotifier::GetInstance().NotifyNetworkActivityNotification(); -} -#endif - -void AppTask::MatterEventHandler(const ChipDeviceEvent * event, intptr_t) -{ - if (event->Type == DeviceEventType::kServiceProvisioningChange && event->ServiceProvisioningChange.IsServiceProvisioned) - { - if (event->ServiceProvisioningChange.IsServiceProvisioned) - { - sIsThreadProvisioned = TRUE; - } - else - { - sIsThreadProvisioned = FALSE; - } - } -#if CHIP_ENABLE_LIT - else if (event->Type == DeviceEventType::kCommissioningComplete) - { - sIsDeviceCommissioned = TRUE; - } -#endif - -#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR - if (event->Type == DeviceEventType::kDnssdInitialized) - { - K32W_LOG("Dnssd platform initialized."); - PlatformMgr().ScheduleWork(InitOTA, 0); - } -#endif -} - -void AppTask::CancelTimer() -{ - if (xTimerStop(sFunctionTimer, 0) == pdFAIL) - { - K32W_LOG("app timer stop() failed"); - } - - mResetTimerActive = false; -} - -void AppTask::StartTimer(uint32_t aTimeoutInMs) -{ - if (xTimerIsTimerActive(sFunctionTimer)) - { - K32W_LOG("app timer already started!"); - CancelTimer(); - } - - // timer is not active, change its period to required value (== restart). - // FreeRTOS- Block for a maximum of 100 ticks if the change period command - // cannot immediately be sent to the timer command queue. - if (xTimerChangePeriod(sFunctionTimer, aTimeoutInMs / portTICK_PERIOD_MS, 100) != pdPASS) - { - K32W_LOG("app timer start() failed"); - } - - mResetTimerActive = true; -} - -void AppTask::OnStateChanged(ContactSensorManager::State aState) -{ - // If the contact state was changed, update LED state and cluster state (only if button was pressed). - // - turn on the contact LED if contact sensor is in closed state. - // - turn off the lock LED if contact sensor is in opened state. - if (ContactSensorManager::State::kContactClosed == aState) - { - K32W_LOG("Contact state changed to closed.") -#if !defined(chip_with_low_power) || (chip_with_low_power == 0) - sContactSensorLED.Set(true); -#endif - } - else if (ContactSensorManager::State::kContactOpened == aState) - { - K32W_LOG("Contact state changed to opened.") -#if !defined(chip_with_low_power) || (chip_with_low_power == 0) - sContactSensorLED.Set(false); -#endif - } - - if (sAppTask.IsSyncClusterToButtonAction()) - { - sAppTask.UpdateClusterState(); - } - - sAppTask.mFunction = Function::kNoneSelected; -} - -void AppTask::OnIdentifyStart(Identify * identify) -{ - if (Clusters::Identify::EffectIdentifierEnum::kBlink == identify->mCurrentEffectIdentifier) - { - if (Function::kNoneSelected != sAppTask.mFunction) - { - K32W_LOG("Another function is scheduled. Could not initiate Identify process!"); - return; - } - K32W_LOG("Identify process has started. Status LED should blink every 0.5 seconds."); - sAppTask.mFunction = Function::kIdentify; -#if !defined(chip_with_low_power) || (chip_with_low_power == 0) -#ifndef CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR - sStatusLED.Set(false); - sStatusLED.Blink(500); -#endif -#endif - } -} - -void AppTask::OnIdentifyStop(Identify * identify) -{ - if (Clusters::Identify::EffectIdentifierEnum::kBlink == identify->mCurrentEffectIdentifier) - { - K32W_LOG("Identify process has stopped."); - sAppTask.mFunction = Function::kNoneSelected; - } -} - -status_t AppTask::LowPowerCallback(pm_event_type_t eventType, uint8_t powerState, void * data) -{ - return kStatus_Success; -} - -void AppTask::PostContactActionRequest(ContactSensorManager::Action aAction) -{ - AppEvent event; - event.Type = AppEvent::kContact; - event.ContactEvent.Action = static_cast(aAction); - event.Handler = ContactActionEventHandler; - PostEvent(&event); -} - -void AppTask::PostEvent(const AppEvent * aEvent) -{ - portBASE_TYPE taskToWake = pdFALSE; - if (sAppEventQueue != NULL) - { - if (__get_IPSR()) - { - if (!xQueueSendToFrontFromISR(sAppEventQueue, aEvent, &taskToWake)) - { - K32W_LOG("Failed to post event to app task event queue"); - } - if (taskToWake) - { - portYIELD_FROM_ISR(taskToWake); - } - } - else if (!xQueueSend(sAppEventQueue, aEvent, 0)) - { - K32W_LOG("Failed to post event to app task event queue"); - } - } -} - -void AppTask::DispatchEvent(AppEvent * aEvent) -{ -#if defined(chip_with_low_power) && (chip_with_low_power == 1) - /* specific processing for events sent from App_PostCallbackMessage (see main.cpp) */ - if (aEvent->Type == AppEvent::kEventType_Lp) - { - aEvent->Handler(aEvent->param); - } - else -#endif - - if (aEvent->Handler) - { - aEvent->Handler(aEvent); - } - else - { - K32W_LOG("Event received with no handler. Dropping event."); - } -} - -void AppTask::UpdateClusterState(void) -{ - PlatformMgr().ScheduleWork(UpdateClusterStateInternal, 0); -} -extern void logBooleanStateEvent(bool state); -void AppTask::UpdateClusterStateInternal(intptr_t arg) -{ - uint8_t newValue = ContactSensorMgr().IsContactClosed(); - - // write the new on/off value - Protocols::InteractionModel::Status status = app::Clusters::BooleanState::Attributes::StateValue::Set(1, newValue); - - if (status != Protocols::InteractionModel::Status::Success) - { - ChipLogError(NotSpecified, "ERR: updating boolean status value %x", to_underlying(status)); - } - logBooleanStateEvent(newValue); -} - -void AppTask::UpdateDeviceState(void) -{ - PlatformMgr().ScheduleWork(UpdateDeviceStateInternal, 0); -} - -void AppTask::UpdateDeviceStateInternal(intptr_t arg) -{ - bool stateValueAttrValue = 0; - - /* get onoff attribute value */ - (void) app::Clusters::BooleanState::Attributes::StateValue::Get(1, &stateValueAttrValue); - -#if !defined(chip_with_low_power) || (chip_with_low_power == 0) - /* set the device state */ - sContactSensorLED.Set(stateValueAttrValue); -#endif -} - -extern "C" void OTAIdleActivities(void) -{ -#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR - OTA_TransactionResume(); -#endif -} diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/main/ContactSensorManager.cpp b/examples/contact-sensor-app/nxp/k32w/k32w1/main/ContactSensorManager.cpp deleted file mode 100644 index 9e0a665cbb5aa9..00000000000000 --- a/examples/contact-sensor-app/nxp/k32w/k32w1/main/ContactSensorManager.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * - * Copyright (c) 2022-2023 Project CHIP Authors - * Copyright (c) 2022 Google LLC. - * Copyright (c) 2023 NXP - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ContactSensorManager.h" - -#include "AppTask.h" -#include "FreeRTOS.h" - -#include "app_config.h" - -ContactSensorManager ContactSensorManager::sContactSensor; - -int ContactSensorManager::Init() -{ - int err = 0; - - mState = State::kContactOpened; - mCallbackStateChanged = nullptr; - - return err; -} - -void ContactSensorManager::SetCallback(CallbackStateChanged aCallbackStateChanged) -{ - mCallbackStateChanged = aCallbackStateChanged; -} - -bool ContactSensorManager::IsContactClosed() -{ - return mState == State::kContactClosed; -} - -void ContactSensorManager::InitiateAction(Action aAction) -{ - AppEvent event; - event.Type = AppEvent::kContact; - event.ContactEvent.Action = static_cast(aAction); - event.Handler = HandleAction; - GetAppTask().PostEvent(&event); -} - -void ContactSensorManager::HandleAction(void * aGenericEvent) -{ - AppEvent * event = static_cast(aGenericEvent); - Action action = static_cast(event->ContactEvent.Action); - // Change current state based on action: - // - if state is closed and action is signal lost, change state to opened - // - if state is opened and action is signal detected, change state to closed - // - else, the state/action combination does not change the state. - if (State::kContactClosed == sContactSensor.mState && Action::kSignalLost == action) - { - sContactSensor.mState = State::kContactOpened; - } - else if (State::kContactOpened == sContactSensor.mState && Action::kSignalDetected == action) - { - sContactSensor.mState = State::kContactClosed; - } - - if (sContactSensor.mCallbackStateChanged != nullptr) - { - sContactSensor.mCallbackStateChanged(sContactSensor.mState); - } - else - { - K32W_LOG("Callback for state change was not set. Please set an appropriate callback."); - } -} diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/main/ZclCallbacks.cpp b/examples/contact-sensor-app/nxp/k32w/k32w1/main/ZclCallbacks.cpp deleted file mode 100644 index e69daab9803d23..00000000000000 --- a/examples/contact-sensor-app/nxp/k32w/k32w1/main/ZclCallbacks.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/* - * - * Copyright (c) 2022-2023 Project CHIP Authors - * Copyright (c) 2023 NXP - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include "AppTask.h" -#include "ContactSensorManager.h" - -#include -#include -#include -#include -#include -#include - -#if CONFIG_DIAG_LOGS_DEMO -#include "DiagnosticLogsProviderDelegateImpl.h" -#include -#endif - -using namespace ::chip; -using namespace ::chip::app; -using namespace ::chip::app::Clusters; -using namespace ::chip::app::Clusters::BooleanState; -#if CONFIG_DIAG_LOGS_DEMO -using namespace ::chip::app::Clusters::DiagnosticLogs; -#endif - -void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & path, uint8_t type, uint16_t size, uint8_t * value) -{ - ChipLogProgress(Zcl, "MatterPostAttributeChangeCallback, value:%d\n", *value); - if (path.mClusterId != BooleanState::Id) - { - ChipLogProgress(Zcl, "Unknown cluster ID: " ChipLogFormatMEI, ChipLogValueMEI(path.mClusterId)); - return; - } - - if (path.mAttributeId != BooleanState::Attributes::StateValue::Id) - { - ChipLogProgress(Zcl, "Unknown attribute ID: " ChipLogFormatMEI, ChipLogValueMEI(path.mAttributeId)); - return; - } - - AppTask & task = GetAppTask(); - // If the callback is called after the cluster attribute was changed due to pressing a button, - // set the sync value to false. Both LED and attribute were updated at this point. - // On the other hand, if the cluster attribute was changed due to a cluster command, - // forward the request to AppTask in order to update the LED state. - if (task.IsSyncClusterToButtonAction()) - { - task.SetSyncClusterToButtonAction(false); - } - else - { - task.PostContactActionRequest(*value ? ContactSensorManager::Action::kSignalDetected - : ContactSensorManager::Action::kSignalLost); - } -} - -/** @brief OnOff Cluster Init - * - * This function is called when a specific cluster is initialized. It gives the - * application an opportunity to take care of cluster initialization procedures. - * It is called exactly once for each endpoint where cluster is present. - * - * @param endpoint Ver.: always - * - * TODO Issue #3841 - * emberAfOnOffClusterInitCallback happens before the stack initialize the cluster - * attributes to the default value. - * The logic here expects something similar to the deprecated Plugins callback - * emberAfPluginOnOffClusterServerPostInitCallback. - * - */ -void emberAfBooleanStateClusterInitCallback(EndpointId endpoint) -{ - ChipLogProgress(Zcl, "emberAfBooleanStateClusterInitCallback\n"); - GetAppTask().UpdateClusterState(); -} - -void logBooleanStateEvent(bool state) -{ - EventNumber eventNumber; - Events::StateChange::Type event{ state }; - if (CHIP_NO_ERROR != LogEvent(event, 1, eventNumber)) - { - ChipLogProgress(Zcl, "booleanstate: failed to reacord state-change event"); - } -} - -#if CONFIG_DIAG_LOGS_DEMO -void emberAfDiagnosticLogsClusterInitCallback(chip::EndpointId endpoint) -{ - auto & logProvider = LogProvider::GetInstance(); - DiagnosticLogsServer::Instance().SetDiagnosticLogsProviderDelegate(endpoint, &logProvider); -} -#endif diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/AppEvent.h b/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/AppEvent.h deleted file mode 100644 index f3e0d729abe2e7..00000000000000 --- a/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/AppEvent.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * - * Copyright (c) 2022 Nest Labs, Inc. - * Copyright (c) 2023 NXP - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -struct AppEvent; -typedef void (*EventHandler)(void *); - -struct AppEvent -{ - enum AppEventTypes - { - kButton = 0, - kTimer, - kContact, - kInstall, -#if defined(chip_with_low_power) && (chip_with_low_power == 1) - kEventType_Lp, -#endif - kOTAResume, - }; - - AppEventTypes Type; - - union - { - struct - { - uint8_t PinNo; - uint8_t Action; - } ButtonEvent; - struct - { - void * Context; - } TimerEvent; - struct - { - uint8_t Action; - } ContactEvent; - }; - - EventHandler Handler; - -#if defined(chip_with_low_power) && (chip_with_low_power == 1) - void * param; -#endif -}; diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/AppTask.h b/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/AppTask.h deleted file mode 100644 index 64842e310561b2..00000000000000 --- a/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/AppTask.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * - * Copyright (c) 2022 Google LLC. - * Copyright (c) 2023 NXP - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include - -#include "AppEvent.h" -#include "ContactSensorManager.h" - -#include "CHIPProjectConfig.h" - -#include -#include - -#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA -#include -#endif - -#include "FreeRTOS.h" -#include "fsl_component_button.h" -#include "fsl_pm_core.h" -#include "timers.h" - -// Application-defined error codes in the CHIP_ERROR space. -#define APP_ERROR_EVENT_QUEUE_FAILED CHIP_APPLICATION_ERROR(0x01) -#define APP_ERROR_CREATE_TASK_FAILED CHIP_APPLICATION_ERROR(0x02) -#define APP_ERROR_UNHANDLED_EVENT CHIP_APPLICATION_ERROR(0x03) -#define APP_ERROR_CREATE_TIMER_FAILED CHIP_APPLICATION_ERROR(0x04) -#define APP_ERROR_START_TIMER_FAILED CHIP_APPLICATION_ERROR(0x05) -#define APP_ERROR_STOP_TIMER_FAILED CHIP_APPLICATION_ERROR(0x06) -#define APP_ERROR_PM_REGISTER_LP_CALLBACK_FAILED CHIP_APPLICATION_ERROR(0x07) - -class AppTask -{ -public: -#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA - using FactoryDataProvider = chip::DeviceLayer::FactoryDataProviderImpl; -#endif - CHIP_ERROR StartAppTask(); - static void AppTaskMain(void * pvParameter); - - void PostContactActionRequest(ContactSensorManager::Action aAction); - void PostEvent(const AppEvent * event); - - void UpdateClusterState(void); - void UpdateDeviceState(void); - - bool IsSyncClusterToButtonAction(); - void SetSyncClusterToButtonAction(bool value); - // Identify cluster callbacks. - static void OnIdentifyStart(Identify * identify); - static void OnIdentifyStop(Identify * identify); - - static status_t LowPowerCallback(pm_event_type_t eventType, uint8_t powerState, void * data); - -private: - friend AppTask & GetAppTask(void); - - CHIP_ERROR Init(); - - static void OnStateChanged(ContactSensorManager::State aState); - - void CancelTimer(void); - - void DispatchEvent(AppEvent * event); - - static void FunctionTimerEventHandler(void * aGenericEvent); - static button_status_t KBD_Callback(void * buttonHandle, button_callback_message_t * message, void * callbackParam); - static void HandleKeyboard(void); - static void SoftResetHandler(void * aGenericEvent); - static void BleHandler(void * aGenericEvent); - static void BleStartAdvertising(intptr_t arg); - static void ContactActionEventHandler(void * aGenericEvent); - static void ResetActionEventHandler(void * aGenericEvent); - static void InstallEventHandler(void * aGenericEvent); -#if CHIP_ENABLE_LIT - static void UserActiveModeHandler(void * aGenericEvent); - static void UserActiveModeTrigger(intptr_t arg); -#endif - - static void ButtonEventHandler(uint8_t pin_no, uint8_t button_action); - static void TimerEventHandler(TimerHandle_t xTimer); - - static void MatterEventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg); - - void StartTimer(uint32_t aTimeoutInMs); - -#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR - static void InitOTA(intptr_t arg); -#endif - - static void UpdateClusterStateInternal(intptr_t arg); - static void UpdateDeviceStateInternal(intptr_t arg); - static void InitServer(intptr_t arg); - static void PrintOnboardingInfo(); - - enum class Function : uint8_t - { - kNoneSelected = 0, - kFactoryReset, - kContact, - kIdentify, - kInvalid - }; - - Function mFunction = Function::kNoneSelected; - bool mResetTimerActive = false; - bool mSyncClusterToButtonAction = false; - - static AppTask sAppTask; -}; - -inline AppTask & GetAppTask(void) -{ - return AppTask::sAppTask; -} - -inline bool AppTask::IsSyncClusterToButtonAction() -{ - return mSyncClusterToButtonAction; -} - -inline void AppTask::SetSyncClusterToButtonAction(bool value) -{ - mSyncClusterToButtonAction = value; -} diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/ContactSensorManager.h b/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/ContactSensorManager.h deleted file mode 100644 index 69a71ee14ee344..00000000000000 --- a/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/ContactSensorManager.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * - * Copyright (c) 2022 Google LLC. - * Copyright (c) 2023 NXP - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include - -#include "AppEvent.h" - -#include "FreeRTOS.h" -#include "timers.h" // provides FreeRTOS timer support - -class ContactSensorManager -{ -public: - enum class Action : uint8_t - { - kSignalDetected = 0, - kSignalLost, - kInvalid - }; - - enum class State : uint8_t - { - kContactClosed = 0, - kContactOpened, - kInvalid - }; - - int Init(); - bool IsContactClosed(); - void InitiateAction(Action aAction); - - typedef void (*CallbackStateChanged)(State aState); - void SetCallback(CallbackStateChanged aCallbackStateChanged); - - static void HandleAction(void * aGenericEvent); - -private: - friend ContactSensorManager & ContactSensorMgr(void); - State mState; - CallbackStateChanged mCallbackStateChanged; - static ContactSensorManager sContactSensor; -}; - -inline ContactSensorManager & ContactSensorMgr(void) -{ - return ContactSensorManager::sContactSensor; -} diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/app_config.h b/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/app_config.h deleted file mode 100644 index 7001f636dbd0d7..00000000000000 --- a/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/app_config.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * - * Copyright (c) 2022 Google LLC. - * Copyright (c) 2023 NXP - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -// ---- Contact Example App Config ---- - -#define RESET_BUTTON 1 -#define CONTACT_SENSOR_BUTTON 2 -#define SOFT_RESET_BUTTON 3 -#define BLE_BUTTON 4 - -#define RESET_BUTTON_PUSH 1 -#define CONTACT_SENSOR_BUTTON_PUSH 2 -#define SOFT_RESET_BUTTON_PUSH 3 -#define BLE_BUTTON_PUSH 4 -#define USER_ACTIVE_MODE_TRIGGER_PUSH 5 - -#define APP_BUTTON_PUSH 1 - -#define CONTACT_SENSOR_STATE_LED 1 -#define SYSTEM_STATE_LED 0 - -// ---- Contact Example SWU Config ---- -#define SWU_INTERVAl_WINDOW_MIN_MS (23 * 60 * 60 * 1000) // 23 hours -#define SWU_INTERVAl_WINDOW_MAX_MS (24 * 60 * 60 * 1000) // 24 hours - -// ---- Thread Polling Config ---- -// #define THREAD_ACTIVE_POLLING_INTERVAL_MS 100 -// #define THREAD_INACTIVE_POLLING_INTERVAL_MS 1000 - -#if K32W_LOG_ENABLED -#define K32W_LOG(...) otPlatLog(OT_LOG_LEVEL_NONE, OT_LOG_REGION_API, ##__VA_ARGS__); -#else -#define K32W_LOG(...) -#endif diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/main/main.cpp b/examples/contact-sensor-app/nxp/k32w/k32w1/main/main.cpp deleted file mode 100644 index 700bbc5ad9356c..00000000000000 --- a/examples/contact-sensor-app/nxp/k32w/k32w1/main/main.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* - * - * Copyright (c) 2022 Google LLC. - * Copyright (c) 2023 NXP - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// ================================================================================ -// Main Code -// ================================================================================ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "FreeRtosHooks.h" -#include "app_config.h" -#include "openthread/platform/logging.h" - -using namespace ::chip; -using namespace ::chip::Inet; -using namespace ::chip::DeviceLayer; -using namespace ::chip::Logging; - -#include - -typedef void (*InitFunc)(void); -extern InitFunc __init_array_start; -extern InitFunc __init_array_end; - -extern "C" void main_task(void const * argument) -{ - CHIP_ERROR err = CHIP_NO_ERROR; - - /* Call C++ constructors */ - InitFunc * pFunc = &__init_array_start; - for (; pFunc < &__init_array_end; ++pFunc) - { - (*pFunc)(); - } - - mbedtls_platform_set_calloc_free(CHIPPlatformMemoryCalloc, CHIPPlatformMemoryFree); - - err = PlatformMgrImpl().InitBoardFwk(); - if (err != CHIP_NO_ERROR) - { - return; - } - - /* Used for HW initializations */ - otSysInit(0, NULL); - - if (err != CHIP_NO_ERROR) - { - return; - } - - K32W_LOG("Welcome to NXP Contact Sensor Demo App"); - - /* Mbedtls Threading support is needed because both - * Thread and Matter tasks are using it */ - freertos_mbedtls_mutex_init(); - - // Init Chip memory management before the stack - chip::Platform::MemoryInit(); - - err = PlatformMgr().InitChipStack(); - if (err != CHIP_NO_ERROR) - { - K32W_LOG("Error during PlatformMgr().InitMatterStack()"); - goto exit; - } - - err = ThreadStackMgr().InitThreadStack(); - if (err != CHIP_NO_ERROR) - { - K32W_LOG("Error during ThreadStackMgr().InitThreadStack()"); - goto exit; - } - - err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_SleepyEndDevice); - if (err != CHIP_NO_ERROR) - { - goto exit; - } - - // Start OpenThread task - err = ThreadStackMgrImpl().StartThreadTask(); - if (err != CHIP_NO_ERROR) - { - K32W_LOG("Error during ThreadStackMgrImpl().StartThreadTask()"); - goto exit; - } - - err = GetAppTask().StartAppTask(); - if (err != CHIP_NO_ERROR) - { - K32W_LOG("Error during GetAppTask().StartAppTask()"); - goto exit; - } - - err = PlatformMgr().StartEventLoopTask(); - if (err != CHIP_NO_ERROR) - { - K32W_LOG("Error during PlatformMgr().StartEventLoopTask();"); - goto exit; - } - - GetAppTask().AppTaskMain(NULL); - -exit: - return; -} - -/** - * Glue function called directly by the OpenThread stack - * when system event processing work is pending. - */ -extern "C" void otSysEventSignalPending(void) -{ - BaseType_t yieldRequired = ThreadStackMgrImpl().SignalThreadActivityPendingFromISR(); - portYIELD_FROM_ISR(yieldRequired); -} diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/third_party/connectedhomeip b/examples/contact-sensor-app/nxp/k32w/k32w1/third_party/connectedhomeip deleted file mode 120000 index 305f2077ffe860..00000000000000 --- a/examples/contact-sensor-app/nxp/k32w/k32w1/third_party/connectedhomeip +++ /dev/null @@ -1 +0,0 @@ -../../../../../.. \ No newline at end of file diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/.gn b/examples/contact-sensor-app/nxp/k32w1/.gn similarity index 93% rename from examples/contact-sensor-app/nxp/k32w/k32w1/.gn rename to examples/contact-sensor-app/nxp/k32w1/.gn index 1e848295f6aa5b..885f306753076d 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w1/.gn +++ b/examples/contact-sensor-app/nxp/k32w1/.gn @@ -28,5 +28,5 @@ default_args = { import("//args.gni") # Import default platform configs - import("${chip_root}/src/platform/nxp/k32w/k32w1/args.gni") + import("${chip_root}/src/platform/nxp/k32w1/args.gni") } diff --git a/examples/contact-sensor-app/nxp/k32w1/BUILD.gn b/examples/contact-sensor-app/nxp/k32w1/BUILD.gn new file mode 100644 index 00000000000000..119dc5cf722eac --- /dev/null +++ b/examples/contact-sensor-app/nxp/k32w1/BUILD.gn @@ -0,0 +1,261 @@ +# Copyright (c) 2021-2023 Project CHIP Authors +# Copyright (c) 2023 NXP +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/chip.gni") +import("//build_overrides/nxp_sdk.gni") +import("//build_overrides/openthread.gni") + +import("${nxp_sdk_build_root}/nxp_sdk.gni") + +import("${nxp_sdk_build_root}/${nxp_sdk_name}/nxp_executable.gni") + +import("${nxp_sdk_build_root}/${nxp_sdk_name}/${nxp_sdk_name}.gni") + +import("${chip_root}/src/app/icd/icd.gni") +import("${chip_root}/src/crypto/crypto.gni") +import("${chip_root}/src/platform/device.gni") +import("${chip_root}/src/platform/nxp/${nxp_platform}/args.gni") + +declare_args() { + # Setup discriminator as argument + setup_discriminator = 3840 + chip_with_diag_logs_demo = true +} + +assert(current_os == "freertos") +assert(target_os == "freertos") + +example_platform_dir = "${chip_root}/examples/platform/nxp/${nxp_platform}" +common_example_dir = "${chip_root}/examples/platform/nxp/common" + +k32w1_sdk("sdk") { + defines = [] + include_dirs = [] + sources = [] + + # Indicate the path to CHIPProjectConfig.h + include_dirs += [ "include/config" ] + + # Indicate the default path to FreeRTOSConfig.h + include_dirs += [ "${example_platform_dir}/app/project_include/freeRTOS" ] + + # Indicate the default path to OpenThreadConfig.h + include_dirs += [ "${example_platform_dir}/app/project_include/openthread" ] + + include_dirs += [ + "${k32w1_sdk_root}/middleware/wireless/framework/boards/kw45_k32w1", + "${k32w1_sdk_root}/middleware/wireless/framework/boards/kw45_k32w1/K32W1480", + ] + + sources += [ + "${k32w1_sdk_root}/middleware/wireless/framework/boards/kw45_k32w1/K32W1480/clock_config.c", + "${k32w1_sdk_root}/middleware/wireless/framework/boards/kw45_k32w1/K32W1480/pin_mux.c", + "${k32w1_sdk_root}/middleware/wireless/framework/boards/kw45_k32w1/app_services_init.c", + "${k32w1_sdk_root}/middleware/wireless/framework/boards/kw45_k32w1/board.c", + "${k32w1_sdk_root}/middleware/wireless/framework/boards/kw45_k32w1/board_comp.c", + "${k32w1_sdk_root}/middleware/wireless/framework/boards/kw45_k32w1/board_dcdc.c", + "${k32w1_sdk_root}/middleware/wireless/framework/boards/kw45_k32w1/board_extflash.c", + "${k32w1_sdk_root}/middleware/wireless/framework/boards/kw45_k32w1/board_lp.c", + "${k32w1_sdk_root}/middleware/wireless/framework/boards/kw45_k32w1/hardware_init.c", + ] + + if (is_debug) { + defines += [ "BUILD_RELEASE=0" ] + } else { + defines += [ "BUILD_RELEASE=1" ] + } + + defines += [ + "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR=${setup_discriminator}", + ] + + if (chip_key_storage == "littlefs") { + include_dirs += [ "${example_platform_dir}/board" ] + sources += [ + "${example_platform_dir}/board/peripherals.c", + "${example_platform_dir}/board/peripherals.h", + ] + } +} + +k32w1_executable("contact_sensor_app") { + output_name = "chip-k32w1-contact-example" + + defines = [] + deps = [] + include_dirs = [] + sources = [] + + # Defines used by common code + defines += [ + "CONFIG_NET_L2_OPENTHREAD=1", + "CONFIG_NETWORK_LAYER_BLE=1", + "CONFIG_THREAD_DEVICE_TYPE=kThreadDeviceType_SleepyEndDevice", + "CONFIG_OPERATIONAL_KEYSTORE=1", + "EXTERNAL_FACTORY_DATA_PROVIDER_HEADER=\"platform/nxp/common/legacy/FactoryDataProvider.h\"", + ] + + if (chip_with_diag_logs_demo) { + defines += [ "CONFIG_DIAG_LOGS_DEMO=1" ] + } + + if (chip_with_low_power == 1) { + defines += [ "CONFIG_LOW_POWER=1" ] + } else { + defines += [ + "CONFIG_ENABLE_FEEDBACK=1", + "APP_QUEUE_TICKS_TO_WAIT=pdMS_TO_TICKS(10)", + ] + } + + # App common files + include_dirs += [ + "${common_example_dir}/app_task/include", + "${common_example_dir}/matter_button/include", + "${common_example_dir}/clusters/include", + "${common_example_dir}/device_callbacks/include", + "${common_example_dir}/device_manager/include", + "${common_example_dir}/diagnostic_logs/include", + "${common_example_dir}/factory_data/include", + "${common_example_dir}/led_widget/include", + "${common_example_dir}/low_power/include", + "${common_example_dir}/operational_keystore/include", + "${common_example_dir}/ui_feedback/include", + ] + + sources += [ + "${common_example_dir}/app_task/source/AppTaskBase.cpp", + "${common_example_dir}/app_task/source/AppTaskFreeRTOS.cpp", + "${common_example_dir}/clusters/source/ZclCallbacks.cpp", + "${common_example_dir}/device_callbacks/source/CommonDeviceCallbacks.cpp", + "${common_example_dir}/device_manager/source/CHIPDeviceManager.cpp", + "${example_platform_dir}/factory_data/source/AppFactoryDataExample.cpp", + ] + + if (chip_with_low_power == 1) { + sources += [ "${common_example_dir}/low_power/source/LowPower.cpp" ] + } + + if (chip_with_factory_data == 1) { + include_dirs += [ "${chip_root}/src/platform/nxp/common/legacy" ] + deps += [ "${chip_root}/src/platform/nxp:nxp_factory_data" ] + } + + if (chip_enable_ota_requestor) { + defines += [ + "CONFIG_CHIP_OTA_IMAGE_PROCESSOR_HEADER=\"platform/nxp/common/legacy/OTAImageProcessorImpl.h\"", + + # The status LED and the external flash CS pin are wired together. The OTA image writing may fail if used together. + "LED_MANAGER_ENABLE_STATUS_LED=0", + ] + + include_dirs += [ "${common_example_dir}/ota_requestor/include" ] + sources += [ "${common_example_dir}/ota_requestor/source/OTARequestorInitiatorMultiImage.cpp" ] + deps += [ "${chip_root}/src/platform/nxp:nxp_ota" ] + } + + if (chip_with_diag_logs_demo) { + sources += [ + "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsDemo.cpp", + "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsProviderDelegateImpl.cpp", + ] + } + + # Platform specific files + include_dirs += [ + "${example_platform_dir}/util", + "${example_platform_dir}/app/support", + "${example_platform_dir}/button", + ] + + sources += [ + "${example_platform_dir}/button/ButtonManager.cpp", + "${example_platform_dir}/clusters/Identify.cpp", + "${example_platform_dir}/operational_keystore/OperationalKeystore.cpp", + ] + + if (chip_enable_ota_requestor) { + sources += [ "${example_platform_dir}/ota/OtaUtils.cpp" ] + } + + include_dirs += [ + "include/config", + "../common/include", + ] + + sources += [ + "../common/AppTask.cpp", + "../common/DeviceCallbacks.cpp", + "../common/ZclCallbacks.cpp", + "../common/main.cpp", + ] + + if (chip_with_low_power == 0) { + sources += [ + "${common_example_dir}/ui_feedback/source/LedManager.cpp", + "${example_platform_dir}/util/LedOnOff.cpp", + ] + } + + deps += [ + "${chip_root}/examples/providers:device_info_provider", + "${chip_root}/src/platform/logging:default", + ] + + #lit and sit are using different zap files + if (chip_enable_icd_lit) { + deps += [ "${chip_root}/examples/contact-sensor-app/nxp/zap-lit/" ] + } else { + deps += [ "${chip_root}/examples/contact-sensor-app/nxp/zap-sit/" ] + } + + if (chip_openthread_ftd) { + deps += [ + "${openthread_root}:libopenthread-cli-ftd", + "${openthread_root}:libopenthread-ftd", + ] + } else { + deps += [ + "${openthread_root}:libopenthread-cli-mtd", + "${openthread_root}:libopenthread-mtd", + ] + } + + cflags = [ "-Wconversion" ] + + ldscript = "${k32w1_sdk_root}/middleware/wireless/framework/Common/devices/kw45_k32w1/gcc/connectivity.ld" + + inputs = [ ldscript ] + + ldflags = [ + "-Wl,--defsym=__heap_size__=0", + "-Wl,--defsym=__stack_size__=0x480", + "-Wl,--defsym=lp_ram_lower_limit=0x04000000", + "-Wl,--defsym=lp_ram_upper_limit=0x2001C000", + "-Wl,-print-memory-usage", + "-Wl,--no-warn-rwx-segments", + "-T" + rebase_path(ldscript, root_build_dir), + ] + + if (chip_with_factory_data == 1) { + ldflags += [ "-Wl,--defsym=gUseFactoryData_d=1" ] + } + + output_dir = root_out_dir +} + +group("default") { + deps = [ ":contact_sensor_app" ] +} diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/README.md b/examples/contact-sensor-app/nxp/k32w1/README.md similarity index 83% rename from examples/contact-sensor-app/nxp/k32w/k32w1/README.md rename to examples/contact-sensor-app/nxp/k32w1/README.md index f3896a01b8362e..7a70f746f6e445 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w1/README.md +++ b/examples/contact-sensor-app/nxp/k32w1/README.md @@ -14,29 +14,29 @@ into an existing Matter network and can be controlled by this network.
- [Matter K32W1 Contact Sensor Example Application](#matter-k32w1-contact-sensor-example-application) -- [Introduction](#introduction) - - [Bluetooth LE Advertising](#bluetooth-le-advertising) - - [Bluetooth LE Rendezvous](#bluetooth-le-rendezvous) -- [Device UI](#device-ui) -- [Building](#building) -- [Long Idle Time ICD Support](#long-idle-time-icd-support) -- [Manufacturing data](#manufacturing-data) -- [Flashing](#flashing) - - [Flashing the NBU image](#flashing-the-nbu-image) - - [Flashing the host image](#flashing-the-host-image) -- [Debugging](#debugging) -- [OTA](#ota) - - [Convert srec into sb3 file](#convert-srec-into-sb3-file) - - [Convert sb3 into ota file](#convert-sb3-into-ota-file) - - [Running OTA](#running-ota) - - [Known issues](#known-issues) -- [Low power](#low-power) - - + - [Introduction](#introduction) + - [Bluetooth LE Advertising](#bluetooth-le-advertising) + - [Bluetooth LE Rendezvous](#bluetooth-le-rendezvous) + - [Thread Provisioning](#thread-provisioning) + - [Device UI](#device-ui) + - [Building](#building) + - [Long Idle Time ICD Support](#long-idle-time-icd-support) + - [Manufacturing data](#manufacturing-data) + - [Flashing](#flashing) + - [Flashing the `NBU` image](#flashing-the-nbu-image) + - [Flashing the host image](#flashing-the-host-image) + - [Debugging](#debugging) + - [OTA](#ota) + - [Convert `srec` into `sb3` file](#convert-srec-into-sb3-file) + - [Convert `sb3` into `ota` file](#convert-sb3-into-ota-file) + - [OTA factory data](#ota-factory-data) + - [Running OTA](#running-ota) + - [Low power](#low-power) + - [Known issues](#known-issues) ## Introduction -![K32W1 EVK](../../../../platform/nxp/k32w/k32w1/doc/images/k32w1-evk.jpg) +![K32W1 EVK](../../../platform/nxp/k32w1/doc/images/k32w1-evk.jpg) The K32W1 contact sensor example application provides a working demonstration of a connected contact sensor device, built using the Matter codebase and the NXP @@ -118,23 +118,50 @@ Matter shutdown procedure. ## Building -In order to build the Matter example, we recommend using a Linux distribution -(the demo-application was compiled on Ubuntu 20.04). +In order to build the Project CHIP example, we recommend using a Linux +distribution. Supported Operating Systems and prerequisites are listed in +[BUILDING](../../../../docs/guides/BUILDING.md). -- Download [K32W1 SDK for Matter](https://mcuxpresso.nxp.com/). Creating an - nxp.com account is required before being able to download the SDK. Once the - account is created, login and follow the steps for downloading K32W1 SDK. - The SDK Builder UI selection should be similar with the one from the image - below. - ![MCUXpresso SDK Download](../../../../platform/nxp/k32w/k32w1/doc/images/mcux-sdk-download.jpg) +- Make sure that below prerequisites are correctly installed + +``` +sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev \ + libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev \ + python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev +``` + +- Step 1: checkout NXP specific submodules only ``` -user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_K32W1_SDK_ROOT=/home/user/Desktop/SDK_K32W1/ -user@ubuntu:~/Desktop/git/connectedhomeip$ source ./scripts/activate.sh user@ubuntu:~/Desktop/git/connectedhomeip$ scripts/checkout_submodules.py --shallow --platform nxp --recursive -user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/contact-sensor-app/nxp/k32w/k32w1 -user@ubuntu:~/Desktop/git/connectedhomeip/examples/contact-sensor-app/nxp/k32w/k32w1$ gn gen out/debug -user@ubuntu:~/Desktop/git/connectedhomeip/examples/contact-sensor-app/nxp/k32w/k32w1$ ninja -C out/debug +``` + +- Step 2: activate local environment + +``` +user@ubuntu:~/Desktop/git/connectedhomeip$ source scripts/activate.sh +``` + +If the script says the environment is out of date, you can update it by running +the following command: + +``` +user@ubuntu:~/Desktop/git/connectedhomeip$ source scripts/bootstrap.sh +``` + +- Step 3: Init NXP SDK(s) + +``` +user@ubuntu:~/Desktop/git/connectedhomeip$ scripts/setup/nxp/update_nxp_sdk.py --platform common_sdk +``` + +Note: By default setup/nxp/update_nxp_sdk.py will try to initialize all NXP +SDKs. Arg "-- help" could be used to view all available options. + +``` +user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/contact-sensor-app/nxp/k32w1 +user@ubuntu:~/Desktop/git/connectedhomeip/examples/contact-sensor-app/nxp/k32w1$ gn gen out/debug +user@ubuntu:~/Desktop/git/connectedhomeip/examples/contact-sensor-app/nxp/k32w1$ ninja -C out/debug ``` In case that Openthread CLI is needed, chip_with_ot_cli build argument must be @@ -185,7 +212,7 @@ using Fibonacci backoff for retries pacing. Use `chip_with_factory_data=1` in the gn build command to enable factory data. For a full guide on manufacturing flow, please see -[Guide for writing manufacturing data on NXP devices](../../../../../docs/guides/nxp/nxp_manufacturing_flow.md). +[Guide for writing manufacturing data on NXP devices](../../../../docs/guides/nxp/nxp_manufacturing_flow.md). ## Flashing @@ -248,7 +275,7 @@ One option for debugging would be to use MCUXpresso IDE. - Drag-and-drop the zip file containing the NXP SDK in the "Installed SDKs" tab: -![Installed SDKs](../../../../platform/nxp/k32w/k32w1/doc/images/installed_sdks.jpg) +![Installed SDKs](../../../platform/nxp/k32w1/doc/images/installed_sdks.jpg) - Import any demo application from the installed SDK: @@ -256,7 +283,7 @@ One option for debugging would be to use MCUXpresso IDE. Import SDK example(s).. -> choose a demo app (demo_apps -> hello_world) -> Finish ``` -![Import demo](../../../../platform/nxp/k32w/k32w1/doc/images/import_demo.jpg) +![Import demo](../../../platform/nxp/k32w1/doc/images/import_demo.jpg) - Flash the previously imported demo application on the board: @@ -275,7 +302,7 @@ resulted after ot-nxp compilation. File -> Import -> C/C++ -> Existing Code as Makefile Project ``` -![New Project](../../../../platform/nxp/k32w/k32w1/doc/images/new_project.jpg) +![New Project](../../../platform/nxp/k32w1/doc/images/new_project.jpg) - Replace the path of the existing demo application with the path of the K32W1 application: @@ -284,7 +311,7 @@ File -> Import -> C/C++ -> Existing Code as Makefile Project Run -> Debug Configurations... -> C/C++ Application ``` -![Debug K32W1](../../../../platform/nxp/k32w/k32w1/doc/images/debug_k32w1.jpg) +![Debug K32W1](../../../platform/nxp/k32w1/doc/images/debug_k32w1.jpg) ## OTA @@ -312,16 +339,21 @@ In `OTAP` application In order to build an OTA image, use NXP wrapper over the standard tool `src/app/ota_image_tool.py`: -- `scripts/tools/nxp/factory_data_generator/ota_image_tool.py` The tool can be - used to generate an OTA image with the following format: - `| OTA image header | TLV1 | TLV2 | ... | TLVn |` where each TLV is in the - form `|tag|length|value|` +- `scripts/tools/nxp/factory_data_generator/ota_image_tool.py`. + +The tool can be used to generate an OTA image with the following format: + +``` + | OTA image header | TLV1 | TLV2 | ... | TLVn | +``` + +where each TLV is in the form `|tag|length|value|`. Note that "standard" TLV format is used. Matter TLV format is only used for factory data TLV value. Please see more in the -[OTA image tool guide](../../../../../scripts/tools/nxp/ota/README.md). +[OTA image tool guide](../../../../scripts/tools/nxp/ota/README.md). Here is an example that generates an OTA image with application update TLV from a `sb3` file: @@ -338,12 +370,24 @@ having a correct OTA process, the OTA header version should be the same as the binary embedded software version. A user can set a custom software version in the gn build args by setting `chip_software_version` to the wanted version. +### OTA factory data + +A user can update the factory data through OTA, at the same time the application +firmware is updated by enabling the following processor in the `gn args`: + +- `chip_enable_ota_factory_data_processor=1` to enable default factory data + update processor (disabled by default). + +The OTA image used must be updated to include the new factory data. + +[OTA image tool guide](../../../../scripts/tools/nxp/ota/README.md). + ### Running OTA The OTA topology used for OTA testing is illustrated in the figure below. Topology is similar with the one used for Matter Test Events. -![OTA_TOPOLOGY](../../../../platform/nxp/k32w/k32w1/doc/images/ota_topology.JPG) +![OTA_TOPOLOGY](../../../platform/nxp/k32w1/doc/images/ota_topology.JPG) The concept for OTA is the next one: diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/args.gni b/examples/contact-sensor-app/nxp/k32w1/args.gni similarity index 84% rename from examples/contact-sensor-app/nxp/k32w/k32w1/args.gni rename to examples/contact-sensor-app/nxp/k32w1/args.gni index 23e6730b79045c..cb952c94bd74d1 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w1/args.gni +++ b/examples/contact-sensor-app/nxp/k32w1/args.gni @@ -17,12 +17,17 @@ import("//build_overrides/chip.gni") import("${chip_root}/config/standalone/args.gni") # SDK target. This is overridden to add our SDK app_config.h & defines. -k32w1_sdk_target = get_label_info(":sdk", "label_no_toolchain") +nxp_sdk_target = get_label_info(":sdk", "label_no_toolchain") +nxp_device = "K32W1480" chip_enable_ota_requestor = true chip_stack_lock_tracking = "fatal" chip_enable_ble = true +chip_system_config_provide_statistics = false +chip_system_config_use_open_thread_inet_endpoints = true +chip_with_lwip = false + chip_enable_icd_server = true chip_enable_icd_lit = false icd_enforce_sit_slow_poll_limit = true diff --git a/examples/contact-sensor-app/nxp/k32w1/build_overrides b/examples/contact-sensor-app/nxp/k32w1/build_overrides new file mode 120000 index 00000000000000..ee19c065d619a2 --- /dev/null +++ b/examples/contact-sensor-app/nxp/k32w1/build_overrides @@ -0,0 +1 @@ +../../../build_overrides/ \ No newline at end of file diff --git a/examples/contact-sensor-app/nxp/k32w1/include/config/AppConfig.h b/examples/contact-sensor-app/nxp/k32w1/include/config/AppConfig.h new file mode 100644 index 00000000000000..0c8019d8e7e33c --- /dev/null +++ b/examples/contact-sensor-app/nxp/k32w1/include/config/AppConfig.h @@ -0,0 +1,29 @@ +/* + * Copyright 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +/* ---- App Config ---- */ +#define APP_DEVICE_TYPE_ENDPOINT 1 +#define APP_CLUSTER_ATTRIBUTE chip::app::Clusters::BooleanState::Attributes::StateValue + +/* ---- Button Manager Config ---- */ +#define BUTTON_MANAGER_FACTORY_RESET_TIMEOUT_MS 6000 + +/* ---- LED Manager Config ---- */ +#define LED_MANAGER_STATUS_LED_INDEX 0 +#define LED_MANAGER_LIGHT_LED_INDEX 1 diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/include/CHIPProjectConfig.h b/examples/contact-sensor-app/nxp/k32w1/include/config/CHIPProjectConfig.h similarity index 98% rename from examples/contact-sensor-app/nxp/k32w/k32w1/include/CHIPProjectConfig.h rename to examples/contact-sensor-app/nxp/k32w1/include/config/CHIPProjectConfig.h index 0d9a4e3b503bee..a16c1bb8b3341c 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w1/include/CHIPProjectConfig.h +++ b/examples/contact-sensor-app/nxp/k32w1/include/config/CHIPProjectConfig.h @@ -192,6 +192,13 @@ #define CHIP_DEVICE_CONFIG_ENABLE_SED 1 +/** + * @def CHIP_DEVICE_CONFIG_KVS_WEAR_STATS + * + * @brief Toggle support for key value store wear stats on or off. + */ +#define CHIP_DEVICE_CONFIG_KVS_WEAR_STATS 1 + /** * @def CHIP_IM_MAX_NUM_COMMAND_HANDLER * diff --git a/examples/contact-sensor-app/nxp/k32w1/third_party/connectedhomeip b/examples/contact-sensor-app/nxp/k32w1/third_party/connectedhomeip new file mode 120000 index 00000000000000..59307833b4fee9 --- /dev/null +++ b/examples/contact-sensor-app/nxp/k32w1/third_party/connectedhomeip @@ -0,0 +1 @@ +../../../../.. \ No newline at end of file diff --git a/examples/dishwasher-app/linux/README.md b/examples/dishwasher-app/linux/README.md index 2d3b461386395d..6b849617099b9c 100644 --- a/examples/dishwasher-app/linux/README.md +++ b/examples/dishwasher-app/linux/README.md @@ -1,8 +1,8 @@ -# Matter Linux Lighting Example +# Matter Linux Dishwasher Example An example showing the use of Matter on the Linux. The document will describe -how to build and run Matter Linux Lighting Example on Raspberry Pi. This doc is -tested on **Ubuntu for Raspberry Pi Server 20.04 LTS (aarch64)** and **Ubuntu +how to build and run Matter Linux Dishwasher Example on Raspberry Pi. This doc +is tested on **Ubuntu for Raspberry Pi Server 20.04 LTS (aarch64)** and **Ubuntu for Raspberry Pi Desktop 20.10 (aarch64)** To cross-compile this example on x64 host and run on **NXP i.MX 8M Mini** @@ -12,7 +12,7 @@ details.
-- [Matter Linux Lighting Example](#matter-linux-lighting-example) +- [Matter Linux Dishwasher Example](#matter-linux-dishwasher-example) - [Building](#building) - [Commandline Arguments](#commandline-arguments) - [Running the Complete Example on Raspberry Pi 4](#running-the-complete-example-on-raspberry-pi-4) @@ -29,7 +29,7 @@ details. - Build the example application: - $ cd ~/connectedhomeip/examples/lighting-app/linux + $ cd ~/connectedhomeip/examples/dishwasher-app/linux $ git submodule update --init $ source third_party/connectedhomeip/scripts/activate.sh $ gn gen out/debug @@ -37,12 +37,12 @@ details. - To delete generated executable, libraries and object files use: - $ cd ~/connectedhomeip/examples/lighting-app/linux + $ cd ~/connectedhomeip/examples/dishwasher-app/linux $ rm -rf out/ - Build the example with pigweed RPC - $ cd ~/connectedhomeip/examples/lighting-app/linux + $ cd ~/connectedhomeip/examples/dishwasher-app/linux $ git submodule update --init $ source third_party/connectedhomeip/scripts/activate.sh $ gn gen out/debug --args='import("//with_pw_rpc.gni")' @@ -107,16 +107,30 @@ details. RX bytes:8609495 acl:14 sco:0 events:217484 errors:0 TX bytes:92185 acl:20 sco:0 commands:5259 errors:0 - - Run Linux Lighting Example App + - Run Linux Dishwasher Example App - $ cd ~/connectedhomeip/examples/lighting-app/linux - $ sudo out/debug/chip-lighting-app --ble-device [bluetooth device number] + $ cd ~/connectedhomeip/examples/dishwasher-app/linux + $ sudo out/debug/chip-dishwasher-app --ble-device [bluetooth device number] # In this example, the device we want to use is hci1 - $ sudo out/debug/chip-lighting-app --ble-device 1 + $ sudo out/debug/chip-dishwasher-app --ble-device 1 - Test the device using ChipDeviceController on your laptop / workstation etc. +## Control + +Control the operational mode: + +``` + $ chip-tool operationalstate start + $ chip-tool operationalstate stop + $ chip-tool operationalstate pause + + $ chip-tool operationalstate start 1 1 + $ chip-tool operationalstate stop 1 1 + $ chip-tool operationalstate pause 1 1 +``` + ## Running RPC Console - As part of building the example with RPCs enabled the chip_rpc python @@ -129,9 +143,9 @@ details. `chip-console -s localhost:33000 -o //pw_log.out` - Then you can Get and Set the light using the RPCs: - `rpcs.chip.rpc.Lighting.Get()` + `rpcs.chip.rpc.Dishwasher.Get()` - `rpcs.chip.rpc.Lighting.Set(on=True, level=128, color=protos.chip.rpc.LightingColor(hue=5, saturation=5))` + `rpcs.chip.rpc.Dishwasher.Set(on=True, level=128, color=protos.chip.rpc.DishwasherColor(hue=5, saturation=5))` ## Device Tracing diff --git a/examples/energy-management-app/energy-management-common/include/EnergyManagementAppCmdLineOptions.h b/examples/energy-management-app/energy-management-common/common/include/EnergyManagementAppCmdLineOptions.h similarity index 100% rename from examples/energy-management-app/energy-management-common/include/EnergyManagementAppCmdLineOptions.h rename to examples/energy-management-app/energy-management-common/common/include/EnergyManagementAppCmdLineOptions.h diff --git a/examples/energy-management-app/energy-management-common/src/EnergyTimeUtils.cpp b/examples/energy-management-app/energy-management-common/common/src/EnergyTimeUtils.cpp similarity index 100% rename from examples/energy-management-app/energy-management-common/src/EnergyTimeUtils.cpp rename to examples/energy-management-app/energy-management-common/common/src/EnergyTimeUtils.cpp diff --git a/examples/energy-management-app/energy-management-common/include/DEMManufacturerDelegate.h b/examples/energy-management-app/energy-management-common/device-energy-management/include/DEMManufacturerDelegate.h similarity index 100% rename from examples/energy-management-app/energy-management-common/include/DEMManufacturerDelegate.h rename to examples/energy-management-app/energy-management-common/device-energy-management/include/DEMManufacturerDelegate.h diff --git a/examples/energy-management-app/energy-management-common/include/DeviceEnergyManagementDelegateImpl.h b/examples/energy-management-app/energy-management-common/device-energy-management/include/DeviceEnergyManagementDelegateImpl.h similarity index 100% rename from examples/energy-management-app/energy-management-common/include/DeviceEnergyManagementDelegateImpl.h rename to examples/energy-management-app/energy-management-common/device-energy-management/include/DeviceEnergyManagementDelegateImpl.h diff --git a/examples/energy-management-app/energy-management-common/include/DeviceEnergyManagementManager.h b/examples/energy-management-app/energy-management-common/device-energy-management/include/DeviceEnergyManagementManager.h similarity index 100% rename from examples/energy-management-app/energy-management-common/include/DeviceEnergyManagementManager.h rename to examples/energy-management-app/energy-management-common/device-energy-management/include/DeviceEnergyManagementManager.h diff --git a/examples/energy-management-app/energy-management-common/include/device-energy-management-modes.h b/examples/energy-management-app/energy-management-common/device-energy-management/include/device-energy-management-modes.h similarity index 100% rename from examples/energy-management-app/energy-management-common/include/device-energy-management-modes.h rename to examples/energy-management-app/energy-management-common/device-energy-management/include/device-energy-management-modes.h diff --git a/examples/energy-management-app/energy-management-common/src/DEMTestEventTriggers.cpp b/examples/energy-management-app/energy-management-common/device-energy-management/src/DEMTestEventTriggers.cpp similarity index 100% rename from examples/energy-management-app/energy-management-common/src/DEMTestEventTriggers.cpp rename to examples/energy-management-app/energy-management-common/device-energy-management/src/DEMTestEventTriggers.cpp diff --git a/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp b/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementDelegateImpl.cpp similarity index 100% rename from examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp rename to examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementDelegateImpl.cpp diff --git a/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp b/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementManager.cpp similarity index 100% rename from examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp rename to examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementManager.cpp diff --git a/examples/energy-management-app/energy-management-common/src/device-energy-management-mode.cpp b/examples/energy-management-app/energy-management-common/device-energy-management/src/device-energy-management-mode.cpp similarity index 100% rename from examples/energy-management-app/energy-management-common/src/device-energy-management-mode.cpp rename to examples/energy-management-app/energy-management-common/device-energy-management/src/device-energy-management-mode.cpp diff --git a/examples/energy-management-app/energy-management-common/include/ChargingTargetsMemMgr.h b/examples/energy-management-app/energy-management-common/energy-evse/include/ChargingTargetsMemMgr.h similarity index 100% rename from examples/energy-management-app/energy-management-common/include/ChargingTargetsMemMgr.h rename to examples/energy-management-app/energy-management-common/energy-evse/include/ChargingTargetsMemMgr.h diff --git a/examples/energy-management-app/energy-management-common/include/EVSECallbacks.h b/examples/energy-management-app/energy-management-common/energy-evse/include/EVSECallbacks.h similarity index 100% rename from examples/energy-management-app/energy-management-common/include/EVSECallbacks.h rename to examples/energy-management-app/energy-management-common/energy-evse/include/EVSECallbacks.h diff --git a/examples/energy-management-app/energy-management-common/include/EVSEManufacturerImpl.h b/examples/energy-management-app/energy-management-common/energy-evse/include/EVSEManufacturerImpl.h similarity index 100% rename from examples/energy-management-app/energy-management-common/include/EVSEManufacturerImpl.h rename to examples/energy-management-app/energy-management-common/energy-evse/include/EVSEManufacturerImpl.h diff --git a/examples/energy-management-app/energy-management-common/include/EnergyEvseDelegateImpl.h b/examples/energy-management-app/energy-management-common/energy-evse/include/EnergyEvseDelegateImpl.h similarity index 100% rename from examples/energy-management-app/energy-management-common/include/EnergyEvseDelegateImpl.h rename to examples/energy-management-app/energy-management-common/energy-evse/include/EnergyEvseDelegateImpl.h diff --git a/examples/energy-management-app/energy-management-common/include/EnergyEvseMain.h b/examples/energy-management-app/energy-management-common/energy-evse/include/EnergyEvseMain.h similarity index 100% rename from examples/energy-management-app/energy-management-common/include/EnergyEvseMain.h rename to examples/energy-management-app/energy-management-common/energy-evse/include/EnergyEvseMain.h diff --git a/examples/energy-management-app/energy-management-common/include/EnergyEvseManager.h b/examples/energy-management-app/energy-management-common/energy-evse/include/EnergyEvseManager.h similarity index 100% rename from examples/energy-management-app/energy-management-common/include/EnergyEvseManager.h rename to examples/energy-management-app/energy-management-common/energy-evse/include/EnergyEvseManager.h diff --git a/examples/energy-management-app/energy-management-common/include/EnergyEvseTargetsStore.h b/examples/energy-management-app/energy-management-common/energy-evse/include/EnergyEvseTargetsStore.h similarity index 100% rename from examples/energy-management-app/energy-management-common/include/EnergyEvseTargetsStore.h rename to examples/energy-management-app/energy-management-common/energy-evse/include/EnergyEvseTargetsStore.h diff --git a/examples/energy-management-app/energy-management-common/include/EnergyTimeUtils.h b/examples/energy-management-app/energy-management-common/energy-evse/include/EnergyTimeUtils.h similarity index 100% rename from examples/energy-management-app/energy-management-common/include/EnergyTimeUtils.h rename to examples/energy-management-app/energy-management-common/energy-evse/include/EnergyTimeUtils.h diff --git a/examples/energy-management-app/energy-management-common/include/energy-evse-modes.h b/examples/energy-management-app/energy-management-common/energy-evse/include/energy-evse-modes.h similarity index 100% rename from examples/energy-management-app/energy-management-common/include/energy-evse-modes.h rename to examples/energy-management-app/energy-management-common/energy-evse/include/energy-evse-modes.h diff --git a/examples/energy-management-app/energy-management-common/src/ChargingTargetsMemMgr.cpp b/examples/energy-management-app/energy-management-common/energy-evse/src/ChargingTargetsMemMgr.cpp similarity index 100% rename from examples/energy-management-app/energy-management-common/src/ChargingTargetsMemMgr.cpp rename to examples/energy-management-app/energy-management-common/energy-evse/src/ChargingTargetsMemMgr.cpp diff --git a/examples/energy-management-app/energy-management-common/src/EVSEManufacturerImpl.cpp b/examples/energy-management-app/energy-management-common/energy-evse/src/EVSEManufacturerImpl.cpp similarity index 100% rename from examples/energy-management-app/energy-management-common/src/EVSEManufacturerImpl.cpp rename to examples/energy-management-app/energy-management-common/energy-evse/src/EVSEManufacturerImpl.cpp diff --git a/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp b/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseDelegateImpl.cpp similarity index 100% rename from examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp rename to examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseDelegateImpl.cpp diff --git a/examples/energy-management-app/energy-management-common/src/EnergyEvseEventTriggers.cpp b/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseEventTriggers.cpp similarity index 100% rename from examples/energy-management-app/energy-management-common/src/EnergyEvseEventTriggers.cpp rename to examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseEventTriggers.cpp diff --git a/examples/energy-management-app/energy-management-common/src/EnergyEvseMain.cpp b/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseMain.cpp similarity index 100% rename from examples/energy-management-app/energy-management-common/src/EnergyEvseMain.cpp rename to examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseMain.cpp diff --git a/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp b/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseManager.cpp similarity index 100% rename from examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp rename to examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseManager.cpp diff --git a/examples/energy-management-app/energy-management-common/src/EnergyEvseTargetsStore.cpp b/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseTargetsStore.cpp similarity index 100% rename from examples/energy-management-app/energy-management-common/src/EnergyEvseTargetsStore.cpp rename to examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseTargetsStore.cpp diff --git a/examples/energy-management-app/energy-management-common/src/energy-evse-mode.cpp b/examples/energy-management-app/energy-management-common/energy-evse/src/energy-evse-mode.cpp similarity index 100% rename from examples/energy-management-app/energy-management-common/src/energy-evse-mode.cpp rename to examples/energy-management-app/energy-management-common/energy-evse/src/energy-evse-mode.cpp diff --git a/examples/energy-management-app/energy-management-common/include/ElectricalPowerMeasurementDelegate.h b/examples/energy-management-app/energy-management-common/energy-reporting/include/ElectricalPowerMeasurementDelegate.h similarity index 100% rename from examples/energy-management-app/energy-management-common/include/ElectricalPowerMeasurementDelegate.h rename to examples/energy-management-app/energy-management-common/energy-reporting/include/ElectricalPowerMeasurementDelegate.h diff --git a/examples/energy-management-app/energy-management-common/include/FakeReadings.h b/examples/energy-management-app/energy-management-common/energy-reporting/include/FakeReadings.h similarity index 100% rename from examples/energy-management-app/energy-management-common/include/FakeReadings.h rename to examples/energy-management-app/energy-management-common/energy-reporting/include/FakeReadings.h diff --git a/examples/energy-management-app/energy-management-common/include/PowerTopologyDelegate.h b/examples/energy-management-app/energy-management-common/energy-reporting/include/PowerTopologyDelegate.h similarity index 100% rename from examples/energy-management-app/energy-management-common/include/PowerTopologyDelegate.h rename to examples/energy-management-app/energy-management-common/energy-reporting/include/PowerTopologyDelegate.h diff --git a/examples/energy-management-app/energy-management-common/src/ElectricalPowerMeasurementDelegate.cpp b/examples/energy-management-app/energy-management-common/energy-reporting/src/ElectricalPowerMeasurementDelegate.cpp similarity index 100% rename from examples/energy-management-app/energy-management-common/src/ElectricalPowerMeasurementDelegate.cpp rename to examples/energy-management-app/energy-management-common/energy-reporting/src/ElectricalPowerMeasurementDelegate.cpp diff --git a/examples/energy-management-app/energy-management-common/src/EnergyReportingEventTriggers.cpp b/examples/energy-management-app/energy-management-common/energy-reporting/src/EnergyReportingEventTriggers.cpp similarity index 100% rename from examples/energy-management-app/energy-management-common/src/EnergyReportingEventTriggers.cpp rename to examples/energy-management-app/energy-management-common/energy-reporting/src/EnergyReportingEventTriggers.cpp diff --git a/examples/energy-management-app/energy-management-common/src/FakeReadings.cpp b/examples/energy-management-app/energy-management-common/energy-reporting/src/FakeReadings.cpp similarity index 100% rename from examples/energy-management-app/energy-management-common/src/FakeReadings.cpp rename to examples/energy-management-app/energy-management-common/energy-reporting/src/FakeReadings.cpp diff --git a/examples/energy-management-app/energy-management-common/src/PowerTopologyDelegate.cpp b/examples/energy-management-app/energy-management-common/energy-reporting/src/PowerTopologyDelegate.cpp similarity index 100% rename from examples/energy-management-app/energy-management-common/src/PowerTopologyDelegate.cpp rename to examples/energy-management-app/energy-management-common/energy-reporting/src/PowerTopologyDelegate.cpp diff --git a/examples/energy-management-app/energy-management-common/tests/BUILD.gn b/examples/energy-management-app/energy-management-common/tests/BUILD.gn index b55340a527233d..c11d783194229a 100644 --- a/examples/energy-management-app/energy-management-common/tests/BUILD.gn +++ b/examples/energy-management-app/energy-management-common/tests/BUILD.gn @@ -18,7 +18,7 @@ import("//build_overrides/chip.gni") import("${chip_root}/build/chip/chip_test_suite.gni") config("tests_config") { - include_dirs = [ "${chip_root}/examples/energy-management-app/energy-management-common/include" ] + include_dirs = [ "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/include" ] } chip_test_suite("tests") { diff --git a/examples/energy-management-app/esp32/main/CMakeLists.txt b/examples/energy-management-app/esp32/main/CMakeLists.txt index cce09303b58d72..03b823462594c9 100644 --- a/examples/energy-management-app/esp32/main/CMakeLists.txt +++ b/examples/energy-management-app/esp32/main/CMakeLists.txt @@ -19,7 +19,10 @@ set(PRIV_INCLUDE_DIRS_LIST "${APP_GEN_DIR}" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/include" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/common/include" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/device-energy-management/include" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/energy-evse/include" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/energy-reporting/include" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/esp32/main/include" "${CMAKE_CURRENT_LIST_DIR}/include" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32" @@ -29,7 +32,10 @@ set(SRC_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/attributes" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/src" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/common/src" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/device-energy-management/src" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/energy-evse/src" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/energy-reporting/src" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/ota" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/common" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/time" diff --git a/examples/energy-management-app/linux/BUILD.gn b/examples/energy-management-app/linux/BUILD.gn index 1a6e2d287fed2e..d2633c67c82b2a 100644 --- a/examples/energy-management-app/linux/BUILD.gn +++ b/examples/energy-management-app/linux/BUILD.gn @@ -34,23 +34,23 @@ config("includes") { executable("chip-energy-management-app") { sources = [ - "${chip_root}/examples/energy-management-app/energy-management-common/src/ChargingTargetsMemMgr.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/DEMTestEventTriggers.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EVSEManufacturerImpl.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/ElectricalPowerMeasurementDelegate.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseEventTriggers.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseMain.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseTargetsStore.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyReportingEventTriggers.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyTimeUtils.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/FakeReadings.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/PowerTopologyDelegate.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/device-energy-management-mode.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/energy-evse-mode.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/common/src/EnergyTimeUtils.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/src/DEMTestEventTriggers.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementDelegateImpl.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementManager.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/src/device-energy-management-mode.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/ChargingTargetsMemMgr.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EVSEManufacturerImpl.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseDelegateImpl.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseEventTriggers.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseMain.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseManager.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseTargetsStore.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/energy-evse-mode.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/src/ElectricalPowerMeasurementDelegate.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/src/EnergyReportingEventTriggers.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/src/FakeReadings.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/src/PowerTopologyDelegate.cpp", "include/CHIPProjectAppConfig.h", "main.cpp", ] @@ -71,7 +71,10 @@ executable("chip-energy-management-app") { include_dirs = [ "include", - "${chip_root}/examples/energy-management-app/energy-management-common/include", + "${chip_root}/examples/energy-management-app/energy-management-common/common/include", + "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/include", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/include", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/include", ] if (chip_enable_pw_rpc) { @@ -129,13 +132,13 @@ executable("chip-energy-management-app") { source_set("test-evse-targets-store") { sources = [ - "${chip_root}/examples/energy-management-app/energy-management-common/src/ChargingTargetsMemMgr.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseTargetsStore.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/ChargingTargetsMemMgr.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseTargetsStore.cpp", ] include_dirs = [ "include", - "${chip_root}/examples/energy-management-app/energy-management-common/include", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/include", ] deps = [ diff --git a/examples/energy-management-app/linux/README.md b/examples/energy-management-app/linux/README.md index ab35600709de47..c9d1dee04af7ca 100644 --- a/examples/energy-management-app/linux/README.md +++ b/examples/energy-management-app/linux/README.md @@ -1,4 +1,4 @@ -# CHIP Linux Energy Management Example +# Matter Linux Energy Management Example An example showing the use of CHIP on the Linux. The document will describe how to build and run CHIP Linux Energy Management Example on Raspberry Pi. This doc @@ -12,7 +12,7 @@ details.
-- [CHIP Linux Energy Management Example](#chip-linux-energy-management-example) +- [Matter Linux Energy Management Example](#matter-linux-energy-management-example) - [Building](#building) - [Commandline arguments](#commandline-arguments) - [Running the Complete Example on Raspberry Pi 4](#running-the-complete-example-on-raspberry-pi-4) diff --git a/examples/energy-management-app/silabs/.gn b/examples/energy-management-app/silabs/.gn new file mode 100644 index 00000000000000..b05216fc9d7eae --- /dev/null +++ b/examples/energy-management-app/silabs/.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") + +# 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 = "arm" + target_os = "freertos" + chip_openthread_ftd = true + + import("//openthread.gni") +} diff --git a/examples/energy-management-app/silabs/BUILD.gn b/examples/energy-management-app/silabs/BUILD.gn new file mode 100644 index 00000000000000..b51ed59de6f52c --- /dev/null +++ b/examples/energy-management-app/silabs/BUILD.gn @@ -0,0 +1,251 @@ +# 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("//build_overrides/efr32_sdk.gni") +import("//build_overrides/pigweed.gni") + +import("${build_root}/config/defaults.gni") +import("${efr32_sdk_build_root}/silabs_executable.gni") + +import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni") +import("${chip_root}/src/platform/device.gni") +import("${chip_root}/third_party/silabs/silabs_board.gni") + +if (chip_enable_pw_rpc) { + import("//build_overrides/pigweed.gni") + import("$dir_pw_build/target_types.gni") +} + +assert(current_os == "freertos") + +silabs_project_dir = "${chip_root}/examples/energy-management-app/silabs" +examples_common_plat_dir = "${chip_root}/examples/platform/silabs" + +if (wifi_soc) { + import("${chip_root}/third_party/silabs/SiWx917_sdk.gni") + examples_plat_dir = "${chip_root}/examples/platform/silabs/SiWx917" +} else { + import("${efr32_sdk_build_root}/efr32_sdk.gni") + examples_plat_dir = "${chip_root}/examples/platform/silabs/efr32" +} + +import("${examples_common_plat_dir}/args.gni") + +declare_args() { + # Dump memory usage at link time. + chip_print_memory_usage = false +} + +if (slc_generate) { + # Generate Project Specific config (Board, hardware used etc..) + print(exec_script("${chip_root}/third_party/silabs/slc_gen/run_slc.py", + [ + rebase_path(chip_root), + "${silabs_board}", + "${disable_lcd}", + "${use_wstk_buttons}", + "${use_wstk_leds}", + "${use_external_flash}", + "${silabs_mcu}", + rebase_path(slc_gen_path), + ], + "list lines")) +} + +if (wifi_soc) { + siwx917_sdk("sdk") { + sources = [ + "${examples_common_plat_dir}/FreeRTOSConfig.h", + "${silabs_project_dir}/include/CHIPProjectConfig.h", + ] + + include_dirs = [ + "${chip_root}/src/platform/silabs/SiWx917", + "${silabs_project_dir}/include", + "${examples_plat_dir}", + "${chip_root}/src/lib", + "${examples_common_plat_dir}", + ] + + defines = [] + if (chip_enable_pw_rpc) { + defines += [ + "HAL_VCOM_ENABLE=1", + "PW_RPC_ENABLED", + ] + } + } +} else { + efr32_sdk("sdk") { + sources = [ + "${examples_common_plat_dir}/FreeRTOSConfig.h", + "${silabs_project_dir}/include/CHIPProjectConfig.h", + ] + + include_dirs = [ + "${chip_root}/src/platform/silabs/efr32", + "${silabs_project_dir}/include", + "${examples_plat_dir}", + "${chip_root}/src/lib", + "${examples_common_plat_dir}", + "../energy-management-common/include", + ] + + if (use_wf200) { + # TODO efr32_sdk should not need a header from this location + include_dirs += [ "${examples_plat_dir}/wf200" ] + } + + if (chip_enable_ble_rs911x) { + # TODO efr32_sdk should not need a header from this location + include_dirs += [ + "${examples_plat_dir}/rs911x", + "${examples_plat_dir}/rs911x/hal", + ] + } + + defines = [] + if (chip_enable_pw_rpc) { + defines += [ + "HAL_VCOM_ENABLE=1", + "PW_RPC_ENABLED", + ] + } + } +} +silabs_executable("energy-management-app") { + output_name = "matter-silabs-energy-management-example.out" + include_dirs = [ "include" ] + defines = [] + + if (silabs_board == "BRD2704A") { + defines += [ "SL_STATUS_LED=0" ] + } + + sources = [ + "${chip_root}/examples/energy-management-app/energy-management-common/src/ChargingTargetsMemMgr.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/src/DEMTestEventTriggers.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/src/EVSEManufacturerImpl.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/src/ElectricalPowerMeasurementDelegate.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseEventTriggers.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseMain.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseTargetsStore.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyReportingEventTriggers.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyTimeUtils.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/src/FakeReadings.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/src/PowerTopologyDelegate.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/src/device-energy-management-mode.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/src/energy-evse-mode.cpp", + "${examples_common_plat_dir}/main.cpp", + "src/AppTask.cpp", + ] + + deps = [ + ":sdk", + app_data_model, + ] + + if (wifi_soc) { + deps += [ "${examples_plat_dir}:siwx917-common" ] + } else { + deps += [ "${examples_plat_dir}:efr32-common" ] + } + + if (chip_enable_pw_rpc) { + defines += [ + "PW_RPC_ENABLED", + "PW_RPC_ATTRIBUTE_SERVICE=1", + "PW_RPC_BUTTON_SERVICE=1", + "PW_RPC_DESCRIPTOR_SERVICE=1", + "PW_RPC_DEVICE_SERVICE=1", + "PW_RPC_LIGHTING_SERVICE=1", + "PW_RPC_OTCLI_SERVICE=1", + "PW_RPC_THREAD_SERVICE=1", + "PW_RPC_TRACING_SERVICE=1", + ] + + sources += [ + "${chip_root}/examples/common/pigweed/RpcService.cpp", + "${chip_root}/examples/common/pigweed/efr32/PigweedLoggerMutex.cpp", + "${examples_common_plat_dir}/PigweedLogger.cpp", + "${examples_common_plat_dir}/Rpc.cpp", + ] + + deps += [ + "$dir_pw_hdlc:rpc_channel_output", + "$dir_pw_stream:sys_io_stream", + "$dir_pw_trace", + "$dir_pw_trace_tokenized", + "$dir_pw_trace_tokenized:trace_rpc_service", + "${chip_root}/config/efr32/lib/pw_rpc:pw_rpc", + "${chip_root}/examples/common/pigweed:attributes_service.nanopb_rpc", + "${chip_root}/examples/common/pigweed:button_service.nanopb_rpc", + "${chip_root}/examples/common/pigweed:descriptor_service.nanopb_rpc", + "${chip_root}/examples/common/pigweed:device_service.nanopb_rpc", + "${chip_root}/examples/common/pigweed:lighting_service.nanopb_rpc", + "${chip_root}/examples/common/pigweed:ot_cli_service.nanopb_rpc", + "${chip_root}/examples/common/pigweed:thread_service.nanopb_rpc", + ] + + if (wifi_soc) { + deps += [ "${examples_plat_dir}/pw_sys_io:pw_sys_io_siwx917" ] + } else { + deps += [ "${examples_common_plat_dir}/pw_sys_io:pw_sys_io_silabs" ] + } + + deps += pw_build_LINK_DEPS + + include_dirs += [ + "${chip_root}/examples/common", + "${chip_root}/examples/common/pigweed/efr32", + ] + } + + ldscript = "${examples_common_plat_dir}/ldscripts/${silabs_family}.ld" + + inputs = [ ldscript ] + + ldflags = [ "-T" + rebase_path(ldscript, root_build_dir) ] + + if (chip_print_memory_usage) { + ldflags += [ + "-Wl,--print-memory-usage", + "-fstack-usage", + ] + } + + # WiFi Settings + if (chip_enable_wifi) { + ldflags += [ + "-Wl,--defsym", + "-Wl,SILABS_WIFI=1", + ] + } + + output_dir = root_out_dir +} + +group("silabs") { + deps = [ ":energy-management-app" ] +} + +group("default") { + deps = [ ":silabs" ] +} diff --git a/examples/energy-management-app/silabs/README.md b/examples/energy-management-app/silabs/README.md new file mode 100644 index 00000000000000..06fc6f5c46b176 --- /dev/null +++ b/examples/energy-management-app/silabs/README.md @@ -0,0 +1,364 @@ +# Matter EFR32 Energy Management Example + +An example showing the use of CHIP on the Silicon Labs EFR32 MG12 and MG24. + +
+ +- [Matter EFR32 Energy Management Example](#matter-efr32-energy-management-example) + - [Introduction](#introduction) + - [Building](#building) + - [Flashing the Application](#flashing-the-application) + - [Viewing Logging Output](#viewing-logging-output) + - [Running the Complete Example](#running-the-complete-example) + - [Notes](#notes) + - [Running RPC console](#running-rpc-console) + - [Device Tracing](#device-tracing) + - [Memory settings](#memory-settings) + - [OTA Software Update](#ota-software-update) + - [Group Communication (Multicast)](#group-communication-multicast) + - [Building options](#building-options) + - [Disabling logging](#disabling-logging) + - [Debug build / release build](#debug-build--release-build) + - [Disabling LCD](#disabling-lcd) + - [KVS maximum entry count](#kvs-maximum-entry-count) + +
+ +> **NOTE:** Silicon Laboratories now maintains a public matter GitHub repo with +> frequent releases thoroughly tested and validated. Developers looking to +> develop matter products with silabs hardware are encouraged to use our latest +> release with added tools and documentation. +> [Silabs Matter Github](https://github.com/SiliconLabs/matter/releases) + +## Introduction + +The EFR32 Energy Management example provides a baseline demonstration of a EVSE +device, built using Matter and the Silicon Labs gecko SDK. It can be controlled +by a Chip controller over an Openthread or Wifi network.. + +The EFR32 device can be commissioned over Bluetooth Low Energy where the device +and the Chip controller will exchange security information with the Rendez-vous +procedure. If using Thread, Thread Network credentials are then provided to the +EFR32 device which will then join the Thread network. + +If the LCD is enabled, the LCD on the Silabs WSTK shows a QR Code containing the +needed commissioning information for the BLE connection and starting the +Rendez-vous procedure. + +The EVSE example is intended to serve both as a means to explore the workings of +Matter as well as a template for creating real products based on the Silicon +Labs platform. + +## Building + +- Download the + [Simplicity Commander](https://www.silabs.com/mcu/programming-options) + command line tool, and ensure that `commander` is your shell search path. + (For Mac OS X, `commander` is located inside + `Commander.app/Contents/MacOS/`.) + +- Download and install a suitable ARM gcc tool chain: + [GNU Arm Embedded Toolchain 9-2019-q4-major](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads) + +- Install some additional tools (likely already present for CHIP developers): + + - Linux: `sudo apt-get install git ninja-build` + + - Mac OS X: `brew install ninja` + +- Supported hardware: + + - > For the latest supported hardware please refer to the + > [Hardware Requirements](https://github.com/SiliconLabs/matter/blob/latest/docs/silabs/general/HARDWARE_REQUIREMENTS.md) + > in the Silicon Labs Matter Github Repo + + MG24 boards : + + - BRD2601B / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm + - BRD2703A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm + - BRD4186A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@10dBm + - BRD4186C / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@10dBm + - BRD4187A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm + - BRD4187C / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm + - BRD2703A / MG24 Explorer Kit + - BRD2704A / SparkFun Thing Plus MGM240P board + +* Build the example application: + + cd ~/connectedhomeip + ./scripts/examples/gn_silabs_example.sh ./examples/energy-management-app/silabs/ ./out/energy-management-app BRD4187C + +- To delete generated executable, libraries and object files use: + + $ cd ~/connectedhomeip + $ rm -rf ./out/ + + OR use GN/Ninja directly + + $ cd ~/connectedhomeip/examples/energy-management-app/silabs + $ git submodule update --init + $ source third_party/connectedhomeip/scripts/activate.sh + $ export SILABS_BOARD=BRD4187C + $ gn gen out/debug + $ ninja -C out/debug + +- To delete generated executable, libraries and object files use: + + $ cd ~/connectedhomeip/examples/energy-management-app/silabs + $ rm -rf out/ + +* Build the example as Intermittently Connected Device (ICD) + + $ ./scripts/examples/gn_silabs_example.sh ./examples/energy-management-app/silabs/ ./out/energy-management-app_ICD BRD4187C --icd + + or use gn as previously mentioned but adding the following arguments: + + $ gn gen out/debug '--args=SILABS_BOARD="BRD4187C" enable_sleepy_device=true chip_openthread_ftd=false' + +* Build the example with pigweed RPC + + $ ./scripts/examples/gn_silabs_example.sh examples/energy-management-app/silabs/ out/energy_management_app_rpc BRD4187C 'import("//with_pw_rpc.gni")' + + or use GN/Ninja Directly + + $ cd ~/connectedhomeip/examples/energy-management-app/silabs + $ git submodule update --init + $ source third_party/connectedhomeip/scripts/activate.sh + $ export SILABS_BOARD=BRD4187C + $ gn gen out/debug --args='import("//with_pw_rpc.gni")' + $ ninja -C out/debug + + [Running Pigweed RPC console](#running-rpc-console) + +For more build options, help is provided when running the build script without +arguments + + ./scripts/examples/gn_silabs_example.sh + +## Flashing the Application + +- On the command line: + + $ cd ~/connectedhomeip/examples/energy-management-app/silabs + $ python3 out/debug/matter-silabs-energy-management-example.flash.py + +- Or with the Ozone debugger, just load the .out file. + +All EFR32 boards require a bootloader, see Silicon Labs documentation for more +info. Pre-built bootloader binaries are available in the Assets section of the +Releases page on +[Silabs Matter Github](https://github.com/SiliconLabs/matter/releases) . + +## Viewing Logging Output + +The example application is built to use the SEGGER Real Time Transfer (RTT) +facility for log output. RTT is a feature built-in to the J-Link Interface MCU +on the WSTK development board. It allows bi-directional communication with an +embedded application without the need for a dedicated UART. + +Using the RTT facility requires downloading and installing the _SEGGER J-Link +Software and Documentation Pack_ +([web site](https://www.segger.com/downloads/jlink#J-LinkSoftwareAndDocumentationPack)). + +Alternatively, SEGGER Ozone J-Link debugger can be used to view RTT logs too +after flashing the .out file. + +- Download the J-Link installer by navigating to the appropriate URL and + agreeing to the license agreement. + +- [JLink_Linux_x86_64.deb](https://www.segger.com/downloads/jlink/JLink_Linux_x86_64.deb) +- [JLink_MacOSX.pkg](https://www.segger.com/downloads/jlink/JLink_MacOSX.pkg) + +* Install the J-Link software + + $ cd ~/Downloads + $ sudo dpkg -i JLink_Linux_V*_x86_64.deb + +* In Linux, grant the logged in user the ability to talk to the development + hardware via the linux tty device (/dev/ttyACMx) by adding them to the + dialout group. + + $ sudo usermod -a -G dialout ${USER} + +Once the above is complete, log output can be viewed using the JLinkExe tool in +combination with JLinkRTTClient as follows: + +- Run the JLinkExe tool with arguments to autoconnect to the WSTK board: + + For MG12 use: + + $ JLinkExe -device EFR32MG12PXXXF1024 -if JTAG -speed 4000 -autoconnect 1 + + For MG21 use: + + $ JLinkExe -device EFR32MG21AXXXF1024 -if SWD -speed 4000 -autoconnect 1 + +- In a second terminal, run the JLinkRTTClient to view logs: + + $ JLinkRTTClient + +## Running the Complete Example + +- It is assumed here that you already have an OpenThread border router + configured and running. If not see the following guide + [Openthread_border_router](https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/openthread_border_router_pi.md) + for more information on how to setup a border router on a raspberryPi. + + Take note that the RCP code is available directly through + [Simplicity Studio 5](https://www.silabs.com/products/development-tools/software/simplicity-studio/simplicity-studio-5) + under File->New->Project Wizard->Examples->Thread : ot-rcp + +- User interface : **LCD** The LCD on Silabs WSTK shows a QR Code. This QR + Code is be scanned by the CHIP Tool app For the Rendez-vous procedure over + BLE + + * On devices that do not have or support the LCD Display like the BRD4166A Thunderboard Sense 2, + a URL can be found in the RTT logs. + + [SVR] Copy/paste the below URL in a browser to see the QR Code: + [SVR] https://project-chip.github.io/connectedhomeip/qrcode.html?data=CH%3AI34NM%20-00%200C9SS0 + + **LED 0** shows the overall state of the device and its connectivity. The + following states are possible: + + - _Short Flash On (50 ms on/950 ms off)_ ; The device is in the + unprovisioned (unpaired) state and is waiting for a commissioning + application to connect. + + - _Rapid Even Flashing_ ; (100 ms on/100 ms off)_ — The device is in the + unprovisioned state and a commissioning application is connected through + Bluetooth LE. + + - _Short Flash Off_ ; (950ms on/50ms off)_ — The device is fully + provisioned, but does not yet have full Thread network or service + connectivity. + + - _Solid On_ ; The device is fully provisioned and has full Thread + network and service connectivity. + + **Push Button 0** + + - _Press and Release_ : Start, or restart, BLE advertisement in fast mode. It will advertise in this mode + for 30 seconds. The device will then switch to a slower interval advertisement. + After 15 minutes, the advertisement stops. + + - _Pressed and hold for 6 s_ : Initiates the factory reset of the device. + Releasing the button within the 6-second window cancels the factory reset + procedure. **LEDs** blink in unison when the factory reset procedure is + initiated. + +* You can provision and control the Chip device using the python controller, + Chip tool standalone, Android or iOS app + +* You can provision and control the Chip device using the python controller, + Chip tool standalone, Android or iOS app + + [CHIPTool](https://github.com/project-chip/connectedhomeip/blob/master/examples/chip-tool/README.md) + + Here is an example with the chip-tool: + + $ chip-tool pairing ble-thread 1 hex: 20202021 3840 + +### Notes + +- Depending on your network settings your router might not provide native ipv6 + addresses to your devices (Border router / PC). If this is the case, you + need to add a static ipv6 addresses on both device and then an ipv6 route to + the border router on your PC + + - On Border Router: `sudo ip addr add dev 2002::2/64` + + - On PC(Linux): `sudo ip addr add dev 2002::1/64` + + - Add Ipv6 route on PC(Linux) + `sudo ip route add /64 via 2002::2` + +## Running RPC console + +- As part of building the example with RPCs enabled the chip_rpc python + interactive console is installed into your venv. The python wheel files are + also created in the output folder: out/debug/chip_rpc_console_wheels. To + install the wheel files without rebuilding: + `pip3 install out/debug/chip_rpc_console_wheels/*.whl` + +- To use the chip-rpc console after it has been installed run: + `chip-console --device /dev/tty. -b 115200 -o //pw_log.out` + +- Then you can simulate a button press or release using the following command + where : idx = 0 or 1 for Button PB0 or PB1 action = 0 for PRESSED, 1 for + RELEASE Test toggling the LED with + `rpcs.chip.rpc.Button.Event(idx=1, pushed=True)` + +## Device Tracing + +Device tracing is available to analyze the device performance. To turn on +tracing, build with RPC enabled. See Build the example with pigweed RPC. + +Obtain tracing json file. + + $ ./{PIGWEED_REPO}/pw_trace_tokenized/py/pw_trace_tokenized/get_trace.py -d {PORT} -o {OUTPUT_FILE} \ + -t {ELF_FILE} {PIGWEED_REPO}/pw_trace_tokenized/pw_trace_protos/trace_rpc.proto + +## Memory settings + +While most of the RAM usage in CHIP is static, allowing easier debugging and +optimization with symbols analysis, we still need some HEAP for the crypto and +OpenThread. Size of the HEAP can be modified by changing the value of the +`configTOTAL_HEAP_SIZE` define inside of the FreeRTOSConfig.h file of this +example. Please take note that a HEAP size smaller than 13k can and will cause a +Mbedtls failure during the BLE rendez-vous or CASE session + +To track memory usage you can set `enable_heap_monitoring = true` either in the +BUILD.gn file or pass it as a build argument to gn. This will print on the RTT +console the RAM usage of each individual task and the number of Memory +allocation and Free. While this is not extensive monitoring you're welcome to +modify `examples/platform/silabs/MemMonitoring.cpp` to add your own memory +tracking code inside the `trackAlloc` and `trackFree` function + +## OTA Software Update + +For the description of Software Update process with EFR32 example applications +see +[EFR32 OTA Software Update](../../../docs/guides/silabs_efr32_software_update.md) + +## Group Communication (Multicast) + +With this Energy Management example you can also use group communication to send +Energy Management commands to multiples devices at once. Please refer to the +[chip-tool documentation](../../chip-tool/README.md) _Configuring the server +side for Group Commands_ and _Using the Client to Send Group (Multicast) Matter +Commands_ + +## Building options + +All of Silabs's examples within the Matter repo have all the features enabled by +default, as to provide the best end user experience. However some of those +features can easily be toggled on or off. Here is a short list of options to be +passed to the build scripts. + +### Disabling logging + +`chip_progress_logging, chip_detail_logging, chip_automation_logging` + + $ ./scripts/examples/gn_silabs_example.sh ./examples/energy-management-app/silabs ./out/energy-management-app BRD4164A "chip_detail_logging=false chip_automation_logging=false chip_progress_logging=false" + +### Debug build / release build + +`is_debug` + + $ ./scripts/examples/gn_silabs_example.sh ./examples/energy-management-app/silabs ./out/energy-management-app BRD4164A "is_debug=false" + +### Disabling LCD + +`show_qr_code` + + $ ./scripts/examples/gn_silabs_example.sh ./examples/energy-management-app/silabs ./out/energy-management-app BRD4164A "show_qr_code=false" + +### KVS maximum entry count + +`kvs_max_entries` + + Set the maximum Kvs entries that can be stored in NVM (Default 75) + Thresholds: 30 <= kvs_max_entries <= 255 + + $ ./scripts/examples/gn_silabs_example.sh ./examples/energy-management-app/silabs ./out/energy-management-app BRD4164A kvs_max_entries=50 diff --git a/examples/platform/nxp/k32w/k32w1/app/BUILD.gn b/examples/energy-management-app/silabs/build_for_wifi_args.gni similarity index 62% rename from examples/platform/nxp/k32w/k32w1/app/BUILD.gn rename to examples/energy-management-app/silabs/build_for_wifi_args.gni index 6671d140688df9..bfded904a34176 100644 --- a/examples/platform/nxp/k32w/k32w1/app/BUILD.gn +++ b/examples/energy-management-app/silabs/build_for_wifi_args.gni @@ -11,17 +11,14 @@ # 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/standalone/args.gni") -config("chip_examples_project_config") { - include_dirs = [ "app/project_include" ] -} - -source_set("openthread_core_config_k32w1_chip_examples") { - sources = [ "app/project_include/OpenThreadConfig.h" ] - - public_deps = [ "${chip_root}/third_party/openthread/platforms/nxp/k32w/k32w1:openthread_core_config_k32w1" ] +silabs_sdk_target = get_label_info(":sdk", "label_no_toolchain") +chip_enable_openthread = false +import("${chip_root}/src/platform/silabs/wifi_args.gni") - public_configs = [ ":chip_examples_project_config" ] -} +chip_enable_ota_requestor = false +disable_lcd = true +app_data_model = + "${chip_root}/examples/energy-management-app/energy-management-common" diff --git a/examples/energy-management-app/silabs/build_for_wifi_gnfile.gn b/examples/energy-management-app/silabs/build_for_wifi_gnfile.gn new file mode 100644 index 00000000000000..d391814190d09f --- /dev/null +++ b/examples/energy-management-app/silabs/build_for_wifi_gnfile.gn @@ -0,0 +1,28 @@ +# 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") + +# 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 = "arm" + target_os = "freertos" + chip_enable_wifi = true + import("//build_for_wifi_args.gni") +} diff --git a/examples/energy-management-app/silabs/build_overrides b/examples/energy-management-app/silabs/build_overrides new file mode 120000 index 00000000000000..e578e73312ebd1 --- /dev/null +++ b/examples/energy-management-app/silabs/build_overrides @@ -0,0 +1 @@ +../../build_overrides \ No newline at end of file diff --git a/examples/energy-management-app/silabs/include/AppConfig.h b/examples/energy-management-app/silabs/include/AppConfig.h new file mode 100644 index 00000000000000..bbd4d201124fbf --- /dev/null +++ b/examples/energy-management-app/silabs/include/AppConfig.h @@ -0,0 +1,28 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * 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 "silabs_utils.h" + +// ---- EVSE Example App Config ---- + +#define APP_TASK_NAME "EVSE" + +#define BLE_DEV_NAME "SiLabs-EVSE" diff --git a/examples/lighting-app/nxp/k32w/k32w1/main/include/AppEvent.h b/examples/energy-management-app/silabs/include/AppEvent.h similarity index 82% rename from examples/lighting-app/nxp/k32w/k32w1/main/include/AppEvent.h rename to examples/energy-management-app/silabs/include/AppEvent.h index 902c70b3cb656f..7f28962b50633f 100644 --- a/examples/lighting-app/nxp/k32w/k32w1/main/include/AppEvent.h +++ b/examples/energy-management-app/silabs/include/AppEvent.h @@ -1,6 +1,7 @@ /* * - * Copyright (c) 2021 Nest Labs, Inc. + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2018 Nest Labs, Inc. * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,21 +26,17 @@ struct AppEvent { enum AppEventTypes { - kEventType_None = 0, - kEventType_Button, + kEventType_Button = 0, kEventType_Timer, - kEventType_TurnOn, kEventType_Install, - kEventType_OTAResume, }; - AppEventTypes Type; + uint16_t Type; union { struct { - uint8_t PinNo; uint8_t Action; } ButtonEvent; struct @@ -50,7 +47,7 @@ struct AppEvent { uint8_t Action; int32_t Actor; - } LightEvent; + } EvseEvent; }; EventHandler Handler; diff --git a/examples/energy-management-app/silabs/include/AppTask.h b/examples/energy-management-app/silabs/include/AppTask.h new file mode 100644 index 00000000000000..99114610948952 --- /dev/null +++ b/examples/energy-management-app/silabs/include/AppTask.h @@ -0,0 +1,110 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * 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 + +/********************************************************** + * Includes + *********************************************************/ + +#include +#include + +#include "AppEvent.h" +#include "BaseApplication.h" +#include "EnergyEvseManager.h" +#include "FreeRTOS.h" +#include "timers.h" // provides FreeRTOS timer support +#include +#include +#include + +/********************************************************** + * Defines + *********************************************************/ + +// Application-defined error codes in the CHIP_ERROR space. +#define APP_ERROR_EVENT_QUEUE_FAILED CHIP_APPLICATION_ERROR(0x01) +#define APP_ERROR_CREATE_TASK_FAILED CHIP_APPLICATION_ERROR(0x02) +#define APP_ERROR_UNHANDLED_EVENT CHIP_APPLICATION_ERROR(0x03) +#define APP_ERROR_CREATE_TIMER_FAILED CHIP_APPLICATION_ERROR(0x04) +#define APP_ERROR_START_TIMER_FAILED CHIP_APPLICATION_ERROR(0x05) +#define APP_ERROR_STOP_TIMER_FAILED CHIP_APPLICATION_ERROR(0x06) + +/********************************************************** + * AppTask Declaration + *********************************************************/ + +class AppTask : public BaseApplication +{ + +public: + AppTask() = default; + + static AppTask & GetAppTask() { return sAppTask; } + + /** + * @brief AppTask task main loop function + * + * @param pvParameter FreeRTOS task parameter + */ + static void AppTaskMain(void * pvParameter); + + CHIP_ERROR StartAppTask(); + + /** + * @brief Event handler when a button is pressed + * Function posts an event for button processing + * + * @param buttonHandle APP_FUNCTION_BUTTON + * @param btnAction button action - SL_SIMPLE_BUTTON_PRESSED, + * SL_SIMPLE_BUTTON_RELEASED or SL_SIMPLE_BUTTON_DISABLED + */ + static void ButtonEventHandler(uint8_t button, uint8_t btnAction); + +private: + static AppTask sAppTask; + static void EvseActionEventHandler(AppEvent * aEvent); + + static void UpdateClusterState(intptr_t context); + + /** + * @brief AppTask initialisation function + * + * @return CHIP_ERROR + */ + CHIP_ERROR Init(); + + /** + * @brief PB0 Button event processing function + * Press and hold will trigger a factory reset timer start + * Press and release will restart BLEAdvertising if not commisionned + * + * @param aEvent button event being processed + */ + static void ButtonHandler(AppEvent * aEvent); + + /** + * @brief PB1 Button event processing function + * Function triggers a switch action sent to the CHIP task + * + * @param aEvent button event being processed + */ + static void SwitchActionEventHandler(AppEvent * aEvent); +}; diff --git a/examples/energy-management-app/silabs/include/CHIPProjectConfig.h b/examples/energy-management-app/silabs/include/CHIPProjectConfig.h new file mode 100644 index 00000000000000..62943f4eef1b63 --- /dev/null +++ b/examples/energy-management-app/silabs/include/CHIPProjectConfig.h @@ -0,0 +1,102 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Example project configuration file for CHIP. + * + * This is a place to put application or project-specific overrides + * to the default configuration values for general CHIP features. + * + */ + +#pragma once + +// Use a default pairing code if one hasn't been provisioned in flash. +#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE +#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021 +#endif + +#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR +#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 +#endif + +// For convenience, Chip Security Test Mode can be enabled and the +// requirement for authentication in various protocols can be disabled. +// +// WARNING: These options make it possible to circumvent basic Chip security functionality, +// including message encryption. Because of this they MUST NEVER BE ENABLED IN PRODUCTION BUILDS. +// +#define CHIP_CONFIG_SECURITY_TEST_MODE 0 + +/** + * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID + * + * 0xFFF1: Test vendor + */ +#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF1 + +/** + * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID + * + * 0x8005: example EVSE app + */ +#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8005 + +/** + * CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE + * + * Enable support for Chip-over-BLE (CHIPoBLE). + */ +#define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE 1 + +/** + * CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER + * + * Enables the use of a hard-coded default serial number if none + * is found in Chip NV storage. + */ +#define CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER "TEST_SN" + +/** + * CHIP_DEVICE_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS + * + * Enable recording UTC timestamps. + */ +#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS 1 + +/** + * CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE + * + * A size, in bytes, of the individual debug event logging buffer. + */ +#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE (512) + +/** + * @def CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL + * + * @brief + * Active retransmit interval, or time to wait before retransmission after + * subsequent failures in milliseconds. + * + * This is the default value, that might be adjusted by end device depending on its + * needs (e.g. sleeping period) using Service Discovery TXT record CRA key. + * + */ +#define CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL (2000_ms32) diff --git a/examples/energy-management-app/silabs/openthread.gn b/examples/energy-management-app/silabs/openthread.gn new file mode 100644 index 00000000000000..b05216fc9d7eae --- /dev/null +++ b/examples/energy-management-app/silabs/openthread.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") + +# 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 = "arm" + target_os = "freertos" + chip_openthread_ftd = true + + import("//openthread.gni") +} diff --git a/examples/platform/nxp/k32w/k32w1/app/args.gni b/examples/energy-management-app/silabs/openthread.gni similarity index 55% rename from examples/platform/nxp/k32w/k32w1/app/args.gni rename to examples/energy-management-app/silabs/openthread.gni index 2705c251fb807d..2813a5a1fb0bda 100644 --- a/examples/platform/nxp/k32w/k32w1/app/args.gni +++ b/examples/energy-management-app/silabs/openthread.gni @@ -13,16 +13,16 @@ # limitations under the License. import("//build_overrides/chip.gni") +import("${chip_root}/config/standalone/args.gni") +import("${chip_root}/src/platform/silabs/efr32/args.gni") -import("${chip_root}/src/platform/nxp/k32w/k32w1/args.gni") +silabs_sdk_target = get_label_info(":sdk", "label_no_toolchain") -openthread_project_core_config_file = "OpenThreadConfig.h" +app_data_model = + "${chip_root}/examples/energy-management-app/energy-management-common" +chip_enable_ota_requestor = false +chip_enable_openthread = true +disable_lcd = true -chip_ble_project_config_include = "" -chip_device_project_config_include = "" -chip_project_config_include = "" -chip_inet_project_config_include = "" -chip_system_project_config_include = "" - -chip_system_config_provide_statistics = false -chip_with_nlfaultinjection = true +openthread_external_platform = + "${chip_root}/third_party/openthread/platforms/efr32:libopenthread-efr32" diff --git a/examples/energy-management-app/silabs/src/AppTask.cpp b/examples/energy-management-app/silabs/src/AppTask.cpp new file mode 100644 index 00000000000000..4ed73efb28711e --- /dev/null +++ b/examples/energy-management-app/silabs/src/AppTask.cpp @@ -0,0 +1,212 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * 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 "AppTask.h" +#include "AppConfig.h" +#include "AppEvent.h" +#include "LEDWidget.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +#include + +#if (defined(SL_CATALOG_SIMPLE_LED_LED1_PRESENT) || defined(SIWX_917)) +#define EVSE_LED 1 +#else +#define EVSE_LED 0 +#endif + +#define APP_FUNCTION_BUTTON 0 +#define APP_EVSE_SWITCH 1 + +namespace { +LEDWidget sEvseLED; +} + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::DeviceEnergyManagement; +using namespace chip::app::Clusters::DeviceEnergyManagement::Attributes; +using namespace ::chip::DeviceLayer; +using namespace ::chip::DeviceLayer::Silabs; +using namespace ::chip::DeviceLayer::Internal; +using namespace chip::TLV; + +namespace chip { +namespace app { +namespace Clusters { +namespace DeviceEnergyManagement { + +// Keep track of the parsed featureMap option +static chip::BitMask sFeatureMap(Feature::kPowerAdjustment, Feature::kPowerForecastReporting, + Feature::kStateForecastReporting, Feature::kStartTimeAdjustment, Feature::kPausable, + Feature::kForecastAdjustment, Feature::kConstraintBasedAdjustment); + +chip::BitMask GetFeatureMapFromCmdLine() +{ + return sFeatureMap; +} + +} // namespace DeviceEnergyManagement +} // namespace Clusters +} // namespace app +} // namespace chip + +AppTask AppTask::sAppTask; + +void ApplicationInit() +{ + chip::DeviceLayer::PlatformMgr().LockChipStack(); + EvseApplicationInit(); + sEvseLED.Init(EVSE_LED); + chip::DeviceLayer::PlatformMgr().UnlockChipStack(); +} +void ApplicationShutdown() +{ + chip::DeviceLayer::PlatformMgr().LockChipStack(); + EvseApplicationShutdown(); + chip::DeviceLayer::PlatformMgr().UnlockChipStack(); +} + +CHIP_ERROR AppTask::Init() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + chip::DeviceLayer::Silabs::GetPlatform().SetButtonsCb(AppTask::ButtonEventHandler); + +#ifdef DISPLAY_ENABLED + GetLCD().Init((uint8_t *) "energy-management-App"); +#endif + + err = BaseApplication::Init(); + if (err != CHIP_NO_ERROR) + { + SILABS_LOG("BaseApplication::Init() failed"); + appError(err); + } + + ApplicationInit(); + +// Update the LCD with the Stored value. Show QR Code if not provisioned +#ifdef DISPLAY_ENABLED + GetLCD().WriteDemoUI(LightMgr().IsLightOn()); +#ifdef QR_CODE_ENABLED +#ifdef SL_WIFI + if (!chip::DeviceLayer::ConnectivityMgr().IsWiFiStationProvisioned()) +#else + if (!chip::DeviceLayer::ConnectivityMgr().IsThreadProvisioned()) +#endif /* !SL_WIFI */ + { + GetLCD().ShowQRCode(true); + } +#endif // QR_CODE_ENABLED +#endif + + return err; +} + +CHIP_ERROR AppTask::StartAppTask() +{ + return BaseApplication::StartAppTask(AppTaskMain); +} + +void AppTask::AppTaskMain(void * pvParameter) +{ + AppEvent event; + osMessageQueueId_t sAppEventQueue = *(static_cast(pvParameter)); + + CHIP_ERROR err = sAppTask.Init(); + if (err != CHIP_NO_ERROR) + { + SILABS_LOG("AppTask.Init() failed"); + appError(err); + } + + SILABS_LOG("App Task started"); + + while (true) + { + osStatus_t eventReceived = osMessageQueueGet(sAppEventQueue, &event, NULL, osWaitForever); + while (eventReceived == osOK) + { + sAppTask.DispatchEvent(&event); + eventReceived = osMessageQueueGet(sAppEventQueue, &event, NULL, 0); + } + } +} + +void AppTask::EvseActionEventHandler(AppEvent * aEvent) +{ + bool initiated = false; + int32_t actor; + CHIP_ERROR err = CHIP_NO_ERROR; + + if (aEvent->Type == AppEvent::kEventType_Button) + { + actor = AppEvent::kEventType_Button; + SILABS_LOG("button event %d ", actor); + } + else + { + err = APP_ERROR_UNHANDLED_EVENT; + } + + if (err == CHIP_NO_ERROR) + { + if (!initiated) + { + SILABS_LOG("Action is already in progress or active."); + } + } +} + +void AppTask::ButtonEventHandler(uint8_t button, uint8_t btnAction) +{ + AppEvent button_event = {}; + button_event.Type = AppEvent::kEventType_Button; + button_event.ButtonEvent.Action = btnAction; + + if (button == APP_EVSE_SWITCH && btnAction == static_cast(SilabsPlatform::ButtonAction::ButtonPressed)) + { + button_event.Handler = EvseActionEventHandler; + AppTask::GetAppTask().PostEvent(&button_event); + } + else if (button == APP_FUNCTION_BUTTON) + { + button_event.Handler = BaseApplication::ButtonHandler; + AppTask::GetAppTask().PostEvent(&button_event); + } +} diff --git a/examples/energy-management-app/silabs/third_party/connectedhomeip b/examples/energy-management-app/silabs/third_party/connectedhomeip new file mode 120000 index 00000000000000..c866b86874994d --- /dev/null +++ b/examples/energy-management-app/silabs/third_party/connectedhomeip @@ -0,0 +1 @@ +../../../.. \ No newline at end of file diff --git a/examples/energy-management-app/silabs/with_pw_rpc.gni b/examples/energy-management-app/silabs/with_pw_rpc.gni new file mode 100644 index 00000000000000..ac5d9953a3b924 --- /dev/null +++ b/examples/energy-management-app/silabs/with_pw_rpc.gni @@ -0,0 +1,30 @@ +# 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. + +# add this gni as import in your build args to use pigweed in the example +# 'import("//with_pw_rpc.gni")' + +import("//build_overrides/chip.gni") +import("${chip_root}/config/efr32/lib/pw_rpc/pw_rpc.gni") +import("${chip_root}/examples/platform/silabs/args.gni") + +silabs_sdk_target = get_label_info(":sdk", "label_no_toolchain") + +app_data_model = + "${chip_root}/examples/energy-management-app/energy-management-common" +chip_enable_pw_rpc = true +chip_enable_openthread = true + +# Light app on EFR enables tracing server +pw_trace_BACKEND = "$dir_pw_trace_tokenized" diff --git a/examples/fabric-admin/BUILD.gn b/examples/fabric-admin/BUILD.gn index be8313d7a944ac..77e851a53c36d2 100644 --- a/examples/fabric-admin/BUILD.gn +++ b/examples/fabric-admin/BUILD.gn @@ -69,9 +69,15 @@ static_library("fabric-admin-utils") { "commands/common/Commands.h", "commands/common/CredentialIssuerCommands.h", "commands/common/HexConversion.h", + "commands/common/IcdManager.cpp", + "commands/common/IcdManager.h", "commands/common/RemoteDataModelLogger.cpp", "commands/common/RemoteDataModelLogger.h", + "commands/common/StayActiveSender.cpp", + "commands/common/StayActiveSender.h", "commands/fabric-sync/FabricSyncCommand.cpp", + "commands/pairing/DeviceSynchronization.cpp", + "commands/pairing/DeviceSynchronization.h", "commands/pairing/OpenCommissioningWindowCommand.cpp", "commands/pairing/OpenCommissioningWindowCommand.h", "commands/pairing/PairingCommand.cpp", diff --git a/examples/fabric-admin/README.md b/examples/fabric-admin/README.md index da2a4d6b21684e..7178ab2c2f8c94 100644 --- a/examples/fabric-admin/README.md +++ b/examples/fabric-admin/README.md @@ -14,7 +14,7 @@ fabrics. For Linux host example: ``` -./scripts/examples/gn_build_example.sh examples/fabric-admin out/debug/standalone chip_config_network_layer_ble=false 'import("//with_pw_rpc.gni")' +./scripts/examples/gn_build_example.sh examples/fabric-admin out/debug/standalone 'import("//with_pw_rpc.gni")' ``` For Raspberry Pi 4 example: diff --git a/examples/fabric-admin/commands/clusters/ReportCommand.cpp b/examples/fabric-admin/commands/clusters/ReportCommand.cpp index 8eb2cc7c33ae0d..ff52a30e661342 100644 --- a/examples/fabric-admin/commands/clusters/ReportCommand.cpp +++ b/examples/fabric-admin/commands/clusters/ReportCommand.cpp @@ -46,7 +46,7 @@ void ReportCommand::OnAttributeData(const app::ConcreteDataAttributePath & path, LogErrorOnFailure(RemoteDataModelLogger::LogAttributeAsJSON(path, data)); - DeviceMgr().HandleAttributeChange(path, data); + DeviceMgr().HandleAttributeData(path, data); } void ReportCommand::OnEventData(const app::EventHeader & eventHeader, TLV::TLVReader * data, const app::StatusIB * status) @@ -73,11 +73,5 @@ void ReportCommand::OnEventData(const app::EventHeader & eventHeader, TLV::TLVRe LogErrorOnFailure(RemoteDataModelLogger::LogEventAsJSON(eventHeader, data)); - CHIP_ERROR error = DataModelLogger::LogEvent(eventHeader, data); - if (CHIP_NO_ERROR != error) - { - ChipLogError(NotSpecified, "Response Failure: Can not decode Data"); - mError = error; - return; - } + DeviceMgr().HandleEventData(eventHeader, data); } diff --git a/examples/fabric-admin/commands/common/CHIPCommand.cpp b/examples/fabric-admin/commands/common/CHIPCommand.cpp index 982c857d206136..0c5455439b22d9 100644 --- a/examples/fabric-admin/commands/common/CHIPCommand.cpp +++ b/examples/fabric-admin/commands/common/CHIPCommand.cpp @@ -18,6 +18,7 @@ #include "CHIPCommand.h" +#include "IcdManager.h" #include #include #include @@ -52,7 +53,6 @@ chip::Credentials::GroupDataProviderImpl CHIPCommand::sGroupDataProvider{ kMaxGr // All fabrics share the same ICD client storage. chip::app::DefaultICDClientStorage CHIPCommand::sICDClientStorage; chip::Crypto::RawKeySessionKeystore CHIPCommand::sSessionKeystore; -chip::app::DefaultCheckInDelegate CHIPCommand::sCheckInDelegate; chip::app::CheckInHandler CHIPCommand::sCheckInHandler; namespace { @@ -148,9 +148,9 @@ CHIP_ERROR CHIPCommand::MaybeSetUpStack() auto engine = chip::app::InteractionModelEngine::GetInstance(); VerifyOrReturnError(engine != nullptr, CHIP_ERROR_INCORRECT_STATE); - ReturnLogErrorOnFailure(sCheckInDelegate.Init(&sICDClientStorage, engine)); + ReturnLogErrorOnFailure(IcdManager::Instance().Init(&sICDClientStorage, engine)); ReturnLogErrorOnFailure(sCheckInHandler.Init(DeviceControllerFactory::GetInstance().GetSystemState()->ExchangeMgr(), - &sICDClientStorage, &sCheckInDelegate, engine)); + &sICDClientStorage, &IcdManager::Instance(), engine)); CommissionerIdentity nullIdentity{ kIdentityNull, chip::kUndefinedNodeId }; ReturnLogErrorOnFailure(InitializeCommissioner(nullIdentity, kIdentityNullFabricId)); diff --git a/examples/fabric-admin/commands/common/CHIPCommand.h b/examples/fabric-admin/commands/common/CHIPCommand.h index af833f5f718652..abd68f6344ea44 100644 --- a/examples/fabric-admin/commands/common/CHIPCommand.h +++ b/examples/fabric-admin/commands/common/CHIPCommand.h @@ -51,6 +51,8 @@ inline constexpr char kIdentityGamma[] = "gamma"; // (CASE) communcation. inline constexpr char kIdentityNull[] = "null-fabric-commissioner"; +constexpr uint16_t kMaxCommandSize = 384; + class CHIPCommand : public Command { public: @@ -166,7 +168,6 @@ class CHIPCommand : public Command static chip::Credentials::GroupDataProviderImpl sGroupDataProvider; static chip::app::DefaultICDClientStorage sICDClientStorage; - static chip::app::DefaultCheckInDelegate sCheckInDelegate; static chip::app::CheckInHandler sCheckInHandler; CredentialIssuerCommands * mCredIssuerCmds; diff --git a/examples/fabric-admin/commands/common/IcdManager.cpp b/examples/fabric-admin/commands/common/IcdManager.cpp new file mode 100644 index 00000000000000..201d7325541982 --- /dev/null +++ b/examples/fabric-admin/commands/common/IcdManager.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "IcdManager.h" + +IcdManager IcdManager::sInstance; + +IcdManager & IcdManager::Instance() +{ + return sInstance; +} + +void IcdManager::OnCheckInComplete(const chip::app::ICDClientInfo & clientInfo) +{ + DefaultCheckInDelegate::OnCheckInComplete(clientInfo); + if (mDelegate) + { + mDelegate->OnCheckInCompleted(clientInfo); + } +} + +void IcdManager::SetDelegate(Delegate * delegate) +{ + // To keep IcdManager simple, there is an assumption that there is only ever + // one delegate set and it's lifetime is identical to IcdManager. In the + // future this assumption can change should there be a need, but that will + // require code changes to IcdManager. For now we will crash if someone tries + // to call SetDelegate for a second time or if delegate is non-null. + VerifyOrDie(delegate); + VerifyOrDie(!mDelegate); + mDelegate = delegate; +} diff --git a/examples/fabric-admin/commands/common/IcdManager.h b/examples/fabric-admin/commands/common/IcdManager.h new file mode 100644 index 00000000000000..8993f24e531e83 --- /dev/null +++ b/examples/fabric-admin/commands/common/IcdManager.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#pragma once + +#include + +/** + * @brief Manages check-ins from ICD devices. + * + * Intended to be used as a thin CheckInDelegate. This allows a delegate register + * themselves so they can be aware when ICD device checks-in allowing the + * delegate to interact with the ICD device during the short window that it is + * awake. + */ +class IcdManager : public chip::app::DefaultCheckInDelegate +{ +public: + class Delegate + { + public: + virtual ~Delegate() = default; + virtual void OnCheckInCompleted(const chip::app::ICDClientInfo & clientInfo) = 0; + }; + + static IcdManager & Instance(); + void OnCheckInComplete(const chip::app::ICDClientInfo & clientInfo) override; + + // There is an assumption delegate assigned only happens once and that it lives + // for the entirety of the lifetime of fabric admin. + void SetDelegate(Delegate * delegate); + +private: + static IcdManager sInstance; + Delegate * mDelegate = nullptr; +}; diff --git a/examples/fabric-admin/commands/common/StayActiveSender.cpp b/examples/fabric-admin/commands/common/StayActiveSender.cpp new file mode 100644 index 00000000000000..16f1d5cd132f81 --- /dev/null +++ b/examples/fabric-admin/commands/common/StayActiveSender.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "StayActiveSender.h" + +#include +#include +#include +#include + +CHIP_ERROR StayActiveSender::SendStayActiveCommand(uint32_t stayActiveDurationMs, const chip::ScopedNodeId & peerNode, + chip::app::InteractionModelEngine * engine, OnDoneCallbackType onDone) +{ + ConstructorOnlyInternallyCallable internal; + auto stayActiveSender = chip::Platform::New(internal, stayActiveDurationMs, peerNode, + chip::app::InteractionModelEngine::GetInstance(), onDone); + VerifyOrReturnError(stayActiveSender != nullptr, CHIP_ERROR_NO_MEMORY); + CHIP_ERROR err = stayActiveSender->EstablishSessionToPeer(); + if (CHIP_NO_ERROR != err) + { + chip::Platform::Delete(stayActiveSender); + } + return err; +} + +StayActiveSender::StayActiveSender(const ConstructorOnlyInternallyCallable & _, uint32_t stayActiveDurationMs, + const chip::ScopedNodeId & peerNode, chip::app::InteractionModelEngine * engine, + OnDoneCallbackType onDone) : + mStayActiveDurationMs(stayActiveDurationMs), + mPeerNode(peerNode), mpImEngine(engine), mOnDone(onDone), mOnConnectedCallback(HandleDeviceConnected, this), + mOnConnectionFailureCallback(HandleDeviceConnectionFailure, this) +{} + +CHIP_ERROR StayActiveSender::SendStayActiveCommand(chip::Messaging::ExchangeManager & exchangeMgr, + const chip::SessionHandle & sessionHandle) +{ + auto onSuccess = [&](const chip::app::ConcreteCommandPath & commandPath, const chip::app::StatusIB & status, + const auto & dataResponse) { + uint32_t promisedActiveDurationMs = dataResponse.promisedActiveDuration; + ChipLogProgress(ICD, "StayActive command succeeded with promised duration %u", promisedActiveDurationMs); + mOnDone(promisedActiveDurationMs); + chip::Platform::Delete(this); + }; + + auto onFailure = [&](CHIP_ERROR error) { + ChipLogError(ICD, "StayActive command failed: %" CHIP_ERROR_FORMAT, error.Format()); + chip::Platform::Delete(this); + }; + + chip::EndpointId endpointId = 0; + chip::app::Clusters::IcdManagement::Commands::StayActiveRequest::Type request; + request.stayActiveDuration = mStayActiveDurationMs; + return chip::Controller::InvokeCommandRequest(&exchangeMgr, sessionHandle, endpointId, request, onSuccess, onFailure); +} + +CHIP_ERROR StayActiveSender::EstablishSessionToPeer() +{ + ChipLogProgress(ICD, "Trying to establish a CASE session to extend the active period for lit icd device"); + auto * caseSessionManager = mpImEngine->GetCASESessionManager(); + VerifyOrReturnError(caseSessionManager != nullptr, CHIP_ERROR_INVALID_CASE_PARAMETER); + caseSessionManager->FindOrEstablishSession(mPeerNode, &mOnConnectedCallback, &mOnConnectionFailureCallback); + return CHIP_NO_ERROR; +} + +void StayActiveSender::HandleDeviceConnected(void * context, chip::Messaging::ExchangeManager & exchangeMgr, + const chip::SessionHandle & sessionHandle) +{ + StayActiveSender * const _this = static_cast(context); + VerifyOrDie(_this != nullptr); + + CHIP_ERROR err = _this->SendStayActiveCommand(exchangeMgr, sessionHandle); + if (CHIP_NO_ERROR != err) + { + ChipLogError(ICD, "Failed to send stay active command"); + chip::Platform::Delete(_this); + } +} + +void StayActiveSender::HandleDeviceConnectionFailure(void * context, const chip::ScopedNodeId & peerId, CHIP_ERROR err) +{ + StayActiveSender * const _this = static_cast(context); + VerifyOrDie(_this != nullptr); + ChipLogError(ICD, "Failed to establish CASE for stay active command with error '%" CHIP_ERROR_FORMAT "'", err.Format()); + chip::Platform::Delete(_this); +} diff --git a/examples/fabric-admin/commands/common/StayActiveSender.h b/examples/fabric-admin/commands/common/StayActiveSender.h new file mode 100644 index 00000000000000..c0caa380e6f912 --- /dev/null +++ b/examples/fabric-admin/commands/common/StayActiveSender.h @@ -0,0 +1,107 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include +#include +#include + +/** + * @brief StayActiveSender contains all the data and methods needed for active period extension of an ICD client. + * + * Lifetime of instance of StayActiveSender is entirely self managed. + */ +class StayActiveSender +{ +private: + // Ideally StayActiveSender would be a private constructor, unfortunately that is not possible as Platform::New + // does not have access to private constructors. As a workaround we have defined this private struct that can + // be forwarded by Platform::New that allows us to enforce that the only way StayActiveSender is constructed is + // if SendStayActiveCommand is called. + struct ConstructorOnlyInternallyCallable + { + }; + +public: + using OnDoneCallbackType = std::function; + + /** + * @brief Attempts to send a StayActiveRequest command + * + * @param[in] stayActiveDurationMs StayActiveRequest command parameter. + * @param[in] peerNode Peer node we sending StayActiveRequest command to + * @param[in] engine Interaction Model Engine instance for sending command. + * @param[in] onDone Upon this function returning success, it is expected that onDone will be called after we + * have successfully recieved a response + * + * @return CHIP_ERROR CHIP_NO_ERROR on success, or corresponding error code. + */ + static CHIP_ERROR SendStayActiveCommand(uint32_t stayActiveDurationMs, const chip::ScopedNodeId & peerNode, + chip::app::InteractionModelEngine * engine, OnDoneCallbackType onDone); + + // Ideally this would be a private constructor, unfortunately that is not possible as Platform::New does not + // have access to private constructors. As a workaround we have defined a private struct that can be forwarded + // by Platform::New that allows us to enforce that the only way this is constructed is if SendStayActiveCommand + // is called. + StayActiveSender(const ConstructorOnlyInternallyCallable & _, uint32_t stayActiveDurationMs, + const chip::ScopedNodeId & peerNode, chip::app::InteractionModelEngine * engine, OnDoneCallbackType onDone); + +private: + /** + * @brief Sets up a CASE session with the peer to extend the client's active period with that peer. + * Returns error if we did not even manage to kick off a CASE attempt. + */ + CHIP_ERROR EstablishSessionToPeer(); + + // CASE session callbacks + /** + *@brief Callback received on successfully establishing a CASE session in order to keep the 'lit icd device' active + * + * @param[in] context - context of the client establishing the CASE session + * @param[in] exchangeMgr - exchange manager to use for the re-registration + * @param[in] sessionHandle - session handle to use for the re-registration + */ + static void HandleDeviceConnected(void * context, chip::Messaging::ExchangeManager & exchangeMgr, + const chip::SessionHandle & sessionHandle); + /** + * @brief Callback received on failure to establish a CASE session + * + * @param[in] context - context of the client establishing the CASE session + * @param[in] peerId - Scoped Node ID of the peer node + * @param[in] err - failure reason + */ + static void HandleDeviceConnectionFailure(void * context, const chip::ScopedNodeId & peerId, CHIP_ERROR err); + + /** + * @brief Used to send a stayActive command to the peer + * + * @param[in] exchangeMgr - exchange manager to use for the re-registration + * @param[in] sessionHandle - session handle to use for the re-registration + */ + CHIP_ERROR SendStayActiveCommand(chip::Messaging::ExchangeManager & exchangeMgr, const chip::SessionHandle & sessionHandle); + + uint32_t mStayActiveDurationMs = 0; + chip::ScopedNodeId mPeerNode; + chip::app::InteractionModelEngine * mpImEngine = nullptr; + OnDoneCallbackType mOnDone; + + chip::Callback::Callback mOnConnectedCallback; + chip::Callback::Callback mOnConnectionFailureCallback; +}; diff --git a/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp index 3e050e90904867..f62d85ce5afd40 100644 --- a/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp +++ b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp @@ -35,9 +35,11 @@ namespace { // Constants constexpr uint32_t kCommissionPrepareTimeMs = 500; constexpr uint16_t kMaxManaulCodeLength = 21; -constexpr uint16_t kSubscribeMinInterval = 0; -constexpr uint16_t kSubscribeMaxInterval = 60; -constexpr uint16_t kRemoteBridgePort = 5540; + +void CheckFabricBridgeSynchronizationSupport(intptr_t ignored) +{ + DeviceMgr().ReadSupportedDeviceCategories(); +} } // namespace @@ -45,8 +47,16 @@ void FabricSyncAddBridgeCommand::OnCommissioningComplete(chip::NodeId deviceId, { if (mBridgeNodeId != deviceId) { - ChipLogProgress(NotSpecified, "Commissioning complete for non-bridge device: NodeId: " ChipLogFormatX64, - ChipLogValueX64(deviceId)); + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to pair non-bridge device (0x:" ChipLogFormatX64 ") with error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(deviceId), err.Format()); + } + else + { + ChipLogProgress(NotSpecified, "Commissioning complete for non-bridge device: NodeId: " ChipLogFormatX64, + ChipLogValueX64(deviceId)); + } return; } @@ -56,11 +66,15 @@ void FabricSyncAddBridgeCommand::OnCommissioningComplete(chip::NodeId deviceId, ChipLogProgress(NotSpecified, "Successfully paired bridge device: NodeId: " ChipLogFormatX64, ChipLogValueX64(mBridgeNodeId)); - char command[kMaxCommandSize]; - snprintf(command, sizeof(command), "descriptor subscribe parts-list %d %d %ld %d", kSubscribeMinInterval, - kSubscribeMaxInterval, mBridgeNodeId, kAggragatorEndpointId); + DeviceMgr().SubscribeRemoteFabricBridge(); - PushCommand(command); + // After successful commissioning of the Commissionee, initiate Reverse Commissioning + // via the Commissioner Control Cluster. However, we must first verify that the + // remote Fabric-Bridge supports Fabric Synchronization. + // + // Note: The Fabric-Admin MUST NOT send the RequestCommissioningApproval command + // if the remote Fabric-Bridge lacks Fabric Synchronization support. + DeviceLayer::PlatformMgr().ScheduleWork(CheckFabricBridgeSynchronizationSupport, 0); } else { @@ -80,10 +94,6 @@ CHIP_ERROR FabricSyncAddBridgeCommand::RunCommand(NodeId remoteId) return CHIP_NO_ERROR; } - char command[kMaxCommandSize]; - snprintf(command, sizeof(command), "pairing already-discovered %ld %d %s %d", remoteId, kSetupPinCode, - reinterpret_cast(mRemoteAddr.data()), kRemoteBridgePort); - PairingCommand * pairingCommand = static_cast(CommandMgr().GetCommandByName("pairing", "already-discovered")); if (pairingCommand == nullptr) @@ -95,7 +105,7 @@ CHIP_ERROR FabricSyncAddBridgeCommand::RunCommand(NodeId remoteId) pairingCommand->RegisterCommissioningDelegate(this); mBridgeNodeId = remoteId; - PushCommand(command); + DeviceMgr().PairRemoteFabricBridge(remoteId, reinterpret_cast(mRemoteAddr.data())); return CHIP_NO_ERROR; } @@ -136,9 +146,6 @@ CHIP_ERROR FabricSyncRemoveBridgeCommand::RunCommand() mBridgeNodeId = bridgeNodeId; - char command[kMaxCommandSize]; - snprintf(command, sizeof(command), "pairing unpair %ld", mBridgeNodeId); - PairingCommand * pairingCommand = static_cast(CommandMgr().GetCommandByName("pairing", "unpair")); if (pairingCommand == nullptr) @@ -149,13 +156,15 @@ CHIP_ERROR FabricSyncRemoveBridgeCommand::RunCommand() pairingCommand->RegisterPairingDelegate(this); - PushCommand(command); + DeviceMgr().UnpairRemoteFabricBridge(); return CHIP_NO_ERROR; } void FabricSyncDeviceCommand::OnCommissioningWindowOpened(NodeId deviceId, CHIP_ERROR err, chip::SetupPayload payload) { + ChipLogProgress(NotSpecified, "FabricSyncDeviceCommand::OnCommissioningWindowOpened"); + if (err == CHIP_NO_ERROR) { char payloadBuffer[kMaxManaulCodeLength + 1]; @@ -163,9 +172,7 @@ void FabricSyncDeviceCommand::OnCommissioningWindowOpened(NodeId deviceId, CHIP_ CHIP_ERROR error = ManualSetupPayloadGenerator(payload).payloadDecimalStringRepresentation(manualCode); if (error == CHIP_NO_ERROR) { - char command[kMaxCommandSize]; NodeId nodeId = DeviceMgr().GetNextAvailableNodeId(); - snprintf(command, sizeof(command), "pairing code %ld %s", nodeId, payloadBuffer); PairingCommand * pairingCommand = static_cast(CommandMgr().GetCommandByName("pairing", "code")); @@ -180,7 +187,7 @@ void FabricSyncDeviceCommand::OnCommissioningWindowOpened(NodeId deviceId, CHIP_ usleep(kCommissionPrepareTimeMs * 1000); - PushCommand(command); + DeviceMgr().PairRemoteDevice(nodeId, payloadBuffer); } else { @@ -224,10 +231,6 @@ CHIP_ERROR FabricSyncDeviceCommand::RunCommand(EndpointId remoteId) return CHIP_NO_ERROR; } - char command[kMaxCommandSize]; - snprintf(command, sizeof(command), "pairing open-commissioning-window %ld %d %d %d %d %d", DeviceMgr().GetRemoteBridgeNodeId(), - remoteId, kEnhancedCommissioningMethod, kWindowTimeout, kIteration, kDiscriminator); - OpenCommissioningWindowCommand * openCommand = static_cast(CommandMgr().GetCommandByName("pairing", "open-commissioning-window")); @@ -238,7 +241,7 @@ CHIP_ERROR FabricSyncDeviceCommand::RunCommand(EndpointId remoteId) openCommand->RegisterDelegate(this); - PushCommand(command); + DeviceMgr().OpenRemoteDeviceCommissioningWindow(remoteId); return CHIP_NO_ERROR; } @@ -249,6 +252,8 @@ CHIP_ERROR FabricAutoSyncCommand::RunCommand(bool enableAutoSync) // print to console fprintf(stderr, "Auto Fabric Sync is %s.\n", enableAutoSync ? "enabled" : "disabled"); + fprintf(stderr, + "WARNING: The auto-sync command is currently under development and may contain bugs. Use it at your own risk.\n"); return CHIP_NO_ERROR; } diff --git a/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.h b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.h index 038094583c8554..ca1b105207f832 100644 --- a/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.h +++ b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.h @@ -22,14 +22,6 @@ #include #include -constexpr uint32_t kSetupPinCode = 20202021; -constexpr uint16_t kMaxCommandSize = 64; -constexpr uint16_t kDiscriminator = 3840; -constexpr uint16_t kWindowTimeout = 300; -constexpr uint16_t kIteration = 1000; -constexpr uint16_t kAggragatorEndpointId = 1; -constexpr uint8_t kEnhancedCommissioningMethod = 1; - class FabricSyncAddBridgeCommand : public CHIPCommand, public CommissioningDelegate { public: diff --git a/examples/fabric-admin/commands/pairing/DeviceSynchronization.cpp b/examples/fabric-admin/commands/pairing/DeviceSynchronization.cpp new file mode 100644 index 00000000000000..3974761fdc4bc2 --- /dev/null +++ b/examples/fabric-admin/commands/pairing/DeviceSynchronization.cpp @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "DeviceSynchronization.h" +#include "rpc/RpcClient.h" + +#include +#include + +#include +#include + +using namespace ::chip; +using namespace ::chip::app; +using chip::app::ReadClient; + +namespace { + +void OnDeviceConnectedWrapper(void * context, Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle) +{ + reinterpret_cast(context)->OnDeviceConnected(exchangeMgr, sessionHandle); +} + +void OnDeviceConnectionFailureWrapper(void * context, const ScopedNodeId & peerId, CHIP_ERROR error) +{ + reinterpret_cast(context)->OnDeviceConnectionFailure(peerId, error); +} + +bool SuccessOrLog(CHIP_ERROR err, const char * name) +{ + if (err == CHIP_NO_ERROR) + { + return true; + } + + ChipLogError(NotSpecified, "Failed to read %s: %" CHIP_ERROR_FORMAT, name, err.Format()); + + return false; +} + +} // namespace + +DeviceSynchronizer & DeviceSynchronizer::Instance() +{ + static DeviceSynchronizer instance; + return instance; +} + +DeviceSynchronizer::DeviceSynchronizer() : + mOnDeviceConnectedCallback(OnDeviceConnectedWrapper, this), + mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureWrapper, this) +{} + +void DeviceSynchronizer::OnAttributeData(const ConcreteDataAttributePath & path, TLV::TLVReader * data, const StatusIB & status) +{ + VerifyOrDie(path.mEndpointId == kRootEndpointId); + VerifyOrDie(path.mClusterId == Clusters::BasicInformation::Id); + + switch (path.mAttributeId) + { + case Clusters::BasicInformation::Attributes::UniqueID::Id: + mCurrentDeviceData.has_unique_id = + SuccessOrLog(data->GetString(mCurrentDeviceData.unique_id, sizeof(mCurrentDeviceData.unique_id)), "UniqueId"); + break; + case Clusters::BasicInformation::Attributes::VendorName::Id: + mCurrentDeviceData.has_vendor_name = + SuccessOrLog(data->GetString(mCurrentDeviceData.vendor_name, sizeof(mCurrentDeviceData.vendor_name)), "VendorName"); + break; + case Clusters::BasicInformation::Attributes::VendorID::Id: + mCurrentDeviceData.has_vendor_id = SuccessOrLog(data->Get(mCurrentDeviceData.vendor_id), "VendorID"); + break; + case Clusters::BasicInformation::Attributes::ProductName::Id: + mCurrentDeviceData.has_product_name = + SuccessOrLog(data->GetString(mCurrentDeviceData.product_name, sizeof(mCurrentDeviceData.product_name)), "ProductName"); + break; + case Clusters::BasicInformation::Attributes::ProductID::Id: + mCurrentDeviceData.has_product_id = SuccessOrLog(data->Get(mCurrentDeviceData.product_id), "ProductID"); + break; + case Clusters::BasicInformation::Attributes::NodeLabel::Id: + mCurrentDeviceData.has_node_label = + SuccessOrLog(data->GetString(mCurrentDeviceData.node_label, sizeof(mCurrentDeviceData.node_label)), "NodeLabel"); + break; + case Clusters::BasicInformation::Attributes::HardwareVersion::Id: + mCurrentDeviceData.has_hardware_version = SuccessOrLog(data->Get(mCurrentDeviceData.hardware_version), "HardwareVersion"); + break; + case Clusters::BasicInformation::Attributes::HardwareVersionString::Id: + mCurrentDeviceData.has_hardware_version_string = SuccessOrLog( + data->GetString(mCurrentDeviceData.hardware_version_string, sizeof(mCurrentDeviceData.hardware_version_string)), + "HardwareVersionString"); + break; + case Clusters::BasicInformation::Attributes::SoftwareVersion::Id: + mCurrentDeviceData.has_software_version = SuccessOrLog(data->Get(mCurrentDeviceData.software_version), "HardwareVersion"); + break; + case Clusters::BasicInformation::Attributes::SoftwareVersionString::Id: + mCurrentDeviceData.has_software_version_string = SuccessOrLog( + data->GetString(mCurrentDeviceData.software_version_string, sizeof(mCurrentDeviceData.software_version_string)), + "SoftwareVersionString"); + break; + default: + break; + } +} + +void DeviceSynchronizer::OnReportEnd() +{ + // Report end is at the end of all attributes (success) +#if defined(PW_RPC_ENABLED) + AddSynchronizedDevice(mCurrentDeviceData); +#else + ChipLogError(NotSpecified, "Cannot synchronize device with fabric bridge: RPC not enabled"); +#endif +} + +void DeviceSynchronizer::OnDone(chip::app::ReadClient * apReadClient) +{ + // Nothing to do: error reported on OnError or report ended called. + mDeviceSyncInProcess = false; +} + +void DeviceSynchronizer::OnError(CHIP_ERROR error) +{ + ChipLogProgress(NotSpecified, "Error fetching device data: %" CHIP_ERROR_FORMAT, error.Format()); +} + +void DeviceSynchronizer::OnDeviceConnected(chip::Messaging::ExchangeManager & exchangeMgr, + const chip::SessionHandle & sessionHandle) +{ + mClient = std::make_unique(app::InteractionModelEngine::GetInstance(), &exchangeMgr /* echangeMgr */, + *this /* callback */, ReadClient::InteractionType::Read); + VerifyOrDie(mClient); + + AttributePathParams readPaths[1]; + readPaths[0] = AttributePathParams(kRootEndpointId, Clusters::BasicInformation::Id); + + ReadPrepareParams readParams(sessionHandle); + + readParams.mpAttributePathParamsList = readPaths; + readParams.mAttributePathParamsListSize = 1; + + CHIP_ERROR err = mClient->SendRequest(readParams); + + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to issue read for BasicInformation data"); + mDeviceSyncInProcess = false; + } +} + +void DeviceSynchronizer::OnDeviceConnectionFailure(const chip::ScopedNodeId & peerId, CHIP_ERROR error) +{ + ChipLogError(NotSpecified, "Device Sync failed to connect to " ChipLogFormatX64, ChipLogValueX64(peerId.GetNodeId())); + mDeviceSyncInProcess = false; +} + +void DeviceSynchronizer::StartDeviceSynchronization(chip::Controller::DeviceController & controller, chip::NodeId nodeId, + bool deviceIsIcd) +{ + if (mDeviceSyncInProcess) + { + ChipLogError(NotSpecified, "Device Sync NOT POSSIBLE: another sync is in progress"); + return; + } + + mCurrentDeviceData = chip_rpc_SynchronizedDevice_init_default; + mCurrentDeviceData.node_id = nodeId; + mCurrentDeviceData.has_is_icd = true; + mCurrentDeviceData.is_icd = deviceIsIcd; + + mDeviceSyncInProcess = true; + + controller.GetConnectedDevice(nodeId, &mOnDeviceConnectedCallback, &mOnDeviceConnectionFailureCallback); +} diff --git a/examples/fabric-admin/commands/pairing/DeviceSynchronization.h b/examples/fabric-admin/commands/pairing/DeviceSynchronization.h new file mode 100644 index 00000000000000..6aca23f31cbeaa --- /dev/null +++ b/examples/fabric-admin/commands/pairing/DeviceSynchronization.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#pragma once + +#include +#include +#include + +#include + +#include "fabric_bridge_service/fabric_bridge_service.pb.h" +#include "fabric_bridge_service/fabric_bridge_service.rpc.pb.h" + +/// Ensures that device data is synchronized to the remote fabric bridge. +/// +/// Includes a state machine that: +/// - initiates a "read basic information data" command to fetch basic information +/// - upon receiving such information, ensures that synchronized device data is sent +/// to the remote end. +class DeviceSynchronizer : public chip::app::ReadClient::Callback +{ +public: + DeviceSynchronizer(); + + /// Usually called after commissioning is complete, initiates a + /// read of required data from the remote node ID and then will synchronize + /// the device towards the fabric bridge + void StartDeviceSynchronization(chip::Controller::DeviceController & controller, chip::NodeId nodeId, bool deviceIsIcd); + + /////////////////////////////////////////////////////////////// + // ReadClient::Callback implementation + /////////////////////////////////////////////////////////////// + void OnAttributeData(const chip::app::ConcreteDataAttributePath & path, chip::TLV::TLVReader * data, + const chip::app::StatusIB & status) override; + void OnReportEnd() override; + void OnError(CHIP_ERROR error) override; + void OnDone(chip::app::ReadClient * apReadClient) override; + + /////////////////////////////////////////////////////////////// + // callbacks for CASE session establishment + /////////////////////////////////////////////////////////////// + void OnDeviceConnected(chip::Messaging::ExchangeManager & exchangeMgr, const chip::SessionHandle & sessionHandle); + void OnDeviceConnectionFailure(const chip::ScopedNodeId & peerId, CHIP_ERROR error); + + static DeviceSynchronizer & Instance(); + +private: + std::unique_ptr mClient; + + chip::Callback::Callback mOnDeviceConnectedCallback; + chip::Callback::Callback mOnDeviceConnectionFailureCallback; + + bool mDeviceSyncInProcess = false; + chip_rpc_SynchronizedDevice mCurrentDeviceData = chip_rpc_SynchronizedDevice_init_default; +}; diff --git a/examples/fabric-admin/commands/pairing/OpenCommissioningWindowCommand.cpp b/examples/fabric-admin/commands/pairing/OpenCommissioningWindowCommand.cpp index b2d811fdc8b114..53073160108036 100644 --- a/examples/fabric-admin/commands/pairing/OpenCommissioningWindowCommand.cpp +++ b/examples/fabric-admin/commands/pairing/OpenCommissioningWindowCommand.cpp @@ -55,6 +55,7 @@ CHIP_ERROR OpenCommissioningWindowCommand::RunCommand() .SetTimeout(mCommissioningWindowTimeout) .SetIteration(mIteration) .SetDiscriminator(mDiscriminator) + .SetSetupPIN(mSetupPIN) .SetSalt(mSalt) .SetReadVIDPIDAttributes(true) .SetCallback(&mOnOpenCommissioningWindowCallback), diff --git a/examples/fabric-admin/commands/pairing/OpenCommissioningWindowCommand.h b/examples/fabric-admin/commands/pairing/OpenCommissioningWindowCommand.h index 09788507210aaf..7edcdba7115665 100644 --- a/examples/fabric-admin/commands/pairing/OpenCommissioningWindowCommand.h +++ b/examples/fabric-admin/commands/pairing/OpenCommissioningWindowCommand.h @@ -46,8 +46,9 @@ class OpenCommissioningWindowCommand : public CHIPCommand "Time, in seconds, before the commissioning window closes."); AddArgument("iteration", chip::Crypto::kSpake2p_Min_PBKDF_Iterations, chip::Crypto::kSpake2p_Max_PBKDF_Iterations, &mIteration, "Number of PBKDF iterations to use to derive the verifier. Ignored if 'option' is 0."); - AddArgument("discriminator", 0, 4096, &mDiscriminator, "Discriminator to use for advertising. Ignored if 'option' is 0."); + AddArgument("discriminator", 0, 4095, &mDiscriminator, "Discriminator to use for advertising. Ignored if 'option' is 0."); AddArgument("timeout", 0, UINT16_MAX, &mTimeout, "Time, in seconds, before this command is considered to have timed out."); + AddArgument("setup-pin", 1, chip::kSetupPINCodeMaximumValue, &mSetupPIN, "The setup PIN (Passcode) to use."); AddArgument("salt", &mSalt, "Salt payload encoded in hexadecimal. Random salt will be generated if absent. " "This needs to be present if verifier is provided, corresponding to salt used for generating verifier"); @@ -76,6 +77,7 @@ class OpenCommissioningWindowCommand : public CHIPCommand uint16_t mDiscriminator; chip::Optional mTimeout; + chip::Optional mSetupPIN; chip::Optional mSalt; chip::Optional mVerifier; diff --git a/examples/fabric-admin/commands/pairing/PairingCommand.cpp b/examples/fabric-admin/commands/pairing/PairingCommand.cpp index 521325a796dce0..aecd259d373d3f 100644 --- a/examples/fabric-admin/commands/pairing/PairingCommand.cpp +++ b/examples/fabric-admin/commands/pairing/PairingCommand.cpp @@ -18,7 +18,10 @@ #include "PairingCommand.h" +#include #include +#include +#include #include #include #include @@ -400,10 +403,7 @@ void PairingCommand::OnCommissioningComplete(NodeId nodeId, CHIP_ERROR err) { // print to console fprintf(stderr, "New device with Node ID: 0x%lx has been successfully added.\n", nodeId); - -#if defined(PW_RPC_ENABLED) - AddSynchronizedDevice(nodeId); -#endif + DeviceSynchronizer::Instance().StartDeviceSynchronization(CurrentCommissioner(), mNodeId, mDeviceIsICD); } else { @@ -464,7 +464,7 @@ void PairingCommand::OnICDRegistrationComplete(ScopedNodeId nodeId, uint32_t icd sizeof(icdSymmetricKeyHex), chip::Encoding::HexFlags::kNullTerminate); app::ICDClientInfo clientInfo; - clientInfo.peer_node = chip::ScopedNodeId(mICDCheckInNodeId.Value(), nodeId.GetFabricIndex()); + clientInfo.peer_node = nodeId; clientInfo.monitored_subject = mICDMonitoredSubject.Value(); clientInfo.start_icd_counter = icdCounter; diff --git a/examples/fabric-admin/device_manager/DeviceManager.cpp b/examples/fabric-admin/device_manager/DeviceManager.cpp index 4ea0b033c47c7f..7204e153d2807f 100644 --- a/examples/fabric-admin/device_manager/DeviceManager.cpp +++ b/examples/fabric-admin/device_manager/DeviceManager.cpp @@ -19,6 +19,8 @@ #include "DeviceManager.h" #include +#include +#include #include #include @@ -26,6 +28,21 @@ using namespace chip; using namespace chip::app::Clusters; +namespace { + +// Constants +constexpr uint32_t kSetupPinCode = 20202021; +constexpr uint16_t kRemoteBridgePort = 5540; +constexpr uint16_t kWindowTimeout = 300; +constexpr uint16_t kIteration = 1000; +constexpr uint16_t kSubscribeMinInterval = 0; +constexpr uint16_t kSubscribeMaxInterval = 60; +constexpr uint16_t kAggragatorEndpointId = 1; +constexpr uint16_t kMaxDiscriminatorLength = 4095; +constexpr uint8_t kEnhancedCommissioningMethod = 1; + +} // namespace + // Define the static member DeviceManager DeviceManager::sInstance; @@ -97,8 +114,159 @@ void DeviceManager::RemoveSyncedDevice(NodeId nodeId) ChipLogValueX64(device->GetNodeId()), device->GetEndpointId()); } -void DeviceManager::HandleAttributeChange(const app::ConcreteDataAttributePath & path, TLV::TLVReader * data) +void DeviceManager::OpenDeviceCommissioningWindow(NodeId nodeId, uint32_t commissioningTimeout, uint32_t iterations, + uint32_t discriminator, const char * saltHex, const char * verifierHex) +{ + // Open the commissioning window of a device within its own fabric. + StringBuilder commandBuilder; + + commandBuilder.Add("pairing open-commissioning-window "); + commandBuilder.AddFormat("%lu %d %d %d %d %d --salt hex:%s --verifier hex:%s", nodeId, kRootEndpointId, + kEnhancedCommissioningMethod, commissioningTimeout, iterations, discriminator, saltHex, verifierHex); + + PushCommand(commandBuilder.c_str()); +} + +void DeviceManager::OpenRemoteDeviceCommissioningWindow(EndpointId remoteEndpointId) +{ + // Open the commissioning window of a device from another fabric via its fabric bridge. + // This method constructs and sends a command to open the commissioning window for a device + // that is part of a different fabric, accessed through a fabric bridge. + StringBuilder<512> commandBuilder; + + // Use random discriminator to have less chance of collission. + uint16_t discriminator = + Crypto::GetRandU16() % (kMaxDiscriminatorLength + 1); // Include the upper limit kMaxDiscriminatorLength + + commandBuilder.Add("pairing open-commissioning-window "); + commandBuilder.AddFormat("%lu %d %d %d %d %d", mRemoteBridgeNodeId, remoteEndpointId, kEnhancedCommissioningMethod, + kWindowTimeout, kIteration, discriminator); + commandBuilder.Add(" --setup-pin 20202021"); + + PushCommand(commandBuilder.c_str()); +} + +void DeviceManager::PairRemoteFabricBridge(NodeId nodeId, const char * deviceRemoteIp) { + StringBuilder commandBuilder; + + commandBuilder.Add("pairing already-discovered "); + commandBuilder.AddFormat("%lu %d %s %d", nodeId, kSetupPinCode, deviceRemoteIp, kRemoteBridgePort); + + PushCommand(commandBuilder.c_str()); +} + +void DeviceManager::PairRemoteDevice(chip::NodeId nodeId, const char * payload) +{ + StringBuilder commandBuilder; + + commandBuilder.Add("pairing code "); + commandBuilder.AddFormat("%lu %s", nodeId, payload); + + PushCommand(commandBuilder.c_str()); +} + +void DeviceManager::UnpairRemoteFabricBridge() +{ + StringBuilder commandBuilder; + + commandBuilder.Add("pairing unpair "); + commandBuilder.AddFormat("%lu", mRemoteBridgeNodeId); + + PushCommand(commandBuilder.c_str()); +} + +void DeviceManager::SubscribeRemoteFabricBridge() +{ + // Listen to the state changes of the remote fabric bridge. + StringBuilder commandBuilder; + + // Prepare and push the descriptor subscribe command + commandBuilder.Add("descriptor subscribe parts-list "); + commandBuilder.AddFormat("%d %d %lu %d", kSubscribeMinInterval, kSubscribeMaxInterval, mRemoteBridgeNodeId, + kAggragatorEndpointId); + PushCommand(commandBuilder.c_str()); + + // Clear the builder for the next command + commandBuilder.Reset(); + + // Prepare and push the commissioner control subscribe command + commandBuilder.Add("commissionercontrol subscribe-event commissioning-request-result "); + commandBuilder.AddFormat("%d %d %lu %d --is-urgent true", kSubscribeMinInterval, kSubscribeMaxInterval, mRemoteBridgeNodeId, + kRootEndpointId); + PushCommand(commandBuilder.c_str()); +} + +void DeviceManager::ReadSupportedDeviceCategories() +{ + if (!IsFabricSyncReady()) + { + // print to console + fprintf(stderr, "Remote Fabric Bridge is not configured yet.\n"); + return; + } + + StringBuilder commandBuilder; + + commandBuilder.Add("commissionercontrol read supported-device-categories "); + commandBuilder.AddFormat("%ld ", mRemoteBridgeNodeId); + commandBuilder.AddFormat("%d", kRootEndpointId); + + PushCommand(commandBuilder.c_str()); +} + +void DeviceManager::StartReverseCommissioning() +{ + ChipLogProgress(NotSpecified, "Starting reverse commissioning for bridge device: NodeId: " ChipLogFormatX64, + ChipLogValueX64(mRemoteBridgeNodeId)); + + uint64_t requestId = Crypto::GetRandU64(); + uint16_t vendorId = static_cast(CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID); + uint16_t productId = static_cast(CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID); + + StringBuilder commandBuilder; + commandBuilder.Add("commissionercontrol request-commissioning-approval "); + commandBuilder.AddFormat("%lu %u %u %lu %d", requestId, vendorId, productId, mRemoteBridgeNodeId, kRootEndpointId); + + mRequestId = requestId; + PushCommand(commandBuilder.c_str()); +} + +void DeviceManager::CommissionApprovedRequest(uint64_t requestId, uint16_t responseTimeoutSeconds) +{ + ChipLogProgress(NotSpecified, "Request the Commissioner Control Server to begin commissioning a previously approved request."); + + StringBuilder commandBuilder; + commandBuilder.Add("commissionercontrol commission-node "); + commandBuilder.AddFormat("%lu %u %lu %d", requestId, responseTimeoutSeconds, mRemoteBridgeNodeId, kRootEndpointId); + + PushCommand(commandBuilder.c_str()); +} + +void DeviceManager::HandleAttributeData(const app::ConcreteDataAttributePath & path, TLV::TLVReader * data) +{ + if (path.mClusterId == CommissionerControl::Id && + path.mAttributeId == CommissionerControl::Attributes::SupportedDeviceCategories::Id) + { + ChipLogProgress(NotSpecified, "Attribute SupportedDeviceCategories detected."); + + BitMask value; + CHIP_ERROR error = app::DataModel::Decode(*data, value); + if (error != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to decode attribute value. Error: %" CHIP_ERROR_FORMAT, error.Format()); + return; + } + + if (value.Has(CommissionerControl::SupportedDeviceCategoryBitmap::kFabricSynchronization)) + { + ChipLogProgress(NotSpecified, "Remote Fabric-Bridge supports Fabric Synchronization, start reverse commissioning."); + StartReverseCommissioning(); + } + + return; + } + if (path.mClusterId != Descriptor::Id || path.mAttributeId != Descriptor::Attributes::PartsList::Id) { return; @@ -163,13 +331,15 @@ void DeviceManager::HandleAttributeChange(const app::ConcreteDataAttributePath & // Process added endpoints for (const auto & endpoint : addedEndpoints) { - ChipLogProgress(NotSpecified, "Endpoint added: %u", endpoint); + // print to console + fprintf(stderr, "A new devie is added on Endpoint: %u\n", endpoint); if (mAutoSyncEnabled) { - char command[64]; - snprintf(command, sizeof(command), "fabricsync sync-device %d", endpoint); - PushCommand(command); + StringBuilder commandBuilder; + commandBuilder.Add("fabricsync sync-device "); + commandBuilder.AddFormat("%d", endpoint); + PushCommand(commandBuilder.c_str()); } } @@ -188,8 +358,9 @@ void DeviceManager::HandleAttributeChange(const app::ConcreteDataAttributePath & if (mAutoSyncEnabled) { - char command[64]; - snprintf(command, sizeof(command), "pairing unpair %ld", device->GetNodeId()); + StringBuilder commandBuilder; + commandBuilder.Add("pairing unpair "); + commandBuilder.AddFormat("%lu", device->GetNodeId()); PairingCommand * pairingCommand = static_cast(CommandMgr().GetCommandByName("pairing", "unpair")); @@ -200,11 +371,46 @@ void DeviceManager::HandleAttributeChange(const app::ConcreteDataAttributePath & } pairingCommand->RegisterPairingDelegate(this); - PushCommand(command); + PushCommand(commandBuilder.c_str()); } } } +void DeviceManager::HandleEventData(const chip::app::EventHeader & header, chip::TLV::TLVReader * data) +{ + if (header.mPath.mClusterId != CommissionerControl::Id || + header.mPath.mEventId != CommissionerControl::Events::CommissioningRequestResult::Id) + { + return; + } + + ChipLogProgress(NotSpecified, "CommissioningRequestResult event received."); + + CommissionerControl::Events::CommissioningRequestResult::DecodableType value; + CHIP_ERROR error = app::DataModel::Decode(*data, value); + if (error != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to decode event value. Error: %" CHIP_ERROR_FORMAT, error.Format()); + return; + } + + if (value.requestId != mRequestId) + { + ChipLogError(NotSpecified, "The RequestId does not match the RequestId provided to RequestCommissioningApproval"); + return; + } + + if (value.statusCode != static_cast(Protocols::InteractionModel::Status::Success)) + { + ChipLogError(NotSpecified, "The server is not ready to begin commissioning the requested device"); + return; + } + + // The server is ready to begin commissioning the requested device, request the Commissioner Control Server to begin + // commissioning a previously approved request. + CommissionApprovedRequest(value.requestId, kResponseTimeoutSeconds); +} + void DeviceManager::OnDeviceRemoved(NodeId deviceId, CHIP_ERROR err) { if (err != CHIP_NO_ERROR) diff --git a/examples/fabric-admin/device_manager/DeviceManager.h b/examples/fabric-admin/device_manager/DeviceManager.h index 6270cfd40e9df0..cad573a9311421 100644 --- a/examples/fabric-admin/device_manager/DeviceManager.h +++ b/examples/fabric-admin/device_manager/DeviceManager.h @@ -24,6 +24,8 @@ #include +constexpr uint16_t kResponseTimeoutSeconds = 30; + class Device { public: @@ -67,7 +69,76 @@ class DeviceManager : public PairingDelegate void RemoveSyncedDevice(chip::NodeId nodeId); - void HandleAttributeChange(const chip::app::ConcreteDataAttributePath & path, chip::TLV::TLVReader * data); + /** + * @brief Open the commissioning window for a specific device within its own fabric. + * + * This function initiates the process to open the commissioning window for a device identified by the given node ID. + * + * @param nodeId The ID of the node that should open the commissioning window. + * @param commissioningTimeout The time in seconds before the commissioning window closes. This value determines + * how long the commissioning window remains open for incoming connections. + * @param iterations The number of PBKDF (Password-Based Key Derivation Function) iterations to use + * for deriving the PAKE (Password Authenticated Key Exchange) verifier. + * @param discriminator The device-specific discriminator, determined during commissioning, which helps + * to uniquely identify the device among others. + * @param saltHex The hexadecimal-encoded salt used in the cryptographic operations for commissioning. + * @param verifierHex The hexadecimal-encoded PAKE verifier used to authenticate the commissioning process. + * + */ + void OpenDeviceCommissioningWindow(chip::NodeId nodeId, uint32_t commissioningTimeout, uint32_t iterations, + uint32_t discriminator, const char * saltHex, const char * verifierHex); + + /** + * @brief Open the commissioning window of a device from another fabric via its fabric bridge. + * + * This function initiates the process to open the commissioning window for a device that belongs to another + * fabric, accessed through a fabric bridge. + * + * @param remoteEndpointId The endpoint ID of the remote device that should open the commissioning window. + * This endpoint is associated with the device in the other fabric, accessed via the + * fabric bridge. + * + * @note This function is used when the device to be commissioned is part of a different fabric and must be + * accessed through an intermediary fabric bridge. + */ + void OpenRemoteDeviceCommissioningWindow(chip::EndpointId remoteEndpointId); + + /** + * @brief Pair a remote fabric bridge with a given node ID. + * + * This function initiates the pairing process for a remote fabric bridge using the specified parameters. + + * @param nodeId The user-defined ID for the node being commissioned. It doesn’t need to be the same ID, + * as for the first fabric. + * @param deviceRemoteIp The IP address of the remote device that is being paired as part of the fabric bridge. + */ + void PairRemoteFabricBridge(chip::NodeId nodeId, const char * deviceRemoteIp); + + /** + * @brief Pair a remote Matter device to the current fabric. + * + * This function initiates the pairing process for a remote device using the specified parameters. + + * @param nodeId The user-defined ID for the node being commissioned. It doesn’t need to be the same ID, + * as for the first fabric. + * @param payload The the QR code payload or a manual pairing code generated by the first commissioner + * instance when opened commissioning window. + */ + void PairRemoteDevice(chip::NodeId nodeId, const char * payload); + + void UnpairRemoteFabricBridge(); + + void SubscribeRemoteFabricBridge(); + + void StartReverseCommissioning(); + + void ReadSupportedDeviceCategories(); + + void CommissionApprovedRequest(uint64_t requestId, uint16_t responseTimeoutSeconds); + + void HandleAttributeData(const chip::app::ConcreteDataAttributePath & path, chip::TLV::TLVReader * data); + + void HandleEventData(const chip::app::EventHeader & header, chip::TLV::TLVReader * data); void OnDeviceRemoved(chip::NodeId deviceId, CHIP_ERROR err) override; @@ -81,6 +152,7 @@ class DeviceManager : public PairingDelegate std::set mSyncedDevices; bool mAutoSyncEnabled = false; bool mInitialized = false; + uint64_t mRequestId = 0; Device * FindDeviceByEndpoint(chip::EndpointId endpointId); Device * FindDeviceByNode(chip::NodeId nodeId); diff --git a/examples/fabric-admin/rpc/RpcClient.cpp b/examples/fabric-admin/rpc/RpcClient.cpp index 00ca1204cc1f19..f5672fc0bd8f85 100644 --- a/examples/fabric-admin/rpc/RpcClient.cpp +++ b/examples/fabric-admin/rpc/RpcClient.cpp @@ -22,16 +22,9 @@ #include #include #include -#include -#include +#include "fabric_bridge_service/fabric_bridge_service.pb.h" #include "fabric_bridge_service/fabric_bridge_service.rpc.pb.h" -#include "pw_assert/check.h" -#include "pw_hdlc/decoder.h" -#include "pw_hdlc/default_addresses.h" -#include "pw_hdlc/rpc_channel.h" -#include "pw_rpc/client.h" -#include "pw_stream/socket_stream.h" using namespace chip; @@ -105,6 +98,23 @@ void OnRemoveDeviceResponseCompleted(const pw_protobuf_Empty & response, pw::Sta } } +void RpcCompletedWithEmptyResponse(const pw_protobuf_Empty & response, pw::Status status) +{ + std::lock_guard lock(responseMutex); + responseReceived = true; + responseError = status.ok() ? CHIP_NO_ERROR : CHIP_ERROR_INTERNAL; + responseCv.notify_one(); + + if (status.ok()) + { + ChipLogProgress(NotSpecified, "RPC call succeeded!"); + } + else + { + ChipLogProgress(NotSpecified, "RPC call failed with status: %d", status.code()); + } +} + } // namespace CHIP_ERROR InitRpcClient(uint16_t rpcServerPort) @@ -113,16 +123,13 @@ CHIP_ERROR InitRpcClient(uint16_t rpcServerPort) return rpc::client::StartPacketProcessing(); } -CHIP_ERROR AddSynchronizedDevice(chip::NodeId nodeId) +CHIP_ERROR AddSynchronizedDevice(const chip_rpc_SynchronizedDevice & data) { ChipLogProgress(NotSpecified, "AddSynchronizedDevice"); - chip_rpc_SynchronizedDevice device; - device.node_id = nodeId; - // The RPC call is kept alive until it completes. When a response is received, it will be logged by the handler // function and the call will complete. - auto call = fabricBridgeClient.AddSynchronizedDevice(device, OnAddDeviceResponseCompleted); + auto call = fabricBridgeClient.AddSynchronizedDevice(data, OnAddDeviceResponseCompleted); if (!call.active()) { @@ -137,8 +144,8 @@ CHIP_ERROR RemoveSynchronizedDevice(chip::NodeId nodeId) { ChipLogProgress(NotSpecified, "RemoveSynchronizedDevice"); - chip_rpc_SynchronizedDevice device; - device.node_id = nodeId; + chip_rpc_SynchronizedDevice device = chip_rpc_SynchronizedDevice_init_default; + device.node_id = nodeId; // The RPC call is kept alive until it completes. When a response is received, it will be logged by the handler // function and the call will complete. @@ -152,3 +159,24 @@ CHIP_ERROR RemoveSynchronizedDevice(chip::NodeId nodeId) return WaitForResponse(call); } + +CHIP_ERROR ActiveChanged(chip::NodeId nodeId, uint32_t promisedActiveDurationMs) +{ + ChipLogProgress(NotSpecified, "ActiveChanged"); + + chip_rpc_KeepActiveChanged parameters; + parameters.node_id = nodeId; + parameters.promised_active_duration_ms = promisedActiveDurationMs; + + // The RPC call is kept alive until it completes. When a response is received, it will be logged by the handler + // function and the call will complete. + auto call = fabricBridgeClient.ActiveChanged(parameters, RpcCompletedWithEmptyResponse); + + if (!call.active()) + { + // The RPC call was not sent. This could occur due to, for example, an invalid channel ID. Handle if necessary. + return CHIP_ERROR_INTERNAL; + } + + return WaitForResponse(call); +} diff --git a/examples/fabric-admin/rpc/RpcClient.h b/examples/fabric-admin/rpc/RpcClient.h index a1754b3846d508..8edee9a3b256ed 100644 --- a/examples/fabric-admin/rpc/RpcClient.h +++ b/examples/fabric-admin/rpc/RpcClient.h @@ -20,6 +20,8 @@ #include +#include "fabric_bridge_service/fabric_bridge_service.rpc.pb.h" + constexpr uint16_t kFabricBridgeServerPort = 33002; /** @@ -39,13 +41,12 @@ CHIP_ERROR InitRpcClient(uint16_t rpcServerPort); * It logs the progress and checks if an `AddSynchronizedDevice` operation is already in progress. * If an operation is in progress, it returns `CHIP_ERROR_BUSY`. * - * @param nodeId The Node ID of the device to be added. * @return CHIP_ERROR An error code indicating the success or failure of the operation. * - CHIP_NO_ERROR: The RPC command was successfully processed. * - CHIP_ERROR_BUSY: Another operation is currently in progress. * - CHIP_ERROR_INTERNAL: An internal error occurred while activating the RPC call. */ -CHIP_ERROR AddSynchronizedDevice(chip::NodeId nodeId); +CHIP_ERROR AddSynchronizedDevice(const chip_rpc_SynchronizedDevice & data); /** * @brief Removes a synchronized device from the RPC client. @@ -61,3 +62,15 @@ CHIP_ERROR AddSynchronizedDevice(chip::NodeId nodeId); * - CHIP_ERROR_INTERNAL: An internal error occurred while activating the RPC call. */ CHIP_ERROR RemoveSynchronizedDevice(chip::NodeId nodeId); + +/** + * @brief Received StayActiveResponse on behalf of client that previously called KeepActive + * + * @param nodeId The Node ID of the device we recieved a StayActiveResponse. + * @param promisedActiveDurationMs the computed duration (in milliseconds) that the ICD intends to stay active for. + * @return CHIP_ERROR An error code indicating the success or failure of the operation. + * - CHIP_NO_ERROR: The RPC command was successfully processed. + * - CHIP_ERROR_BUSY: Another operation is currently in progress. + * - CHIP_ERROR_INTERNAL: An internal error occurred while activating the RPC call. + */ +CHIP_ERROR ActiveChanged(chip::NodeId nodeId, uint32_t promisedActiveDurationMs); diff --git a/examples/fabric-admin/rpc/RpcServer.cpp b/examples/fabric-admin/rpc/RpcServer.cpp index d4979e5a27c427..86d90ad294beb7 100644 --- a/examples/fabric-admin/rpc/RpcServer.cpp +++ b/examples/fabric-admin/rpc/RpcServer.cpp @@ -20,10 +20,16 @@ #include "pw_rpc_system_server/rpc_server.h" #include "pw_rpc_system_server/socket.h" +#include +#include + +#include "RpcClient.h" +#include +#include #include #include +#include #include -#include #if defined(PW_RPC_FABRIC_ADMIN_SERVICE) && PW_RPC_FABRIC_ADMIN_SERVICE #include "pigweed/rpc_services/FabricAdmin.h" @@ -34,9 +40,33 @@ using namespace ::chip; namespace { #if defined(PW_RPC_FABRIC_ADMIN_SERVICE) && PW_RPC_FABRIC_ADMIN_SERVICE -class FabricAdmin final : public rpc::FabricAdmin + +class FabricAdmin final : public rpc::FabricAdmin, public IcdManager::Delegate { public: + void OnCheckInCompleted(const chip::app::ICDClientInfo & clientInfo) override + { + chip::NodeId nodeId = clientInfo.peer_node.GetNodeId(); + auto it = mPendingKeepActiveTimesMs.find(nodeId); + VerifyOrReturn(it != mPendingKeepActiveTimesMs.end()); + // TODO(#33221): We also need a mechanism here to drop KeepActive + // request if they were recieved over 60 mins ago. + uint32_t stayActiveDurationMs = it->second; + + // TODO(#33221): If there is a failure in sending the message this request just gets dropped. + // Work to see if there should be update to spec on whether some sort of failure later on + // Should be indicated in some manner, or identify a better recovery mechanism here. + mPendingKeepActiveTimesMs.erase(nodeId); + + auto onDone = [=](uint32_t promisedActiveDuration) { ActiveChanged(nodeId, promisedActiveDuration); }; + CHIP_ERROR err = StayActiveSender::SendStayActiveCommand(stayActiveDurationMs, clientInfo.peer_node, + chip::app::InteractionModelEngine::GetInstance(), onDone); + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to send StayActive command %s", err.AsString()); + } + } + pw::Status OpenCommissioningWindow(const chip_rpc_DeviceCommissioningWindowInfo & request, chip_rpc_OperationStatus & response) override { @@ -54,17 +84,51 @@ class FabricAdmin final : public rpc::FabricAdmin ChipLogProgress(NotSpecified, "Received OpenCommissioningWindow request: 0x%lx", nodeId); - char command[512]; - snprintf(command, sizeof(command), "pairing open-commissioning-window %ld %d %d %d %d %d --salt hex:%s --verifier hex:%s", - nodeId, kRootEndpointId, kEnhancedCommissioningMethod, commissioningTimeout, iterations, discriminator, saltHex, - verifierHex); - - PushCommand(command); + DeviceMgr().OpenDeviceCommissioningWindow(nodeId, commissioningTimeout, iterations, discriminator, saltHex, verifierHex); response.success = true; return pw::OkStatus(); } + + pw::Status KeepActive(const chip_rpc_KeepActiveParameters & request, pw_protobuf_Empty & response) override + { + ChipLogProgress(NotSpecified, "Received KeepActive request: 0x%lx, %u", request.node_id, request.stay_active_duration_ms); + // TODO(#33221): We should really be using ScopedNode, but that requires larger fix in communication between + // fabric-admin and fabric-bridge. For now we make the assumption that there is only one fabric used by + // fabric-admin. + KeepActiveWorkData * data = chip::Platform::New(this, request.node_id, request.stay_active_duration_ms); + VerifyOrReturnValue(data, pw::Status::Internal()); + chip::DeviceLayer::PlatformMgr().ScheduleWork(KeepActiveWork, reinterpret_cast(data)); + return pw::OkStatus(); + } + + void ScheduleSendingKeepActiveOnCheckIn(chip::NodeId nodeId, uint32_t stayActiveDurationMs) + { + mPendingKeepActiveTimesMs[nodeId] = stayActiveDurationMs; + } + +private: + struct KeepActiveWorkData + { + KeepActiveWorkData(FabricAdmin * fabricAdmin, chip::NodeId nodeId, uint32_t stayActiveDurationMs) : + mFabricAdmin(fabricAdmin), mNodeId(nodeId), mStayActiveDurationMs(stayActiveDurationMs) + {} + + FabricAdmin * mFabricAdmin; + chip::NodeId mNodeId; + uint32_t mStayActiveDurationMs; + }; + + static void KeepActiveWork(intptr_t arg) + { + KeepActiveWorkData * data = reinterpret_cast(arg); + data->mFabricAdmin->ScheduleSendingKeepActiveOnCheckIn(data->mNodeId, data->mStayActiveDurationMs); + chip::Platform::Delete(data); + } + + // Modifications to mPendingKeepActiveTimesMs should be done on the MatterEventLoop thread + std::map mPendingKeepActiveTimesMs; }; FabricAdmin fabric_admin_service; @@ -74,6 +138,7 @@ void RegisterServices(pw::rpc::Server & server) { #if defined(PW_RPC_FABRIC_ADMIN_SERVICE) && PW_RPC_FABRIC_ADMIN_SERVICE server.RegisterService(fabric_admin_service); + IcdManager::Instance().SetDelegate(&fabric_admin_service); #endif } diff --git a/examples/fabric-admin/scripts/run_fabric_sink.sh b/examples/fabric-admin/scripts/run_fabric_sink.sh deleted file mode 100755 index 3013965479268a..00000000000000 --- a/examples/fabric-admin/scripts/run_fabric_sink.sh +++ /dev/null @@ -1,78 +0,0 @@ -#!/bin/bash - -# Default paths -DEFAULT_CHOICES=( - "./fabric-admin" - "out/debug/standalone/fabric-admin" - "out/linux-x64-fabric-admin/fabric-admin" - "out/darwin-arm64-fabric-admin/fabric-admin" -) -FABRIC_ADMIN_LOG="/tmp/fabric_admin.log" -FABRIC_ADMIN_PATH="" - -# Function to find fabric-admin binary -find_fabric_admin() { - local choices=("$@") - for path in "${choices[@]}"; do - if [[ -e "$path" ]]; then - echo "$path" - return 0 - fi - done - return 1 -} - -# Parse arguments -VERBOSE=false -SPECIFIED_PATH="" - -for arg in "$@"; do - case $arg in - --verbose) - VERBOSE=true - ;; - --path=*) - SPECIFIED_PATH="${arg#*=}" - ;; - esac -done - -# Use specified path if provided -if [[ -n "$SPECIFIED_PATH" ]]; then - if [[ -e "$SPECIFIED_PATH" ]]; then - FABRIC_ADMIN_PATH="$SPECIFIED_PATH" - else - echo >&2 "Specified path does not exist: $SPECIFIED_PATH" - exit 1 - fi -else - FABRIC_ADMIN_PATH=$(find_fabric_admin "${DEFAULT_CHOICES[@]}") - if [[ $? -ne 0 ]]; then - echo >&2 "Could not find the fabric-admin binary" - exit 1 - fi -fi - -echo "PATH IS: $FABRIC_ADMIN_PATH" - -# Kill fabric-admin if it is running -echo "Checking for running fabric-admin process..." -fabric_admin_pid=$(pgrep -f "$FABRIC_ADMIN_PATH") -if [[ -n "$fabric_admin_pid" ]]; then - echo "Found fabric-admin with PID $fabric_admin_pid, attempting to kill..." - kill -9 "$fabric_admin_pid" - echo "Killed fabric-admin with PID $fabric_admin_pid" -fi - -# Remove /tmp/chip_* files and directories -echo "Removing /tmp/chip_* files and directories..." -sudo rm -rf /tmp/chip_* -echo "Removed /tmp/chip_* files and directories" - -# Start fabric-admin with or without log file path based on --verbose option -echo "Starting fabric-admin..." -if [ "$VERBOSE" = true ]; then - "$FABRIC_ADMIN_PATH" -else - "$FABRIC_ADMIN_PATH" --log-file-path "$FABRIC_ADMIN_LOG" -fi diff --git a/examples/fabric-admin/scripts/run_fabric_source.sh b/examples/fabric-admin/scripts/run_fabric_sync.sh similarity index 85% rename from examples/fabric-admin/scripts/run_fabric_source.sh rename to examples/fabric-admin/scripts/run_fabric_sync.sh index 95df7a135bb596..8c820d111c37c1 100755 --- a/examples/fabric-admin/scripts/run_fabric_source.sh +++ b/examples/fabric-admin/scripts/run_fabric_sync.sh @@ -86,19 +86,19 @@ fi echo "Admin path: $FABRIC_ADMIN_PATH" echo "Bridge path: $FABRIC_BRIDGE_APP_PATH" -# Determine the path to stop_fabric_source.sh based on the location of run_fabric_source.sh -RUN_FABRIC_SOURCE_PATH=$(find_binary "$SCRIPT_DIR/run_fabric_source.sh") +# Determine the path to stop_fabric_sync.sh based on the location of run_fabric_sync.sh +RUN_FABRIC_SOURCE_PATH=$(find_binary "$SCRIPT_DIR/run_fabric_sync.sh") if [[ $? -ne 0 ]]; then - echo >&2 "Could not find the run_fabric_source.sh script" + echo >&2 "Could not find the run_fabric_sync.sh script" exit 1 fi -STOP_FABRIC_SOURCE_PATH="${RUN_FABRIC_SOURCE_PATH/run_fabric_source/stop_fabric_source}" +STOP_FABRIC_SYNC_PATH="${RUN_FABRIC_SOURCE_PATH/run_fabric_sync/stop_fabric_sync}" # Stop any running instances and clean up -if [[ -e "$STOP_FABRIC_SOURCE_PATH" ]]; then - "$STOP_FABRIC_SOURCE_PATH" +if [[ -e "$STOP_FABRIC_SYNC_PATH" ]]; then + "$STOP_FABRIC_SYNC_PATH" else - echo >&2 "Could not find the stop_fabric_source.sh script" + echo >&2 "Could not find the stop_fabric_sync.sh script" exit 1 fi diff --git a/examples/fabric-admin/scripts/stop_fabric_source.sh b/examples/fabric-admin/scripts/stop_fabric_sync.sh similarity index 63% rename from examples/fabric-admin/scripts/stop_fabric_source.sh rename to examples/fabric-admin/scripts/stop_fabric_sync.sh index 85fff9e3a878cc..e947c8992fac27 100755 --- a/examples/fabric-admin/scripts/stop_fabric_source.sh +++ b/examples/fabric-admin/scripts/stop_fabric_sync.sh @@ -1,17 +1,19 @@ #!/bin/bash -FABRIC_ADMIN_PATH="/fabric-admin" -FABRIC_BRIDGE_APP_PATH="/fabric-bridge-app" +FABRIC_ADMIN_PATH="fabric-admin" +FABRIC_BRIDGE_APP_PATH="fabric-bridge" # Kill fabric-admin if it is running -fabric_admin_pid=$(pgrep -f "$FABRIC_ADMIN_PATH") +fabric_admin_pid=$(pgrep "$FABRIC_ADMIN_PATH") +echo "Found fabric-admin PID: $fabric_admin_pid" if [ ! -z "$fabric_admin_pid" ]; then kill -9 "$fabric_admin_pid" echo "Killed fabric-admin with PID $fabric_admin_pid" fi # Kill fabric-bridge-app if it is running -fabric_bridge_app_pid=$(pgrep -f "$FABRIC_BRIDGE_APP_PATH") +fabric_bridge_app_pid=$(pgrep "$FABRIC_BRIDGE_APP_PATH") +echo "Found fabric-bridge-app PID: $fabric_bridge_app_pid" if [ ! -z "$fabric_bridge_app_pid" ]; then kill -9 "$fabric_bridge_app_pid" echo "Killed fabric-bridge-app with PID $fabric_bridge_app_pid" diff --git a/examples/fabric-bridge-app/fabric-bridge-common/BUILD.gn b/examples/fabric-bridge-app/fabric-bridge-common/BUILD.gn index 10cb48c31c584e..b7b07d3be37bc3 100644 --- a/examples/fabric-bridge-app/fabric-bridge-common/BUILD.gn +++ b/examples/fabric-bridge-app/fabric-bridge-common/BUILD.gn @@ -19,21 +19,37 @@ config("config") { include_dirs = [ "include" ] } -chip_data_model("fabric-bridge-common") { +chip_data_model("fabric-bridge-common-zap") { zap_file = "fabric-bridge-app.zap" is_server = true cflags = [ "-DDYNAMIC_ENDPOINT_COUNT=16" ] } +# This includes all the clusters that only exist on the dynamic endpoint. +source_set("fabric-bridge-common") { + public_configs = [ ":config" ] + + sources = [ + "${chip_root}/src/app/clusters/ecosystem-information-server/ecosystem-information-server.cpp", + "${chip_root}/src/app/clusters/ecosystem-information-server/ecosystem-information-server.h", + ] + + public_deps = [ ":fabric-bridge-common-zap" ] +} + source_set("fabric-bridge-lib") { public_configs = [ ":config" ] sources = [ "include/BridgedDevice.h", + "include/BridgedDeviceBasicInformationImpl.h", "include/BridgedDeviceManager.h", "include/CHIPProjectAppConfig.h", + "include/CommissionerControl.h", "src/BridgedDevice.cpp", + "src/BridgedDeviceBasicInformationImpl.cpp", "src/BridgedDeviceManager.cpp", + "src/CommissionerControl.cpp", "src/ZCLCallbacks.cpp", ] diff --git a/examples/fabric-bridge-app/fabric-bridge-common/include/BridgedDevice.h b/examples/fabric-bridge-app/fabric-bridge-common/include/BridgedDevice.h index a237d93d133eb7..3dab8d3b16b2d6 100644 --- a/examples/fabric-bridge-app/fabric-bridge-common/include/BridgedDevice.h +++ b/examples/fabric-bridge-app/fabric-bridge-common/include/BridgedDevice.h @@ -20,41 +20,57 @@ #include -#include -#include - -#include #include -#include class BridgedDevice { public: - static const int kDeviceNameSize = 32; + /// Defines all attributes that we keep track of for a bridged device + struct BridgedAttributes + { + std::string uniqueId; + std::string vendorName; + uint16_t vendorId = 0; + std::string productName; + uint16_t productId = 0; + std::string nodeLabel; + uint16_t hardwareVersion = 0; + std::string hardwareVersionString; + uint32_t softwareVersion = 0; + std::string softwareVersionString; + }; BridgedDevice(chip::NodeId nodeId); - virtual ~BridgedDevice() {} + virtual ~BridgedDevice() = default; - bool IsReachable(); + [[nodiscard]] bool IsReachable() const { return mReachable; } void SetReachable(bool reachable); - void SetName(const char * name); - void SetLocation(std::string location) { mLocation = location; }; + + void LogActiveChangeEvent(uint32_t promisedActiveDurationMs); + + [[nodiscard]] bool IsIcd() const { return mIsIcd; } + void SetIcd(bool icd) { mIsIcd = icd; } + inline void SetEndpointId(chip::EndpointId id) { mEndpointId = id; }; inline chip::EndpointId GetEndpointId() { return mEndpointId; }; inline chip::NodeId GetNodeId() { return mNodeId; }; inline void SetParentEndpointId(chip::EndpointId id) { mParentEndpointId = id; }; inline chip::EndpointId GetParentEndpointId() { return mParentEndpointId; }; - inline char * GetName() { return mName; }; - inline std::string GetLocation() { return mLocation; }; - inline std::string GetZone() { return mZone; }; - inline void SetZone(std::string zone) { mZone = zone; }; + + [[nodiscard]] const BridgedAttributes & GetBridgedAttributes() const { return mAttributes; } + void SetBridgedAttributes(const BridgedAttributes & value) { mAttributes = value; } + + /// Convenience method to set just the unique id of a bridged device as it + /// is one of the few attributes that is not always bulk-set + void SetUniqueId(const std::string & value) { mAttributes.uniqueId = value; } protected: - bool mReachable; - char mName[kDeviceNameSize]; - std::string mLocation; - chip::NodeId mNodeId; - chip::EndpointId mEndpointId; - chip::EndpointId mParentEndpointId; - std::string mZone; + bool mReachable = false; + bool mIsIcd = false; + + chip::NodeId mNodeId = 0; + chip::EndpointId mEndpointId = 0; + chip::EndpointId mParentEndpointId = 0; + + BridgedAttributes mAttributes; }; diff --git a/examples/fabric-bridge-app/fabric-bridge-common/include/BridgedDeviceBasicInformationImpl.h b/examples/fabric-bridge-app/fabric-bridge-common/include/BridgedDeviceBasicInformationImpl.h new file mode 100644 index 00000000000000..23403438ab2be8 --- /dev/null +++ b/examples/fabric-bridge-app/fabric-bridge-common/include/BridgedDeviceBasicInformationImpl.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include +#include + +class BridgedDeviceBasicInformationImpl : public chip::app::AttributeAccessInterface +{ +public: + BridgedDeviceBasicInformationImpl() : + chip::app::AttributeAccessInterface(chip::NullOptional /* endpointId */, + chip::app::Clusters::BridgedDeviceBasicInformation::Id) + {} + + // AttributeAccessInterface implementation + CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & path, chip::app::AttributeValueEncoder & encoder) override; + CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & path, chip::app::AttributeValueDecoder & decoder) override; +}; diff --git a/examples/fabric-bridge-app/fabric-bridge-common/include/BridgedDeviceManager.h b/examples/fabric-bridge-app/fabric-bridge-common/include/BridgedDeviceManager.h index 8411ec656f9803..ac28d31edf507c 100644 --- a/examples/fabric-bridge-app/fabric-bridge-common/include/BridgedDeviceManager.h +++ b/examples/fabric-bridge-app/fabric-bridge-common/include/BridgedDeviceManager.h @@ -22,6 +22,8 @@ #include "BridgedDevice.h" +#include + class BridgedDeviceManager { public: @@ -41,13 +43,19 @@ class BridgedDeviceManager * This function attempts to add a device to a dynamic endpoint. It tries to find an available * endpoint slot and retries the addition process up to a specified maximum number of times if * the endpoint already exists. If the addition is successful, it returns the index of the - * dynamic endpoint; otherwise, it returns -1. + * dynamic endpoint; + * + * Ensures that the device has a unique id: + * - device MUST set its unique id if any BEFORE calling this method + * - if no unique id (i.e. empty string), a new unique id will be generated + * - Add will fail if the unique id is not unique * * @param dev A pointer to the device to be added. * @param parentEndpointId The parent endpoint ID. Defaults to an invalid endpoint ID. - * @return int The index of the dynamic endpoint if successful, -1 otherwise. + * @return int The index of the dynamic endpoint if successful, nullopt otherwise */ - int AddDeviceEndpoint(BridgedDevice * dev, chip::EndpointId parentEndpointId = chip::kInvalidEndpointId); + std::optional AddDeviceEndpoint(std::unique_ptr dev, + chip::EndpointId parentEndpointId = chip::kInvalidEndpointId); /** * @brief Removes a device from a dynamic endpoint. @@ -95,16 +103,26 @@ class BridgedDeviceManager * @param nodeId The NodeId of the device to be removed. * @return int The index of the removed dynamic endpoint if successful, -1 otherwise. */ - int RemoveDeviceByNodeId(chip::NodeId nodeId); + std::optional RemoveDeviceByNodeId(chip::NodeId nodeId); + + /** + * Finds the device with the given unique id (if any) + */ + BridgedDevice * GetDeviceByUniqueId(const std::string & id); private: friend BridgedDeviceManager & BridgeDeviceMgr(); + /** + * Creates a new unique ID that is not used by any other mDevice + */ + std::string GenerateUniqueId(); + static BridgedDeviceManager sInstance; chip::EndpointId mCurrentEndpointId; chip::EndpointId mFirstDynamicEndpointId; - BridgedDevice * mDevices[CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT + 1]; + std::unique_ptr mDevices[CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT + 1]; }; /** diff --git a/examples/fabric-bridge-app/fabric-bridge-common/include/CommissionerControl.h b/examples/fabric-bridge-app/fabric-bridge-common/include/CommissionerControl.h new file mode 100644 index 00000000000000..b5caa6a2ce1f3d --- /dev/null +++ b/examples/fabric-bridge-app/fabric-bridge-common/include/CommissionerControl.h @@ -0,0 +1,57 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include +#include +#include + +namespace chip { +namespace app { +namespace Clusters { +namespace CommissionerControl { + +class CommissionerControlDelegate : public Delegate +{ +public: + CHIP_ERROR HandleCommissioningApprovalRequest(const CommissioningApprovalRequest & request) override; + CHIP_ERROR ValidateCommissionNodeCommand(NodeId clientNodeId, uint64_t requestId) override; + CHIP_ERROR GetCommissioningWindowParams(CommissioningWindowParams & outParams) override; + CHIP_ERROR ReverseCommissionNode(const CommissioningWindowParams & params, const Optional & ipAddress, + const Optional & port) override; + + ~CommissionerControlDelegate() = default; + +private: + static constexpr size_t kLabelBufferSize = 64; + + uint64_t mRequestId = 0; + NodeId mClientNodeId = kUndefinedNodeId; + VendorId mVendorId = VendorId::Unspecified; + uint16_t mProductId = 0; + char mLabelBuffer[kLabelBufferSize + 1]; + Optional mLabel; +}; + +} // namespace CommissionerControl +} // namespace Clusters +} // namespace app +} // namespace chip + +CHIP_ERROR CommissionerControlInit(); +CHIP_ERROR CommissionerControlShutdown(); diff --git a/examples/fabric-bridge-app/fabric-bridge-common/src/BridgedDevice.cpp b/examples/fabric-bridge-app/fabric-bridge-common/src/BridgedDevice.cpp index d641f3743d43f0..21f19189afefe6 100644 --- a/examples/fabric-bridge-app/fabric-bridge-common/src/BridgedDevice.cpp +++ b/examples/fabric-bridge-app/fabric-bridge-common/src/BridgedDevice.cpp @@ -19,9 +19,35 @@ #include "BridgedDevice.h" #include + +#include #include -#include +namespace { + +struct ActiveChangeEventWorkData +{ + chip::EndpointId mEndpointId; + uint32_t mPromisedActiveDuration; +}; + +void ActiveChangeEventWork(intptr_t arg) +{ + ActiveChangeEventWorkData * data = reinterpret_cast(arg); + + chip::app::Clusters::BridgedDeviceBasicInformation::Events::ActiveChanged::Type event{}; + event.promisedActiveDuration = data->mPromisedActiveDuration; + chip::EventNumber eventNumber = 0; + + CHIP_ERROR err = chip::app::LogEvent(event, data->mEndpointId, eventNumber); + if (err != CHIP_NO_ERROR) + { + ChipLogProgress(NotSpecified, "LogEvent for ActiveChanged failed %s", err.AsString()); + } + chip::Platform::Delete(data); +} + +} // namespace using namespace chip::app::Clusters::Actions; @@ -32,9 +58,13 @@ BridgedDevice::BridgedDevice(chip::NodeId nodeId) mEndpointId = chip::kInvalidEndpointId; } -bool BridgedDevice::IsReachable() +void BridgedDevice::LogActiveChangeEvent(uint32_t promisedActiveDurationMs) { - return mReachable; + ActiveChangeEventWorkData * workdata = chip::Platform::New(); + workdata->mEndpointId = mEndpointId; + workdata->mPromisedActiveDuration = promisedActiveDurationMs; + + chip::DeviceLayer::PlatformMgr().ScheduleWork(ActiveChangeEventWork, reinterpret_cast(workdata)); } void BridgedDevice::SetReachable(bool reachable) @@ -43,17 +73,10 @@ void BridgedDevice::SetReachable(bool reachable) if (reachable) { - ChipLogProgress(NotSpecified, "BridgedDevice[%s]: ONLINE", mName); + ChipLogProgress(NotSpecified, "BridgedDevice[%s]: ONLINE", mAttributes.uniqueId.c_str()); } else { - ChipLogProgress(NotSpecified, "BridgedDevice[%s]: OFFLINE", mName); + ChipLogProgress(NotSpecified, "BridgedDevice[%s]: OFFLINE", mAttributes.uniqueId.c_str()); } } - -void BridgedDevice::SetName(const char * name) -{ - ChipLogProgress(NotSpecified, "BridgedDevice[%s]: New Name=\"%s\"", mName, name); - - chip::Platform::CopyString(mName, name); -} diff --git a/examples/fabric-bridge-app/fabric-bridge-common/src/BridgedDeviceBasicInformationImpl.cpp b/examples/fabric-bridge-app/fabric-bridge-common/src/BridgedDeviceBasicInformationImpl.cpp new file mode 100644 index 00000000000000..7fa48a4a158ddd --- /dev/null +++ b/examples/fabric-bridge-app/fabric-bridge-common/src/BridgedDeviceBasicInformationImpl.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "BridgedDeviceBasicInformationImpl.h" + +#include "BridgedDeviceManager.h" + +#include +#include +#include + +#include + +static constexpr unsigned kBridgedDeviceBasicInformationClusterRevision = 4; + +using namespace ::chip; +using namespace ::chip::app; +using namespace ::chip::app::Clusters; + +CHIP_ERROR BridgedDeviceBasicInformationImpl::Read(const ConcreteReadAttributePath & path, AttributeValueEncoder & encoder) +{ + // Registration is done for the bridged device basic information only + VerifyOrDie(path.mClusterId == app::Clusters::BridgedDeviceBasicInformation::Id); + + BridgedDevice * dev = BridgeDeviceMgr().GetDevice(path.mEndpointId); + VerifyOrReturnError(dev != nullptr, CHIP_ERROR_NOT_FOUND); + + switch (path.mAttributeId) + { + case BasicInformation::Attributes::Reachable::Id: + encoder.Encode(dev->IsReachable()); + break; + case BasicInformation::Attributes::NodeLabel::Id: + encoder.Encode(CharSpan::fromCharString(dev->GetBridgedAttributes().nodeLabel.c_str())); + break; + case BasicInformation::Attributes::ClusterRevision::Id: + encoder.Encode(kBridgedDeviceBasicInformationClusterRevision); + break; + case BasicInformation::Attributes::FeatureMap::Id: { + BitMask features; + features.Set(Clusters::BridgedDeviceBasicInformation::Feature::kBridgedICDSupport, dev->IsIcd()); + encoder.Encode(features); + } + break; + case BasicInformation::Attributes::UniqueID::Id: + encoder.Encode(CharSpan::fromCharString(dev->GetBridgedAttributes().uniqueId.c_str())); + break; + case BasicInformation::Attributes::VendorName::Id: + encoder.Encode(CharSpan::fromCharString(dev->GetBridgedAttributes().vendorName.c_str())); + break; + case BasicInformation::Attributes::VendorID::Id: + encoder.Encode(dev->GetBridgedAttributes().vendorId); + break; + case BasicInformation::Attributes::ProductName::Id: + encoder.Encode(CharSpan::fromCharString(dev->GetBridgedAttributes().productName.c_str())); + break; + case BasicInformation::Attributes::ProductID::Id: + encoder.Encode(dev->GetBridgedAttributes().productId); + break; + case BasicInformation::Attributes::HardwareVersion::Id: + encoder.Encode(dev->GetBridgedAttributes().hardwareVersion); + break; + case BasicInformation::Attributes::HardwareVersionString::Id: + encoder.Encode(CharSpan::fromCharString(dev->GetBridgedAttributes().hardwareVersionString.c_str())); + break; + case BasicInformation::Attributes::SoftwareVersion::Id: + encoder.Encode(dev->GetBridgedAttributes().softwareVersion); + break; + case BasicInformation::Attributes::SoftwareVersionString::Id: + encoder.Encode(CharSpan::fromCharString(dev->GetBridgedAttributes().softwareVersionString.c_str())); + break; + default: + return CHIP_ERROR_INVALID_ARGUMENT; + } + return CHIP_NO_ERROR; +} + +CHIP_ERROR BridgedDeviceBasicInformationImpl::Write(const ConcreteDataAttributePath & path, AttributeValueDecoder & decoder) +{ + VerifyOrDie(path.mClusterId == app::Clusters::BridgedDeviceBasicInformation::Id); + + BridgedDevice * dev = BridgeDeviceMgr().GetDevice(path.mEndpointId); + VerifyOrReturnError(dev != nullptr, CHIP_ERROR_NOT_FOUND); + + if (!dev->IsReachable()) + { + return CHIP_ERROR_NOT_CONNECTED; + } + + ChipLogProgress(NotSpecified, "Bridged device basic information attempt to write attribute: ep=%d", path.mAttributeId); + + // nothing writable right now ... + + return CHIP_ERROR_INVALID_ARGUMENT; +} diff --git a/examples/fabric-bridge-app/fabric-bridge-common/src/BridgedDeviceManager.cpp b/examples/fabric-bridge-app/fabric-bridge-common/src/BridgedDeviceManager.cpp index 170b39cd2c94e2..8db44c3e8bfd9b 100644 --- a/examples/fabric-bridge-app/fabric-bridge-common/src/BridgedDeviceManager.cpp +++ b/examples/fabric-bridge-app/fabric-bridge-common/src/BridgedDeviceManager.cpp @@ -29,10 +29,12 @@ #include #include #include +#include #include #include #include +#include #include using namespace chip; @@ -45,8 +47,13 @@ using namespace chip::app::Clusters; namespace { -constexpr uint8_t kMaxRetries = 10; -constexpr int kNodeLabelSize = 32; +constexpr uint8_t kMaxRetries = 10; +constexpr int kNodeLabelSize = 32; +constexpr int kUniqueIdSize = 32; +constexpr int kVendorNameSize = 32; +constexpr int kProductNameSize = 32; +constexpr int kHardwareVersionSize = 64; +constexpr int kSoftwareVersionSize = 64; // Current ZCL implementation of Struct uses a max-size array of 254 bytes constexpr int kDescriptorAttributeArraySize = 254; @@ -76,27 +83,56 @@ constexpr int kDescriptorAttributeArraySize = 254; // - Bridged Device Basic Information // - Administrator Commissioning +// clang-format off // Declare Descriptor cluster attributes DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(descriptorAttrs) -DECLARE_DYNAMIC_ATTRIBUTE(Descriptor::Attributes::DeviceTypeList::Id, ARRAY, kDescriptorAttributeArraySize, 0), /* device list */ - DECLARE_DYNAMIC_ATTRIBUTE(Descriptor::Attributes::ServerList::Id, ARRAY, kDescriptorAttributeArraySize, 0), /* server list */ - DECLARE_DYNAMIC_ATTRIBUTE(Descriptor::Attributes::ClientList::Id, ARRAY, kDescriptorAttributeArraySize, 0), /* client list */ - DECLARE_DYNAMIC_ATTRIBUTE(Descriptor::Attributes::PartsList::Id, ARRAY, kDescriptorAttributeArraySize, 0), /* parts list */ - DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); + DECLARE_DYNAMIC_ATTRIBUTE(Descriptor::Attributes::DeviceTypeList::Id, ARRAY, kDescriptorAttributeArraySize, 0), /* device list */ + DECLARE_DYNAMIC_ATTRIBUTE(Descriptor::Attributes::ServerList::Id, ARRAY, kDescriptorAttributeArraySize, 0), /* server list */ + DECLARE_DYNAMIC_ATTRIBUTE(Descriptor::Attributes::ClientList::Id, ARRAY, kDescriptorAttributeArraySize, 0), /* client list */ + DECLARE_DYNAMIC_ATTRIBUTE(Descriptor::Attributes::PartsList::Id, ARRAY, kDescriptorAttributeArraySize, 0), /* parts list */ +DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); // Declare Bridged Device Basic Information cluster attributes DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(bridgedDeviceBasicAttrs) -DECLARE_DYNAMIC_ATTRIBUTE(BridgedDeviceBasicInformation::Attributes::NodeLabel::Id, CHAR_STRING, kNodeLabelSize, 0), /* NodeLabel */ - DECLARE_DYNAMIC_ATTRIBUTE(BridgedDeviceBasicInformation::Attributes::Reachable::Id, BOOLEAN, 1, 0), /* Reachable */ - DECLARE_DYNAMIC_ATTRIBUTE(BridgedDeviceBasicInformation::Attributes::FeatureMap::Id, BITMAP32, 4, 0), /* feature map */ + // The attributes below are MANDATORY in the Bridged Device Information Cluster + DECLARE_DYNAMIC_ATTRIBUTE(BridgedDeviceBasicInformation::Attributes::Reachable::Id, BOOLEAN, 1, 0), + DECLARE_DYNAMIC_ATTRIBUTE(BridgedDeviceBasicInformation::Attributes::UniqueID::Id, CHAR_STRING, kUniqueIdSize, 0), + DECLARE_DYNAMIC_ATTRIBUTE(BridgedDeviceBasicInformation::Attributes::FeatureMap::Id, BITMAP32, 4, 0), + + // The attributes below are OPTIONAL in the bridged device, however they are MANDATORY in the BasicInformation cluster + // so they can always be provided if desired + DECLARE_DYNAMIC_ATTRIBUTE(BridgedDeviceBasicInformation::Attributes::VendorName::Id, CHAR_STRING, kVendorNameSize, 0), + DECLARE_DYNAMIC_ATTRIBUTE(BridgedDeviceBasicInformation::Attributes::VendorID::Id, INT16U, 2, 0), + DECLARE_DYNAMIC_ATTRIBUTE(BridgedDeviceBasicInformation::Attributes::ProductName::Id, CHAR_STRING, kProductNameSize, 0), + DECLARE_DYNAMIC_ATTRIBUTE(BridgedDeviceBasicInformation::Attributes::ProductID::Id, INT16U, 2, 0), + DECLARE_DYNAMIC_ATTRIBUTE(BridgedDeviceBasicInformation::Attributes::NodeLabel::Id, CHAR_STRING, kNodeLabelSize, 0), + DECLARE_DYNAMIC_ATTRIBUTE(BridgedDeviceBasicInformation::Attributes::HardwareVersion::Id, INT16U, 2, 0), + DECLARE_DYNAMIC_ATTRIBUTE(BridgedDeviceBasicInformation::Attributes::HardwareVersionString::Id, CHAR_STRING, + kHardwareVersionSize, 0), + DECLARE_DYNAMIC_ATTRIBUTE(BridgedDeviceBasicInformation::Attributes::SoftwareVersion::Id, INT32U, 4, 0), + DECLARE_DYNAMIC_ATTRIBUTE(BridgedDeviceBasicInformation::Attributes::SoftwareVersionString::Id, CHAR_STRING, + kSoftwareVersionSize, 0), +DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); + +// Declare Ecosystem Information cluster attributes +DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(ecosystemInformationBasicAttrs) +DECLARE_DYNAMIC_ATTRIBUTE(EcosystemInformation::Attributes::RemovedOn::Id, EPOCH_US, kNodeLabelSize, ATTRIBUTE_MASK_NULLABLE), + DECLARE_DYNAMIC_ATTRIBUTE(EcosystemInformation::Attributes::DeviceDirectory::Id, ARRAY, kDescriptorAttributeArraySize, 0), + DECLARE_DYNAMIC_ATTRIBUTE(EcosystemInformation::Attributes::LocationDirectory::Id, ARRAY, kDescriptorAttributeArraySize, 0), DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); // Declare Administrator Commissioning cluster attributes DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(AdministratorCommissioningAttrs) -DECLARE_DYNAMIC_ATTRIBUTE(AdministratorCommissioning::Attributes::WindowStatus::Id, ENUM8, 1, 0), /* NodeLabel */ - DECLARE_DYNAMIC_ATTRIBUTE(AdministratorCommissioning::Attributes::AdminFabricIndex::Id, FABRIC_IDX, 1, 0), /* Reachable */ - DECLARE_DYNAMIC_ATTRIBUTE(AdministratorCommissioning::Attributes::AdminVendorId::Id, VENDOR_ID, 2, 0), /* Reachable */ - DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); + DECLARE_DYNAMIC_ATTRIBUTE(AdministratorCommissioning::Attributes::WindowStatus::Id, ENUM8, 1, 0), + DECLARE_DYNAMIC_ATTRIBUTE(AdministratorCommissioning::Attributes::AdminFabricIndex::Id, FABRIC_IDX, 1, 0), + DECLARE_DYNAMIC_ATTRIBUTE(AdministratorCommissioning::Attributes::AdminVendorId::Id, VENDOR_ID, 2, 0), +DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); +// clang-format on + +constexpr CommandId bridgedDeviceBasicInformationCommands[] = { + app::Clusters::BridgedDeviceBasicInformation::Commands::KeepActive::Id, + kInvalidCommandId, +}; constexpr CommandId administratorCommissioningCommands[] = { app::Clusters::AdministratorCommissioning::Commands::OpenCommissioningWindow::Id, @@ -105,15 +141,31 @@ constexpr CommandId administratorCommissioningCommands[] = { kInvalidCommandId, }; +// clang-format off // Declare Cluster List for Bridged Node endpoint DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(bridgedNodeClusters) -DECLARE_DYNAMIC_CLUSTER(Descriptor::Id, descriptorAttrs, ZAP_CLUSTER_MASK(SERVER), nullptr, nullptr), + DECLARE_DYNAMIC_CLUSTER(Descriptor::Id, descriptorAttrs, ZAP_CLUSTER_MASK(SERVER), nullptr, nullptr), DECLARE_DYNAMIC_CLUSTER(BridgedDeviceBasicInformation::Id, bridgedDeviceBasicAttrs, ZAP_CLUSTER_MASK(SERVER), nullptr, nullptr), + DECLARE_DYNAMIC_CLUSTER(EcosystemInformation::Id, ecosystemInformationBasicAttrs, ZAP_CLUSTER_MASK(SERVER), nullptr, nullptr), DECLARE_DYNAMIC_CLUSTER(AdministratorCommissioning::Id, AdministratorCommissioningAttrs, ZAP_CLUSTER_MASK(SERVER), - administratorCommissioningCommands, nullptr) DECLARE_DYNAMIC_CLUSTER_LIST_END; + administratorCommissioningCommands, nullptr) +DECLARE_DYNAMIC_CLUSTER_LIST_END; + +DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(icdBridgedNodeClusters) + DECLARE_DYNAMIC_CLUSTER(Descriptor::Id, descriptorAttrs, ZAP_CLUSTER_MASK(SERVER), nullptr, nullptr), + DECLARE_DYNAMIC_CLUSTER(BridgedDeviceBasicInformation::Id, bridgedDeviceBasicAttrs, ZAP_CLUSTER_MASK(SERVER), + bridgedDeviceBasicInformationCommands, nullptr), + DECLARE_DYNAMIC_CLUSTER(AdministratorCommissioning::Id, AdministratorCommissioningAttrs, ZAP_CLUSTER_MASK(SERVER), + administratorCommissioningCommands, nullptr) +DECLARE_DYNAMIC_CLUSTER_LIST_END; +// clang-format on // Declare Bridged Node endpoint DECLARE_DYNAMIC_ENDPOINT(sBridgedNodeEndpoint, bridgedNodeClusters); +DECLARE_DYNAMIC_ENDPOINT(sIcdBridgedNodeEndpoint, icdBridgedNodeClusters); + +// TODO: this is a single version array, however we may have many +// different clusters that are independent. DataVersion sBridgedNodeDataVersions[ArraySize(bridgedNodeClusters)]; const EmberAfDeviceType sBridgedDeviceTypes[] = { { DEVICE_TYPE_BRIDGED_NODE, DEVICE_VERSION_DEFAULT } }; @@ -125,60 +177,68 @@ BridgedDeviceManager BridgedDeviceManager::sInstance; void BridgedDeviceManager::Init() { - memset(mDevices, 0, sizeof(mDevices)); mFirstDynamicEndpointId = static_cast( static_cast(emberAfEndpointFromIndex(static_cast(emberAfFixedEndpointCount() - 1))) + 1); mCurrentEndpointId = mFirstDynamicEndpointId; } -int BridgedDeviceManager::AddDeviceEndpoint(BridgedDevice * dev, chip::EndpointId parentEndpointId) +std::optional BridgedDeviceManager::AddDeviceEndpoint(std::unique_ptr dev, + chip::EndpointId parentEndpointId) { - uint8_t index = 0; - EmberAfEndpointType * ep = &sBridgedNodeEndpoint; + EmberAfEndpointType * ep = dev->IsIcd() ? &sIcdBridgedNodeEndpoint : &sBridgedNodeEndpoint; + const chip::Span & deviceTypeList = Span(sBridgedDeviceTypes); - const chip::Span & dataVersionStorage = Span(sBridgedNodeDataVersions); - while (index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) + // TODO: this shares data version among different clusters, which seems incorrect + const chip::Span & dataVersionStorage = Span(sBridgedNodeDataVersions); + + if (dev->GetBridgedAttributes().uniqueId.empty()) { - if (nullptr == mDevices[index]) + dev->SetUniqueId(GenerateUniqueId()); + } + else if (GetDeviceByUniqueId(dev->GetBridgedAttributes().uniqueId) != nullptr) + { + ChipLogProgress(NotSpecified, "A device with unique id '%s' already exists", dev->GetBridgedAttributes().uniqueId.c_str()); + return std::nullopt; + } + + for (unsigned index = 0; index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT; index++) + { + if (mDevices[index]) + { + continue; + } + + for (int retryCount = 0; retryCount < kMaxRetries; retryCount++) { - mDevices[index] = dev; - CHIP_ERROR err; - int retryCount = 0; - while (retryCount < kMaxRetries) + DeviceLayer::StackLock lock; + dev->SetEndpointId(mCurrentEndpointId); + dev->SetParentEndpointId(parentEndpointId); + CHIP_ERROR err = + emberAfSetDynamicEndpoint(index, mCurrentEndpointId, ep, dataVersionStorage, deviceTypeList, parentEndpointId); + if (err == CHIP_NO_ERROR) { - DeviceLayer::StackLock lock; - dev->SetEndpointId(mCurrentEndpointId); - dev->SetParentEndpointId(parentEndpointId); - err = - emberAfSetDynamicEndpoint(index, mCurrentEndpointId, ep, dataVersionStorage, deviceTypeList, parentEndpointId); - if (err == CHIP_NO_ERROR) - { - ChipLogProgress(NotSpecified, - "Added device with nodeId=0x" ChipLogFormatX64 " to dynamic endpoint %d (index=%d)", - ChipLogValueX64(dev->GetNodeId()), mCurrentEndpointId, index); - return index; - } - if (err != CHIP_ERROR_ENDPOINT_EXISTS) - { - mDevices[index] = nullptr; - return -1; // Return error as endpoint addition failed due to an error other than endpoint already exists - } - // Increment the endpoint ID and handle wrap condition - if (++mCurrentEndpointId < mFirstDynamicEndpointId) - { - mCurrentEndpointId = mFirstDynamicEndpointId; - } - retryCount++; + ChipLogProgress(NotSpecified, "Added device with nodeId=0x" ChipLogFormatX64 " to dynamic endpoint %d (index=%d)", + ChipLogValueX64(dev->GetNodeId()), mCurrentEndpointId, index); + mDevices[index] = std::move(dev); + return index; + } + if (err != CHIP_ERROR_ENDPOINT_EXISTS) + { + return std::nullopt; // Return error as endpoint addition failed due to an error other than endpoint already exists + } + // Increment the endpoint ID and handle wrap condition + if (++mCurrentEndpointId < mFirstDynamicEndpointId) + { + mCurrentEndpointId = mFirstDynamicEndpointId; } - ChipLogError(NotSpecified, "Failed to add dynamic endpoint after %d retries", kMaxRetries); - mDevices[index] = nullptr; - return -1; // Return error as all retries are exhausted } - index++; + ChipLogError(NotSpecified, "Failed to add dynamic endpoint after %d retries", kMaxRetries); + return std::nullopt; // Return error as all retries are exhausted } + ChipLogProgress(NotSpecified, "Failed to add dynamic endpoint: No endpoints available!"); - return -1; + return std::nullopt; } int BridgedDeviceManager::RemoveDeviceEndpoint(BridgedDevice * dev) @@ -186,14 +246,15 @@ int BridgedDeviceManager::RemoveDeviceEndpoint(BridgedDevice * dev) uint8_t index = 0; while (index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) { - if (mDevices[index] == dev) + if (mDevices[index].get() == dev) { DeviceLayer::StackLock lock; // Silence complaints about unused ep when progress logging // disabled. [[maybe_unused]] EndpointId ep = emberAfClearDynamicEndpoint(index); mDevices[index] = nullptr; - ChipLogProgress(NotSpecified, "Removed device %s from dynamic endpoint %d (index=%d)", dev->GetName(), ep, index); + ChipLogProgress(NotSpecified, "Removed device %s from dynamic endpoint %d (index=%d)", + dev->GetBridgedAttributes().uniqueId.c_str(), ep, index); return index; } index++; @@ -207,7 +268,45 @@ BridgedDevice * BridgedDeviceManager::GetDevice(chip::EndpointId endpointId) con { if (mDevices[index] && mDevices[index]->GetEndpointId() == endpointId) { - return mDevices[index]; + return mDevices[index].get(); + } + } + return nullptr; +} + +std::string BridgedDeviceManager::GenerateUniqueId() +{ + char rand_buffer[kUniqueIdSize + 1]; + memset(rand_buffer, 0, sizeof(rand_buffer)); + + static const char kRandCharChoices[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + while (true) + { + /// for nice viewing, prefix the generated value + memcpy(rand_buffer, "GEN-", 4); + for (unsigned idx = 4; idx < kUniqueIdSize; idx++) + { + rand_buffer[idx] = kRandCharChoices[Crypto::GetRandU8() % (sizeof(kRandCharChoices) - 1)]; + } + + // we know zero-terminated due to the memset + std::string uniqueIdChoice = rand_buffer; + + if (!GetDeviceByUniqueId(uniqueIdChoice)) + { + return uniqueIdChoice; + } + } +} + +BridgedDevice * BridgedDeviceManager::GetDeviceByUniqueId(const std::string & id) +{ + for (uint8_t index = 0; index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT; ++index) + { + if (mDevices[index] && mDevices[index]->GetBridgedAttributes().uniqueId == id) + { + return mDevices[index].get(); } } return nullptr; @@ -219,15 +318,15 @@ BridgedDevice * BridgedDeviceManager::GetDeviceByNodeId(chip::NodeId nodeId) con { if (mDevices[index] && mDevices[index]->GetNodeId() == nodeId) { - return mDevices[index]; + return mDevices[index].get(); } } return nullptr; } -int BridgedDeviceManager::RemoveDeviceByNodeId(chip::NodeId nodeId) +std::optional BridgedDeviceManager::RemoveDeviceByNodeId(chip::NodeId nodeId) { - for (uint8_t index = 0; index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT; ++index) + for (unsigned index = 0; index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT; ++index) { if (mDevices[index] && mDevices[index]->GetNodeId() == nodeId) { @@ -239,5 +338,5 @@ int BridgedDeviceManager::RemoveDeviceByNodeId(chip::NodeId nodeId) return index; } } - return -1; + return std::nullopt; } diff --git a/examples/fabric-bridge-app/fabric-bridge-common/src/CommissionerControl.cpp b/examples/fabric-bridge-app/fabric-bridge-common/src/CommissionerControl.cpp new file mode 100644 index 00000000000000..076ced816596d2 --- /dev/null +++ b/examples/fabric-bridge-app/fabric-bridge-common/src/CommissionerControl.cpp @@ -0,0 +1,175 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CommissionerControl.h" + +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; + +namespace { + +std::unique_ptr sCommissionerControlDelegate; + +} // namespace + +namespace chip { +namespace app { +namespace Clusters { +namespace CommissionerControl { + +CHIP_ERROR CommissionerControlDelegate::HandleCommissioningApprovalRequest(const CommissioningApprovalRequest & request) +{ + CommissionerControl::Events::CommissioningRequestResult::Type result; + result.requestId = request.requestId; + result.clientNodeId = request.clientNodeId; + result.fabricIndex = request.fabricIndex; + result.statusCode = static_cast(Protocols::InteractionModel::Status::Success); + + mRequestId = request.requestId; + mClientNodeId = request.clientNodeId; + mVendorId = request.vendorId; + mProductId = request.productId; + + if (request.label.HasValue()) + { + const CharSpan & labelSpan = request.label.Value(); + size_t labelLength = labelSpan.size(); + + if (labelLength >= kLabelBufferSize) + { + ChipLogError(Zcl, "Label too long to fit in buffer"); + return CHIP_ERROR_BUFFER_TOO_SMALL; + } + + if (labelLength == 0) + { + mLabel.ClearValue(); + } + else + { + memcpy(mLabelBuffer, labelSpan.data(), labelLength); + mLabelBuffer[labelLength] = '\0'; // Null-terminate the copied string + mLabel.SetValue(CharSpan(mLabelBuffer, labelLength)); + } + } + else + { + mLabel.ClearValue(); + } + + return CommissionerControlServer::Instance().GenerateCommissioningRequestResultEvent(result); +} + +CHIP_ERROR CommissionerControlDelegate::ValidateCommissionNodeCommand(NodeId clientNodeId, uint64_t requestId) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + // Verify if the CommissionNode command is sent from the same NodeId as the RequestCommissioningApproval. + VerifyOrExit(mClientNodeId == clientNodeId, err = CHIP_ERROR_WRONG_NODE_ID); + + // Verify if the provided RequestId matches the value provided to the RequestCommissioningApproval. + VerifyOrExit(mRequestId == requestId, err = CHIP_ERROR_INCORRECT_STATE); + +exit: + return err; +} + +CHIP_ERROR CommissionerControlDelegate::GetCommissioningWindowParams(CommissioningWindowParams & outParams) +{ + // TODO: Populate outParams with the required details. + // outParams.commissioningWindowParams.iterations = mIterations; + // outParams.commissioningWindowParams.commissioningTimeout = mCommissioningTimeout; + // outParams.commissioningWindowParams.discriminator = mDiscriminator; + // outParams.commissioningWindowParams.PAKEPasscodeVerifier = mPAKEPasscodeVerifier; + // outParams.commissioningWindowParams.salt = mSalt; + + // outParams.ipAddress = mIpAddress; + // outParams.port = mPort; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR CommissionerControlDelegate::ReverseCommissionNode(const CommissioningWindowParams & params, + const Optional & ipAddress, const Optional & port) +{ + return CHIP_NO_ERROR; +} + +} // namespace CommissionerControl +} // namespace Clusters +} // namespace app +} // namespace chip + +CHIP_ERROR CommissionerControlInit() +{ + CHIP_ERROR err; + + if (sCommissionerControlDelegate) + { + ChipLogError(NotSpecified, "Commissioner Control Delegate already exists."); + return CHIP_ERROR_INCORRECT_STATE; + } + + sCommissionerControlDelegate = std::make_unique(); + if (!sCommissionerControlDelegate) + { + ChipLogError(NotSpecified, "Failed to allocate memory for Commissioner Control Delegate."); + return CHIP_ERROR_NO_MEMORY; + } + + err = Clusters::CommissionerControl::CommissionerControlServer::Instance().Init(*sCommissionerControlDelegate); + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "Initialization failed on Commissioner Control Delegate."); + sCommissionerControlDelegate.reset(); + return err; + } + + ChipLogProgress(Zcl, "Initializing SupportedDeviceCategories of Commissioner Control Cluster for this device."); + + BitMask supportedDeviceCategories; + supportedDeviceCategories.SetField(Clusters::CommissionerControl::SupportedDeviceCategoryBitmap::kFabricSynchronization, 1); + + Protocols::InteractionModel::Status status = + Clusters::CommissionerControl::CommissionerControlServer::Instance().SetSupportedDeviceCategoriesValue( + kRootEndpointId, supportedDeviceCategories); + + if (status != Protocols::InteractionModel::Status::Success) + { + ChipLogError(NotSpecified, "Failed to set SupportedDeviceCategories: %d", static_cast(status)); + sCommissionerControlDelegate.reset(); + return CHIP_ERROR_INTERNAL; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR CommissionerControlShutdown() +{ + if (sCommissionerControlDelegate) + { + sCommissionerControlDelegate.reset(); + } + + return CHIP_NO_ERROR; +} diff --git a/examples/fabric-bridge-app/fabric-bridge-common/src/ZCLCallbacks.cpp b/examples/fabric-bridge-app/fabric-bridge-common/src/ZCLCallbacks.cpp index 26e727901abf0e..d4da982cfa45a5 100644 --- a/examples/fabric-bridge-app/fabric-bridge-common/src/ZCLCallbacks.cpp +++ b/examples/fabric-bridge-app/fabric-bridge-common/src/ZCLCallbacks.cpp @@ -25,88 +25,26 @@ using namespace ::chip; using namespace ::chip::app::Clusters; -#define ZCL_DESCRIPTOR_CLUSTER_REVISION (1u) #define ZCL_ADMINISTRATOR_COMMISSIONING_CLUSTER_REVISION (1u) -#define ZCL_BRIDGED_DEVICE_BASIC_INFORMATION_CLUSTER_REVISION (2u) -#define ZCL_BRIDGED_DEVICE_BASIC_INFORMATION_FEATURE_MAP (0u) // External attribute read callback function Protocols::InteractionModel::Status emberAfExternalAttributeReadCallback(EndpointId endpoint, ClusterId clusterId, const EmberAfAttributeMetadata * attributeMetadata, uint8_t * buffer, uint16_t maxReadLength) { - AttributeId attributeId = attributeMetadata->attributeId; - - BridgedDevice * dev = BridgeDeviceMgr().GetDevice(endpoint); - if (dev == nullptr) - { - return Protocols::InteractionModel::Status::Failure; - } - - if (clusterId == BridgedDeviceBasicInformation::Id) - { - using namespace BridgedDeviceBasicInformation::Attributes; - ChipLogProgress(NotSpecified, "HandleReadBridgedDeviceBasicAttribute: attrId=%d, maxReadLength=%d", attributeId, - maxReadLength); - - if ((attributeId == Reachable::Id) && (maxReadLength == 1)) - { - *buffer = dev->IsReachable() ? 1 : 0; - } - else if ((attributeId == NodeLabel::Id) && (maxReadLength == 32)) - { - MutableByteSpan zclNameSpan(buffer, maxReadLength); - MakeZclCharString(zclNameSpan, dev->GetName()); - } - else if ((attributeId == ClusterRevision::Id) && (maxReadLength == 2)) - { - uint16_t rev = ZCL_BRIDGED_DEVICE_BASIC_INFORMATION_CLUSTER_REVISION; - memcpy(buffer, &rev, sizeof(rev)); - } - else if ((attributeId == FeatureMap::Id) && (maxReadLength == 4)) - { - uint32_t featureMap = ZCL_BRIDGED_DEVICE_BASIC_INFORMATION_FEATURE_MAP; - memcpy(buffer, &featureMap, sizeof(featureMap)); - } - else - { - return Protocols::InteractionModel::Status::Failure; - } - return Protocols::InteractionModel::Status::Success; - } - if (clusterId == AdministratorCommissioning::Id) { // TODO(#34791) This is a workaround to prevent crash. CADMIN is still reading incorrect // Attribute values on dynamic endpoint as it only reads the root node and not the actual bridge // device we are representing here, when addressing the issue over there we can more easily // resolve this workaround. - if ((attributeId == AdministratorCommissioning::Attributes::ClusterRevision::Id) && (maxReadLength == 2)) + if ((attributeMetadata->attributeId == AdministratorCommissioning::Attributes::ClusterRevision::Id) && (maxReadLength == 2)) { uint16_t rev = ZCL_ADMINISTRATOR_COMMISSIONING_CLUSTER_REVISION; memcpy(buffer, &rev, sizeof(rev)); return Protocols::InteractionModel::Status::Success; } - return Protocols::InteractionModel::Status::Failure; } return Protocols::InteractionModel::Status::Failure; } - -// External attribute write callback function -Protocols::InteractionModel::Status emberAfExternalAttributeWriteCallback(EndpointId endpoint, ClusterId clusterId, - const EmberAfAttributeMetadata * attributeMetadata, - uint8_t * buffer) -{ - uint16_t endpointIndex = emberAfGetDynamicIndexFromEndpoint(endpoint); - Protocols::InteractionModel::Status ret = Protocols::InteractionModel::Status::Failure; - - BridgedDevice * dev = BridgeDeviceMgr().GetDevice(endpointIndex); - if (dev != nullptr && dev->IsReachable()) - { - ChipLogProgress(NotSpecified, "emberAfExternalAttributeWriteCallback: ep=%d, clusterId=%d", endpoint, clusterId); - ret = Protocols::InteractionModel::Status::Success; - } - - return ret; -} diff --git a/examples/fabric-bridge-app/linux/RpcClient.cpp b/examples/fabric-bridge-app/linux/RpcClient.cpp index d2aef5d1d82e5e..1260c8744b67f2 100644 --- a/examples/fabric-bridge-app/linux/RpcClient.cpp +++ b/examples/fabric-bridge-app/linux/RpcClient.cpp @@ -87,6 +87,24 @@ void OnOpenCommissioningWindowCompleted(const chip_rpc_OperationStatus & respons } } +// Callback function to be called when the RPC response is received for generic empty response. +void RpcCompletedWithEmptyResponse(const pw_protobuf_Empty & response, pw::Status status) +{ + std::lock_guard lock(responseMutex); + responseReceived = true; + responseError = status.ok() ? CHIP_NO_ERROR : CHIP_ERROR_INTERNAL; + responseCv.notify_one(); + + if (status.ok()) + { + ChipLogProgress(NotSpecified, "RPC call succeeded!"); + } + else + { + ChipLogProgress(NotSpecified, "RPC call failed with status: %d", status.code()); + } +} + } // namespace CHIP_ERROR InitRpcClient(uint16_t rpcServerPort) @@ -143,3 +161,22 @@ OpenCommissioningWindow(chip::Controller::CommissioningWindowVerifierParams para return OpenCommissioningWindow(device); } + +CHIP_ERROR KeepActive(chip::NodeId nodeId, uint32_t stayActiveDurationMs) +{ + chip_rpc_KeepActiveParameters params; + params.node_id = nodeId; + params.stay_active_duration_ms = stayActiveDurationMs; + + // The RPC call is kept alive until it completes. When a response is received, it will be logged by the handler + // function and the call will complete. + auto call = fabricAdminClient.KeepActive(params, RpcCompletedWithEmptyResponse); + + if (!call.active()) + { + // The RPC call was not sent. This could occur due to, for example, an invalid channel ID. Handle if necessary. + return CHIP_ERROR_INTERNAL; + } + + return WaitForResponse(call); +} diff --git a/examples/fabric-bridge-app/linux/RpcServer.cpp b/examples/fabric-bridge-app/linux/RpcServer.cpp index 76fe8f84653d39..bae007ed484935 100644 --- a/examples/fabric-bridge-app/linux/RpcServer.cpp +++ b/examples/fabric-bridge-app/linux/RpcServer.cpp @@ -20,6 +20,7 @@ #include "pw_rpc_system_server/rpc_server.h" #include "pw_rpc_system_server/socket.h" +#include #include #include @@ -44,6 +45,7 @@ class FabricBridge final : public chip::rpc::FabricBridge public: pw::Status AddSynchronizedDevice(const chip_rpc_SynchronizedDevice & request, pw_protobuf_Empty & response) override; pw::Status RemoveSynchronizedDevice(const chip_rpc_SynchronizedDevice & request, pw_protobuf_Empty & response) override; + pw::Status ActiveChanged(const chip_rpc_KeepActiveChanged & request, pw_protobuf_Empty & response) override; }; pw::Status FabricBridge::AddSynchronizedDevice(const chip_rpc_SynchronizedDevice & request, pw_protobuf_Empty & response) @@ -51,17 +53,78 @@ pw::Status FabricBridge::AddSynchronizedDevice(const chip_rpc_SynchronizedDevice NodeId nodeId = request.node_id; ChipLogProgress(NotSpecified, "Received AddSynchronizedDevice: " ChipLogFormatX64, ChipLogValueX64(nodeId)); - BridgedDevice * device = new BridgedDevice(nodeId); + auto device = std::make_unique(nodeId); device->SetReachable(true); - int result = BridgeDeviceMgr().AddDeviceEndpoint(device, 1); - if (result == -1) + BridgedDevice::BridgedAttributes attributes; + + if (request.has_unique_id) + { + attributes.uniqueId = request.unique_id; + } + + if (request.has_vendor_name) + { + attributes.vendorName = request.vendor_name; + } + + if (request.has_vendor_id) + { + attributes.vendorId = request.vendor_id; + } + + if (request.has_product_name) + { + attributes.productName = request.product_name; + } + + if (request.has_product_id) + { + attributes.productId = request.product_id; + } + + if (request.has_node_label) + { + attributes.nodeLabel = request.node_label; + } + + if (request.has_hardware_version) + { + attributes.hardwareVersion = request.hardware_version; + } + + if (request.has_hardware_version_string) + { + attributes.hardwareVersionString = request.hardware_version_string; + } + + if (request.has_software_version) + { + attributes.softwareVersion = request.software_version; + } + + if (request.has_software_version_string) + { + attributes.softwareVersionString = request.software_version_string; + } + + device->SetBridgedAttributes(attributes); + device->SetIcd(request.has_is_icd && request.is_icd); + + auto result = BridgeDeviceMgr().AddDeviceEndpoint(std::move(device), 1 /* parentEndpointId */); + if (!result.has_value()) { - delete device; ChipLogError(NotSpecified, "Failed to add device with nodeId=0x" ChipLogFormatX64, ChipLogValueX64(nodeId)); return pw::Status::Unknown(); } + BridgedDevice * addedDevice = BridgeDeviceMgr().GetDeviceByNodeId(nodeId); + VerifyOrDie(addedDevice); + + CHIP_ERROR err = EcosystemInformation::EcosystemInformationServer::Instance().AddEcosystemInformationClusterToEndpoint( + addedDevice->GetEndpointId()); + VerifyOrDie(err == CHIP_NO_ERROR); + return pw::OkStatus(); } @@ -70,8 +133,8 @@ pw::Status FabricBridge::RemoveSynchronizedDevice(const chip_rpc_SynchronizedDev NodeId nodeId = request.node_id; ChipLogProgress(NotSpecified, "Received RemoveSynchronizedDevice: " ChipLogFormatX64, ChipLogValueX64(nodeId)); - int removed_idx = BridgeDeviceMgr().RemoveDeviceByNodeId(nodeId); - if (removed_idx < 0) + auto removed_idx = BridgeDeviceMgr().RemoveDeviceByNodeId(nodeId); + if (!removed_idx.has_value()) { ChipLogError(NotSpecified, "Failed to remove device with nodeId=0x" ChipLogFormatX64, ChipLogValueX64(nodeId)); return pw::Status::NotFound(); @@ -80,6 +143,23 @@ pw::Status FabricBridge::RemoveSynchronizedDevice(const chip_rpc_SynchronizedDev return pw::OkStatus(); } +pw::Status FabricBridge::ActiveChanged(const chip_rpc_KeepActiveChanged & request, pw_protobuf_Empty & response) +{ + NodeId nodeId = request.node_id; + ChipLogProgress(NotSpecified, "Received ActiveChanged: " ChipLogFormatX64, ChipLogValueX64(nodeId)); + + auto * device = BridgeDeviceMgr().GetDeviceByNodeId(nodeId); + if (device == nullptr) + { + ChipLogError(NotSpecified, "Could not find bridged device associated with nodeId=0x" ChipLogFormatX64, + ChipLogValueX64(nodeId)); + return pw::Status::NotFound(); + } + + device->LogActiveChangeEvent(request.promised_active_duration_ms); + return pw::OkStatus(); +} + FabricBridge fabric_bridge_service; #endif // defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE diff --git a/examples/fabric-bridge-app/linux/include/RpcClient.h b/examples/fabric-bridge-app/linux/include/RpcClient.h index e7e2cc5b48505c..6913a66d8c24a1 100644 --- a/examples/fabric-bridge-app/linux/include/RpcClient.h +++ b/examples/fabric-bridge-app/linux/include/RpcClient.h @@ -56,3 +56,5 @@ OpenCommissioningWindow(chip::Controller::CommissioningWindowPasscodeParams para */ CHIP_ERROR OpenCommissioningWindow(chip::Controller::CommissioningWindowVerifierParams params); + +CHIP_ERROR KeepActive(chip::NodeId nodeId, uint32_t stayActiveDurationMs); diff --git a/examples/fabric-bridge-app/linux/main.cpp b/examples/fabric-bridge-app/linux/main.cpp index c708b256727520..57907db8872b0a 100644 --- a/examples/fabric-bridge-app/linux/main.cpp +++ b/examples/fabric-bridge-app/linux/main.cpp @@ -19,26 +19,36 @@ #include #include "BridgedDevice.h" +#include "BridgedDeviceBasicInformationImpl.h" #include "BridgedDeviceManager.h" #include "CommissionableInit.h" +#include "CommissionerControl.h" #include #include +#include #if defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE #include "RpcClient.h" #include "RpcServer.h" #endif -#include #include #include -using namespace chip; +// This is declared here and not in a header because zap/embr assumes all clusters +// are defined in a static endpoint in the .zap file. From there, the codegen will +// automatically use PluginApplicationCallbacksHeader.jinja to declare and call +// the respective Init callbacks. However, because EcosystemInformation cluster is only +// ever on a dynamic endpoint, this doesn't get declared and called for us, so we +// need to declare and call it ourselves where the application is initialized. +void MatterEcosystemInformationPluginServerInitCallback(); +using namespace chip; using namespace chip::app; using namespace chip::app::Clusters; using namespace chip::app::Clusters::AdministratorCommissioning; +using namespace chip::app::Clusters::BridgedDeviceBasicInformation; namespace { @@ -48,6 +58,8 @@ constexpr uint16_t kPollIntervalMs = 100; constexpr uint16_t kRetryIntervalS = 3; #endif +BridgedDeviceBasicInformationImpl gBridgedDeviceBasicInformationAttributes; + bool KeyboardHit() { int bytesWaiting; @@ -122,7 +134,8 @@ void AdministratorCommissioningCommandHandler::InvokeCommand(HandlerContext & ha EndpointId endpointId = handlerContext.mRequestPath.mEndpointId; ChipLogProgress(NotSpecified, "Received command to open commissioning window on Endpoint: %d", endpointId); - if (handlerContext.mRequestPath.mCommandId != Commands::OpenCommissioningWindow::Id || endpointId == kRootEndpointId) + if (handlerContext.mRequestPath.mCommandId != AdministratorCommissioning::Commands::OpenCommissioningWindow::Id || + endpointId == kRootEndpointId) { // Proceed with default handling in Administrator Commissioning Server return; @@ -130,7 +143,7 @@ void AdministratorCommissioningCommandHandler::InvokeCommand(HandlerContext & ha handlerContext.SetCommandHandled(); - Commands::OpenCommissioningWindow::DecodableType commandData; + AdministratorCommissioning::Commands::OpenCommissioningWindow::DecodableType commandData; if (DataModel::Decode(handlerContext.mPayload, commandData) != CHIP_NO_ERROR) { handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::InvalidCommand); @@ -166,7 +179,63 @@ void AdministratorCommissioningCommandHandler::InvokeCommand(HandlerContext & ha handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, status); } +class BridgedDeviceInformationCommandHandler : public CommandHandlerInterface +{ +public: + // Register for the BridgedDeviceBasicInformation cluster on all endpoints. + BridgedDeviceInformationCommandHandler() : + CommandHandlerInterface(Optional::Missing(), BridgedDeviceBasicInformation::Id) + {} + + void InvokeCommand(HandlerContext & handlerContext) override; +}; + +void BridgedDeviceInformationCommandHandler::InvokeCommand(HandlerContext & handlerContext) +{ + using Protocols::InteractionModel::Status; + VerifyOrReturn(handlerContext.mRequestPath.mCommandId == BridgedDeviceBasicInformation::Commands::KeepActive::Id); + + EndpointId endpointId = handlerContext.mRequestPath.mEndpointId; + ChipLogProgress(NotSpecified, "Received command to KeepActive on Endpoint: %d", endpointId); + + BridgedDevice * device = BridgeDeviceMgr().GetDevice(endpointId); + + handlerContext.SetCommandHandled(); + + if (device == nullptr || !device->IsIcd()) + { + handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::Failure); + return; + } + + BridgedDeviceBasicInformation::Commands::KeepActive::DecodableType commandData; + if (DataModel::Decode(handlerContext.mPayload, commandData) != CHIP_NO_ERROR) + { + handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::InvalidCommand); + return; + } + + Status status = Status::Failure; + +#if defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE + if (KeepActive(device->GetNodeId(), commandData.stayActiveDuration) == CHIP_NO_ERROR) + { + ChipLogProgress(NotSpecified, "KeepActive successfully processed"); + status = Status::Success; + } + else + { + ChipLogProgress(NotSpecified, "KeepActive failed to process"); + } +#else + ChipLogProgress(NotSpecified, "Unable to properly call KeepActive: PW_RPC_FABRIC_BRIDGE_SERVICE not defined"); +#endif // defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE + + handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, status); +} + AdministratorCommissioningCommandHandler gAdministratorCommissioningCommandHandler; +BridgedDeviceInformationCommandHandler gBridgedDeviceInformationCommandHandler; } // namespace @@ -174,7 +243,10 @@ void ApplicationInit() { ChipLogDetail(NotSpecified, "Fabric-Bridge: ApplicationInit()"); - CommandHandlerInterfaceRegistry::RegisterCommandHandler(&gAdministratorCommissioningCommandHandler); + MatterEcosystemInformationPluginServerInitCallback(); + CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(&gAdministratorCommissioningCommandHandler); + CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(&gBridgedDeviceInformationCommandHandler); + AttributeAccessInterfaceRegistry::Instance().Register(&gBridgedDeviceBasicInformationAttributes); #if defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE InitRpcServer(kFabricBridgeServerPort); @@ -186,11 +258,19 @@ void ApplicationInit() pollingThread.detach(); BridgeDeviceMgr().Init(); + + VerifyOrDieWithMsg(CommissionerControlInit() == CHIP_NO_ERROR, NotSpecified, + "Failed to initialize Commissioner Control Server"); } void ApplicationShutdown() { ChipLogDetail(NotSpecified, "Fabric-Bridge: ApplicationShutdown()"); + + if (CommissionerControlShutdown() != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to shutdown Commissioner Control Server"); + } } int main(int argc, char * argv[]) diff --git a/examples/lighting-app/bouffalolab/README.md b/examples/lighting-app/bouffalolab/README.md index 83ff6a87b6a0f4..d2fd8b72afadf6 100644 --- a/examples/lighting-app/bouffalolab/README.md +++ b/examples/lighting-app/bouffalolab/README.md @@ -4,7 +4,13 @@ This example functions as a light bulb device type, with on/off and level capabilities and uses a test Vendor ID (VID) and a Product ID (PID) of **0x8005**. -The steps were verified on `Bouffalo Lab` BL602 and BL706 development board. +Current supported boards: + +- `BL602DK` +- `BL706DK` +- `BL704LDK` + +Legacy supported boards: - `BL602-IoT-Matter-V1`, [here](https://www.amazon.com/dp/B0B9ZVGXD8) to purchase. @@ -21,10 +27,6 @@ The steps were verified on `Bouffalo Lab` BL602 and BL706 development board. BL602/BL604 is combo chip-set for Wi-Fi 802.11b/g/n and BLE 5.0 base-band/MAC. -### BL602-IoT-Matter-V1 - - - ## BL70x BL70x is combo chip-set for BLE and IEEE 802.15.4/ZigBee/Thread. @@ -35,16 +37,34 @@ BL70x is combo chip-set for BLE and IEEE 802.15.4/ZigBee/Thread. general name. BL70x has fully certified with all Thread 1.3 features, included Thread `SSED` -and Thread Border Router with `DUA manager`. - -### `XT-ZB6-DevKit` - - +and Thread Border Router. + +## Solutions introduction + +`Bouffalo Lab` has full connectives support for Matter Applications. + +- Wi-Fi 4/6 application, we have + - BL602, Wi-Fi 4 application. + - BL706 + BL602, Wi-Fi 4 application. BL602 runs as a normal WLAN + transceiver; TCP/IP stack runs as BL706 side. We recommend this solution + is for Openthread Border Router application and Matter ZigBee bridge. + - Openthread Border Router application, please refer to Openthread + Border Router application + - Matter ZigBee Bridge application, please contact `Bouffalo Lab` for + support. +- Thread application, we have + - B70X +- Ethernet application, we have + - BL706. It supports single Matter application, and also Openthread Border + Router application and Matter ZigBee bridge + - Openthread Border Router application, please refer to Openthread + Border Router application + - Matter ZigBee application, please contact `Bouffalo Lab` for + support. ## Initial setup -The following steps in this document were validated on Ubuntu 18.04/20.04 and -Mac OS. +The following steps in this document were validated on Ubuntu 20.04. - Install dependencies as specified in the **connectedhomeip** repository: [Building Matter](https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/BUILDING.md). @@ -58,77 +78,67 @@ Mac OS. source ./scripts/activate.sh -p bouffalolab ``` - > After environment setup `Bouffalo Lab` flash tool, `bflb-iot-tool`, - > imports under this environment. If not, please try - > `scripts/bootstrap.sh -p bouffalolab` for matter environment update. - - Setup build environment for `Bouffalo Lab` SoC - Run `setup.sh` to install `Bouffalo Lab` SDK to /opt/bouffalolab_sdk - ``` - cd third_party/bouffalolab/repo - sudo bash scripts/setup.sh + ./integrations/docker/images/stage-2/chip-build-bouffalolab/setup.sh ``` - Please execute following command to export `BOUFFALOLAB_SDK_ROOT` before - building. + Script `setpu.sh` requires to select install path, and please execute + following command to export `BOUFFALOLAB_SDK_ROOT` before building. ``` - export BOUFFALOLAB_SDK_ROOT=/opt/bouffalolab_sdk + export BOUFFALOLAB_SDK_ROOT="Your install path" ``` ## Build CHIP Lighting App example -The following steps take examples for `BL602-IoT-Matter-V1` BL602 board, -`BL706DK` BL706 board, and `BL704LDK` BL704L board . +The following steps take examples for `BL602DK`, `BL704LDK` and `BL706DK`. - Build lighting app with UART baudrate 2000000 ``` - ./scripts/build/build_examples.py --target bouffalolab-bl602-iot-matter-v1-light build - ./scripts/build/build_examples.py --target bouffalolab-bl706dk-light build - ./scripts/build/build_examples.py --target bouffalolab-bl706dk-light-ethernet build - ./scripts/build/build_examples.py --target bouffalolab-bl706dk-light-wifi build + ./scripts/build/build_examples.py --target bouffalolab-bl602dk-light build ./scripts/build/build_examples.py --target bouffalolab-bl704ldk-light build - ``` - -- Build lighting app with UART baudrate 115200 - - ``` - ./scripts/build/build_examples.py --target bouffalolab-bl602-iot-matter-v1-light-115200 build - ./scripts/build/build_examples.py --target bouffalolab-bl706dk-light-light-115200 build - ./scripts/build/build_examples.py --target bouffalolab-bl704ldk-light-light-115200 build + ./scripts/build/build_examples.py --target bouffalolab-bl706dk-light build ``` - Build lighting app with RPC enabled and UART baudrate 115200. ``` - ./scripts/build/build_examples.py --target bouffalolab-bl602-iot-matter-v1-light-rpc build - ./scripts/build/build_examples.py --target bouffalolab-bl706dk-light-light-rpc build - ./scripts/build/build_examples.py --target bouffalolab-bl704ldk-light-light-rpc build + ./scripts/build/build_examples.py --target bouffalolab-bl602dk-light-light-rpc-115200 build + ./scripts/build/build_examples.py --target bouffalolab-bl704ldk-light-light-rpc-115200 build + ./scripts/build/build_examples.py --target bouffalolab-bl706dk-light-light-rpc-115200 build ``` ### Build options with build_examples.py -- `-shell`, enable UART command line -- `-115200`, set UART baudrate to 115200 for log and command line +- `-wifi`, to specify that connectivity Wi-Fi is enabled for Matter + application. + + - BL602 uses `-wifi` by default + - BL702 needs specify to use BL706 + BL602 for Wi-Fi connectivity. + +- `-thread`, to specify that connectivity Thread is enabled for Matter + application. + + - BL70X uses `-thread` by default. + +- `-ethernet`, to specify that connectivity Ethernet is enabled for Matte + application. + + - BL706 needs specify to use Ethernet connectivity. + +- `-easyflash`, to specify that `easyflash` is used for flash storage access. +- `-mfd`, enable Matter factory data feature, which load factory data from + `MFD` partition +- `-shell`, enable command line - `-rpc`, enable Pigweed RPC feature +- `-115200`, set UART baudrate to 115200 for log and command line - `-cdc`, enable USB CDC feature, only support for BL706, and can't work with Ethernet Board - `-resetCnt`, enable feature to do factory reset when continues power cycle is greater than 3 -- `-mfd`, enable Matter factory data feature, which load factory data from - `DTS` region and `MFD` partition - - Please contact to `Bouffalo Lab` for Matter factory data support. -- `-mfdtest`, enable Matter factory data module, but only load factory data - from `FactoryDataProvider.cpp` file. -- `-wifi`, to specify that connectivity Wi-Fi is enabled for Matter - application. -- `-ethernet`, to specify that connectivity Ethernet is enabled for Matter - application. -- `-thread`, to specify that connectivity Thread is enabled for Matter - application. - `-mot`, to specify to use openthread stack under `third_party/openthread/repo` - Without `-mot` specified, Matter Thread will use openthread stack under @@ -147,12 +157,6 @@ The following steps take examples for `BL602-IoT-Matter-V1` BL602 board, - `chip-bl702-lighting-example.flash.py` for BL702 - `chip-bl702l-lighting-example.flash.py` for BL702L - > Note 1, `*.flash.py` should be ran under Matter build environment; if - > python module `bflb_iot_tool` is not found, please try to do - > `source scripts/bootstrap.sh` or install as - > `pip3 install bflb-iot-tool`.
Note 2, different build options will - > generate different output folder. - Download operation steps as below, please check `help` option of script for more detail. @@ -167,45 +171,25 @@ The following steps take examples for `BL602-IoT-Matter-V1` BL602 board, - Type following command for image download. Please set serial port accordingly, here we use /dev/ttyACM0 as a serial port example. - - `bl602-iot-matter-v1`, `bl706dk` and `bl704ldk` without additional - build options - - ```shell - ./out/bouffalolab-bl602-iot-matter-v1-light/chip-bl602-lighting-example.flash.py --port /dev/ttyACM0 - ./out/bouffalolab-bl706dk-light/chip-bl702-lighting-example.flash.py --port /dev/ttyACM0 - ./out/bouffalolab-bl704ldk-light/chip-bl702l-lighting-example.flash.py --port /dev/ttyACM0 - ``` + - `BL602DK`, `BL704LDK` and `BL706DK`. - - `bl706dk` with 115200 baudrate setting ```shell - ./out/bouffalolab-bl706dk-light-115200/chip-bl702-lighting-example.flash.py --port /dev/ttyACM0 + ./out/bouffalolab-bl602dk-light/chip-bl602-lighting-example.flash.py --port /dev/ttyACM0 + ./out/bouffalolab-bl704ldk-light/chip-bl702l-lighting-example.flash.py --port /dev/ttyACM0 + ./out/bouffalolab-bl706dk-light/chip-bl702-lighting-example.flash.py --port /dev/ttyACM0 ``` - - To wipe out flash and download image, please append `--erase` to the - above command. + - To wipe out flash and download image, please append `--erase` + option. Take BL602DK as example. ```shell - ./out/bouffalolab-bl602-iot-matter-v1-light/chip-bl602-lighting-example.flash.py --port /dev/ttyACM0 --erase - ./out/bouffalolab-bl706dk-light-115200/chip-bl702-lighting-example.flash.py --port /dev/ttyACM0 --erase - ./out/bouffalolab-bl704ldk-light/chip-bl702l-lighting-example.flash.py --port /dev/ttyACM0 --erase + ./out/bouffalolab-bl602dk-light/chip-bl602-lighting-example.flash.py --port /dev/ttyACM0 --erase ``` > Note, better to append --erase option to download image for BL602 > develop board at first time. -- Using `Bouffalo Lab` GUI flash tool `BLDevCube`, please download on - [this page](https://dev.bouffalolab.com/download). - - Hold BOOT pin and reset chip, put the board in download mode. - - Select `DTS` file; - - Select Partition Table under - `examples/platform/bouffalolab/bl602/flash_config` or - `examples/platform/bouffalolab/bl702/flash_config` - - Select Firmware Bin; - - Select Chip Erase if need; - - Choose Target COM port. - - Then click Create & Download. - ## Run the example - You can open the serial console. For example, if the device is at @@ -249,13 +233,13 @@ sudo ot-ctl dataset active -x - Enter build out folder of chip-tool and running the following command to do BLE commission - - BL602 + - Wi-Fi ```shell ./chip-tool pairing ble-wifi 20202021 3840 ``` - - BL706 + - Thread ```shell ./chip-tool pairing ble-thread hex: 20202021 3840 @@ -308,34 +292,26 @@ After successful commissioning, cluster commands available to control the board. Please take [guide](../../ota-provider-app/linux/README.md) for more detail on ota-provider-app build and usage. -### Create the Matter OTA image with Bouffalolab OTA `bin.xz.hash` format image - -- `Bouffalo Lab` OTA `bin.xz.hash` format image +### Create the Matter OTA image - - Build `Bouffalo Lab` OTA image as following execution using python - script `*.flash.py` under firmware build out folder, - `shell ./.flash.py --build` After script executed, - a folder `ota_images` and an image `FW_OTA.bin.xz.hash` will be - generated. `FW_OTA.bin.xz.hash` is compressed with hash verification for - build out firmware. +`Bouffalo Lab` Matter OTA image contains two parts: - - `bin.xz.hash` image +- `Bouffalo Lab` OTA bootable image: + - Add boot parameters, signature/encryption if specified + - And specify whether image has be compressed. +- Add Matter recognition header by + [ota_image_tool.py](../../../docs/guides/openthread_border_router_pi.md). - After compile done, the build script will call - `.flash.py` to generate `Bouffalo Lab` OTA format - image as above, and put it under out folder with name likes - `.bin.xz.hash` +Script `*.flash.py` builds `Bouffalo Lab` bootable image and call +[ota_image_tool.py](../../../docs/guides/openthread_border_router_pi.md) to add +Matter recognition header. Take `BL602DK` as example. -* Build Matter `*.ota` OTA image with `Bouffalo Lab` OTA image under - **connectedhomeip** repo folder - - ```shell - $ ./src/app/ota_image_tool.py create -v 0xFFF1 -p 0x8005 -vn 10 -vs "1.0" -da sha256 lighting-app.ota - - ``` +```shell +./out/bouffalolab-bl602dk-light/chip-bl602-lighting-example.flash.py --build-ota --vendor-id --product-id --version --version-str --digest-algorithm +``` - > lighting-app.ota should have greater software version which is defined by - > macro `CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION` in CHIPProjectConfig.h +> lighting-app.ota should have greater software version which is defined by +> macro `CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION` in CHIPProjectConfig.h ### Start ota-provider-app diff --git a/examples/lighting-app/bouffalolab/bl602/BUILD.gn b/examples/lighting-app/bouffalolab/bl602/BUILD.gn index f03a18c004a131..6fc584fa8eeade 100644 --- a/examples/lighting-app/bouffalolab/bl602/BUILD.gn +++ b/examples/lighting-app/bouffalolab/bl602/BUILD.gn @@ -110,9 +110,6 @@ bouffalolab_executable("lighting_app") { defines += [ "CONF_ENABLE_FRAME_PTR=${enable_debug_frame_ptr}" ] defines += [ "CONFIG_BOUFFALOLAB_FACTORY_DATA_ENABLE=${chip_enable_factory_data}" ] - defines += [ - "CONFIG_BOUFFALOLAB_FACTORY_DATA_TEST=${chip_enable_factory_data_test}", - ] bl_plat_name = "bl602" sources = [ diff --git a/examples/lighting-app/bouffalolab/bl602/args.gni b/examples/lighting-app/bouffalolab/bl602/args.gni index 4c69abdaa1259f..0fcb5aac2edc9b 100644 --- a/examples/lighting-app/bouffalolab/bl602/args.gni +++ b/examples/lighting-app/bouffalolab/bl602/args.gni @@ -25,6 +25,8 @@ pw_rpc_CONFIG = "$dir_pw_rpc:disable_global_mutex" chip_detail_logging = false +#is_debug = false + pw_build_LINK_DEPS = [ "$dir_pw_assert:impl", "$dir_pw_log:impl", diff --git a/examples/lighting-app/bouffalolab/bl702/BUILD.gn b/examples/lighting-app/bouffalolab/bl702/BUILD.gn index ac3a5e5f7e66af..209e473e693869 100644 --- a/examples/lighting-app/bouffalolab/bl702/BUILD.gn +++ b/examples/lighting-app/bouffalolab/bl702/BUILD.gn @@ -138,9 +138,6 @@ bouffalolab_executable("lighting_app") { defines += [ "CONF_ENABLE_FRAME_PTR=${enable_debug_frame_ptr}" ] defines += [ "CONFIG_BOUFFALOLAB_FACTORY_DATA_ENABLE=${chip_enable_factory_data}" ] - defines += [ - "CONFIG_BOUFFALOLAB_FACTORY_DATA_TEST=${chip_enable_factory_data_test}", - ] if (chip_config_network_layer_ble) { defines += [ "CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE=1" ] } diff --git a/examples/lighting-app/bouffalolab/bl702/args.gni b/examples/lighting-app/bouffalolab/bl702/args.gni index e35ae89f6a9426..e06c706903b935 100644 --- a/examples/lighting-app/bouffalolab/bl702/args.gni +++ b/examples/lighting-app/bouffalolab/bl702/args.gni @@ -25,6 +25,9 @@ pw_rpc_CONFIG = "$dir_pw_rpc:disable_global_mutex" chip_detail_logging = false +# use -Os instead of -Og +is_debug = false + pw_build_LINK_DEPS = [ "$dir_pw_assert:impl", "$dir_pw_log:impl", diff --git a/examples/lighting-app/bouffalolab/bl702l/BUILD.gn b/examples/lighting-app/bouffalolab/bl702l/BUILD.gn index f7ca4144bb8a04..50d2bd417a2ba4 100644 --- a/examples/lighting-app/bouffalolab/bl702l/BUILD.gn +++ b/examples/lighting-app/bouffalolab/bl702l/BUILD.gn @@ -115,9 +115,6 @@ bouffalolab_executable("lighting_app") { defines += [ "CONF_ENABLE_FRAME_PTR=${enable_debug_frame_ptr}" ] defines += [ "CONFIG_BOUFFALOLAB_FACTORY_DATA_ENABLE=${chip_enable_factory_data}" ] - defines += [ - "CONFIG_BOUFFALOLAB_FACTORY_DATA_TEST=${chip_enable_factory_data_test}", - ] if (chip_config_network_layer_ble) { defines += [ "CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE=1" ] } diff --git a/examples/lighting-app/bouffalolab/bl702l/args.gni b/examples/lighting-app/bouffalolab/bl702l/args.gni index f2eb36a8b29f73..3120af1cce60f6 100644 --- a/examples/lighting-app/bouffalolab/bl702l/args.gni +++ b/examples/lighting-app/bouffalolab/bl702l/args.gni @@ -24,6 +24,7 @@ pw_assert_BACKEND = "$dir_pw_assert_log" pw_rpc_CONFIG = "$dir_pw_rpc:disable_global_mutex" chip_detail_logging = false +is_debug = false pw_build_LINK_DEPS = [ "$dir_pw_assert:impl", diff --git a/examples/lighting-app/bouffalolab/common/AppTask.cpp b/examples/lighting-app/bouffalolab/common/AppTask.cpp index fafc9943e24890..7e9b4920d03783 100644 --- a/examples/lighting-app/bouffalolab/common/AppTask.cpp +++ b/examples/lighting-app/bouffalolab/common/AppTask.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #if HEAP_MONITORING @@ -133,7 +134,8 @@ void AppTask::PostEvent(app_event_t event) void AppTask::AppTaskMain(void * pvParameter) { app_event_t appEvent; - bool onoff = false; + bool onoff = false; + uint64_t currentHeapFree = 0; #if !(CHIP_DEVICE_LAYER_TARGET_BL702 && CHIP_DEVICE_CONFIG_ENABLE_ETHERNET) sLightLED.Init(); @@ -184,7 +186,8 @@ void AppTask::AppTaskMain(void * pvParameter) vTaskSuspend(NULL); - ChipLogProgress(NotSpecified, "App Task started, with SRAM heap %d left\r\n", xPortGetFreeHeapSize()); + DiagnosticDataProviderImpl::GetDefaultInstance().GetCurrentHeapFree(currentHeapFree); + ChipLogProgress(NotSpecified, "App Task started, with SRAM heap %lld left\r\n", currentHeapFree); while (true) { diff --git a/examples/lighting-app/infineon/psoc6/README.md b/examples/lighting-app/infineon/psoc6/README.md index e5b5854fc275e5..773a05af1f3899 100644 --- a/examples/lighting-app/infineon/psoc6/README.md +++ b/examples/lighting-app/infineon/psoc6/README.md @@ -31,10 +31,11 @@ will then join the network. ## Building -- [Modustoolbox Software](https://www.cypress.com/products/modustoolbox) +- Download and install + [Modustoolbox Software v3.2](https://www.infineon.com/modustoolbox) - Refer to `integrations/docker/images/chip-build-infineon/Dockerfile` or - `scripts/examples/gn_psoc6_example.sh` for downloading the Software and + Refer to `integrations/docker/images/stage-2/chip-build-infineon/Dockerfile` + or `scripts/examples/gn_psoc6_example.sh` for downloading the Software and related tools. - Install some additional tools (likely already present for Matter @@ -43,7 +44,7 @@ will then join the network. python3-pip - Supported hardware: - [CY8CKIT-062S2-43012](https://www.cypress.com/CY8CKIT-062S2-43012) + [CY8CKIT-062S2-43012](https://www.infineon.com/CY8CKIT-062S2-43012) * Build the example application: @@ -59,11 +60,12 @@ will then join the network. - Put CY8CKIT-062S2-43012 board on KitProg3 CMSIS-DAP Mode by pressing the `MODE SELECT` button. `KITPROG3 STATUS` LED is ON confirms board is in - proper mode. + proper mode. (Modustoolbox Software needs to be installed) - On the command line: $ cd ~/connectedhomeip + $ export CY_TOOLS_PATHS=/tools_3.2 $ python3 out/infineon-psoc6-light/chip-psoc6-lighting-example.flash.py ## Commissioning and cluster control diff --git a/examples/lighting-app/lighting-common/lighting-app.matter b/examples/lighting-app/lighting-common/lighting-app.matter index 8bdaaedaa68ce6..5ddd7071470692 100644 --- a/examples/lighting-app/lighting-common/lighting-app.matter +++ b/examples/lighting-app/lighting-common/lighting-app.matter @@ -3193,7 +3193,7 @@ endpoint 1 { ram attribute occupancy; ram attribute occupancySensorType; ram attribute occupancySensorTypeBitmap; - ram attribute featureMap default = 0; + callback attribute featureMap; ram attribute clusterRevision default = 5; } } diff --git a/examples/lighting-app/nxp/common/AppTask.cpp b/examples/lighting-app/nxp/common/AppTask.cpp new file mode 100644 index 00000000000000..6bca4669760c2a --- /dev/null +++ b/examples/lighting-app/nxp/common/AppTask.cpp @@ -0,0 +1,37 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "AppTask.h" + +#include + +void LightingApp::AppTask::PreInitMatterStack() +{ + ChipLogProgress(DeviceLayer, "Welcome to NXP Lighting Demo App"); +} + +LightingApp::AppTask & LightingApp::AppTask::GetDefaultInstance() +{ + static LightingApp::AppTask sAppTask; + return sAppTask; +} + +chip::NXP::App::AppTaskBase & chip::NXP::App::GetAppTask() +{ + return LightingApp::AppTask::GetDefaultInstance(); +} diff --git a/examples/lighting-app/nxp/k32w/k32w1/main/ZclCallbacks.cpp b/examples/lighting-app/nxp/common/DeviceCallbacks.cpp similarity index 51% rename from examples/lighting-app/nxp/k32w/k32w1/main/ZclCallbacks.cpp rename to examples/lighting-app/nxp/common/DeviceCallbacks.cpp index 97a3fb9aa72a98..140cdffb9febe2 100644 --- a/examples/lighting-app/nxp/k32w/k32w1/main/ZclCallbacks.cpp +++ b/examples/lighting-app/nxp/common/DeviceCallbacks.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2021 Project CHIP Authors + * Copyright (c) 2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,59 +18,72 @@ #include -#include "AppTask.h" -#include "LightingManager.h" +#include "DeviceCallbacks.h" +#if CONFIG_ENABLE_FEEDBACK +#include "UserInterfaceFeedback.h" +#endif #include #include -#include -#include using namespace ::chip; using namespace ::chip::app::Clusters; -void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & path, uint8_t type, uint16_t size, uint8_t * value) +void LightingApp::DeviceCallbacks::PostAttributeChangeCallback(chip::EndpointId endpoint, chip::ClusterId clusterId, + chip::AttributeId attributeId, uint8_t type, uint16_t size, + uint8_t * value) { - if (path.mClusterId == OnOff::Id) + if (clusterId == OnOff::Id) { - if (path.mAttributeId != OnOff::Attributes::OnOff::Id) + if (attributeId != OnOff::Attributes::OnOff::Id) { - ChipLogProgress(Zcl, "Unknown attribute ID: " ChipLogFormatMEI, ChipLogValueMEI(path.mAttributeId)); + ChipLogProgress(Zcl, "Unknown attribute ID: " ChipLogFormatMEI, ChipLogValueMEI(attributeId)); return; } - - LightingMgr().InitiateAction(0, *value ? LightingManager::TURNON_ACTION : LightingManager::TURNOFF_ACTION, *value); +#if CONFIG_ENABLE_FEEDBACK + FeedbackMgr().RestoreState(); +#endif } - else if (path.mClusterId == LevelControl::Id) + else if (clusterId == LevelControl::Id) { - if (path.mAttributeId != LevelControl::Attributes::CurrentLevel::Id) + if (attributeId != LevelControl::Attributes::CurrentLevel::Id) { - ChipLogProgress(Zcl, "Unknown attribute ID: " ChipLogFormatMEI, ChipLogValueMEI(path.mAttributeId)); + ChipLogProgress(Zcl, "Unknown attribute ID: " ChipLogFormatMEI, ChipLogValueMEI(attributeId)); return; } - +#if LIGHTING_MANAGER_ENABLE_DIMMABLE_LED if (*value > 1 && *value < 254) { ChipLogProgress(Zcl, "Setting value: %d", *value); - LightingMgr().InitiateAction(0, LightingManager::DIM_ACTION, *value); + // The cluster attribute value will be read in RestoreState and the proper action will be taken: e.g. ApplyDim. +#if CONFIG_ENABLE_FEEDBACK + FeedbackMgr().RestoreState(); +#endif } +#endif } - else if (path.mClusterId == ColorControl::Id) + else if (clusterId == ColorControl::Id) { ChipLogProgress(Zcl, "Color Control attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u", - ChipLogValueMEI(path.mAttributeId), type, *value, size); + ChipLogValueMEI(attributeId), type, *value, size); // WIP Apply attribute change to Light } - else if (path.mClusterId == OnOffSwitchConfiguration::Id) + else if (clusterId == OnOffSwitchConfiguration::Id) { ChipLogProgress(Zcl, "OnOff Switch Configuration attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u", - ChipLogValueMEI(path.mAttributeId), type, *value, size); + ChipLogValueMEI(attributeId), type, *value, size); // WIP Apply attribute change to Light } else { - ChipLogProgress(Zcl, "Unknown attribute ID: " ChipLogFormatMEI, ChipLogValueMEI(path.mAttributeId)); + ChipLogProgress(Zcl, "Unknown attribute ID: " ChipLogFormatMEI, ChipLogValueMEI(attributeId)); } } + +chip::DeviceManager::CHIPDeviceManagerCallbacks & chip::NXP::App::GetDeviceCallbacks() +{ + static LightingApp::DeviceCallbacks sDeviceCallbacks; + return sDeviceCallbacks; +} diff --git a/src/platform/nxp/k32w/k32w1/DefaultTestEventTriggerDelegate.h b/examples/lighting-app/nxp/common/include/AppEvent.h similarity index 60% rename from src/platform/nxp/k32w/k32w1/DefaultTestEventTriggerDelegate.h rename to examples/lighting-app/nxp/common/include/AppEvent.h index 0bfd4c5b0fa725..b292afaddf8c18 100644 --- a/src/platform/nxp/k32w/k32w1/DefaultTestEventTriggerDelegate.h +++ b/examples/lighting-app/nxp/common/include/AppEvent.h @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2022 Project CHIP Authors + * Copyright (c) 2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,19 +18,10 @@ #pragma once -#include +struct AppEvent; +typedef void (*EventHandler)(const AppEvent &); -namespace chip { - -class DefaultTestEventTriggerDelegate : public TestEventTriggerDelegate +struct AppEvent { -public: - explicit DefaultTestEventTriggerDelegate(const ByteSpan & enableKey) : mEnableKey(enableKey) {} - - bool DoesEnableKeyMatch(const ByteSpan & enableKey) const override; - -private: - ByteSpan mEnableKey; + EventHandler Handler; }; - -} // namespace chip diff --git a/examples/lighting-app/nxp/common/include/AppTask.h b/examples/lighting-app/nxp/common/include/AppTask.h new file mode 100644 index 00000000000000..9f73d340f35957 --- /dev/null +++ b/examples/lighting-app/nxp/common/include/AppTask.h @@ -0,0 +1,46 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "AppConfig.h" +#include "AppTaskFreeRTOS.h" + +#include + +namespace LightingApp { + +class AppTask : public chip::NXP::App::AppTaskFreeRTOS +{ +public: + // AppTaskFreeRTOS virtual methods + void PreInitMatterStack() override; + + // This returns an instance of this class. + static AppTask & GetDefaultInstance(); +}; + +} // namespace LightingApp + +/** + * Returns the application-specific implementation of the AppTaskBase object. + * + * Applications can use this to gain access to features of the AppTaskBase + * that are specific to the selected application. + */ +chip::NXP::App::AppTaskBase & GetAppTask(); diff --git a/examples/lighting-app/nxp/common/include/DeviceCallbacks.h b/examples/lighting-app/nxp/common/include/DeviceCallbacks.h new file mode 100644 index 00000000000000..555021b36ebb16 --- /dev/null +++ b/examples/lighting-app/nxp/common/include/DeviceCallbacks.h @@ -0,0 +1,51 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file DeviceCallbacks.h + * + * Lighting app implementation for the DeviceManager callbacks for all applications + * + **/ + +#pragma once + +#include "CHIPDeviceManager.h" +#include "CommonDeviceCallbacks.h" + +namespace LightingApp { + +class DeviceCallbacks : public chip::NXP::App::CommonDeviceCallbacks +{ +public: + void PostAttributeChangeCallback(chip::EndpointId endpoint, chip::ClusterId clusterId, chip::AttributeId attributeId, + uint8_t type, uint16_t size, uint8_t * value) override; +}; + +} // namespace LightingApp + +namespace chip::NXP::App { +/** + * Returns the application-specific implementation of the CommonDeviceCallbacks object. + * + * Applications can use this to gain access to features of the CommonDeviceCallbacks + * that are specific to the selected application. + */ +chip::DeviceManager::CHIPDeviceManagerCallbacks & GetDeviceCallbacks(); + +} // namespace chip::NXP::App diff --git a/examples/lighting-app/nxp/common/main.cpp b/examples/lighting-app/nxp/common/main.cpp new file mode 100644 index 00000000000000..d9672b5402c867 --- /dev/null +++ b/examples/lighting-app/nxp/common/main.cpp @@ -0,0 +1,39 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "AppTask.h" +#include "FreeRTOS.h" + +#if configAPPLICATION_ALLOCATED_HEAP +uint8_t __attribute__((section(".heap"))) ucHeap[configTOTAL_HEAP_SIZE]; +#endif + +#if FSL_OSA_MAIN_FUNC_ENABLE +extern "C" void main_task(void const * argument) +{ + chip::DeviceLayer::PlatformMgrImpl().HardwareInit(); + chip::NXP::App::GetAppTask().Start(); +} +#else +extern "C" int main(int argc, char * argv[]) +{ + chip::DeviceLayer::PlatformMgrImpl().HardwareInit(); + chip::NXP::App::GetAppTask().Start(); + vTaskStartScheduler(); +} +#endif diff --git a/examples/lighting-app/nxp/k32w/k32w1/BUILD.gn b/examples/lighting-app/nxp/k32w/k32w1/BUILD.gn deleted file mode 100644 index dd40445e0e7b79..00000000000000 --- a/examples/lighting-app/nxp/k32w/k32w1/BUILD.gn +++ /dev/null @@ -1,196 +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. - -import("//build_overrides/chip.gni") -import("//build_overrides/nxp_sdk.gni") -import("//build_overrides/openthread.gni") -import("${nxp_sdk_build_root}/nxp_sdk.gni") - -import("${nxp_sdk_build_root}/${nxp_sdk_name}/nxp_executable.gni") - -import("${nxp_sdk_build_root}/${nxp_sdk_name}/${nxp_sdk_name}.gni") - -import("${chip_root}/src/crypto/crypto.gni") -import("${chip_root}/src/lib/core/core.gni") -import("${chip_root}/src/platform/device.gni") -import("${chip_root}/src/platform/nxp/${nxp_platform}/args.gni") - -import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni") - -if (chip_enable_pw_rpc) { - import("//build_overrides/pigweed.gni") - import("$dir_pw_build/target_types.gni") - import("${chip_root}/examples/platform/nxp/pw_rpc_server.gni") -} - -declare_args() { - chip_software_version = 0 - - # Setup discriminator as argument - setup_discriminator = 3840 -} - -assert(current_os == "freertos") - -k32w1_platform_dir = "${chip_root}/examples/platform/nxp/k32w/k32w1" -k32w1_sdk_root = getenv("NXP_K32W1_SDK_ROOT") - -k32w1_sdk("sdk") { - sources = [ - "${k32w1_platform_dir}/app/project_include/OpenThreadConfig.h", - "include/CHIPProjectConfig.h", - "include/FreeRTOSConfig.h", - "main/include/app_config.h", - ] - - public_deps = - [ "${chip_root}/third_party/openthread/platforms:libopenthread-platform" ] - - include_dirs = [ - "main/include", - "main", - "include", - "${k32w1_platform_dir}/app/project_include", - "${k32w1_platform_dir}/app/support", - "${k32w1_platform_dir}/app/ldscripts", - "${k32w1_platform_dir}/util/include", - ] - - defines = [] - if (is_debug) { - defines += [ "BUILD_RELEASE=0" ] - } else { - defines += [ "BUILD_RELEASE=1" ] - } - - if (chip_software_version != 0) { - defines += [ - "CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION=${chip_software_version}", - ] - } - - if (chip_enable_pw_rpc) { - defines += [ - "PW_RPC_ENABLED", - "STREAMER_UART_FLUSH_DELAY_MS=0", - "STREAMER_UART_SERIAL_MANAGER_RING_BUFFER_SIZE=512", - "BOARD_APP_UART_CLK_FREQ=96000000", - ] - } - - defines += [ - "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR=${setup_discriminator}", - ] -} - -k32w1_executable("light_app") { - output_name = "chip-k32w1-light-example" - - sources = [] - deps = [] - defines = [] - - if (chip_config_dimmable_led) { - defines += [ "CHIP_CONFIG_ENABLE_DIMMABLE_LED = 1" ] - } else { - defines += [ "CHIP_CONFIG_ENABLE_DIMMABLE_LED = 0" ] - } - - if (chip_enable_pw_rpc) { - forward_variables_from(pw_rpc_server, "*") - } else { - cflags = [ "-Wconversion" ] - } - - sources += [ - "${k32w1_platform_dir}/util/LEDWidget.cpp", - "${k32w1_platform_dir}/util/include/LEDWidget.h", - "main/AppTask.cpp", - "main/LightingManager.cpp", - "main/ZclCallbacks.cpp", - "main/include/AppEvent.h", - "main/include/AppTask.h", - "main/include/LightingManager.h", - "main/main.cpp", - ] - - if (chip_config_dimmable_led) { - sources += [ - "${k32w1_platform_dir}/util/LED_Dimmer.cpp", - "${k32w1_platform_dir}/util/include/LED_Dimmer.h", - ] - deps += [ "${chip_root}/examples/lighting-app/lighting-common/" ] - } else { - deps += [ "${chip_root}/examples/lighting-app/nxp/zap/" ] - } - - deps += [ - ":sdk", - "${chip_root}/examples/common/QRCode", - "${chip_root}/examples/providers:device_info_provider", - "${chip_root}/src/lib", - "${chip_root}/src/platform:syscalls_stub", - "${chip_root}/src/platform/logging:default", - "${chip_root}/third_party/mbedtls:mbedtls", - "${k32w1_platform_dir}/app/support:freertos_mbedtls_utils", - ] - - if (chip_openthread_ftd) { - deps += [ - "${openthread_root}:libopenthread-cli-ftd", - "${openthread_root}:libopenthread-ftd", - ] - } else { - deps += [ - "${openthread_root}:libopenthread-cli-mtd", - "${openthread_root}:libopenthread-mtd", - ] - } - - if (use_smu2_static) { - ldscript = "${k32w1_platform_dir}/app/ldscripts/k32w1_app.ld" - base_ldscript_dir = "${k32w1_sdk_root}/middleware/wireless/framework/Common/devices/kw45_k32w1/gcc" - } else { - ldscript = "${k32w1_sdk_root}/middleware/wireless/framework/Common/devices/kw45_k32w1/gcc/connectivity.ld" - } - - inputs = [ ldscript ] - - ldflags = [ - "-Wl,--defsym=__heap_size__=0", - "-Wl,--defsym=__stack_size__=0x480", - "-Wl,--defsym=gUseFactoryData_d=1", - "-Wl,-print-memory-usage", - "-Wl,--no-warn-rwx-segments", - "-T" + rebase_path(ldscript, root_build_dir), - ] - - if (chip_with_factory_data == 1) { - ldflags += [ "-Wl,--defsym=gUseFactoryData_d=1" ] - } - - if (use_smu2_static) { - ldflags += [ "-L" + rebase_path(base_ldscript_dir, root_build_dir) ] - } - - output_dir = root_out_dir -} - -group("k32w1") { - deps = [ ":light_app" ] -} - -group("default") { - deps = [ ":k32w1" ] -} diff --git a/examples/lighting-app/nxp/k32w/k32w1/build_overrides b/examples/lighting-app/nxp/k32w/k32w1/build_overrides deleted file mode 120000 index ad07557834803a..00000000000000 --- a/examples/lighting-app/nxp/k32w/k32w1/build_overrides +++ /dev/null @@ -1 +0,0 @@ -../../../../build_overrides/ \ No newline at end of file diff --git a/examples/lighting-app/nxp/k32w/k32w1/include/FreeRTOSConfig.h b/examples/lighting-app/nxp/k32w/k32w1/include/FreeRTOSConfig.h deleted file mode 100644 index 95279e6337a7f7..00000000000000 --- a/examples/lighting-app/nxp/k32w/k32w1/include/FreeRTOSConfig.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * FreeRTOS Kernel V10.2.0 - * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos - * - * 1 tab == 4 spaces! - */ - -#pragma once - -/*----------------------------------------------------------- - * Application specific definitions. - * - * These definitions should be adjusted for your particular hardware and - * application requirements. - * - * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE - * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. - * - * See http://www.freertos.org/a00110.html. - *----------------------------------------------------------*/ - -#define configUSE_PREEMPTION 1 -#define configUSE_TICKLESS_IDLE 0 -/* Ensure stdint is only used by the compiler, and not the assembler. */ -#if defined(__ICCARM__) || defined(__ARMCC_VERSION) || defined(__GNUC__) -#include -extern uint32_t SystemCoreClock; -#endif -#define configCPU_CLOCK_HZ (SystemCoreClock) -#define configTICK_RATE_HZ ((TickType_t) 100) -#define configMAX_PRIORITIES (8) -// idle task stack size needs to be increased for OTA EEPROM processing -#define configMINIMAL_STACK_SIZE ((unsigned short) 450) -#define configMAX_TASK_NAME_LEN 20 -#define configUSE_16_BIT_TICKS 0 -#define configIDLE_SHOULD_YIELD 1 -#define configUSE_TASK_NOTIFICATIONS 1 -#define configUSE_MUTEXES 1 -#define configUSE_RECURSIVE_MUTEXES 1 -#define configUSE_COUNTING_SEMAPHORES 1 -#define configUSE_ALTERNATIVE_API 0 /* Deprecated! */ -#define configQUEUE_REGISTRY_SIZE 8 -#define configUSE_QUEUE_SETS 0 -#define configUSE_TIME_SLICING 0 -#define configUSE_NEWLIB_REENTRANT 0 -#define configENABLE_BACKWARD_COMPATIBILITY 1 -#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5 - -/* Tasks.c additions (e.g. Thread Aware Debug capability) */ -#define configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H 1 - -/* Used memory allocation (heap_x.c) */ -#define configFRTOS_MEMORY_SCHEME 4 - -/* Memory allocation related definitions. */ -#define configSUPPORT_STATIC_ALLOCATION 0 -#define configSUPPORT_DYNAMIC_ALLOCATION 1 -#define configTOTAL_HEAP_SIZE ((size_t) (gTotalHeapSize_c)) -#define configAPPLICATION_ALLOCATED_HEAP 1 - -/* Hook function related definitions. */ -#ifndef configUSE_IDLE_HOOK -#define configUSE_IDLE_HOOK 1 -#endif -#define configUSE_TICK_HOOK 0 -#define configCHECK_FOR_STACK_OVERFLOW 0 -#ifndef configUSE_MALLOC_FAILED_HOOK -#define configUSE_MALLOC_FAILED_HOOK 0 -#endif -#define configUSE_DAEMON_TASK_STARTUP_HOOK 0 - -/* Run time and task stats gathering related definitions. */ -#define configGENERATE_RUN_TIME_STATS 0 -#define configUSE_TRACE_FACILITY 1 -#define configUSE_STATS_FORMATTING_FUNCTIONS 0 - -/* Task aware debugging. */ -#define configRECORD_STACK_HIGH_ADDRESS 1 - -/* Co-routine related definitions. */ -#define configUSE_CO_ROUTINES 0 -#define configMAX_CO_ROUTINE_PRIORITIES 2 - -/* Software timer related definitions. */ -#define configUSE_TIMERS 1 -#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1) -#define configTIMER_QUEUE_LENGTH 10 -#define configTIMER_TASK_STACK_DEPTH (360) - -/* Define to trap errors during development. */ -#define configASSERT(x) \ - if ((x) == 0) \ - { \ - taskDISABLE_INTERRUPTS(); \ - for (;;) \ - ; \ - } - -/* Optional functions - most linkers will remove unused functions anyway. */ -#define INCLUDE_vTaskPrioritySet 1 -#define INCLUDE_uxTaskPriorityGet 1 -#define INCLUDE_vTaskDelete 1 -#define INCLUDE_vTaskSuspend 1 -#define INCLUDE_xResumeFromISR 1 -#define INCLUDE_vTaskDelayUntil 1 -#define INCLUDE_vTaskDelay 1 -#define INCLUDE_xTaskGetSchedulerState 1 -#define INCLUDE_xTaskGetCurrentTaskHandle 1 -#define INCLUDE_uxTaskGetStackHighWaterMark 1 -#define INCLUDE_xTaskGetIdleTaskHandle 0 -#define INCLUDE_eTaskGetState 0 -#define INCLUDE_xEventGroupSetBitFromISR 1 -#define INCLUDE_xTimerPendFunctionCall 1 -#define INCLUDE_xTaskAbortDelay 0 -#define INCLUDE_xTaskGetHandle 0 -#define INCLUDE_xTaskResumeFromISR 1 -#define INCLUDE_xQueueGetMutexHolder 1 - -/* Interrupt nesting behaviour configuration. Cortex-M specific. */ -#ifdef __NVIC_PRIO_BITS -/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */ -#define configPRIO_BITS __NVIC_PRIO_BITS -#else -#define configPRIO_BITS 3 -#endif - -/* The lowest interrupt priority that can be used in a call to a "set priority" -function. */ -#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x7 - -/* The highest interrupt priority that can be used by any interrupt service -routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL -INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER -PRIORITY THAN THIS! (higher priorities are lower numeric values. */ -#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 1 - -/* Interrupt priorities used by the kernel port layer itself. These are generic -to all Cortex-M ports, and do not rely on any particular library functions. */ -#define configKERNEL_INTERRUPT_PRIORITY (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS)) -/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! -See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ -#define configMAX_SYSCALL_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS)) - -#ifndef configENABLE_FPU -#define configENABLE_FPU 0 -#endif -#ifndef configENABLE_MPU -#define configENABLE_MPU 0 -#endif -#ifndef configENABLE_TRUSTZONE -#define configENABLE_TRUSTZONE 0 -#endif -#ifndef configRUN_FREERTOS_SECURE_ONLY -#define configRUN_FREERTOS_SECURE_ONLY 1 -#endif - -/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS -standard names. */ -#define vPortSVCHandler SVC_Handler -#define xPortPendSVHandler PendSV_Handler -#define xPortSysTickHandler SysTick_Handler diff --git a/examples/lighting-app/nxp/k32w/k32w1/main/AppTask.cpp b/examples/lighting-app/nxp/k32w/k32w1/main/AppTask.cpp deleted file mode 100644 index 4c1d0875470ee4..00000000000000 --- a/examples/lighting-app/nxp/k32w/k32w1/main/AppTask.cpp +++ /dev/null @@ -1,932 +0,0 @@ -/* - * - * Copyright (c) 2021 Project CHIP Authors - * Copyright (c) 2021 Google LLC. - * 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 "AppTask.h" -#include "AppEvent.h" -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(USE_SMU2_DYNAMIC) -#include -#endif - -#include -#include -#include -#include - -/* OTA related includes */ -#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR -#include "OtaSupport.h" -#include -#include -#include -#include -#include -#endif - -#include "K32W1PersistentStorageOpKeystore.h" - -#include "LEDWidget.h" -#include "app.h" -#include "app_config.h" -#include "fsl_component_button.h" -#include "fwk_platform.h" - -#if CHIP_CONFIG_ENABLE_DIMMABLE_LED -#include "LED_Dimmer.h" -#endif - -#define FACTORY_RESET_TRIGGER_TIMEOUT 6000 -#define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 3000 -#define APP_TASK_PRIORITY 2 -#define APP_EVENT_QUEUE_SIZE 10 - -TimerHandle_t sFunctionTimer; // FreeRTOS app sw timer. - -static QueueHandle_t sAppEventQueue; - -/* - * The status LED and the external flash CS pin are wired together. - * The OTA image writing may fail if used together. - */ -#ifndef CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR -static LEDWidget sStatusLED; -#endif -static LEDWidget sLightLED; - -static bool sIsThreadProvisioned = false; -#ifndef CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR -static bool sHaveFullConnectivity = false; -#endif -static bool sHaveBLEConnections = false; - -#if CHIP_DEVICE_CONFIG_THREAD_ENABLE_CLI -extern "C" void otPlatUartProcess(void); -#endif - -using namespace ::chip::Credentials; -using namespace ::chip::DeviceLayer; -using namespace chip; -using namespace chip::app; - -AppTask AppTask::sAppTask; -#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA -static AppTask::FactoryDataProvider sFactoryDataProvider; -#endif - -// This key is for testing/certification only and should not be used in production devices. -// For production devices this key must be provided from factory data. -uint8_t sTestEventTriggerEnableKey[TestEventTriggerDelegate::kEnableKeyLength] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, - 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; - -static Identify gIdentify = { chip::EndpointId{ 1 }, AppTask::OnIdentifyStart, AppTask::OnIdentifyStop, - Clusters::Identify::IdentifyTypeEnum::kVisibleIndicator, AppTask::OnTriggerEffect, - // Use invalid value for identifiers to enable TriggerEffect command - // to stop Identify command for each effect - Clusters::Identify::EffectIdentifierEnum::kUnknownEnumValue, - Clusters::Identify::EffectVariantEnum::kDefault }; - -/* OTA related variables */ -#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR -static DefaultOTARequestor gRequestorCore; -static DefaultOTARequestorStorage gRequestorStorage; -static DeviceLayer::DefaultOTARequestorDriver gRequestorUser; -static BDXDownloader gDownloader; - -constexpr uint16_t requestedOtaBlockSize = 1024; -#endif - -CHIP_ERROR AppTask::StartAppTask() -{ - CHIP_ERROR err = CHIP_NO_ERROR; - - sAppEventQueue = xQueueCreate(APP_EVENT_QUEUE_SIZE, sizeof(AppEvent)); - if (sAppEventQueue == NULL) - { - err = APP_ERROR_EVENT_QUEUE_FAILED; - K32W_LOG("Failed to allocate app event queue"); - assert(err == CHIP_NO_ERROR); - } - - return err; -} - -CHIP_ERROR AppTask::Init() -{ - CHIP_ERROR err = CHIP_NO_ERROR; - - PlatformMgr().AddEventHandler(MatterEventHandler, 0); - - // Init ZCL Data Model and start server - PlatformMgr().ScheduleWork(InitServer, 0); - -#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA - ReturnErrorOnFailure(sFactoryDataProvider.Init()); - SetDeviceInstanceInfoProvider(&sFactoryDataProvider); - SetDeviceAttestationCredentialsProvider(&sFactoryDataProvider); - SetCommissionableDataProvider(&sFactoryDataProvider); -#else - SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); -#endif // CONFIG_CHIP_LOAD_REAL_FACTORY_DATA - - // QR code will be used with CHIP Tool - AppTask::PrintOnboardingInfo(); - - if (LightingMgr().Init() != 0) - { - K32W_LOG("LightingMgr().Init() failed"); - assert(0); - } - - LightingMgr().SetCallbacks(ActionInitiated, ActionCompleted); - - /* start with all LEDS turnedd off */ -#ifndef CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR - sStatusLED.Init(SYSTEM_STATE_LED, false); -#endif - -#if CHIP_CONFIG_ENABLE_DIMMABLE_LED - init_dimmable(); -#else - sLightLED.Init(LIGHT_STATE_LED, false); -#endif - - UpdateDeviceState(); - - /* intialize the Keyboard and button press callback */ - BUTTON_InstallCallback((button_handle_t) g_buttonHandle[0], KBD_Callback, (void *) BLE_BUTTON); - BUTTON_InstallCallback((button_handle_t) g_buttonHandle[1], KBD_Callback, (void *) LIGHT_BUTTON); - - // Create FreeRTOS sw timer for Function Selection. - sFunctionTimer = xTimerCreate("FnTmr", // Just a text name, not used by the RTOS kernel - 1, // == default timer period (mS) - false, // no timer reload (==one-shot) - (void *) this, // init timer id = app task obj context - TimerEventHandler // timer callback handler - ); - - if (sFunctionTimer == NULL) - { - err = APP_ERROR_CREATE_TIMER_FAILED; - K32W_LOG("app_timer_create() failed"); - assert(err == CHIP_NO_ERROR); - } - - // Print the current software version - char currentSoftwareVer[ConfigurationManager::kMaxSoftwareVersionStringLength + 1] = { 0 }; - err = ConfigurationMgr().GetSoftwareVersionString(currentSoftwareVer, sizeof(currentSoftwareVer)); - if (err != CHIP_NO_ERROR) - { - K32W_LOG("Get version error"); - assert(err == CHIP_NO_ERROR); - } - - uint32_t currentVersion; - err = ConfigurationMgr().GetSoftwareVersion(currentVersion); - - K32W_LOG("Current Software Version: %s, %d", currentSoftwareVer, currentVersion); - - return err; -} - -void LockOpenThreadTask(void) -{ - chip::DeviceLayer::ThreadStackMgr().LockThreadStack(); -} - -void UnlockOpenThreadTask(void) -{ - chip::DeviceLayer::ThreadStackMgr().UnlockThreadStack(); -} - -void AppTask::InitServer(intptr_t arg) -{ - static chip::CommonCaseDeviceServerInitParams initParams; - (void) initParams.InitializeStaticResourcesBeforeServerInit(); - -#if CHIP_CRYPTO_PLATFORM - static chip::K32W1PersistentStorageOpKeystore sK32W1PersistentStorageOpKeystore; - VerifyOrDie((sK32W1PersistentStorageOpKeystore.Init(initParams.persistentStorageDelegate)) == CHIP_NO_ERROR); - initParams.operationalKeystore = &sK32W1PersistentStorageOpKeystore; -#endif - -#if defined(USE_SMU2_DYNAMIC) - VerifyOrDie(SMU2::Init() == CHIP_NO_ERROR); -#endif - - // Init ZCL Data Model and start server - static DefaultTestEventTriggerDelegate sTestEventTriggerDelegate{ ByteSpan(sTestEventTriggerEnableKey) }; - initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; - chip::Inet::EndPointStateOpenThread::OpenThreadEndpointInitParam nativeParams; - nativeParams.lockCb = LockOpenThreadTask; - nativeParams.unlockCb = UnlockOpenThreadTask; - nativeParams.openThreadInstancePtr = chip::DeviceLayer::ThreadStackMgrImpl().OTInstance(); - initParams.endpointNativeParams = static_cast(&nativeParams); - VerifyOrDie((chip::Server::GetInstance().Init(initParams)) == CHIP_NO_ERROR); -} - -void AppTask::PrintOnboardingInfo() -{ - chip::PayloadContents payload; - CHIP_ERROR err = GetPayloadContents(payload, chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE)); - if (err != CHIP_NO_ERROR) - { - ChipLogError(AppServer, "GetPayloadContents() failed: %" CHIP_ERROR_FORMAT, err.Format()); - } - payload.commissioningFlow = chip::CommissioningFlow::kUserActionRequired; - PrintOnboardingCodes(payload); -} - -#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR -void AppTask::InitOTA(intptr_t arg) -{ - // Initialize and interconnect the Requestor and Image Processor objects -- START - SetRequestorInstance(&gRequestorCore); - - gRequestorStorage.Init(chip::Server::GetInstance().GetPersistentStorage()); - gRequestorCore.Init(chip::Server::GetInstance(), gRequestorStorage, gRequestorUser, gDownloader); - gRequestorUser.SetMaxDownloadBlockSize(requestedOtaBlockSize); - auto & imageProcessor = OTAImageProcessorImpl::GetDefaultInstance(); - gRequestorUser.Init(&gRequestorCore, &imageProcessor); - CHIP_ERROR err = imageProcessor.Init(&gDownloader); - if (err != CHIP_NO_ERROR) - { - K32W_LOG("Image processor init failed"); - assert(err == CHIP_NO_ERROR); - } - - // Connect the gDownloader and Image Processor objects - gDownloader.SetImageProcessorDelegate(&imageProcessor); - // Initialize and interconnect the Requestor and Image Processor objects -- END -} -#endif - -void AppTask::AppTaskMain(void * pvParameter) -{ - AppEvent event; - - CHIP_ERROR err = sAppTask.Init(); - if (err != CHIP_NO_ERROR) - { - K32W_LOG("AppTask.Init() failed"); - assert(err == CHIP_NO_ERROR); - } - - while (true) - { - BaseType_t eventReceived = xQueueReceive(sAppEventQueue, &event, pdMS_TO_TICKS(10)); - while (eventReceived == pdTRUE) - { - sAppTask.DispatchEvent(&event); - eventReceived = xQueueReceive(sAppEventQueue, &event, 0); - } - - // Collect connectivity and configuration state from the CHIP stack. Because the - // CHIP event loop is being run in a separate task, the stack must be locked - // while these values are queried. However we use a non-blocking lock request - // (TryLockChipStack()) to avoid blocking other UI activities when the CHIP - // task is busy (e.g. with a long crypto operation). - if (PlatformMgr().TryLockChipStack()) - { -#if CHIP_DEVICE_CONFIG_THREAD_ENABLE_CLI - otPlatUartProcess(); -#endif - - sIsThreadProvisioned = ConnectivityMgr().IsThreadProvisioned(); - sHaveBLEConnections = (ConnectivityMgr().NumBLEConnections() != 0); - PlatformMgr().UnlockChipStack(); - } - - // Update the status LED if factory reset or identify process have not been initiated. - // - // If system has "full connectivity", keep the LED On constantly. - // - // If thread and service provisioned, but not attached to the thread network yet OR no - // connectivity to the service OR subscriptions are not fully established - // THEN blink the LED Off for a short period of time. - // - // If the system has ble connection(s) uptill the stage above, THEN blink the LEDs at an even - // rate of 100ms. - // - // Otherwise, blink the LED ON for a very short time. - if (sAppTask.mFunction != kFunction_FactoryReset) - { -#ifndef CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR - if (sHaveFullConnectivity) - { - sStatusLED.Set(true); - } - else if (sIsThreadProvisioned) - { - sStatusLED.Blink(950, 50); - } - else if (sHaveBLEConnections) - { - sStatusLED.Blink(100, 100); - } - else - { - sStatusLED.Blink(50, 950); - } -#endif - } - -#ifndef CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR - sStatusLED.Animate(); -#endif - sLightLED.Animate(); - } -} - -void AppTask::ButtonEventHandler(uint8_t pin_no, uint8_t button_action) -{ - if ((pin_no != RESET_BUTTON) && (pin_no != LIGHT_BUTTON) && (pin_no != SOFT_RESET_BUTTON) && (pin_no != BLE_BUTTON)) - { - return; - } - - AppEvent button_event; - button_event.Type = AppEvent::kEventType_Button; - button_event.ButtonEvent.PinNo = pin_no; - button_event.ButtonEvent.Action = button_action; - - if (pin_no == LIGHT_BUTTON) - { - button_event.Handler = LightActionEventHandler; - } - else if (pin_no == SOFT_RESET_BUTTON) - { - // Soft reset ensures that platform manager shutdown procedure is called. - button_event.Handler = SoftResetHandler; - } - else if (pin_no == BLE_BUTTON) - { - button_event.Handler = BleHandler; - - if (button_action == RESET_BUTTON_PUSH) - { - button_event.Handler = ResetActionEventHandler; - } - } - sAppTask.PostEvent(&button_event); -} - -button_status_t AppTask::KBD_Callback(void * buttonHandle, button_callback_message_t * message, void * callbackParam) -{ - uint32_t pinNb = (uint32_t) callbackParam; - switch (message->event) - { - case kBUTTON_EventOneClick: - case kBUTTON_EventShortPress: - switch (pinNb) - { - case BLE_BUTTON: - // K32W_LOG("pb1 short press"); - if (sAppTask.mResetTimerActive) - { - ButtonEventHandler(BLE_BUTTON, RESET_BUTTON_PUSH); - } - else - { - ButtonEventHandler(BLE_BUTTON, BLE_BUTTON_PUSH); - } - break; - - case LIGHT_BUTTON: - // K32W_LOG("pb2 short press"); - ButtonEventHandler(LIGHT_BUTTON, LIGHT_BUTTON_PUSH); - break; - } - break; - - case kBUTTON_EventLongPress: - switch (pinNb) - { - case BLE_BUTTON: - // K32W_LOG("pb1 long press"); - ButtonEventHandler(BLE_BUTTON, RESET_BUTTON_PUSH); - break; - - case LIGHT_BUTTON: - // K32W_LOG("pb2 long press"); - ButtonEventHandler(SOFT_RESET_BUTTON, SOFT_RESET_BUTTON_PUSH); - break; - } - break; - - default: - /* No action required */ - break; - } - return kStatus_BUTTON_Success; -} - -void AppTask::TimerEventHandler(TimerHandle_t xTimer) -{ - AppEvent event; - event.Type = AppEvent::kEventType_Timer; - event.TimerEvent.Context = (void *) xTimer; - event.Handler = FunctionTimerEventHandler; - sAppTask.PostEvent(&event); -} - -void AppTask::FunctionTimerEventHandler(AppEvent * aEvent) -{ - if (aEvent->Type != AppEvent::kEventType_Timer) - return; - - K32W_LOG("Device will factory reset..."); - - // Actually trigger Factory Reset - chip::Server::GetInstance().ScheduleFactoryReset(); -} - -void AppTask::ResetActionEventHandler(AppEvent * aEvent) -{ - if (aEvent->ButtonEvent.PinNo != RESET_BUTTON && aEvent->ButtonEvent.PinNo != BLE_BUTTON) - return; - - if (sAppTask.mResetTimerActive) - { - sAppTask.CancelTimer(); - sAppTask.mFunction = kFunction_NoneSelected; - - RestoreLightingState(); - - K32W_LOG("Factory Reset was cancelled!"); - } - else - { - uint32_t resetTimeout = FACTORY_RESET_TRIGGER_TIMEOUT; - - if (sAppTask.mFunction != kFunction_NoneSelected) - { - K32W_LOG("Another function is scheduled. Could not initiate Factory Reset!"); - return; - } - - K32W_LOG("Factory Reset Triggered. Push the RESET button within %lu ms to cancel!", resetTimeout); - sAppTask.mFunction = kFunction_FactoryReset; - - /* LEDs will start blinking to signal that a Factory Reset was scheduled */ -#ifndef CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR - sStatusLED.Set(false); -#endif - -#if CHIP_CONFIG_ENABLE_DIMMABLE_LED - sLightLED.SetLevel(0); -#else - sLightLED.Set(false); -#endif - -#ifndef CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR - sStatusLED.Blink(500); -#endif - sLightLED.Blink(500); - - sAppTask.StartTimer(FACTORY_RESET_TRIGGER_TIMEOUT); - } -} - -void AppTask::LightActionEventHandler(AppEvent * aEvent) -{ - LightingManager::Action_t action; - CHIP_ERROR err = CHIP_NO_ERROR; - int32_t actor = 0; - bool initiated = false; - - if (sAppTask.mFunction != kFunction_NoneSelected) - { - K32W_LOG("Another function is scheduled. Could not initiate ON/OFF Light command!"); - return; - } - - if (aEvent->Type == AppEvent::kEventType_TurnOn) - { - action = static_cast(aEvent->LightEvent.Action); - actor = aEvent->LightEvent.Actor; - } - else if (aEvent->Type == AppEvent::kEventType_Button) - { - actor = AppEvent::kEventType_Button; - - if (LightingMgr().IsTurnedOff()) - { - action = LightingManager::TURNON_ACTION; - } - else - { - action = LightingManager::TURNOFF_ACTION; - } - } - else - { - err = APP_ERROR_UNHANDLED_EVENT; - action = LightingManager::INVALID_ACTION; - } - - if (err == CHIP_NO_ERROR) - { - initiated = LightingMgr().InitiateAction(actor, action, LightingMgr().IsTurnedOff() ? 0 : 1); - - if (!initiated) - { - K32W_LOG("Action is already in progress or active."); - } - } -} - -void AppTask::SoftResetHandler(AppEvent * aEvent) -{ - if (aEvent->ButtonEvent.PinNo != SOFT_RESET_BUTTON) - return; - - PlatformMgrImpl().CleanReset(); -} - -void AppTask::BleHandler(AppEvent * aEvent) -{ - if (aEvent->ButtonEvent.PinNo != BLE_BUTTON) - return; - - if (sAppTask.mFunction != kFunction_NoneSelected) - { - K32W_LOG("Another function is scheduled. Could not toggle BLE state!"); - return; - } - PlatformMgr().ScheduleWork(AppTask::BleStartAdvertising, 0); -} - -void AppTask::BleStartAdvertising(intptr_t arg) -{ - if (ConnectivityMgr().IsBLEAdvertisingEnabled()) - { - ConnectivityMgr().SetBLEAdvertisingEnabled(false); - K32W_LOG("Stopped BLE Advertising!"); - } - else - { - ConnectivityMgr().SetBLEAdvertisingEnabled(true); - if (chip::Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow() == CHIP_NO_ERROR) - { - K32W_LOG("Started BLE Advertising!"); - } - else - { - K32W_LOG("OpenBasicCommissioningWindow() failed"); - } - } -} - -void AppTask::MatterEventHandler(const ChipDeviceEvent * event, intptr_t) -{ -#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR - if (event->Type == DeviceEventType::kDnssdInitialized) - { - K32W_LOG("Dnssd platform initialized."); - PlatformMgr().ScheduleWork(InitOTA, 0); - } -#else - if (event->Type == DeviceEventType::kDnssdInitialized) - { - sHaveFullConnectivity = TRUE; - } -#endif -} - -void AppTask::CancelTimer() -{ - if (xTimerStop(sFunctionTimer, 0) == pdFAIL) - { - K32W_LOG("app timer stop() failed"); - } - - mResetTimerActive = false; -} - -void AppTask::StartTimer(uint32_t aTimeoutInMs) -{ - if (xTimerIsTimerActive(sFunctionTimer)) - { - K32W_LOG("app timer already started!"); - CancelTimer(); - } - - // timer is not active, change its period to required value (== restart). - // FreeRTOS- Block for a maximum of 100 ticks if the change period command - // cannot immediately be sent to the timer command queue. - if (xTimerChangePeriod(sFunctionTimer, aTimeoutInMs / portTICK_PERIOD_MS, 100) != pdPASS) - { - K32W_LOG("app timer start() failed"); - } - - mResetTimerActive = true; -} - -void AppTask::ActionInitiated(LightingManager::Action_t aAction, int32_t aActor) -{ - // start flashing the LEDs rapidly to indicate action initiation. - if (aAction == LightingManager::TURNON_ACTION) - { - K32W_LOG("Turn on Action has been initiated") - } - else if (aAction == LightingManager::TURNOFF_ACTION) - { - K32W_LOG("Turn off Action has been initiated") - } - else if (aAction == LightingManager::DIM_ACTION) - { - K32W_LOG("Dim Action has been initiated"); - } - - if (aActor == AppEvent::kEventType_Button) - { - sAppTask.mSyncClusterToButtonAction = true; - } - - sAppTask.mFunction = kFunctionTurnOnTurnOff; -} - -void AppTask::ActionCompleted(LightingManager::Action_t aAction, uint8_t level) -{ - // Turn on the light LED if in a TURNON state OR - // Turn off the light LED if in a TURNOFF state. - if (aAction == LightingManager::TURNON_ACTION) - { - K32W_LOG("Turn on action has been completed") -#if CHIP_CONFIG_ENABLE_DIMMABLE_LED -#else - sLightLED.Set(true); -#endif - } - else if (aAction == LightingManager::TURNOFF_ACTION) - { - K32W_LOG("Turn off action has been completed") -#if CHIP_CONFIG_ENABLE_DIMMABLE_LED -#else - sLightLED.Set(false); -#endif - } - else if (aAction == LightingManager::DIM_ACTION) - { - K32W_LOG("Move to level %d completed", level); - } -#if CHIP_CONFIG_ENABLE_DIMMABLE_LED - sLightLED.SetLevel(LightingMgr().IsTurnedOff() ? 1 : LightingMgr().GetDimLevel()); -#endif - - if (sAppTask.mSyncClusterToButtonAction) - { - sAppTask.UpdateClusterState(); - sAppTask.mSyncClusterToButtonAction = false; - } - - sAppTask.mFunction = kFunction_NoneSelected; -} - -void AppTask::RestoreLightingState(void) -{ -#if CHIP_CONFIG_ENABLE_DIMMABLE_LED - LightingMgr().SetState(!LightingMgr().IsTurnedOff()); -#else - /* restore initial state for the LED indicating Lighting state */ - if (LightingMgr().IsTurnedOff()) - { - sLightLED.Set(false); - } - else - { - sLightLED.Set(true); - } -#endif -} - -void AppTask::OnIdentifyStart(Identify * identify) -{ - if ((kFunction_NoneSelected != sAppTask.mFunction) && (kFunction_TriggerEffect != sAppTask.mFunction)) - { - K32W_LOG("Another function is scheduled. Could not initiate Identify process!"); - return; - } - - if (kFunction_TriggerEffect == sAppTask.mFunction) - { - chip::DeviceLayer::SystemLayer().CancelTimer(OnTriggerEffectComplete, identify); - OnTriggerEffectComplete(&chip::DeviceLayer::SystemLayer(), identify); - } - - ChipLogProgress(Zcl, "Identify process has started. Status LED should blink with a period of 0.5 seconds."); - sAppTask.mFunction = kFunction_Identify; -#if CHIP_CONFIG_ENABLE_DIMMABLE_LED - sLightLED.SetLevel(0); -#else - sLightLED.Set(false); -#endif - sLightLED.Blink(250); -} - -void AppTask::OnIdentifyStop(Identify * identify) -{ - if (kFunction_Identify == sAppTask.mFunction) - { - ChipLogProgress(Zcl, "Identify process has stopped."); - sAppTask.mFunction = kFunction_NoneSelected; - - RestoreLightingState(); - } -} - -void AppTask::OnTriggerEffectComplete(chip::System::Layer * systemLayer, void * appState) -{ - // Let Identify command take over if called during TriggerEffect already running - if (kFunction_TriggerEffect == sAppTask.mFunction) - { - ChipLogProgress(Zcl, "TriggerEffect has stopped."); - sAppTask.mFunction = kFunction_NoneSelected; - - // TriggerEffect finished - reset identifiers - // Use invalid value for identifiers to enable TriggerEffect command - // to stop Identify command for each effect - gIdentify.mCurrentEffectIdentifier = Clusters::Identify::EffectIdentifierEnum::kUnknownEnumValue; - gIdentify.mTargetEffectIdentifier = Clusters::Identify::EffectIdentifierEnum::kUnknownEnumValue; - gIdentify.mEffectVariant = Clusters::Identify::EffectVariantEnum::kDefault; - - RestoreLightingState(); - } -} - -void AppTask::OnTriggerEffect(Identify * identify) -{ - // Allow overlapping TriggerEffect calls - if ((kFunction_NoneSelected != sAppTask.mFunction) && (kFunction_TriggerEffect != sAppTask.mFunction)) - { - K32W_LOG("Another function is scheduled. Could not initiate Identify process!"); - return; - } - - sAppTask.mFunction = kFunction_TriggerEffect; - uint16_t timerDelay = 0; - - ChipLogProgress(Zcl, "TriggerEffect has started."); - - switch (identify->mCurrentEffectIdentifier) - { - case Clusters::Identify::EffectIdentifierEnum::kBlink: - timerDelay = 2; - break; - - case Clusters::Identify::EffectIdentifierEnum::kBreathe: - timerDelay = 15; - break; - - case Clusters::Identify::EffectIdentifierEnum::kOkay: - timerDelay = 4; - break; - - case Clusters::Identify::EffectIdentifierEnum::kChannelChange: - ChipLogProgress(Zcl, "Channel Change effect not supported, using effect %d", - to_underlying(Clusters::Identify::EffectIdentifierEnum::kBlink)); - timerDelay = 2; - break; - - case Clusters::Identify::EffectIdentifierEnum::kFinishEffect: - chip::DeviceLayer::SystemLayer().CancelTimer(OnTriggerEffectComplete, identify); - timerDelay = 1; - break; - - case Clusters::Identify::EffectIdentifierEnum::kStopEffect: - chip::DeviceLayer::SystemLayer().CancelTimer(OnTriggerEffectComplete, identify); - OnTriggerEffectComplete(&chip::DeviceLayer::SystemLayer(), identify); - break; - - default: - ChipLogProgress(Zcl, "Invalid effect identifier."); - } - - if (timerDelay) - { -#if CHIP_CONFIG_ENABLE_DIMMABLE_LED - sLightLED.SetLevel(0); -#else - sLightLED.Set(false); -#endif - sLightLED.Blink(500); - - chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds16(timerDelay), OnTriggerEffectComplete, identify); - } -} - -void AppTask::PostTurnOnActionRequest(int32_t aActor, LightingManager::Action_t aAction) -{ - AppEvent event; - event.Type = AppEvent::kEventType_TurnOn; - event.LightEvent.Actor = aActor; - event.LightEvent.Action = aAction; - event.Handler = LightActionEventHandler; - PostEvent(&event); -} - -void AppTask::PostEvent(const AppEvent * aEvent) -{ - portBASE_TYPE taskToWake = pdFALSE; - if (sAppEventQueue != NULL) - { - if (__get_IPSR()) - { - if (!xQueueSendToFrontFromISR(sAppEventQueue, aEvent, &taskToWake)) - { - K32W_LOG("Failed to post event to app task event queue"); - } - - portYIELD_FROM_ISR(taskToWake); - } - else - { - if (!xQueueSend(sAppEventQueue, aEvent, 1)) - { - K32W_LOG("Failed to post event to app task event queue"); - } - } - } -} - -void AppTask::DispatchEvent(AppEvent * aEvent) -{ - if (aEvent->Handler) - { - aEvent->Handler(aEvent); - } - else - { - K32W_LOG("Event received with no handler. Dropping event."); - } -} - -void AppTask::UpdateClusterState(void) -{ - PlatformMgr().ScheduleWork(UpdateClusterStateInternal, 0); -} - -void AppTask::UpdateClusterStateInternal(intptr_t arg) -{ - uint8_t newValue = !LightingMgr().IsTurnedOff(); - - // write the new on/off value - Protocols::InteractionModel::Status status = app::Clusters::OnOff::Attributes::OnOff::Set(1, newValue); - if (status != Protocols::InteractionModel::Status::Success) - { - ChipLogError(NotSpecified, "ERR: updating on/off %x", to_underlying(status)); - } -} - -void AppTask::UpdateDeviceState(void) -{ - PlatformMgr().ScheduleWork(UpdateDeviceStateInternal, 0); -} - -void AppTask::UpdateDeviceStateInternal(intptr_t arg) -{ - bool onoffAttrValue = 0; - - /* get onoff attribute value */ - (void) app::Clusters::OnOff::Attributes::OnOff::Get(1, &onoffAttrValue); - - /* set the device state */ -#if CHIP_CONFIG_ENABLE_DIMMABLE_LED -#else - sLightLED.Set(onoffAttrValue); -#endif - LightingMgr().SetState(onoffAttrValue); -} - -extern "C" void OTAIdleActivities(void) -{ -#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR - OTA_TransactionResume(); -#endif -} diff --git a/examples/lighting-app/nxp/k32w/k32w1/main/LightingManager.cpp b/examples/lighting-app/nxp/k32w/k32w1/main/LightingManager.cpp deleted file mode 100644 index 2627138043bbe4..00000000000000 --- a/examples/lighting-app/nxp/k32w/k32w1/main/LightingManager.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - * - * Copyright (c) 2021 Project CHIP Authors - * Copyright (c) 2019 Google LLC. - * 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 "LightingManager.h" - -#if CHIP_CONFIG_ENABLE_DIMMABLE_LED -#include "LED_Dimmer.h" -#endif - -#include "AppTask.h" -#include "FreeRTOS.h" - -#include "app_config.h" - -LightingManager LightingManager::sLight; - -int LightingManager::Init() -{ - mState = kState_On; - - mLevel = kLevel_Max; - - return 0; -} - -void LightingManager::SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB) -{ - mActionInitiated_CB = aActionInitiated_CB; - mActionCompleted_CB = aActionCompleted_CB; -} - -void LightingManager::SetState(bool state) -{ - mState = state ? kState_On : kState_Off; -} - -void LightingManager::SetDimLevel(uint8_t level) -{ - mLevel = level; -} - -bool LightingManager::IsTurnedOff() -{ - return (mState == kState_Off) ? true : false; -} - -uint8_t LightingManager::GetDimLevel() -{ - return mLevel; -} - -bool LightingManager::InitiateAction(int32_t aActor, Action_t aAction, uint8_t kValue) -{ - bool action_initiated = false; - State_t current_state; - - if (mState == kState_On && aAction == TURNOFF_ACTION) - { - action_initiated = true; - current_state = kState_Off; - } - else if (mState == kState_Off && aAction == TURNON_ACTION) - { - action_initiated = true; - current_state = kState_On; - } - - else if (aAction == DIM_ACTION && kValue != mLevel) - { - action_initiated = true; - if (kValue == 1) - { - current_state = kState_Off; - } - else - { - current_state = kState_On; - } - } - - if (action_initiated) - { - if (mActionInitiated_CB) - { - mActionInitiated_CB(aAction, aActor); - } - - if (aAction == TURNON_ACTION || aAction == TURNOFF_ACTION) - { - SetState(current_state == kState_On); - } - else if (aAction == DIM_ACTION) - { - mState = current_state; - SetDimLevel(kValue); - } - - if (mActionCompleted_CB) - { - mActionCompleted_CB(aAction, kValue); - } - } - - return action_initiated; -} diff --git a/examples/lighting-app/nxp/k32w/k32w1/main/include/AppTask.h b/examples/lighting-app/nxp/k32w/k32w1/main/include/AppTask.h deleted file mode 100644 index 096690c680b1d2..00000000000000 --- a/examples/lighting-app/nxp/k32w/k32w1/main/include/AppTask.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * - * Copyright (c) 2021 Google LLC. - * 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 "AppEvent.h" -#include "LightingManager.h" - -#include -#include - -#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA -#include -#endif - -#include "FreeRTOS.h" -#include "fsl_component_button.h" -#include "timers.h" - -// Application-defined error codes in the CHIP_ERROR space. -#define APP_ERROR_EVENT_QUEUE_FAILED CHIP_APPLICATION_ERROR(0x01) -#define APP_ERROR_CREATE_TASK_FAILED CHIP_APPLICATION_ERROR(0x02) -#define APP_ERROR_UNHANDLED_EVENT CHIP_APPLICATION_ERROR(0x03) -#define APP_ERROR_CREATE_TIMER_FAILED CHIP_APPLICATION_ERROR(0x04) -#define APP_ERROR_START_TIMER_FAILED CHIP_APPLICATION_ERROR(0x05) -#define APP_ERROR_STOP_TIMER_FAILED CHIP_APPLICATION_ERROR(0x06) - -class AppTask -{ -public: -#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA - using FactoryDataProvider = chip::DeviceLayer::FactoryDataProviderImpl; -#endif - CHIP_ERROR StartAppTask(); - static void AppTaskMain(void * pvParameter); - - void PostTurnOnActionRequest(int32_t aActor, LightingManager::Action_t aAction); - void PostEvent(const AppEvent * event); - - void UpdateClusterState(void); - void UpdateDeviceState(void); - - // Identify cluster callbacks. - static void OnIdentifyStart(Identify * identify); - static void OnIdentifyStop(Identify * identify); - static void OnTriggerEffect(Identify * identify); - static void OnTriggerEffectComplete(chip::System::Layer * systemLayer, void * appState); - static void ButtonEventHandler(uint8_t pin_no, uint8_t button_action); - -private: - friend AppTask & GetAppTask(void); - - CHIP_ERROR Init(); - - static void ActionInitiated(LightingManager::Action_t aAction, int32_t aActor); - static void ActionCompleted(LightingManager::Action_t aAction, uint8_t level); - - void CancelTimer(void); - - void DispatchEvent(AppEvent * event); - - static void FunctionTimerEventHandler(AppEvent * aEvent); - static button_status_t KBD_Callback(void * buttonHandle, button_callback_message_t * message, void * callbackParam); - static void SoftResetHandler(AppEvent * aEvent); - static void BleHandler(AppEvent * aEvent); - static void BleStartAdvertising(intptr_t arg); - static void LightActionEventHandler(AppEvent * aEvent); - static void ResetActionEventHandler(AppEvent * aEvent); - static void InstallEventHandler(AppEvent * aEvent); - - static void TimerEventHandler(TimerHandle_t xTimer); - - static void MatterEventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg); - void StartTimer(uint32_t aTimeoutInMs); - - static void RestoreLightingState(void); - -#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR - static void InitOTA(intptr_t arg); - static void StartOTAQuery(intptr_t arg); -#endif - - static void UpdateClusterStateInternal(intptr_t arg); - static void UpdateDeviceStateInternal(intptr_t arg); - static void InitServer(intptr_t arg); - static void PrintOnboardingInfo(); - - enum Function_t - { - kFunction_NoneSelected = 0, - kFunction_FactoryReset, - kFunctionTurnOnTurnOff, - kFunction_Identify, - kFunction_TriggerEffect, - kFunction_Invalid - } Function; - - Function_t mFunction = kFunction_NoneSelected; - bool mResetTimerActive = false; - bool mSyncClusterToButtonAction = false; - - static AppTask sAppTask; -}; - -inline AppTask & GetAppTask(void) -{ - return AppTask::sAppTask; -} diff --git a/examples/lighting-app/nxp/k32w/k32w1/main/include/LightingManager.h b/examples/lighting-app/nxp/k32w/k32w1/main/include/LightingManager.h deleted file mode 100644 index f96d6c7ecae40c..00000000000000 --- a/examples/lighting-app/nxp/k32w/k32w1/main/include/LightingManager.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * - * Copyright (c) 2021 Google LLC. - * 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 "AppEvent.h" - -#include "FreeRTOS.h" -#include "timers.h" // provides FreeRTOS timer support - -class LightingManager -{ -public: - enum Action_t - { - TURNON_ACTION = 0, - TURNOFF_ACTION, - DIM_ACTION, - INVALID_ACTION - } Action; - - enum State_t - { - kState_On = 0, - kState_Off, - } State; - - static const uint8_t kLevel_Max = 254; - static const uint8_t kLevel_Min = 0; - - int Init(); - bool IsTurnedOff(); - uint8_t GetDimLevel(); - bool InitiateAction(int32_t aActor, Action_t aAction, uint8_t kValue); - - typedef void (*Callback_fn_initiated)(Action_t, int32_t aActor); - typedef void (*Callback_fn_completed)(Action_t, uint8_t level); - void SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB); - void SetState(bool state); - void SetDimLevel(uint8_t level); - -private: - friend LightingManager & LightingMgr(void); - State_t mState; - uint8_t mLevel; - - Callback_fn_initiated mActionInitiated_CB; - Callback_fn_completed mActionCompleted_CB; - - static LightingManager sLight; -}; - -inline LightingManager & LightingMgr(void) -{ - return LightingManager::sLight; -} diff --git a/examples/lighting-app/nxp/k32w/k32w1/main/include/app_config.h b/examples/lighting-app/nxp/k32w/k32w1/main/include/app_config.h deleted file mode 100644 index 1478b53b11aba1..00000000000000 --- a/examples/lighting-app/nxp/k32w/k32w1/main/include/app_config.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * - * Copyright (c) 2021 Google LLC. - * 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 - -// ---- Light Example App Config ---- - -#define RESET_BUTTON 1 -#define LIGHT_BUTTON 2 -#define SOFT_RESET_BUTTON 3 -#define BLE_BUTTON 4 - -#define RESET_BUTTON_PUSH 1 -#define LIGHT_BUTTON_PUSH 2 -#define SOFT_RESET_BUTTON_PUSH 3 -#define BLE_BUTTON_PUSH 4 - -#define APP_BUTTON_PUSH 1 - -#define LIGHT_STATE_LED 1 -#define SYSTEM_STATE_LED 0 - -// Time it takes for the light to switch on/off -#define ACTUATOR_MOVEMENT_PERIOS_MS 50 - -// ---- Light Example SWU Config ---- -#define SWU_INTERVAl_WINDOW_MIN_MS (23 * 60 * 60 * 1000) // 23 hours -#define SWU_INTERVAl_WINDOW_MAX_MS (24 * 60 * 60 * 1000) // 24 hours - -#if K32W_LOG_ENABLED -#define K32W_LOG(...) otPlatLog(OT_LOG_LEVEL_NONE, OT_LOG_REGION_API, ##__VA_ARGS__); -#else -#define K32W_LOG(...) -#endif diff --git a/examples/lighting-app/nxp/k32w/k32w1/main/main.cpp b/examples/lighting-app/nxp/k32w/k32w1/main/main.cpp deleted file mode 100644 index 53a6efbbb3ffd5..00000000000000 --- a/examples/lighting-app/nxp/k32w/k32w1/main/main.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/* - * - * Copyright (c) 2021 Google LLC. - * 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. - */ - -// ================================================================================ -// Main Code -// ================================================================================ - -#include "openthread/platform/logging.h" -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "FreeRtosHooks.h" -#include "app_config.h" -#include "pin_mux.h" - -using namespace ::chip; -using namespace ::chip::Inet; -using namespace ::chip::DeviceLayer; -using namespace ::chip::Logging; - -#include - -#if PW_RPC_ENABLED -#include "Rpc.h" -#endif - -typedef void (*InitFunc)(void); -extern InitFunc __init_array_start; -extern InitFunc __init_array_end; - -extern "C" void main_task(void const * argument) -{ - CHIP_ERROR err = CHIP_NO_ERROR; - - /* Call C++ constructors */ - InitFunc * pFunc = &__init_array_start; - for (; pFunc < &__init_array_end; ++pFunc) - { - (*pFunc)(); - } - - mbedtls_platform_set_calloc_free(CHIPPlatformMemoryCalloc, CHIPPlatformMemoryFree); - - err = PlatformMgrImpl().InitBoardFwk(); - if (err != CHIP_NO_ERROR) - { - return; - } - - /* Used for HW initializations */ - otSysInit(0, NULL); - -#if PW_RPC_ENABLED - /* set clock */ - CLOCK_SetIpSrc(kCLOCK_Lpuart1, kCLOCK_IpSrcFro192M); - /* enable clock */ - CLOCK_EnableClock(kCLOCK_Lpuart1); - - BOARD_InitPinLPUART1_TX(); - BOARD_InitPinLPUART1_RX(); - chip::rpc::Init(); -#endif - - K32W_LOG("Welcome to NXP Lighting Demo App"); - - /* Mbedtls Threading support is needed because both - * Thread and Matter tasks are using it */ - freertos_mbedtls_mutex_init(); - - // Init Chip memory management before the stack - chip::Platform::MemoryInit(); - - err = PlatformMgr().InitChipStack(); - if (err != CHIP_NO_ERROR) - { - K32W_LOG("Error during PlatformMgr().InitMatterStack()"); - goto exit; - } - - err = ThreadStackMgr().InitThreadStack(); - if (err != CHIP_NO_ERROR) - { - K32W_LOG("Error during ThreadStackMgr().InitThreadStack()"); - goto exit; - } - - err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_Router); - - if (err != CHIP_NO_ERROR) - { - goto exit; - } - - // Start OpenThread task - err = ThreadStackMgrImpl().StartThreadTask(); - if (err != CHIP_NO_ERROR) - { - K32W_LOG("Error during ThreadStackMgrImpl().StartThreadTask()"); - goto exit; - } - - err = GetAppTask().StartAppTask(); - if (err != CHIP_NO_ERROR) - { - K32W_LOG("Error during GetAppTask().StartAppTask()"); - goto exit; - } - - err = PlatformMgr().StartEventLoopTask(); - if (err != CHIP_NO_ERROR) - { - K32W_LOG("Error during PlatformMgr().StartEventLoopTask();"); - goto exit; - } - - GetAppTask().AppTaskMain(NULL); - -exit: - return; -} - -/** - * Glue function called directly by the OpenThread stack - * when system event processing work is pending. - */ -extern "C" void otSysEventSignalPending(void) -{ - { - BaseType_t yieldRequired = ThreadStackMgrImpl().SignalThreadActivityPendingFromISR(); - portYIELD_FROM_ISR(yieldRequired); - } -} diff --git a/examples/lighting-app/nxp/k32w/k32w1/third_party/connectedhomeip b/examples/lighting-app/nxp/k32w/k32w1/third_party/connectedhomeip deleted file mode 120000 index 305f2077ffe860..00000000000000 --- a/examples/lighting-app/nxp/k32w/k32w1/third_party/connectedhomeip +++ /dev/null @@ -1 +0,0 @@ -../../../../../.. \ No newline at end of file diff --git a/examples/lighting-app/nxp/k32w/k32w1/.gn b/examples/lighting-app/nxp/k32w1/.gn similarity index 93% rename from examples/lighting-app/nxp/k32w/k32w1/.gn rename to examples/lighting-app/nxp/k32w1/.gn index a88f6f5aa7cb3f..afa5bfea46aca8 100644 --- a/examples/lighting-app/nxp/k32w/k32w1/.gn +++ b/examples/lighting-app/nxp/k32w1/.gn @@ -27,5 +27,5 @@ default_args = { import("//args.gni") # Import default platform configs - import("${chip_root}/src/platform/nxp/k32w/k32w1/args.gni") + import("${chip_root}/src/platform/nxp/k32w1/args.gni") } diff --git a/examples/lighting-app/nxp/k32w1/BUILD.gn b/examples/lighting-app/nxp/k32w1/BUILD.gn new file mode 100644 index 00000000000000..b6e6db814ad221 --- /dev/null +++ b/examples/lighting-app/nxp/k32w1/BUILD.gn @@ -0,0 +1,268 @@ +# 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. + +import("//build_overrides/chip.gni") +import("//build_overrides/nxp_sdk.gni") +import("//build_overrides/openthread.gni") + +import("${nxp_sdk_build_root}/nxp_sdk.gni") + +import("${nxp_sdk_build_root}/${nxp_sdk_name}/nxp_executable.gni") + +import("${nxp_sdk_build_root}/${nxp_sdk_name}/${nxp_sdk_name}.gni") + +import("${chip_root}/src/crypto/crypto.gni") +import("${chip_root}/src/platform/device.gni") +import("${chip_root}/src/platform/nxp/${nxp_platform}/args.gni") + +import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni") + +if (chip_enable_pw_rpc) { + import("//build_overrides/pigweed.gni") + import("$dir_pw_build/target_types.gni") + import("${chip_root}/examples/platform/nxp/pw_rpc_server.gni") +} + +declare_args() { + # Setup discriminator as argument + setup_discriminator = 3840 +} + +assert(current_os == "freertos") +assert(target_os == "freertos") + +example_platform_dir = "${chip_root}/examples/platform/nxp/${nxp_platform}" +common_example_dir = "${chip_root}/examples/platform/nxp/common" + +k32w1_sdk("sdk") { + defines = [] + include_dirs = [] + sources = [] + + # Indicate the path to CHIPProjectConfig.h + include_dirs += [ "include/config" ] + + # Indicate the default path to FreeRTOSConfig.h + include_dirs += [ "${example_platform_dir}/app/project_include/freeRTOS" ] + + # Indicate the default path to OpenThreadConfig.h + include_dirs += [ "${example_platform_dir}/app/project_include/openthread" ] + + include_dirs += [ + "${k32w1_sdk_root}/middleware/wireless/framework/boards/kw45_k32w1", + "${k32w1_sdk_root}/middleware/wireless/framework/boards/kw45_k32w1/K32W1480", + ] + + sources += [ + "${k32w1_sdk_root}/middleware/wireless/framework/boards/kw45_k32w1/K32W1480/clock_config.c", + "${k32w1_sdk_root}/middleware/wireless/framework/boards/kw45_k32w1/K32W1480/pin_mux.c", + "${k32w1_sdk_root}/middleware/wireless/framework/boards/kw45_k32w1/app_services_init.c", + "${k32w1_sdk_root}/middleware/wireless/framework/boards/kw45_k32w1/board.c", + "${k32w1_sdk_root}/middleware/wireless/framework/boards/kw45_k32w1/board_comp.c", + "${k32w1_sdk_root}/middleware/wireless/framework/boards/kw45_k32w1/board_dcdc.c", + "${k32w1_sdk_root}/middleware/wireless/framework/boards/kw45_k32w1/board_extflash.c", + "${k32w1_sdk_root}/middleware/wireless/framework/boards/kw45_k32w1/board_lp.c", + "${k32w1_sdk_root}/middleware/wireless/framework/boards/kw45_k32w1/hardware_init.c", + ] + + if (is_debug) { + defines += [ "BUILD_RELEASE=0" ] + } else { + defines += [ "BUILD_RELEASE=1" ] + } + + if (chip_enable_pw_rpc) { + defines += [ + "CONFIG_ENABLE_PW_RPC", + "STREAMER_UART_FLUSH_DELAY_MS=0", + "STREAMER_UART_SERIAL_MANAGER_RING_BUFFER_SIZE=512", + "BOARD_APP_UART_CLK_FREQ=96000000", + ] + } + + defines += [ + "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR=${setup_discriminator}", + ] + + if (chip_key_storage == "littlefs") { + include_dirs += [ "${example_platform_dir}/board" ] + sources += [ + "${example_platform_dir}/board/peripherals.c", + "${example_platform_dir}/board/peripherals.h", + ] + } +} + +k32w1_executable("light_app") { + output_name = "chip-k32w1-light-example" + + defines = [] + deps = [] + sources = [] + + if (chip_enable_pw_rpc) { + forward_variables_from(pw_rpc_server, "*") + } else { + include_dirs = [] + cflags = [ "-Wconversion" ] + } + + # Defines used by common code + defines += [ + "CONFIG_NET_L2_OPENTHREAD=1", + "CONFIG_NETWORK_LAYER_BLE=1", + "CONFIG_OPERATIONAL_KEYSTORE=1", + "CONFIG_ENABLE_FEEDBACK=1", + "APP_QUEUE_TICKS_TO_WAIT=pdMS_TO_TICKS(10)", + "EXTERNAL_FACTORY_DATA_PROVIDER_HEADER=\"platform/nxp/common/legacy/FactoryDataProvider.h\"", + ] + + # App common files + include_dirs += [ + "${common_example_dir}/app_task/include", + "${common_example_dir}/matter_button/include", + "${common_example_dir}/clusters/include", + "${common_example_dir}/device_callbacks/include", + "${common_example_dir}/device_manager/include", + "${common_example_dir}/factory_data/include", + "${common_example_dir}/led_widget/include", + "${common_example_dir}/operational_keystore/include", + "${common_example_dir}/rpc/include", + "${common_example_dir}/ui_feedback/include", + ] + + sources += [ + "${common_example_dir}/app_task/source/AppTaskBase.cpp", + "${common_example_dir}/app_task/source/AppTaskFreeRTOS.cpp", + "${common_example_dir}/clusters/source/ZclCallbacks.cpp", + "${common_example_dir}/device_callbacks/source/CommonDeviceCallbacks.cpp", + "${common_example_dir}/device_manager/source/CHIPDeviceManager.cpp", + "${example_platform_dir}/factory_data/source/AppFactoryDataExample.cpp", + ] + + if (chip_enable_ota_requestor) { + defines += [ + "CONFIG_CHIP_OTA_IMAGE_PROCESSOR_HEADER=\"platform/nxp/common/legacy/OTAImageProcessorImpl.h\"", + + # The status LED and the external flash CS pin are wired together. The OTA image writing may fail if used together. + "LED_MANAGER_ENABLE_STATUS_LED=0", + ] + + include_dirs += [ "${common_example_dir}/ota_requestor/include" ] + sources += [ "${common_example_dir}/ota_requestor/source/OTARequestorInitiatorMultiImage.cpp" ] + deps += [ "${chip_root}/src/platform/nxp:nxp_ota" ] + } + + # Platform specific files + include_dirs += [ + "${example_platform_dir}/util", + "${example_platform_dir}/app/support", + "${example_platform_dir}/button", + ] + + sources += [ + "${example_platform_dir}/button/ButtonManager.cpp", + "${example_platform_dir}/clusters/Identify.cpp", + "${example_platform_dir}/operational_keystore/OperationalKeystore.cpp", + ] + + if (chip_enable_ota_requestor) { + sources += [ "${example_platform_dir}/ota/OtaUtils.cpp" ] + } + + if (chip_enable_pw_rpc) { + sources += [ "${example_platform_dir}/rpc/AppRpc.cpp" ] + } + + if (chip_with_factory_data == 1) { + include_dirs += [ "${chip_root}/src/platform/nxp/common/legacy" ] + deps += [ "${chip_root}/src/platform/nxp:nxp_factory_data" ] + } + + sources += [ + "../common/AppTask.cpp", + "../common/DeviceCallbacks.cpp", + "../common/main.cpp", + ] + + include_dirs += [ + "../common", + "../common/include", + "include/config", + ] + + deps += [ + "${chip_root}/examples/providers:device_info_provider", + "${chip_root}/src/platform/logging:default", + ] + + if (chip_config_dimmable_led) { + defines += [ "LIGHTING_MANAGER_ENABLE_DIMMABLE_LED=1" ] + sources += [ + "${common_example_dir}/led_widget/include/LedDimmer.h", + "${example_platform_dir}/util/LedDimmer.cpp", + "${example_platform_dir}/util/LightingManagerDimmable.cpp", + ] + deps += [ "${chip_root}/examples/lighting-app/lighting-common/" ] + } else { + sources += [ + "${common_example_dir}/ui_feedback/source/LedManager.cpp", + "${example_platform_dir}/util/LedOnOff.cpp", + ] + deps += [ "${chip_root}/examples/lighting-app/nxp/zap/" ] + } + + if (chip_openthread_ftd) { + deps += [ + "${openthread_root}:libopenthread-cli-ftd", + "${openthread_root}:libopenthread-ftd", + ] + } else { + deps += [ + "${openthread_root}:libopenthread-cli-mtd", + "${openthread_root}:libopenthread-mtd", + ] + } + + if (use_smu2_static) { + ldscript = "${example_platform_dir}/app/ldscripts/k32w1_app.ld" + base_ldscript_dir = "${k32w1_sdk_root}/middleware/wireless/framework/Common/devices/kw45_k32w1/gcc" + } else { + ldscript = "${k32w1_sdk_root}/middleware/wireless/framework/Common/devices/kw45_k32w1/gcc/connectivity.ld" + } + + inputs = [ ldscript ] + + ldflags = [ + "-Wl,--defsym=__heap_size__=0", + "-Wl,--defsym=__stack_size__=0x480", + "-Wl,-print-memory-usage", + "-Wl,--no-warn-rwx-segments", + "-T" + rebase_path(ldscript, root_build_dir), + ] + + if (chip_with_factory_data == 1) { + ldflags += [ "-Wl,--defsym=gUseFactoryData_d=1" ] + } + + if (use_smu2_static) { + ldflags += [ "-L" + rebase_path(base_ldscript_dir, root_build_dir) ] + } + + output_dir = root_out_dir +} + +group("default") { + deps = [ ":light_app" ] +} diff --git a/examples/lighting-app/nxp/k32w/k32w1/README.md b/examples/lighting-app/nxp/k32w1/README.md similarity index 80% rename from examples/lighting-app/nxp/k32w/k32w1/README.md rename to examples/lighting-app/nxp/k32w1/README.md index 3bf2ab8105481b..349deef640727d 100644 --- a/examples/lighting-app/nxp/k32w/k32w1/README.md +++ b/examples/lighting-app/nxp/k32w1/README.md @@ -16,30 +16,32 @@ into an existing Matter network and can be controlled by this network.
- [Matter K32W1 Lighting Example Application](#matter-k32w1-lighting-example-application) -- [Introduction](#introduction) - - [Bluetooth LE Advertising](#bluetooth-le-advertising) - - [Bluetooth LE Rendezvous](#bluetooth-le-rendezvous) -- [Device UI](#device-ui) -- [Building](#building) - - [SMU2](#smu2-memory) - - [LED PWM](#led-pwm) -- [Manufacturing data](#manufacturing-data) -- [Flashing](#flashing) - - [Flashing the NBU image](#flashing-the-nbu-image) - - [Flashing the host image](#flashing-the-host-image) -- [Debugging](#debugging) -- [OTA](#ota) - - [Convert srec into sb3 file](#convert-srec-into-sb3-file) - - [Convert sb3 into ota file](#convert-sb3-into-ota-file) - - [Running OTA](#running-ota) - - [Known issues](#known-issues) -- [Running RPC console](#running-rpc-console) + - [Introduction](#introduction) + - [Bluetooth LE Advertising](#bluetooth-le-advertising) + - [Bluetooth LE Rendezvous](#bluetooth-le-rendezvous) + - [Thread Provisioning](#thread-provisioning) + - [Device UI](#device-ui) + - [Building](#building) + - [`SMU2` Memory](#smu2-memory) + - [LED PWM](#led-pwm) + - [Manufacturing data](#manufacturing-data) + - [Flashing](#flashing) + - [Flashing the `NBU` image](#flashing-the-nbu-image) + - [Flashing the host image](#flashing-the-host-image) + - [Debugging](#debugging) + - [OTA](#ota) + - [Convert `srec` into `sb3` file](#convert-srec-into-sb3-file) + - [Convert `sb3` into `ota` file](#convert-sb3-into-ota-file) + - [OTA factory data](#ota-factory-data) + - [Running OTA](#running-ota) + - [Known issues](#known-issues) + - [Running RPC console](#running-rpc-console) ## Introduction -![K32W1 EVK](../../../../platform/nxp/k32w/k32w1/doc/images/k32w1-evk.jpg) +![K32W1 EVK](../../../platform/nxp/k32w1/doc/images/k32w1-evk.jpg) The K32W1 lighting example application provides a working demonstration of a light bulb device, built using the Matter codebase and the NXP K32W1 SDK. The @@ -119,26 +121,52 @@ does a clean soft reset that takes into account Matter shutdown procedure. ## Building -In order to build the Matter example, we recommend using a Linux distribution -(the demo-application was compiled on Ubuntu 20.04). +In order to build the Project CHIP example, we recommend using a Linux +distribution. Supported Operating Systems and prerequisites are listed in +[BUILDING](../../../../docs/guides/BUILDING.md). -- Download [K32W1 SDK for Matter](https://mcuxpresso.nxp.com/). Creating an - nxp.com account is required before being able to download the SDK. Once the - account is created, login and follow the steps for downloading K32W148-EVK - MCUXpresso SDK. The SDK Builder UI selection should be similar with the one - from the image below. +- Make sure that below prerequisites are correctly installed - ![MCUXpresso SDK Download](../../../../platform/nxp/k32w/k32w1/doc/images/mcux-sdk-download.jpg) +``` +sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev \ + libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev \ + python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev +``` - Please refer to Matter release notes for getting the latest released SDK. +- Step 1: checkout NXP specific submodules only ``` -user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_K32W1_SDK_ROOT=/home/user/Desktop/SDK_K32W1/ -user@ubuntu:~/Desktop/git/connectedhomeip$ source ./scripts/activate.sh user@ubuntu:~/Desktop/git/connectedhomeip$ scripts/checkout_submodules.py --shallow --platform nxp --recursive -user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/lighting-app/nxp/k32w/k32w1 -user@ubuntu:~/Desktop/git/connectedhomeip/examples/lighting-app/nxp/k32w/k32w1$ gn gen out/debug -user@ubuntu:~/Desktop/git/connectedhomeip/examples/lighting-app/nxp/k32w/k32w1$ ninja -C out/debug +``` + +- Step 2: activate local environment + +``` +user@ubuntu:~/Desktop/git/connectedhomeip$ source scripts/activate.sh +``` + +If the script says the environment is out of date, you can update it by running +the following command: + +``` +user@ubuntu:~/Desktop/git/connectedhomeip$ source scripts/bootstrap.sh +``` + +- Step 3: Init NXP SDK(s) + +``` +user@ubuntu:~/Desktop/git/connectedhomeip$ scripts/setup/nxp/update_nxp_sdk.py --platform common_sdk +``` + +Note: By default setup/nxp/update_nxp_sdk.py will try to initialize all NXP +SDKs. Arg "-- help" could be used to view all available options. + +- Start building the application. + +``` +user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/lighting-app/nxp/k32w1 +user@ubuntu:~/Desktop/git/connectedhomeip/examples/lighting-app/nxp/k32w1$ gn gen out/debug +user@ubuntu:~/Desktop/git/connectedhomeip/examples/lighting-app/nxp/k32w1$ ninja -C out/debug ``` In case that Openthread CLI is needed, `chip_with_ot_cli` build argument must be @@ -162,8 +190,8 @@ memory: These instances and global variables are placed in `SMU2` memory through name matching in the application linker script. They should not be changed or, if changed, the names must be updated in `k32w1_app.ld`. See -[k32w1_app.ld](../../../../platform/nxp/k32w/k32w1/app/ldscripts/k32w1_app.ld) -for names and `SMU2` memory range size. +[k32w1_app.ld](../../../platform/nxp/k32w1/app/ldscripts/k32w1_app.ld) for names +and `SMU2` memory range size. The OpenThread buffers can be allocated from a 13KB `SMU2` range after a successful commissioning process until a factory reset is initiated. This way, @@ -171,6 +199,8 @@ the OpenThread buffers will be dynamically allocated instead of statically, freeing some `SRAM`. To enable this feature compile with OpenThread FTD support (`chip_openthread_ftd=true`) and with `use_smu2_dynamic=true`. +`use_smu2_static` and `use_smu2_dynamic` are set to `true` by default. + ### LED PWM In the default configuration, the onboard RGB LED pins are configured as GPIO @@ -180,14 +210,14 @@ this feature, compile the application with: `chip_config_dimmable_led=true` If the feature is enabled, the LED brightness can be controlled using **Level control** cluster -[commands](../../../../../docs/guides/chip_tool_guide.md#step-7-control-application-data-model-clusters). +[commands](../../../../docs/guides/chip_tool_guide.md#step-7-control-application-data-model-clusters). ## Manufacturing data Use `chip_with_factory_data=1` in the gn build command to enable factory data. For a full guide on manufacturing flow, please see -[Guide for writing manufacturing data on NXP devices](../../../../../docs/guides/nxp/nxp_manufacturing_flow.md). +[Guide for writing manufacturing data on NXP devices](../../../../docs/guides/nxp/nxp_manufacturing_flow.md). ## Flashing @@ -250,7 +280,7 @@ One option for debugging would be to use MCUXpresso IDE. - Drag-and-drop the zip file containing the NXP SDK in the "Installed SDKs" tab: -![Installed SDKs](../../../../platform/nxp/k32w/k32w1/doc/images/installed_sdks.jpg) +![Installed SDKs](../../../platform/nxp/k32w1/doc/images/installed_sdks.jpg) - Import any demo application from the installed SDK: @@ -258,7 +288,7 @@ One option for debugging would be to use MCUXpresso IDE. Import SDK example(s).. -> choose a demo app (demo_apps -> hello_world) -> Finish ``` -![Import demo](../../../../platform/nxp/k32w/k32w1/doc/images/import_demo.jpg) +![Import demo](../../../platform/nxp/k32w1/doc/images/import_demo.jpg) - Flash the previously imported demo application on the board: @@ -277,7 +307,7 @@ resulted after ot-nxp compilation. File -> Import -> C/C++ -> Existing Code as Makefile Project ``` -![New Project](../../../../platform/nxp/k32w/k32w1/doc/images/new_project.jpg) +![New Project](../../../platform/nxp/k32w1/doc/images/new_project.jpg) - Replace the path of the existing demo application with the path of the K32W1 application: @@ -286,7 +316,7 @@ File -> Import -> C/C++ -> Existing Code as Makefile Project Run -> Debug Configurations... -> C/C++ Application ``` -![Debug K32W1](../../../../platform/nxp/k32w/k32w1/doc/images/debug_k32w1.jpg) +![Debug K32W1](../../../platform/nxp/k32w1/doc/images/debug_k32w1.jpg) ## OTA @@ -314,16 +344,21 @@ In `OTAP` application In order to build an OTA image, use NXP wrapper over the standard tool `src/app/ota_image_tool.py`: -- `scripts/tools/nxp/factory_data_generator/ota_image_tool.py` The tool can be - used to generate an OTA image with the following format: - `| OTA image header | TLV1 | TLV2 | ... | TLVn |` where each TLV is in the - form `|tag|length|value|` +- `scripts/tools/nxp/factory_data_generator/ota_image_tool.py` + +The tool can be used to generate an OTA image with the following format: + +``` + | OTA image header | TLV1 | TLV2 | ... | TLVn | +``` + +where each TLV is in the form `|tag|length|value|`. Note that "standard" TLV format is used. Matter TLV format is only used for factory data TLV value. Please see more in the -[OTA image tool guide](../../../../../scripts/tools/nxp/ota/README.md). +[OTA image tool guide](../../../../scripts/tools/nxp/ota/README.md). Here is an example that generates an OTA image with application update TLV from a sb3 file: @@ -340,12 +375,24 @@ having a correct OTA process, the OTA header version should be the same as the binary embedded software version. A user can set a custom software version in the gn build args by setting `chip_software_version` to the wanted version. +### OTA factory data + +A user can update the factory data through OTA, at the same time the application +firmware is updated by enabling the following processor in the `gn args`: + +- `chip_enable_ota_factory_data_processor=1` to enable default factory data + update processor (disabled by default). + +The OTA image used must be updated to include the new factory data. + +[OTA image tool guide](../../../../scripts/tools/nxp/ota/README.md). + ### Running OTA The OTA topology used for OTA testing is illustrated in the figure below. Topology is similar with the one used for Matter Test Events. -![OTA_TOPOLOGY](../../../../platform/nxp/k32w/k32w1/doc/images/ota_topology.JPG) +![OTA_TOPOLOGY](../../../platform/nxp/k32w1/doc/images/ota_topology.JPG) The concept for OTA is the next one: @@ -460,10 +507,16 @@ by running: `chip-console --device /dev/tty. -b 115200 -o pw_log.out` The console should already have been installed in the virtual environment. From -the `chip-console`, a user can send specific commands to the device, e.g.: +the `chip-console`, a user can send specific commands to the device. + +For button commands, please run `rpcs.chip.rpc.Button.Event(index)` based on the +table below: + +| index | action | +| ----- | --------------------------------------------- | +| 0 | Start/stop BLE advertising | +| 1 | Factory reset the device | +| 2 | Application specific action (e.g. toggle LED) | +| 3 | Soft reset the device | -- To toggle the LED (`#define LIGHT_BUTTON 2` in `app_config.h`) - `rpcs.chip.rpc.Button.Event(idx=2)` -- To start BLE advertising (`#define BLE_BUTTON 4` in `app_config.h`) - `rpcs.chip.rpc.Button.Event(idx=4)` -- To reboot the device `rpcs.chip.rpc.Device.Reboot()` +To reboot the device, please run `rpcs.chip.rpc.Device.Reboot()`. diff --git a/examples/lighting-app/nxp/k32w/k32w1/args.gni b/examples/lighting-app/nxp/k32w1/args.gni similarity index 74% rename from examples/lighting-app/nxp/k32w/k32w1/args.gni rename to examples/lighting-app/nxp/k32w1/args.gni index d0c28a1e048545..7d5e752aae6934 100644 --- a/examples/lighting-app/nxp/k32w/k32w1/args.gni +++ b/examples/lighting-app/nxp/k32w1/args.gni @@ -13,9 +13,11 @@ # limitations under the License. import("//build_overrides/chip.gni") +import("${chip_root}/config/standalone/args.gni") # SDK target. This is overridden to add our SDK app_config.h & defines. -k32w1_sdk_target = get_label_info(":sdk", "label_no_toolchain") +nxp_sdk_target = get_label_info(":sdk", "label_no_toolchain") +nxp_device = "K32W1480" chip_config_dimmable_led = false chip_enable_ota_requestor = true @@ -27,3 +29,10 @@ is_debug = false chip_crypto = "platform" chip_openthread_ftd = true chip_with_ot_cli = 0 + +chip_system_config_provide_statistics = false +chip_system_config_use_open_thread_inet_endpoints = true +chip_with_lwip = false + +use_smu2_static = false +use_smu2_dynamic = false diff --git a/examples/lighting-app/nxp/k32w1/build_overrides b/examples/lighting-app/nxp/k32w1/build_overrides new file mode 120000 index 00000000000000..ee19c065d619a2 --- /dev/null +++ b/examples/lighting-app/nxp/k32w1/build_overrides @@ -0,0 +1 @@ +../../../build_overrides/ \ No newline at end of file diff --git a/examples/lighting-app/nxp/k32w1/include/config/AppConfig.h b/examples/lighting-app/nxp/k32w1/include/config/AppConfig.h new file mode 100644 index 00000000000000..6dcccf749bbebe --- /dev/null +++ b/examples/lighting-app/nxp/k32w1/include/config/AppConfig.h @@ -0,0 +1,29 @@ +/* + * Copyright 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +/* ---- App Config ---- */ +#define APP_DEVICE_TYPE_ENDPOINT 1 +#define APP_CLUSTER_ATTRIBUTE chip::app::Clusters::OnOff::Attributes::OnOff + +/* ---- Button Manager Config ---- */ +#define BUTTON_MANAGER_FACTORY_RESET_TIMEOUT_MS 6000 + +/* ---- LED Manager Config ---- */ +#define LED_MANAGER_STATUS_LED_INDEX 0 +#define LED_MANAGER_LIGHT_LED_INDEX 1 diff --git a/examples/lighting-app/nxp/k32w/k32w1/include/CHIPProjectConfig.h b/examples/lighting-app/nxp/k32w1/include/config/CHIPProjectConfig.h similarity index 100% rename from examples/lighting-app/nxp/k32w/k32w1/include/CHIPProjectConfig.h rename to examples/lighting-app/nxp/k32w1/include/config/CHIPProjectConfig.h diff --git a/examples/lighting-app/nxp/k32w1/third_party/connectedhomeip b/examples/lighting-app/nxp/k32w1/third_party/connectedhomeip new file mode 120000 index 00000000000000..59307833b4fee9 --- /dev/null +++ b/examples/lighting-app/nxp/k32w1/third_party/connectedhomeip @@ -0,0 +1 @@ +../../../../.. \ No newline at end of file diff --git a/examples/lighting-app/nxp/k32w/k32w1/with_pw_rpc.gni b/examples/lighting-app/nxp/k32w1/with_pw_rpc.gni similarity index 84% rename from examples/lighting-app/nxp/k32w/k32w1/with_pw_rpc.gni rename to examples/lighting-app/nxp/k32w1/with_pw_rpc.gni index d6bea63f8402c0..c2dc1950544640 100644 --- a/examples/lighting-app/nxp/k32w/k32w1/with_pw_rpc.gni +++ b/examples/lighting-app/nxp/k32w1/with_pw_rpc.gni @@ -17,17 +17,21 @@ import("//build_overrides/chip.gni") import("${chip_root}/config/nxp/lib/pw_rpc/pw_rpc.gni") -import("${chip_root}/examples/platform/nxp/k32w/k32w1/args.gni") -k32w1_sdk_target = get_label_info(":sdk", "label_no_toolchain") +nxp_sdk_target = get_label_info(":sdk", "label_no_toolchain") -chip_enable_ota_requestor = true -chip_stack_lock_tracking = "fatal" +chip_crypto = "platform" chip_enable_ble = true +chip_enable_ota_requestor = true chip_enable_pw_rpc = true -chip_with_ot_cli = 0 -is_debug = false chip_openthread_ftd = true -chip_crypto = "platform" +chip_stack_lock_tracking = "fatal" + +chip_system_config_provide_statistics = false +chip_system_config_use_open_thread_inet_endpoints = true + +chip_with_lwip = false +chip_with_ot_cli = 0 cpp_standard = "gnu++17" +is_debug = false diff --git a/examples/lock-app/infineon/psoc6/README.md b/examples/lock-app/infineon/psoc6/README.md index b1e1e1a0e9ac6b..0c8e8eb1e8c781 100644 --- a/examples/lock-app/infineon/psoc6/README.md +++ b/examples/lock-app/infineon/psoc6/README.md @@ -33,10 +33,11 @@ will then join the network. ## Building -- [Modustoolbox Software](https://www.cypress.com/products/modustoolbox) +- Download and install + [Modustoolbox Software v3.2](https://www.infineon.com/modustoolbox) - Refer to `integrations/docker/images/chip-build-infineon/Dockerfile` or - `scripts/examples/gn_psoc6_example.sh` for downloading the Software and + Refer to `integrations/docker/images/stage-2/chip-build-infineon/Dockerfile` + or `scripts/examples/gn_psoc6_example.sh` for downloading the Software and related tools. - Install some additional tools (likely already present for Matter @@ -45,7 +46,7 @@ will then join the network. python3-pip - Supported hardware: - [CY8CKIT-062S2-43012](https://www.cypress.com/CY8CKIT-062S2-43012) + [CY8CKIT-062S2-43012](https://www.infineon.com/CY8CKIT-062S2-43012) * Build the example application: @@ -66,11 +67,12 @@ more instructions_ - Put CY8CKIT-062S2-43012 board on KitProg3 CMSIS-DAP Mode by pressing the `MODE SELECT` button. `KITPROG3 STATUS` LED is ON confirms board is in - proper mode. + proper mode. (Modustoolbox Software needs to be installed) - On the command line: $ cd ~/connectedhomeip + $ export CY_TOOLS_PATHS=/tools_3.2 $ python3 out/infineon-psoc6-lock/chip-psoc6-lock-example.flash.py ## Commissioning and cluster control @@ -116,12 +118,12 @@ commands. These power cycle the BlueTooth hardware and disable BR/EDR mode. ### Cluster control -- After successful commissioning, use the OnOff cluster command to toggle - device between On or Off states. +- After successful commissioning, use the doorlock cluster command to toggle + device between lock or Unlock states. - `$ ./out/debug/chip-tool onoff on 1234 1` + `$ ./out/debug/chip-tool doorlock lock-door 1234 1 --timedInteractionTimeoutMs 100` - `$ ./out/debug/chip-tool onoff off 1234 1` + `$ ./out/debug/chip-tool doorlock unlock-door 1234 1 --timedInteractionTimeoutMs 100` - Cluster OnOff can also be done using the `USER_BTN1` button on the board. This button is configured with `APP_LOCK_BUTTON` in `include/AppConfig.h`. diff --git a/examples/lock-app/lock-common/src/LockManager.cpp b/examples/lock-app/lock-common/src/LockManager.cpp index 8af66051883aa4..cb7011899c9487 100644 --- a/examples/lock-app/lock-common/src/LockManager.cpp +++ b/examples/lock-app/lock-common/src/LockManager.cpp @@ -18,7 +18,6 @@ #include "LockManager.h" -#include #include #include diff --git a/examples/log-source-app/linux/main.cpp b/examples/log-source-app/linux/main.cpp index 20ed1c54b5b215..d39e4431e86525 100644 --- a/examples/log-source-app/linux/main.cpp +++ b/examples/log-source-app/linux/main.cpp @@ -110,7 +110,7 @@ int main(int argc, char * argv[]) // Initialize device attestation config SetDeviceAttestationCredentialsProvider(chip::Credentials::Examples::GetExampleDACProvider()); - CommandHandlerInterfaceRegistry::RegisterCommandHandler(&GetLogProvider()); + CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(&GetLogProvider()); chip::DeviceLayer::PlatformMgr().RunEventLoop(); diff --git a/examples/network-manager-app/linux/tbrm.cpp b/examples/network-manager-app/linux/tbrm.cpp index 908666ee61d8a0..eada060526add7 100644 --- a/examples/network-manager-app/linux/tbrm.cpp +++ b/examples/network-manager-app/linux/tbrm.cpp @@ -94,15 +94,23 @@ class FakeBorderRouterDelegate final : public ThreadBorderRouterManagement::Dele mActivateDatasetCallback = callback; mActivateDatasetSequence = sequenceNum; - DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(3000), CompleteDatasetActivation, this); + DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(1000), ActivateActiveDataset, this); } CHIP_ERROR CommitActiveDataset() override { return CHIP_NO_ERROR; } CHIP_ERROR RevertActiveDataset() override { return CHIP_ERROR_NOT_IMPLEMENTED; } - CHIP_ERROR SetPendingDataset(const Thread::OperationalDataset & pendingDataset) override { return CHIP_ERROR_NOT_IMPLEMENTED; } + + CHIP_ERROR SetPendingDataset(const Thread::OperationalDataset & pendingDataset) override + { + ReturnErrorOnFailure(mPendingDataset.Init(pendingDataset.AsByteSpan())); + uint32_t delayTimerMillis; + ReturnErrorOnFailure(mPendingDataset.GetDelayTimer(delayTimerMillis)); + DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(delayTimerMillis), ActivatePendingDataset, this); + return CHIP_NO_ERROR; + } private: - static void CompleteDatasetActivation(System::Layer *, void * context) + static void ActivateActiveDataset(System::Layer *, void * context) { auto * self = static_cast(context); auto * callback = self->mActivateDatasetCallback; @@ -111,6 +119,18 @@ class FakeBorderRouterDelegate final : public ThreadBorderRouterManagement::Dele callback->OnActivateDatasetComplete(sequenceNum, CHIP_NO_ERROR); } + static void ActivatePendingDataset(System::Layer *, void * context) + { + auto * self = static_cast(context); + self->mActiveDataset.Init(self->mPendingDataset.AsByteSpan()); + self->mPendingDataset.Clear(); + // This could just call MatterReportingAttributeChangeCallback directly + self->mAttributeChangeCallback->ReportAttributeChanged( + ThreadBorderRouterManagement::Attributes::ActiveDatasetTimestamp::Id); + self->mAttributeChangeCallback->ReportAttributeChanged( + ThreadBorderRouterManagement::Attributes::PendingDatasetTimestamp::Id); + } + AttributeChangeCallback * mAttributeChangeCallback; Thread::OperationalDataset mActiveDataset; Thread::OperationalDataset mPendingDataset; diff --git a/examples/network-manager-app/network-manager-common/network-manager-app.matter b/examples/network-manager-app/network-manager-common/network-manager-app.matter index bbd20d46b43d94..627838288db0d1 100644 --- a/examples/network-manager-app/network-manager-common/network-manager-app.matter +++ b/examples/network-manager-app/network-manager-common/network-manager-app.matter @@ -1518,6 +1518,7 @@ provisional cluster ThreadBorderRouterManagement = 1106 { provisional readonly attribute int16u threadVersion = 2; provisional readonly attribute boolean interfaceEnabled = 3; provisional readonly attribute nullable int64u activeDatasetTimestamp = 4; + provisional readonly attribute nullable int64u pendingDatasetTimestamp = 5; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -1879,6 +1880,7 @@ endpoint 1 { callback attribute threadVersion; callback attribute interfaceEnabled; callback attribute activeDatasetTimestamp; + callback attribute pendingDatasetTimestamp; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute eventList; @@ -1890,6 +1892,7 @@ endpoint 1 { handle command GetPendingDatasetRequest; handle command DatasetResponse; handle command SetActiveDatasetRequest; + handle command SetPendingDatasetRequest; } server cluster ThreadNetworkDirectory { diff --git a/examples/network-manager-app/network-manager-common/network-manager-app.zap b/examples/network-manager-app/network-manager-common/network-manager-app.zap index 0a14bcb26d7b03..1d27e3c346f320 100644 --- a/examples/network-manager-app/network-manager-common/network-manager-app.zap +++ b/examples/network-manager-app/network-manager-common/network-manager-app.zap @@ -3407,6 +3407,14 @@ "source": "client", "isIncoming": 1, "isEnabled": 1 + }, + { + "name": "SetPendingDatasetRequest", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 } ], "attributes": [ @@ -3420,7 +3428,7 @@ "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3436,7 +3444,7 @@ "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3452,7 +3460,7 @@ "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3468,7 +3476,7 @@ "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3484,7 +3492,23 @@ "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PendingDatasetTimestamp", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3500,7 +3524,7 @@ "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3516,7 +3540,7 @@ "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3532,7 +3556,7 @@ "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3548,7 +3572,7 @@ "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3564,7 +3588,7 @@ "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, diff --git a/examples/placeholder/linux/apps/app1/config.matter b/examples/placeholder/linux/apps/app1/config.matter index 87b61c8a45357c..b72a4b280351b9 100644 --- a/examples/placeholder/linux/apps/app1/config.matter +++ b/examples/placeholder/linux/apps/app1/config.matter @@ -8236,6 +8236,9 @@ cluster ApplicationLauncher = 1292 { kSuccess = 0; kAppNotAvailable = 1; kSystemBusy = 2; + kPendingUserApproval = 3; + kDownloading = 4; + kInstalling = 5; } bitmap Feature : bitmap32 { @@ -8295,6 +8298,9 @@ cluster ApplicationLauncher = 1292 { kSuccess = 0; kAppNotAvailable = 1; kSystemBusy = 2; + kPendingUserApproval = 3; + kDownloading = 4; + kInstalling = 5; } bitmap Feature : bitmap32 { @@ -9589,7 +9595,7 @@ endpoint 1 { ram attribute physicalContactOccupiedToUnoccupiedDelay default = 0x00; ram attribute physicalContactUnoccupiedToOccupiedDelay default = 0x00; ram attribute physicalContactUnoccupiedToOccupiedThreshold default = 1; - ram attribute featureMap default = 0; + callback attribute featureMap; callback attribute clusterRevision default = 5; } } diff --git a/examples/placeholder/linux/apps/app2/config.matter b/examples/placeholder/linux/apps/app2/config.matter index db46fa85d7e71d..41421c7e917d0e 100644 --- a/examples/placeholder/linux/apps/app2/config.matter +++ b/examples/placeholder/linux/apps/app2/config.matter @@ -8193,6 +8193,9 @@ cluster ApplicationLauncher = 1292 { kSuccess = 0; kAppNotAvailable = 1; kSystemBusy = 2; + kPendingUserApproval = 3; + kDownloading = 4; + kInstalling = 5; } bitmap Feature : bitmap32 { @@ -8252,6 +8255,9 @@ cluster ApplicationLauncher = 1292 { kSuccess = 0; kAppNotAvailable = 1; kSystemBusy = 2; + kPendingUserApproval = 3; + kDownloading = 4; + kInstalling = 5; } bitmap Feature : bitmap32 { @@ -9528,7 +9534,7 @@ endpoint 1 { ram attribute physicalContactOccupiedToUnoccupiedDelay default = 0x00; ram attribute physicalContactUnoccupiedToOccupiedDelay default = 0x00; ram attribute physicalContactUnoccupiedToOccupiedThreshold default = 1; - ram attribute featureMap default = 0; + callback attribute featureMap; callback attribute clusterRevision default = 5; } } diff --git a/examples/placeholder/linux/src/bridged-actions-stub.cpp b/examples/placeholder/linux/src/bridged-actions-stub.cpp index ea6e824738a857..d7abf17cd9106e 100644 --- a/examples/placeholder/linux/src/bridged-actions-stub.cpp +++ b/examples/placeholder/linux/src/bridged-actions-stub.cpp @@ -98,5 +98,5 @@ CHIP_ERROR ActionsAttrAccess::Read(const ConcreteReadAttributePath & aPath, Attr void MatterActionsPluginServerInitCallback(void) { - registerAttributeAccessOverride(&gAttrAccess); + chip::app::AttributeAccessInterfaceRegistry::Instance().Register(&gAttrAccess); } diff --git a/examples/platform/bouffalolab/bl602/lwipopts/lwipopts.h b/examples/platform/bouffalolab/bl602/lwipopts/lwipopts.h index dea0e2e715136d..ba744a119d77e3 100644 --- a/examples/platform/bouffalolab/bl602/lwipopts/lwipopts.h +++ b/examples/platform/bouffalolab/bl602/lwipopts/lwipopts.h @@ -264,7 +264,7 @@ a lot of data that needs to be copied, this should be set high. */ #define LWIP_IPV6_DHCP6 1 #define LWIP_AUTOIP 1 #define LWIP_IPV6_MLD 1 -#define LWIP_ND6_RDNSS_MAX_DNS_SERVERS 1 +#define LWIP_ND6_RDNSS_MAX_DNS_SERVERS 0 #define LWIP_HOOK_FILENAME "bl_lwip_hooks.h" #define LWIP_NETIF_EXT_STATUS_CALLBACK 1 diff --git a/examples/platform/bouffalolab/bl702l/FreeRTOSConfig.h b/examples/platform/bouffalolab/bl702l/FreeRTOSConfig.h index a131725750a742..27b474da904602 100644 --- a/examples/platform/bouffalolab/bl702l/FreeRTOSConfig.h +++ b/examples/platform/bouffalolab/bl702l/FreeRTOSConfig.h @@ -159,9 +159,9 @@ to exclude the API function. */ /* Normal assert() semantics without relying on the provision of an assert.h header file. */ #ifdef __cplusplus -extern "C" void (*vAssertCalled)(void); +extern "C" void vAssertCalled(void); #else -extern void (*vAssertCalled)(void); +extern void vAssertCalled(void); #endif #define configASSERT(x) \ if ((x) == 0) \ @@ -182,9 +182,9 @@ Like all task stack sizes, the value is the number of words, not bytes. */ #if (configUSE_TICKLESS_IDLE != 0) #include "portmacro.h" #ifdef __cplusplus -extern "C" void (*vApplicationSleep)(TickType_t xExpectedIdleTime); +extern "C" void vApplicationSleep(TickType_t xExpectedIdleTime); #else -extern void (*vApplicationSleep)(TickType_t xExpectedIdleTime); +extern void vApplicationSleep(TickType_t xExpectedIdleTime); #endif #define portSUPPRESS_TICKS_AND_SLEEP(xExpectedIdleTime) vApplicationSleep(xExpectedIdleTime) #endif diff --git a/examples/platform/bouffalolab/bl702l/ldscripts/psram_flash_rom.ld b/examples/platform/bouffalolab/bl702l/ldscripts/psram_flash_rom.ld index 9b244b848e56e3..5d74cdb0557a90 100644 --- a/examples/platform/bouffalolab/bl702l/ldscripts/psram_flash_rom.ld +++ b/examples/platform/bouffalolab/bl702l/ldscripts/psram_flash_rom.ld @@ -297,7 +297,4 @@ SECTIONS /* rom driver */ INCLUDE ../../third_party/bouffalolab/repo/components/platform/soc/bl702l/bl702l/evb/ld/romdriver.ld - - /* rom data & code */ - INCLUDE ../../third_party/bouffalolab/repo/components/platform/soc/bl702l/bl702l/evb/ld/rom_map.ld } diff --git a/examples/platform/bouffalolab/common/iot_sdk/platform_port.cpp b/examples/platform/bouffalolab/common/iot_sdk/platform_port.cpp index 32cf15e2ea7cb3..5b18c866ed7c3f 100644 --- a/examples/platform/bouffalolab/common/iot_sdk/platform_port.cpp +++ b/examples/platform/bouffalolab/common/iot_sdk/platform_port.cpp @@ -56,12 +56,6 @@ extern "C" { #elif CHIP_DEVICE_LAYER_TARGET_BL702L #include #endif - -#if CHIP_DEVICE_LAYER_TARGET_BL702L -#include -#include -#include -#endif } #include @@ -85,7 +79,6 @@ extern "C" unsigned int sleep(unsigned int seconds) return 0; } -#if !CHIP_DEVICE_LAYER_TARGET_BL702L extern "C" void vApplicationStackOverflowHook(TaskHandle_t xTask, char * pcTaskName) { printf("Stack Overflow checked. Stack name %s", pcTaskName); @@ -169,9 +162,7 @@ extern "C" void vAssertCalled(void) { void * ra = (void *) __builtin_return_address(0); -#if CONF_ENABLE_FRAME_PTR == 0 taskDISABLE_INTERRUPTS(); -#endif if (xPortIsInsideInterrupt()) { @@ -182,65 +173,14 @@ extern "C" void vAssertCalled(void) printf("vAssertCalled, ra = %p in task %s\r\n", (void *) ra, pcTaskGetName(NULL)); } -#if CONF_ENABLE_FRAME_PTR portABORT(); -#endif while (true) ; } -#endif - -#if CHIP_DEVICE_LAYER_TARGET_BL702L -extern "C" void __attribute__((weak)) user_vAssertCalled(void) -{ - void * ra = (void *) __builtin_return_address(0); - - taskDISABLE_INTERRUPTS(); - if (xPortIsInsideInterrupt()) - { - printf("vAssertCalled, ra = %p in ISR\r\n", (void *) ra); - } - else - { - printf("vAssertCalled, ra = %p in task %s\r\n", (void *) ra, pcTaskGetName(NULL)); - } - - while (true) - ; -} - -extern "C" void __attribute__((weak)) user_vApplicationStackOverflowHook(TaskHandle_t xTask, char * pcTaskName) -{ - puts("Stack Overflow checked\r\n"); - if (pcTaskName) - { - printf("Stack name %s\r\n", pcTaskName); - } - while (1) - { - /*empty here*/ - } -} - -extern "C" void __attribute__((weak)) user_vApplicationMallocFailedHook(void) -{ - printf("Memory Allocate Failed. Current left size is %d bytes\r\n", xPortGetFreeHeapSize()); -#if defined(CFG_USE_PSRAM) - printf("Current psram left size is %d bytes\r\n", xPortGetFreeHeapSizePsram()); -#endif - while (1) - { - /*empty here*/ - } -} - -extern "C" void bflb_assert(void) __attribute__((weak, alias("user_vAssertCalled"))); -#else extern "C" void user_vAssertCalled(void) __attribute__((weak, alias("vAssertCalled"))); extern "C" void bflb_assert(void) __attribute__((weak, alias("vAssertCalled"))); -#endif // ================================================================================ // Main Code @@ -336,16 +276,8 @@ extern "C" void setup_heap() { bl_sys_init(); -#if CHIP_DEVICE_LAYER_TARGET_BL702 - bl_sys_em_config(); -#elif CHIP_DEVICE_LAYER_TARGET_BL702L +#if CHIP_DEVICE_LAYER_TARGET_BL702 || CHIP_DEVICE_LAYER_TARGET_BL702L bl_sys_em_config(); - - // Initialize rom data - extern uint8_t _rom_data_run; - extern uint8_t _rom_data_load; - extern uint8_t _rom_data_size; - memcpy((void *) &_rom_data_run, (void *) &_rom_data_load, (size_t) &_rom_data_size); #endif #if CHIP_DEVICE_LAYER_TARGET_BL702 @@ -376,9 +308,6 @@ extern "C" void app_init(void) #if CHIP_DEVICE_LAYER_TARGET_BL702L bl_flash_init(); - - rom_freertos_init(256, 400); - rom_hal_init(); #endif hosal_uart_init(&uart_stdio); diff --git a/examples/platform/bouffalolab/common/plat/OTAConfig.cpp b/examples/platform/bouffalolab/common/plat/OTAConfig.cpp index b6ca3b621cd747..30bc9d2ea46ac0 100644 --- a/examples/platform/bouffalolab/common/plat/OTAConfig.cpp +++ b/examples/platform/bouffalolab/common/plat/OTAConfig.cpp @@ -20,6 +20,7 @@ #include #include + // Global OTA objects chip::DefaultOTARequestor gRequestorCore; chip::DefaultOTARequestorStorage gRequestorStorage; diff --git a/examples/platform/bouffalolab/common/plat/platform.cpp b/examples/platform/bouffalolab/common/plat/platform.cpp index 329e3eee49f262..6a91567ab9b803 100644 --- a/examples/platform/bouffalolab/common/plat/platform.cpp +++ b/examples/platform/bouffalolab/common/plat/platform.cpp @@ -42,7 +42,7 @@ #include #endif -#if CONFIG_BOUFFALOLAB_FACTORY_DATA_ENABLE || CONFIG_BOUFFALOLAB_FACTORY_DATA_TEST +#if CONFIG_BOUFFALOLAB_FACTORY_DATA_ENABLE #include #endif @@ -87,7 +87,7 @@ chip::app::Clusters::NetworkCommissioning::Instance } #endif -#if CONFIG_BOUFFALOLAB_FACTORY_DATA_ENABLE || CONFIG_BOUFFALOLAB_FACTORY_DATA_TEST +#if CONFIG_BOUFFALOLAB_FACTORY_DATA_ENABLE namespace { FactoryDataProvider sFactoryDataProvider; } @@ -180,7 +180,7 @@ void UnlockOpenThreadTask(void) CHIP_ERROR PlatformManagerImpl::PlatformInit(void) { chip::RendezvousInformationFlags rendezvousMode(chip::RendezvousInformationFlag::kOnNetwork); -#if CONFIG_BOUFFALOLAB_FACTORY_DATA_ENABLE || CONFIG_BOUFFALOLAB_FACTORY_DATA_TEST +#if CONFIG_BOUFFALOLAB_FACTORY_DATA_ENABLE CHIP_ERROR retFactoryData = sFactoryDataProvider.Init(); #endif @@ -213,7 +213,6 @@ CHIP_ERROR PlatformManagerImpl::PlatformInit(void) #else ReturnLogErrorOnFailure(ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_MinimalEndDevice)); #endif - #endif #if CHIP_DEVICE_CONFIG_ENABLE_WIFI @@ -221,7 +220,7 @@ CHIP_ERROR PlatformManagerImpl::PlatformInit(void) #endif // Initialize device attestation config -#if CONFIG_BOUFFALOLAB_FACTORY_DATA_ENABLE || CONFIG_BOUFFALOLAB_FACTORY_DATA_TEST +#if CONFIG_BOUFFALOLAB_FACTORY_DATA_ENABLE if (CHIP_NO_ERROR == retFactoryData) { SetDeviceInstanceInfoProvider(&sFactoryDataProvider); diff --git a/examples/platform/bouffalolab/common/route_hook/bl_route_hook.c b/examples/platform/bouffalolab/common/route_hook/bl_route_hook.c index 68c51bd327e3a2..0da6d1bfb34383 100644 --- a/examples/platform/bouffalolab/common/route_hook/bl_route_hook.c +++ b/examples/platform/bouffalolab/common/route_hook/bl_route_hook.c @@ -8,6 +8,7 @@ #include "lwip/prot/ip6.h" #include "lwip/prot/nd6.h" #include "lwip/raw.h" +#include #include "bl_route_hook.h" #include "bl_route_table.h" @@ -158,17 +159,21 @@ int8_t bl_route_hook_init(void) uint8_t ret = 0; struct netif * lwip_netif = deviceInterface_getNetif(); + LOCK_TCPIP_CORE(); + if (lwip_netif == NULL) { printf("Invalid network interface\r\n"); - return -1; + ret = -1; + goto exit; } for (bl_route_hook_t * iter = s_hooks; iter != NULL; iter++) { if (iter->netif == lwip_netif) { - return 0; + ret = 0; + break; } } @@ -176,7 +181,8 @@ int8_t bl_route_hook_init(void) if (hook == NULL) { printf("Cannot allocate hook\r\n"); - return -1; + ret = -1; + goto exit; } if (mld6_joingroup_netif(lwip_netif, ip_2_ip6(&router_group)) != ERR_OK) @@ -202,5 +208,7 @@ int8_t bl_route_hook_init(void) { free(hook); } + UNLOCK_TCPIP_CORE(); + return ret; } diff --git a/examples/platform/esp32/common/CommonDeviceCallbacks.cpp b/examples/platform/esp32/common/CommonDeviceCallbacks.cpp index 7203a0cd6a92cf..2dfcffef3dece8 100644 --- a/examples/platform/esp32/common/CommonDeviceCallbacks.cpp +++ b/examples/platform/esp32/common/CommonDeviceCallbacks.cpp @@ -84,6 +84,14 @@ void CommonDeviceCallbacks::DeviceEventCallback(const ChipDeviceEvent * event, i // newly selected address. chip::app::DnssdServer::Instance().StartServer(); } + if (event->InterfaceIpAddressChanged.Type == InterfaceIpChangeType::kIpV6_Assigned) + { + appDelegate = DeviceCallbacksDelegate::Instance().GetAppDelegate(); + if (appDelegate != nullptr) + { + appDelegate->OnIPv6ConnectivityEstablished(); + } + } break; } diff --git a/examples/platform/esp32/common/CommonDeviceCallbacks.h b/examples/platform/esp32/common/CommonDeviceCallbacks.h index f76cdc405aa80e..de6770f1ee311d 100644 --- a/examples/platform/esp32/common/CommonDeviceCallbacks.h +++ b/examples/platform/esp32/common/CommonDeviceCallbacks.h @@ -41,6 +41,7 @@ class DeviceCallbacksDelegate virtual void OnIPv4ConnectivityEstablished() {} virtual void OnIPv4ConnectivityLost() {} virtual void OnDnssdInitialized() {} + virtual void OnIPv6ConnectivityEstablished() {} DeviceCallbacksDelegate * mDelegate = nullptr; void SetAppDelegate(DeviceCallbacksDelegate * delegate) { mDelegate = delegate; } DeviceCallbacksDelegate * GetAppDelegate() { return mDelegate; } diff --git a/examples/platform/esp32/common/Esp32AppServer.cpp b/examples/platform/esp32/common/Esp32AppServer.cpp index 8ee5d4d7a05a27..f0e75cfef62e24 100644 --- a/examples/platform/esp32/common/Esp32AppServer.cpp +++ b/examples/platform/esp32/common/Esp32AppServer.cpp @@ -51,7 +51,6 @@ using namespace chip::DeviceLayer; static constexpr char TAG[] = "ESP32Appserver"; namespace { - #if CONFIG_TEST_EVENT_TRIGGER_ENABLED static uint8_t sTestEventTriggerEnableKey[TestEventTriggerDelegate::kEnableKeyLength] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, @@ -103,8 +102,10 @@ static size_t hex_string_to_binary(const char * hex_string, uint8_t * buf, size_ void Esp32AppServer::DeInitBLEIfCommissioned(void) { #ifdef CONFIG_USE_BLE_ONLY_FOR_COMMISSIONING - if (chip::Server::GetInstance().GetFabricTable().FabricCount() > 0) + static bool bleAlreadyShutdown = false; + if (chip::Server::GetInstance().GetFabricTable().FabricCount() > 0 && (!bleAlreadyShutdown)) { + bleAlreadyShutdown = true; chip::DeviceLayer::Internal::BLEMgr().Shutdown(); } #endif /* CONFIG_USE_BLE_ONLY_FOR_COMMISSIONING */ diff --git a/examples/platform/esp32/common/Esp32ThreadInit.cpp b/examples/platform/esp32/common/Esp32ThreadInit.cpp index 6964598649e519..f02f91c06d5538 100644 --- a/examples/platform/esp32/common/Esp32ThreadInit.cpp +++ b/examples/platform/esp32/common/Esp32ThreadInit.cpp @@ -21,6 +21,9 @@ #include #include #endif // CONFIG_OPENTHREAD_ENABLED +#ifdef CONFIG_OPENTHREAD_BORDER_ROUTER +#include +#endif #include #if CONFIG_PM_ENABLE @@ -39,6 +42,18 @@ void ESPOpenThreadInit() .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), }; +#ifdef CONFIG_OPENTHREAD_BORDER_ROUTER + esp_vfs_spiffs_conf_t rcp_fw_conf = { + .base_path = "/rcp_fw", .partition_label = "rcp_fw", .max_files = 10, .format_if_mount_failed = false + }; + if (ESP_OK != esp_vfs_spiffs_register(&rcp_fw_conf)) + { + ESP_LOGE(TAG, "Failed to mount rcp firmware storage"); + return; + } + esp_rcp_update_config_t rcp_update_config = ESP_OPENTHREAD_RCP_UPDATE_CONFIG(); + openthread_init_br_rcp(&rcp_update_config); +#endif // CONFIG_OPENTHREAD_BORDER_ROUTER set_openthread_platform_config(&config); if (ThreadStackMgr().InitThreadStack() != CHIP_NO_ERROR) diff --git a/examples/platform/esp32/common/Esp32ThreadInit.h b/examples/platform/esp32/common/Esp32ThreadInit.h index f6edba24b2b82f..affca51392f65a 100644 --- a/examples/platform/esp32/common/Esp32ThreadInit.h +++ b/examples/platform/esp32/common/Esp32ThreadInit.h @@ -22,10 +22,57 @@ #if CONFIG_OPENTHREAD_ENABLED #include "esp_openthread_types.h" +#if CONFIG_OPENTHREAD_RADIO_NATIVE #define ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG() \ { \ .radio_mode = RADIO_MODE_NATIVE, \ } +#elif CONFIG_OPENTHREAD_RADIO_SPINEL_UART +#define ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG() \ + { \ + .radio_mode = RADIO_MODE_UART_RCP, \ + .radio_uart_config = { \ + .port = UART_NUM_1, \ + .uart_config = \ + { \ + .baud_rate = 460800, \ + .data_bits = UART_DATA_8_BITS, \ + .parity = UART_PARITY_DISABLE, \ + .stop_bits = UART_STOP_BITS_1, \ + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, \ + .rx_flow_ctrl_thresh = 0, \ + .source_clk = UART_SCLK_DEFAULT, \ + }, \ + .rx_pin = GPIO_NUM_17, \ + .tx_pin = GPIO_NUM_18, \ + }, \ + } +#else +#define ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG() \ + { \ + .radio_mode = RADIO_MODE_SPI_RCP, \ + .radio_spi_config = { \ + .host_device = SPI2_HOST, \ + .dma_channel = 2, \ + .spi_interface = \ + { \ + .mosi_io_num = 11, \ + .sclk_io_num = 12, \ + .miso_io_num = 13, \ + }, \ + .spi_device = \ + { \ + .cs_ena_pretrans = 2, \ + .input_delay_ns = 100, \ + .mode = 0, \ + .clock_speed_hz = 2500 * 1000, \ + .spics_io_num = 10, \ + .queue_size = 5, \ + }, \ + .intr_pin = 8, \ + }, \ + } +#endif // CONFIG_OPENTHREAD_RADIO_SPINEL_UART OR CONFIG_OPENTHREAD_RADIO_SPINEL_SPI #define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \ { \ @@ -36,6 +83,18 @@ { \ .storage_partition_name = "nvs", .netif_queue_size = 10, .task_queue_size = 10, \ } + +#ifdef CONFIG_OPENTHREAD_BORDER_ROUTER +#include +#define RCP_FIRMWARE_DIR "/spiffs/ot_rcp" + +#define ESP_OPENTHREAD_RCP_UPDATE_CONFIG() \ + { \ + .rcp_type = RCP_TYPE_ESP32H2_UART, .uart_rx_pin = 17, .uart_tx_pin = 18, .uart_port = 1, .uart_baudrate = 115200, \ + .reset_pin = 7, .boot_pin = 8, .update_baudrate = 460800, .firmware_dir = "/rcp_fw/ot_rcp", .target_chip = ESP32H2_CHIP, \ + } +#endif // CONFIG_OPENTHREAD_BORDER_ROUTER + #endif // CONFIG_OPENTHREAD_ENABLED void ESPOpenThreadInit(); diff --git a/examples/platform/esp32/external_platform/ESP32_custom/BUILD.gn b/examples/platform/esp32/external_platform/ESP32_custom/BUILD.gn index 93b00ef8f81617..d8d2f92b542ac7 100644 --- a/examples/platform/esp32/external_platform/ESP32_custom/BUILD.gn +++ b/examples/platform/esp32/external_platform/ESP32_custom/BUILD.gn @@ -29,7 +29,6 @@ declare_args() { chip_bt_bluedroid_enabled = true chip_max_discovered_ip_addresses = 5 chip_enable_route_hook = false - chip_enable_thread_border_router = false } buildconfig_header("custom_buildconfig") { diff --git a/examples/platform/linux/BUILD.gn b/examples/platform/linux/BUILD.gn index 410b1a189245d2..1fcee183f131b3 100644 --- a/examples/platform/linux/BUILD.gn +++ b/examples/platform/linux/BUILD.gn @@ -93,7 +93,7 @@ source_set("app-main") { "${chip_root}/src/controller:controller", "${chip_root}/src/controller:gen_check_chip_controller_headers", "${chip_root}/src/lib", - "${chip_root}/src/platform/logging:stdio", + "${chip_root}/src/platform/logging:default", ] deps = [ ":ota-test-event-trigger", diff --git a/examples/platform/nxp/Rpc.cpp b/examples/platform/nxp/Rpc.cpp index 262825386ed13c..c0cb0b933f2ac7 100644 --- a/examples/platform/nxp/Rpc.cpp +++ b/examples/platform/nxp/Rpc.cpp @@ -16,7 +16,7 @@ * limitations under the License. */ -#include "AppTask.h" +#include "AppRpc.h" #include "FreeRTOS.h" #include "PigweedLogger.h" #include "PigweedLoggerMutex.h" @@ -43,8 +43,14 @@ #include "pigweed/rpc_services/Locking.h" #endif // defined(PW_RPC_LOCKING_SERVICE) && PW_RPC_LOCKING_SERVICE +#ifndef RPC_TASK_STACK_SIZE #define RPC_TASK_STACK_SIZE 2048 +#endif + +#ifndef RPC_TASK_PRIORITY #define RPC_TASK_PRIORITY 1 +#endif + TaskHandle_t RpcTaskHandle; namespace chip { @@ -56,7 +62,7 @@ class NxpButton final : public Button public: pw::Status Event(const chip_rpc_ButtonEvent & request, pw_protobuf_Empty & response) override { - GetAppTask().ButtonEventHandler(request.idx, request.idx); + chip::NXP::App::Rpc::ButtonHandler(request); return pw::OkStatus(); } }; @@ -77,7 +83,7 @@ class NxpDevice final : public Device static constexpr TickType_t kRebootTimerPeriodTicks = 300; TimerHandle_t mRebootTimer; - static void RebootHandler(TimerHandle_t) { NVIC_SystemReset(); } + static void RebootHandler(TimerHandle_t) { chip::NXP::App::Rpc::Reboot(); } }; #endif // defined(PW_RPC_DEVICE_SERVICE) && PW_RPC_DEVICE_SERVICE diff --git a/examples/platform/nxp/common/app_task/include/AppTaskBase.h b/examples/platform/nxp/common/app_task/include/AppTaskBase.h index 98cec56832b705..76e18df7f47eb0 100644 --- a/examples/platform/nxp/common/app_task/include/AppTaskBase.h +++ b/examples/platform/nxp/common/app_task/include/AppTaskBase.h @@ -27,9 +27,8 @@ #include #include -namespace chip { -namespace NXP { -namespace App { +namespace chip::NXP::App { + class AppTaskBase { public: @@ -97,6 +96,44 @@ class AppTaskBase */ virtual void AppMatter_RegisterCustomCliCommands(void){}; + /** + * \brief Disallow entering low power mode. + * + * This function can be overridden in order to implement a specific disallow mechanism. + * + */ + virtual void AppMatter_DisallowDeviceToSleep(void) {} + + /** + * \brief Allow entering low power mode. + * + * This function can be overridden in order to implement a specific allow mechanism. + * + */ + virtual void AppMatter_AllowDeviceToSleep(void) {} + + /** + * \brief Print onboarding information. + * + * It can be overwritten by derived classes for custom information, + * such as setting the commissioning flow to kUserActionRequired. + * + */ + virtual void PrintOnboardingInfo(); + + /** + * \brief Print current software version string and software version. + * + * It uses the ConfigurationManager API to extract the information. + */ + virtual void PrintCurrentVersion(); + + /** + * \brief Send event to the event queue. + * + */ + virtual void PostEvent(const AppEvent & event){}; + /** * \brief This function could be overridden in order to dispatch event. * @@ -142,6 +179,7 @@ class AppTaskBase private: inline static chip::CommonCaseDeviceServerInitParams initParams; + /* Functions used by the public commisioning handlers */ static void StartCommissioning(intptr_t arg); static void StopCommissioning(intptr_t arg); @@ -154,6 +192,5 @@ class AppTaskBase * Applications can use this to gain access to features of the AppTaskBase. */ extern AppTaskBase & GetAppTask(); -} // namespace App -} // namespace NXP -} // namespace chip + +} // namespace chip::NXP::App diff --git a/examples/platform/nxp/common/app_task/include/AppTaskFreeRTOS.h b/examples/platform/nxp/common/app_task/include/AppTaskFreeRTOS.h index 7ebc4a7430ccaf..0dd5c0d20652a7 100644 --- a/examples/platform/nxp/common/app_task/include/AppTaskFreeRTOS.h +++ b/examples/platform/nxp/common/app_task/include/AppTaskFreeRTOS.h @@ -21,9 +21,8 @@ #include "AppTaskBase.h" -namespace chip { -namespace NXP { -namespace App { +namespace chip::NXP::App { + class AppTaskFreeRTOS : public AppTaskBase { public: @@ -53,7 +52,7 @@ class AppTaskFreeRTOS : public AppTaskBase * \brief Send event to the event queue. * */ - void PostEvent(const AppEvent & event); + void PostEvent(const AppEvent & event) override; /** * \brief Return a pointer to the NXP Wifi Driver instance. @@ -72,9 +71,20 @@ class AppTaskFreeRTOS : public AppTaskBase */ virtual CHIP_ERROR AppMatter_Register(void) override; + /** + * \brief The app event queue handle should be static such that the concrete + * application task can initialize it during Start() call. + */ + QueueHandle_t appEventQueue; + + /** + * \brief This value is used when xQueueReceive is called to specify + * the maximum amount of time the task should block waiting for an event. + * This can be modified according to the application needs. + */ + TickType_t ticksToWait; + private: void DispatchEvent(const AppEvent & event); }; -} // namespace App -} // namespace NXP -} // namespace chip +} // namespace chip::NXP::App diff --git a/examples/platform/nxp/common/app_task/include/AppTaskZephyr.h b/examples/platform/nxp/common/app_task/include/AppTaskZephyr.h index 77cfaa0e468ccf..9a333a768e1f93 100644 --- a/examples/platform/nxp/common/app_task/include/AppTaskZephyr.h +++ b/examples/platform/nxp/common/app_task/include/AppTaskZephyr.h @@ -21,9 +21,8 @@ #include "AppTaskBase.h" -namespace chip { -namespace NXP { -namespace App { +namespace chip::NXP::App { + class AppTaskZephyr : public AppTaskBase { public: @@ -43,7 +42,7 @@ class AppTaskZephyr : public AppTaskBase * \brief Send event to the event queue. * */ - void PostEvent(const AppEvent & event); + void PostEvent(const AppEvent & event) override; /** * \brief Return a pointer to the NXP Wifi Driver instance. @@ -65,6 +64,5 @@ class AppTaskZephyr : public AppTaskBase private: void DispatchEvent(const AppEvent & event); }; -} // namespace App -} // namespace NXP -} // namespace chip + +} // namespace chip::NXP::App diff --git a/examples/platform/nxp/common/app_task/source/AppTaskBase.cpp b/examples/platform/nxp/common/app_task/source/AppTaskBase.cpp index 9ba90e6c146b74..10422121e5c81f 100644 --- a/examples/platform/nxp/common/app_task/source/AppTaskBase.cpp +++ b/examples/platform/nxp/common/app_task/source/AppTaskBase.cpp @@ -26,7 +26,6 @@ #include #include -#include #include #include @@ -37,7 +36,18 @@ #include -#ifdef EMBER_AF_PLUGIN_BINDING +#if defined(MATTER_DM_PLUGIN_USER_LABEL) || defined(MATTER_DM_PLUGIN_FIXED_LABEL) +#ifndef CONFIG_DEVICE_INFO_PROVIDER_IMPL +#define CONFIG_DEVICE_INFO_PROVIDER_IMPL 1 +#endif +#endif + +#if CONFIG_DEVICE_INFO_PROVIDER_IMPL +#include +#endif + +/* Flag generated by Zap */ +#ifdef MATTER_DM_PLUGIN_BINDING #include "binding-handler.h" #endif @@ -50,10 +60,22 @@ #include "TcpDownload.h" #endif +#if CONFIG_OPERATIONAL_KEYSTORE +#include "OperationalKeystore.h" +#endif + #if CONFIG_CHIP_OTA_PROVIDER #include #endif +#if CONFIG_DIAG_LOGS_DEMO +#include "DiagnosticLogsDemo.h" +#endif + +#if CONFIG_LOW_POWER +#include "LowPower.h" +#endif + #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR #include "OTARequestorInitiator.h" #endif @@ -66,6 +88,19 @@ #include #endif +#ifdef SMOKE_CO_ALARM +#include +#include +#endif + +#if CHIP_CONFIG_ENABLE_ICD_SERVER +#include +#endif + +#ifndef CONFIG_THREAD_DEVICE_TYPE +#define CONFIG_THREAD_DEVICE_TYPE kThreadDeviceType_Router +#endif + using namespace chip; using namespace chip::TLV; using namespace ::chip::Credentials; @@ -73,14 +108,16 @@ using namespace ::chip::DeviceLayer; using namespace ::chip::DeviceManager; using namespace ::chip::app::Clusters; +#if CONFIG_DEVICE_INFO_PROVIDER_IMPL chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider; +#endif #if CONFIG_CHIP_WIFI || CHIP_DEVICE_CONFIG_ENABLE_WPA app::Clusters::NetworkCommissioning::Instance sNetworkCommissioningInstance(0, chip::NXP::App::GetAppTask().GetWifiDriverInstance()); #endif -#if CONFIG_CHIP_TEST_EVENT && CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR +#if CHIP_CONFIG_ENABLE_ICD_SERVER || (CONFIG_CHIP_TEST_EVENT && CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR) static uint8_t sTestEventTriggerEnableKey[TestEventTriggerDelegate::kEnableKeyLength] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; @@ -89,12 +126,14 @@ static uint8_t sTestEventTriggerEnableKey[TestEventTriggerDelegate::kEnableKeyLe #if CONFIG_NET_L2_OPENTHREAD void LockOpenThreadTask(void) { + chip::NXP::App::GetAppTask().AppMatter_DisallowDeviceToSleep(); chip::DeviceLayer::ThreadStackMgr().LockThreadStack(); } void UnlockOpenThreadTask(void) { chip::DeviceLayer::ThreadStackMgr().UnlockThreadStack(); + chip::NXP::App::GetAppTask().AppMatter_AllowDeviceToSleep(); } #endif @@ -106,7 +145,26 @@ void chip::NXP::App::AppTaskBase::InitServer(intptr_t arg) static OTATestEventTriggerDelegate testEventTriggerDelegate{ ByteSpan(sTestEventTriggerEnableKey) }; initParams.testEventTriggerDelegate = &testEventTriggerDelegate; #endif + +#ifdef SMOKE_CO_ALARM + static SimpleTestEventTriggerDelegate sTestEventTriggerDelegate{}; + static SmokeCOTestEventTriggerHandler sSmokeCOTestEventTriggerHandler{}; + VerifyOrDie(sTestEventTriggerDelegate.Init(ByteSpan(sTestEventTriggerEnableKey)) == CHIP_NO_ERROR); + VerifyOrDie(sTestEventTriggerDelegate.AddHandler(&sSmokeCOTestEventTriggerHandler) == CHIP_NO_ERROR); + initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; +#endif + +#if CHIP_CONFIG_ENABLE_ICD_SERVER + static SimpleTestEventTriggerDelegate sTestEventTriggerDelegate{}; + VerifyOrDie(sTestEventTriggerDelegate.Init(ByteSpan(sTestEventTriggerEnableKey)) == CHIP_NO_ERROR); + initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; +#endif + +#if CONFIG_OPERATIONAL_KEYSTORE + initParams.operationalKeystore = chip::NXP::App::OperationalKeystore::GetInstance(); +#endif (void) initParams.InitializeStaticResourcesBeforeServerInit(); + #if CONFIG_NET_L2_OPENTHREAD // Init ZCL Data Model and start server chip::Inet::EndPointStateOpenThread::OpenThreadEndpointInitParam nativeParams; @@ -117,12 +175,22 @@ void chip::NXP::App::AppTaskBase::InitServer(intptr_t arg) #endif VerifyOrDie((chip::Server::GetInstance().Init(initParams)) == CHIP_NO_ERROR); + auto * persistentStorage = &Server::GetInstance().GetPersistentStorage(); +#if CONFIG_OPERATIONAL_KEYSTORE + chip::NXP::App::OperationalKeystore::Init(persistentStorage); +#endif - gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); +#if CONFIG_DEVICE_INFO_PROVIDER_IMPL + gExampleDeviceInfoProvider.SetStorageDelegate(persistentStorage); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); +#endif GetAppTask().PostInitMatterServerInstance(); +#if CONFIG_DIAG_LOGS_DEMO + chip::NXP::App::DiagnosticLogsDemo::DisplayUsage(); +#endif + #if CONFIG_CHIP_OTA_PROVIDER InitOTAServer(); #endif @@ -135,6 +203,10 @@ CHIP_ERROR chip::NXP::App::AppTaskBase::Init() /* Init Chip memory management before the stack */ chip::Platform::MemoryInit(); +#if CONFIG_LOW_POWER + chip::NXP::App::LowPower::Init(); +#endif + /* Initialize Matter factory data before initializing the Matter stack */ err = AppFactoryData_PreMatterStackInit(); @@ -187,7 +259,7 @@ CHIP_ERROR chip::NXP::App::AppTaskBase::Init() return err; } - err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_Router); + err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::CONFIG_THREAD_DEVICE_TYPE); if (err != CHIP_NO_ERROR) { return err; @@ -200,7 +272,8 @@ CHIP_ERROR chip::NXP::App::AppTaskBase::Init() */ PlatformMgr().ScheduleWork(InitServer, 0); -#ifdef EMBER_AF_PLUGIN_BINDING +/* Flag generated by Zap */ +#ifdef MATTER_DM_PLUGIN_BINDING /* Init binding handlers */ err = InitBindingHandlers(); if (err != CHIP_NO_ERROR) @@ -227,11 +300,9 @@ CHIP_ERROR chip::NXP::App::AppTaskBase::Init() ConfigurationMgr().LogDeviceConfig(); // QR code will be used with CHIP Tool -#if CONFIG_NETWORK_LAYER_BLE - PrintOnboardingCodes(chip::RendezvousInformationFlag(chip::RendezvousInformationFlag::kBLE)); -#else - PrintOnboardingCodes(chip::RendezvousInformationFlag(chip::RendezvousInformationFlag::kOnNetwork)); -#endif /* CONFIG_NETWORK_LAYER_BLE */ + PrintOnboardingInfo(); + + PrintCurrentVersion(); /* Start a task to run the CHIP Device event loop. */ err = PlatformMgr().StartEventLoopTask(); @@ -333,3 +404,37 @@ void chip::NXP::App::AppTaskBase::FactoryResetHandler(void) chip::Server::GetInstance().GenerateShutDownEvent(); chip::Server::GetInstance().ScheduleFactoryReset(); } + +void chip::NXP::App::AppTaskBase::PrintOnboardingInfo() +{ +#if CONFIG_NETWORK_LAYER_BLE + auto flags = chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE); +#else + auto flags = chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kOnNetwork); +#endif /* CONFIG_NETWORK_LAYER_BLE */ + + chip::PayloadContents payload; + CHIP_ERROR err = GetPayloadContents(payload, flags); + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "GetPayloadContents() failed: %" CHIP_ERROR_FORMAT, err.Format()); + } +#if CONFIG_USER_ACTION_REQUIRED + payload.commissioningFlow = chip::CommissioningFlow::kUserActionRequired; +#endif + PrintOnboardingCodes(payload); +} + +void chip::NXP::App::AppTaskBase::PrintCurrentVersion() +{ + // Print the current software version + char currentSoftwareVer[ConfigurationManager::kMaxSoftwareVersionStringLength + 1] = { 0 }; + auto err = ConfigurationMgr().GetSoftwareVersionString(currentSoftwareVer, sizeof(currentSoftwareVer)); + ReturnOnFailure(err); + + uint32_t currentVersion; + err = ConfigurationMgr().GetSoftwareVersion(currentVersion); + ReturnOnFailure(err); + + ChipLogProgress(DeviceLayer, "Current Software Version: %s, %d", currentSoftwareVer, static_cast(currentVersion)); +} diff --git a/examples/platform/nxp/common/app_task/source/AppTaskFreeRTOS.cpp b/examples/platform/nxp/common/app_task/source/AppTaskFreeRTOS.cpp index c48894ed6467cf..5b8e3eab70be40 100644 --- a/examples/platform/nxp/common/app_task/source/AppTaskFreeRTOS.cpp +++ b/examples/platform/nxp/common/app_task/source/AppTaskFreeRTOS.cpp @@ -34,6 +34,14 @@ #include "AppCLIBase.h" #endif +#if CONFIG_ENABLE_FEEDBACK +#include "UserInterfaceFeedback.h" +#endif + +#if CONFIG_ENABLE_PW_RPC +#include "AppRpc.h" +#endif + #include #include @@ -45,12 +53,18 @@ #ifndef APP_TASK_STACK_SIZE #define APP_TASK_STACK_SIZE ((configSTACK_DEPTH_TYPE) 6144 / sizeof(portSTACK_TYPE)) #endif + #ifndef APP_TASK_PRIORITY #define APP_TASK_PRIORITY 2 #endif + +#ifndef APP_EVENT_QUEUE_SIZE #define APP_EVENT_QUEUE_SIZE 10 +#endif -static QueueHandle_t sAppEventQueue; +#ifndef APP_QUEUE_TICKS_TO_WAIT +#define APP_QUEUE_TICKS_TO_WAIT portMAX_DELAY +#endif using namespace chip; using namespace chip::TLV; @@ -71,12 +85,18 @@ chip::DeviceLayer::NetworkCommissioning::WiFiDriver * chip::NXP::App::AppTaskFre CHIP_ERROR chip::NXP::App::AppTaskFreeRTOS::AppMatter_Register() { CHIP_ERROR err = CHIP_NO_ERROR; + /* Register Matter CLI cmds */ #ifdef ENABLE_CHIP_SHELL err = chip::NXP::App::GetAppCLI().Init(); VerifyOrReturnError(err == CHIP_NO_ERROR, err, ChipLogError(DeviceLayer, "Error during CLI init")); AppMatter_RegisterCustomCliCommands(); #endif + +#if CONFIG_ENABLE_FEEDBACK + FeedbackMgr().Init(); +#endif + /* Register Matter buttons */ err = AppMatterButton_registerButtons(); if (err != CHIP_NO_ERROR) @@ -92,14 +112,30 @@ CHIP_ERROR chip::NXP::App::AppTaskFreeRTOS::Start() CHIP_ERROR err = CHIP_NO_ERROR; TaskHandle_t taskHandle; - sAppEventQueue = xQueueCreate(APP_EVENT_QUEUE_SIZE, sizeof(AppEvent)); - if (sAppEventQueue == NULL) +#if CONFIG_ENABLE_PW_RPC + chip::NXP::App::Rpc::Init(); +#endif + + appEventQueue = xQueueCreate(APP_EVENT_QUEUE_SIZE, sizeof(AppEvent)); + if (appEventQueue == NULL) { err = CHIP_ERROR_NO_MEMORY; ChipLogError(DeviceLayer, "Failed to allocate app event queue"); assert(err == CHIP_NO_ERROR); } + ticksToWait = APP_QUEUE_TICKS_TO_WAIT; + +#if FSL_OSA_MAIN_FUNC_ENABLE + /* When OSA is used, this code will be called from within the startup_task + * and the scheduler will be started at this point. Just call AppTaskMain to + * start the main loop instead of creating a task, since we are already in it. + * Task parameters are configured through SDK flags: + * - gMainThreadPriority_c + * - gMainThreadStackSize_c + */ + AppTaskFreeRTOS::AppTaskMain(this); +#else /* AppTaskMain function will loss actual object instance, give it as parameter */ if (xTaskCreate(&AppTaskFreeRTOS::AppTaskMain, "AppTaskMain", APP_TASK_STACK_SIZE, this, APP_TASK_PRIORITY, &taskHandle) != pdPASS) @@ -108,6 +144,7 @@ CHIP_ERROR chip::NXP::App::AppTaskFreeRTOS::Start() ChipLogError(DeviceLayer, "Failed to start app task"); assert(err == CHIP_NO_ERROR); } +#endif // FSL_OSA_TASK_ENABLE return err; } @@ -122,31 +159,43 @@ void chip::NXP::App::AppTaskFreeRTOS::AppTaskMain(void * pvParameter) sAppTask->PreInitMatterStack(); err = sAppTask->Init(); + VerifyOrDieWithMsg(err == CHIP_NO_ERROR, DeviceLayer, "AppTask.Init() failed"); sAppTask->PostInitMatterStack(); - if (err != CHIP_NO_ERROR) - { - ChipLogError(DeviceLayer, "AppTask.Init() failed"); - assert(err == CHIP_NO_ERROR); - } while (true) { - BaseType_t eventReceived = xQueueReceive(sAppEventQueue, &event, portMAX_DELAY); + BaseType_t eventReceived = xQueueReceive(sAppTask->appEventQueue, &event, sAppTask->ticksToWait); while (eventReceived == pdTRUE) { sAppTask->DispatchEvent(event); - eventReceived = xQueueReceive(sAppEventQueue, &event, 0); + eventReceived = xQueueReceive(sAppTask->appEventQueue, &event, 0); } +#if CONFIG_ENABLE_FEEDBACK + FeedbackMgr().DisplayInLoop(); +#endif } } void chip::NXP::App::AppTaskFreeRTOS::PostEvent(const AppEvent & event) { - if (sAppEventQueue != NULL) + if (appEventQueue != NULL) { - if (!xQueueSend(sAppEventQueue, &event, 0)) + if (__get_IPSR()) + { + portBASE_TYPE taskToWake = pdFALSE; + if (!xQueueSendToFrontFromISR(appEventQueue, &event, &taskToWake)) + { + ChipLogError(DeviceLayer, "Failed to post event to app task event queue from ISR"); + } + + portYIELD_FROM_ISR(taskToWake); + } + else { - ChipLogError(DeviceLayer, "Failed to post event to app task event queue"); + if (!xQueueSend(appEventQueue, &event, 0)) + { + ChipLogError(DeviceLayer, "Failed to post event to app task event queue"); + } } } } diff --git a/examples/platform/nxp/common/clusters/include/Identify.h b/examples/platform/nxp/common/clusters/include/Identify.h new file mode 100644 index 00000000000000..a742e3808791bc --- /dev/null +++ b/examples/platform/nxp/common/clusters/include/Identify.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +namespace chip::NXP::App { + +// Identify cluster callbacks. +void OnIdentifyStart(Identify * identify); +void OnIdentifyStop(Identify * identify); +void OnTriggerEffect(Identify * identify); +void OnTriggerEffectComplete(chip::System::Layer * systemLayer, void * appState); + +} // namespace chip::NXP::App diff --git a/examples/platform/nxp/common/clusters/source/ZclCallbacks.cpp b/examples/platform/nxp/common/clusters/source/ZclCallbacks.cpp new file mode 100644 index 00000000000000..99329a818cc68c --- /dev/null +++ b/examples/platform/nxp/common/clusters/source/ZclCallbacks.cpp @@ -0,0 +1,52 @@ +/* + * + * Copyright (c) 2021-2023 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CHIPDeviceManager.h" + +#include + +#if CONFIG_DIAG_LOGS_DEMO +#include "DiagnosticLogsProviderDelegateImpl.h" +#include +#endif + +void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & path, uint8_t type, uint16_t size, uint8_t * value) +{ + chip::DeviceManager::CHIPDeviceManagerCallbacks * cb = + chip::DeviceManager::CHIPDeviceManager::GetInstance().GetCHIPDeviceManagerCallbacks(); + if (cb != nullptr) + { + // propagate event to device manager + cb->PostAttributeChangeCallback(path.mEndpointId, path.mClusterId, path.mAttributeId, type, size, value); + } +} + +#if CONFIG_DIAG_LOGS_DEMO +/** @brief DiagnosticLogs Cluster Init + * + * This function is called when a specific cluster is initialized. It gives the + * application an opportunity to take care of cluster initialization procedures. + * It is called exactly once for each endpoint where cluster is present. + */ +void emberAfDiagnosticLogsClusterInitCallback(chip::EndpointId endpoint) +{ + auto & logProvider = chip::app::Clusters::DiagnosticLogs::LogProvider::GetInstance(); + auto & server = chip::app::Clusters::DiagnosticLogs::DiagnosticLogsServer::Instance(); + server.SetDiagnosticLogsProviderDelegate(endpoint, &logProvider); +} +#endif diff --git a/examples/platform/nxp/common/device_callbacks/source/CommonDeviceCallbacks.cpp b/examples/platform/nxp/common/device_callbacks/source/CommonDeviceCallbacks.cpp index d38d6f59f8c572..bc7a8dca431c42 100644 --- a/examples/platform/nxp/common/device_callbacks/source/CommonDeviceCallbacks.cpp +++ b/examples/platform/nxp/common/device_callbacks/source/CommonDeviceCallbacks.cpp @@ -33,7 +33,6 @@ #include #if CHIP_ENABLE_OPENTHREAD && CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED #include "openthread-system.h" -#include "ot_platform_common.h" #endif /* CHIP_ENABLE_OPENTHREAD && CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED */ #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR diff --git a/examples/platform/nxp/common/diagnostic_logs/include/DiagnosticLogsDemo.h b/examples/platform/nxp/common/diagnostic_logs/include/DiagnosticLogsDemo.h new file mode 100644 index 00000000000000..e801837e09a04b --- /dev/null +++ b/examples/platform/nxp/common/diagnostic_logs/include/DiagnosticLogsDemo.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +namespace chip::NXP::App::DiagnosticLogsDemo { + +/** + * @brief Display a demo usage of the diagnostic logs provider. + * + */ +CHIP_ERROR DisplayUsage(); + +} // namespace chip::NXP::App::DiagnosticLogsDemo diff --git a/examples/platform/nxp/common/diagnostic_logs/DiagnosticLogsProviderDelegateImpl.h b/examples/platform/nxp/common/diagnostic_logs/include/DiagnosticLogsProviderDelegateImpl.h similarity index 100% rename from examples/platform/nxp/common/diagnostic_logs/DiagnosticLogsProviderDelegateImpl.h rename to examples/platform/nxp/common/diagnostic_logs/include/DiagnosticLogsProviderDelegateImpl.h diff --git a/examples/platform/nxp/common/diagnostic_logs/source/DiagnosticLogsDemo.cpp b/examples/platform/nxp/common/diagnostic_logs/source/DiagnosticLogsDemo.cpp new file mode 100644 index 00000000000000..359952609352f0 --- /dev/null +++ b/examples/platform/nxp/common/diagnostic_logs/source/DiagnosticLogsDemo.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "DiagnosticLogsDemo.h" +#include "DiagnosticLogsProviderDelegateImpl.h" + +#include + +CHIP_ERROR chip::NXP::App::DiagnosticLogsDemo::DisplayUsage() +{ + char diagLog[CHIP_DEVICE_CONFIG_MAX_DIAG_LOG_SIZE]; + uint16_t diagLogSize = CHIP_DEVICE_CONFIG_MAX_DIAG_LOG_SIZE; + + chip::StorageKeyName keyUser = chip::app::Clusters::DiagnosticLogs::LogProvider::GetKeyDiagUserSupport(); + chip::StorageKeyName keyNwk = chip::app::Clusters::DiagnosticLogs::LogProvider::GetKeyDiagNetwork(); + chip::StorageKeyName keyCrash = chip::app::Clusters::DiagnosticLogs::LogProvider::GetKeyDiagCrashLog(); + + auto & persistentStorage = chip::Server::GetInstance().GetPersistentStorage(); + /* The KVS wear stats are stored in the user diagnostic log key hence only + * initialize this key if the KVS wear stats are not enabled. */ +#if (CHIP_DEVICE_CONFIG_KVS_WEAR_STATS != 1) + memset(diagLog, 0, diagLogSize); + persistentStorage.SyncSetKeyValue(keyUser.KeyName(), diagLog, diagLogSize); +#endif + + memset(diagLog, 1, diagLogSize); + persistentStorage.SyncSetKeyValue(keyNwk.KeyName(), diagLog, diagLogSize); + + memset(diagLog, 2, diagLogSize); + persistentStorage.SyncSetKeyValue(keyCrash.KeyName(), diagLog, diagLogSize); + + return CHIP_NO_ERROR; +} diff --git a/examples/platform/nxp/common/diagnostic_logs/DiagnosticLogsProviderDelegateImpl.cpp b/examples/platform/nxp/common/diagnostic_logs/source/DiagnosticLogsProviderDelegateImpl.cpp similarity index 98% rename from examples/platform/nxp/common/diagnostic_logs/DiagnosticLogsProviderDelegateImpl.cpp rename to examples/platform/nxp/common/diagnostic_logs/source/DiagnosticLogsProviderDelegateImpl.cpp index 359edc3dedc9a6..929905afad828f 100644 --- a/examples/platform/nxp/common/diagnostic_logs/DiagnosticLogsProviderDelegateImpl.cpp +++ b/examples/platform/nxp/common/diagnostic_logs/source/DiagnosticLogsProviderDelegateImpl.cpp @@ -142,7 +142,7 @@ size_t LogProvider::GetSizeForIntent(IntentEnum intent) VerifyOrReturnValue(buffer.Get() != nullptr, 0); err = Server::GetInstance().GetPersistentStorage().SyncGetKeyValue(key.KeyName(), buffer.Get(), sizeForIntent); - VerifyOrReturnValue(err == CHIP_NO_ERROR, 0); + VerifyOrReturnValue(err == CHIP_ERROR_BUFFER_TOO_SMALL, 0); return sizeForIntent; } diff --git a/examples/platform/nxp/common/factory_data/source/AppFactoryDataDefaultImpl.cpp b/examples/platform/nxp/common/factory_data/source/AppFactoryDataDefaultImpl.cpp index 4fd176075f00d2..c1b85604226677 100644 --- a/examples/platform/nxp/common/factory_data/source/AppFactoryDataDefaultImpl.cpp +++ b/examples/platform/nxp/common/factory_data/source/AppFactoryDataDefaultImpl.cpp @@ -24,7 +24,10 @@ #include #if CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA -#include "FactoryDataProvider.h" +#ifndef EXTERNAL_FACTORY_DATA_PROVIDER_HEADER +#define EXTERNAL_FACTORY_DATA_PROVIDER_HEADER "platform/nxp/common/factory_data/FactoryDataProvider.h" +#endif +#include EXTERNAL_FACTORY_DATA_PROVIDER_HEADER #if CONFIG_CHIP_ENCRYPTED_FACTORY_DATA /* * Test key used to encrypt factory data before storing it to the flash. @@ -64,7 +67,7 @@ CHIP_ERROR chip::NXP::App::AppFactoryData_PostMatterStackInit(void) FactoryDataPrvdImpl().SetAes128Key(&aes128TestKey[0]); #endif /* CONFIG_CHIP_ENCRYPTED_FACTORY_DATA */ - ReturnErrorOnFailure(FactoryDataPrvdImpl().Init()); + ReturnErrorOnFailure(FactoryDataPrvd().Init()); SetDeviceInstanceInfoProvider(&FactoryDataPrvd()); SetDeviceAttestationCredentialsProvider(&FactoryDataPrvd()); diff --git a/examples/platform/nxp/common/led_widget/include/LedDimmer.h b/examples/platform/nxp/common/led_widget/include/LedDimmer.h new file mode 100644 index 00000000000000..83632738baf769 --- /dev/null +++ b/examples/platform/nxp/common/led_widget/include/LedDimmer.h @@ -0,0 +1,37 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "LedWidgetInterface.h" + +namespace chip::NXP::App { + +/** + * @brief + * A class that manages dimmer LED operations. + */ +class LedDimmer : public LedWidgetInterface +{ +public: + void Init(uint8_t index = 0, bool inverted = false) override; + void Set(uint8_t level = 0) override; + void Animate(uint32_t onTimeMS = 0, uint32_t offTimeMS = 0) override {} +}; + +} // namespace chip::NXP::App diff --git a/examples/platform/nxp/common/led_widget/include/LedOnOff.h b/examples/platform/nxp/common/led_widget/include/LedOnOff.h new file mode 100644 index 00000000000000..128bbb89aaa3cd --- /dev/null +++ b/examples/platform/nxp/common/led_widget/include/LedOnOff.h @@ -0,0 +1,47 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "LedWidgetInterface.h" + +namespace chip::NXP::App { + +/** + * @brief + * A base class that manages an on-off LED on a board. + */ +class LedOnOff : public LedWidgetInterface +{ +public: + void Init(uint8_t index = 0, bool inverted = 0) override; + void Set(uint8_t level = 0) override; + void Animate(uint32_t onTimeMS = 0, uint32_t offTimeMS = 0) override; + +private: + uint64_t mLastChangeTimeMS = 0; + uint32_t mOnTimeMS = 0; + uint32_t mOffTimeMS = 0; + uint8_t mIndex = 0; + + bool mOnLogic = true; + + void DoSet(bool state); +}; + +} // namespace chip::NXP::App diff --git a/examples/platform/nxp/k32w/k32w1/util/include/LEDWidget.h b/examples/platform/nxp/common/led_widget/include/LedWidgetInterface.h similarity index 55% rename from examples/platform/nxp/k32w/k32w1/util/include/LEDWidget.h rename to examples/platform/nxp/common/led_widget/include/LedWidgetInterface.h index a73ab8a904018b..155da65eea9d06 100644 --- a/examples/platform/nxp/k32w/k32w1/util/include/LEDWidget.h +++ b/examples/platform/nxp/common/led_widget/include/LedWidgetInterface.h @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2020 Google LLC. + * Copyright (c) 2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,28 +16,29 @@ * limitations under the License. */ -// #include "LED.h" -#include "EmbeddedTypes.h" #pragma once -class LEDWidget +#include "EmbeddedTypes.h" + +namespace chip::NXP::App { + +/** + * @brief + * An interface that defines LED operations. + */ +class LedWidgetInterface { public: - void Init(uint8_t gpioNum, bool inverted); - void Set(bool state); - void SetLevel(uint8_t level); - void Invert(void); - void Blink(uint32_t changeRateMS); - void Blink(uint32_t onTimeMS, uint32_t offTimeMS); - void Animate(); - -private: - uint64_t mLastChangeTimeMS; - uint32_t mBlinkOnTimeMS; - uint32_t mBlinkOffTimeMS; - uint8_t mGPIONum; - bool mState; - bool mOnLogic; - - void DoSet(bool state); + virtual ~LedWidgetInterface() {} + + virtual void Init(uint8_t index = 0, bool inverted = false) = 0; + virtual void Set(uint8_t level = 0) = 0; + virtual void Animate(uint32_t onTimeMS = 0, uint32_t offTimeMS = 0) = 0; + + bool IsTurnedOff() { return !mState; } + +protected: + bool mState = false; }; + +} // namespace chip::NXP::App diff --git a/examples/platform/nxp/common/low_power/include/LowPower.h b/examples/platform/nxp/common/low_power/include/LowPower.h new file mode 100644 index 00000000000000..fc2bdd8ff0fcfd --- /dev/null +++ b/examples/platform/nxp/common/low_power/include/LowPower.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +namespace chip::NXP::App::LowPower { + +/** + * @brief Low-power related init function. + * + * For example, it can be used to register an enter/exit low power callback. + * + */ +CHIP_ERROR Init(); + +} // namespace chip::NXP::App::LowPower diff --git a/examples/platform/nxp/common/low_power/source/LowPower.cpp b/examples/platform/nxp/common/low_power/source/LowPower.cpp new file mode 100644 index 00000000000000..9b5afd19b18bf8 --- /dev/null +++ b/examples/platform/nxp/common/low_power/source/LowPower.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "LowPower.h" +#include "fsl_pm_core.h" + +#include + +#define APP_ERROR_PM_REGISTER_LP_CALLBACK_FAILED CHIP_APPLICATION_ERROR(0x01) + +static status_t LowPowerCallback(pm_event_type_t type, uint8_t state, void * data); + +static pm_notify_element_t appNotifyElement = { + .notifyCallback = LowPowerCallback, + .data = NULL, +}; + +static status_t LowPowerCallback(pm_event_type_t type, uint8_t state, void * data) +{ + // This is just an example. It does nothing by default. + return kStatus_Success; +} + +namespace chip::NXP::App::LowPower { + +CHIP_ERROR Init() +{ + status_t status = PM_RegisterNotify(kPM_NotifyGroup2, &appNotifyElement); + VerifyOrReturnError(status == kStatus_Success, APP_ERROR_PM_REGISTER_LP_CALLBACK_FAILED); + + return CHIP_NO_ERROR; +} + +} // namespace chip::NXP::App::LowPower diff --git a/examples/platform/nxp/common/operational_keystore/include/OperationalKeystore.h b/examples/platform/nxp/common/operational_keystore/include/OperationalKeystore.h new file mode 100644 index 00000000000000..4bb3582fc63de0 --- /dev/null +++ b/examples/platform/nxp/common/operational_keystore/include/OperationalKeystore.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +namespace chip::NXP::App::OperationalKeystore { + +/** + * @brief Getter for operational keystore instance. + * + * It can be overwritten to return an instance of a dervied keystore implementation. + * + */ +chip::Crypto::OperationalKeystore * GetInstance(); + +/** + * @brief Initialization entry for specific operational keystore actions. + * + * For example, it can be overwritten to register a persistent storage delegate. + * + */ +CHIP_ERROR Init(PersistentStorageDelegate * delegate); + +} // namespace chip::NXP::App::OperationalKeystore diff --git a/examples/platform/nxp/common/operational_keystore/source/OperationalKeystoreEmpty.cpp b/examples/platform/nxp/common/operational_keystore/source/OperationalKeystoreEmpty.cpp new file mode 100644 index 00000000000000..6d69720bc060c0 --- /dev/null +++ b/examples/platform/nxp/common/operational_keystore/source/OperationalKeystoreEmpty.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "OperationalKeystore.h" + +chip::Crypto::OperationalKeystore * chip::NXP::App::OperationalKeystore::GetInstance() +{ + // Default implementation returns a null pointer. + // Applications that have a specific operational keystore defined should implement + // this function and return a pointer to that instance. + return nullptr; +} + +CHIP_ERROR chip::NXP::App::OperationalKeystore::Init(PersistentStorageDelegate * delegate) +{ + return CHIP_NO_ERROR; +} diff --git a/examples/platform/nxp/common/ota_requestor/source/OTARequestorInitiatorMultiImage.cpp b/examples/platform/nxp/common/ota_requestor/source/OTARequestorInitiatorMultiImage.cpp new file mode 100644 index 00000000000000..527b416a86a4e4 --- /dev/null +++ b/examples/platform/nxp/common/ota_requestor/source/OTARequestorInitiatorMultiImage.cpp @@ -0,0 +1,43 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "OTARequestorInitiator.h" + +using namespace chip; + +constexpr uint16_t requestedOtaBlockSize = 1024; + +void chip::NXP::App::OTARequestorInitiator::InitOTA(intptr_t context) +{ + auto * otaRequestorInit = reinterpret_cast(context); + // Set the global instance of the OTA requestor core component + SetRequestorInstance(&otaRequestorInit->gRequestorCore); + + otaRequestorInit->gRequestorStorage.Init(chip::Server::GetInstance().GetPersistentStorage()); + otaRequestorInit->gRequestorCore.Init(chip::Server::GetInstance(), otaRequestorInit->gRequestorStorage, + otaRequestorInit->gRequestorUser, otaRequestorInit->gDownloader); + otaRequestorInit->gRequestorUser.SetMaxDownloadBlockSize(requestedOtaBlockSize); + + auto & imageProcessor = OTAImageProcessorImpl::GetDefaultInstance(); + otaRequestorInit->gRequestorUser.Init(&otaRequestorInit->gRequestorCore, &imageProcessor); + imageProcessor.Init(&otaRequestorInit->gDownloader); + // Set the image processor instance used for handling image being downloaded + otaRequestorInit->gDownloader.SetImageProcessorDelegate(&imageProcessor); +} + +void chip::NXP::App::OTARequestorInitiator::HandleSelfTest() {} diff --git a/examples/platform/nxp/common/rpc/include/AppRpc.h b/examples/platform/nxp/common/rpc/include/AppRpc.h new file mode 100644 index 00000000000000..9e56a8b80d0b00 --- /dev/null +++ b/examples/platform/nxp/common/rpc/include/AppRpc.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#if defined(PW_RPC_BUTTON_SERVICE) && PW_RPC_BUTTON_SERVICE +#include "pigweed/rpc_services/Button.h" +#endif + +namespace chip::NXP::App::Rpc { + +/** + * @brief Initialization of RPC-related board code. + * + * For example, enabling clock for UART interface + * and initializing board pins. + * + */ +CHIP_ERROR Init(); + +#if defined(PW_RPC_DEVICE_SERVICE) && PW_RPC_DEVICE_SERVICE +/** + * @brief Rebooting the device. + * + * RPC implementation will delegate reboot procedure to this function. + * + */ +void Reboot(); +#endif + +#if defined(PW_RPC_BUTTON_SERVICE) && PW_RPC_BUTTON_SERVICE +/** + * @brief Handles button events. + * + * RPC implementation will delegate handling events to this function. + */ +void ButtonHandler(const chip_rpc_ButtonEvent & request); +#endif + +} // namespace chip::NXP::App::Rpc diff --git a/examples/platform/nxp/common/ui_feedback/include/LedManager.h b/examples/platform/nxp/common/ui_feedback/include/LedManager.h new file mode 100644 index 00000000000000..b14fae7aebb60c --- /dev/null +++ b/examples/platform/nxp/common/ui_feedback/include/LedManager.h @@ -0,0 +1,91 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "AppConfig.h" +#include "LedOnOff.h" +#include "LedWidgetInterface.h" +#include "UserInterfaceFeedback.h" + +#include +#include + +using namespace chip::NXP::App; + +/** + * @brief Specifies the array index of the status LED. + * + * The status LED is usually used to indicate additional information + * related to the connectivity status of the application. + */ +#ifndef LED_MANAGER_STATUS_LED_INDEX +#define LED_MANAGER_STATUS_LED_INDEX 0 +#endif + +/** + * @brief Specifies the array index of the light LED. + * + * The light LED is usually used to indicate the state of some cluster + * attribute: e.g OnOff attribute from OnOff cluster. + */ +#ifndef LED_MANAGER_LIGHT_LED_INDEX +#define LED_MANAGER_LIGHT_LED_INDEX 1 +#endif + +/** + * @brief Enable status LED. + * + */ +#ifndef LED_MANAGER_ENABLE_STATUS_LED +#define LED_MANAGER_ENABLE_STATUS_LED 0 +#endif + +/** + * @brief Manager of LedWidgetInterface concrete classes. + * + * It implements the UserInterfaceFeedback abstract interface. + */ +class LedManager : public UserInterfaceFeedback +{ +public: + void Init() override; + void DisplayInLoop() override; + void DisplayOnAction(Action action) override; + void RestoreState() override; + +private: + void ApplyTurnOn(); + void ApplyTurnOff(); + void AnimateOnAction(uint32_t onTimeMS, uint32_t offTimeMS); + +#if LED_MANAGER_ENABLE_STATUS_LED + void UpdateStatus(); + + LedOnOff statusLed; +#endif + LedOnOff lightLed; + + friend LedManager & LightingMgr(void); + static LedManager sLedManager; +}; + +inline LedManager & LightingMgr(void) +{ + return LedManager::sLedManager; +} diff --git a/examples/platform/nxp/common/ui_feedback/include/UserInterfaceFeedback.h b/examples/platform/nxp/common/ui_feedback/include/UserInterfaceFeedback.h new file mode 100644 index 00000000000000..9e844a73d9191f --- /dev/null +++ b/examples/platform/nxp/common/ui_feedback/include/UserInterfaceFeedback.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +/** + * @brief Defines an abstract interface for providing feedback to the user. + * + * For example, the feedback can be provided through a logging mechanism or + * through LED animation. + */ +class UserInterfaceFeedback +{ +public: + /** + * @brief Set of possible actions handled by the DisplayOnAction method. + * + */ + enum class Action : uint8_t + { + kFactoryReset = 0, + kTriggerEffect, + kIdentify + }; + + virtual ~UserInterfaceFeedback() = default; + + virtual void Init() = 0; + + /** + * @brief Provide feedback in app task main loop. + * + * For a concrete example, this can be a LED animation command. + */ + virtual void DisplayInLoop() = 0; + + /** + * @brief Provide feedback on a specific action. + * + */ + virtual void DisplayOnAction(Action action) = 0; + + /** + * @brief Restore feedback state based on a default config. + * + * For example, the restoration can be based on a cluster attribute + * value, such as OnOff value in case of a LightingManager. + */ + virtual void RestoreState() = 0; +}; + +/** + * @brief Getter for the concrete class that implements the interface. + * + * It returns a reference to UserInterfaceFeedback, such that only the + * public API can be used regardless of the actual concrete class. + */ +extern UserInterfaceFeedback & FeedbackMgr(); diff --git a/examples/platform/nxp/common/ui_feedback/source/LedManager.cpp b/examples/platform/nxp/common/ui_feedback/source/LedManager.cpp new file mode 100644 index 00000000000000..ac2456f327b61c --- /dev/null +++ b/examples/platform/nxp/common/ui_feedback/source/LedManager.cpp @@ -0,0 +1,150 @@ +/* + * + * Copyright (c) 2021, 2024 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * 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 "LedManager.h" + +#include "AppConfig.h" +#include "AppTask.h" + +#include +#include +#include +#include +#include + +LedManager LedManager::sLedManager; + +#if CONFIG_ENABLE_FEEDBACK +UserInterfaceFeedback & FeedbackMgr() +{ + return LightingMgr(); +} +#endif + +void LedManager::ApplyTurnOn() +{ + if (!lightLed.IsTurnedOff()) + return; + + lightLed.Set(true); +} + +void LedManager::ApplyTurnOff() +{ + if (lightLed.IsTurnedOff()) + return; + + lightLed.Set(false); +} + +void LedManager::Init() +{ + /* start with all LEDS turned off */ +#if LED_MANAGER_ENABLE_STATUS_LED + statusLed.Init(LED_MANAGER_STATUS_LED_INDEX, false); +#endif + /* The parameters will not be used by the dimmer init. */ + lightLed.Init(LED_MANAGER_LIGHT_LED_INDEX, false); + + RestoreState(); +} + +void LedManager::DisplayInLoop() +{ +#if LED_MANAGER_ENABLE_STATUS_LED + UpdateStatus(); + statusLed.Animate(); +#endif + lightLed.Animate(); +} + +void LedManager::DisplayOnAction(Action action) +{ + switch (action) + { + case UserInterfaceFeedback::Action::kFactoryReset: + case UserInterfaceFeedback::Action::kTriggerEffect: + AnimateOnAction(500, 500); + break; + case UserInterfaceFeedback::Action::kIdentify: + AnimateOnAction(250, 250); + break; + default: + break; + } +} + +void LedManager::RestoreState() +{ + /* restore initial state for the LED indicating Lighting state */ + lightLed.Set(false); + + chip::DeviceLayer::PlatformMgr().ScheduleWork([](intptr_t arg) { + bool val = false; + APP_CLUSTER_ATTRIBUTE::Get(APP_DEVICE_TYPE_ENDPOINT, &val); + if (val) + LightingMgr().ApplyTurnOn(); + else + LightingMgr().ApplyTurnOff(); + }); +} + +void LedManager::AnimateOnAction(uint32_t onTimeMS, uint32_t offTimeMS) +{ +#if LED_MANAGER_ENABLE_STATUS_LED + statusLed.Set(false); + statusLed.Animate(onTimeMS, offTimeMS); +#endif + + lightLed.Set(false); + lightLed.Animate(onTimeMS, offTimeMS); +} + +#if LED_MANAGER_ENABLE_STATUS_LED +void LedManager::UpdateStatus() +{ + bool isThreadProvisioned = false; + uint16_t bleConnections = 0; + + // Collect connectivity and configuration state from the CHIP stack. Because the + // CHIP event loop is being run in a separate task, the stack must be locked + // while these values are queried. However we use a non-blocking lock request + // (TryLockChipStack()) to avoid blocking other UI activities when the CHIP + // task is busy (e.g. with a long crypto operation). + if (chip::DeviceLayer::PlatformMgr().TryLockChipStack()) + { + isThreadProvisioned = chip::DeviceLayer::ConnectivityMgr().IsThreadProvisioned(); + bleConnections = chip::DeviceLayer::ConnectivityMgr().NumBLEConnections(); + chip::DeviceLayer::PlatformMgr().UnlockChipStack(); + } + + if (isThreadProvisioned) + { + statusLed.Animate(950, 50); + } + else if (bleConnections != 0) + { + statusLed.Animate(100, 100); + } + else + { + statusLed.Animate(50, 950); + } +} +#endif diff --git a/examples/platform/nxp/k32w/k32w1/args.gni b/examples/platform/nxp/k32w/k32w1/args.gni deleted file mode 100644 index f7d9dccd82e1fd..00000000000000 --- a/examples/platform/nxp/k32w/k32w1/args.gni +++ /dev/null @@ -1,38 +0,0 @@ -# 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") - -import("${chip_root}/src/platform/nxp/k32w/k32w1/args.gni") - -arm_float_abi = "hard" -arm_cpu = "cortex-m33" -arm_fpu = "fpv5-sp-d16" -arm_arch = "armv8-m.main+dsp+fp" - -chip_openthread_ftd = false -openthread_core_config_deps = [] -openthread_core_config_deps = [ "${chip_root}/examples/platform/nxp/k32w/k32w1:openthread_core_config_k32w1_chip_examples" ] - -chip_ble_project_config_include = "" -chip_device_project_config_include = "" -chip_project_config_include = "" -chip_inet_project_config_include = "" -chip_system_project_config_include = "" - -chip_system_config_provide_statistics = false -chip_with_nlfaultinjection = true - -chip_system_config_use_open_thread_inet_endpoints = true -chip_with_lwip = false diff --git a/examples/platform/nxp/k32w/k32w1/app/ldscripts/k32w1_app.ld b/examples/platform/nxp/k32w1/app/ldscripts/k32w1_app.ld similarity index 100% rename from examples/platform/nxp/k32w/k32w1/app/ldscripts/k32w1_app.ld rename to examples/platform/nxp/k32w1/app/ldscripts/k32w1_app.ld diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/include/FreeRTOSConfig.h b/examples/platform/nxp/k32w1/app/project_include/freeRTOS/FreeRTOSConfig.h similarity index 97% rename from examples/contact-sensor-app/nxp/k32w/k32w1/include/FreeRTOSConfig.h rename to examples/platform/nxp/k32w1/app/project_include/freeRTOS/FreeRTOSConfig.h index a4e204700672a3..286566a027b6f9 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w1/include/FreeRTOSConfig.h +++ b/examples/platform/nxp/k32w1/app/project_include/freeRTOS/FreeRTOSConfig.h @@ -85,14 +85,9 @@ extern uint32_t SystemCoreClock; /* Tasks.c additions (e.g. Thread Aware Debug capability) */ #define configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H 1 -/* Used memory allocation (heap_x.c) */ -#define configFRTOS_MEMORY_SCHEME 4 - /* Memory allocation related definitions. */ #define configSUPPORT_STATIC_ALLOCATION 0 #define configSUPPORT_DYNAMIC_ALLOCATION 1 -#define configTOTAL_HEAP_SIZE ((size_t) (gTotalHeapSize_c)) -#define configAPPLICATION_ALLOCATED_HEAP 1 /* Hook function related definitions. */ #ifndef configUSE_IDLE_HOOK diff --git a/examples/platform/nxp/k32w/k32w1/app/project_include/OpenThreadConfig.h b/examples/platform/nxp/k32w1/app/project_include/openthread/OpenThreadConfig.h similarity index 100% rename from examples/platform/nxp/k32w/k32w1/app/project_include/OpenThreadConfig.h rename to examples/platform/nxp/k32w1/app/project_include/openthread/OpenThreadConfig.h diff --git a/examples/platform/nxp/k32w/k32w1/app/support/BUILD.gn b/examples/platform/nxp/k32w1/app/support/BUILD.gn similarity index 78% rename from examples/platform/nxp/k32w/k32w1/app/support/BUILD.gn rename to examples/platform/nxp/k32w1/app/support/BUILD.gn index dc688edc2c78ed..96d05e9ba29f13 100644 --- a/examples/platform/nxp/k32w/k32w1/app/support/BUILD.gn +++ b/examples/platform/nxp/k32w1/app/support/BUILD.gn @@ -15,8 +15,12 @@ import("//build_overrides/chip.gni") import("//build_overrides/nxp_sdk.gni") +import("${nxp_sdk_matter_support_root}/gn_build/nxp_sdk.gni") + +import("${chip_root}/src/platform/nxp/${nxp_platform}/args.gni") + config("support_config") { - include_dirs = [ "../../../../.." ] + include_dirs = [ "${chip_root}" ] # Link options that provides replace dynamic memory operations in standard # library with the FreeRTOS malloc in platform code. @@ -29,7 +33,7 @@ config("support_config") { "-Wl,--wrap=MemoryAlloc", # Wrap these in case internal newlib call them (e.g. strdup will) - # directly call _malloc_r) + # directly call _malloc_r "-Wl,--wrap=_malloc_r", "-Wl,--wrap=_realloc_r", "-Wl,--wrap=_free_r", @@ -38,7 +42,7 @@ config("support_config") { ] } -source_set("freertos_mbedtls_utils") { +source_set("freertos_memory_utils") { sources = [ "FreeRtosHooks.c", "FreeRtosHooks.h", @@ -49,5 +53,11 @@ source_set("freertos_mbedtls_utils") { cflags = [ "-Wconversion" ] + if (chip_key_storage == "fwk_nvm") { + defines = [ "CHIP_PLAT_NVM_SUPPORT=1" ] + } else if (chip_key_storage == "littlefs") { + defines = [ "CHIP_PLAT_NVM_SUPPORT=3" ] + } + public_configs = [ ":support_config" ] } diff --git a/examples/platform/nxp/k32w/k32w1/app/support/FreeRtosHooks.c b/examples/platform/nxp/k32w1/app/support/FreeRtosHooks.c similarity index 96% rename from examples/platform/nxp/k32w/k32w1/app/support/FreeRtosHooks.c rename to examples/platform/nxp/k32w1/app/support/FreeRtosHooks.c index a7c78a77440e03..72d5f1acc6161e 100644 --- a/examples/platform/nxp/k32w/k32w1/app/support/FreeRtosHooks.c +++ b/examples/platform/nxp/k32w1/app/support/FreeRtosHooks.c @@ -27,7 +27,11 @@ #include #include +#if (CHIP_PLAT_NVM_SUPPORT == 1) #include "NVM_Interface.h" +#elif (CHIP_PLAT_NVM_SUPPORT == 3) +#include "fwk_file_cache.h" +#endif #include "PWR_Interface.h" #include "board.h" #include "fsl_os_abstraction.h" @@ -139,8 +143,10 @@ void vApplicationIdleHook(void) // to ensure there is no context switch during the actual // writing, thus avoiding race conditions. OSA_InterruptDisable(); -#if CHIP_PLAT_NVM_SUPPORT +#if (CHIP_PLAT_NVM_SUPPORT == 1) NvIdle(); +#elif (CHIP_PLAT_NVM_SUPPORT == 3) + FC_Process(); #endif OSA_InterruptEnable(); diff --git a/examples/platform/nxp/k32w/k32w1/app/support/FreeRtosHooks.h b/examples/platform/nxp/k32w1/app/support/FreeRtosHooks.h similarity index 100% rename from examples/platform/nxp/k32w/k32w1/app/support/FreeRtosHooks.h rename to examples/platform/nxp/k32w1/app/support/FreeRtosHooks.h diff --git a/examples/platform/nxp/k32w/k32w1/app/support/Memconfig.cpp b/examples/platform/nxp/k32w1/app/support/Memconfig.cpp similarity index 100% rename from examples/platform/nxp/k32w/k32w1/app/support/Memconfig.cpp rename to examples/platform/nxp/k32w1/app/support/Memconfig.cpp diff --git a/examples/platform/nxp/k32w1/board/peripherals.c b/examples/platform/nxp/k32w1/board/peripherals.c new file mode 100644 index 00000000000000..f66203bfe2153b --- /dev/null +++ b/examples/platform/nxp/k32w1/board/peripherals.c @@ -0,0 +1,66 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * Copyright (c) 2024 NXP + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*********************************************************************************************************************** + * Included files + **********************************************************************************************************************/ +#include "peripherals.h" + +/*********************************************************************************************************************** + * BOARD_InitPeripherals functional group + **********************************************************************************************************************/ + +/* LittleFS context */ +extern struct lfs_mflash_ctx LittleFS_ctx; +const struct lfs_config LittleFS_config = { .context = (void *) &LittleFS_ctx, + .read = lfs_mflash_read, + .prog = lfs_mflash_prog, + .erase = lfs_mflash_erase, + .sync = lfs_mflash_sync, +#ifdef LFS_THREADSAFE + .lock = lfs_mutex_lock, + .unlock = lfs_mutex_unlock, +#endif + .read_size = LITTLEFS_READ_SIZE, + .prog_size = LITTLEFS_PROG_SIZE, + .block_size = LITTLEFS_BLOCK_SIZE, + .block_count = LITTLEFS_BLOCK_COUNT, + .block_cycles = LITTLEFS_BLOCK_CYCLES, + .cache_size = LITTLEFS_CACHE_SIZE, + .lookahead_size = LITTLEFS_LOOKAHEAD_SIZE }; + +/* Empty initialization function (commented out) +static void LittleFS_init(void) { +} */ + +/*********************************************************************************************************************** + * Initialization functions + **********************************************************************************************************************/ +void BOARD_InitPeripherals(void) +{ + /* Initialize components */ +} + +/*********************************************************************************************************************** + * BOARD_InitBootPeripherals function + **********************************************************************************************************************/ +void BOARD_InitBootPeripherals(void) +{ + BOARD_InitPeripherals(); +} diff --git a/examples/platform/nxp/k32w1/board/peripherals.h b/examples/platform/nxp/k32w1/board/peripherals.h new file mode 100644 index 00000000000000..38caf2657c4d0f --- /dev/null +++ b/examples/platform/nxp/k32w1/board/peripherals.h @@ -0,0 +1,101 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * Copyright (c) 2024 NXP + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _PERIPHERALS_H_ +#define _PERIPHERALS_H_ + +/*********************************************************************************************************************** + * Included files + **********************************************************************************************************************/ +#include "fsl_common.h" + +#include "lfs.h" + +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus */ + +/*********************************************************************************************************************** + * User definitions + **********************************************************************************************************************/ +extern uint32_t NV_STORAGE_START_ADDRESS[]; +extern uint32_t NV_STORAGE_MAX_SECTORS[]; + +#define LITTLEFS_START_ADDR (uint32_t)(NV_STORAGE_START_ADDRESS) + +/*********************************************************************************************************************** + * Definitions + **********************************************************************************************************************/ +/* Definitions for BOARD_InitPeripherals functional group */ +/* Maximum block read size definition */ +#define LITTLEFS_READ_SIZE 16 +/* Maximum block program size definition */ +#define LITTLEFS_PROG_SIZE 128 +/* Erasable block size definition */ +#define LITTLEFS_BLOCK_SIZE 8192 +/* Block count definition */ +#define LITTLEFS_BLOCK_COUNT (uint32_t)(NV_STORAGE_MAX_SECTORS) +/* Block cycles definition */ +#define LITTLEFS_BLOCK_CYCLES 100 +/* Minimum block cache size definition */ +#define LITTLEFS_CACHE_SIZE 1024 +/* Minimum lookahead buffer size definition */ +#define LITTLEFS_LOOKAHEAD_SIZE 16 +/* Block starting address definition */ +#define LITTLEFS_START_ADDR (uint32_t)(NV_STORAGE_START_ADDRESS) + +/*********************************************************************************************************************** + * Global variables + **********************************************************************************************************************/ +/* LittleFS configuration */ +extern const struct lfs_config LittleFS_config; + +/*********************************************************************************************************************** + * Callback functions + **********************************************************************************************************************/ +/* LittleFS read a block region callback*/ +extern int lfs_mflash_read(const struct lfs_config *, lfs_block_t, lfs_off_t, void *, lfs_size_t); +/* LittleFS program a block region callback*/ +extern int lfs_mflash_prog(const struct lfs_config *, lfs_block_t, lfs_off_t, const void *, lfs_size_t); +/* LittleFS erase a block callback*/ +extern int lfs_mflash_erase(const struct lfs_config *, lfs_block_t); +/* LittleFS state sync callback*/ +extern int lfs_mflash_sync(const struct lfs_config *); +/* LittleFS state lock callback*/ +extern int lfs_mutex_lock(const struct lfs_config *); +/* LittleFS state unlock callback*/ +extern int lfs_mutex_unlock(const struct lfs_config *); + +/*********************************************************************************************************************** + * Initialization functions + **********************************************************************************************************************/ + +void BOARD_InitPeripherals(void); + +/*********************************************************************************************************************** + * BOARD_InitBootPeripherals function + **********************************************************************************************************************/ + +void BOARD_InitBootPeripherals(void); + +#if defined(__cplusplus) +} +#endif + +#endif /* _PERIPHERALS_H_ */ diff --git a/examples/platform/nxp/k32w1/button/ButtonManager.cpp b/examples/platform/nxp/k32w1/button/ButtonManager.cpp new file mode 100644 index 00000000000000..47e5f9fd4b6c9d --- /dev/null +++ b/examples/platform/nxp/k32w1/button/ButtonManager.cpp @@ -0,0 +1,215 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ButtonManager.h" +#include "AppConfig.h" +#include "AppMatterButton.h" +#include "AppTask.h" +#include "UserInterfaceFeedback.h" + +#include + +extern "C" { +#include "app.h" +#include "board_comp.h" +} + +CHIP_ERROR chip::NXP::App::AppMatterButton_registerButtons(void) +{ + /* Board buttons are initialized in otSysInit, when APP_InitServices is called. */ + button_status_t bStatus; + + bStatus = BUTTON_InstallCallback((button_handle_t) g_buttonHandle[0], ButtonManager::BleCallback, NULL); + VerifyOrReturnError(bStatus == kStatus_BUTTON_Success, CHIP_ERROR_UNEXPECTED_EVENT, + ChipLogError(DeviceLayer, "button init error")); + + bStatus = BUTTON_InstallCallback((button_handle_t) g_buttonHandle[1], ButtonManager::AppActionCallback, NULL); + VerifyOrReturnError(bStatus == kStatus_BUTTON_Success, CHIP_ERROR_UNEXPECTED_EVENT, + ChipLogError(DeviceLayer, "button init error")); + + ReturnErrorOnFailure(ButtonMgr().Init()); + + return CHIP_NO_ERROR; +} + +ButtonManager ButtonManager::sInstance; + +TimerHandle_t resetTimer; + +CHIP_ERROR ButtonManager::Init() +{ + resetTimer = xTimerCreate("FnTmr", 1, false, (void *) this, [](TimerHandle_t xTimer) { + AppEvent event; + event.Handler = FunctionTimerEventHandler; + chip::NXP::App::GetAppTask().PostEvent(event); + }); + VerifyOrReturnError(resetTimer != NULL, APP_ERROR_CREATE_TIMER_FAILED); + + return CHIP_NO_ERROR; +} + +button_status_t ButtonManager::BleCallback(void * handle, button_callback_message_t * message, void * param) +{ + AppEvent event; + + switch (message->event) + { + case kBUTTON_EventOneClick: + case kBUTTON_EventShortPress: + event.Handler = ButtonManager::BleHandler; + break; + case kBUTTON_EventLongPress: + event.Handler = ButtonManager::ResetActionEventHandler; + break; + default: + /* No action required */ + break; + } + + chip::NXP::App::GetAppTask().PostEvent(event); + + return kStatus_BUTTON_Success; +} + +button_status_t ButtonManager::AppActionCallback(void * handle, button_callback_message_t * message, void * param) +{ + AppEvent event; + + switch (message->event) + { + case kBUTTON_EventOneClick: + case kBUTTON_EventShortPress: + event.Handler = ButtonManager::AppActionEventHandler; + break; + case kBUTTON_EventLongPress: + // Soft reset ensures that platform manager shutdown procedure is called. + event.Handler = ButtonManager::SoftResetHandler; + break; + default: + /* No action required */ + break; + } + + chip::NXP::App::GetAppTask().PostEvent(event); + + return kStatus_BUTTON_Success; +} + +void ButtonManager::FunctionTimerEventHandler(const AppEvent & event) +{ + ChipLogProgress(DeviceLayer, "Device will factory reset..."); + + // Actually trigger Factory Reset + chip::Server::GetInstance().ScheduleFactoryReset(); +} + +void ButtonManager::ResetActionEventHandler(const AppEvent & event) +{ + if (xTimerIsTimerActive(resetTimer)) + { + ButtonMgr().CancelTimer(); +#if CONFIG_ENABLE_FEEDBACK + FeedbackMgr().RestoreState(); +#endif + ChipLogProgress(DeviceLayer, "Factory Reset was cancelled!"); + } + else + { + uint32_t resetTimeout = BUTTON_MANAGER_FACTORY_RESET_TIMEOUT_MS; + ChipLogProgress(DeviceLayer, "Factory Reset Triggered. Push the RESET button within %lu ms to cancel!", resetTimeout); + +#if CONFIG_ENABLE_FEEDBACK + FeedbackMgr().DisplayOnAction(UserInterfaceFeedback::Action::kFactoryReset); +#endif + ButtonMgr().StartTimer(resetTimeout); + } +} + +void ButtonManager::AppActionEventHandler(const AppEvent & event) +{ + chip::DeviceLayer::PlatformMgr().ScheduleWork( + [](intptr_t arg) { + bool val = false; + APP_CLUSTER_ATTRIBUTE::Get(APP_DEVICE_TYPE_ENDPOINT, &val); + auto status = APP_CLUSTER_ATTRIBUTE::Set(APP_DEVICE_TYPE_ENDPOINT, (bool) !val); + if (status != chip::Protocols::InteractionModel::Status::Success) + { + ChipLogProgress(DeviceLayer, "Error when updating cluster attribute"); + } + }, + (intptr_t) nullptr); +} + +void ButtonManager::SoftResetHandler(const AppEvent & event) +{ + chip::DeviceLayer::PlatformMgrImpl().CleanReset(); +} + +#if CHIP_CONFIG_ENABLE_ICD_LIT +static void UserActiveModeHandler(const AppEvent & event) +{ + chip::DeviceLayer::PlatformMgr().ScheduleWork( + [](intptr_t arg) { chip::app::ICDNotifier::GetInstance().NotifyNetworkActivityNotification(); }, 0); +} +#endif + +void ButtonManager::BleHandler(const AppEvent & event) +{ + if (xTimerIsTimerActive(resetTimer)) + { + // If a factory reset is scheduled, pressing the BLE button will cancel it. + ResetActionEventHandler(event); + return; + } + +#if CHIP_CONFIG_ENABLE_ICD_LIT + if (chip::DeviceLayer::ConfigurationMgr().IsFullyProvisioned()) + { + // If the device is commissioned and a factory reset is not scheduled, switch to active mode. + UserActiveModeHandler(event); + return; + } +#endif + + chip::NXP::App::GetAppTask().SwitchCommissioningStateHandler(); +} + +void ButtonManager::CancelTimer() +{ + if (xTimerStop(resetTimer, 0) == pdFAIL) + { + ChipLogProgress(DeviceLayer, "app timer stop() failed"); + } +} + +void ButtonManager::StartTimer(uint32_t aTimeoutInMs) +{ + if (xTimerIsTimerActive(resetTimer)) + { + ChipLogProgress(DeviceLayer, "app timer already started!"); + CancelTimer(); + } + + // timer is not active, change its period to required value (== restart). + // FreeRTOS- Block for a maximum of 100 ticks if the change period command + // cannot immediately be sent to the timer command queue. + if (xTimerChangePeriod(resetTimer, aTimeoutInMs / portTICK_PERIOD_MS, 100) != pdPASS) + { + ChipLogProgress(DeviceLayer, "app timer start() failed"); + } +} diff --git a/examples/platform/nxp/k32w1/button/ButtonManager.h b/examples/platform/nxp/k32w1/button/ButtonManager.h new file mode 100644 index 00000000000000..aec2411e1095af --- /dev/null +++ b/examples/platform/nxp/k32w1/button/ButtonManager.h @@ -0,0 +1,108 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "AppEvent.h" + +#include "FreeRTOS.h" +#include "timers.h" + +#include "fsl_component_button.h" + +#include + +// Application-defined error codes in the CHIP_ERROR space. +#define APP_ERROR_CREATE_TIMER_FAILED CHIP_APPLICATION_ERROR(0x01) + +/** + * @brief Timeout (ms) for factory data reset action. + * + * During this timeout, the factory reset action can be cancelled by pressing a button. + */ +#ifndef BUTTON_MANAGER_FACTORY_RESET_TIMEOUT_MS +#define BUTTON_MANAGER_FACTORY_RESET_TIMEOUT_MS 6000 +#endif + +/** + * @brief This class describes a manager for button callbacks. + * + */ +class ButtonManager +{ +public: + CHIP_ERROR Init(); + + // These are the callbacks registered with the buttons. They will delegate actions + // to other methods based on the button event: short press, long press etc. + static button_status_t BleCallback(void * handle, button_callback_message_t * message, void * param); + static button_status_t AppActionCallback(void * handle, button_callback_message_t * message, void * param); + +private: + /** + * @brief This callback performs a soft reset. + * + * This can be used when the user wants to clean reset the device, + * meaning that Matter is properly shutdown, unlike a RESET button + * press, where the device resets without calling the shutdown procedure. + */ + static void SoftResetHandler(const AppEvent & event); + + /** + * @brief This callback toggles between BLE start/stop advertising. + * + * It is used during commissioning to ensure a user-intent commissioning flow. + */ + static void BleHandler(const AppEvent & event); + + /** + * @brief This callback updates the application state. + * + * An example of application state would be the lighting manager light LED state. + * This handler will toggle the light LED state. + */ + static void AppActionEventHandler(const AppEvent & event); + + /** + * @brief This callback schedules a factory reset. + * + * The factory reset is scheduled based on the value of BUTTON_MANAGER_FACTORY_RESET_TIMEOUT_MS. + * Until the timer expires, the user can cancel the factory reset operation by doing an action. + * In this reference app, the action would be pressing again the factory reset button. + */ + static void ResetActionEventHandler(const AppEvent & event); + + /** + * @brief This callback performs a factory reset. + * + * This is the callback registered with the timer scheduled in ResetActionEventHandler. + * It will schedule a factory reset using the Matter server instance. + */ + static void FunctionTimerEventHandler(const AppEvent & event); + + void CancelTimer(); + void StartTimer(uint32_t aTimeoutInMs); + + friend ButtonManager & ButtonMgr(); + static ButtonManager sInstance; +}; + +inline ButtonManager & ButtonMgr() +{ + return ButtonManager::sInstance; +} diff --git a/examples/platform/nxp/k32w1/clusters/Identify.cpp b/examples/platform/nxp/k32w1/clusters/Identify.cpp new file mode 100644 index 00000000000000..2d309f975eaca0 --- /dev/null +++ b/examples/platform/nxp/k32w1/clusters/Identify.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Identify.h" +#include "AppTask.h" +#include "UserInterfaceFeedback.h" + +#include + +using namespace chip; +using namespace chip::app; + +static Identify gIdentify = { EndpointId{ 1 }, NXP::App::OnIdentifyStart, NXP::App::OnIdentifyStop, + Clusters::Identify::IdentifyTypeEnum::kVisibleIndicator, NXP::App::OnTriggerEffect, + // Use invalid value for identifiers to enable TriggerEffect command + // to stop Identify command for each effect + Clusters::Identify::EffectIdentifierEnum::kUnknownEnumValue, + Clusters::Identify::EffectVariantEnum::kDefault }; + +namespace chip::NXP::App { + +void OnIdentifyStart(Identify * identify) +{ + chip::DeviceLayer::SystemLayer().CancelTimer(OnTriggerEffectComplete, identify); + OnTriggerEffectComplete(&chip::DeviceLayer::SystemLayer(), identify); + + ChipLogProgress(Zcl, "Identify process has started. Status LED should blink with a period of 0.5 seconds."); + +#if CONFIG_ENABLE_FEEDBACK + FeedbackMgr().DisplayOnAction(UserInterfaceFeedback::Action::kIdentify); +#endif +} + +void OnIdentifyStop(Identify * identify) +{ + ChipLogProgress(Zcl, "Identify process has stopped."); + +#if CONFIG_ENABLE_FEEDBACK + FeedbackMgr().RestoreState(); +#endif +} + +void OnTriggerEffectComplete(chip::System::Layer * systemLayer, void * appState) +{ + // Let Identify command take over if called during TriggerEffect already running + ChipLogProgress(Zcl, "TriggerEffect has stopped."); + + // TriggerEffect finished - reset identifiers + // Use invalid value for identifiers to enable TriggerEffect command + // to stop Identify command for each effect + gIdentify.mCurrentEffectIdentifier = Clusters::Identify::EffectIdentifierEnum::kUnknownEnumValue; + gIdentify.mTargetEffectIdentifier = Clusters::Identify::EffectIdentifierEnum::kUnknownEnumValue; + gIdentify.mEffectVariant = Clusters::Identify::EffectVariantEnum::kDefault; + +#if CONFIG_ENABLE_FEEDBACK + FeedbackMgr().RestoreState(); +#endif +} + +void OnTriggerEffect(Identify * identify) +{ + uint16_t timerDelay = 0; + + ChipLogProgress(Zcl, "TriggerEffect has started."); + + switch (identify->mCurrentEffectIdentifier) + { + case Clusters::Identify::EffectIdentifierEnum::kBlink: + timerDelay = 2; + break; + + case Clusters::Identify::EffectIdentifierEnum::kBreathe: + timerDelay = 15; + break; + + case Clusters::Identify::EffectIdentifierEnum::kOkay: + timerDelay = 4; + break; + + case Clusters::Identify::EffectIdentifierEnum::kChannelChange: + ChipLogProgress(Zcl, "Channel Change effect not supported, using effect %d", + to_underlying(Clusters::Identify::EffectIdentifierEnum::kBlink)); + timerDelay = 2; + break; + + case Clusters::Identify::EffectIdentifierEnum::kFinishEffect: + chip::DeviceLayer::SystemLayer().CancelTimer(OnTriggerEffectComplete, identify); + timerDelay = 1; + break; + + case Clusters::Identify::EffectIdentifierEnum::kStopEffect: + chip::DeviceLayer::SystemLayer().CancelTimer(OnTriggerEffectComplete, identify); + OnTriggerEffectComplete(&chip::DeviceLayer::SystemLayer(), identify); + break; + + default: + ChipLogProgress(Zcl, "Invalid effect identifier."); + } + + if (timerDelay) + { +#if CONFIG_ENABLE_FEEDBACK + FeedbackMgr().DisplayOnAction(UserInterfaceFeedback::Action::kTriggerEffect); +#endif + chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds16(timerDelay), OnTriggerEffectComplete, identify); + } +} + +} // namespace chip::NXP::App diff --git a/examples/platform/nxp/k32w/k32w1/doc/images/debug_k32w1.jpg b/examples/platform/nxp/k32w1/doc/images/debug_k32w1.jpg similarity index 100% rename from examples/platform/nxp/k32w/k32w1/doc/images/debug_k32w1.jpg rename to examples/platform/nxp/k32w1/doc/images/debug_k32w1.jpg diff --git a/examples/platform/nxp/k32w/k32w1/doc/images/import_demo.jpg b/examples/platform/nxp/k32w1/doc/images/import_demo.jpg similarity index 100% rename from examples/platform/nxp/k32w/k32w1/doc/images/import_demo.jpg rename to examples/platform/nxp/k32w1/doc/images/import_demo.jpg diff --git a/examples/platform/nxp/k32w/k32w1/doc/images/installed_sdks.jpg b/examples/platform/nxp/k32w1/doc/images/installed_sdks.jpg similarity index 100% rename from examples/platform/nxp/k32w/k32w1/doc/images/installed_sdks.jpg rename to examples/platform/nxp/k32w1/doc/images/installed_sdks.jpg diff --git a/examples/platform/nxp/k32w/k32w1/doc/images/k32w1-evk.jpg b/examples/platform/nxp/k32w1/doc/images/k32w1-evk.jpg similarity index 100% rename from examples/platform/nxp/k32w/k32w1/doc/images/k32w1-evk.jpg rename to examples/platform/nxp/k32w1/doc/images/k32w1-evk.jpg diff --git a/examples/platform/nxp/k32w/k32w1/doc/images/mcux-sdk-download.jpg b/examples/platform/nxp/k32w1/doc/images/mcux-sdk-download.jpg similarity index 100% rename from examples/platform/nxp/k32w/k32w1/doc/images/mcux-sdk-download.jpg rename to examples/platform/nxp/k32w1/doc/images/mcux-sdk-download.jpg diff --git a/examples/platform/nxp/k32w/k32w1/doc/images/new_project.jpg b/examples/platform/nxp/k32w1/doc/images/new_project.jpg similarity index 100% rename from examples/platform/nxp/k32w/k32w1/doc/images/new_project.jpg rename to examples/platform/nxp/k32w1/doc/images/new_project.jpg diff --git a/examples/platform/nxp/k32w/k32w1/doc/images/ota_topology.JPG b/examples/platform/nxp/k32w1/doc/images/ota_topology.JPG similarity index 100% rename from examples/platform/nxp/k32w/k32w1/doc/images/ota_topology.JPG rename to examples/platform/nxp/k32w1/doc/images/ota_topology.JPG diff --git a/examples/platform/nxp/k32w1/factory_data/source/AppFactoryDataExample.cpp b/examples/platform/nxp/k32w1/factory_data/source/AppFactoryDataExample.cpp new file mode 100644 index 00000000000000..dbccc2fd7dc7f9 --- /dev/null +++ b/examples/platform/nxp/k32w1/factory_data/source/AppFactoryDataExample.cpp @@ -0,0 +1,76 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * Copyright 2023-2024 NXP + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "AppFactoryData.h" + +#include +#include +#include + +#if CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA +#include "FactoryDataDriver.h" +#include "FactoryDataProvider.h" +#else +#include +#endif + +using namespace chip; +using namespace ::chip::Credentials; +using namespace ::chip::DeviceLayer; + +#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA && CONFIG_CHIP_OTA_FACTORY_DATA_PROCESSOR +/** + * Custom factory data restore mechanism. This function must be implemented by vendors. + */ +CHIP_ERROR CustomFactoryDataRestoreMechanism(void) +{ + ChipLogProgress(DeviceLayer, "This is a custom factory data restore mechanism."); + + return CHIP_NO_ERROR; +} +#endif + +/** + * Allows to register Matter factory data before initializing the Matter stack + */ +CHIP_ERROR NXP::App::AppFactoryData_PreMatterStackInit(void) +{ + return CHIP_NO_ERROR; +} + +/** + * Allows to register Matter factory data after initializing the Matter stack + */ +CHIP_ERROR NXP::App::AppFactoryData_PostMatterStackInit(void) +{ +#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA + ReturnErrorOnFailure(FactoryDataDrv().Init()); +#if CONFIG_CHIP_OTA_FACTORY_DATA_PROCESSOR + FactoryDataPrvd().RegisterRestoreMechanism(CustomFactoryDataRestoreMechanism); +#endif + ReturnErrorOnFailure(FactoryDataPrvd().Init()); + SetDeviceInstanceInfoProvider(&FactoryDataPrvd()); + SetDeviceAttestationCredentialsProvider(&FactoryDataPrvd()); + SetCommissionableDataProvider(&FactoryDataPrvd()); +#else + // Initialize device attestation with example one (only for debug purpose) + SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); +#endif + return CHIP_NO_ERROR; +} diff --git a/examples/platform/nxp/k32w1/operational_keystore/OperationalKeystore.cpp b/examples/platform/nxp/k32w1/operational_keystore/OperationalKeystore.cpp new file mode 100644 index 00000000000000..ecd72266178984 --- /dev/null +++ b/examples/platform/nxp/k32w1/operational_keystore/OperationalKeystore.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "OperationalKeystore.h" +#include "K32W1PersistentStorageOpKeystore.h" + +static chip::K32W1PersistentStorageOpKeystore sInstance; + +chip::Crypto::OperationalKeystore * chip::NXP::App::OperationalKeystore::GetInstance() +{ + return &sInstance; +} + +CHIP_ERROR chip::NXP::App::OperationalKeystore::Init(PersistentStorageDelegate * delegate) +{ + VerifyOrReturnError(delegate != nullptr, CHIP_ERROR_INTERNAL); + sInstance.Init(delegate); + + return CHIP_NO_ERROR; +} diff --git a/examples/platform/nxp/k32w/k32w1/util/include/LED_Dimmer.h b/examples/platform/nxp/k32w1/ota/OtaUtils.cpp similarity index 81% rename from examples/platform/nxp/k32w/k32w1/util/include/LED_Dimmer.h rename to examples/platform/nxp/k32w1/ota/OtaUtils.cpp index 424ffa20c97bbd..4088196ba34973 100644 --- a/examples/platform/nxp/k32w/k32w1/util/include/LED_Dimmer.h +++ b/examples/platform/nxp/k32w1/ota/OtaUtils.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2020 Google LLC. + * Copyright (c) 2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,6 +16,9 @@ * limitations under the License. */ -void init_dimmable(); -void init_tpm(); -void move_to_level(uint8_t level); +#include "OtaSupport.h" + +extern "C" void OTAIdleActivities(void) +{ + OTA_TransactionResume(); +} diff --git a/examples/platform/nxp/k32w1/rpc/AppRpc.cpp b/examples/platform/nxp/k32w1/rpc/AppRpc.cpp new file mode 100644 index 00000000000000..beea8408438300 --- /dev/null +++ b/examples/platform/nxp/k32w1/rpc/AppRpc.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "AppRpc.h" +#include "ButtonManager.h" +#include "clock_config.h" +#include "pin_mux.h" + +#include "Rpc.h" + +CHIP_ERROR chip::NXP::App::Rpc::Init() +{ + /* set clock */ + CLOCK_SetIpSrc(kCLOCK_Lpuart1, kCLOCK_IpSrcFro192M); + /* enable clock */ + CLOCK_EnableClock(kCLOCK_Lpuart1); + + BOARD_InitPinLPUART1_TX(); + BOARD_InitPinLPUART1_RX(); + chip::rpc::Init(); + + return CHIP_NO_ERROR; +} + +#if defined(PW_RPC_DEVICE_SERVICE) && PW_RPC_DEVICE_SERVICE +void chip::NXP::App::Rpc::Reboot() +{ + NVIC_SystemReset(); +} +#endif + +#if defined(PW_RPC_BUTTON_SERVICE) && PW_RPC_BUTTON_SERVICE +void chip::NXP::App::Rpc::ButtonHandler(const chip_rpc_ButtonEvent & request) +{ + button_callback_message_t * message = new button_callback_message_t; + + switch (request.idx) + { + case 0: + message->event = kBUTTON_EventShortPress; + ButtonMgr().BleCallback(nullptr, message, nullptr); + break; + case 1: + message->event = kBUTTON_EventLongPress; + ButtonMgr().BleCallback(nullptr, message, nullptr); + break; + case 2: + message->event = kBUTTON_EventShortPress; + ButtonMgr().AppActionCallback(nullptr, message, nullptr); + break; + case 3: + message->event = kBUTTON_EventLongPress; + ButtonMgr().AppActionCallback(nullptr, message, nullptr); + break; + default: + break; + } + + delete message; +} +#endif diff --git a/examples/platform/nxp/k32w/k32w1/util/LED_Dimmer.cpp b/examples/platform/nxp/k32w1/util/LedDimmer.cpp similarity index 97% rename from examples/platform/nxp/k32w/k32w1/util/LED_Dimmer.cpp rename to examples/platform/nxp/k32w1/util/LedDimmer.cpp index 02a62724716e53..c682abb5c1480a 100644 --- a/examples/platform/nxp/k32w/k32w1/util/LED_Dimmer.cpp +++ b/examples/platform/nxp/k32w1/util/LedDimmer.cpp @@ -17,7 +17,7 @@ * limitations under the License. */ -#include "LED_Dimmer.h" +#include "LedDimmer.h" #include "fsl_common.h" #include "fsl_port.h" #include "fsl_tpm.h" @@ -36,9 +36,11 @@ #define DEMO_PWM_FREQUENCY (24000U) #endif +namespace chip::NXP::App { + volatile uint8_t updatedDutycycle = 0U; -void init_dimmable() +static void initConfig() { const port_pin_config_t porta20_pin17_config = { /* Internal pull-up/down resistor is disabled */ (uint16_t) kPORT_PullDisable, @@ -105,15 +107,15 @@ void init_dimmable() }; /* PORTA19 (pin 14) is configured as TPM0_CH0 */ PORT_SetPinConfig(PORTA, 19U, &porta19_pin14_config); - - init_tpm(); } -void init_tpm() +void LedDimmer::Init(uint8_t index, bool inverted) { tpm_config_t tpmInfo; tpm_chnl_pwm_signal_param_t tpmParam[3]; + initConfig(); + /* TPM 0 Clock Gate Control: Clock enabled */ CLOCK_EnableClock(kCLOCK_Tpm0); /* Set the source for the LPIT module */ @@ -157,10 +159,12 @@ void init_tpm() TPM_StartTimer(BOARD_TPM_BASEADDR, kTPM_SystemClock); } -void move_to_level(uint8_t level) +void LedDimmer::Set(uint8_t level) { uint8_t control; + mState = level != 0; + updatedDutycycle = static_cast(level * 90) / 255; control = TPM_GetChannelContorlBits(BOARD_TPM_BASEADDR, (tpm_chnl_t) BOARD_FIRST_TPM_CHANNEL); @@ -191,3 +195,5 @@ void move_to_level(uint8_t level) TPM_EnableChannel(BOARD_TPM_BASEADDR, (tpm_chnl_t) BOARD_SECOND_TPM_CHANNEL, control); TPM_EnableChannel(BOARD_TPM_BASEADDR, (tpm_chnl_t) BOARD_THIRD_TPM_CHANNEL, control); } + +} // namespace chip::NXP::App diff --git a/examples/platform/nxp/k32w/k32w1/util/LEDWidget.cpp b/examples/platform/nxp/k32w1/util/LedOnOff.cpp similarity index 53% rename from examples/platform/nxp/k32w/k32w1/util/LEDWidget.cpp rename to examples/platform/nxp/k32w1/util/LedOnOff.cpp index 695da50e3dae32..92b1f41ebfba4f 100644 --- a/examples/platform/nxp/k32w/k32w1/util/LEDWidget.cpp +++ b/examples/platform/nxp/k32w1/util/LedOnOff.cpp @@ -17,93 +17,69 @@ * limitations under the License. */ -#include "LEDWidget.h" +#include "LedOnOff.h" +#include "app.h" #include -#include "app.h" - -#if CHIP_CONFIG_ENABLE_DIMMABLE_LED -#include "LED_Dimmer.h" -#endif +namespace chip::NXP::App { #if (defined(gAppLedCnt_c) && (gAppLedCnt_c > 0)) -void LEDWidget::Init(uint8_t led, bool inverted) +void LedOnOff::Init(uint8_t index, bool inverted) { mLastChangeTimeMS = 0; - mBlinkOnTimeMS = 0; - mBlinkOffTimeMS = 0; - mGPIONum = led; + mOnTimeMS = 0; + mOffTimeMS = 0; + mIndex = index; mState = false; mOnLogic = !inverted; Set(false); } -void LEDWidget::Invert(void) -{ - Set(!mState); -} - -void LEDWidget::Set(bool state) -{ - mLastChangeTimeMS = mBlinkOnTimeMS = mBlinkOffTimeMS = 0; - DoSet(state); -} - -void LEDWidget::SetLevel(uint8_t level) +void LedOnOff::Set(uint8_t level) { -#if CHIP_CONFIG_ENABLE_DIMMABLE_LED - move_to_level(level); -#endif + mLastChangeTimeMS = mOnTimeMS = mOffTimeMS = 0; + DoSet(level != 0); } -void LEDWidget::Blink(uint32_t changeRateMS) +void LedOnOff::Animate(uint32_t onTimeMS, uint32_t offTimeMS) { - Blink(changeRateMS, changeRateMS); -} - -void LEDWidget::Blink(uint32_t onTimeMS, uint32_t offTimeMS) -{ - mBlinkOnTimeMS = onTimeMS; - mBlinkOffTimeMS = offTimeMS; - Animate(); -} + if (onTimeMS && offTimeMS) + { + mOnTimeMS = onTimeMS; + mOffTimeMS = offTimeMS; + } -void LEDWidget::Animate() -{ - if (mBlinkOnTimeMS != 0 && mBlinkOffTimeMS != 0) + if (mOnTimeMS && mOffTimeMS) { uint64_t nowMS = chip::System::SystemClock().GetMonotonicMilliseconds64().count(); - uint64_t stateDurMS = mState ? mBlinkOnTimeMS : mBlinkOffTimeMS; + uint64_t stateDurMS = mState ? mOnTimeMS : mOffTimeMS; uint64_t nextChangeTimeMS = mLastChangeTimeMS + stateDurMS; if (nextChangeTimeMS < nowMS) { -#if CHIP_CONFIG_ENABLE_DIMMABLE_LED - SetLevel(!mState * 254); - mState = !mState; -#else DoSet(!mState); -#endif mLastChangeTimeMS = nowMS; } } } -void LEDWidget::DoSet(bool state) +void LedOnOff::DoSet(bool state) { mState = state; if (state) { - (void) LED_TurnOnOff((led_handle_t) g_ledHandle[mGPIONum], mOnLogic); + (void) LED_TurnOnOff((led_handle_t) g_ledHandle[mIndex], mOnLogic); } else { - (void) LED_TurnOnOff((led_handle_t) g_ledHandle[mGPIONum], !mOnLogic); + (void) LED_TurnOnOff((led_handle_t) g_ledHandle[mIndex], !mOnLogic); } } #endif /* (defined(gAppLedCnt_c) && (gAppLedCnt_c > 0)) */ + +} // namespace chip::NXP::App diff --git a/examples/platform/nxp/k32w1/util/LightingManagerDimmable.cpp b/examples/platform/nxp/k32w1/util/LightingManagerDimmable.cpp new file mode 100644 index 00000000000000..8476101f5d1a3e --- /dev/null +++ b/examples/platform/nxp/k32w1/util/LightingManagerDimmable.cpp @@ -0,0 +1,79 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "LightingManagerDimmable.h" + +#include "AppConfig.h" +#include "AppTask.h" + +#include +#include +#include +#include +#include + +LightingManagerDimmable LightingManagerDimmable::sLightingManager; + +#if CONFIG_ENABLE_FEEDBACK +UserInterfaceFeedback & FeedbackMgr() +{ + return LightingMgr(); +} +#endif + +void LightingManagerDimmable::ApplyDim(uint8_t value) +{ + ChipLogProgress(DeviceLayer, "Dim action has been initiated"); + LightingManagerDimmable::lightLed.Set(LightingManagerDimmable::lightLed.IsTurnedOff() ? 1 : value); + ChipLogProgress(DeviceLayer, "Move to level %d completed", value); +} + +void LightingManagerDimmable::Init() +{ + /* The parameters will not be used by the dimmer init. */ + lightLed.Init(LIGHTING_MANAGER_LIGHT_LED_INDEX, false); + + RestoreState(); +} + +void LightingManagerDimmable::DisplayInLoop() +{ + lightLed.Animate(); +} + +void LightingManagerDimmable::DisplayOnAction(Action action) +{ + // Do nothing for now. +} + +void LightingManagerDimmable::RestoreState() +{ + /* restore initial state for the LED indicating Lighting state */ + lightLed.Set(false); + + chip::DeviceLayer::PlatformMgr().ScheduleWork([](intptr_t arg) { + chip::app::DataModel::Nullable currentLevel; + chip::app::Clusters::LevelControl::Attributes::CurrentLevel::Get(LIGHTING_MANAGER_APP_DEVICE_TYPE_ENDPOINT, currentLevel); + LightingMgr().ApplyDim(currentLevel.Value()); + }); +} + +void LightingManagerDimmable::UpdateState() +{ + // Do nothing for now. +} diff --git a/examples/platform/nxp/k32w1/util/LightingManagerDimmable.h b/examples/platform/nxp/k32w1/util/LightingManagerDimmable.h new file mode 100644 index 00000000000000..0cd4475ebfb7da --- /dev/null +++ b/examples/platform/nxp/k32w1/util/LightingManagerDimmable.h @@ -0,0 +1,85 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "AppConfig.h" +#include "LedDimmer.h" +#include "LedWidgetInterface.h" +#include "UserInterfaceFeedback.h" + +#include +#include + +using namespace chip::NXP::App; + +/* These flags can be overwritten in AppConfig.h */ +/** + * @brief Specifies the endpoint on which Application Device Type cluster is present. + * + * For example, this should be 1 for Contact Sensor and Lighting App reference apps. + */ +#ifndef LIGHTING_MANAGER_APP_DEVICE_TYPE_ENDPOINT +#define LIGHTING_MANAGER_APP_DEVICE_TYPE_ENDPOINT 1 +#endif + +/** + * @brief Specifies the array index of the light LED. + * + * The light LED is usually used to indicate the state of some cluster + * attribute: e.g OnOff attribute from OnOff cluster. + */ +#ifndef LIGHTING_MANAGER_LIGHT_LED_INDEX +#define LIGHTING_MANAGER_LIGHT_LED_INDEX 1 +#endif + +/** + * @brief Enable dimmable LED instead of a simple on/off LED. + * + */ +#ifndef LIGHTING_MANAGER_ENABLE_DIMMABLE_LED +#define LIGHTING_MANAGER_ENABLE_DIMMABLE_LED 1 +#endif + +/** + * @brief Manager of LedDimmer instance. + * + * It implements the UserInterfaceFeedback abstract interface. + */ +class LightingManagerDimmable : public UserInterfaceFeedback +{ +public: + void Init() override; + void DisplayInLoop() override; + void DisplayOnAction(Action action) override; + void RestoreState() override; + void UpdateState() override; + +private: + void ApplyDim(uint8_t value); + + LedDimmer lightLed; + + friend LightingManagerDimmable & LightingMgr(void); + static LightingManagerDimmable sLightingManager; +}; + +inline LightingManagerDimmable & LightingMgr(void) +{ + return LightingManagerDimmable::sLightingManager; +} diff --git a/examples/platform/nxp/pw_rpc_server.gni b/examples/platform/nxp/pw_rpc_server.gni index 0ec2d3b121b2d5..7133b44bf24aac 100644 --- a/examples/platform/nxp/pw_rpc_server.gni +++ b/examples/platform/nxp/pw_rpc_server.gni @@ -48,6 +48,7 @@ pw_rpc_server = { ] deps = [ + "$dir_pw_hdlc:default_addresses", "$dir_pw_hdlc:rpc_channel_output", "$dir_pw_stream:sys_io_stream", "$dir_pw_trace", diff --git a/examples/platform/silabs/BaseApplication.cpp b/examples/platform/silabs/BaseApplication.cpp index beda9d3a6981f1..99123c5bf764d1 100644 --- a/examples/platform/silabs/BaseApplication.cpp +++ b/examples/platform/silabs/BaseApplication.cpp @@ -188,6 +188,17 @@ void BaseApplicationDelegate::OnCommissioningWindowClosed() } } #endif // CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI917 + if (BaseApplication::GetProvisionStatus()) + { +#ifdef DISPLAY_ENABLED +#ifdef QR_CODE_ENABLED + SilabsLCD::Screen_e screen; + slLCD.GetScreen(screen); + VerifyOrReturn(screen == SilabsLCD::Screen_e::QRCodeScreen); + slLCD.SetScreen(SilabsLCD::Screen_e::DemoScreen); +#endif // QR_CODE_ENABLED +#endif // DISPLAY_ENABLED + } } void BaseApplicationDelegate::OnFabricCommitted(const FabricTable & fabricTable, FabricIndex fabricIndex) diff --git a/examples/platform/silabs/OTAConfig.h b/examples/platform/silabs/OTAConfig.h index 2b7ed9a45fa257..c97202e401f266 100644 --- a/examples/platform/silabs/OTAConfig.h +++ b/examples/platform/silabs/OTAConfig.h @@ -29,6 +29,10 @@ #include #endif +#if (SL_MATTER_GN_BUILD == 0) +#include "sl_matter_ota_config.h" +#endif + class OTAConfig { public: diff --git a/examples/platform/silabs/SiWx917/BUILD.gn b/examples/platform/silabs/SiWx917/BUILD.gn index 8acee7c3b9cfcd..80d247b56c4df4 100644 --- a/examples/platform/silabs/SiWx917/BUILD.gn +++ b/examples/platform/silabs/SiWx917/BUILD.gn @@ -115,12 +115,6 @@ source_set("siwx917-matter-shell") { config("siwx917-common-config") { defines = [ "OTA_PERIODIC_TIMEOUT=${ota_periodic_query_timeout_sec}" ] - if (sl_si91x_crypto_flavor == "psa") { - libs = - [ "${sdk_support_root}/matter/provision/lib/libProvisionPSA_si917.a" ] - } else { - libs = [ "${sdk_support_root}/matter/provision/lib/libProvision_si917.a" ] - } if (!disable_lcd) { include_dirs = [ "${silabs_common_plat_dir}/display" ] @@ -177,7 +171,7 @@ config("silabs-wifi-config") { } source_set("siwx917-common") { - deps = [ "${chip_root}/src/platform/silabs/provision:provision-headers" ] + deps = [ "${silabs_common_plat_dir}/provision:storage" ] defines = [] public_deps = [] public_configs = [ @@ -197,8 +191,6 @@ source_set("siwx917-common") { "${silabs_common_plat_dir}/LEDWidget.cpp", "${silabs_common_plat_dir}/MatterConfig.cpp", "${silabs_common_plat_dir}/SoftwareFaultReports.cpp", - "${silabs_common_plat_dir}/provision/ProvisionStorageCustom.cpp", - "${silabs_common_plat_dir}/provision/ProvisionStorageFlash.cpp", "${silabs_common_plat_dir}/silabs_utils.cpp", "${silabs_common_plat_dir}/syscalls_stubs.cpp", "${silabs_plat_si91x_wifi_dir}/dhcp_client.cpp", @@ -210,7 +202,7 @@ source_set("siwx917-common") { ] if (chip_enable_pw_rpc || chip_build_libshell || sl_uart_log_output) { - sources += [ "uart.cpp" ] + sources += [ "${silabs_common_plat_dir}/uart.cpp" ] } if (chip_enable_ota_requestor) { diff --git a/examples/platform/silabs/SiWx917/SiWx917/sl_wifi_if.cpp b/examples/platform/silabs/SiWx917/SiWx917/sl_wifi_if.cpp index 59bf52bbc0f30f..bfdedbfe82bb13 100644 --- a/examples/platform/silabs/SiWx917/SiWx917/sl_wifi_if.cpp +++ b/examples/platform/silabs/SiWx917/SiWx917/sl_wifi_if.cpp @@ -19,6 +19,10 @@ #include #include +#if (SL_MATTER_GN_BUILD == 0) +#include "sl_matter_wifi_config.h" +#endif // SL_MATTER_GN_BUILD + #include "sl_status.h" #include #include @@ -52,9 +56,15 @@ extern "C" { #include "sl_si91x_m4_ps.h" } +namespace { // TODO: should be removed once we are getting the press interrupt for button 0 with sleep #define BUTTON_PRESSED 1 bool btn0_pressed = false; + +#ifdef ENABLE_CHIP_SHELL +bool ps_requirement_added = false; +#endif // ENABLE_CHIP_SHELL +} // namespace #endif // CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI91X_MCU_INTERFACE #include "dhcp_client.h" @@ -288,6 +298,26 @@ void sl_si91x_invoke_btn_press_event() { btn0_pressed = false; } + +#ifdef ENABLE_CHIP_SHELL + // Checking the UULP PIN 1 status to reinit the UART and not allow the device to go to sleep + if (RSI_NPSSGPIO_GetPin(RTE_UULP_GPIO_1_PIN)) + { + if (!ps_requirement_added) + { + sl_si91x_power_manager_add_ps_requirement(SL_SI91X_POWER_MANAGER_PS4); + ps_requirement_added = true; + } + } + else + { + if (ps_requirement_added) + { + sl_si91x_power_manager_remove_ps_requirement(SL_SI91X_POWER_MANAGER_PS4); + ps_requirement_added = false; + } + } +#endif // ENABLE_CHIP_SHELL } /****************************************************************** @@ -426,6 +456,16 @@ static sl_status_t wfx_rsi_init(void) ChipLogError(DeviceLayer, "sl_si91x_m4_ta_secure_handshake failed: 0x%lx", static_cast(status)); return status; } +#ifdef ENABLE_CHIP_SHELL + // While using the matter shell with the ICD server, the GPIO 1 is used to check the UULP PIN 1 status + // since UART doesn't act as a wakeup source in the UULP mode + /*Configuring the NPS GPIO 1*/ + RSI_NPSSGPIO_SetPinMux(RTE_UULP_GPIO_1_PIN, 0); + /*Configure the NPSS GPIO direction to input */ + RSI_NPSSGPIO_SetDir(RTE_UULP_GPIO_1_PIN, 1); + /*Enable the REN*/ + RSI_NPSSGPIO_InputBufferEn(RTE_UULP_GPIO_1_PIN, 1); +#endif // ENABLE_CHIP_SHELL #endif /* CHIP_CONFIG_ENABLE_ICD_SERVER */ #endif /* SLI_SI91X_MCU_INTERFACE */ diff --git a/examples/platform/silabs/SiWx917/uart.cpp b/examples/platform/silabs/SiWx917/uart.cpp deleted file mode 100644 index 863beef67f7f04..00000000000000 --- a/examples/platform/silabs/SiWx917/uart.cpp +++ /dev/null @@ -1,169 +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. - */ -#include "AppConfig.h" -#include "USART.h" -#include "matter_shell.h" -#include "rsi_rom_egpio.h" -#include "silabs_utils.h" -#include "sl_si91x_usart.h" -#ifdef __cplusplus -extern "C" { -#endif -#include "assert.h" -#include "rsi_board.h" -#include "rsi_debug.h" -#include "uart.h" -#include -#include - -#define USART_BAUDRATE 115200 // Baud rate <9600-7372800> -#define UART_CONSOLE_ERR -1 // Negative value in case of UART Console action failed. Triggers a failure for PW_RPC - -sl_usart_handle_t usart_handle; - -void callback_event(uint32_t event); - -/******************************************************************************* - * Callback function triggered on data Transfer and reception - ******************************************************************************/ -void callback_event(uint32_t event) -{ - switch (event) - { - case SL_USART_EVENT_SEND_COMPLETE: - break; - case SL_USART_EVENT_RECEIVE_COMPLETE: -#ifdef ENABLE_CHIP_SHELL - chip::NotifyShellProcess(); -#endif - case SL_USART_EVENT_TRANSFER_COMPLETE: - break; - } -} - -void uartConsoleInit(void) -{ - int32_t status = 0; - - sl_si91x_usart_control_config_t usart_config; - usart_config.baudrate = USART_BAUDRATE; - usart_config.mode = SL_USART_MODE_ASYNCHRONOUS; - usart_config.parity = SL_USART_NO_PARITY; - usart_config.stopbits = SL_USART_STOP_BITS_1; - usart_config.hwflowcontrol = SL_USART_FLOW_CONTROL_NONE; - usart_config.databits = SL_USART_DATA_BITS_8; - usart_config.misc_control = SL_USART_MISC_CONTROL_NONE; - usart_config.usart_module = USART_0; - usart_config.config_enable = ENABLE; - usart_config.synch_mode = DISABLE; - sl_si91x_usart_control_config_t get_config; - - // Initialize the UART - status = sl_si91x_usart_init((usart_peripheral_t) usart_config.usart_module, &usart_handle); - if (status != SL_STATUS_OK) - { - SILABS_LOG("sl_si91x_usart_initialize: Error Code : %lu \n", status); - } - - // Configure the USART configurations - status = sl_si91x_usart_set_configuration(usart_handle, &usart_config); - if (status != SL_STATUS_OK) - { - SILABS_LOG("sl_si91x_usart_set_configuration: Error Code : %lu \n", status); - } - - // Register user callback function - status = sl_si91x_usart_register_event_callback(callback_event); - if (status != SL_STATUS_OK) - { - SILABS_LOG("sl_si91x_usart_register_event_callback: Error Code : %lu \n", status); - } - - NVIC_EnableIRQ(USART0_IRQn); - NVIC_SetPriority(USART0_IRQn, 7); -} - -/* - * @brief Read the data available from the console Uart - * @param Buffer that contains the data to write, number bytes to write. - * @return Amount of bytes written or ERROR (-1) - */ -int16_t uartConsoleWrite(const char * Buf, uint16_t BufLength) -{ - int32_t status = 0; - if (Buf == NULL || BufLength < 1) - { - return UART_CONSOLE_ERR; - } - - status = sl_si91x_usart_send_data(usart_handle, Buf, BufLength); - if (status != SL_STATUS_OK) - { - return status; - } - return BufLength; -} - -/** - * @brief Write Logs to the Uart. Appends a return character - * - * @param log pointer to the logs - * @param length number of bytes to write - * @return int16_t Amount of bytes written or ERROR (-1) - */ -int16_t uartLogWrite(const char * log, uint16_t length) -{ - if (log == NULL || length == 0) - { - return UART_CONSOLE_ERR; - } - for (uint16_t i = 0; i < length; i++) - { - Board_UARTPutChar(log[i]); - } - // To print next log in new line with proper formatting - Board_UARTPutChar('\r'); - Board_UARTPutChar('\n'); - - return length + 2; -} - -/* - * @brief Read the data available from the console Uart - * @param Buffer for the data to be read, number bytes to read. - * @return Amount of bytes that was read from the rx fifo or ERROR (-1) - */ -int16_t uartConsoleRead(char * Buf, uint16_t NbBytesToRead) -{ - int32_t status = 0; - if (Buf == NULL || NbBytesToRead < 1) - { - return UART_CONSOLE_ERR; - } - - status = sl_si91x_usart_receive_data(usart_handle, Buf, NbBytesToRead); - if (status != SL_STATUS_OK) - { - return status; - } - return NbBytesToRead; -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/platform/silabs/SoftwareFaultReports.cpp b/examples/platform/silabs/SoftwareFaultReports.cpp index fc7b6a9c5e3d76..8245b1bf454307 100644 --- a/examples/platform/silabs/SoftwareFaultReports.cpp +++ b/examples/platform/silabs/SoftwareFaultReports.cpp @@ -26,17 +26,18 @@ #include #include -#ifndef BRD4325A +#if !defined(SLI_SI91X_MCU_INTERFACE) || !defined(SLI_SI91X_ENABLE_BLE) #include "rail_types.h" #ifdef RAIL_ASSERT_DEBUG_STRING #include "rail_assert_error_codes.h" #endif -#endif // BRD4325A +#endif // !defined(SLI_SI91X_MCU_INTERFACE) || !defined(SLI_SI91X_ENABLE_BLE) + +#if defined(SLI_SI91X_MCU_INTERFACE) && SLI_SI91X_MCU_INTERFACE -#ifdef BRD4325A // For SiWx917 Platform only #include "core_cm4.h" -#endif +#endif // defined(SLI_SI91X_MCU_INTERFACE) && SLI_SI91X_MCU_INTERFACE // Technically FaultRecording is an octstr up to 1024 bytes. // We currently only report short strings. 100 char will more than enough for now. @@ -227,7 +228,7 @@ extern "C" void vApplicationGetTimerTaskMemory(StaticTask_t ** ppxTimerTaskTCBBu *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; } -#ifndef BRD4325A +#if !defined(SLI_SI91X_MCU_INTERFACE) || !defined(SLI_SI91X_ENABLE_BLE) extern "C" void RAILCb_AssertFailed(RAIL_Handle_t railHandle, uint32_t errorCode) { char faultMessage[kMaxFaultStringLen] = { 0 }; @@ -251,6 +252,5 @@ extern "C" void RAILCb_AssertFailed(RAIL_Handle_t railHandle, uint32_t errorCode chipAbort(); } -#endif // BRD4325A - +#endif // !defined(SLI_SI91X_MCU_INTERFACE) || !defined(SLI_SI91X_ENABLE_BLE) #endif // HARD_FAULT_LOG_ENABLE diff --git a/examples/platform/silabs/efr32/BUILD.gn b/examples/platform/silabs/efr32/BUILD.gn index 6cf43897f43b10..22b7458588d97c 100644 --- a/examples/platform/silabs/efr32/BUILD.gn +++ b/examples/platform/silabs/efr32/BUILD.gn @@ -148,9 +148,6 @@ source_set("efr-matter-shell") { config("efr32-common-config") { defines = [ "OTA_PERIODIC_TIMEOUT=${ota_periodic_query_timeout_sec}" ] - libs = [ - "${sdk_support_root}/matter/provision/lib/libProvision_${silabs_family}.a", - ] if (!disable_lcd) { include_dirs = [ "${silabs_common_plat_dir}/display" ] @@ -212,7 +209,7 @@ config("silabs-wifi-config") { } source_set("efr32-common") { - deps = [ "${chip_root}/src/platform/silabs/provision:provision-headers" ] + deps = [ "${silabs_common_plat_dir}/provision:storage" ] defines = [] public_deps = [] public_configs = [ @@ -241,14 +238,12 @@ source_set("efr32-common") { "${silabs_common_plat_dir}/LEDWidget.cpp", "${silabs_common_plat_dir}/MatterConfig.cpp", "${silabs_common_plat_dir}/SoftwareFaultReports.cpp", - "${silabs_common_plat_dir}/provision/ProvisionStorageCustom.cpp", - "${silabs_common_plat_dir}/provision/ProvisionStorageDefault.cpp", "${silabs_common_plat_dir}/silabs_utils.cpp", "${silabs_common_plat_dir}/syscalls_stubs.cpp", ] if (chip_enable_pw_rpc || chip_build_libshell || enable_openthread_cli) { - sources += [ "uart.cpp" ] + sources += [ "${silabs_common_plat_dir}/uart.cpp" ] } if (chip_enable_ota_requestor) { diff --git a/examples/platform/silabs/provision/BUILD.gn b/examples/platform/silabs/provision/BUILD.gn new file mode 100644 index 00000000000000..ccd5b919bc0379 --- /dev/null +++ b/examples/platform/silabs/provision/BUILD.gn @@ -0,0 +1,52 @@ +# Copyright (c) 2024 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/chip.gni") +import("//build_overrides/efr32_sdk.gni") +import("${efr32_sdk_build_root}/silabs_board.gni") + +if (wifi_soc) { + import("${efr32_sdk_build_root}/SiWx917_sdk.gni") +} else { + import("${efr32_sdk_build_root}/efr32_sdk.gni") +} + +source_set("storage") { + sources = [ "ProvisionStorageCustom.cpp" ] + + if (use_provision_flash_storage) { + sources += [ "ProvisionStorageFlash.cpp" ] + } else { + sources += [ "ProvisionStorageDefault.cpp" ] + } + + if (wifi_soc) { + if (sl_si91x_crypto_flavor == "psa") { + libs = + [ "${sdk_support_root}/matter/provision/lib/libProvisionPSA_si917.a" ] + } else { + libs = [ "${sdk_support_root}/matter/provision/lib/libProvision_si917.a" ] + } + } else { + if (use_provision_flash_storage) { + libs = [ "${sdk_support_root}/matter/provision/lib/libProvisionFlash_${silabs_family}.a" ] + } else { + libs = [ "${sdk_support_root}/matter/provision/lib/libProvision_${silabs_family}.a" ] + } + } + + deps = [ "${chip_root}/src/lib" ] + public_deps = + [ "${chip_root}/src/platform/silabs/provision:provision-headers" ] +} diff --git a/examples/platform/silabs/efr32/uart.cpp b/examples/platform/silabs/uart.cpp similarity index 89% rename from examples/platform/silabs/efr32/uart.cpp rename to examples/platform/silabs/uart.cpp index 80d2dbba63b3a8..7d6dad912314db 100644 --- a/examples/platform/silabs/efr32/uart.cpp +++ b/examples/platform/silabs/uart.cpp @@ -18,14 +18,31 @@ #include "AppConfig.h" #include "matter_shell.h" #include +#include #include #ifdef __cplusplus extern "C" { #endif -#include "assert.h" + +#include "uart.h" +#include +#include + +#define UART_CONSOLE_ERR -1 // Negative value in case of UART Console action failed. Triggers a failure for PW_RPC +#define MAX_BUFFER_SIZE 256 +#define MAX_DMA_BUFFER_SIZE (MAX_BUFFER_SIZE / 2) + +#if SLI_SI91X_MCU_INTERFACE +#include "USART.h" +#include "rsi_board.h" +#include "rsi_debug.h" +#include "rsi_rom_egpio.h" +#include "sl_si91x_usart.h" +#else // For EFR32 #include "em_core.h" #include "em_usart.h" +#include "uartdrv.h" #ifdef SL_BOARD_NAME #include "sl_board_control.h" #endif @@ -38,11 +55,7 @@ extern "C" { #endif #ifdef SL_CATALOG_UARTDRV_USART_PRESENT #include "sl_uartdrv_usart_vcom_config.h" -#endif // EFR32MG24 -#include "uart.h" -#include "uartdrv.h" -#include -#include +#endif // SL_CATALOG_UARTDRV_USART_PRESENT #if defined(SL_CATALOG_POWER_MANAGER_PRESENT) #include "sl_power_manager.h" @@ -79,6 +92,16 @@ extern "C" { #define vcom_handle sl_uartdrv_usart_vcom_handle #endif // EFR32MG24 +namespace { +// In order to reduce the probability of data loss during the dmaFull callback handler we use +// two duplicate receive buffers so we can always have one "active" receive queue. +uint8_t sRxDmaBuffer[MAX_DMA_BUFFER_SIZE] = { 0 }; +uint8_t sRxDmaBuffer2[MAX_DMA_BUFFER_SIZE] = { 0 }; +uint16_t lastCount = 0; // Nb of bytes already processed from the active dmaBuffer +} // namespace + +#endif // SLI_SI91X_MCU_INTERFACE + typedef struct { // The data buffer @@ -91,15 +114,6 @@ typedef struct uint16_t MaxSize; } Fifo_t; -#define UART_CONSOLE_ERR -1 // Negative value in case of UART Console action failed. Triggers a failure for PW_RPC -#define MAX_BUFFER_SIZE 256 -#define MAX_DMA_BUFFER_SIZE (MAX_BUFFER_SIZE / 2) -// In order to reduce the probability of data loss during the dmaFull callback handler we use -// two duplicate receive buffers so we can always have one "active" receive queue. -static uint8_t sRxDmaBuffer[MAX_DMA_BUFFER_SIZE]; -static uint8_t sRxDmaBuffer2[MAX_DMA_BUFFER_SIZE]; -static uint16_t lastCount; // Nb of bytes already processed from the active dmaBuffer - // uart transmit #if SILABS_LOG_OUT_UART #define UART_MAX_QUEUE_SIZE 125 @@ -144,7 +158,9 @@ constexpr osMessageQueueAttr_t kUartTxQueueAttr = { .cb_mem = &sUartTxQueueStru static uint8_t sRxFifoBuffer[MAX_BUFFER_SIZE]; static Fifo_t sReceiveFifo; +#if SLI_SI91X_MCU_INTERFACE == 0 static void UART_rx_callback(UARTDRV_Handle_t handle, Ecode_t transferStatus, uint8_t * data, UARTDRV_Count_t transferCount); +#endif // SLI_SI91X_MCU_INTERFACE == 0 static void uartSendBytes(uint8_t * buffer, uint16_t nbOfBytes); static bool InitFifo(Fifo_t * fifo, uint8_t * pDataBuffer, uint16_t bufferSize) @@ -196,9 +212,9 @@ static uint16_t RemainingSpace(Fifo_t * fifo) */ static void WriteToFifo(Fifo_t * fifo, uint8_t * pDataToWrite, uint16_t SizeToWrite) { - assert(fifo); - assert(pDataToWrite); - assert(SizeToWrite <= fifo->MaxSize); + VerifyOrDie(fifo != nullptr); + VerifyOrDie(pDataToWrite != nullptr); + VerifyOrDie(SizeToWrite <= fifo->MaxSize); // Overwrite is not allowed if (RemainingSpace(fifo) >= SizeToWrite) @@ -227,9 +243,9 @@ static void WriteToFifo(Fifo_t * fifo, uint8_t * pDataToWrite, uint16_t SizeToWr */ static uint16_t RetrieveFromFifo(Fifo_t * fifo, uint8_t * pData, uint16_t SizeToRead) { - assert(fifo); - assert(pData); - assert(SizeToRead <= fifo->MaxSize); + VerifyOrDie(fifo != nullptr); + VerifyOrDie(pData != nullptr); + VerifyOrDie(SizeToRead <= fifo->MaxSize); uint16_t ReadSize = MIN(SizeToRead, AvailableDataCount(fifo)); uint16_t nBytesBeforWrap = (fifo->MaxSize - fifo->Head); @@ -263,22 +279,24 @@ void uartConsoleInit(void) return; } + sUartTxQueue = osMessageQueueNew(UART_MAX_QUEUE_SIZE, sizeof(UartTxStruct_t), &kUartTxQueueAttr); + sUartTaskHandle = osThreadNew(uartMainLoop, nullptr, &kUartTaskAttr); + + // Init a fifo for the data received on the uart + InitFifo(&sReceiveFifo, sRxFifoBuffer, MAX_BUFFER_SIZE); + + VerifyOrDie(sUartTaskHandle != nullptr); + VerifyOrDie(sUartTxQueue != nullptr); + +#if SLI_SI91X_MCU_INTERFACE == 0 #ifdef SL_BOARD_NAME sl_board_enable_vcom(); #endif - // Init a fifo for the data received on the uart - InitFifo(&sReceiveFifo, sRxFifoBuffer, MAX_BUFFER_SIZE); // Activate 2 dma queues to always have one active UARTDRV_Receive(vcom_handle, sRxDmaBuffer, MAX_DMA_BUFFER_SIZE, UART_rx_callback); UARTDRV_Receive(vcom_handle, sRxDmaBuffer2, MAX_DMA_BUFFER_SIZE, UART_rx_callback); - sUartTxQueue = osMessageQueueNew(UART_MAX_QUEUE_SIZE, sizeof(UartTxStruct_t), &kUartTxQueueAttr); - sUartTaskHandle = osThreadNew(uartMainLoop, nullptr, &kUartTaskAttr); - - assert(sUartTaskHandle); - assert(sUartTxQueue); - // Enable USART0/EUSART0 interrupt to wake OT task when data arrives NVIC_ClearPendingIRQ(USART_IRQ); NVIC_EnableIRQ(USART_IRQ); @@ -295,8 +313,24 @@ void uartConsoleInit(void) #else USART_IntEnable(SL_UARTDRV_USART_VCOM_PERIPHERAL, USART_IF_RXDATAV); #endif // EFR32MG24 +#endif // SLI_SI91X_MCU_INTERFACE == 0 +} + +#if SLI_SI91X_MCU_INTERFACE +void cache_uart_rx_data(char character) +{ + if (RemainingSpace(&sReceiveFifo) >= 1) + { + WriteToFifo(&sReceiveFifo, (uint8_t *) &character, 1); + } +#ifdef ENABLE_CHIP_SHELL + chip::NotifyShellProcess(); +#endif // ENABLE_CHIP_SHELL } +#endif // SLI_SI91X_MCU_INTERFACE +#if SLI_SI91X_MCU_INTERFACE == 0 +// For EFR32 void USART_IRQHandler(void) { #ifdef ENABLE_CHIP_SHELL @@ -346,6 +380,7 @@ static void UART_rx_callback(UARTDRV_Handle_t handle, Ecode_t transferStatus, ui otSysEventSignalPending(); #endif } +#endif // SLI_SI91X_MCU_INTERFACE == 0 /** * @brief Read the data available from the console Uart @@ -420,15 +455,15 @@ int16_t uartLogWrite(const char * log, uint16_t length) int16_t uartConsoleRead(char * Buf, uint16_t NbBytesToRead) { uint8_t * data; - UARTDRV_Count_t count, remaining; if (Buf == NULL || NbBytesToRead < 1) { return UART_CONSOLE_ERR; } - +#if SLI_SI91X_MCU_INTERFACE == 0 if (NbBytesToRead > AvailableDataCount(&sReceiveFifo)) { + UARTDRV_Count_t count, remaining; // Not enough data available in the fifo for the read size request // If there is data available in dma buffer, get it now. CORE_ATOMIC_SECTION(UARTDRV_GetReceiveStatus(vcom_handle, &data, &count, &remaining); if (count > lastCount) { @@ -436,6 +471,7 @@ int16_t uartConsoleRead(char * Buf, uint16_t NbBytesToRead) lastCount = count; }) } +#endif // SLI_SI91X_MCU_INTERFACE == 0 return (int16_t) RetrieveFromFifo(&sReceiveFifo, (uint8_t *) Buf, NbBytesToRead); } @@ -464,6 +500,14 @@ void uartMainLoop(void * args) */ void uartSendBytes(uint8_t * buffer, uint16_t nbOfBytes) { +#if SLI_SI91X_MCU_INTERFACE + // ensuring null termination of buffer + if (nbOfBytes != CHIP_SHELL_MAX_LINE_SIZE && buffer[nbOfBytes - 1] != '\0') + { + buffer[nbOfBytes] = '\0'; + } + Board_UARTPutSTR(reinterpret_cast(buffer)); +#else #if defined(SL_CATALOG_POWER_MANAGER_PRESENT) sl_power_manager_add_em_requirement(SL_POWER_MANAGER_EM1); #endif // SL_CATALOG_POWER_MANAGER_PRESENT @@ -489,6 +533,7 @@ void uartSendBytes(uint8_t * buffer, uint16_t nbOfBytes) #if defined(SL_CATALOG_POWER_MANAGER_PRESENT) sl_power_manager_remove_em_requirement(SL_POWER_MANAGER_EM1); #endif // SL_CATALOG_POWER_MANAGER_PRESENT +#endif // SLI_SI91X_MCU_INTERFACE } #ifdef __cplusplus diff --git a/examples/rvc-app/README.md b/examples/rvc-app/README.md index 2943f54103f828..da9317f508fe39 100644 --- a/examples/rvc-app/README.md +++ b/examples/rvc-app/README.md @@ -20,6 +20,46 @@ must have a `"Name"` key that contains the command name. This name is shown in the state machine diagram above. Example `echo '{"Name": "Charged"}' > /tmp/chip_rvc_fifo_42`. +### ServiceArea related messages + +#### `AddMap` message + +This message adds a map to the SupportedMaps attribute of the Service Area +cluster. This message requires the following extra keys. + +- `MapId` This is an `int` setting the ID of the new map. +- `MapName` This is a `string` setting the name of the new map. + +#### `AddArea` message + +This message adds a new area to the SupportedAreas attribute of the Service Area +cluster. This message requires the following extra keys, most of which are +optional. Consult the `SupportedAreas` attribute spec for more information on +what are valid areas. + +- `AreaId` This is an `int` setting the ID of the area. +- `MapId` This is an `int` sitting the map ID the area is associated with. +- `LocationName` This is a `string` setting the location's name. +- `FloorNumber` This is an `int` setting the floor number of the area. +- `AreaType` This is an `int` setting the area type tag. +- `LandmarkTag` This is an `int` setting the landmark tag. +- `PositianTag` This is an `int` setting the position tag. + +#### `RemoveMap` message + +This message removes a map with the given map ID. This message requires the +`int` key `MapId`. + +#### `RemoveArea` message + +This message removes an area with the given area ID. This message requires the +`int` key `AreaId`. + +#### `AreaComplete` message + +This indicates that the area currently being serviced as indicated by the +service area cluster is now complete. + ### `ErrorEvent` message The error event message requires the additional key `"Error"` which specifies @@ -37,10 +77,14 @@ and setting up the testing environment, python tests can be executed with `./scripts/tests/run_python_test.py --script src/python_testing/.py --script-args "--storage-path admin_storage.json --PICS examples/rvc-app/rvc-common/pics/RVC_App_Test_Plan.txt --int-arg "` **Note:** If the testing environment has not been commissioned with the RVC app, -use chip-tool to switch on the commissioning window -`chip-tool pairing open-commissioning-window`, and add the following flags to -the `--script-args` above. -`--commissioning-method on-network --discriminator XXXX --passcode XXXX`. + +1. use chip-tool to switch on the commissioning window + `out/debug/chip-tool pairing open-commissioning-window 0x1230 1 180 1000 42` +2. Get the manual pairing code. This will look something like + `Manual pairing code: [01073112097]`. +3. Run any one of the tests with the `--commission-only` and `--manual-code` + flags: + `./scripts/tests/run_python_test.py --script src/python_testing/TC_RVCCLEANM_1_2.py --script-args "--commissioning-method on-network --manual-code 01073112097 --commission-only"` Below are the PIXIT definitions required for the different python tests. @@ -127,3 +171,33 @@ to transition to the required states. After commissioning the device, all the yaml tests can be run by running the `run_all_yaml_tests.sh` script from the root dir with the node ID that the device was commissioned with. + +### Service Area Cluster + +### TC 1.2 + +Example command: +`./scripts/tests/run_python_test.py --script src/python_testing/TC_SEAR_1_2.py --script-args "--storage-path admin_storage.json --PICS examples/rvc-app/rvc-common/pics/rvc-app-pics-values --endpoint 1"` + +### TC 1.3 + +todo once the +[test plan issue](https://github.com/CHIP-Specifications/chip-test-plans/issues/4454) +is resolved, add the required PIXIT and set the +PICS`SEAR.S.M.VALID_STATE_FOR_SELECT_AREAS=1`. PIXIT: `` Example command: +`./scripts/tests/run_python_test.py --script src/python_testing/TC_SEAR_1_3.py --script-args "--storage-path admin_storage.json --PICS examples/rvc-app/rvc-common/pics/rvc-app-pics-values --endpoint 1` + +### TC 1.4 + +Example command: +`./scripts/tests/run_python_test.py --script src/python_testing/TC_SEAR_1_4.py --script-args "--storage-path admin_storage.json --PICS examples/rvc-app/rvc-common/pics/rvc-app-pics-values --endpoint 1` + +#### TC 1.5 + +Example command: +`./scripts/tests/run_python_test.py --script src/python_testing/TC_SEAR_1_5.py --script-args "--storage-path admin_storage.json --PICS examples/rvc-app/rvc-common/pics/rvc-app-pics-values --endpoint 1"` + +#### TC 1.6 + +Example command: +`./scripts/tests/run_python_test.py --script src/python_testing/TC_SEAR_1_6.py --script-args "--storage-path admin_storage.json --PICS examples/rvc-app/rvc-common/pics/rvc-app-pics-values --endpoint 1` diff --git a/examples/rvc-app/linux/RvcAppCommandDelegate.cpp b/examples/rvc-app/linux/RvcAppCommandDelegate.cpp index 58610e1b11d112..791df4d482cfe8 100644 --- a/examples/rvc-app/linux/RvcAppCommandDelegate.cpp +++ b/examples/rvc-app/linux/RvcAppCommandDelegate.cpp @@ -17,6 +17,7 @@ */ #include "RvcAppCommandDelegate.h" +#include #include #include "rvc-device.h" @@ -24,6 +25,7 @@ #include using namespace chip; +using namespace chip::app; using namespace chip::app::Clusters; RvcAppCommandHandler * RvcAppCommandHandler::FromJSON(const char * json) @@ -83,6 +85,29 @@ void RvcAppCommandHandler::HandleCommand(intptr_t context) { self->OnActivityCompleteHandler(); } + else if (name == "AreaComplete") + { + self->OnAreaCompleteHandler(); + } + else if (name == "AddMap") + { + self->OnAddServiceAreaMap(self->mJsonValue); + } + else if (name == "AddArea") + { + VerifyOrExit(self->mJsonValue.isMember("AreaId"), ChipLogError(NotSpecified, "RVC App: AreaId key is missing")); + self->OnAddServiceAreaArea(self->mJsonValue); + } + else if (name == "RemoveMap") + { + VerifyOrExit(self->mJsonValue.isMember("MapId"), ChipLogError(NotSpecified, "RVC App: MapId key is missing")); + self->OnRemoveServiceAreaMap(self->mJsonValue["MapId"].asUInt()); + } + else if (name == "RemoveArea") + { + VerifyOrExit(self->mJsonValue.isMember("AreaId"), ChipLogError(NotSpecified, "RVC App: AreaId key is missing")); + self->OnRemoveServiceAreaArea(self->mJsonValue["AreaId"].asUInt()); + } else if (name == "ErrorEvent") { std::string error = self->mJsonValue["Error"].asString(); @@ -140,6 +165,78 @@ void RvcAppCommandHandler::OnActivityCompleteHandler() mRvcDevice->HandleActivityCompleteEvent(); } +void RvcAppCommandHandler::OnAreaCompleteHandler() +{ + mRvcDevice->HandleAreaCompletedEvent(); +} + +void RvcAppCommandHandler::OnAddServiceAreaMap(Json::Value jsonValue) +{ + // Find if self->mJsonValue has the MapId and MapName Keys + if (jsonValue.isMember("MapId") && jsonValue.isMember("MapName")) + { + uint32_t mapId = jsonValue["MapId"].asUInt(); + std::string mapName = jsonValue["MapName"].asString(); + mRvcDevice->HandleAddServiceAreaMap(mapId, CharSpan(mapName.data(), mapName.size())); + } + else + { + ChipLogError(NotSpecified, "RVC App: MapId and MapName keys are missing"); + } +} + +void RvcAppCommandHandler::OnAddServiceAreaArea(Json::Value jsonValue) +{ + ServiceArea::AreaStructureWrapper area; + area.SetAreaId(jsonValue["AreaId"].asUInt()); + if (jsonValue.isMember("MapId")) + { + area.SetMapId(jsonValue["MapId"].asUInt()); + } + + // Set the location info + if (jsonValue.isMember("LocationName") || jsonValue.isMember("FloorNumber") || jsonValue.isMember("AreaType")) + { + DataModel::Nullable floorNumber = DataModel::NullNullable; + if (jsonValue.isMember("FloorNumber")) + { + floorNumber = jsonValue["FloorNumber"].asInt(); + } + DataModel::Nullable areaType = DataModel::NullNullable; + if (jsonValue.isMember("AreaType")) + { + areaType = Globals::AreaTypeTag(jsonValue["AreaType"].asUInt()); + } + auto locationName = jsonValue["LocationName"].asString(); + + area.SetLocationInfo(CharSpan(locationName.data(), locationName.size()), floorNumber, areaType); + } + + // Set landmark info + if (jsonValue.isMember("LandmarkTag")) + { + DataModel::Nullable relativePositionTag = DataModel::NullNullable; + if (jsonValue.isMember("PositionTag")) + { + relativePositionTag = Globals::RelativePositionTag(jsonValue["PositionTag"].asUInt()); + } + + area.SetLandmarkInfo(Globals::LandmarkTag(jsonValue["LandmarkTag"].asUInt()), relativePositionTag); + } + + mRvcDevice->HandleAddServiceAreaArea(area); +} + +void RvcAppCommandHandler::OnRemoveServiceAreaMap(uint32_t mapId) +{ + mRvcDevice->HandleRemoveServiceAreaMap(mapId); +} + +void RvcAppCommandHandler::OnRemoveServiceAreaArea(uint32_t areaId) +{ + mRvcDevice->HandleRemoveServiceAreaArea(areaId); +} + void RvcAppCommandHandler::OnErrorEventHandler(const std::string & error) { mRvcDevice->HandleErrorEvent(error); diff --git a/examples/rvc-app/linux/RvcAppCommandDelegate.h b/examples/rvc-app/linux/RvcAppCommandDelegate.h index 366772bf0842ab..6f896641dab1c7 100644 --- a/examples/rvc-app/linux/RvcAppCommandDelegate.h +++ b/examples/rvc-app/linux/RvcAppCommandDelegate.h @@ -55,6 +55,16 @@ class RvcAppCommandHandler void OnActivityCompleteHandler(); + void OnAreaCompleteHandler(); + + void OnAddServiceAreaMap(Json::Value jsonValue); + + void OnAddServiceAreaArea(Json::Value jsonValue); + + void OnRemoveServiceAreaMap(uint32_t mapId); + + void OnRemoveServiceAreaArea(uint32_t areaId); + void OnErrorEventHandler(const std::string & error); void OnClearErrorHandler(); diff --git a/examples/rvc-app/rvc-common/include/rvc-device.h b/examples/rvc-app/rvc-common/include/rvc-device.h index 092ded91f76272..b66ce3251feba6 100644 --- a/examples/rvc-app/rvc-common/include/rvc-device.h +++ b/examples/rvc-app/rvc-common/include/rvc-device.h @@ -44,7 +44,8 @@ class RvcDevice mRunModeDelegate(), mRunModeInstance(&mRunModeDelegate, aRvcClustersEndpoint, RvcRunMode::Id, 0), mCleanModeDelegate(), mCleanModeInstance(&mCleanModeDelegate, aRvcClustersEndpoint, RvcCleanMode::Id, 0), mOperationalStateDelegate(), mOperationalStateInstance(&mOperationalStateDelegate, aRvcClustersEndpoint), mServiceAreaDelegate(), - mServiceAreaInstance(&mServiceAreaDelegate, aRvcClustersEndpoint, BitMask(0)) + mServiceAreaInstance(&mServiceAreaDelegate, aRvcClustersEndpoint, + BitMask(ServiceArea::Feature::kMaps, ServiceArea::Feature::kProgressReporting)) { // set the current-mode at start-up mRunModeInstance.UpdateCurrentMode(RvcRunMode::ModeIdle); @@ -58,6 +59,11 @@ class RvcDevice mOperationalStateDelegate.SetPauseCallback(&RvcDevice::HandleOpStatePauseCallback, this); mOperationalStateDelegate.SetResumeCallback(&RvcDevice::HandleOpStateResumeCallback, this); mOperationalStateDelegate.SetGoHomeCallback(&RvcDevice::HandleOpStateGoHomeCallback, this); + + mServiceAreaDelegate.SetIsSetSelectedAreasAllowedCallback(&RvcDevice::SaIsSetSelectedAreasAllowed, this); + mServiceAreaDelegate.SetHandleSkipCurrentAreaCallback(&RvcDevice::SaHandleSkipCurrentArea, this); + mServiceAreaDelegate.SetIsSupportedAreasChangeAllowedCallback(&RvcDevice::SaIsSupportedAreasChangeAllowed, this); + mServiceAreaDelegate.SetIsSupportedMapChangeAllowedCallback(&RvcDevice::SaIsSupportedMapChangeAllowed, this); } /** @@ -96,6 +102,14 @@ class RvcDevice */ void HandleOpStateGoHomeCallback(Clusters::OperationalState::GenericOperationalError & err); + bool SaIsSetSelectedAreasAllowed(MutableCharSpan & statusText); + + bool SaHandleSkipCurrentArea(uint32_t skippedArea, MutableCharSpan & skipStatusText); + + bool SaIsSupportedAreasChangeAllowed(); + + bool SaIsSupportedMapChangeAllowed(); + /** * Updates the state machine when the device becomes fully-charged. */ @@ -111,6 +125,16 @@ class RvcDevice void HandleActivityCompleteEvent(); + void HandleAreaCompletedEvent(); + + void HandleAddServiceAreaMap(uint32_t mapId, const CharSpan & mapName); + + void HandleAddServiceAreaArea(ServiceArea::AreaStructureWrapper & area); + + void HandleRemoveServiceAreaMap(uint32_t mapId); + + void HandleRemoveServiceAreaArea(uint32_t areaId); + /** * Sets the device to an error state with the error state ID matching the error name given. * @param error The error name. Could be one of UnableToStartOrResume, UnableToCompleteOperation, CommandInvalidInState, @@ -122,6 +146,12 @@ class RvcDevice void HandleClearErrorMessage(); void HandleResetMessage(); + + /** + * Updates the Service area progress elements when an activity has ended. + * Sets any remaining Operating or Pending states to Skipped. + */ + void UpdateServiceAreaProgressOnExit(); }; } // namespace Clusters diff --git a/examples/rvc-app/rvc-common/include/rvc-service-area-delegate.h b/examples/rvc-app/rvc-common/include/rvc-service-area-delegate.h index 40f312ffb78c2f..4c13fcd493d7eb 100644 --- a/examples/rvc-app/rvc-common/include/rvc-service-area-delegate.h +++ b/examples/rvc-app/rvc-common/include/rvc-service-area-delegate.h @@ -29,6 +29,10 @@ namespace Clusters { class RvcDevice; +typedef bool (RvcDevice::*IsSetSelectedAreasAllowedCallback)(MutableCharSpan & statusText); +typedef bool (RvcDevice::*HandleSkipCurrentAreaCallback)(uint32_t skippedArea, MutableCharSpan & skipStatusText); +typedef bool (RvcDevice::*IsChangeAllowedSimpleCallback)(); + namespace ServiceArea { class RvcServiceAreaDelegate : public Delegate @@ -40,35 +44,75 @@ class RvcServiceAreaDelegate : public Delegate std::vector mSelectedAreas; std::vector mProgressList; + RvcDevice * mIsSetSelectedAreasAllowedDeviceInstance; + IsSetSelectedAreasAllowedCallback mIsSetSelectedAreasAllowedCallback; + RvcDevice * mHandleSkipCurrentAreaDeviceInstance; + HandleSkipCurrentAreaCallback mHandleSkipCurrentAreaCallback; + RvcDevice * mIsSupportedAreasChangeAllowedDeviceInstance; + IsChangeAllowedSimpleCallback mIsSupportedAreasChangeAllowedCallback; + RvcDevice * mIsSupportedMapChangeAllowedDeviceInstance; + IsChangeAllowedSimpleCallback mIsSupportedMapChangeAllowedCallback; + + // hardcoded values for SUPPORTED MAPS. + const uint32_t supportedMapId_XX = 3; + const uint32_t supportedMapId_YY = 245; + + // hardcoded values for SUPPORTED AREAS. + const uint32_t supportedAreaID_A = 7; + const uint32_t supportedAreaID_B = 1234567; + const uint32_t supportedAreaID_C = 10050; + const uint32_t supportedAreaID_D = 0x88888888; + public: + /** + * Set the SupportedMaps and SupportedAreas where the SupportedMaps is not null. + */ + void SetMapTopology(); + + /** + * Set the SupportedMaps and SupportedAreas where the SupportedMaps is null. + */ + void SetNoMapTopology(); + CHIP_ERROR Init() override; // command support - bool IsSetSelectedAreasAllowed(MutableCharSpan statusText) override; + bool IsSetSelectedAreasAllowed(MutableCharSpan & statusText) override; bool IsValidSelectAreasSet(const ServiceArea::Commands::SelectAreas::DecodableType & req, - ServiceArea::SelectAreasStatus & locationStatus, MutableCharSpan statusText) override; + ServiceArea::SelectAreasStatus & areaStatus, MutableCharSpan & statusText) override; - bool HandleSkipCurrentArea(MutableCharSpan skipStatusText) override; + bool HandleSkipCurrentArea(uint32_t skippedArea, MutableCharSpan & skipStatusText) override; //************************************************************************* - // Supported Locations accessors + // Supported Areas accessors bool IsSupportedAreasChangeAllowed() override; uint32_t GetNumberOfSupportedAreas() override; - bool GetSupportedLocationByIndex(uint32_t listIndex, ServiceArea::AreaStructureWrapper & supportedLocation) override; + bool GetSupportedAreaByIndex(uint32_t listIndex, AreaStructureWrapper & supportedArea) override; - bool GetSupportedLocationById(uint32_t aAreaId, uint32_t & listIndex, - ServiceArea::AreaStructureWrapper & supportedLocation) override; + bool GetSupportedAreaById(uint32_t aAreaId, uint32_t & listIndex, AreaStructureWrapper & supportedArea) override; - bool AddSupportedLocation(const ServiceArea::AreaStructureWrapper & newArea, uint32_t & listIndex) override; + bool AddSupportedArea(const AreaStructureWrapper & newArea, uint32_t & listIndex) override; - bool ModifySupportedLocation(uint32_t listIndex, const ServiceArea::AreaStructureWrapper & modifiedLocation) override; + bool ModifySupportedArea(uint32_t listIndex, const AreaStructureWrapper & modifiedArea) override; bool ClearSupportedAreas() override; + /** + * This is a more sophisticated way of ensuring that we all attributes are still valid when a supported area is removed. + * Rather than clearing all the attributes that depend on the supported aeras, we only remove the elements that point to + * the removed supported areas. + */ + void HandleSupportedAreasUpdated() override; + + /** + * Note: Call the HandleSupportedAreasUpdated() method when finished removing supported areas. + */ + bool RemoveSupportedArea(uint32_t areaId); + //************************************************************************* // Supported Maps accessors @@ -78,7 +122,7 @@ class RvcServiceAreaDelegate : public Delegate bool GetSupportedMapByIndex(uint32_t listIndex, ServiceArea::MapStructureWrapper & supportedMap) override; - bool GetSupportedMapById(uint8_t aMapId, uint32_t & listIndex, ServiceArea::MapStructureWrapper & supportedMap) override; + bool GetSupportedMapById(uint32_t aMapId, uint32_t & listIndex, ServiceArea::MapStructureWrapper & supportedMap) override; bool AddSupportedMap(const ServiceArea::MapStructureWrapper & newMap, uint32_t & listIndex) override; @@ -86,16 +130,16 @@ class RvcServiceAreaDelegate : public Delegate bool ClearSupportedMaps() override; + bool RemoveSupportedMap(uint32_t mapId); + //************************************************************************* - // Selected Locations accessors + // Selected Areas accessors uint32_t GetNumberOfSelectedAreas() override; - bool GetSelectedLocationByIndex(uint32_t listIndex, uint32_t & selectedLocation) override; - - // IsSelectedLocation() no override + bool GetSelectedAreaByIndex(uint32_t listIndex, uint32_t & selectedArea) override; - bool AddSelectedLocation(uint32_t aAreaId, uint32_t & listIndex) override; + bool AddSelectedArea(uint32_t aAreaId, uint32_t & listIndex) override; bool ClearSelectedAreas() override; @@ -115,6 +159,50 @@ class RvcServiceAreaDelegate : public Delegate const ServiceArea::Structs::ProgressStruct::Type & modifiedProgressElement) override; bool ClearProgress() override; + + //************************************************************************* + // RVC device callback setters + + void SetIsSetSelectedAreasAllowedCallback(IsSetSelectedAreasAllowedCallback callback, RvcDevice * instance) + { + mIsSetSelectedAreasAllowedCallback = callback; + mIsSetSelectedAreasAllowedDeviceInstance = instance; + } + + void SetHandleSkipCurrentAreaCallback(HandleSkipCurrentAreaCallback callback, RvcDevice * instance) + { + mHandleSkipCurrentAreaCallback = callback; + mHandleSkipCurrentAreaDeviceInstance = instance; + } + + void SetIsSupportedAreasChangeAllowedCallback(IsChangeAllowedSimpleCallback callback, RvcDevice * instance) + { + mIsSupportedAreasChangeAllowedCallback = callback; + mIsSupportedAreasChangeAllowedDeviceInstance = instance; + } + + void SetIsSupportedMapChangeAllowedCallback(IsChangeAllowedSimpleCallback callback, RvcDevice * instance) + { + mIsSupportedMapChangeAllowedCallback = callback; + mIsSupportedMapChangeAllowedDeviceInstance = instance; + } + + //************************************************************************* + // Helper methods for setting service area attributes. + + /** + * Sets the service area attributes at the start of a clean. + * This includes the current area an progress attributes. + */ + void SetAttributesAtCleanStart(); + + /** + * Go to the next area in the list of selected areas. + * @param currentAreaOpState The operational state to be set in the Status field of the Progress attribute for the current area. + * This can only be Completed or Skipped. + * @param finished true if there are no more areas to clean an we should end the clean. + */ + void GoToNextArea(OperationalStatusEnum currentAreaOpState, bool & finished); }; } // namespace ServiceArea diff --git a/examples/rvc-app/rvc-common/pics/rvc-app-pics-values b/examples/rvc-app/rvc-common/pics/rvc-app-pics-values index 669abd26c33f94..c38f0c1b7e00a0 100644 --- a/examples/rvc-app/rvc-common/pics/rvc-app-pics-values +++ b/examples/rvc-app/rvc-common/pics/rvc-app-pics-values @@ -50,3 +50,31 @@ RVCRUNM.S.C01.Tx=1 RVCRUNM.S.F00=0 RVCRUNM.S.M.CAN_TEST_MODE_FAILURE=1 RVCRUNM.S.M.CAN_MANUALLY_CONTROLLED=1 + +SEAR.S=1 +SEAR.S.F00=0 +SEAR.S.F01=1 +SEAR.S.F02=1 +SEAR.S.A0000=1 +SEAR.S.A0001=1 +SEAR.S.A0002=1 +SEAR.S.A0003=1 +SEAR.S.A0004=1 +SEAR.S.A0005=1 +SEAR.S.C00.Rsp=1 +SEAR.S.C02.Rsp=1 +SEAR.S.C01.Tx=1 +SEAR.S.C03.Tx=1 +SEAR.S.M.REMOVE_AREA=1 +SEAR.S.M.ADD_AREA=1 +SEAR.S.M.REMOVE_MAP=1 +SEAR.S.M.ADD_MAP=1 +SEAR.S.M.INVALID_STATE_FOR_SELECT_AREAS=1 +SEAR.S.M.VALID_STATE_FOR_SELECT_AREAS=0 +SEAR.S.M.SELECT_AREAS_WHILE_NON_IDLE=1 +SEAR.S.M.HAS_MANUAL_SELAREA_STATE_CONTROL=1 +SEAR.S.M.HAS_MANUAL_SKIP_STATE_CONTROL=1 +SEAR.S.M.INVALID_STATE_FOR_SKIP=1 +SEAR.S.M.NO_SELAREA_FOR_SKIP=1 +SEAR.S.M.VALID_STATE_FOR_SKIP=1 +SEAR.S.M.HAS_MANUAL_OPERATING_STATE_CONTROL=1 \ No newline at end of file diff --git a/examples/rvc-app/rvc-common/rvc-app.matter b/examples/rvc-app/rvc-common/rvc-app.matter index 7a87e9e83dbe90..4467c170acc6eb 100644 --- a/examples/rvc-app/rvc-common/rvc-app.matter +++ b/examples/rvc-app/rvc-common/rvc-app.matter @@ -1424,9 +1424,9 @@ cluster RvcOperationalState = 97 { command GoHome(): OperationalCommandResponse = 128; } -/** The Service Area cluster provides an interface for controlling the locations where a device should operate, and for querying the current location. */ +/** The Service Area cluster provides an interface for controlling the areas where a device should operate, and for querying the current area being serviced. */ provisional cluster ServiceArea = 336 { - revision 1; // NOTE: Default/not specifically set + revision 1; enum OperationalStatusEnum : enum8 { kPending = 0; @@ -1447,28 +1447,33 @@ provisional cluster ServiceArea = 336 { kSuccess = 0; kInvalidAreaList = 1; kInvalidInMode = 2; + kInvalidSkippedArea = 3; } bitmap Feature : bitmap32 { - kListOrder = 0x1; - kSelectWhileRunning = 0x2; + kSelectWhileRunning = 0x1; + kProgressReporting = 0x2; + kMaps = 0x4; + } + + struct LandmarkInfoStruct { + LandmarkTag landmarkTag = 0; + nullable RelativePositionTag positionTag = 1; } struct AreaInfoStruct { nullable LocationDescriptorStruct locationInfo = 0; - nullable LandmarkTag landmarkTag = 1; - nullable PositionTag positionTag = 2; - nullable FloorSurfaceTag surfaceTag = 3; + nullable LandmarkInfoStruct landmarkInfo = 1; } struct AreaStruct { int32u areaID = 0; - nullable int8u mapID = 1; + nullable int32u mapID = 1; AreaInfoStruct areaDesc = 2; } struct MapStruct { - int8u mapID = 0; + int32u mapID = 0; char_string<64> name = 1; } @@ -1480,7 +1485,7 @@ provisional cluster ServiceArea = 336 { } readonly attribute AreaStruct supportedAreas[] = 0; - readonly attribute MapStruct supportedMaps[] = 1; + readonly attribute optional MapStruct supportedMaps[] = 1; readonly attribute int32u selectedAreas[] = 2; readonly attribute optional nullable int32u currentArea = 3; readonly attribute optional nullable epoch_s estimatedEndTime = 4; @@ -1498,18 +1503,22 @@ provisional cluster ServiceArea = 336 { response struct SelectAreasResponse = 1 { SelectAreasStatus status = 0; - optional char_string<256> statusText = 1; + char_string<256> statusText = 1; + } + + request struct SkipAreaRequest { + int32u skippedArea = 0; } response struct SkipAreaResponse = 3 { SkipAreaStatus status = 0; - optional char_string<256> statusText = 1; + char_string<256> statusText = 1; } /** Command used to select a set of device areas, where the device is to operate. */ command SelectAreas(SelectAreasRequest): SelectAreasResponse = 0; /** This command is used to skip an area where the device operates. */ - command SkipArea(): SkipAreaResponse = 2; + command SkipArea(SkipAreaRequest): SkipAreaResponse = 2; } endpoint 0 { diff --git a/examples/rvc-app/rvc-common/src/rvc-device.cpp b/examples/rvc-app/rvc-common/src/rvc-device.cpp index e018e0929301c7..623c95963f8834 100644 --- a/examples/rvc-app/rvc-common/src/rvc-device.cpp +++ b/examples/rvc-app/rvc-common/src/rvc-device.cpp @@ -52,6 +52,7 @@ void RvcDevice::HandleRvcRunChangeToMode(uint8_t newMode, ModeBase::Commands::Ch mDocked = false; mRunModeInstance.UpdateCurrentMode(newMode); mOperationalStateInstance.SetOperationalState(to_underlying(OperationalState::OperationalStateEnum::kRunning)); + mServiceAreaDelegate.SetAttributesAtCleanStart(); response.status = to_underlying(ModeBase::StatusCode::kSuccess); return; } @@ -68,6 +69,8 @@ void RvcDevice::HandleRvcRunChangeToMode(uint8_t newMode, ModeBase::Commands::Ch mRunModeInstance.UpdateCurrentMode(newMode); mOperationalStateInstance.SetOperationalState(to_underlying(RvcOperationalState::OperationalStateEnum::kSeekingCharger)); response.status = to_underlying(ModeBase::StatusCode::kSuccess); + + UpdateServiceAreaProgressOnExit(); return; } break; @@ -161,6 +164,55 @@ void RvcDevice::HandleOpStateGoHomeCallback(Clusters::OperationalState::GenericO } } +bool RvcDevice::SaIsSetSelectedAreasAllowed(MutableCharSpan & statusText) +{ + if (mOperationalStateInstance.GetCurrentOperationalState() == to_underlying(OperationalState::OperationalStateEnum::kRunning)) + { + CopyCharSpanToMutableCharSpan("cannot set the Selected Areas while the device is running"_span, statusText); + return false; + } + return true; +} + +bool RvcDevice::SaHandleSkipCurrentArea(uint32_t skippedArea, MutableCharSpan & skipStatusText) +{ + if (mServiceAreaInstance.GetCurrentArea() != skippedArea) + { + // This device only supports skipping the current location. + CopyCharSpanToMutableCharSpan("the skipped area does not match the current area"_span, skipStatusText); + return false; + } + + if (mOperationalStateInstance.GetCurrentOperationalState() != to_underlying(OperationalState::OperationalStateEnum::kRunning)) + { + // This device only accepts the skip are command while in the running state + CopyCharSpanToMutableCharSpan("skip area is only accepted when the device is running"_span, skipStatusText); + return false; + } + + bool finished; + mServiceAreaDelegate.GoToNextArea(ServiceArea::OperationalStatusEnum::kSkipped, finished); + + if (finished) + { + HandleActivityCompleteEvent(); + } + + return true; +} + +bool RvcDevice::SaIsSupportedAreasChangeAllowed() +{ + return mOperationalStateInstance.GetCurrentOperationalState() != + to_underlying(OperationalState::OperationalStateEnum::kRunning); +} + +bool RvcDevice::SaIsSupportedMapChangeAllowed() +{ + return mOperationalStateInstance.GetCurrentOperationalState() != + to_underlying(OperationalState::OperationalStateEnum::kRunning); +} + void RvcDevice::HandleChargedMessage() { if (mOperationalStateInstance.GetCurrentOperationalState() != @@ -258,6 +310,41 @@ void RvcDevice::HandleActivityCompleteEvent() mOperationalStateInstance.OnOperationCompletionDetected(0, a, b); mOperationalStateInstance.SetOperationalState(to_underlying(RvcOperationalState::OperationalStateEnum::kSeekingCharger)); + + mServiceAreaInstance.SetCurrentArea(DataModel::NullNullable); + mServiceAreaInstance.SetEstimatedEndTime(DataModel::NullNullable); + UpdateServiceAreaProgressOnExit(); +} + +void RvcDevice::HandleAreaCompletedEvent() +{ + bool finished; + mServiceAreaDelegate.GoToNextArea(ServiceArea::OperationalStatusEnum::kCompleted, finished); + + if (finished) + { + HandleActivityCompleteEvent(); + } +} + +void RvcDevice::HandleAddServiceAreaMap(uint32_t mapId, const CharSpan & mapName) +{ + mServiceAreaInstance.AddSupportedMap(mapId, mapName); +} + +void RvcDevice::HandleAddServiceAreaArea(ServiceArea::AreaStructureWrapper & area) +{ + mServiceAreaInstance.AddSupportedArea(area); +} + +void RvcDevice::HandleRemoveServiceAreaMap(uint32_t mapId) +{ + mServiceAreaDelegate.RemoveSupportedMap(mapId); +} + +void RvcDevice::HandleRemoveServiceAreaArea(uint32_t areaId) +{ + mServiceAreaDelegate.RemoveSupportedArea(areaId); } void RvcDevice::HandleErrorEvent(const std::string & error) @@ -334,4 +421,31 @@ void RvcDevice::HandleResetMessage() mRunModeInstance.UpdateCurrentMode(RvcRunMode::ModeIdle); mOperationalStateInstance.SetOperationalState(to_underlying(OperationalState::OperationalStateEnum::kStopped)); mCleanModeInstance.UpdateCurrentMode(RvcCleanMode::ModeQuick); + + mServiceAreaInstance.ClearSelectedAreas(); + mServiceAreaInstance.ClearProgress(); + mServiceAreaInstance.SetCurrentArea(DataModel::NullNullable); + mServiceAreaInstance.SetEstimatedEndTime(DataModel::NullNullable); + + mServiceAreaDelegate.SetMapTopology(); +} + +void RvcDevice::UpdateServiceAreaProgressOnExit() +{ + if (!mServiceAreaInstance.HasFeature(ServiceArea::Feature::kProgressReporting)) + { + return; + } + + uint32_t i = 0; + ServiceArea::Structs::ProgressStruct::Type progressElement; + while (mServiceAreaDelegate.GetProgressElementByIndex(i, progressElement)) + { + if (progressElement.status == ServiceArea::OperationalStatusEnum::kOperating || + progressElement.status == ServiceArea::OperationalStatusEnum::kPending) + { + mServiceAreaInstance.SetProgressStatus(progressElement.areaID, ServiceArea::OperationalStatusEnum::kSkipped); + } + i++; + } } diff --git a/examples/rvc-app/rvc-common/src/rvc-service-area-delegate.cpp b/examples/rvc-app/rvc-common/src/rvc-service-area-delegate.cpp index e46d3eaa22dff7..984472977a0356 100644 --- a/examples/rvc-app/rvc-common/src/rvc-service-area-delegate.cpp +++ b/examples/rvc-app/rvc-common/src/rvc-service-area-delegate.cpp @@ -17,53 +17,88 @@ */ #include #include +#include using namespace chip; using namespace chip::app::Clusters; using namespace chip::app::Clusters::ServiceArea; -CHIP_ERROR RvcServiceAreaDelegate::Init() +void RvcServiceAreaDelegate::SetMapTopology() { - // hardcoded fill of SUPPORTED MAPS for prototyping - uint8_t supportedMapId_XX = 3; - uint8_t supportedMapId_YY = 245; + GetInstance()->ClearSupportedMaps(); GetInstance()->AddSupportedMap(supportedMapId_XX, "My Map XX"_span); GetInstance()->AddSupportedMap(supportedMapId_YY, "My Map YY"_span); - // hardcoded fill of SUPPORTED LOCATIONS for prototyping - uint32_t supportedAreaID_A = 7; - uint32_t supportedAreaID_B = 1234567; - uint32_t supportedAreaID_C = 10050; - uint32_t supportedAreaID_D = 0x88888888; - - // Location A has name, floor number, uses map XX - GetInstance()->AddSupportedLocation( - supportedAreaID_A, DataModel::Nullable(supportedMapId_XX), "My Location A"_span, - DataModel::Nullable(4), DataModel::Nullable(), DataModel::Nullable(), - DataModel::Nullable(), DataModel::Nullable()); - - // Location B has name, uses map XX - GetInstance()->AddSupportedLocation( - supportedAreaID_B, DataModel::Nullable(supportedMapId_XX), "My Location B"_span, - DataModel::Nullable(), DataModel::Nullable(), DataModel::Nullable(), - DataModel::Nullable(), DataModel::Nullable()); - - // Location C has full SemData, no name, Map YY - GetInstance()->AddSupportedLocation(supportedAreaID_C, DataModel::Nullable(supportedMapId_YY), CharSpan(), - DataModel::Nullable(-1), - DataModel::Nullable(Globals::AreaTypeTag::kPlayRoom), - DataModel::Nullable(Globals::LandmarkTag::kBackDoor), - DataModel::Nullable(Globals::PositionTag::kLeft), - DataModel::Nullable(Globals::FloorSurfaceTag::kConcrete)); - - // Location D has null values for all HomeLocationStruct fields, Map YY - GetInstance()->AddSupportedLocation(supportedAreaID_D, DataModel::Nullable(supportedMapId_YY), - "My Location D"_span, DataModel::Nullable(), - DataModel::Nullable(), - DataModel::Nullable(Globals::LandmarkTag::kCouch), - DataModel::Nullable(Globals::PositionTag::kLeft), - DataModel::Nullable(Globals::FloorSurfaceTag::kHardwood)); + // Area A has name, floor number, uses map XX + auto areaA = + AreaStructureWrapper{} + .SetAreaId(supportedAreaID_A) + .SetMapId(supportedMapId_XX) + .SetLocationInfo("My Location A"_span, DataModel::Nullable(4), DataModel::Nullable()); + + // Area B has name, uses map XX + auto areaB = AreaStructureWrapper{} + .SetAreaId(supportedAreaID_B) + .SetMapId(supportedMapId_XX) + .SetLocationInfo("My Location B"_span, DataModel::NullNullable, DataModel::NullNullable); + + // Area C has full SemData, no name, Map YY + auto areaC = AreaStructureWrapper{} + .SetAreaId(supportedAreaID_C) + .SetMapId(supportedMapId_YY) + .SetLocationInfo(""_span, -1, Globals::AreaTypeTag::kPlayRoom) + .SetLandmarkInfo(Globals::LandmarkTag::kBackDoor, Globals::RelativePositionTag::kNextTo); + + // Area D has null values for all landmark fields, Map YY + auto areaD = AreaStructureWrapper{} + .SetAreaId(supportedAreaID_D) + .SetMapId(supportedMapId_YY) + .SetLocationInfo("My Location D"_span, DataModel::NullNullable, DataModel::NullNullable) + .SetLandmarkInfo(Globals::LandmarkTag::kCouch, Globals::RelativePositionTag::kNextTo); + + GetInstance()->AddSupportedArea(areaA); + GetInstance()->AddSupportedArea(areaB); + GetInstance()->AddSupportedArea(areaC); + GetInstance()->AddSupportedArea(areaD); +} + +void RvcServiceAreaDelegate::SetNoMapTopology() +{ + GetInstance()->ClearSupportedMaps(); + + // Area A has name, floor number. + auto areaA = + AreaStructureWrapper{} + .SetAreaId(supportedAreaID_A) + .SetLocationInfo("My Location A"_span, DataModel::Nullable(4), DataModel::Nullable()); + + // Area B has name. + auto areaB = AreaStructureWrapper{} + .SetAreaId(supportedAreaID_B) + .SetLocationInfo("My Location B"_span, DataModel::NullNullable, DataModel::NullNullable); + + // Area C has full SemData, no name. + auto areaC = AreaStructureWrapper{} + .SetAreaId(supportedAreaID_C) + .SetLocationInfo(""_span, -1, Globals::AreaTypeTag::kPlayRoom) + .SetLandmarkInfo(Globals::LandmarkTag::kBackDoor, Globals::RelativePositionTag::kNextTo); + + // Area D has null values for all landmark fields. + auto areaD = AreaStructureWrapper{} + .SetAreaId(supportedAreaID_D) + .SetLocationInfo("My Location D"_span, DataModel::NullNullable, DataModel::NullNullable) + .SetLandmarkInfo(Globals::LandmarkTag::kCouch, Globals::RelativePositionTag::kNextTo); + + GetInstance()->AddSupportedArea(areaA); + GetInstance()->AddSupportedArea(areaB); + GetInstance()->AddSupportedArea(areaC); + GetInstance()->AddSupportedArea(areaD); +} + +CHIP_ERROR RvcServiceAreaDelegate::Init() +{ + SetMapTopology(); GetInstance()->SetCurrentArea(supportedAreaID_C); @@ -73,32 +108,89 @@ CHIP_ERROR RvcServiceAreaDelegate::Init() //************************************************************************* // command support -bool RvcServiceAreaDelegate::IsSetSelectedAreasAllowed(MutableCharSpan statusText) +bool RvcServiceAreaDelegate::IsSetSelectedAreasAllowed(MutableCharSpan & statusText) { - // TODO IMPLEMENT - return true; + return (mIsSetSelectedAreasAllowedDeviceInstance->*mIsSetSelectedAreasAllowedCallback)(statusText); }; -bool RvcServiceAreaDelegate::IsValidSelectAreasSet(const Commands::SelectAreas::DecodableType & req, - SelectAreasStatus & locationStatus, MutableCharSpan statusText) +bool RvcServiceAreaDelegate::IsValidSelectAreasSet(const Commands::SelectAreas::DecodableType & req, SelectAreasStatus & areaStatus, + MutableCharSpan & statusText) { - // TODO IMPLEMENT + // if req is empty list return true. + { + size_t reqSize; + if (req.newAreas.ComputeSize(&reqSize) != CHIP_NO_ERROR) + { + areaStatus = SelectAreasStatus::kInvalidSet; // todo Not sure this is the correct error to use here + CopyCharSpanToMutableCharSpan("error computing number of selected areas"_span, statusText); + return false; + } + + if (reqSize == 0) + { + return true; + } + } + + // If there is 1 or 0 supported maps, any combination of areas is valid. + if (!GetInstance()->HasFeature(Feature::kMaps) || GetNumberOfSupportedMaps() <= 1) + { + return true; + } + + // Check that all the requested areas are in the same map. + auto newAreasIter = req.newAreas.begin(); + newAreasIter.Next(); + + AreaStructureWrapper tempArea; + uint32_t ignoredIndex; + if (!GetSupportedAreaById(newAreasIter.GetValue(), ignoredIndex, tempArea)) + { + areaStatus = SelectAreasStatus::kUnsupportedArea; + CopyCharSpanToMutableCharSpan("unable to find selected area in supported areas"_span, statusText); + return false; + } + + auto mapId = tempArea.mapID.Value(); // It is safe to call `.Value()` as we confirmed that there are at least 2 maps. + + while (newAreasIter.Next()) + { + if (!GetSupportedAreaById(newAreasIter.GetValue(), ignoredIndex, tempArea)) + { + areaStatus = SelectAreasStatus::kUnsupportedArea; + CopyCharSpanToMutableCharSpan("unable to find selected area in supported areas"_span, statusText); + return false; + } + + if (tempArea.mapID.Value() != mapId) + { + areaStatus = SelectAreasStatus::kInvalidSet; + CopyCharSpanToMutableCharSpan("all selected areas must be in the same map"_span, statusText); + return false; + } + } + + if (CHIP_NO_ERROR != newAreasIter.GetStatus()) + { + areaStatus = SelectAreasStatus::kInvalidSet; + CopyCharSpanToMutableCharSpan("error processing new areas."_span, statusText); + return false; + } + return true; }; -bool RvcServiceAreaDelegate::HandleSkipCurrentArea(MutableCharSpan skipStatusText) +bool RvcServiceAreaDelegate::HandleSkipCurrentArea(uint32_t skippedArea, MutableCharSpan & skipStatusText) { - // TODO IMPLEMENT - return true; + return (mHandleSkipCurrentAreaDeviceInstance->*mHandleSkipCurrentAreaCallback)(skippedArea, skipStatusText); }; //************************************************************************* -// Supported Locations accessors +// Supported Areas accessors bool RvcServiceAreaDelegate::IsSupportedAreasChangeAllowed() { - // TODO IMPLEMENT - return true; + return (mIsSupportedAreasChangeAllowedDeviceInstance->*mIsSupportedAreasChangeAllowedCallback)(); } uint32_t RvcServiceAreaDelegate::GetNumberOfSupportedAreas() @@ -106,19 +198,18 @@ uint32_t RvcServiceAreaDelegate::GetNumberOfSupportedAreas() return static_cast(mSupportedAreas.size()); } -bool RvcServiceAreaDelegate::GetSupportedLocationByIndex(uint32_t listIndex, AreaStructureWrapper & aSupportedLocation) +bool RvcServiceAreaDelegate::GetSupportedAreaByIndex(uint32_t listIndex, AreaStructureWrapper & supportedArea) { if (listIndex < mSupportedAreas.size()) { - aSupportedLocation = mSupportedAreas[listIndex]; + supportedArea = mSupportedAreas[listIndex]; return true; } return false; }; -bool RvcServiceAreaDelegate::GetSupportedLocationById(uint32_t aAreaID, uint32_t & listIndex, - AreaStructureWrapper & aSupportedLocation) +bool RvcServiceAreaDelegate::GetSupportedAreaById(uint32_t aAreaID, uint32_t & listIndex, AreaStructureWrapper & supportedArea) { // We do not need to reimplement this method as it's already done by the SDK. // We are reimplementing this method, still using linear search, but with some optimization on the SDK implementation @@ -129,7 +220,7 @@ bool RvcServiceAreaDelegate::GetSupportedLocationById(uint32_t aAreaID, uint32_t { if (mSupportedAreas[listIndex].areaID == aAreaID) { - aSupportedLocation = mSupportedAreas[listIndex]; + supportedArea = mSupportedAreas[listIndex]; return true; } @@ -139,7 +230,7 @@ bool RvcServiceAreaDelegate::GetSupportedLocationById(uint32_t aAreaID, uint32_t return false; }; -bool RvcServiceAreaDelegate::AddSupportedLocation(const AreaStructureWrapper & newArea, uint32_t & listIndex) +bool RvcServiceAreaDelegate::AddSupportedArea(const AreaStructureWrapper & newArea, uint32_t & listIndex) { // The server instance (caller) is responsible for ensuring that there are no duplicate area IDs, list size not exceeded, // etc. @@ -147,33 +238,33 @@ bool RvcServiceAreaDelegate::AddSupportedLocation(const AreaStructureWrapper & n // Double-check list size to ensure there no memory issues. if (mSupportedAreas.size() < kMaxNumSupportedAreas) { - // not sorting list, number of locations normally expected to be small, max 255 + // not sorting list, number of areas normally expected to be small, max 255 mSupportedAreas.push_back(newArea); listIndex = static_cast(mSupportedMaps.size()) - 1; // new element is last in list return true; } - ChipLogError(Zcl, "AddSupportedLocation %u - supported locations list is already at maximum size %u", newArea.areaID, + ChipLogError(Zcl, "AddSupportedArea %u - supported areas list is already at maximum size %u", newArea.areaID, static_cast(kMaxNumSupportedAreas)); return false; } -bool RvcServiceAreaDelegate::ModifySupportedLocation(uint32_t listIndex, const AreaStructureWrapper & modifiedLocation) +bool RvcServiceAreaDelegate::ModifySupportedArea(uint32_t listIndex, const AreaStructureWrapper & modifiedArea) { // The server instance (caller) is responsible for ensuring that there are no duplicate area IDs, list size not exceeded, // etc. // Double-check that areaID's match. - if (modifiedLocation.areaID != mSupportedAreas[listIndex].areaID) + if (modifiedArea.areaID != mSupportedAreas[listIndex].areaID) { - ChipLogError(Zcl, "ModifySupportedLocation - areaID's do not match, new areaID %u, existing areaID %u", - modifiedLocation.areaID, mSupportedAreas[listIndex].areaID); + ChipLogError(Zcl, "ModifySupportedArea - areaID's do not match, new areaID %u, existing areaID %u", modifiedArea.areaID, + mSupportedAreas[listIndex].areaID); return false; } // checks passed, update the attribute - mSupportedAreas[listIndex] = modifiedLocation; + mSupportedAreas[listIndex] = modifiedArea; return true; } @@ -188,13 +279,26 @@ bool RvcServiceAreaDelegate::ClearSupportedAreas() return false; } +bool RvcServiceAreaDelegate::RemoveSupportedArea(uint32_t areaId) +{ + for (auto it = mSupportedAreas.begin(); it != mSupportedAreas.end(); ++it) + { + if (it->areaID == areaId) + { + mSupportedAreas.erase(it); + return true; + } + } + + return false; +} + //************************************************************************* // Supported Maps accessors bool RvcServiceAreaDelegate::IsSupportedMapChangeAllowed() { - // TODO IMPLEMENT - return true; + return (mIsSupportedMapChangeAllowedDeviceInstance->*mIsSupportedMapChangeAllowedCallback)(); } uint32_t RvcServiceAreaDelegate::GetNumberOfSupportedMaps() @@ -213,7 +317,7 @@ bool RvcServiceAreaDelegate::GetSupportedMapByIndex(uint32_t listIndex, MapStruc return false; }; -bool RvcServiceAreaDelegate::GetSupportedMapById(uint8_t aMapId, uint32_t & listIndex, MapStructureWrapper & aSupportedMap) +bool RvcServiceAreaDelegate::GetSupportedMapById(uint32_t aMapId, uint32_t & listIndex, MapStructureWrapper & aSupportedMap) { // We do not need to reimplement this method as it's already done by the SDK. // We are reimplementing this method, still using linear search, but with some optimization on the SDK implementation @@ -242,7 +346,7 @@ bool RvcServiceAreaDelegate::AddSupportedMap(const MapStructureWrapper & newMap, // Double-check list size to ensure there no memory issues. if (mSupportedMaps.size() < kMaxNumSupportedMaps) { - // not sorting list, number of locations normally expected to be small, max 255 + // not sorting list, number of areas normally expected to be small, max 255 mSupportedMaps.push_back(newMap); listIndex = static_cast(mSupportedMaps.size()) - 1; // new element is last in list return true; @@ -282,26 +386,134 @@ bool RvcServiceAreaDelegate::ClearSupportedMaps() return false; } +void RvcServiceAreaDelegate::HandleSupportedAreasUpdated() +{ + // Get a list of supported area IDs as `supportedAreaIDs` + std::vector supportedAreaIDs; + for (const auto & supportedArea : mSupportedAreas) + { + supportedAreaIDs.push_back(supportedArea.areaID); + } + + if (supportedAreaIDs.empty()) + { + // Clear all selected areas, current area, and progress if there are no supported areas. + GetInstance()->ClearSelectedAreas(); + GetInstance()->SetCurrentArea(DataModel::NullNullable); + GetInstance()->ClearProgress(); + return; + } + + // Remove mSelectedArea elements that do not exist is `supportedAreaIDs` + { + for (auto it = mSelectedAreas.begin(); it != mSelectedAreas.end();) + { + if (std::find(supportedAreaIDs.begin(), supportedAreaIDs.end(), *it) == supportedAreaIDs.end()) + { + it = mSelectedAreas.erase(it); + } + else + { + ++it; + } + } + } + + // Set current Area to null if current area is not in `supportedAreaIDs` + { + auto currentAreaId = GetInstance()->GetCurrentArea(); + if (!currentAreaId.IsNull() && + std::find(supportedAreaIDs.begin(), supportedAreaIDs.end(), currentAreaId.Value()) == supportedAreaIDs.end()) + { + GetInstance()->SetCurrentArea(DataModel::NullNullable); + } + } + + // Remove mProgress elements that do not exist is `supportedAreaIDs` + { + for (auto it = mProgressList.begin(); it != mProgressList.end();) + { + if (std::find(supportedAreaIDs.begin(), supportedAreaIDs.end(), it->areaID) == supportedAreaIDs.end()) + { + it = mProgressList.erase(it); + } + else + { + ++it; + } + } + } +} + +bool RvcServiceAreaDelegate::RemoveSupportedMap(uint32_t mapId) +{ + bool removedEntry = false; + for (auto it = mSupportedMaps.begin(); it != mSupportedMaps.end(); ++it) + { + if (it->mapID == mapId) + { + mSupportedMaps.erase(it); + removedEntry = true; + } + } + + if (!removedEntry) + { + return false; + } + + // If there are no supported maps left, none of the supported areas are vaild and their MapID needs to be null. + if (GetNumberOfSupportedMaps() == 0) + { + ClearSupportedAreas(); + return true; + } + + // Get the supported area IDs where the map ID matches the removed map ID + std::vector supportedAreaIds; + { + for (const auto & supportedArea : mSupportedAreas) + { + if (supportedArea.mapID == mapId) + { + supportedAreaIds.push_back(supportedArea.areaID); + } + } + } + + // Remove the supported areas with the matching map ID + if (!supportedAreaIds.empty()) + { + for (const auto & supportedAreaId : supportedAreaIds) + { + RemoveSupportedArea(supportedAreaId); + } + HandleSupportedAreasUpdated(); + } + + return true; +} + //************************************************************************* -// Selected Locations accessors +// Selected areas accessors uint32_t RvcServiceAreaDelegate::GetNumberOfSelectedAreas() { return static_cast(mSelectedAreas.size()); } -bool RvcServiceAreaDelegate::GetSelectedLocationByIndex(uint32_t listIndex, uint32_t & aSelectedLocation) +bool RvcServiceAreaDelegate::GetSelectedAreaByIndex(uint32_t listIndex, uint32_t & selectedArea) { if (listIndex < mSelectedAreas.size()) { - aSelectedLocation = mSelectedAreas[listIndex]; + selectedArea = mSelectedAreas[listIndex]; return true; } return false; }; -bool RvcServiceAreaDelegate::AddSelectedLocation(uint32_t aAreaID, uint32_t & listIndex) +bool RvcServiceAreaDelegate::AddSelectedArea(uint32_t aAreaID, uint32_t & listIndex) { // The server instance (caller) is responsible for ensuring that there are no duplicate area IDs, list size not exceeded, // etc. @@ -309,12 +521,12 @@ bool RvcServiceAreaDelegate::AddSelectedLocation(uint32_t aAreaID, uint32_t & li // Double-check list size to ensure there no memory issues. if (mSelectedAreas.size() < kMaxNumSelectedAreas) { - // not sorting list, number of locations normally expected to be small, max 255 + // not sorting list, number of areas normally expected to be small, max 255 mSelectedAreas.push_back(aAreaID); listIndex = static_cast(mSelectedAreas.size()) - 1; // new element is last in list return true; } - ChipLogError(Zcl, "AddSelectedLocation %u - selected locations list is already at maximum size %u", aAreaID, + ChipLogError(Zcl, "AddSelectedArea %u - selected areas list is already at maximum size %u", aAreaID, static_cast(kMaxNumSelectedAreas)); return false; @@ -380,7 +592,7 @@ bool RvcServiceAreaDelegate::AddProgressElement(const Structs::ProgressStruct::T // Double-check list size to ensure there no memory issues. if (mProgressList.size() < kMaxNumProgressElements) { - // not sorting list, number of locations normally expected to be small, max 255 + // not sorting list, number of areas normally expected to be small, max 255 mProgressList.push_back(newProgressElement); listIndex = static_cast(mProgressList.size()) - 1; // new element is last in list return true; @@ -394,8 +606,15 @@ bool RvcServiceAreaDelegate::AddProgressElement(const Structs::ProgressStruct::T bool RvcServiceAreaDelegate::ModifyProgressElement(uint32_t listIndex, const Structs::ProgressStruct::Type & modifiedProgressElement) { - // TODO IMPLEMENT - return false; + if (modifiedProgressElement.areaID != mProgressList[listIndex].areaID) + { + ChipLogError(Zcl, "ModifyProgressElement - areaID's do not match, new areaID %u, existing areaID %u", + modifiedProgressElement.areaID, mProgressList[listIndex].areaID); + return false; + } + + mProgressList[listIndex] = modifiedProgressElement; + return true; } bool RvcServiceAreaDelegate::ClearProgress() @@ -408,3 +627,125 @@ bool RvcServiceAreaDelegate::ClearProgress() return false; } + +void RvcServiceAreaDelegate::SetAttributesAtCleanStart() +{ + if (GetNumberOfSupportedAreas() == 0) + { + return; + } + + if (GetNumberOfSelectedAreas() == 0) + { + AreaStructureWrapper firstArea; + GetSupportedAreaByIndex(0, firstArea); + + GetInstance()->SetCurrentArea(firstArea.areaID); + + if (GetInstance()->HasFeature(Feature::kProgressReporting)) + { + GetInstance()->AddPendingProgressElement(firstArea.areaID); + GetInstance()->SetProgressStatus(firstArea.areaID, OperationalStatusEnum::kOperating); + } + } + else + { + uint32_t areaId; + GetSelectedAreaByIndex(0, areaId); + + GetInstance()->SetCurrentArea(areaId); + + if (GetInstance()->HasFeature(Feature::kProgressReporting)) + { + GetInstance()->AddPendingProgressElement(areaId); + GetInstance()->SetProgressStatus(areaId, OperationalStatusEnum::kOperating); + + uint32_t i = 1; + while (GetSelectedAreaByIndex(i, areaId)) + { + GetInstance()->AddPendingProgressElement(areaId); + i++; + } + } + } +} + +void RvcServiceAreaDelegate::GoToNextArea(OperationalStatusEnum currentAreaOpState, bool & finished) +{ + AreaStructureWrapper currentArea; + auto currentAreaIdN = GetInstance()->GetCurrentArea(); + + if (currentAreaIdN.IsNull()) + { + ChipLogError(Zcl, "GoToNextArea: Cannot go to the next area when the current area is null."); + return; + } + + if (currentAreaOpState != OperationalStatusEnum::kCompleted && currentAreaOpState != OperationalStatusEnum::kSkipped) + { + ChipLogError(Zcl, "GoToNextArea: currentAreaOpState must be either completed or skipped."); + return; + } + + auto currentAreaId = currentAreaIdN.Value(); + uint32_t currentAreaIndex; + GetSupportedAreaById(currentAreaId, currentAreaIndex, currentArea); + auto currentAreaMapId = currentArea.mapID; + finished = true; + + if (GetInstance()->HasFeature(Feature::kProgressReporting)) + { + GetInstance()->SetProgressStatus(currentAreaId, currentAreaOpState); + } + + if (GetNumberOfSelectedAreas() == 0) + { + AreaStructureWrapper nextArea; + uint32_t nextIndex = currentAreaIndex + 1; + while (GetSupportedAreaByIndex(nextIndex, nextArea)) + { + if (!currentAreaMapId.IsNull() && nextArea.mapID == currentAreaMapId.Value()) + { + GetInstance()->SetCurrentArea(nextArea.areaID); + + if (GetInstance()->HasFeature(Feature::kProgressReporting)) + { + GetInstance()->SetProgressStatus(nextArea.areaID, OperationalStatusEnum::kOperating); + } + + finished = false; + return; + } + + ++nextIndex; + } + } + else + { + uint32_t selectedAreaId; + uint32_t selectedAreaIndex = 0; + while (GetSelectedAreaByIndex(selectedAreaIndex, selectedAreaId)) + { + if (selectedAreaId == currentAreaId) + { + break; + } + ++selectedAreaIndex; + } + + uint32_t nextSelectedAreaId; + uint32_t nextSelectedAreaIndex = selectedAreaIndex + 1; + if (GetSelectedAreaByIndex(nextSelectedAreaIndex, nextSelectedAreaId)) + { + GetInstance()->SetCurrentArea(nextSelectedAreaId); + + if (GetInstance()->HasFeature(Feature::kProgressReporting)) + { + GetInstance()->SetProgressStatus(nextSelectedAreaId, OperationalStatusEnum::kOperating); + } + + finished = false; + return; + } + } +} diff --git a/examples/shell/shell_common/BUILD.gn b/examples/shell/shell_common/BUILD.gn index 470f81b5d2459a..e4aa2973f8cc04 100644 --- a/examples/shell/shell_common/BUILD.gn +++ b/examples/shell/shell_common/BUILD.gn @@ -70,20 +70,24 @@ static_library("shell_common") { "${chip_root}/examples/all-clusters-app/all-clusters-common/src/smco-stub.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-temperature-levels.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/ChargingTargetsMemMgr.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EVSEManufacturerImpl.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/ElectricalPowerMeasurementDelegate.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseTargetsStore.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyTimeUtils.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/common/src/EnergyTimeUtils.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementDelegateImpl.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementManager.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/ChargingTargetsMemMgr.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EVSEManufacturerImpl.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseDelegateImpl.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseManager.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseTargetsStore.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/energy-evse-mode.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/src/ElectricalPowerMeasurementDelegate.cpp", ] include_dirs = [ "${chip_root}/examples/all-clusters-app/all-clusters-common/include", - "${chip_root}/examples/energy-management-app/energy-management-common/include", + "${chip_root}/examples/energy-management-app/energy-management-common/common/include", + "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/include", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/include", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/include", "${chip_root}/src/app/clusters/device-energy-management-server", ] diff --git a/examples/smoke-co-alarm-app/silabs/src/AppTask.cpp b/examples/smoke-co-alarm-app/silabs/src/AppTask.cpp index dc99728ccf90d5..105a3c9e5b6d9c 100644 --- a/examples/smoke-co-alarm-app/silabs/src/AppTask.cpp +++ b/examples/smoke-co-alarm-app/silabs/src/AppTask.cpp @@ -31,7 +31,7 @@ #include #include -#if (defined(SL_CATALOG_SIMPLE_LED_LED1_PRESENT) || defined(BRD4325B)) +#if (defined(SL_CATALOG_SIMPLE_LED_LED1_PRESENT)) #define LIGHT_LED 1 #else #define LIGHT_LED 0 diff --git a/examples/temperature-measurement-app/esp32/main/DeviceCallbacks.cpp b/examples/temperature-measurement-app/esp32/main/DeviceCallbacks.cpp index e0d7decc849616..88fee24b7535b6 100644 --- a/examples/temperature-measurement-app/esp32/main/DeviceCallbacks.cpp +++ b/examples/temperature-measurement-app/esp32/main/DeviceCallbacks.cpp @@ -23,6 +23,7 @@ * **/ #include "DeviceCallbacks.h" +#include static const char TAG[] = "echo-devicecallbacks"; diff --git a/examples/thermostat/linux/include/thermostat-delegate-impl.h b/examples/thermostat/linux/include/thermostat-delegate-impl.h index f559977f341949..8252f2274f9d79 100644 --- a/examples/thermostat/linux/include/thermostat-delegate-impl.h +++ b/examples/thermostat/linux/include/thermostat-delegate-impl.h @@ -44,6 +44,10 @@ class ThermostatDelegate : public Delegate public: static inline ThermostatDelegate & GetInstance() { return sInstance; } + std::optional + GetAtomicWriteTimeout(DataModel::DecodableList attributeRequests, + System::Clock::Milliseconds16 timeoutRequest) override; + CHIP_ERROR GetPresetTypeAtIndex(size_t index, Structs::PresetTypeStruct::Type & presetType) override; uint8_t GetNumberOfPresets() override; diff --git a/examples/thermostat/linux/thermostat-delegate-impl.cpp b/examples/thermostat/linux/thermostat-delegate-impl.cpp index 61d496f233b408..c39a757a8b0644 100644 --- a/examples/thermostat/linux/thermostat-delegate-impl.cpp +++ b/examples/thermostat/linux/thermostat-delegate-impl.cpp @@ -148,6 +148,47 @@ CHIP_ERROR ThermostatDelegate::SetActivePresetHandle(const DataModel::Nullable +ThermostatDelegate::GetAtomicWriteTimeout(DataModel::DecodableList attributeRequests, + System::Clock::Milliseconds16 timeoutRequest) +{ + auto attributeIdsIter = attributeRequests.begin(); + bool requestedPresets = false, requestedSchedules = false; + while (attributeIdsIter.Next()) + { + auto & attributeId = attributeIdsIter.GetValue(); + + switch (attributeId) + { + case Attributes::Presets::Id: + requestedPresets = true; + break; + case Attributes::Schedules::Id: + requestedSchedules = true; + break; + default: + return System::Clock::Milliseconds16(0); + } + } + if (attributeIdsIter.GetStatus() != CHIP_NO_ERROR) + { + return System::Clock::Milliseconds16(0); + } + auto timeout = System::Clock::Milliseconds16(0); + if (requestedPresets) + { + // If the client expects to edit the presets, then we'll give it 3 seconds to do so + timeout += std::chrono::milliseconds(3000); + } + if (requestedSchedules) + { + // If the client expects to edit the schedules, then we'll give it 9 seconds to do so + timeout += std::chrono::milliseconds(9000); + } + // If the client requested an even smaller timeout, then use that one + return std::min(timeoutRequest, timeout); +} + void ThermostatDelegate::InitializePendingPresets() { mNextFreeIndexInPendingPresetsList = 0; diff --git a/examples/thermostat/thermostat-common/thermostat.matter b/examples/thermostat/thermostat-common/thermostat.matter index a53e3cdc692952..c53651c537894e 100644 --- a/examples/thermostat/thermostat-common/thermostat.matter +++ b/examples/thermostat/thermostat-common/thermostat.matter @@ -2801,7 +2801,7 @@ endpoint 1 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0x123; - ram attribute clusterRevision default = 6; + ram attribute clusterRevision default = 7; handle command SetpointRaiseLower; handle command SetActiveScheduleRequest; diff --git a/examples/thermostat/thermostat-common/thermostat.zap b/examples/thermostat/thermostat-common/thermostat.zap index 8b2fe4f5c82318..ffb9da2b136de9 100644 --- a/examples/thermostat/thermostat-common/thermostat.zap +++ b/examples/thermostat/thermostat-common/thermostat.zap @@ -5088,7 +5088,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "6", + "defaultValue": "7", "reportable": 1, "minInterval": 0, "maxInterval": 65344, diff --git a/examples/thread-br-app/esp32/.gitignore b/examples/thread-br-app/esp32/.gitignore new file mode 100644 index 00000000000000..234526a082ad26 --- /dev/null +++ b/examples/thread-br-app/esp32/.gitignore @@ -0,0 +1,5 @@ +*.vscode + +/build/ +/sdkconfig +/sdkconfig.old diff --git a/examples/thread-br-app/esp32/CMakeLists.txt b/examples/thread-br-app/esp32/CMakeLists.txt new file mode 100644 index 00000000000000..7661eae12fdfc0 --- /dev/null +++ b/examples/thread-br-app/esp32/CMakeLists.txt @@ -0,0 +1,49 @@ +# +# 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. + +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +set(PROJECT_VER "v1.0") +set(PROJECT_VER_NUMBER 1) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/../../common/cmake/idf_flashing.cmake) + +set(EXTRA_COMPONENT_DIRS + "${CMAKE_CURRENT_LIST_DIR}/third_party/connectedhomeip/config/esp32/components" +) + +project(chip-thread-br-app) + +# C++17 is required for RPC build. +idf_build_set_property(CXX_COMPILE_OPTIONS "-std=gnu++17;-Os;-DCHIP_HAVE_CONFIG_H" APPEND) +idf_build_set_property(C_COMPILE_OPTIONS "-Os" APPEND) +# For the C3, project_include.cmake sets -Wno-format, but does not clear various +# flags that depend on -Wformat +idf_build_set_property(COMPILE_OPTIONS "-Wno-format-nonliteral;-Wno-format-security" APPEND) + +# We don't need Thread Network Commissioning Driver +idf_build_set_property(COMPILE_OPTIONS "-D_NO_GENERIC_THREAD_NETWORK_COMMISSIONING_DRIVER_" APPEND) + +# -Wmaybe-uninitialized has too many false positives, including on std::optional +# and chip::Optional. Make it nonfatal. +# +# See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80635 +idf_build_set_property(COMPILE_OPTIONS "-Wno-error=maybe-uninitialized" APPEND) + +flashing_script() diff --git a/examples/thread-br-app/esp32/README.md b/examples/thread-br-app/esp32/README.md new file mode 100644 index 00000000000000..576339cd43b224 --- /dev/null +++ b/examples/thread-br-app/esp32/README.md @@ -0,0 +1,94 @@ +# Matter ESP32 Thread Border Router Example + +A prototype application that demonstrates OpenThread Border Router on ESP32-S3 + +ESP32-H2 Thread Border Router DevKit Board. + +Please +[setup ESP-IDF and CHIP Environment](../../../docs/guides/esp32/setup_idf_chip.md) +and refer +[building and commissioning](../../../docs/guides/esp32/build_app_and_commission.md) +guides to get started. + +--- + +- [OpenThread Border Router Board](#openthread-border-router-board) +- [OpenThread RCP](#openthread-rcp) +- [OpenThread CLI](#openthread-cli) +- [Setup Thread Network](#setup-thread-network) +- [Commissioning Thread End Devices](#commissioning-thread-end-devices) + +--- + +### OpenThread Border Router Board + +The ESP Thread border router board provides an integrated module of an ESP32-S3 +and an ESP32-H2. + +![Border Router Board](image/esp-thread-border-router-board.png) + +### OpenThread RCP + +We need to build an OpenThread RCP(Radio Co-Processor) firmware for ESP32-H2 of +the Border Router Board before building this Thread Border example. + +``` +cd $IDF_PATH/examples/openthread/ot_rcp +idf.py set-target esp32h2 +idf.py build +``` + +Then we need to connect the USB2 port(ESP32-S3) of the Border Router Board to +your host machine. Build and flash this example. + +``` +cd ${CHIP_ROOT}/examples/thread-br-app/esp32 +idf.py set-target esp32s3 +idf.py build +idf.py -p {port} erase-flash flash monitor +``` + +This example will detect the RCP firmware built in ESP-IDF path and flash it to +the spiffs partition. When starting this example, the ESP32-S3 will compare the +versions of both the RCP firmware in the spiffs partition and the firmware on +ESP32-H2. if the spiffs RCP firmware is newer than the firmware on ESP32-H2, the +Thread BR will flash the RCP firmware to ESP32-H2 automatically. + +### OpenThread CLI + +After you build this example and flash it to the ESP32-S3 of Border Router +Board, you can access a standard OpenThread CLI via the device console with a +`matter otcli` prefix. + +For instance, you can get the state: + +``` +> matter otcli state +Detached +Done +``` + +### Setup Thread Network + +You can send SetActiveDatasetRequest command to the Thread BR after +commissioning it as a Matter-Over-Wi-Fi device to setup the Thread network or +join an existing Thread network. + +``` +./chip-tool pairing ble-wifi 1 20202021 3840 +./chip-tool generalcommissioning arm-fail-safe 180 1 1 0 +./chip-tool threadborderroutermanagement set-active-dataset-request hex: 1 1 1 +./chip-tool generalcommissioning commissioning-complete 1 0 +``` + +The Thread BR with enable the Thread network interface and start Thread network +after it receives SetActiveDatasetRequest command. And after the Thread BR sets +up or join a Thread network, it will send the success response. + +### Commissioning Thread End Devices + +After setting up the Thread network, you can commission a Thread End-device to +the Thread network. + +``` +./chip-tool pairing ble-wifi 2 hex: +``` diff --git a/examples/thread-br-app/esp32/create_ota_image.py b/examples/thread-br-app/esp32/create_ota_image.py new file mode 100755 index 00000000000000..56f7caa81f1b85 --- /dev/null +++ b/examples/thread-br-app/esp32/create_ota_image.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 + +import argparse +import os +import pathlib +import struct + +FILETAG_RCP_VERSION = 0 +FILETAG_RCP_FLASH_ARGS = 1 +FILETAG_RCP_BOOTLOADER = 2 +FILETAG_RCP_PARTITION_TABLE = 3 +FILETAG_RCP_FIRMWARE = 4 +FILETAG_BR_OTA_IMAGE = 5 +FILETAG_IMAGE_HEADER = 0xff + +HEADER_ENTRY_SIZE = 3 * 4 +RCP_IMAGE_HEADER_SIZE = HEADER_ENTRY_SIZE * 6 +RCP_FLASH_ARGS_SIZE = 2 * 4 * 3 + + +def append_subfile_header(fout, tag, size, offset): + fout.write(struct.pack(' 0: + fout.write(data) + data = fin.read(buf_size) + + +def append_flash_args(fout, flash_args_path): + with open(flash_args_path, 'r') as f: + # skip first line + next(f) + partition_info_list = [line.split() for line in f] + for offset, partition_file in partition_info_list: + offset = int(offset, 0) + if partition_file.find('bootloader') >= 0: + fout.write(struct.pack('= 0: + fout.write(struct.pack('" +) diff --git a/examples/thread-br-app/esp32/main/DeviceCallbacks.cpp b/examples/thread-br-app/esp32/main/DeviceCallbacks.cpp new file mode 100644 index 00000000000000..6925df9b21da8f --- /dev/null +++ b/examples/thread-br-app/esp32/main/DeviceCallbacks.cpp @@ -0,0 +1,61 @@ +/* + * + * 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. + */ + +/** + * @file DeviceCallbacks.cpp + * + * Implements all the callbacks to the application from the CHIP Stack + * + **/ + +#include "DeviceCallbacks.h" +#include "common/Esp32ThreadInit.h" +#include "platform/ESP32/OpenthreadLauncher.h" +#include "platform/ThreadStackManager.h" +#include +#include +#include +#include + +static const char TAG[] = "thread-br-app-callbacks"; + +using namespace chip; +using namespace chip::Inet; +using namespace chip::System; +using namespace chip::app::Clusters; + +void AppDeviceCallbacks::PostAttributeChangeCallback(EndpointId endpointId, ClusterId clusterId, AttributeId attributeId, + uint8_t type, uint16_t size, uint8_t * value) +{ + ESP_LOGI(TAG, "PostAttributeChangeCallback - Cluster ID: '0x%" PRIx32 "', EndPoint ID: '0x%x', Attribute ID: '0x%" PRIx32 "'", + clusterId, endpointId, attributeId); + + ESP_LOGI(TAG, "Current free heap: %u\n", static_cast(heap_caps_get_free_size(MALLOC_CAP_8BIT))); +} + +void AppDeviceCallbacksDelegate::OnIPv6ConnectivityEstablished(void) +{ + static bool sThreadBRInitialized = false; + if (!sThreadBRInitialized) + { + esp_openthread_lock_acquire(portMAX_DELAY); + esp_openthread_border_router_init(); + esp_openthread_lock_release(); + sThreadBRInitialized = true; + } +} diff --git a/examples/thread-br-app/esp32/main/Kconfig.projbuild b/examples/thread-br-app/esp32/main/Kconfig.projbuild new file mode 100644 index 00000000000000..7f65d083795e42 --- /dev/null +++ b/examples/thread-br-app/esp32/main/Kconfig.projbuild @@ -0,0 +1,45 @@ +# +# 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. +# +# Description: +# Configuration options CHIP ESP32 demo application. +# + +menu "Demo" + choice + prompt "Rendezvous Mode" + default RENDEZVOUS_MODE_BLE + help + Specifies the Rendezvous mode of the peripheral. + + config RENDEZVOUS_MODE_WIFI + bool "Wi-Fi" + config RENDEZVOUS_MODE_BLE + bool "BLE" + config RENDEZVOUS_MODE_THREAD + bool "Thread" + config RENDEZVOUS_MODE_ETHERNET + bool "Ethernet" + endchoice + + config RENDEZVOUS_MODE + int + range 0 8 + default 1 if RENDEZVOUS_MODE_WIFI + default 2 if RENDEZVOUS_MODE_BLE + default 4 if RENDEZVOUS_MODE_THREAD + default 8 if RENDEZVOUS_MODE_ETHERNET +endmenu diff --git a/examples/thread-br-app/esp32/main/include/DeviceCallbacks.h b/examples/thread-br-app/esp32/main/include/DeviceCallbacks.h new file mode 100644 index 00000000000000..1507e284e0d5f5 --- /dev/null +++ b/examples/thread-br-app/esp32/main/include/DeviceCallbacks.h @@ -0,0 +1,45 @@ +/* + * + * 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. + */ + +/** + * @file DeviceCallbacks.h + * + * Implementations for the DeviceManager callbacks for this application + * + **/ + +#pragma once + +#include +#include + +class AppDeviceCallbacks : public CommonDeviceCallbacks +{ +public: + virtual void PostAttributeChangeCallback(chip::EndpointId endpointId, chip::ClusterId clusterId, chip::AttributeId attributeId, + uint8_t type, uint16_t size, uint8_t * value); +}; + +class AppDeviceCallbacksDelegate : public DeviceCallbacksDelegate +{ +public: + void OnIPv4ConnectivityEstablished(void) override {} + void OnIPv4ConnectivityLost(void) override {} + void OnIPv6ConnectivityEstablished(void) override; + void OnDnssdInitialized(void) override {} +}; diff --git a/examples/thread-br-app/esp32/main/main.cpp b/examples/thread-br-app/esp32/main/main.cpp new file mode 100644 index 00000000000000..dcafcc1c74ae40 --- /dev/null +++ b/examples/thread-br-app/esp32/main/main.cpp @@ -0,0 +1,160 @@ +/* + * + * 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 "DeviceCallbacks.h" +#include + +#include +#include +#include +#include + +#include "core/CHIPPersistentStorageDelegate.h" +#include "esp_log.h" +#include "esp_netif.h" +#include "esp_openthread_border_router.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "nvs_flash.h" +#include "shell_extension/launch.h" +#include "support/CHIPMem.h" + +#include +#include +#include +#include +#include +#include + +#if CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER +#include +#endif // CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER + +#if CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER +#include +#else +#include +#endif // CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER + +using namespace ::chip; +using namespace ::chip::Credentials; +using namespace ::chip::DeviceManager; +using namespace ::chip::DeviceLayer; +using namespace ::chip::app::Clusters; + +namespace { +#if CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER +DeviceLayer::ESP32FactoryDataProvider sFactoryDataProvider; +#endif // CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER + +#if CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER +DeviceLayer::ESP32DeviceInfoProvider gExampleDeviceInfoProvider; +#else +DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider; +#endif // CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER +} // namespace + +static const char TAG[] = "thread-br-app"; + +static AppDeviceCallbacks EchoCallbacks; +static AppDeviceCallbacksDelegate sAppDeviceCallbacksDelegate; + +static constexpr EndpointId kThreadBRMgmtEndpoint = 1; +static ThreadBorderRouterManagement::GenericOpenThreadBorderRouterDelegate * sThreadBRDelegate; +static ThreadBorderRouterManagement::ServerInstance * sThreadBRMgmtInstance; + +static void InitServer(intptr_t context) +{ + // Print QR Code URL + PrintOnboardingCodes(chip::RendezvousInformationFlags(CONFIG_RENDEZVOUS_MODE)); + + Esp32AppServer::Init(); // Init ZCL Data Model and CHIP App Server AND Initialize device attestation config + PersistentStorageDelegate * storageDelegate = &chip::Server::GetInstance().GetPersistentStorage(); + sThreadBRDelegate = chip::Platform::New(storageDelegate); + sThreadBRMgmtInstance = chip::Platform::New( + kThreadBRMgmtEndpoint, sThreadBRDelegate, chip::Server::GetInstance().GetFailSafeContext()); + char borderRouterName[] = "Espressif-ThreadBR"; + sThreadBRDelegate->SetThreadBorderRouterName(CharSpan(borderRouterName)); + sThreadBRMgmtInstance->Init(); +} + +extern "C" void app_main() +{ + // Initialize the ESP NVS layer. + esp_err_t err = nvs_flash_init(); + if (err != ESP_OK) + { + ESP_LOGE(TAG, "nvs_flash_init() failed: %s", esp_err_to_name(err)); + return; + } + err = esp_event_loop_create_default(); + if (err != ESP_OK) + { + ESP_LOGE(TAG, "esp_event_loop_create_default() failed: %s", esp_err_to_name(err)); + return; + } + + ESP_LOGI(TAG, "=================================================="); + ESP_LOGI(TAG, "chip-esp32-thread-br-example starting"); + ESP_LOGI(TAG, "=================================================="); + +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI + if (DeviceLayer::Internal::ESP32Utils::InitWiFiStack() != CHIP_NO_ERROR) + { + ESP_LOGE(TAG, "Failed to initialize the Wi-Fi stack"); + return; + } +#endif + +#if CONFIG_ENABLE_CHIP_SHELL +#if CONFIG_OPENTHREAD_CLI + chip::RegisterOpenThreadCliCommands(); +#endif + chip::LaunchShell(); +#endif // CONFIG_ENABLE_CHIP_SHELL + + DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); + + CHIPDeviceManager & deviceMgr = CHIPDeviceManager::GetInstance(); + CHIP_ERROR error = deviceMgr.Init(&EchoCallbacks); + DeviceCallbacksDelegate::Instance().SetAppDelegate(&sAppDeviceCallbacksDelegate); + if (error != CHIP_NO_ERROR) + { + ESP_LOGE(TAG, "device.Init() failed: %" CHIP_ERROR_FORMAT, error.Format()); + return; + } + +#if CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER + SetCommissionableDataProvider(&sFactoryDataProvider); + SetDeviceAttestationCredentialsProvider(&sFactoryDataProvider); +#if CONFIG_ENABLE_ESP32_DEVICE_INSTANCE_INFO_PROVIDER + SetDeviceInstanceInfoProvider(&sFactoryDataProvider); +#endif +#else + SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); +#endif // CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER + esp_openthread_set_backbone_netif(esp_netif_get_handle_from_ifkey("WIFI_STA_DEF")); + ESPOpenThreadInit(); + + chip::DeviceLayer::PlatformMgr().ScheduleWork(InitServer, reinterpret_cast(nullptr)); +} + +extern "C" void otSysProcessDrivers(otInstance * aInstance) +{ + (void) aInstance; +} diff --git a/examples/thread-br-app/esp32/partitions.csv b/examples/thread-br-app/esp32/partitions.csv new file mode 100644 index 00000000000000..745321df3785fc --- /dev/null +++ b/examples/thread-br-app/esp32/partitions.csv @@ -0,0 +1,8 @@ +# Name, Type, SubType, Offset, Size, Flags +# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap +nvs, data, nvs, , 0xC000, +otadata, data, ota, , 0x2000, +phy_init, data, phy, , 0x1000, +ota_0, app, ota_0, , 1800K, +ota_1, app, ota_1, , 1800K, +rcp_fw, data, spiffs, , 300K, diff --git a/examples/thread-br-app/esp32/sdkconfig.defaults b/examples/thread-br-app/esp32/sdkconfig.defaults new file mode 100644 index 00000000000000..dffd9283bc498a --- /dev/null +++ b/examples/thread-br-app/esp32/sdkconfig.defaults @@ -0,0 +1,74 @@ +# +# Copyright (c) 2024 Project CHIP Authors +# All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Description: +# Some useful defaults for the demo app configuration. +# + +# Flash size and partition table +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_PARTITION_TABLE_CUSTOM=y + +# BLE +CONFIG_BT_ENABLED=y +CONFIG_BT_NIMBLE_ENABLED=y +CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=n + +# Increase some stack size +CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=7200 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=5120 +CONFIG_ESP_TIMER_TASK_STACK_SIZE=5120 + +# USB console for Thread border board +CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y + +# Disable SoftAP +CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n + +# LWIP +CONFIG_LWIP_IPV6_FORWARD=y +CONFIG_LWIP_IPV6_AUTOCONFIG=y +CONFIG_LWIP_IPV6_NUM_ADDRESSES=8 +CONFIG_LWIP_MULTICAST_PING=y +CONFIG_LWIP_NETIF_STATUS_CALLBACK=y +CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT=y +CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT=y +CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM=y +CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_CUSTOM=y + +# ESP Border Router will also enable a route hook so we don't need the route hook in matter +CONFIG_ENABLE_ROUTE_HOOK=n + +# mbedTLS +CONFIG_MBEDTLS_KEY_EXCHANGE_ECJPAKE=y +CONFIG_MBEDTLS_SSL_PROTO_DTLS=y +CONFIG_MBEDTLS_ECJPAKE_C=y +CONFIG_MBEDTLS_HKDF_C=y + +# OpenThread +CONFIG_OPENTHREAD_ENABLED=y +CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC=n +CONFIG_OPENTHREAD_LOG_LEVEL_NOTE=y +CONFIG_OPENTHREAD_SRP_CLIENT=n +CONFIG_OPENTHREAD_DNS_CLIENT=n +CONFIG_OPENTHREAD_BORDER_ROUTER=y +CONFIG_THREAD_NETWORK_COMMISSIONING_DRIVER=n + +# Use platform mDNS +CONFIG_USE_MINIMAL_MDNS=n + +# Enable Matter shell +CONFIG_ENABLE_CHIP_SHELL=y diff --git a/examples/thread-br-app/esp32/third_party/connectedhomeip b/examples/thread-br-app/esp32/third_party/connectedhomeip new file mode 120000 index 00000000000000..11a54ed360106c --- /dev/null +++ b/examples/thread-br-app/esp32/third_party/connectedhomeip @@ -0,0 +1 @@ +../../../../ \ No newline at end of file diff --git a/examples/thread-br-app/thread-br-common/thread-br-app.matter b/examples/thread-br-app/thread-br-common/thread-br-app.matter new file mode 100644 index 00000000000000..1b043a7cdde916 --- /dev/null +++ b/examples/thread-br-app/thread-br-common/thread-br-app.matter @@ -0,0 +1,1721 @@ +// This IDL was generated automatically by ZAP. +// It is for view/code review purposes only. + +enum AreaTypeTag : enum8 { + kAisle = 0; + kAttic = 1; + kBackDoor = 2; + kBackYard = 3; + kBalcony = 4; + kBallroom = 5; + kBathroom = 6; + kBedroom = 7; + kBorder = 8; + kBoxroom = 9; + kBreakfastRoom = 10; + kCarport = 11; + kCellar = 12; + kCloakroom = 13; + kCloset = 14; + kConservatory = 15; + kCorridor = 16; + kCraftRoom = 17; + kCupboard = 18; + kDeck = 19; + kDen = 20; + kDining = 21; + kDrawingRoom = 22; + kDressingRoom = 23; + kDriveway = 24; + kElevator = 25; + kEnsuite = 26; + kEntrance = 27; + kEntryway = 28; + kFamilyRoom = 29; + kFoyer = 30; + kFrontDoor = 31; + kFrontYard = 32; + kGameRoom = 33; + kGarage = 34; + kGarageDoor = 35; + kGarden = 36; + kGardenDoor = 37; + kGuestBathroom = 38; + kGuestBedroom = 39; + kGuestRestroom = 40; + kGuestRoom = 41; + kGym = 42; + kHallway = 43; + kHearthRoom = 44; + kKidsRoom = 45; + kKidsBedroom = 46; + kKitchen = 47; + kLarder = 48; + kLaundryRoom = 49; + kLawn = 50; + kLibrary = 51; + kLivingRoom = 52; + kLounge = 53; + kMediaTVRoom = 54; + kMudRoom = 55; + kMusicRoom = 56; + kNursery = 57; + kOffice = 58; + kOutdoorKitchen = 59; + kOutside = 60; + kPantry = 61; + kParkingLot = 62; + kParlor = 63; + kPatio = 64; + kPlayRoom = 65; + kPoolRoom = 66; + kPorch = 67; + kPrimaryBathroom = 68; + kPrimaryBedroom = 69; + kRamp = 70; + kReceptionRoom = 71; + kRecreationRoom = 72; + kRestroom = 73; + kRoof = 74; + kSauna = 75; + kScullery = 76; + kSewingRoom = 77; + kShed = 78; + kSideDoor = 79; + kSideYard = 80; + kSittingRoom = 81; + kSnug = 82; + kSpa = 83; + kStaircase = 84; + kSteamRoom = 85; + kStorageRoom = 86; + kStudio = 87; + kStudy = 88; + kSunRoom = 89; + kSwimmingPool = 90; + kTerrace = 91; + kUtilityRoom = 92; + kWard = 93; + kWorkshop = 94; +} + +enum AtomicRequestTypeEnum : enum8 { + kBeginWrite = 0; + kCommitWrite = 1; + kRollbackWrite = 2; +} + +enum FloorSurfaceTag : enum8 { + kCarpet = 0; + kCeramic = 1; + kConcrete = 2; + kCork = 3; + kDeepCarpet = 4; + kDirt = 5; + kEngineeredWood = 6; + kGlass = 7; + kGrass = 8; + kHardwood = 9; + kLaminate = 10; + kLinoleum = 11; + kMat = 12; + kMetal = 13; + kPlastic = 14; + kPolishedConcrete = 15; + kRubber = 16; + kRug = 17; + kSand = 18; + kStone = 19; + kTatami = 20; + kTerrazzo = 21; + kTile = 22; + kVinyl = 23; +} + +enum LandmarkTag : enum8 { + kAirConditioner = 0; + kAirPurifier = 1; + kBackDoor = 2; + kBarStool = 3; + kBathMat = 4; + kBathtub = 5; + kBed = 6; + kBookshelf = 7; + kChair = 8; + kChristmasTree = 9; + kCoatRack = 10; + kCoffeeTable = 11; + kCookingRange = 12; + kCouch = 13; + kCountertop = 14; + kCradle = 15; + kCrib = 16; + kDesk = 17; + kDiningTable = 18; + kDishwasher = 19; + kDoor = 20; + kDresser = 21; + kLaundryDryer = 22; + kFan = 23; + kFireplace = 24; + kFreezer = 25; + kFrontDoor = 26; + kHighChair = 27; + kKitchenIsland = 28; + kLamp = 29; + kLitterBox = 30; + kMirror = 31; + kNightstand = 32; + kOven = 33; + kPetBed = 34; + kPetBowl = 35; + kPetCrate = 36; + kRefrigerator = 37; + kScratchingPost = 38; + kShoeRack = 39; + kShower = 40; + kSideDoor = 41; + kSink = 42; + kSofa = 43; + kStove = 44; + kTable = 45; + kToilet = 46; + kTrashCan = 47; + kLaundryWasher = 48; + kWindow = 49; + kWineCooler = 50; +} + +enum PositionTag : enum8 { + kLeft = 0; + kRight = 1; + kTop = 2; + kBottom = 3; + kMiddle = 4; + kRow = 5; + kColumn = 6; +} + +enum RelativePositionTag : enum8 { + kUnder = 0; + kNextTo = 1; + kAround = 2; + kOn = 3; + kAbove = 4; + kFrontOf = 5; + kBehind = 6; +} + +enum TestGlobalEnum : enum8 { + kSomeValue = 0; + kSomeOtherValue = 1; + kFinalValue = 2; +} + +bitmap TestGlobalBitmap : bitmap32 { + kFirstBit = 0x1; + kSecondBit = 0x2; +} + +struct TestGlobalStruct { + char_string<128> name = 0; + nullable TestGlobalBitmap myBitmap = 1; + optional nullable TestGlobalEnum myEnum = 2; +} + +struct LocationDescriptorStruct { + char_string<128> locationName = 0; + nullable int16s floorNumber = 1; + nullable AreaTypeTag areaType = 2; +} + +struct AtomicAttributeStatusStruct { + attrib_id attributeID = 0; + status statusCode = 1; +} + +/** The Descriptor Cluster is meant to replace the support from the Zigbee Device Object (ZDO) for describing a node, its endpoints and clusters. */ +cluster Descriptor = 29 { + revision 2; + + bitmap Feature : bitmap32 { + kTagList = 0x1; + } + + struct DeviceTypeStruct { + devtype_id deviceType = 0; + int16u revision = 1; + } + + struct SemanticTagStruct { + nullable vendor_id mfgCode = 0; + enum8 namespaceID = 1; + enum8 tag = 2; + optional nullable char_string label = 3; + } + + readonly attribute DeviceTypeStruct deviceTypeList[] = 0; + readonly attribute cluster_id serverList[] = 1; + readonly attribute cluster_id clientList[] = 2; + readonly attribute endpoint_no partsList[] = 3; + readonly attribute optional SemanticTagStruct tagList[] = 4; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** The Access Control Cluster exposes a data model view of a + Node's Access Control List (ACL), which codifies the rules used to manage + and enforce Access Control for the Node's endpoints and their associated + cluster instances. */ +cluster AccessControl = 31 { + revision 2; + + enum AccessControlEntryAuthModeEnum : enum8 { + kPASE = 1; + kCASE = 2; + kGroup = 3; + } + + enum AccessControlEntryPrivilegeEnum : enum8 { + kView = 1; + kProxyView = 2; + kOperate = 3; + kManage = 4; + kAdminister = 5; + } + + enum AccessRestrictionTypeEnum : enum8 { + kAttributeAccessForbidden = 0; + kAttributeWriteForbidden = 1; + kCommandForbidden = 2; + kEventForbidden = 3; + } + + enum ChangeTypeEnum : enum8 { + kChanged = 0; + kAdded = 1; + kRemoved = 2; + } + + bitmap Feature : bitmap32 { + kExtension = 0x1; + kManagedDevice = 0x2; + } + + struct AccessRestrictionStruct { + AccessRestrictionTypeEnum type = 0; + nullable int32u id = 1; + } + + struct CommissioningAccessRestrictionEntryStruct { + endpoint_no endpoint = 0; + cluster_id cluster = 1; + AccessRestrictionStruct restrictions[] = 2; + } + + fabric_scoped struct AccessRestrictionEntryStruct { + fabric_sensitive endpoint_no endpoint = 0; + fabric_sensitive cluster_id cluster = 1; + fabric_sensitive AccessRestrictionStruct restrictions[] = 2; + fabric_idx fabricIndex = 254; + } + + struct AccessControlTargetStruct { + nullable cluster_id cluster = 0; + nullable endpoint_no endpoint = 1; + nullable devtype_id deviceType = 2; + } + + fabric_scoped struct AccessControlEntryStruct { + fabric_sensitive AccessControlEntryPrivilegeEnum privilege = 1; + fabric_sensitive AccessControlEntryAuthModeEnum authMode = 2; + nullable fabric_sensitive int64u subjects[] = 3; + nullable fabric_sensitive AccessControlTargetStruct targets[] = 4; + fabric_idx fabricIndex = 254; + } + + fabric_scoped struct AccessControlExtensionStruct { + fabric_sensitive octet_string<128> data = 1; + fabric_idx fabricIndex = 254; + } + + fabric_sensitive info event access(read: administer) AccessControlEntryChanged = 0 { + nullable node_id adminNodeID = 1; + nullable int16u adminPasscodeID = 2; + ChangeTypeEnum changeType = 3; + nullable AccessControlEntryStruct latestValue = 4; + fabric_idx fabricIndex = 254; + } + + fabric_sensitive info event access(read: administer) AccessControlExtensionChanged = 1 { + nullable node_id adminNodeID = 1; + nullable int16u adminPasscodeID = 2; + ChangeTypeEnum changeType = 3; + nullable AccessControlExtensionStruct latestValue = 4; + fabric_idx fabricIndex = 254; + } + + fabric_sensitive info event access(read: administer) AccessRestrictionEntryChanged = 2 { + fabric_idx fabricIndex = 254; + } + + fabric_sensitive info event access(read: administer) FabricRestrictionReviewUpdate = 3 { + int64u token = 0; + nullable long_char_string instruction = 1; + nullable long_char_string redirectURL = 2; + fabric_idx fabricIndex = 254; + } + + attribute access(read: administer, write: administer) AccessControlEntryStruct acl[] = 0; + attribute access(read: administer, write: administer) optional AccessControlExtensionStruct extension[] = 1; + readonly attribute int16u subjectsPerAccessControlEntry = 2; + readonly attribute int16u targetsPerAccessControlEntry = 3; + readonly attribute int16u accessControlEntriesPerFabric = 4; + readonly attribute optional CommissioningAccessRestrictionEntryStruct commissioningARL[] = 5; + readonly attribute optional AccessRestrictionEntryStruct arl[] = 6; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct ReviewFabricRestrictionsRequest { + CommissioningAccessRestrictionEntryStruct arl[] = 0; + } + + response struct ReviewFabricRestrictionsResponse = 1 { + int64u token = 0; + } + + /** This command signals to the service associated with the device vendor that the fabric administrator would like a review of the current restrictions on the accessing fabric. */ + fabric command access(invoke: administer) ReviewFabricRestrictions(ReviewFabricRestrictionsRequest): DefaultSuccess = 0; +} + +/** This cluster provides attributes and events for determining basic information about Nodes, which supports both + Commissioning and operational determination of Node characteristics, such as Vendor ID, Product ID and serial number, + which apply to the whole Node. Also allows setting user device information such as location. */ +cluster BasicInformation = 40 { + revision 3; + + enum ColorEnum : enum8 { + kBlack = 0; + kNavy = 1; + kGreen = 2; + kTeal = 3; + kMaroon = 4; + kPurple = 5; + kOlive = 6; + kGray = 7; + kBlue = 8; + kLime = 9; + kAqua = 10; + kRed = 11; + kFuchsia = 12; + kYellow = 13; + kWhite = 14; + kNickel = 15; + kChrome = 16; + kBrass = 17; + kCopper = 18; + kSilver = 19; + kGold = 20; + } + + enum ProductFinishEnum : enum8 { + kOther = 0; + kMatte = 1; + kSatin = 2; + kPolished = 3; + kRugged = 4; + kFabric = 5; + } + + struct CapabilityMinimaStruct { + int16u caseSessionsPerFabric = 0; + int16u subscriptionsPerFabric = 1; + } + + struct ProductAppearanceStruct { + ProductFinishEnum finish = 0; + nullable ColorEnum primaryColor = 1; + } + + critical event StartUp = 0 { + int32u softwareVersion = 0; + } + + critical event ShutDown = 1 { + } + + info event Leave = 2 { + fabric_idx fabricIndex = 0; + } + + info event ReachableChanged = 3 { + boolean reachableNewValue = 0; + } + + readonly attribute int16u dataModelRevision = 0; + readonly attribute char_string<32> vendorName = 1; + readonly attribute vendor_id vendorID = 2; + readonly attribute char_string<32> productName = 3; + readonly attribute int16u productID = 4; + attribute access(write: manage) char_string<32> nodeLabel = 5; + attribute access(write: administer) char_string<2> location = 6; + readonly attribute int16u hardwareVersion = 7; + readonly attribute char_string<64> hardwareVersionString = 8; + readonly attribute int32u softwareVersion = 9; + readonly attribute char_string<64> softwareVersionString = 10; + readonly attribute optional char_string<16> manufacturingDate = 11; + readonly attribute optional char_string<32> partNumber = 12; + readonly attribute optional long_char_string<256> productURL = 13; + readonly attribute optional char_string<64> productLabel = 14; + readonly attribute optional char_string<32> serialNumber = 15; + attribute access(write: manage) optional boolean localConfigDisabled = 16; + readonly attribute optional boolean reachable = 17; + readonly attribute char_string<32> uniqueID = 18; + readonly attribute CapabilityMinimaStruct capabilityMinima = 19; + readonly attribute optional ProductAppearanceStruct productAppearance = 20; + readonly attribute int32u specificationVersion = 21; + readonly attribute int16u maxPathsPerInvoke = 22; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + command MfgSpecificPing(): DefaultSuccess = 0; +} + +/** Nodes should be expected to be deployed to any and all regions of the world. These global regions + may have differing common languages, units of measurements, and numerical formatting + standards. As such, Nodes that visually or audibly convey information need a mechanism by which + they can be configured to use a user’s preferred language, units, etc */ +cluster LocalizationConfiguration = 43 { + revision 1; // NOTE: Default/not specifically set + + attribute access(write: manage) char_string<35> activeLocale = 0; + readonly attribute char_string supportedLocales[] = 1; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Nodes should be expected to be deployed to any and all regions of the world. These global regions + may have differing preferences for how dates and times are conveyed. As such, Nodes that visually + or audibly convey time information need a mechanism by which they can be configured to use a + user’s preferred format. */ +cluster TimeFormatLocalization = 44 { + revision 1; // NOTE: Default/not specifically set + + enum CalendarTypeEnum : enum8 { + kBuddhist = 0; + kChinese = 1; + kCoptic = 2; + kEthiopian = 3; + kGregorian = 4; + kHebrew = 5; + kIndian = 6; + kIslamic = 7; + kJapanese = 8; + kKorean = 9; + kPersian = 10; + kTaiwanese = 11; + kUseActiveLocale = 255; + } + + enum HourFormatEnum : enum8 { + k12hr = 0; + k24hr = 1; + kUseActiveLocale = 255; + } + + bitmap Feature : bitmap32 { + kCalendarFormat = 0x1; + } + + attribute access(write: manage) HourFormatEnum hourFormat = 0; + attribute access(write: manage) optional CalendarTypeEnum activeCalendarType = 1; + readonly attribute optional CalendarTypeEnum supportedCalendarTypes[] = 2; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** This cluster is used to manage global aspects of the Commissioning flow. */ +cluster GeneralCommissioning = 48 { + revision 1; // NOTE: Default/not specifically set + + enum CommissioningErrorEnum : enum8 { + kOK = 0; + kValueOutsideRange = 1; + kInvalidAuthentication = 2; + kNoFailSafe = 3; + kBusyWithOtherAdmin = 4; + kRequiredTCNotAccepted = 5; + kTCAcknowledgementsNotReceived = 6; + kTCMinVersionNotMet = 7; + } + + enum RegulatoryLocationTypeEnum : enum8 { + kIndoor = 0; + kOutdoor = 1; + kIndoorOutdoor = 2; + } + + bitmap Feature : bitmap32 { + kTermsAndConditions = 0x1; + } + + struct BasicCommissioningInfo { + int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; + } + + attribute access(write: administer) int64u breadcrumb = 0; + readonly attribute BasicCommissioningInfo basicCommissioningInfo = 1; + readonly attribute RegulatoryLocationTypeEnum regulatoryConfig = 2; + readonly attribute RegulatoryLocationTypeEnum locationCapability = 3; + readonly attribute boolean supportsConcurrentConnection = 4; + provisional readonly attribute access(read: administer) optional int16u TCAcceptedVersion = 5; + provisional readonly attribute access(read: administer) optional int16u TCMinRequiredVersion = 6; + provisional readonly attribute access(read: administer) optional bitmap16 TCAcknowledgements = 7; + provisional readonly attribute access(read: administer) optional boolean TCAcknowledgementsRequired = 8; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct ArmFailSafeRequest { + int16u expiryLengthSeconds = 0; + int64u breadcrumb = 1; + } + + response struct ArmFailSafeResponse = 1 { + CommissioningErrorEnum errorCode = 0; + char_string<128> debugText = 1; + } + + request struct SetRegulatoryConfigRequest { + RegulatoryLocationTypeEnum newRegulatoryConfig = 0; + char_string<2> countryCode = 1; + int64u breadcrumb = 2; + } + + response struct SetRegulatoryConfigResponse = 3 { + CommissioningErrorEnum errorCode = 0; + char_string debugText = 1; + } + + response struct CommissioningCompleteResponse = 5 { + CommissioningErrorEnum errorCode = 0; + char_string debugText = 1; + } + + request struct SetTCAcknowledgementsRequest { + int16u TCVersion = 0; + bitmap16 TCUserResponse = 1; + } + + response struct SetTCAcknowledgementsResponse = 7 { + CommissioningErrorEnum errorCode = 0; + } + + /** Arm the persistent fail-safe timer with an expiry time of now + ExpiryLengthSeconds using device clock */ + command access(invoke: administer) ArmFailSafe(ArmFailSafeRequest): ArmFailSafeResponse = 0; + /** Set the regulatory configuration to be used during commissioning */ + command access(invoke: administer) SetRegulatoryConfig(SetRegulatoryConfigRequest): SetRegulatoryConfigResponse = 2; + /** Signals the Server that the Client has successfully completed all steps of Commissioning/Recofiguration needed during fail-safe period. */ + fabric command access(invoke: administer) CommissioningComplete(): CommissioningCompleteResponse = 4; + /** This command sets the user acknowledgements received in the Enhanced Setup Flow Terms and Conditions into the node. */ + command access(invoke: administer) SetTCAcknowledgements(SetTCAcknowledgementsRequest): SetTCAcknowledgementsResponse = 6; +} + +/** Functionality to configure, enable, disable network credentials and access on a Matter device. */ +cluster NetworkCommissioning = 49 { + revision 1; // NOTE: Default/not specifically set + + enum NetworkCommissioningStatusEnum : enum8 { + kSuccess = 0; + kOutOfRange = 1; + kBoundsExceeded = 2; + kNetworkIDNotFound = 3; + kDuplicateNetworkID = 4; + kNetworkNotFound = 5; + kRegulatoryError = 6; + kAuthFailure = 7; + kUnsupportedSecurity = 8; + kOtherConnectionFailure = 9; + kIPV6Failed = 10; + kIPBindFailed = 11; + kUnknownError = 12; + } + + enum WiFiBandEnum : enum8 { + k2G4 = 0; + k3G65 = 1; + k5G = 2; + k6G = 3; + k60G = 4; + k1G = 5; + } + + bitmap Feature : bitmap32 { + kWiFiNetworkInterface = 0x1; + kThreadNetworkInterface = 0x2; + kEthernetNetworkInterface = 0x4; + kPerDeviceCredentials = 0x8; + } + + bitmap ThreadCapabilitiesBitmap : bitmap16 { + kIsBorderRouterCapable = 0x1; + kIsRouterCapable = 0x2; + kIsSleepyEndDeviceCapable = 0x4; + kIsFullThreadDevice = 0x8; + kIsSynchronizedSleepyEndDeviceCapable = 0x10; + } + + bitmap WiFiSecurityBitmap : bitmap8 { + kUnencrypted = 0x1; + kWEP = 0x2; + kWPAPersonal = 0x4; + kWPA2Personal = 0x8; + kWPA3Personal = 0x10; + kWPA3MatterPDC = 0x20; + } + + struct NetworkInfoStruct { + octet_string<32> networkID = 0; + boolean connected = 1; + optional nullable octet_string<20> networkIdentifier = 2; + optional nullable octet_string<20> clientIdentifier = 3; + } + + struct ThreadInterfaceScanResultStruct { + int16u panId = 0; + int64u extendedPanId = 1; + char_string<16> networkName = 2; + int16u channel = 3; + int8u version = 4; + octet_string<8> extendedAddress = 5; + int8s rssi = 6; + int8u lqi = 7; + } + + struct WiFiInterfaceScanResultStruct { + WiFiSecurityBitmap security = 0; + octet_string<32> ssid = 1; + octet_string<6> bssid = 2; + int16u channel = 3; + WiFiBandEnum wiFiBand = 4; + int8s rssi = 5; + } + + readonly attribute access(read: administer) int8u maxNetworks = 0; + readonly attribute access(read: administer) NetworkInfoStruct networks[] = 1; + readonly attribute optional int8u scanMaxTimeSeconds = 2; + readonly attribute optional int8u connectMaxTimeSeconds = 3; + attribute access(write: administer) boolean interfaceEnabled = 4; + readonly attribute access(read: administer) nullable NetworkCommissioningStatusEnum lastNetworkingStatus = 5; + readonly attribute access(read: administer) nullable octet_string<32> lastNetworkID = 6; + readonly attribute access(read: administer) nullable int32s lastConnectErrorValue = 7; + provisional readonly attribute optional WiFiBandEnum supportedWiFiBands[] = 8; + provisional readonly attribute optional ThreadCapabilitiesBitmap supportedThreadFeatures = 9; + provisional readonly attribute optional int16u threadVersion = 10; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct ScanNetworksRequest { + optional nullable octet_string<32> ssid = 0; + optional int64u breadcrumb = 1; + } + + response struct ScanNetworksResponse = 1 { + NetworkCommissioningStatusEnum networkingStatus = 0; + optional char_string debugText = 1; + optional WiFiInterfaceScanResultStruct wiFiScanResults[] = 2; + optional ThreadInterfaceScanResultStruct threadScanResults[] = 3; + } + + request struct AddOrUpdateWiFiNetworkRequest { + octet_string<32> ssid = 0; + octet_string<64> credentials = 1; + optional int64u breadcrumb = 2; + optional octet_string<140> networkIdentity = 3; + optional octet_string<20> clientIdentifier = 4; + optional octet_string<32> possessionNonce = 5; + } + + request struct AddOrUpdateThreadNetworkRequest { + octet_string<254> operationalDataset = 0; + optional int64u breadcrumb = 1; + } + + request struct RemoveNetworkRequest { + octet_string<32> networkID = 0; + optional int64u breadcrumb = 1; + } + + response struct NetworkConfigResponse = 5 { + NetworkCommissioningStatusEnum networkingStatus = 0; + optional char_string<512> debugText = 1; + optional int8u networkIndex = 2; + optional octet_string<140> clientIdentity = 3; + optional octet_string<64> possessionSignature = 4; + } + + request struct ConnectNetworkRequest { + octet_string<32> networkID = 0; + optional int64u breadcrumb = 1; + } + + response struct ConnectNetworkResponse = 7 { + NetworkCommissioningStatusEnum networkingStatus = 0; + optional char_string debugText = 1; + nullable int32s errorValue = 2; + } + + request struct ReorderNetworkRequest { + octet_string<32> networkID = 0; + int8u networkIndex = 1; + optional int64u breadcrumb = 2; + } + + request struct QueryIdentityRequest { + octet_string<20> keyIdentifier = 0; + optional octet_string<32> possessionNonce = 1; + } + + response struct QueryIdentityResponse = 10 { + octet_string<140> identity = 0; + optional octet_string<64> possessionSignature = 1; + } + + /** Detemine the set of networks the device sees as available. */ + command access(invoke: administer) ScanNetworks(ScanNetworksRequest): ScanNetworksResponse = 0; + /** Add or update the credentials for a given Wi-Fi network. */ + command access(invoke: administer) AddOrUpdateWiFiNetwork(AddOrUpdateWiFiNetworkRequest): NetworkConfigResponse = 2; + /** Add or update the credentials for a given Thread network. */ + command access(invoke: administer) AddOrUpdateThreadNetwork(AddOrUpdateThreadNetworkRequest): NetworkConfigResponse = 3; + /** Remove the definition of a given network (including its credentials). */ + command access(invoke: administer) RemoveNetwork(RemoveNetworkRequest): NetworkConfigResponse = 4; + /** Connect to the specified network, using previously-defined credentials. */ + command access(invoke: administer) ConnectNetwork(ConnectNetworkRequest): ConnectNetworkResponse = 6; + /** Modify the order in which networks will be presented in the Networks attribute. */ + command access(invoke: administer) ReorderNetwork(ReorderNetworkRequest): NetworkConfigResponse = 8; + /** Retrieve details about and optionally proof of possession of a network client identity. */ + command access(invoke: administer) QueryIdentity(QueryIdentityRequest): QueryIdentityResponse = 9; +} + +/** The General Diagnostics Cluster, along with other diagnostics clusters, provide a means to acquire standardized diagnostics metrics that MAY be used by a Node to assist a user or Administrative Node in diagnosing potential problems. */ +cluster GeneralDiagnostics = 51 { + revision 2; + + enum BootReasonEnum : enum8 { + kUnspecified = 0; + kPowerOnReboot = 1; + kBrownOutReset = 2; + kSoftwareWatchdogReset = 3; + kHardwareWatchdogReset = 4; + kSoftwareUpdateCompleted = 5; + kSoftwareReset = 6; + } + + enum HardwareFaultEnum : enum8 { + kUnspecified = 0; + kRadio = 1; + kSensor = 2; + kResettableOverTemp = 3; + kNonResettableOverTemp = 4; + kPowerSource = 5; + kVisualDisplayFault = 6; + kAudioOutputFault = 7; + kUserInterfaceFault = 8; + kNonVolatileMemoryError = 9; + kTamperDetected = 10; + } + + enum InterfaceTypeEnum : enum8 { + kUnspecified = 0; + kWiFi = 1; + kEthernet = 2; + kCellular = 3; + kThread = 4; + } + + enum NetworkFaultEnum : enum8 { + kUnspecified = 0; + kHardwareFailure = 1; + kNetworkJammed = 2; + kConnectionFailed = 3; + } + + enum RadioFaultEnum : enum8 { + kUnspecified = 0; + kWiFiFault = 1; + kCellularFault = 2; + kThreadFault = 3; + kNFCFault = 4; + kBLEFault = 5; + kEthernetFault = 6; + } + + bitmap Feature : bitmap32 { + kDataModelTest = 0x1; + } + + struct NetworkInterface { + char_string<32> name = 0; + boolean isOperational = 1; + nullable boolean offPremiseServicesReachableIPv4 = 2; + nullable boolean offPremiseServicesReachableIPv6 = 3; + octet_string<8> hardwareAddress = 4; + octet_string IPv4Addresses[] = 5; + octet_string IPv6Addresses[] = 6; + InterfaceTypeEnum type = 7; + } + + critical event HardwareFaultChange = 0 { + HardwareFaultEnum current[] = 0; + HardwareFaultEnum previous[] = 1; + } + + critical event RadioFaultChange = 1 { + RadioFaultEnum current[] = 0; + RadioFaultEnum previous[] = 1; + } + + critical event NetworkFaultChange = 2 { + NetworkFaultEnum current[] = 0; + NetworkFaultEnum previous[] = 1; + } + + critical event BootReason = 3 { + BootReasonEnum bootReason = 0; + } + + readonly attribute NetworkInterface networkInterfaces[] = 0; + readonly attribute int16u rebootCount = 1; + readonly attribute optional int64u upTime = 2; + readonly attribute optional int32u totalOperationalHours = 3; + readonly attribute optional BootReasonEnum bootReason = 4; + readonly attribute optional HardwareFaultEnum activeHardwareFaults[] = 5; + readonly attribute optional RadioFaultEnum activeRadioFaults[] = 6; + readonly attribute optional NetworkFaultEnum activeNetworkFaults[] = 7; + readonly attribute boolean testEventTriggersEnabled = 8; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct TestEventTriggerRequest { + octet_string<16> enableKey = 0; + int64u eventTrigger = 1; + } + + response struct TimeSnapshotResponse = 2 { + systime_ms systemTimeMs = 0; + nullable posix_ms posixTimeMs = 1; + } + + request struct PayloadTestRequestRequest { + octet_string<16> enableKey = 0; + int8u value = 1; + int16u count = 2; + } + + response struct PayloadTestResponse = 4 { + octet_string payload = 0; + } + + /** Provide a means for certification tests to trigger some test-plan-specific events */ + command access(invoke: manage) TestEventTrigger(TestEventTriggerRequest): DefaultSuccess = 0; + /** Take a snapshot of system time and epoch time. */ + command TimeSnapshot(): TimeSnapshotResponse = 1; + /** Request a variable length payload response. */ + command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; +} + +/** The Thread Network Diagnostics Cluster provides a means to acquire standardized diagnostics metrics that MAY be used by a Node to assist a user or Administrative Node in diagnosing potential problems */ +cluster ThreadNetworkDiagnostics = 53 { + revision 2; + + enum ConnectionStatusEnum : enum8 { + kConnected = 0; + kNotConnected = 1; + } + + enum NetworkFaultEnum : enum8 { + kUnspecified = 0; + kLinkDown = 1; + kHardwareFailure = 2; + kNetworkJammed = 3; + } + + enum RoutingRoleEnum : enum8 { + kUnspecified = 0; + kUnassigned = 1; + kSleepyEndDevice = 2; + kEndDevice = 3; + kREED = 4; + kRouter = 5; + kLeader = 6; + } + + bitmap Feature : bitmap32 { + kPacketCounts = 0x1; + kErrorCounts = 0x2; + kMLECounts = 0x4; + kMACCounts = 0x8; + } + + struct NeighborTableStruct { + int64u extAddress = 0; + int32u age = 1; + int16u rloc16 = 2; + int32u linkFrameCounter = 3; + int32u mleFrameCounter = 4; + int8u lqi = 5; + nullable int8s averageRssi = 6; + nullable int8s lastRssi = 7; + int8u frameErrorRate = 8; + int8u messageErrorRate = 9; + boolean rxOnWhenIdle = 10; + boolean fullThreadDevice = 11; + boolean fullNetworkData = 12; + boolean isChild = 13; + } + + struct OperationalDatasetComponents { + boolean activeTimestampPresent = 0; + boolean pendingTimestampPresent = 1; + boolean masterKeyPresent = 2; + boolean networkNamePresent = 3; + boolean extendedPanIdPresent = 4; + boolean meshLocalPrefixPresent = 5; + boolean delayPresent = 6; + boolean panIdPresent = 7; + boolean channelPresent = 8; + boolean pskcPresent = 9; + boolean securityPolicyPresent = 10; + boolean channelMaskPresent = 11; + } + + struct RouteTableStruct { + int64u extAddress = 0; + int16u rloc16 = 1; + int8u routerId = 2; + int8u nextHop = 3; + int8u pathCost = 4; + int8u LQIIn = 5; + int8u LQIOut = 6; + int8u age = 7; + boolean allocated = 8; + boolean linkEstablished = 9; + } + + struct SecurityPolicy { + int16u rotationTime = 0; + int16u flags = 1; + } + + info event ConnectionStatus = 0 { + ConnectionStatusEnum connectionStatus = 0; + } + + info event NetworkFaultChange = 1 { + NetworkFaultEnum current[] = 0; + NetworkFaultEnum previous[] = 1; + } + + readonly attribute nullable int16u channel = 0; + readonly attribute nullable RoutingRoleEnum routingRole = 1; + readonly attribute nullable char_string<16> networkName = 2; + readonly attribute nullable int16u panId = 3; + readonly attribute nullable int64u extendedPanId = 4; + readonly attribute nullable octet_string<17> meshLocalPrefix = 5; + readonly attribute optional int64u overrunCount = 6; + readonly attribute NeighborTableStruct neighborTable[] = 7; + readonly attribute RouteTableStruct routeTable[] = 8; + readonly attribute nullable int32u partitionId = 9; + readonly attribute nullable int16u weighting = 10; + readonly attribute nullable int16u dataVersion = 11; + readonly attribute nullable int16u stableDataVersion = 12; + readonly attribute nullable int8u leaderRouterId = 13; + readonly attribute optional int16u detachedRoleCount = 14; + readonly attribute optional int16u childRoleCount = 15; + readonly attribute optional int16u routerRoleCount = 16; + readonly attribute optional int16u leaderRoleCount = 17; + readonly attribute optional int16u attachAttemptCount = 18; + readonly attribute optional int16u partitionIdChangeCount = 19; + readonly attribute optional int16u betterPartitionAttachAttemptCount = 20; + readonly attribute optional int16u parentChangeCount = 21; + readonly attribute optional int32u txTotalCount = 22; + readonly attribute optional int32u txUnicastCount = 23; + readonly attribute optional int32u txBroadcastCount = 24; + readonly attribute optional int32u txAckRequestedCount = 25; + readonly attribute optional int32u txAckedCount = 26; + readonly attribute optional int32u txNoAckRequestedCount = 27; + readonly attribute optional int32u txDataCount = 28; + readonly attribute optional int32u txDataPollCount = 29; + readonly attribute optional int32u txBeaconCount = 30; + readonly attribute optional int32u txBeaconRequestCount = 31; + readonly attribute optional int32u txOtherCount = 32; + readonly attribute optional int32u txRetryCount = 33; + readonly attribute optional int32u txDirectMaxRetryExpiryCount = 34; + readonly attribute optional int32u txIndirectMaxRetryExpiryCount = 35; + readonly attribute optional int32u txErrCcaCount = 36; + readonly attribute optional int32u txErrAbortCount = 37; + readonly attribute optional int32u txErrBusyChannelCount = 38; + readonly attribute optional int32u rxTotalCount = 39; + readonly attribute optional int32u rxUnicastCount = 40; + readonly attribute optional int32u rxBroadcastCount = 41; + readonly attribute optional int32u rxDataCount = 42; + readonly attribute optional int32u rxDataPollCount = 43; + readonly attribute optional int32u rxBeaconCount = 44; + readonly attribute optional int32u rxBeaconRequestCount = 45; + readonly attribute optional int32u rxOtherCount = 46; + readonly attribute optional int32u rxAddressFilteredCount = 47; + readonly attribute optional int32u rxDestAddrFilteredCount = 48; + readonly attribute optional int32u rxDuplicatedCount = 49; + readonly attribute optional int32u rxErrNoFrameCount = 50; + readonly attribute optional int32u rxErrUnknownNeighborCount = 51; + readonly attribute optional int32u rxErrInvalidSrcAddrCount = 52; + readonly attribute optional int32u rxErrSecCount = 53; + readonly attribute optional int32u rxErrFcsCount = 54; + readonly attribute optional int32u rxErrOtherCount = 55; + readonly attribute optional nullable int64u activeTimestamp = 56; + readonly attribute optional nullable int64u pendingTimestamp = 57; + readonly attribute optional nullable int32u delay = 58; + readonly attribute nullable SecurityPolicy securityPolicy = 59; + readonly attribute nullable octet_string<4> channelPage0Mask = 60; + readonly attribute nullable OperationalDatasetComponents operationalDatasetComponents = 61; + readonly attribute NetworkFaultEnum activeNetworkFaultsList[] = 62; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + /** Reception of this command SHALL reset the OverrunCount attributes to 0 */ + command access(invoke: manage) ResetCounts(): DefaultSuccess = 0; +} + +/** Commands to trigger a Node to allow a new Administrator to commission it. */ +cluster AdministratorCommissioning = 60 { + revision 1; // NOTE: Default/not specifically set + + enum CommissioningWindowStatusEnum : enum8 { + kWindowNotOpen = 0; + kEnhancedWindowOpen = 1; + kBasicWindowOpen = 2; + } + + enum StatusCode : enum8 { + kBusy = 2; + kPAKEParameterError = 3; + kWindowNotOpen = 4; + } + + bitmap Feature : bitmap32 { + kBasic = 0x1; + } + + readonly attribute CommissioningWindowStatusEnum windowStatus = 0; + readonly attribute nullable fabric_idx adminFabricIndex = 1; + readonly attribute nullable vendor_id adminVendorId = 2; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct OpenCommissioningWindowRequest { + int16u commissioningTimeout = 0; + octet_string PAKEPasscodeVerifier = 1; + int16u discriminator = 2; + int32u iterations = 3; + octet_string<32> salt = 4; + } + + request struct OpenBasicCommissioningWindowRequest { + int16u commissioningTimeout = 0; + } + + /** This command is used by a current Administrator to instruct a Node to go into commissioning mode using enhanced commissioning method. */ + timed command access(invoke: administer) OpenCommissioningWindow(OpenCommissioningWindowRequest): DefaultSuccess = 0; + /** This command is used by a current Administrator to instruct a Node to go into commissioning mode using basic commissioning method, if the node supports it. */ + timed command access(invoke: administer) OpenBasicCommissioningWindow(OpenBasicCommissioningWindowRequest): DefaultSuccess = 1; + /** This command is used by a current Administrator to instruct a Node to revoke any active Open Commissioning Window or Open Basic Commissioning Window command. */ + timed command access(invoke: administer) RevokeCommissioning(): DefaultSuccess = 2; +} + +/** This cluster is used to add or remove Operational Credentials on a Commissionee or Node, as well as manage the associated Fabrics. */ +cluster OperationalCredentials = 62 { + revision 1; // NOTE: Default/not specifically set + + enum CertificateChainTypeEnum : enum8 { + kDACCertificate = 1; + kPAICertificate = 2; + } + + enum NodeOperationalCertStatusEnum : enum8 { + kOK = 0; + kInvalidPublicKey = 1; + kInvalidNodeOpId = 2; + kInvalidNOC = 3; + kMissingCsr = 4; + kTableFull = 5; + kInvalidAdminSubject = 6; + kFabricConflict = 9; + kLabelConflict = 10; + kInvalidFabricIndex = 11; + } + + fabric_scoped struct FabricDescriptorStruct { + octet_string<65> rootPublicKey = 1; + vendor_id vendorID = 2; + fabric_id fabricID = 3; + node_id nodeID = 4; + char_string<32> label = 5; + fabric_idx fabricIndex = 254; + } + + fabric_scoped struct NOCStruct { + fabric_sensitive octet_string noc = 1; + nullable fabric_sensitive octet_string icac = 2; + fabric_idx fabricIndex = 254; + } + + readonly attribute access(read: administer) NOCStruct NOCs[] = 0; + readonly attribute FabricDescriptorStruct fabrics[] = 1; + readonly attribute int8u supportedFabrics = 2; + readonly attribute int8u commissionedFabrics = 3; + readonly attribute octet_string trustedRootCertificates[] = 4; + readonly attribute int8u currentFabricIndex = 5; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct AttestationRequestRequest { + octet_string<32> attestationNonce = 0; + } + + response struct AttestationResponse = 1 { + octet_string<900> attestationElements = 0; + octet_string<64> attestationSignature = 1; + } + + request struct CertificateChainRequestRequest { + CertificateChainTypeEnum certificateType = 0; + } + + response struct CertificateChainResponse = 3 { + octet_string<600> certificate = 0; + } + + request struct CSRRequestRequest { + octet_string<32> CSRNonce = 0; + optional boolean isForUpdateNOC = 1; + } + + response struct CSRResponse = 5 { + octet_string NOCSRElements = 0; + octet_string attestationSignature = 1; + } + + request struct AddNOCRequest { + octet_string<400> NOCValue = 0; + optional octet_string<400> ICACValue = 1; + octet_string<16> IPKValue = 2; + int64u caseAdminSubject = 3; + vendor_id adminVendorId = 4; + } + + request struct UpdateNOCRequest { + octet_string NOCValue = 0; + optional octet_string ICACValue = 1; + } + + response struct NOCResponse = 8 { + NodeOperationalCertStatusEnum statusCode = 0; + optional fabric_idx fabricIndex = 1; + optional char_string<128> debugText = 2; + } + + request struct UpdateFabricLabelRequest { + char_string<32> label = 0; + } + + request struct RemoveFabricRequest { + fabric_idx fabricIndex = 0; + } + + request struct AddTrustedRootCertificateRequest { + octet_string rootCACertificate = 0; + } + + /** Sender is requesting attestation information from the receiver. */ + command access(invoke: administer) AttestationRequest(AttestationRequestRequest): AttestationResponse = 0; + /** Sender is requesting a device attestation certificate from the receiver. */ + command access(invoke: administer) CertificateChainRequest(CertificateChainRequestRequest): CertificateChainResponse = 2; + /** Sender is requesting a certificate signing request (CSR) from the receiver. */ + command access(invoke: administer) CSRRequest(CSRRequestRequest): CSRResponse = 4; + /** Sender is requesting to add the new node operational certificates. */ + command access(invoke: administer) AddNOC(AddNOCRequest): NOCResponse = 6; + /** Sender is requesting to update the node operational certificates. */ + fabric command access(invoke: administer) UpdateNOC(UpdateNOCRequest): NOCResponse = 7; + /** This command SHALL be used by an Administrative Node to set the user-visible Label field for a given Fabric, as reflected by entries in the Fabrics attribute. */ + fabric command access(invoke: administer) UpdateFabricLabel(UpdateFabricLabelRequest): NOCResponse = 9; + /** This command is used by Administrative Nodes to remove a given fabric index and delete all associated fabric-scoped data. */ + command access(invoke: administer) RemoveFabric(RemoveFabricRequest): NOCResponse = 10; + /** This command SHALL add a Trusted Root CA Certificate, provided as its CHIP Certificate representation. */ + command access(invoke: administer) AddTrustedRootCertificate(AddTrustedRootCertificateRequest): DefaultSuccess = 11; +} + +/** The Group Key Management Cluster is the mechanism by which group keys are managed. */ +cluster GroupKeyManagement = 63 { + revision 1; // NOTE: Default/not specifically set + + enum GroupKeySecurityPolicyEnum : enum8 { + kTrustFirst = 0; + kCacheAndSync = 1; + } + + bitmap Feature : bitmap32 { + kCacheAndSync = 0x1; + } + + fabric_scoped struct GroupInfoMapStruct { + group_id groupId = 1; + endpoint_no endpoints[] = 2; + optional char_string<16> groupName = 3; + fabric_idx fabricIndex = 254; + } + + fabric_scoped struct GroupKeyMapStruct { + group_id groupId = 1; + int16u groupKeySetID = 2; + fabric_idx fabricIndex = 254; + } + + struct GroupKeySetStruct { + int16u groupKeySetID = 0; + GroupKeySecurityPolicyEnum groupKeySecurityPolicy = 1; + nullable octet_string<16> epochKey0 = 2; + nullable epoch_us epochStartTime0 = 3; + nullable octet_string<16> epochKey1 = 4; + nullable epoch_us epochStartTime1 = 5; + nullable octet_string<16> epochKey2 = 6; + nullable epoch_us epochStartTime2 = 7; + } + + attribute access(write: manage) GroupKeyMapStruct groupKeyMap[] = 0; + readonly attribute GroupInfoMapStruct groupTable[] = 1; + readonly attribute int16u maxGroupsPerFabric = 2; + readonly attribute int16u maxGroupKeysPerFabric = 3; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct KeySetWriteRequest { + GroupKeySetStruct groupKeySet = 0; + } + + request struct KeySetReadRequest { + int16u groupKeySetID = 0; + } + + response struct KeySetReadResponse = 2 { + GroupKeySetStruct groupKeySet = 0; + } + + request struct KeySetRemoveRequest { + int16u groupKeySetID = 0; + } + + response struct KeySetReadAllIndicesResponse = 5 { + int16u groupKeySetIDs[] = 0; + } + + /** Write a new set of keys for the given key set id. */ + fabric command access(invoke: administer) KeySetWrite(KeySetWriteRequest): DefaultSuccess = 0; + /** Read the keys for a given key set id. */ + fabric command access(invoke: administer) KeySetRead(KeySetReadRequest): KeySetReadResponse = 1; + /** Revoke a Root Key from a Group */ + fabric command access(invoke: administer) KeySetRemove(KeySetRemoveRequest): DefaultSuccess = 3; + /** Return the list of Group Key Sets associated with the accessing fabric */ + fabric command access(invoke: administer) KeySetReadAllIndices(): KeySetReadAllIndicesResponse = 4; +} + +/** The Fixed Label Cluster provides a feature for the device to tag an endpoint with zero or more read only +labels. */ +cluster FixedLabel = 64 { + revision 1; // NOTE: Default/not specifically set + + struct LabelStruct { + char_string<16> label = 0; + char_string<16> value = 1; + } + + readonly attribute LabelStruct labelList[] = 0; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** The User Label Cluster provides a feature to tag an endpoint with zero or more labels. */ +cluster UserLabel = 65 { + revision 1; // NOTE: Default/not specifically set + + struct LabelStruct { + char_string<16> label = 0; + char_string<16> value = 1; + } + + attribute access(write: manage) LabelStruct labelList[] = 0; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Manage the Thread network of Thread Border Router */ +provisional cluster ThreadBorderRouterManagement = 1106 { + revision 1; + + bitmap Feature : bitmap32 { + kPANChange = 0x1; + } + + provisional readonly attribute char_string<63> borderRouterName = 0; + provisional readonly attribute octet_string<254> borderAgentID = 1; + provisional readonly attribute int16u threadVersion = 2; + provisional readonly attribute boolean interfaceEnabled = 3; + provisional readonly attribute nullable int64u activeDatasetTimestamp = 4; + provisional readonly attribute nullable int64u pendingDatasetTimestamp = 5; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + response struct DatasetResponse = 2 { + octet_string<254> dataset = 0; + } + + request struct SetActiveDatasetRequestRequest { + octet_string<254> activeDataset = 0; + optional int64u breadcrumb = 1; + } + + request struct SetPendingDatasetRequestRequest { + octet_string<254> pendingDataset = 0; + } + + /** Command to request the active operational dataset of the Thread network to which the border router is connected. This command must be sent over a valid CASE session */ + command access(invoke: manage) GetActiveDatasetRequest(): DatasetResponse = 0; + /** Command to request the pending dataset of the Thread network to which the border router is connected. This command must be sent over a valid CASE session */ + command access(invoke: manage) GetPendingDatasetRequest(): DatasetResponse = 1; + /** Command to set or update the active Dataset of the Thread network to which the Border Router is connected. */ + command access(invoke: manage) SetActiveDatasetRequest(SetActiveDatasetRequestRequest): DefaultSuccess = 3; + /** Command set or update the pending Dataset of the Thread network to which the Border Router is connected. */ + command access(invoke: manage) SetPendingDatasetRequest(SetPendingDatasetRequestRequest): DefaultSuccess = 4; +} + +endpoint 0 { + device type ma_rootdevice = 22, version 1; + + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster AccessControl { + emits event AccessControlEntryChanged; + emits event AccessControlExtensionChanged; + callback attribute acl; + callback attribute extension; + callback attribute subjectsPerAccessControlEntry; + callback attribute targetsPerAccessControlEntry; + callback attribute accessControlEntriesPerFabric; + callback attribute attributeList; + ram attribute featureMap default = 0; + callback attribute clusterRevision; + } + + server cluster BasicInformation { + emits event StartUp; + emits event ShutDown; + emits event Leave; + callback attribute dataModelRevision; + callback attribute vendorName; + callback attribute vendorID; + callback attribute productName; + callback attribute productID; + persist attribute nodeLabel; + callback attribute location; + callback attribute hardwareVersion; + callback attribute hardwareVersionString; + callback attribute softwareVersion; + callback attribute softwareVersionString; + callback attribute manufacturingDate; + callback attribute partNumber; + callback attribute productURL; + callback attribute productLabel; + callback attribute serialNumber; + persist attribute localConfigDisabled default = 0; + callback attribute uniqueID; + callback attribute capabilityMinima; + callback attribute specificationVersion; + callback attribute maxPathsPerInvoke; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 3; + } + + server cluster LocalizationConfiguration { + persist attribute activeLocale default = "en-US"; + callback attribute supportedLocales; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster TimeFormatLocalization { + persist attribute hourFormat default = 0; + persist attribute activeCalendarType default = 0; + callback attribute supportedCalendarTypes; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster GeneralCommissioning { + ram attribute breadcrumb default = 0x0000000000000000; + callback attribute basicCommissioningInfo; + callback attribute regulatoryConfig; + callback attribute locationCapability; + callback attribute supportsConcurrentConnection; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + + handle command ArmFailSafe; + handle command ArmFailSafeResponse; + handle command SetRegulatoryConfig; + handle command SetRegulatoryConfigResponse; + handle command CommissioningComplete; + handle command CommissioningCompleteResponse; + } + + server cluster NetworkCommissioning { + ram attribute maxNetworks; + callback attribute networks; + ram attribute scanMaxTimeSeconds; + ram attribute connectMaxTimeSeconds; + ram attribute interfaceEnabled; + ram attribute lastNetworkingStatus; + ram attribute lastNetworkID; + ram attribute lastConnectErrorValue; + ram attribute featureMap default = 2; + ram attribute clusterRevision default = 1; + + handle command ScanNetworks; + handle command ScanNetworksResponse; + handle command AddOrUpdateWiFiNetwork; + handle command AddOrUpdateThreadNetwork; + handle command RemoveNetwork; + handle command NetworkConfigResponse; + handle command ConnectNetwork; + handle command ConnectNetworkResponse; + handle command ReorderNetwork; + } + + server cluster GeneralDiagnostics { + emits event BootReason; + callback attribute networkInterfaces; + callback attribute rebootCount; + callback attribute upTime; + callback attribute totalOperationalHours; + callback attribute bootReason; + callback attribute activeHardwareFaults; + callback attribute activeRadioFaults; + callback attribute activeNetworkFaults; + callback attribute testEventTriggersEnabled default = false; + callback attribute featureMap; + callback attribute clusterRevision; + + handle command TestEventTrigger; + handle command TimeSnapshot; + handle command TimeSnapshotResponse; + } + + server cluster AdministratorCommissioning { + callback attribute windowStatus; + callback attribute adminFabricIndex; + callback attribute adminVendorId; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + + handle command OpenCommissioningWindow; + handle command OpenBasicCommissioningWindow; + handle command RevokeCommissioning; + } + + server cluster OperationalCredentials { + callback attribute NOCs; + callback attribute fabrics; + callback attribute supportedFabrics; + callback attribute commissionedFabrics; + callback attribute trustedRootCertificates; + callback attribute currentFabricIndex; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + + handle command AttestationRequest; + handle command AttestationResponse; + handle command CertificateChainRequest; + handle command CertificateChainResponse; + handle command CSRRequest; + handle command CSRResponse; + handle command AddNOC; + handle command UpdateNOC; + handle command NOCResponse; + handle command UpdateFabricLabel; + handle command RemoveFabric; + handle command AddTrustedRootCertificate; + } + + server cluster GroupKeyManagement { + callback attribute groupKeyMap; + callback attribute groupTable; + callback attribute maxGroupsPerFabric; + callback attribute maxGroupKeysPerFabric; + callback attribute featureMap; + callback attribute clusterRevision; + + handle command KeySetWrite; + handle command KeySetRead; + handle command KeySetReadResponse; + handle command KeySetRemove; + handle command KeySetReadAllIndices; + handle command KeySetReadAllIndicesResponse; + } + + server cluster FixedLabel { + callback attribute labelList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster UserLabel { + callback attribute labelList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } +} +endpoint 1 { + device type ma_thread_border_router = 145, version 1; + + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster ThreadNetworkDiagnostics { + callback attribute channel; + callback attribute routingRole; + callback attribute networkName; + callback attribute panId; + callback attribute extendedPanId; + callback attribute meshLocalPrefix; + callback attribute neighborTable; + callback attribute routeTable; + callback attribute partitionId; + callback attribute weighting; + callback attribute dataVersion; + callback attribute stableDataVersion; + callback attribute leaderRouterId; + callback attribute securityPolicy; + callback attribute channelPage0Mask; + callback attribute operationalDatasetComponents; + callback attribute activeNetworkFaultsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 2; + } + + server cluster ThreadBorderRouterManagement { + callback attribute borderRouterName; + callback attribute borderAgentID; + callback attribute threadVersion; + callback attribute interfaceEnabled; + callback attribute activeDatasetTimestamp; + callback attribute pendingDatasetTimestamp; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 1; + + handle command GetActiveDatasetRequest; + handle command GetPendingDatasetRequest; + handle command DatasetResponse; + handle command SetActiveDatasetRequest; + handle command SetPendingDatasetRequest; + } +} + + diff --git a/examples/thread-br-app/thread-br-common/thread-br-app.zap b/examples/thread-br-app/thread-br-common/thread-br-app.zap new file mode 100644 index 00000000000000..e8c999068390e6 --- /dev/null +++ b/examples/thread-br-app/thread-br-common/thread-br-app.zap @@ -0,0 +1,3041 @@ +{ + "fileFormat": 2, + "featureLevel": 103, + "creator": "zap", + "keyValuePairs": [ + { + "key": "commandDiscovery", + "value": "1" + }, + { + "key": "defaultResponsePolicy", + "value": "always" + }, + { + "key": "manufacturerCodes", + "value": "0x1002" + } + ], + "package": [ + { + "pathRelativity": "relativeToZap", + "path": "../../../src/app/zap-templates/zcl/zcl.json", + "type": "zcl-properties", + "category": "matter", + "version": 1, + "description": "Matter SDK ZCL data" + }, + { + "pathRelativity": "relativeToZap", + "path": "../../../src/app/zap-templates/app-templates.json", + "type": "gen-templates-json", + "category": "matter", + "version": "chip-v1" + } + ], + "endpointTypes": [ + { + "id": 1, + "name": "MA-rootdevice", + "deviceTypeRef": { + "code": 22, + "profileId": 259, + "label": "MA-rootdevice", + "name": "MA-rootdevice" + }, + "deviceTypes": [ + { + "code": 22, + "profileId": 259, + "label": "MA-rootdevice", + "name": "MA-rootdevice" + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 22 + ], + "deviceTypeName": "MA-rootdevice", + "deviceTypeCode": 22, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Access Control", + "code": 31, + "mfgCode": null, + "define": "ACCESS_CONTROL_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "ACL", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Extension", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SubjectsPerAccessControlEntry", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TargetsPerAccessControlEntry", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AccessControlEntriesPerFabric", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "AccessControlEntryChanged", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "AccessControlExtensionChanged", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, + { + "name": "Basic Information", + "code": 40, + "mfgCode": null, + "define": "BASIC_INFORMATION_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DataModelRevision", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "VendorName", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "VendorID", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "vendor_id", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductName", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductID", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NodeLabel", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "NVM", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Location", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "HardwareVersion", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "HardwareVersionString", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SoftwareVersion", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SoftwareVersionString", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ManufacturingDate", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PartNumber", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductURL", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "long_char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductLabel", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SerialNumber", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LocalConfigDisabled", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "NVM", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UniqueID", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CapabilityMinima", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "CapabilityMinimaStruct", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SpecificationVersion", + "code": 21, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxPathsPerInvoke", + "code": 22, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "StartUp", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "ShutDown", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "Leave", + "code": 2, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, + { + "name": "Localization Configuration", + "code": 43, + "mfgCode": null, + "define": "LOCALIZATION_CONFIGURATION_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "ActiveLocale", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "en-US", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SupportedLocales", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Time Format Localization", + "code": 44, + "mfgCode": null, + "define": "TIME_FORMAT_LOCALIZATION_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "HourFormat", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "HourFormatEnum", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveCalendarType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "CalendarTypeEnum", + "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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "General Commissioning", + "code": 48, + "mfgCode": null, + "define": "GENERAL_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ArmFailSafe", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ArmFailSafeResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "SetRegulatoryConfig", + "code": 2, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "SetRegulatoryConfigResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "CommissioningComplete", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "CommissioningCompleteResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "Breadcrumb", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "BasicCommissioningInfo", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "BasicCommissioningInfo", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RegulatoryConfig", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "RegulatoryLocationTypeEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LocationCapability", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "RegulatoryLocationTypeEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SupportsConcurrentConnection", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Network Commissioning", + "code": 49, + "mfgCode": null, + "define": "NETWORK_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ScanNetworks", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ScanNetworksResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "AddOrUpdateWiFiNetwork", + "code": 2, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "AddOrUpdateThreadNetwork", + "code": 3, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "RemoveNetwork", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "NetworkConfigResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "ConnectNetwork", + "code": 6, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ConnectNetworkResponse", + "code": 7, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "ReorderNetwork", + "code": 8, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "MaxNetworks", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Networks", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ScanMaxTimeSeconds", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ConnectMaxTimeSeconds", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "InterfaceEnabled", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LastNetworkingStatus", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "NetworkCommissioningStatusEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LastNetworkID", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LastConnectErrorValue", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int32s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "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": "General Diagnostics", + "code": 51, + "mfgCode": null, + "define": "GENERAL_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "TestEventTrigger", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TimeSnapshot", + "code": 1, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TimeSnapshotResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "NetworkInterfaces", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RebootCount", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UpTime", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TotalOperationalHours", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BootReason", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "BootReasonEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveHardwareFaults", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveRadioFaults", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveNetworkFaults", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "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": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "BootReason", + "code": 3, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, + { + "name": "Administrator Commissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "OpenCommissioningWindow", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "OpenBasicCommissioningWindow", + "code": 1, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "RevokeCommissioning", + "code": 2, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "WindowStatus", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "CommissioningWindowStatusEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AdminFabricIndex", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "fabric_idx", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AdminVendorId", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "vendor_id", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Operational Credentials", + "code": 62, + "mfgCode": null, + "define": "OPERATIONAL_CREDENTIALS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "AttestationRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "AttestationResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "CertificateChainRequest", + "code": 2, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "CertificateChainResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "CSRRequest", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "CSRResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "AddNOC", + "code": 6, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "UpdateNOC", + "code": 7, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "NOCResponse", + "code": 8, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "UpdateFabricLabel", + "code": 9, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "RemoveFabric", + "code": 10, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "AddTrustedRootCertificate", + "code": 11, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "NOCs", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Fabrics", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SupportedFabrics", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CommissionedFabrics", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TrustedRootCertificates", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentFabricIndex", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Group Key Management", + "code": 63, + "mfgCode": null, + "define": "GROUP_KEY_MANAGEMENT_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "KeySetWrite", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "KeySetRead", + "code": 1, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "KeySetReadResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "KeySetRemove", + "code": 3, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "KeySetReadAllIndices", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "KeySetReadAllIndicesResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "GroupKeyMap", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "GroupTable", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MaxGroupsPerFabric", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxGroupKeysPerFabric", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Fixed Label", + "code": 64, + "mfgCode": null, + "define": "FIXED_LABEL_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "LabelList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 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": "server", + "enabled": 1, + "attributes": [ + { + "name": "LabelList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + }, + { + "id": 2, + "name": "Anonymous Endpoint Type", + "deviceTypeRef": { + "code": 145, + "profileId": 259, + "label": "MA-thread-border-router", + "name": "MA-thread-border-router" + }, + "deviceTypes": [ + { + "code": 145, + "profileId": 259, + "label": "MA-thread-border-router", + "name": "MA-thread-border-router" + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 145 + ], + "deviceTypeName": "MA-thread-border-router", + "deviceTypeCode": 145, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Thread Network Diagnostics", + "code": 53, + "mfgCode": null, + "define": "THREAD_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "Channel", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "RoutingRole", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "RoutingRoleEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "NetworkName", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PanId", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ExtendedPanId", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeshLocalPrefix", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "NeighborTable", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "RouteTable", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartitionId", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Weighting", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "DataVersion", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "StableDataVersion", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LeaderRouterId", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SecurityPolicy", + "code": 59, + "mfgCode": null, + "side": "server", + "type": "SecurityPolicy", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ChannelPage0Mask", + "code": 60, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "OperationalDatasetComponents", + "code": 61, + "mfgCode": null, + "side": "server", + "type": "OperationalDatasetComponents", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveNetworkFaultsList", + "code": 62, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Thread Border Router Management", + "code": 1106, + "mfgCode": null, + "define": "THREAD_BORDER_ROUTER_MANAGEMENT_CLUSTER", + "side": "server", + "enabled": 1, + "apiMaturity": "provisional", + "commands": [ + { + "name": "GetActiveDatasetRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "GetPendingDatasetRequest", + "code": 1, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "DatasetResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "SetActiveDatasetRequest", + "code": 3, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "SetPendingDatasetRequest", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "BorderRouterName", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BorderAgentID", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ThreadVersion", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "InterfaceEnabled", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveDatasetTimestamp", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PendingDatasetTimestamp", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + } + ], + "endpoints": [ + { + "endpointTypeName": "MA-rootdevice", + "endpointTypeIndex": 0, + "profileId": 259, + "endpointId": 0, + "networkId": 0, + "parentEndpointIdentifier": null + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 1, + "profileId": 259, + "endpointId": 1, + "networkId": 0, + "parentEndpointIdentifier": null + } + ] +} \ No newline at end of file diff --git a/examples/tv-app/android/App/platform-app/build.gradle b/examples/tv-app/android/App/platform-app/build.gradle index 0845105bffccc5..5b4203e9c1509c 100644 --- a/examples/tv-app/android/App/platform-app/build.gradle +++ b/examples/tv-app/android/App/platform-app/build.gradle @@ -72,4 +72,4 @@ dependencies { androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' implementation 'com.google.zxing:core:3.3.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" -} +} \ No newline at end of file diff --git a/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/handlers/ApplicationLauncherManagerImpl.java b/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/handlers/ApplicationLauncherManagerImpl.java new file mode 100644 index 00000000000000..bb1856ec6e14d1 --- /dev/null +++ b/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/handlers/ApplicationLauncherManagerImpl.java @@ -0,0 +1,165 @@ +package com.matter.tv.server.handlers; + +import android.content.Context; +import android.content.pm.PackageManager; +import android.util.Log; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.Observer; +import com.matter.tv.server.tvapp.Application; +import com.matter.tv.server.tvapp.ApplicationLauncherManager; +import com.matter.tv.server.tvapp.LauncherResponse; +import com.matter.tv.server.utils.EndpointsDataStore; +import com.matter.tv.server.utils.InstallationObserver; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public class ApplicationLauncherManagerImpl implements ApplicationLauncherManager { + + private static final String TAG = "ApplicationLauncherService"; + + private volatile boolean registered = false; + private PackageManager packageManager; + private EndpointsDataStore endpointsDataStore; + + /** Hash Map of packageName & Install Status */ + private Map lastReceivedInstallationStatus = + new HashMap<>(); + + private LiveData installStateLiveData; + + public ApplicationLauncherManagerImpl(Context context) { + packageManager = context.getPackageManager(); + endpointsDataStore = EndpointsDataStore.getInstance(context); + registerSelf(context); + } + + private final Observer installStateObserver = + state -> { + lastReceivedInstallationStatus.put(state.getAppPackageName(), state.getStatus()); + switch (state.getStatus()) { + case IN_PROGRESS: + // Installation is in progress + Log.d(TAG, "Installation of " + state.getAppPackageName() + " in progress"); + break; + case SUCCEEDED: + // Installation succeeded + Log.d(TAG, "Installation of " + state.getAppPackageName() + " succeeded"); + break; + case FAILED: + // Installation failed + Log.d(TAG, "Installation of " + state.getAppPackageName() + " failed"); + break; + } + }; + + private void stopObservingInstallations() { + if (installStateLiveData != null) { + Log.d("InstallationObserver", "Stopped Observing"); + installStateLiveData.removeObserver(installStateObserver); + } + } + + public void unregister() { + stopObservingInstallations(); + } + + private void registerSelf(Context context) { + if (registered) { + Log.i(TAG, "Package update receiver for matter already registered"); + return; + } else { + registered = true; + } + Log.i(TAG, "Registered the matter package updates receiver"); + + installStateLiveData = InstallationObserver.installationStates(context); + installStateLiveData.observeForever(installStateObserver); + Log.d(TAG, "Started Observing package installations"); + } + + @Override + public int[] getCatalogList() { + Log.i(TAG, "Get Catalog List"); + return new int[] {123, 456, 89010}; + } + + @Override + public LauncherResponse launchApp(Application app, String data) { + Log.i( + TAG, + "Launch app id:" + app.applicationId + " cid:" + app.catalogVendorId + " data:" + data); + + int status = 0; + String responseData = ""; + + // Installed Apps that have declared CSA product id & vendor id in their manifes + boolean matterEnabledAppdIsInstalled = + endpointsDataStore.getAllPersistedContentApps().containsKey(app.applicationId); + // Installed App + boolean appIsInstalled = + InstallationObserver.getInstalledPackages(packageManager).contains(app.applicationId); + boolean isAppInstalling = + Objects.equals( + lastReceivedInstallationStatus.get(app.applicationId), + InstallationObserver.InstallStatus.IN_PROGRESS); + boolean appInstallFailed = + Objects.equals( + lastReceivedInstallationStatus.get(app.applicationId), + InstallationObserver.InstallStatus.FAILED); + + // This use-case can happen if app is installed + // but it does not support Matter + if (!matterEnabledAppdIsInstalled && appIsInstalled) { + Log.i( + TAG, + "Matter enabled app is not installed, but app is installed. Launching app's install page"); + status = LauncherResponse.STATUS_PENDING_USER_APPROVAL; + responseData = "App is installed, try updating"; + + // + // Add code to launch App Install Page + // + + } else if (!matterEnabledAppdIsInstalled && !appIsInstalled) { + Log.i( + TAG, + "Matter enabled app is not installed and app is not installed. Launching app's install page"); + if (isAppInstalling) { + Log.i(TAG, "App is installing"); + status = LauncherResponse.STATUS_INSTALLING; + } else { + status = LauncherResponse.STATUS_PENDING_USER_APPROVAL; + if (appInstallFailed) { + responseData = "App install failed. Try again"; + } + } + + // + // Add code to launch App Install Page + // + + } else if (matterEnabledAppdIsInstalled && appIsInstalled) { + Log.i(TAG, "Launching the app"); + status = LauncherResponse.STATUS_SUCCESS; + + // + // Add code to launch an app + // + } + + return new LauncherResponse(status, responseData); + } + + @Override + public LauncherResponse stopApp(Application app) { + Log.i(TAG, "Stop app id:" + app.applicationId + " cid:" + app.catalogVendorId); + return new LauncherResponse(LauncherResponse.STATUS_SUCCESS, ""); + } + + @Override + public LauncherResponse hideApp(Application app) { + Log.i(TAG, "Hide app id:" + app.applicationId + " cid:" + app.catalogVendorId); + return new LauncherResponse(LauncherResponse.STATUS_SUCCESS, ""); + } +} 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 c1d479e6d147e1..683fb226c9e441 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 @@ -30,6 +30,8 @@ import chip.platform.PreferencesConfigurationManager; import chip.platform.PreferencesKeyValueStoreManager; import com.matter.tv.server.MatterCommissioningPrompter; +import com.matter.tv.server.handlers.ApplicationLauncherManagerImpl; +import com.matter.tv.server.tvapp.ApplicationLauncherManager; import com.matter.tv.server.tvapp.ChannelManagerStub; import com.matter.tv.server.tvapp.Clusters; import com.matter.tv.server.tvapp.ContentLaunchManagerStub; @@ -55,6 +57,8 @@ public class MatterServant { private boolean mIsOn = true; private int mOnOffEndpoint; private int mLevelEndpoint; + private MatterCommissioningPrompter matterCommissioningPrompter; + private ApplicationLauncherManager applicationLauncherManager; private MatterServant() {} @@ -72,17 +76,25 @@ public void init(@NonNull Context context) { this.context = context; + this.applicationLauncherManager = new ApplicationLauncherManagerImpl(context); + // The order is important, must // first new TvApp to load dynamic library // then chipPlatform to prepare platform // then TvApp.preServerInit to initialize any server configuration // then start ChipAppServer // then TvApp.postServerInit to init app platform + // + // TODO: Move all of the bellow KeypadInputManager...LevelManagerStub to + // PlatformAppCommandDelegate + // There is no need for this complicated logic mTvApp = new TvApp( (app, clusterId, endpoint) -> { if (clusterId == Clusters.ClusterId_KeypadInput) { app.setKeypadInputManager(endpoint, new KeypadInputManagerStub(endpoint)); + } else if (clusterId == Clusters.ClusterId_ApplicationLauncher) { + app.setApplicationLauncherManager(endpoint, applicationLauncherManager); } else if (clusterId == Clusters.ClusterId_WakeOnLan) { app.setWakeOnLanManager(endpoint, new WakeOnLanManagerStub(endpoint)); } else if (clusterId == Clusters.ClusterId_MediaInput) { diff --git a/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/utils/EndpointsDataStore.java b/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/utils/EndpointsDataStore.java index 227ea9326be538..7b3822bb1b59a4 100644 --- a/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/utils/EndpointsDataStore.java +++ b/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/utils/EndpointsDataStore.java @@ -4,6 +4,7 @@ import android.content.SharedPreferences; import android.util.JsonReader; import android.util.JsonWriter; +import android.util.Log; import com.matter.tv.app.api.SupportedCluster; import com.matter.tv.server.model.ContentApp; import java.io.IOException; @@ -59,6 +60,7 @@ public Map getAllPersistedContentApps() { } public void persistContentAppEndpoint(ContentApp app) { + Log.i(EndpointsDataStore.class.toString(), "Persist Content App Endpoint " + app.getAppName()); persistedContentApps.put(app.getAppName(), app); discoveredEndpoints.edit().putString(app.getAppName(), serializeContentApp(app)).apply(); } diff --git a/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/utils/InstallationObserver.java b/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/utils/InstallationObserver.java new file mode 100644 index 00000000000000..c47359272a1359 --- /dev/null +++ b/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/utils/InstallationObserver.java @@ -0,0 +1,137 @@ +package com.matter.tv.server.utils; + +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageInstaller; +import android.content.pm.PackageManager; +import android.util.Log; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +public class InstallationObserver { + public enum InstallStatus { + IN_PROGRESS, + SUCCEEDED, + FAILED + } + + public static class InstallState { + private final String appPackageName; + private final InstallStatus status; + + public InstallState(String appPackageName, InstallStatus status) { + this.appPackageName = appPackageName; + this.status = status; + } + + public String getAppPackageName() { + return appPackageName; + } + + public InstallStatus getStatus() { + return status; + } + + public String getPackageShortName() { + return appPackageName.substring(appPackageName.lastIndexOf(".") + 1); + } + + public String getPackageTitle() { + String shortName = getPackageShortName(); + return shortName.substring(0, 1).toUpperCase(Locale.getDefault()) + shortName.substring(1); + } + } + + private static InstallState stateFromId(PackageInstaller installer, int sessionId) { + PackageInstaller.SessionInfo info = installer.getSessionInfo(sessionId); + if (info == null || info.getAppPackageName() == null) { + return null; + } + return new InstallState(info.getAppPackageName(), InstallStatus.IN_PROGRESS); + } + + public static Set getInstalledPackages(PackageManager packageManager) { + List packageInfoList = packageManager.getInstalledPackages(0); + Set setOfInstalledApps = new HashSet<>(); + for (PackageInfo info : packageInfoList) { + setOfInstalledApps.add(info.packageName); + } + return setOfInstalledApps; + } + + public static LiveData installationStates(Context context) { + MutableLiveData liveData = new MutableLiveData<>(); + PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller(); + Map inProgressSessions = new HashMap<>(); + + PackageInstaller.SessionCallback callback = + new PackageInstaller.SessionCallback() { + @Override + public void onCreated(int sessionId) { + Log.d(TAG, "onCreated "); + InstallState state = stateFromId(packageInstaller, sessionId); + if (state != null) { + inProgressSessions.put(sessionId, state); + liveData.postValue(state); + } + } + + @Override + public void onBadgingChanged(int sessionId) {} + + @Override + public void onActiveChanged(int sessionId, boolean active) { + Log.d(TAG, "onActiveChanged"); + InstallState state = stateFromId(packageInstaller, sessionId); + if (state != null) { + inProgressSessions.put(sessionId, state); + liveData.postValue(state); + } + } + + @Override + public void onProgressChanged(int sessionId, float progress) { + Log.d(TAG, "onProgressChanged:" + progress); + InstallState state = stateFromId(packageInstaller, sessionId); + if (state != null) { + inProgressSessions.put(sessionId, state); + liveData.postValue(state); + } + } + + @Override + public void onFinished(int sessionId, boolean success) { + Log.d(TAG, "onFinished " + sessionId + " " + success); + InstallState current = inProgressSessions.get(sessionId); + if (current != null) { + InstallState newState = + new InstallState( + current.getAppPackageName(), + success ? InstallStatus.SUCCEEDED : InstallStatus.FAILED); + liveData.postValue(newState); + inProgressSessions.remove(sessionId); + } + } + }; + + packageInstaller.registerSessionCallback(callback); + + for (PackageInstaller.SessionInfo info : packageInstaller.getMySessions()) { + if (info.isActive() && info.getAppPackageName() != null) { + InstallState state = new InstallState(info.getAppPackageName(), InstallStatus.IN_PROGRESS); + inProgressSessions.put(info.getSessionId(), state); + liveData.postValue(state); + } + } + + return liveData; + } + + private static final String TAG = "InstallationObserver"; +} diff --git a/examples/tv-app/android/BUILD.gn b/examples/tv-app/android/BUILD.gn index 38c75d9273c243..f08f16f363e516 100644 --- a/examples/tv-app/android/BUILD.gn +++ b/examples/tv-app/android/BUILD.gn @@ -28,8 +28,6 @@ shared_library("jni") { "include/account-login/AccountLoginManager.h", "include/application-basic/ApplicationBasicManager.cpp", "include/application-basic/ApplicationBasicManager.h", - "include/application-launcher/ApplicationLauncherManager.cpp", - "include/application-launcher/ApplicationLauncherManager.h", "include/audio-output/AudioOutputManager.cpp", "include/audio-output/AudioOutputManager.h", "include/cluster-init.cpp", @@ -80,6 +78,8 @@ shared_library("jni") { "java/TVApp-JNI.cpp", "java/WakeOnLanManager.cpp", "java/WakeOnLanManager.h", + "java/application-launcher/ApplicationLauncherManager.cpp", + "java/application-launcher/ApplicationLauncherManager.h", ] deps = [ @@ -115,6 +115,8 @@ android_library("java") { sources = [ "java/src/com/matter/tv/server/tvapp/AppPlatform.java", "java/src/com/matter/tv/server/tvapp/AppPlatformShellCommands.java", + "java/src/com/matter/tv/server/tvapp/Application.java", + "java/src/com/matter/tv/server/tvapp/ApplicationLauncherManager.java", "java/src/com/matter/tv/server/tvapp/ChannelInfo.java", "java/src/com/matter/tv/server/tvapp/ChannelLineupInfo.java", "java/src/com/matter/tv/server/tvapp/ChannelManager.java", @@ -136,6 +138,7 @@ android_library("java") { "java/src/com/matter/tv/server/tvapp/DeviceEventProvider.java", "java/src/com/matter/tv/server/tvapp/KeypadInputManager.java", "java/src/com/matter/tv/server/tvapp/KeypadInputManagerStub.java", + "java/src/com/matter/tv/server/tvapp/LauncherResponse.java", "java/src/com/matter/tv/server/tvapp/LevelManager.java", "java/src/com/matter/tv/server/tvapp/LevelManagerStub.java", "java/src/com/matter/tv/server/tvapp/LowPowerManager.java", diff --git a/examples/tv-app/android/include/application-launcher/ApplicationLauncherManager.cpp b/examples/tv-app/android/include/application-launcher/ApplicationLauncherManager.cpp deleted file mode 100644 index c915856f48fd4d..00000000000000 --- a/examples/tv-app/android/include/application-launcher/ApplicationLauncherManager.cpp +++ /dev/null @@ -1,76 +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. - */ - -#include "ApplicationLauncherManager.h" - -using namespace std; -using namespace chip::app; -using namespace chip::app::Clusters; -using namespace chip::app::Clusters::ApplicationLauncher; -using namespace chip::Uint8; - -CHIP_ERROR ApplicationLauncherManager::HandleGetCatalogList(AttributeValueEncoder & aEncoder) -{ - std::list catalogList = { 123, 456 }; - return aEncoder.EncodeList([catalogList](const auto & encoder) -> CHIP_ERROR { - for (const auto & catalog : catalogList) - { - ReturnErrorOnFailure(encoder.Encode(catalog)); - } - return CHIP_NO_ERROR; - }); -} - -void ApplicationLauncherManager::HandleLaunchApp(CommandResponseHelper & helper, const ByteSpan & data, - const ApplicationType & application) -{ - ChipLogProgress(Zcl, "ApplicationLauncherManager::HandleLaunchApp"); - - // TODO: Insert code here - LauncherResponseType response; - const char * buf = "data"; - response.data.SetValue(ByteSpan(from_const_char(buf), strlen(buf))); - response.status = StatusEnum::kSuccess; - helper.Success(response); -} - -void ApplicationLauncherManager::HandleStopApp(CommandResponseHelper & helper, - const ApplicationType & application) -{ - ChipLogProgress(Zcl, "ApplicationLauncherManager::HandleStopApp"); - - // TODO: Insert code here - LauncherResponseType response; - const char * buf = "data"; - response.data.SetValue(ByteSpan(from_const_char(buf), strlen(buf))); - response.status = StatusEnum::kSuccess; - helper.Success(response); -} - -void ApplicationLauncherManager::HandleHideApp(CommandResponseHelper & helper, - const ApplicationType & application) -{ - ChipLogProgress(Zcl, "ApplicationLauncherManager::HandleHideApp"); - - // TODO: Insert code here - LauncherResponseType response; - const char * buf = "data"; - response.data.SetValue(ByteSpan(from_const_char(buf), strlen(buf))); - response.status = StatusEnum::kSuccess; - helper.Success(response); -} diff --git a/examples/tv-app/android/include/cluster-init.cpp b/examples/tv-app/android/include/cluster-init.cpp index e6f0cd8b481f57..7481625b664a21 100644 --- a/examples/tv-app/android/include/cluster-init.cpp +++ b/examples/tv-app/android/include/cluster-init.cpp @@ -17,7 +17,6 @@ */ #include "application-basic/ApplicationBasicManager.h" -#include "application-launcher/ApplicationLauncherManager.h" #include "audio-output/AudioOutputManager.h" #include "target-navigator/TargetNavigatorManager.h" @@ -30,7 +29,6 @@ using namespace chip; namespace { static ApplicationBasicManager applicationBasicManager; -static ApplicationLauncherManager applicationLauncherManager; static AudioOutputManager audioOutputManager; static TargetNavigatorManager targetNavigatorManager; } // namespace @@ -50,21 +48,6 @@ void emberAfApplicationBasicClusterInitCallback(chip::EndpointId endpoint) chip::app::Clusters::ApplicationBasic::SetDefaultDelegate(endpoint, &applicationBasicManager); } -/** @brief Application Launcher Cluster Init - * - * This function is called when a specific cluster is initialized. It gives the - * application an opportunity to take care of cluster initialization procedures. - * It is called exactly once for each endpoint where cluster is present. - * - * @param endpoint Ver.: always - * - */ -void emberAfApplicationLauncherClusterInitCallback(EndpointId endpoint) -{ - ChipLogProgress(Zcl, "TV Android App: ApplicationLauncher::SetDefaultDelegate"); - chip::app::Clusters::ApplicationLauncher::SetDefaultDelegate(endpoint, &applicationLauncherManager); -} - /** @brief Audio Output Cluster Init * * This function is called when a specific cluster is initialized. It gives the diff --git a/examples/tv-app/android/java/AppImpl.cpp b/examples/tv-app/android/java/AppImpl.cpp index d04964ee5eb747..d7da8ab6661a46 100644 --- a/examples/tv-app/android/java/AppImpl.cpp +++ b/examples/tv-app/android/java/AppImpl.cpp @@ -503,6 +503,18 @@ EndpointId ContentAppFactoryImpl::RemoveContentApp(EndpointId epId) return kInvalidEndpointId; } +void ContentAppFactoryImpl::LogInstalledApps() +{ + for (auto & contentApp : mContentApps) + { + ChipLogProgress(DeviceLayer, "Content app vid=%d pid=%d id=%s is on ep=%d", + contentApp->GetApplicationBasicDelegate()->HandleGetVendorId(), + contentApp->GetApplicationBasicDelegate()->HandleGetProductId(), + contentApp->GetApplicationBasicDelegate()->GetCatalogVendorApp()->GetApplicationId(), + contentApp->GetEndpointId()); + } +} + void ContentAppFactoryImpl::AddAdminVendorId(uint16_t vendorId) { mAdminVendorIds.push_back(vendorId); @@ -572,7 +584,7 @@ CHIP_ERROR InitVideoPlayerPlatform(jobject contentAppEndpointManager) { ContentAppCommandDelegate * delegate = new ContentAppCommandDelegate(contentAppEndpointManager, contentAppClusters[i].clusterId); - chip::app::CommandHandlerInterfaceRegistry::RegisterCommandHandler(delegate); + app::CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(delegate); ChipLogProgress(AppServer, "Registered command handler delegate for cluster %d", contentAppClusters[i].clusterId); } diff --git a/examples/tv-app/android/java/AppImpl.h b/examples/tv-app/android/java/AppImpl.h index b10c96608c8fc1..a86a11c4386626 100644 --- a/examples/tv-app/android/java/AppImpl.h +++ b/examples/tv-app/android/java/AppImpl.h @@ -35,7 +35,6 @@ #include "../include/account-login/AccountLoginManager.h" #include "../include/application-basic/ApplicationBasicManager.h" -#include "../include/application-launcher/ApplicationLauncherManager.h" #include "../include/content-control/ContentController.h" #include "../include/content-launcher/AppContentLauncherManager.h" #include "../include/media-playback/AppMediaPlaybackManager.h" @@ -45,6 +44,7 @@ #include "ContentAppAttributeDelegate.h" #include "ContentAppCommandDelegate.h" #include "KeypadInputManager.h" +#include "application-launcher/ApplicationLauncherManager.h" #include #include #include @@ -198,6 +198,8 @@ class DLL_EXPORT ContentAppFactoryImpl : public ContentAppFactory void setContentAppCommandDelegate(ContentAppCommandDelegate * commandDelegate); + void LogInstalledApps(); + protected: // TODO: Update to use unique_ptr instead of raw pointers std::vector mContentApps; diff --git a/examples/tv-app/android/java/AppPlatformShellCommands-JNI.cpp b/examples/tv-app/android/java/AppPlatformShellCommands-JNI.cpp index f15ef7bebae54c..cb491fcae91163 100644 --- a/examples/tv-app/android/java/AppPlatformShellCommands-JNI.cpp +++ b/examples/tv-app/android/java/AppPlatformShellCommands-JNI.cpp @@ -269,6 +269,17 @@ char * AppPlatformHandler(int argc, char ** argv) } return response; } + else if (strcmp(argv[0], "print-apps") == 0) + { + ContentAppFactoryImpl * factory = GetContentAppFactoryImpl(); + factory->LogInstalledApps(); + + ChipLogProgress(DeviceLayer, "logged installed apps"); + + strcpy(response, "logged installed apps"); + + return response; + } else if (strcmp(argv[0], "remove-app-access") == 0) { Access::GetAccessControl().DeleteAllEntriesForFabric(GetDeviceCommissioner()->GetFabricIndex()); diff --git a/examples/tv-app/android/java/ContentAppCommandDelegate.cpp b/examples/tv-app/android/java/ContentAppCommandDelegate.cpp index 8d459588a7a8d6..02b4a7e806fefb 100644 --- a/examples/tv-app/android/java/ContentAppCommandDelegate.cpp +++ b/examples/tv-app/android/java/ContentAppCommandDelegate.cpp @@ -49,6 +49,37 @@ using Status = chip::Protocols::InteractionModel::Status; const std::string FAILURE_KEY = "PlatformError"; const std::string FAILURE_STATUS_KEY = "Status"; +bool isValidJson(const char * response) +{ + Json::Reader reader; + + Json::CharReaderBuilder readerBuilder; + std::string errors; + + Json::Value value; + std::unique_ptr testReader(readerBuilder.newCharReader()); + + if (!testReader->parse(response, response + std::strlen(response), &value, &errors)) + { + ChipLogError(Zcl, "Failed to parse JSON: %s\n", errors.c_str()); + return false; + } + + // Validate and access JSON data safely + if (!value.isObject()) + { + ChipLogError(Zcl, "Invalid JSON structure: not an object"); + return false; + } + + if (!reader.parse(response, value)) + { + return false; + } + + return true; +} + void ContentAppCommandDelegate::InvokeCommand(CommandHandlerInterface::HandlerContext & handlerContext) { if (handlerContext.mRequestPath.mEndpointId >= FIXED_ENDPOINT_COUNT) @@ -94,7 +125,15 @@ void ContentAppCommandDelegate::InvokeCommand(CommandHandlerInterface::HandlerCo { JniUtfString respStr(env, resp); ChipLogProgress(Zcl, "ContentAppCommandDelegate::InvokeCommand got response %s", respStr.c_str()); - FormatResponseData(handlerContext, respStr.c_str()); + if (isValidJson(respStr.c_str())) + { + FormatResponseData(handlerContext, respStr.c_str()); + } + else + { + // return dummy value in case JSON is invalid + FormatResponseData(handlerContext, "{\"value\":{}}"); + } } env->DeleteLocalRef(resp); } @@ -141,7 +180,6 @@ Status ContentAppCommandDelegate::InvokeCommand(EndpointId epId, ClusterId clust if (!testReader->parse(respStr.c_str(), respStr.c_str() + std::strlen(respStr.c_str()), &value, &errors)) { ChipLogError(Zcl, "Failed to parse JSON: %s\n", errors.c_str()); - env->DeleteLocalRef(resp); return chip::Protocols::InteractionModel::Status::Failure; } @@ -149,14 +187,12 @@ Status ContentAppCommandDelegate::InvokeCommand(EndpointId epId, ClusterId clust if (!value.isObject()) { ChipLogError(Zcl, "Invalid JSON structure: not an object"); - env->DeleteLocalRef(resp); return chip::Protocols::InteractionModel::Status::Failure; } Json::Reader reader; if (!reader.parse(respStr.c_str(), value)) { - env->DeleteLocalRef(resp); return chip::Protocols::InteractionModel::Status::Failure; } } @@ -185,31 +221,7 @@ Status ContentAppCommandDelegate::InvokeCommand(EndpointId epId, ClusterId clust void ContentAppCommandDelegate::FormatResponseData(CommandHandlerInterface::HandlerContext & handlerContext, const char * response) { handlerContext.SetCommandHandled(); - Json::Reader reader; - - Json::CharReaderBuilder readerBuilder; - std::string errors; - Json::Value value; - std::unique_ptr testReader(readerBuilder.newCharReader()); - - if (!testReader->parse(response, response + std::strlen(response), &value, &errors)) - { - ChipLogError(Zcl, "Failed to parse JSON: %s\n", errors.c_str()); - return; - } - - // Validate and access JSON data safely - if (!value.isObject()) - { - ChipLogError(Zcl, "Invalid JSON structure: not an object"); - return; - } - - if (!reader.parse(response, value)) - { - return; - } // handle errors from platform-app if (!value[FAILURE_KEY].empty()) diff --git a/examples/tv-app/android/java/TVApp-JNI.cpp b/examples/tv-app/android/java/TVApp-JNI.cpp index 65a0a4409e9b8f..0fe1bdef939ca8 100644 --- a/examples/tv-app/android/java/TVApp-JNI.cpp +++ b/examples/tv-app/android/java/TVApp-JNI.cpp @@ -31,6 +31,7 @@ #include "MyUserPrompter-JNI.h" #include "OnOffManager.h" #include "WakeOnLanManager.h" +#include "application-launcher/ApplicationLauncherManager.h" #include "credentials/DeviceAttestationCredsProvider.h" #include #include @@ -139,6 +140,11 @@ JNI_METHOD(void, setMediaPlaybackManager)(JNIEnv *, jobject, jint endpoint, jobj MediaPlaybackManager::NewManager(endpoint, manager); } +JNI_METHOD(void, setApplicationLauncherManager)(JNIEnv *, jobject, jint endpoint, jobject manager) +{ + ApplicationLauncherManager::NewManager(endpoint, manager); +} + JNI_METHOD(void, setMessagesManager)(JNIEnv *, jobject, jint endpoint, jobject manager) { MessagesManager::NewManager(endpoint, manager); diff --git a/examples/tv-app/android/java/application-launcher/ApplicationLauncherManager.cpp b/examples/tv-app/android/java/application-launcher/ApplicationLauncherManager.cpp new file mode 100644 index 00000000000000..8ee91292a5e76a --- /dev/null +++ b/examples/tv-app/android/java/application-launcher/ApplicationLauncherManager.cpp @@ -0,0 +1,345 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ApplicationLauncherManager.h" +#include "../TvApp-JNI.h" +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::ApplicationLauncher; +using namespace chip::Uint8; + +void emberAfApplicationLauncherClusterInitCallback(chip::EndpointId endpoint) +{ + ChipLogProgress(Zcl, "TV Android App: ApplicationLauncher::PostClusterInit"); + if (endpoint > kLocalVideoPlayerEndpointId) + { + ChipLogProgress(Zcl, "TV Android App: ignore setting the delegate for endpoints larger than 1"); + return; + } + TvAppJNIMgr().PostClusterInit(chip::app::Clusters::ApplicationLauncher::Id, endpoint); +} + +void ApplicationLauncherManager::NewManager(jint endpoint, jobject manager) +{ + if (endpoint > kLocalVideoPlayerEndpointId) + { + ChipLogProgress(Zcl, "TV Android App: ignore setting the delegate for endpoints larger than 1"); + return; + } + ChipLogProgress(Zcl, "TV Android App: ApplicationLauncher::SetDefaultDelegate for endpoint: %d", endpoint); + ApplicationLauncherManager * mgr = new ApplicationLauncherManager(); + mgr->InitializeWithObjects(manager); + chip::app::Clusters::ApplicationLauncher::SetDefaultDelegate(static_cast(endpoint), mgr); +} + +CHIP_ERROR ApplicationLauncherManager::HandleGetCatalogList(AttributeValueEncoder & aEncoder) +{ + chip::DeviceLayer::StackUnlock unlock; + CHIP_ERROR err = CHIP_NO_ERROR; + JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread(); + VerifyOrReturnError(env != nullptr, CHIP_JNI_ERROR_NO_ENV, ChipLogError(Zcl, "Could not get JNIEnv for current thread")); + chip::JniLocalReferenceScope scope(env); + + ChipLogProgress(Zcl, "Received ApplicationLauncherManager::GetCatalogList"); + VerifyOrExit(mApplicationLauncherManagerObject.HasValidObjectRef(), err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mGetCatalogListMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + + env->ExceptionClear(); + + return aEncoder.EncodeList([this, env](const auto & encoder) -> CHIP_ERROR { + jintArray jCatalogList = + (jintArray) env->CallObjectMethod(mApplicationLauncherManagerObject.ObjectRef(), mGetCatalogListMethod); + if (env->ExceptionCheck()) + { + ChipLogError(Zcl, "Java exception in ApplicationLauncherManager::GetCatalogList"); + env->ExceptionDescribe(); + env->ExceptionClear(); + return CHIP_ERROR_INCORRECT_STATE; + } + + jint size = env->GetArrayLength(jCatalogList); + jint * elements = env->GetIntArrayElements(jCatalogList, 0); + for (int i = 0; i < size; i++) + { + jint jCatalogVendorId = elements[i]; + ReturnErrorOnFailure(encoder.Encode(static_cast(jCatalogVendorId))); + } + + return CHIP_NO_ERROR; + }); + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "ApplicationLauncherManager::GetCatalogList status error: %s", err.AsString()); + } + + return err; +} + +void ApplicationLauncherManager::HandleLaunchApp(CommandResponseHelper & helper, const ByteSpan & data, + const ApplicationType & application) +{ + chip::DeviceLayer::StackUnlock unlock; + LauncherResponseType response; + CHIP_ERROR err = CHIP_NO_ERROR; + JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread(); + VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNIEnv for current thread")); + chip::JniLocalReferenceScope scope(env); + + ChipLogProgress(Zcl, "Received ApplicationLauncherManager::LaunchApp"); + VerifyOrExit(mApplicationLauncherManagerObject.HasValidObjectRef(), err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mLaunchAppMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + + env->ExceptionClear(); + + { + // UtfString accepts const char * data + chip::UtfString jByteData(env, reinterpret_cast(data.data())); + + chip::UtfString jappId(env, application.applicationID); + + // Create an instance of Application + jobject appObject = env->NewObject(mApplicationClass, mCreateApplicationMethod, + static_cast(application.catalogVendorID), jappId.jniValue()); + VerifyOrReturn(appObject != nullptr, ChipLogError(Zcl, "Failed to create Application object")); + + jobject resp = + env->CallObjectMethod(mApplicationLauncherManagerObject.ObjectRef(), mLaunchAppMethod, appObject, jByteData.jniValue()); + if (env->ExceptionCheck()) + { + ChipLogError(Zcl, "Java exception in ApplicationLauncherManager::LaunchApp"); + env->ExceptionDescribe(); + env->ExceptionClear(); + err = CHIP_ERROR_INCORRECT_STATE; + goto exit; + } + + VerifyOrExit(resp != nullptr, err = CHIP_JNI_ERROR_NULL_OBJECT); + jclass respCls = env->GetObjectClass(resp); + jfieldID statusFid = env->GetFieldID(respCls, "status", "I"); + VerifyOrExit(statusFid != nullptr, err = CHIP_JNI_ERROR_FIELD_NOT_FOUND); + jint status = env->GetIntField(resp, statusFid); + + jfieldID dataFid = env->GetFieldID(respCls, "data", "Ljava/lang/String;"); + VerifyOrExit(dataFid != nullptr, err = CHIP_JNI_ERROR_FIELD_NOT_FOUND); + jstring jdataStr = (jstring) env->GetObjectField(resp, dataFid); + chip::JniUtfString dataStr(env, jdataStr); + + response.status = static_cast(status); + response.data = chip::Optional(dataStr.byteSpan()); + + err = helper.Success(response); + } + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "ApplicationLauncherManager::LaunchApp status error: %s", err.AsString()); + } +} + +void ApplicationLauncherManager::HandleStopApp(CommandResponseHelper & helper, + const ApplicationType & application) +{ + chip::DeviceLayer::StackUnlock unlock; + LauncherResponseType response; + CHIP_ERROR err = CHIP_NO_ERROR; + JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread(); + VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNIEnv for current thread")); + chip::JniLocalReferenceScope scope(env); + + ChipLogProgress(Zcl, "Received ApplicationLauncherManager::StopApp"); + VerifyOrExit(mApplicationLauncherManagerObject.HasValidObjectRef(), err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mStopAppMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + + env->ExceptionClear(); + + { + chip::UtfString jappId(env, application.applicationID); + + // Create an instance of Application + jobject appObject = env->NewObject(mApplicationClass, mCreateApplicationMethod, + static_cast(application.catalogVendorID), jappId.jniValue()); + VerifyOrReturn(appObject != nullptr, ChipLogError(Zcl, "Failed to create Application object")); + + jobject resp = env->CallObjectMethod(mApplicationLauncherManagerObject.ObjectRef(), mStopAppMethod, appObject); + if (env->ExceptionCheck()) + { + ChipLogError(Zcl, "Java exception in ApplicationLauncherManager::StopApp"); + env->ExceptionDescribe(); + env->ExceptionClear(); + err = CHIP_ERROR_INCORRECT_STATE; + goto exit; + } + + VerifyOrExit(resp != nullptr, err = CHIP_JNI_ERROR_NULL_OBJECT); + jclass respCls = env->GetObjectClass(resp); + jfieldID statusFid = env->GetFieldID(respCls, "status", "I"); + VerifyOrExit(statusFid != nullptr, err = CHIP_JNI_ERROR_FIELD_NOT_FOUND); + jint status = env->GetIntField(resp, statusFid); + + jfieldID dataFid = env->GetFieldID(respCls, "data", "Ljava/lang/String;"); + VerifyOrExit(dataFid != nullptr, err = CHIP_JNI_ERROR_FIELD_NOT_FOUND); + jstring jdataStr = (jstring) env->GetObjectField(resp, dataFid); + chip::JniUtfString dataStr(env, jdataStr); + + response.status = static_cast(status); + response.data = chip::Optional(dataStr.byteSpan()); + + err = helper.Success(response); + } + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "ApplicationLauncherManager::StopApp status error: %s", err.AsString()); + } +} + +void ApplicationLauncherManager::HandleHideApp(CommandResponseHelper & helper, + const ApplicationType & application) +{ + chip::DeviceLayer::StackUnlock unlock; + LauncherResponseType response; + CHIP_ERROR err = CHIP_NO_ERROR; + JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread(); + VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNIEnv for current thread")); + chip::JniLocalReferenceScope scope(env); + + ChipLogProgress(Zcl, "Received ApplicationLauncherManager::HideApp"); + VerifyOrExit(mApplicationLauncherManagerObject.HasValidObjectRef(), err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mHideAppMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + + env->ExceptionClear(); + + { + chip::UtfString jappId(env, application.applicationID); + + // Create an instance of Application + jobject appObject = env->NewObject(mApplicationClass, mCreateApplicationMethod, + static_cast(application.catalogVendorID), jappId.jniValue()); + VerifyOrReturn(appObject != nullptr, ChipLogError(Zcl, "Failed to create Application object")); + + jobject resp = env->CallObjectMethod(mApplicationLauncherManagerObject.ObjectRef(), mHideAppMethod, appObject); + if (env->ExceptionCheck()) + { + ChipLogError(Zcl, "Java exception in ApplicationLauncherManager::HideApp"); + env->ExceptionDescribe(); + env->ExceptionClear(); + err = CHIP_ERROR_INCORRECT_STATE; + goto exit; + } + + VerifyOrExit(resp != nullptr, err = CHIP_JNI_ERROR_NULL_OBJECT); + jclass respCls = env->GetObjectClass(resp); + jfieldID statusFid = env->GetFieldID(respCls, "status", "I"); + VerifyOrExit(statusFid != nullptr, err = CHIP_JNI_ERROR_FIELD_NOT_FOUND); + jint status = env->GetIntField(resp, statusFid); + + jfieldID dataFid = env->GetFieldID(respCls, "data", "Ljava/lang/String;"); + VerifyOrExit(dataFid != nullptr, err = CHIP_JNI_ERROR_FIELD_NOT_FOUND); + jstring jdataStr = (jstring) env->GetObjectField(resp, dataFid); + chip::JniUtfString dataStr(env, jdataStr); + + response.status = static_cast(status); + response.data = chip::Optional(dataStr.byteSpan()); + + err = helper.Success(response); + } + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "ApplicationLauncherManager::HideApp status error: %s", err.AsString()); + } +} + +void ApplicationLauncherManager::InitializeWithObjects(jobject managerObject) +{ + JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread(); + VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Failed to GetEnvForCurrentThread for ApplicationLauncherManager")); + + VerifyOrReturn(mApplicationLauncherManagerObject.Init(managerObject) == CHIP_NO_ERROR, + ChipLogError(Zcl, "Failed to init mApplicationLauncherManagerObject")); + + jclass applicationLauncherClass = env->GetObjectClass(managerObject); + VerifyOrReturn(applicationLauncherClass != nullptr, ChipLogError(Zcl, "Failed to get ApplicationLauncherManager Java class")); + + mGetCatalogListMethod = env->GetMethodID(applicationLauncherClass, "getCatalogList", "()[I"); + if (mGetCatalogListMethod == nullptr) + { + ChipLogError(Zcl, "Failed to access ApplicationLauncherManager 'getCatalogList' method"); + env->ExceptionClear(); + } + + mLaunchAppMethod = env->GetMethodID(applicationLauncherClass, "launchApp", + "(Lcom/matter/tv/server/tvapp/" + "Application;Ljava/lang/String;)Lcom/matter/tv/server/tvapp/LauncherResponse;"); + if (mLaunchAppMethod == nullptr) + { + ChipLogError(Zcl, "Failed to access ApplicationLauncherManager 'launchApp' method"); + env->ExceptionClear(); + } + + mStopAppMethod = env->GetMethodID(applicationLauncherClass, "stopApp", + "(Lcom/matter/tv/server/tvapp/" + "Application;)Lcom/matter/tv/server/tvapp/LauncherResponse;"); + if (mStopAppMethod == nullptr) + { + ChipLogError(Zcl, "Failed to access ApplicationLauncherManager 'stopApp' method"); + env->ExceptionClear(); + } + + mHideAppMethod = env->GetMethodID(applicationLauncherClass, "hideApp", + "(Lcom/matter/tv/server/tvapp/" + "Application;)Lcom/matter/tv/server/tvapp/LauncherResponse;"); + if (mHideAppMethod == nullptr) + { + ChipLogError(Zcl, "Failed to access ApplicationLauncherManager 'hideApp' method"); + env->ExceptionClear(); + } + + // Find the Application class + jclass jc = env->FindClass("com/matter/tv/server/tvapp/Application"); + // convert it to a global reference, otherwise code will crash + mApplicationClass = static_cast(env->NewGlobalRef(jc)); + if (mApplicationClass == nullptr) + { + ChipLogError(Zcl, "Failed to find Application Java class"); + env->ExceptionClear(); + } + + // Get the constructor method ID + mCreateApplicationMethod = env->GetMethodID(mApplicationClass, "", "(ILjava/lang/String;)V"); + if (mCreateApplicationMethod == nullptr) + { + ChipLogError(Zcl, "Failed to find constructor of Application Java class"); + env->ExceptionClear(); + } +} diff --git a/examples/tv-app/android/include/application-launcher/ApplicationLauncherManager.h b/examples/tv-app/android/java/application-launcher/ApplicationLauncherManager.h similarity index 74% rename from examples/tv-app/android/include/application-launcher/ApplicationLauncherManager.h rename to examples/tv-app/android/java/application-launcher/ApplicationLauncherManager.h index ffdd89ca8731e9..fd0f40d84b5b60 100644 --- a/examples/tv-app/android/include/application-launcher/ApplicationLauncherManager.h +++ b/examples/tv-app/android/java/application-launcher/ApplicationLauncherManager.h @@ -19,7 +19,9 @@ #pragma once #include -#include + +#include +#include using chip::ByteSpan; using chip::app::AttributeValueEncoder; @@ -28,11 +30,13 @@ using ApplicationLauncherDelegate = chip::app::Clusters::ApplicationLauncher::De using ApplicationType = chip::app::Clusters::ApplicationLauncher::Structs::ApplicationStruct::Type; using LauncherResponseType = chip::app::Clusters::ApplicationLauncher::Commands::LauncherResponse::Type; +inline constexpr chip::EndpointId kLocalVideoPlayerEndpointId = 1; + class ApplicationLauncherManager : public ApplicationLauncherDelegate { public: - ApplicationLauncherManager() : ApplicationLauncherDelegate(){}; - ApplicationLauncherManager(bool featureMapContentPlatform) : ApplicationLauncherDelegate(featureMapContentPlatform){}; + static void NewManager(jint endpoint, jobject manager); + void InitializeWithObjects(jobject managerObject); CHIP_ERROR HandleGetCatalogList(AttributeValueEncoder & aEncoder) override; @@ -40,4 +44,12 @@ class ApplicationLauncherManager : public ApplicationLauncherDelegate const ApplicationType & application) override; void HandleStopApp(CommandResponseHelper & helper, const ApplicationType & application) override; void HandleHideApp(CommandResponseHelper & helper, const ApplicationType & application) override; + + chip::JniGlobalReference mApplicationLauncherManagerObject; + jmethodID mGetCatalogListMethod = nullptr; + jmethodID mLaunchAppMethod = nullptr; + jmethodID mStopAppMethod = nullptr; + jmethodID mHideAppMethod = nullptr; + jmethodID mCreateApplicationMethod = nullptr; + jclass mApplicationClass = nullptr; }; diff --git a/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/Application.java b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/Application.java new file mode 100644 index 00000000000000..bac89b09420213 --- /dev/null +++ b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/Application.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.matter.tv.server.tvapp; + +public class Application { + + public int catalogVendorId; + public String applicationId; + + public Application(int catalogVendorId, String applicationId) { + this.catalogVendorId = catalogVendorId; + this.applicationId = applicationId; + } + + public Application createApplication(int catalogVendorId, String applicationId) { + return new Application(catalogVendorId, applicationId); + } + + @Override + public String toString() { + return "Application{" + "catalogVendorId=" + catalogVendorId + ", applicationId='" + '\'' + '}'; + } +} diff --git a/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/ApplicationLauncherManager.java b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/ApplicationLauncherManager.java new file mode 100644 index 00000000000000..7f80eb7a6c3421 --- /dev/null +++ b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/ApplicationLauncherManager.java @@ -0,0 +1,36 @@ +package com.matter.tv.server.tvapp; + +public interface ApplicationLauncherManager { + + /** + * Return a list of available catalogs + * + * @return list of int + */ + int[] getCatalogList(); + + /** + * Launch an app + * + * @param app that you want to launch + * @param data to send addditional data if needed + * @return launcher response with status + */ + LauncherResponse launchApp(Application app, String data); + + /** + * Stop an app + * + * @param app that you want to stop + * @return launcher response with status + */ + LauncherResponse stopApp(Application app); + + /** + * hide an app + * + * @param app that you want to hide + * @return launcher response with status + */ + LauncherResponse hideApp(Application app); +} diff --git a/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/LauncherResponse.java b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/LauncherResponse.java new file mode 100644 index 00000000000000..c0a41d2b153969 --- /dev/null +++ b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/LauncherResponse.java @@ -0,0 +1,22 @@ +package com.matter.tv.server.tvapp; + +public class LauncherResponse { + + public static final int STATUS_SUCCESS = 0; + public static final int STATUS_APP_NOT_AVAILABLE = 1; + public static final int STATUS_SYSTEM_BUSY = 2; + public static final int STATUS_PENDING_USER_APPROVAL = 3; + public static final int STATUS_DOWNLOADING = 4; + public static final int STATUS_INSTALLING = 5; + + public LauncherResponse(int status, String data) { + this.status = status; + this.data = data; + } + + /** The status in STATUS_XXX */ + public int status; + + /** Optional app-specific data. */ + public String data; +} diff --git a/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/TvApp.java b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/TvApp.java index eaf207e45f3618..8cac42ff582e3e 100644 --- a/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/TvApp.java +++ b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/TvApp.java @@ -47,6 +47,9 @@ private void postClusterInit(long clusterId, int endpoint) { public native void setKeypadInputManager(int endpoint, KeypadInputManager manager); + public native void setApplicationLauncherManager( + int endpoint, ApplicationLauncherManager manager); + public native void setWakeOnLanManager(int endpoint, WakeOnLanManager manager); public native void setMediaInputManager(int endpoint, MediaInputManager manager); diff --git a/examples/tv-app/tv-common/tv-app.matter b/examples/tv-app/tv-common/tv-app.matter index 34aa4475c79677..f2a2a6f0affb0f 100644 --- a/examples/tv-app/tv-common/tv-app.matter +++ b/examples/tv-app/tv-common/tv-app.matter @@ -3259,6 +3259,9 @@ cluster ApplicationLauncher = 1292 { kSuccess = 0; kAppNotAvailable = 1; kSystemBusy = 2; + kPendingUserApproval = 3; + kDownloading = 4; + kInstalling = 5; } bitmap Feature : bitmap32 { diff --git a/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/ConnectionExampleFragment.java b/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/ConnectionExampleFragment.java index b61b63f3e0785e..5db9a3560749b5 100644 --- a/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/ConnectionExampleFragment.java +++ b/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/ConnectionExampleFragment.java @@ -160,13 +160,17 @@ public void handle(Void v) { Log.i( TAG, "Successfully connected to CastingPlayer with deviceId: " - + targetCastingPlayer.getDeviceId()); + + targetCastingPlayer.getDeviceId() + + ", useCommissionerGeneratedPasscode: " + + useCommissionerGeneratedPasscode); getActivity() .runOnUiThread( () -> { connectionFragmentStatusTextView.setText( "Successfully connected to Casting Player with device name: " + targetCastingPlayer.getDeviceName() + + "\n\nUsed CastingPlayer Passcode: " + + useCommissionerGeneratedPasscode + "\n\n"); connectionFragmentNextButton.setEnabled(true); }); diff --git a/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/DiscoveryExampleFragment.java b/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/DiscoveryExampleFragment.java index 3dca2320b8924c..64130fa94cfe7b 100644 --- a/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/DiscoveryExampleFragment.java +++ b/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/DiscoveryExampleFragment.java @@ -67,7 +67,8 @@ public class DiscoveryExampleFragment extends Fragment { public void onAdded(CastingPlayer castingPlayer) { Log.i( TAG, - "onAdded() Discovered CastingPlayer deviceId: " + castingPlayer.getDeviceId()); + "DiscoveryExampleFragment onAdded() Discovered CastingPlayer deviceId: " + + castingPlayer.getDeviceId()); // Display CastingPlayer info on the screen new Handler(Looper.getMainLooper()) .post( @@ -80,7 +81,7 @@ public void onAdded(CastingPlayer castingPlayer) { public void onChanged(CastingPlayer castingPlayer) { Log.i( TAG, - "onChanged() Discovered changes to CastingPlayer with deviceId: " + "DiscoveryExampleFragment onChanged() Discovered changes to CastingPlayer with deviceId: " + castingPlayer.getDeviceId()); // Update the CastingPlayer on the screen new Handler(Looper.getMainLooper()) @@ -107,7 +108,7 @@ public void onChanged(CastingPlayer castingPlayer) { public void onRemoved(CastingPlayer castingPlayer) { Log.i( TAG, - "onRemoved() Removed CastingPlayer with deviceId: " + "DiscoveryExampleFragment onRemoved() Removed CastingPlayer with deviceId: " + castingPlayer.getDeviceId()); // Remove CastingPlayer from the screen new Handler(Looper.getMainLooper()) @@ -215,7 +216,10 @@ public void onResume() { @Override public void onPause() { super.onPause(); - Log.i(TAG, "onPause() called"); + Log.i(TAG, "DiscoveryExampleFragment onPause() called, calling stopDiscovery()"); + // Stop discovery when leaving the fragment, for example, while displaying the + // ConnectionExampleFragment. + stopDiscovery(); } /** Interface for notifying the host. */ @@ -261,7 +265,7 @@ private boolean startDiscovery() { } private void stopDiscovery() { - Log.i(TAG, "stopDiscovery() called"); + Log.i(TAG, "DiscoveryExampleFragment stopDiscovery() called"); matterDiscoveryErrorMessageTextView.setText( getString(R.string.matter_discovery_error_message_initial)); diff --git a/examples/tv-casting-app/android/App/app/src/main/res/layout/custom_passcode_dialog.xml b/examples/tv-casting-app/android/App/app/src/main/res/layout/custom_passcode_dialog.xml index 1b868e06b71f29..c91fa4ad404089 100644 --- a/examples/tv-casting-app/android/App/app/src/main/res/layout/custom_passcode_dialog.xml +++ b/examples/tv-casting-app/android/App/app/src/main/res/layout/custom_passcode_dialog.xml @@ -1,5 +1,6 @@ @@ -11,7 +12,6 @@ android:textStyle="bold" android:textSize="18sp" android:padding="16dp" - android:textColor="@android:color/white" android:gravity="center" android:text="@string/matter_connection_input_dialog_title" /> @@ -24,7 +24,6 @@ android:paddingEnd="16dp" android:paddingTop="8dp" android:paddingBottom="8dp" - android:textColor="@android:color/white" android:text="@string/matter_connection_input_dialog_instructions" /> - - -