diff --git a/.github/ISSUE_TEMPLATE/Issue-report.yml b/.github/ISSUE_TEMPLATE/Issue-report.yml index 436c8a57b7e..e3a4e92926e 100644 --- a/.github/ISSUE_TEMPLATE/Issue-report.yml +++ b/.github/ISSUE_TEMPLATE/Issue-report.yml @@ -41,6 +41,8 @@ body: options: - latest master (checkout manually) - latest development Release Candidate (RC-X) + - v3.1.0 + - v3.0.7 - v3.0.6 - v3.0.5 - v3.0.4 diff --git a/.github/scripts/on-push.sh b/.github/scripts/on-push.sh index aafc9de0596..6095f88e727 100755 --- a/.github/scripts/on-push.sh +++ b/.github/scripts/on-push.sh @@ -9,8 +9,9 @@ function build { local chunk_index=$2 local chunks_cnt=$3 local build_log=$4 - local sketches_file=$5 - shift 5 + local log_level=${5:-none} + local sketches_file=$6 + shift 6 local sketches=("$@") local BUILD_SKETCH="${SCRIPTS_DIR}/sketch_utils.sh build" @@ -19,7 +20,7 @@ function build { local args=("-ai" "$ARDUINO_IDE_PATH" "-au" "$ARDUINO_USR_PATH" "-t" "$target") if [ "$OS_IS_LINUX" == "1" ]; then - args+=("-p" "$ARDUINO_ESP32_PATH/libraries" "-i" "$chunk_index" "-m" "$chunks_cnt") + args+=("-p" "$ARDUINO_ESP32_PATH/libraries" "-i" "$chunk_index" "-m" "$chunks_cnt" "-d" "$log_level") if [ -n "$sketches_file" ]; then args+=("-f" "$sketches_file") fi @@ -54,7 +55,8 @@ fi CHUNK_INDEX=$1 CHUNKS_CNT=$2 BUILD_LOG=$3 -SKETCHES_FILE=$4 +LOG_LEVEL=$4 +SKETCHES_FILE=$5 if [ "$#" -lt 2 ] || [ "$CHUNKS_CNT" -le 0 ]; then CHUNK_INDEX=0 CHUNKS_CNT=1 @@ -88,13 +90,13 @@ if [ "$BUILD_LOG" -eq 1 ]; then fi #build sketches for different targets -build "esp32p4" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}" -build "esp32s3" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}" -build "esp32s2" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}" -build "esp32c3" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}" -build "esp32c6" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}" -build "esp32h2" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}" -build "esp32" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}" +build "esp32p4" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}" +build "esp32s3" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}" +build "esp32s2" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}" +build "esp32c3" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}" +build "esp32c6" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}" +build "esp32h2" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}" +build "esp32" "$CHUNK_INDEX" "$CHUNKS_CNT" "$BUILD_LOG" "$LOG_LEVEL" "$SKETCHES_FILE" "${SKETCHES_ESP32[@]}" if [ "$BUILD_LOG" -eq 1 ]; then #remove last comma from the last JSON object diff --git a/.github/scripts/sketch_utils.sh b/.github/scripts/sketch_utils.sh index 3e6ceb675e9..00d7d1bc232 100755 --- a/.github/scripts/sketch_utils.sh +++ b/.github/scripts/sketch_utils.sh @@ -443,6 +443,11 @@ function build_sketches { # build_sketches > $GITHUB_ENV + elif [ "${{ github.event_name }}" == "schedule" ]; then + echo "LOG_LEVEL=verbose" >> $GITHUB_ENV + else + echo "LOG_LEVEL=none" >> $GITHUB_ENV + fi + - name: Build all sketches if: ${{ needs.gen-chunks.outputs.build_all == 'true' }} - run: bash ./.github/scripts/on-push.sh ${{ matrix.chunk }} ${{ env.MAX_CHUNKS }} 1 + run: bash ./.github/scripts/on-push.sh ${{ matrix.chunk }} ${{ env.MAX_CHUNKS }} 1 ${{ env.LOG_LEVEL }} - name: Download sketches found if: ${{ needs.gen-chunks.outputs.build_all == 'false' && needs.gen-chunks.outputs.build_libraries == 'true' }} @@ -175,7 +201,7 @@ jobs: - name: Build selected sketches if: ${{ needs.gen-chunks.outputs.build_all == 'false' && needs.gen-chunks.outputs.build_libraries == 'true' }} - run: bash ./.github/scripts/on-push.sh ${{ matrix.chunk }} ${{ needs.gen-chunks.outputs.chunk_count }} 1 sketches_found.txt + run: bash ./.github/scripts/on-push.sh ${{ matrix.chunk }} ${{ needs.gen-chunks.outputs.chunk_count }} 1 ${{ env.LOG_LEVEL }} sketches_found.txt #Upload cli compile json as artifact - name: Upload cli compile json diff --git a/.github/workflows/tests_results.yml b/.github/workflows/tests_results.yml index 4ef338a9e16..947de64ece5 100644 --- a/.github/workflows/tests_results.yml +++ b/.github/workflows/tests_results.yml @@ -149,9 +149,10 @@ jobs: uses: jaywcjlove/generated-badges@v1.0.13 with: label: Runtime Tests - status: ${{ job.status }} + status: ${{ job.status == 'success' && 'passing' || 'failing' }} output: runtime-tests-results/badge.svg color: ${{ job.status == 'success' && 'green' || 'red' }} + style: flat - name: Push badge if: ${{ !cancelled() && (env.original_event == 'schedule' || env.original_event == 'workflow_dispatch') }} # codespell:ignore cancelled diff --git a/.github/workflows/upload-idf-component.yml b/.github/workflows/upload-idf-component.yml index c716e8144c2..8faddef7e5f 100644 --- a/.github/workflows/upload-idf-component.yml +++ b/.github/workflows/upload-idf-component.yml @@ -1,6 +1,11 @@ name: Push components to https://components.espressif.com on: + workflow_dispatch: + inputs: + tag: + description: 'Tag to push to the component registry' + required: true workflow_run: workflows: ["ESP32 Arduino Release"] types: @@ -15,9 +20,9 @@ jobs: steps: - name: Get the release tag env: - head_branch: ${{ github.event.workflow_run.head_branch }} + head_branch: ${{ inputs.tag || github.event.workflow_run.head_branch }} run: | - if [ "${{ github.event.workflow_run.conclusion }}" != "success" ]; then + if [ "${{ github.event.workflow_run.conclusion }}" != "success" ] && [ "${{ github.event_name }}" == "workflow_run" ]; then echo "Release workflow failed. Exiting..." exit 1 fi @@ -39,6 +44,7 @@ jobs: - uses: actions/checkout@v4 with: + ref: ${{ env.RELEASE_TAG }} submodules: "recursive" - name: Upload components to the component registry diff --git a/CMakeLists.txt b/CMakeLists.txt index b6478aa16a3..dd15e06dac8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -179,6 +179,8 @@ set(ARDUINO_LIBRARY_Matter_SRCS libraries/Matter/src/MatterEndpoints/MatterHumiditySensor.cpp libraries/Matter/src/MatterEndpoints/MatterContactSensor.cpp libraries/Matter/src/MatterEndpoints/MatterPressureSensor.cpp + libraries/Matter/src/MatterEndpoints/MatterOccupancySensor.cpp + libraries/Matter/src/MatterEndpoints/MatterOnOffPlugin.cpp libraries/Matter/src/Matter.cpp) set(ARDUINO_LIBRARY_PPP_SRCS @@ -274,10 +276,15 @@ set(ARDUINO_LIBRARY_Zigbee_SRCS libraries/Zigbee/src/ZigbeeHandlers.cpp libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp + libraries/Zigbee/src/ep/ZigbeeDimmableLight.cpp libraries/Zigbee/src/ep/ZigbeeLight.cpp libraries/Zigbee/src/ep/ZigbeeSwitch.cpp libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp libraries/Zigbee/src/ep/ZigbeeThermostat.cpp + libraries/Zigbee/src/ep/ZigbeeFlowSensor.cpp + libraries/Zigbee/src/ep/ZigbeePressureSensor.cpp + libraries/Zigbee/src/ep/ZigbeeOccupancySensor.cpp + libraries/Zigbee/src/ep/ZigbeeCarbonDioxideSensor.cpp ) set(ARDUINO_LIBRARY_BLE_SRCS diff --git a/README.md b/README.md index 5b1b1865efa..e610229fc60 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ # Arduino core for the ESP32, ESP32-P4, ESP32-S2, ESP32-S3, ESP32-C3, ESP32-C6 and ESP32-H2 -[![Build Status](https://github.com/espressif/arduino-esp32/actions/workflows/push.yml/badge.svg?branch=master&event=push)](https://github.com/espressif/arduino-esp32/actions/workflows/push.yml) [![External Libraries Test](https://github.com/espressif/arduino-esp32/actions/workflows/lib.yml/badge.svg?branch=master&event=schedule)](https://github.com/espressif/arduino-esp32/blob/gh-pages/LIBRARIES_TEST.md) [![Hardware Tests](https://github.com/espressif/arduino-esp32/blob/gh-pages/runtime-tests-results/badge.svg)](https://github.com/espressif/arduino-esp32/actions/workflows/tests_results.yml) +[![Build Status](https://img.shields.io/github/actions/workflow/status/espressif/arduino-esp32/push.yml?branch=master&event=push&label=Compilation%20Tests)](https://github.com/espressif/arduino-esp32/actions/workflows/push.yml?query=branch%3Amaster+event%3Apush) +[![Verbose Build Status](https://img.shields.io/github/actions/workflow/status/espressif/arduino-esp32/push.yml?branch=master&event=schedule&label=Compilation%20Tests%20(Verbose))](https://github.com/espressif/arduino-esp32/actions/workflows/push.yml?query=branch%3Amaster+event%3Aschedule) +[![External Libraries Test](https://img.shields.io/github/actions/workflow/status/espressif/arduino-esp32/lib.yml?branch=master&event=schedule&label=External%20Libraries%20Test)](https://github.com/espressif/arduino-esp32/blob/gh-pages/LIBRARIES_TEST.md) +[![Runtime Tests](https://github.com/espressif/arduino-esp32/blob/gh-pages/runtime-tests-results/badge.svg)](https://github.com/espressif/arduino-esp32/actions/workflows/tests_results.yml) ### Need help or have a question? Join the chat at [Gitter](https://gitter.im/espressif/arduino-esp32) or [open a new Discussion](https://github.com/espressif/arduino-esp32/discussions) @@ -16,9 +19,17 @@ ### Development Status -Latest Stable Release [![Release Version](https://img.shields.io/github/release/espressif/arduino-esp32.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/latest/) [![Release Date](https://img.shields.io/github/release-date/espressif/arduino-esp32.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/latest/) [![Downloads](https://img.shields.io/github/downloads/espressif/arduino-esp32/latest/total.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/latest/) +#### Latest Stable Release -Latest Development Release [![Release Version](https://img.shields.io/github/release/espressif/arduino-esp32/all.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/) [![Release Date](https://img.shields.io/github/release-date-pre/espressif/arduino-esp32.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/) [![Downloads](https://img.shields.io/github/downloads-pre/espressif/arduino-esp32/latest/total.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/) +[![Release Version](https://img.shields.io/github/release/espressif/arduino-esp32.svg)](https://github.com/espressif/arduino-esp32/releases/latest/) +[![Release Date](https://img.shields.io/github/release-date/espressif/arduino-esp32.svg)](https://github.com/espressif/arduino-esp32/releases/latest/) +[![Downloads](https://img.shields.io/github/downloads/espressif/arduino-esp32/latest/total.svg)](https://github.com/espressif/arduino-esp32/releases/latest/) + +#### Latest Development Release + +[![Release Version](https://img.shields.io/github/release/espressif/arduino-esp32/all.svg)](https://github.com/espressif/arduino-esp32/releases/) +[![Release Date](https://img.shields.io/github/release-date-pre/espressif/arduino-esp32.svg)](https://github.com/espressif/arduino-esp32/releases/) +[![Downloads](https://img.shields.io/github/downloads-pre/espressif/arduino-esp32/latest/total.svg)](https://github.com/espressif/arduino-esp32/releases/) ### Development Planning @@ -59,7 +70,7 @@ Here are the ESP32 series supported by the Arduino-ESP32 project: | ESP32-S3 | Yes | Yes | [ESP32-S3](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) | | ESP32-C6 | Yes | Yes | [ESP32-C6](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf) | | ESP32-H2 | Yes | Yes | [ESP32-H2](https://www.espressif.com/sites/default/files/documentation/esp32-h2_datasheet_en.pdf) | -| ESP32-P4 | No | Yes | [ESP32-P4](https://www.espressif.com/sites/default/files/documentation/esp32-p4_datasheet_en.pdf) | +| ESP32-P4 | Yes | Yes | [ESP32-P4](https://www.espressif.com/sites/default/files/documentation/esp32-p4_datasheet_en.pdf) | > [!NOTE] > ESP32-C2 is also supported by Arduino-ESP32 but requires rebuilding the static libraries. This is not trivial and requires a good understanding of the ESP-IDF diff --git a/boards.txt b/boards.txt index 11bcd372871..26ec251ecfe 100644 --- a/boards.txt +++ b/boards.txt @@ -48128,3 +48128,222 @@ yb_esp32s3_amp_v3.menu.EraseFlash.all=Enabled yb_esp32s3_amp_v3.menu.EraseFlash.all.upload.erase_cmd=-e ############################################################## + +yb_esp32s3_eth.name=YelloByte YB-ESP32-S3-ETH + +yb_esp32s3_eth.bootloader.tool=esptool_py +yb_esp32s3_eth.bootloader.tool.default=esptool_py + +yb_esp32s3_eth.upload.tool=esptool_py +yb_esp32s3_eth.upload.tool.default=esptool_py +yb_esp32s3_eth.upload.tool.network=esp_ota + +yb_esp32s3_eth.upload.maximum_size=1310720 +yb_esp32s3_eth.upload.maximum_data_size=327680 +yb_esp32s3_eth.upload.flags= +yb_esp32s3_eth.upload.extra_flags= +yb_esp32s3_eth.upload.use_1200bps_touch=false +yb_esp32s3_eth.upload.wait_for_upload_port=false + +yb_esp32s3_eth.serial.disableDTR=false +yb_esp32s3_eth.serial.disableRTS=false + +yb_esp32s3_eth.build.tarch=xtensa +yb_esp32s3_eth.build.bootloader_addr=0x0 +yb_esp32s3_eth.build.target=esp32s3 +yb_esp32s3_eth.build.mcu=esp32s3 +yb_esp32s3_eth.build.core=esp32 +yb_esp32s3_eth.build.variant=yb_esp32s3_eth +yb_esp32s3_eth.build.board=YB_ESP32S3_ETH + +yb_esp32s3_eth.build.usb_mode=1 +yb_esp32s3_eth.build.cdc_on_boot=0 +yb_esp32s3_eth.build.msc_on_boot=0 +yb_esp32s3_eth.build.dfu_on_boot=0 +yb_esp32s3_eth.build.f_cpu=240000000L +yb_esp32s3_eth.build.flash_size=4MB +yb_esp32s3_eth.build.flash_freq=80m +yb_esp32s3_eth.build.flash_mode=dio +yb_esp32s3_eth.build.boot=qio +yb_esp32s3_eth.build.boot_freq=80m +yb_esp32s3_eth.build.partitions=default +yb_esp32s3_eth.build.defines= +yb_esp32s3_eth.build.loop_core= +yb_esp32s3_eth.build.event_core= +yb_esp32s3_eth.build.psram_type=qspi +yb_esp32s3_eth.build.memory_type={build.boot}_{build.psram_type} + +yb_esp32s3_eth.menu.JTAGAdapter.default=Disabled +yb_esp32s3_eth.menu.JTAGAdapter.default.build.copy_jtag_files=0 +yb_esp32s3_eth.menu.JTAGAdapter.builtin=Integrated USB JTAG +yb_esp32s3_eth.menu.JTAGAdapter.builtin.build.openocdscript=esp32s3-builtin.cfg +yb_esp32s3_eth.menu.JTAGAdapter.builtin.build.copy_jtag_files=1 +yb_esp32s3_eth.menu.JTAGAdapter.external=FTDI Adapter +yb_esp32s3_eth.menu.JTAGAdapter.external.build.openocdscript=esp32s3-ftdi.cfg +yb_esp32s3_eth.menu.JTAGAdapter.external.build.copy_jtag_files=1 +yb_esp32s3_eth.menu.JTAGAdapter.bridge=ESP USB Bridge +yb_esp32s3_eth.menu.JTAGAdapter.bridge.build.openocdscript=esp32s3-bridge.cfg +yb_esp32s3_eth.menu.JTAGAdapter.bridge.build.copy_jtag_files=1 + +yb_esp32s3_eth.menu.LoopCore.1=Core 1 +yb_esp32s3_eth.menu.LoopCore.1.build.loop_core=-DARDUINO_RUNNING_CORE=1 +yb_esp32s3_eth.menu.LoopCore.0=Core 0 +yb_esp32s3_eth.menu.LoopCore.0.build.loop_core=-DARDUINO_RUNNING_CORE=0 + +yb_esp32s3_eth.menu.EventsCore.1=Core 1 +yb_esp32s3_eth.menu.EventsCore.1.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1 +yb_esp32s3_eth.menu.EventsCore.0=Core 0 +yb_esp32s3_eth.menu.EventsCore.0.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=0 + +yb_esp32s3_eth.menu.USBMode.hwcdc=Hardware CDC and JTAG +yb_esp32s3_eth.menu.USBMode.hwcdc.build.usb_mode=1 +yb_esp32s3_eth.menu.USBMode.default=USB-OTG (TinyUSB) +yb_esp32s3_eth.menu.USBMode.default.build.usb_mode=0 + +yb_esp32s3_eth.menu.CDCOnBoot.default=Disabled +yb_esp32s3_eth.menu.CDCOnBoot.default.build.cdc_on_boot=0 +yb_esp32s3_eth.menu.CDCOnBoot.cdc=Enabled +yb_esp32s3_eth.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 + +yb_esp32s3_eth.menu.MSCOnBoot.default=Disabled +yb_esp32s3_eth.menu.MSCOnBoot.default.build.msc_on_boot=0 +yb_esp32s3_eth.menu.MSCOnBoot.msc=Enabled (Requires USB-OTG Mode) +yb_esp32s3_eth.menu.MSCOnBoot.msc.build.msc_on_boot=1 + +yb_esp32s3_eth.menu.DFUOnBoot.default=Disabled +yb_esp32s3_eth.menu.DFUOnBoot.default.build.dfu_on_boot=0 +yb_esp32s3_eth.menu.DFUOnBoot.dfu=Enabled (Requires USB-OTG Mode) +yb_esp32s3_eth.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 + +yb_esp32s3_eth.menu.UploadMode.default=UART0 / Hardware CDC +yb_esp32s3_eth.menu.UploadMode.default.upload.use_1200bps_touch=false +yb_esp32s3_eth.menu.UploadMode.default.upload.wait_for_upload_port=false +yb_esp32s3_eth.menu.UploadMode.cdc=USB-OTG CDC (TinyUSB) +yb_esp32s3_eth.menu.UploadMode.cdc.upload.use_1200bps_touch=true +yb_esp32s3_eth.menu.UploadMode.cdc.upload.wait_for_upload_port=true + +yb_esp32s3_eth.menu.PSRAM.disabled=Disabled +yb_esp32s3_eth.menu.PSRAM.disabled.build.defines= +yb_esp32s3_eth.menu.PSRAM.disabled.build.psram_type=qspi +yb_esp32s3_eth.menu.PSRAM.enabled=QSPI PSRAM +yb_esp32s3_eth.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM +yb_esp32s3_eth.menu.PSRAM.enabled.build.psram_type=qspi +yb_esp32s3_eth.menu.PSRAM.opi=OPI PSRAM +yb_esp32s3_eth.menu.PSRAM.opi.build.defines=-DBOARD_HAS_PSRAM +yb_esp32s3_eth.menu.PSRAM.opi.build.psram_type=opi + +yb_esp32s3_eth.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) +yb_esp32s3_eth.menu.PartitionScheme.default.build.partitions=default +yb_esp32s3_eth.menu.PartitionScheme.default_8MB=8M with spiffs (3MB APP/1.5MB SPIFFS) +yb_esp32s3_eth.menu.PartitionScheme.default_8MB.build.partitions=default_8MB +yb_esp32s3_eth.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 +yb_esp32s3_eth.menu.PartitionScheme.default_16MB=16M with spiffs (6.25MB APP/3.43MB SPIFFS) +yb_esp32s3_eth.menu.PartitionScheme.default_16MB.build.partitions=default_16MB +yb_esp32s3_eth.menu.PartitionScheme.default_16MB.upload.maximum_size=6553600 +yb_esp32s3_eth.menu.PartitionScheme.max_app_8MB=Maximum APP (7.9MB APP No OTA/No FS) +yb_esp32s3_eth.menu.PartitionScheme.max_app_8MB.build.partitions=max_app_8MB +yb_esp32s3_eth.menu.PartitionScheme.max_app_8MB.upload.maximum_size=8257536 +yb_esp32s3_eth.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FATFS) +yb_esp32s3_eth.menu.PartitionScheme.fatflash.build.partitions=ffat +yb_esp32s3_eth.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 +yb_esp32s3_eth.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) +yb_esp32s3_eth.menu.PartitionScheme.defaultffat.build.partitions=default_ffat +yb_esp32s3_eth.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) +yb_esp32s3_eth.menu.PartitionScheme.minimal.build.partitions=minimal +yb_esp32s3_eth.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) +yb_esp32s3_eth.menu.PartitionScheme.no_ota.build.partitions=no_ota +yb_esp32s3_eth.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 +yb_esp32s3_eth.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) +yb_esp32s3_eth.menu.PartitionScheme.noota_3g.build.partitions=noota_3g +yb_esp32s3_eth.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 +yb_esp32s3_eth.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) +yb_esp32s3_eth.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat +yb_esp32s3_eth.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 +yb_esp32s3_eth.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) +yb_esp32s3_eth.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat +yb_esp32s3_eth.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 +yb_esp32s3_eth.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) +yb_esp32s3_eth.menu.PartitionScheme.huge_app.build.partitions=huge_app +yb_esp32s3_eth.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 +yb_esp32s3_eth.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) +yb_esp32s3_eth.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs +yb_esp32s3_eth.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +yb_esp32s3_eth.menu.PartitionScheme.custom=Custom +yb_esp32s3_eth.menu.PartitionScheme.custom.build.partitions= +yb_esp32s3_eth.menu.PartitionScheme.custom.upload.maximum_size=16777216 + +yb_esp32s3_eth.menu.CPUFreq.240=240MHz (WiFi) +yb_esp32s3_eth.menu.CPUFreq.240.build.f_cpu=240000000L +yb_esp32s3_eth.menu.CPUFreq.160=160MHz (WiFi) +yb_esp32s3_eth.menu.CPUFreq.160.build.f_cpu=160000000L +yb_esp32s3_eth.menu.CPUFreq.80=80MHz (WiFi) +yb_esp32s3_eth.menu.CPUFreq.80.build.f_cpu=80000000L +yb_esp32s3_eth.menu.CPUFreq.40=40MHz +yb_esp32s3_eth.menu.CPUFreq.40.build.f_cpu=40000000L +yb_esp32s3_eth.menu.CPUFreq.20=20MHz +yb_esp32s3_eth.menu.CPUFreq.20.build.f_cpu=20000000L +yb_esp32s3_eth.menu.CPUFreq.10=10MHz +yb_esp32s3_eth.menu.CPUFreq.10.build.f_cpu=10000000L + +yb_esp32s3_eth.menu.FlashMode.qio=QIO 80MHz +yb_esp32s3_eth.menu.FlashMode.qio.build.flash_mode=dio +yb_esp32s3_eth.menu.FlashMode.qio.build.boot=qio +yb_esp32s3_eth.menu.FlashMode.qio.build.boot_freq=80m +yb_esp32s3_eth.menu.FlashMode.qio.build.flash_freq=80m +yb_esp32s3_eth.menu.FlashMode.qio120=QIO 120MHz +yb_esp32s3_eth.menu.FlashMode.qio120.build.flash_mode=dio +yb_esp32s3_eth.menu.FlashMode.qio120.build.boot=qio +yb_esp32s3_eth.menu.FlashMode.qio120.build.boot_freq=120m +yb_esp32s3_eth.menu.FlashMode.qio120.build.flash_freq=80m +yb_esp32s3_eth.menu.FlashMode.dio=DIO 80MHz +yb_esp32s3_eth.menu.FlashMode.dio.build.flash_mode=dio +yb_esp32s3_eth.menu.FlashMode.dio.build.boot=dio +yb_esp32s3_eth.menu.FlashMode.dio.build.boot_freq=80m +yb_esp32s3_eth.menu.FlashMode.dio.build.flash_freq=80m +yb_esp32s3_eth.menu.FlashMode.opi=OPI 80MHz +yb_esp32s3_eth.menu.FlashMode.opi.build.flash_mode=dout +yb_esp32s3_eth.menu.FlashMode.opi.build.boot=opi +yb_esp32s3_eth.menu.FlashMode.opi.build.boot_freq=80m +yb_esp32s3_eth.menu.FlashMode.opi.build.flash_freq=80m + +yb_esp32s3_eth.menu.FlashSize.4M=4MB (32Mb) +yb_esp32s3_eth.menu.FlashSize.4M.build.flash_size=4MB +yb_esp32s3_eth.menu.FlashSize.8M=8MB (64Mb) +yb_esp32s3_eth.menu.FlashSize.8M.build.flash_size=8MB +yb_esp32s3_eth.menu.FlashSize.16M=16MB (128Mb) +yb_esp32s3_eth.menu.FlashSize.16M.build.flash_size=16MB + +yb_esp32s3_eth.menu.UploadSpeed.921600=921600 +yb_esp32s3_eth.menu.UploadSpeed.921600.upload.speed=921600 +yb_esp32s3_eth.menu.UploadSpeed.115200=115200 +yb_esp32s3_eth.menu.UploadSpeed.115200.upload.speed=115200 +yb_esp32s3_eth.menu.UploadSpeed.256000.windows=256000 +yb_esp32s3_eth.menu.UploadSpeed.256000.upload.speed=256000 +yb_esp32s3_eth.menu.UploadSpeed.230400.windows.upload.speed=256000 +yb_esp32s3_eth.menu.UploadSpeed.230400=230400 +yb_esp32s3_eth.menu.UploadSpeed.230400.upload.speed=230400 +yb_esp32s3_eth.menu.UploadSpeed.460800.linux=460800 +yb_esp32s3_eth.menu.UploadSpeed.460800.macosx=460800 +yb_esp32s3_eth.menu.UploadSpeed.460800.upload.speed=460800 +yb_esp32s3_eth.menu.UploadSpeed.512000.windows=512000 +yb_esp32s3_eth.menu.UploadSpeed.512000.upload.speed=512000 + +yb_esp32s3_eth.menu.DebugLevel.none=None +yb_esp32s3_eth.menu.DebugLevel.none.build.code_debug=0 +yb_esp32s3_eth.menu.DebugLevel.error=Error +yb_esp32s3_eth.menu.DebugLevel.error.build.code_debug=1 +yb_esp32s3_eth.menu.DebugLevel.warn=Warn +yb_esp32s3_eth.menu.DebugLevel.warn.build.code_debug=2 +yb_esp32s3_eth.menu.DebugLevel.info=Info +yb_esp32s3_eth.menu.DebugLevel.info.build.code_debug=3 +yb_esp32s3_eth.menu.DebugLevel.debug=Debug +yb_esp32s3_eth.menu.DebugLevel.debug.build.code_debug=4 +yb_esp32s3_eth.menu.DebugLevel.verbose=Verbose +yb_esp32s3_eth.menu.DebugLevel.verbose.build.code_debug=5 + +yb_esp32s3_eth.menu.EraseFlash.none=Disabled +yb_esp32s3_eth.menu.EraseFlash.none.upload.erase_cmd= +yb_esp32s3_eth.menu.EraseFlash.all=Enabled +yb_esp32s3_eth.menu.EraseFlash.all.upload.erase_cmd=-e + +############################################################## diff --git a/cores/esp32/esp32-hal-cpu.c b/cores/esp32/esp32-hal-cpu.c index e9baf3613c2..1ffde860792 100644 --- a/cores/esp32/esp32-hal-cpu.c +++ b/cores/esp32/esp32-hal-cpu.c @@ -259,18 +259,10 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz) { if (apb_change_callbacks) { triggerApbChangeCallback(APB_AFTER_CHANGE, capb, apb); } - // clang-format off -#ifdef SOC_CLK_APLL_SUPPORTED +#if defined(SOC_CLK_APLL_SUPPORTED) && !defined(CONFIG_IDF_TARGET_ESP32P4) // APLL not yet supported in ESP32-P4 log_d( "%s: %u / %u = %u Mhz, APB: %u Hz", - (conf.source == SOC_CPU_CLK_SRC_PLL) ? "PLL" - : ((conf.source == SOC_CPU_CLK_SRC_APLL) ? "APLL" - : ((conf.source == SOC_CPU_CLK_SRC_XTAL) ? "XTAL" -#ifdef CONFIG_IDF_TARGET_ESP32P4 - : "17.5M")), -#else - : "8M")), -#endif + (conf.source == SOC_CPU_CLK_SRC_PLL) ? "PLL" : ((conf.source == SOC_CPU_CLK_SRC_APLL) ? "APLL" : ((conf.source == SOC_CPU_CLK_SRC_XTAL) ? "XTAL" : "8M")), conf.source_freq_mhz, conf.div, conf.freq_mhz, apb ); #else @@ -279,7 +271,6 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz) { conf.source_freq_mhz, conf.div, conf.freq_mhz, apb ); #endif - // clang-format on return true; } diff --git a/cores/esp32/esp32-hal-time.c b/cores/esp32/esp32-hal-time.c index 25c060eabdd..074e999be71 100644 --- a/cores/esp32/esp32-hal-time.c +++ b/cores/esp32/esp32-hal-time.c @@ -51,9 +51,6 @@ static void setTimeZone(long offset, int daylight) { void configTime(long gmtOffset_sec, int daylightOffset_sec, const char *server1, const char *server2, const char *server3) { //tcpip_adapter_init(); // Should not hurt anything if already inited esp_netif_init(); - if (sntp_enabled()) { - sntp_stop(); - } #ifdef CONFIG_LWIP_TCPIP_CORE_LOCKING if (!sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)) { @@ -61,6 +58,10 @@ void configTime(long gmtOffset_sec, int daylightOffset_sec, const char *server1, } #endif + if (sntp_enabled()) { + sntp_stop(); + } + sntp_setoperatingmode(SNTP_OPMODE_POLL); sntp_setservername(0, (char *)server1); sntp_setservername(1, (char *)server2); @@ -83,9 +84,6 @@ void configTime(long gmtOffset_sec, int daylightOffset_sec, const char *server1, void configTzTime(const char *tz, const char *server1, const char *server2, const char *server3) { //tcpip_adapter_init(); // Should not hurt anything if already inited esp_netif_init(); - if (sntp_enabled()) { - sntp_stop(); - } #ifdef CONFIG_LWIP_TCPIP_CORE_LOCKING if (!sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)) { @@ -93,6 +91,10 @@ void configTzTime(const char *tz, const char *server1, const char *server2, cons } #endif + if (sntp_enabled()) { + sntp_stop(); + } + sntp_setoperatingmode(SNTP_OPMODE_POLL); sntp_setservername(0, (char *)server1); sntp_setservername(1, (char *)server2); diff --git a/libraries/ESP32/examples/Timer/RepeatTimer/RepeatTimer.ino b/libraries/ESP32/examples/Timer/RepeatTimer/RepeatTimer.ino index 18fdc8035a5..e4ef7bc865b 100644 --- a/libraries/ESP32/examples/Timer/RepeatTimer/RepeatTimer.ino +++ b/libraries/ESP32/examples/Timer/RepeatTimer/RepeatTimer.ino @@ -33,7 +33,7 @@ void setup() { Serial.begin(115200); // Set BTN_STOP_ALARM to input mode - pinMode(BTN_STOP_ALARM, INPUT); + pinMode(BTN_STOP_ALARM, INPUT_PULLUP); // Create semaphore to inform us when the timer has fired timerSemaphore = xSemaphoreCreateBinary(); diff --git a/libraries/Matter/examples/MatterColorLight/MatterColorLight.ino b/libraries/Matter/examples/MatterColorLight/MatterColorLight.ino index ea91baef0ea..dd1724f602d 100644 --- a/libraries/Matter/examples/MatterColorLight/MatterColorLight.ino +++ b/libraries/Matter/examples/MatterColorLight/MatterColorLight.ino @@ -21,6 +21,10 @@ // Color Light Endpoint MatterColorLight ColorLight; +// WiFi is manually set and started +const char *ssid = "your-ssid"; // Change this to your WiFi SSID +const char *password = "your-password"; // Change this to your WiFi password + // it will keep last OnOff & HSV Color state stored, using Preferences Preferences matterPref; const char *onOffPrefKey = "OnOff"; @@ -43,10 +47,6 @@ bool button_state = false; // false = released | true = pres const uint32_t debouceTime = 250; // button debouncing time (ms) const uint32_t decommissioningTimeout = 5000; // keep the button pressed for 5s, or longer, to decommission -// WiFi is manually set and started -const char *ssid = "your-ssid"; // Change this to your WiFi SSID -const char *password = "your-password"; // Change this to your WiFi password - // Set the RGB LED Light based on the current state of the Color Light bool setLightState(bool state, espHsvColor_t colorHSV) { @@ -76,15 +76,10 @@ void setup() { pinMode(ledPin, OUTPUT); Serial.begin(115200); - while (!Serial) { - delay(100); - } // We start by connecting to a WiFi network Serial.print("Connecting to "); Serial.println(ssid); - // enable IPv6 - WiFi.enableIPv6(true); // Manually connect to WiFi WiFi.begin(ssid, password); // Wait for connection diff --git a/libraries/Matter/examples/MatterCommissionTest/MatterCommissionTest.ino b/libraries/Matter/examples/MatterCommissionTest/MatterCommissionTest.ino index 9024479c881..0e93ed6d155 100644 --- a/libraries/Matter/examples/MatterCommissionTest/MatterCommissionTest.ino +++ b/libraries/Matter/examples/MatterCommissionTest/MatterCommissionTest.ino @@ -26,15 +26,10 @@ const char *password = "your-password"; // Change this to your WiFi password void setup() { Serial.begin(115200); - while (!Serial) { - delay(100); - } // We start by connecting to a WiFi network Serial.print("Connecting to "); Serial.println(ssid); - // enable IPv6 - WiFi.enableIPv6(true); // Manually connect to WiFi WiFi.begin(ssid, password); // Wait for connection diff --git a/libraries/Matter/examples/MatterComposedLights/MatterComposedLights.ino b/libraries/Matter/examples/MatterComposedLights/MatterComposedLights.ino index 63062ba36a9..9c3dcf05a83 100644 --- a/libraries/Matter/examples/MatterComposedLights/MatterComposedLights.ino +++ b/libraries/Matter/examples/MatterComposedLights/MatterComposedLights.ino @@ -55,15 +55,10 @@ void setup() { pinMode(buttonPin, INPUT_PULLUP); Serial.begin(115200); - while (!Serial) { - delay(100); - } // We start by connecting to a WiFi network Serial.print("Connecting to "); Serial.println(ssid); - // enable IPv6 - WiFi.enableIPv6(true); // Manually connect to WiFi WiFi.begin(ssid, password); // Wait for connection diff --git a/libraries/Matter/examples/MatterContactSensor/MatterContactSensor.ino b/libraries/Matter/examples/MatterContactSensor/MatterContactSensor.ino index 7b4d95a880b..e27f70e613d 100644 --- a/libraries/Matter/examples/MatterContactSensor/MatterContactSensor.ino +++ b/libraries/Matter/examples/MatterContactSensor/MatterContactSensor.ino @@ -36,6 +36,10 @@ // Matter Contact Sensor Endpoint MatterContactSensor ContactSensor; +// WiFi is manually set and started +const char *ssid = "your-ssid"; // Change this to your WiFi SSID +const char *password = "your-password"; // Change this to your WiFi password + // LED will be used to indicate the Contact Sensor state // set your board RGB LED pin here #ifdef RGB_BUILTIN @@ -48,10 +52,6 @@ const uint8_t ledPin = 2; // Set your pin here if your board has not defined LE // set your board USER BUTTON pin here - decommissioning and Manual Contact Sensor toggle button const uint8_t buttonPin = BOOT_PIN; // Set your pin here. Using BOOT Button. -// WiFi is manually set and started -const char *ssid = "your-ssid"; // Change this to your WiFi SSID -const char *password = "your-password"; // Change this to your WiFi password - // Button control uint32_t button_time_stamp = 0; // debouncing control bool button_state = false; // false = released | true = pressed diff --git a/libraries/Matter/examples/MatterDimmableLight/MatterDimmableLight.ino b/libraries/Matter/examples/MatterDimmableLight/MatterDimmableLight.ino index f1af4f84dfc..cb8b8b6f17f 100644 --- a/libraries/Matter/examples/MatterDimmableLight/MatterDimmableLight.ino +++ b/libraries/Matter/examples/MatterDimmableLight/MatterDimmableLight.ino @@ -21,6 +21,10 @@ // Dimmable Light Endpoint MatterDimmableLight DimmableLight; +// WiFi is manually set and started +const char *ssid = "your-ssid"; // Change this to your WiFi SSID +const char *password = "your-password"; // Change this to your WiFi password + // it will keep last OnOff & Brightness state stored, using Preferences Preferences matterPref; const char *onOffPrefKey = "OnOff"; @@ -43,10 +47,6 @@ bool button_state = false; // false = released | true = pres const uint32_t debouceTime = 250; // button debouncing time (ms) const uint32_t decommissioningTimeout = 5000; // keep the button pressed for 5s, or longer, to decommission -// WiFi is manually set and started -const char *ssid = "your-ssid"; // Change this to your WiFi SSID -const char *password = "your-password"; // Change this to your WiFi password - // Set the RGB LED Light based on the current state of the Dimmable Light bool setLightState(bool state, uint8_t brightness) { if (state) { @@ -72,15 +72,10 @@ void setup() { pinMode(ledPin, OUTPUT); Serial.begin(115200); - while (!Serial) { - delay(100); - } // We start by connecting to a WiFi network Serial.print("Connecting to "); Serial.println(ssid); - // enable IPv6 - WiFi.enableIPv6(true); // Manually connect to WiFi WiFi.begin(ssid, password); // Wait for connection diff --git a/libraries/Matter/examples/MatterEnhancedColorLight/MatterEnhancedColorLight.ino b/libraries/Matter/examples/MatterEnhancedColorLight/MatterEnhancedColorLight.ino index eddbd0f2b21..bd2d13899ca 100644 --- a/libraries/Matter/examples/MatterEnhancedColorLight/MatterEnhancedColorLight.ino +++ b/libraries/Matter/examples/MatterEnhancedColorLight/MatterEnhancedColorLight.ino @@ -21,6 +21,10 @@ // Color Light Endpoint MatterEnhancedColorLight EnhancedColorLight; +// WiFi is manually set and started +const char *ssid = "your-ssid"; // Change this to your WiFi SSID +const char *password = "your-password"; // Change this to your WiFi password + // It will use HSV color to control all Matter Attribute Changes HsvColor_t currentHSVColor = {0, 0, 0}; @@ -46,10 +50,6 @@ bool button_state = false; // false = released | true = pres const uint32_t debouceTime = 250; // button debouncing time (ms) const uint32_t decommissioningTimeout = 5000; // keep the button pressed for 5s, or longer, to decommission -// WiFi is manually set and started -const char *ssid = "your-ssid"; // Change this to your WiFi SSID -const char *password = "your-password"; // Change this to your WiFi password - // Set the RGB LED Light based on the current state of the Enhanced Color Light bool setLightState(bool state, espHsvColor_t colorHSV, uint8_t brighteness, uint16_t temperature_Mireds) { @@ -80,15 +80,10 @@ void setup() { pinMode(ledPin, OUTPUT); Serial.begin(115200); - while (!Serial) { - delay(100); - } // We start by connecting to a WiFi network Serial.print("Connecting to "); Serial.println(ssid); - // enable IPv6 - WiFi.enableIPv6(true); // Manually connect to WiFi WiFi.begin(ssid, password); // Wait for connection diff --git a/libraries/Matter/examples/MatterFan/MatterFan.ino b/libraries/Matter/examples/MatterFan/MatterFan.ino index a226dedf75d..3dc0c89fcf4 100644 --- a/libraries/Matter/examples/MatterFan/MatterFan.ino +++ b/libraries/Matter/examples/MatterFan/MatterFan.ino @@ -20,6 +20,10 @@ // Fan Endpoint - On/Off control + Speed Percent Control + Fan Modes MatterFan Fan; +// WiFi is manually set and started +const char *ssid = "your-ssid"; // Change this to your WiFi SSID +const char *password = "your-password"; // Change this to your WiFi password + // set your board USER BUTTON pin here - used for toggling On/Off and decommission the Matter Node const uint8_t buttonPin = BOOT_PIN; // Set your pin here. Using BOOT Button. @@ -41,10 +45,6 @@ const uint8_t dcMotorPin = 2; // Set your pin here if your board has not define #warning "Do not forget to set the RGB LED pin" #endif -// WiFi is manually set and started -const char *ssid = "your-ssid"; // Change this to your WiFi SSID -const char *password = "your-password"; // Change this to your WiFi password - void fanDCMotorDrive(bool fanState, uint8_t speedPercent) { // drive the Fan DC motor if (fanState == false) { @@ -71,15 +71,10 @@ void setup() { pinMode(dcMotorPin, OUTPUT); Serial.begin(115200); - while (!Serial) { - delay(100); - } // We start by connecting to a WiFi network Serial.print("Connecting to "); Serial.println(ssid); - // enable IPv6 - WiFi.enableIPv6(true); // Manually connect to WiFi WiFi.begin(ssid, password); // Wait for connection diff --git a/libraries/Matter/examples/MatterHumiditySensor/MatterHumiditySensor.ino b/libraries/Matter/examples/MatterHumiditySensor/MatterHumiditySensor.ino index c4977772c1b..3fcab46c565 100644 --- a/libraries/Matter/examples/MatterHumiditySensor/MatterHumiditySensor.ino +++ b/libraries/Matter/examples/MatterHumiditySensor/MatterHumiditySensor.ino @@ -27,13 +27,13 @@ // Matter Humidity Sensor Endpoint MatterHumiditySensor SimulatedHumiditySensor; -// set your board USER BUTTON pin here - decommissioning button -const uint8_t buttonPin = BOOT_PIN; // Set your pin here. Using BOOT Button. - // WiFi is manually set and started const char *ssid = "your-ssid"; // Change this to your WiFi SSID const char *password = "your-password"; // Change this to your WiFi password +// set your board USER BUTTON pin here - decommissioning button +const uint8_t buttonPin = BOOT_PIN; // Set your pin here. Using BOOT Button. + // Button control - decommision the Matter Node uint32_t button_time_stamp = 0; // debouncing control bool button_state = false; // false = released | true = pressed diff --git a/libraries/Matter/examples/MatterMinimum/MatterMinimum.ino b/libraries/Matter/examples/MatterMinimum/MatterMinimum.ino index cc54d3c12c0..fa2599df6dd 100644 --- a/libraries/Matter/examples/MatterMinimum/MatterMinimum.ino +++ b/libraries/Matter/examples/MatterMinimum/MatterMinimum.ino @@ -28,6 +28,10 @@ // Single On/Off Light Endpoint - at least one per node MatterOnOffLight OnOffLight; +// WiFi is manually set and started +const char *ssid = "your-ssid"; // Change this to your WiFi SSID +const char *password = "your-password"; // Change this to your WiFi password + // Light GPIO that can be controlled by Matter APP #ifdef LED_BUILTIN const uint8_t ledPin = LED_BUILTIN; @@ -44,23 +48,18 @@ bool button_state = false; // false = released | true = pres const uint32_t decommissioningTimeout = 5000; // keep the button pressed for 5s, or longer, to decommission // Matter Protocol Endpoint (On/OFF Light) Callback -bool matterCB(bool state) { +bool onOffLightCallback(bool state) { digitalWrite(ledPin, state ? HIGH : LOW); // This callback must return the success state to Matter core return true; } -// WiFi is manually set and started -const char *ssid = "your-ssid"; // Change this to your WiFi SSID -const char *password = "your-password"; // Change this to your WiFi password - void setup() { // Initialize the USER BUTTON (Boot button) that will be used to decommission the Matter Node pinMode(buttonPin, INPUT_PULLUP); // Initialize the LED GPIO pinMode(ledPin, OUTPUT); - WiFi.enableIPv6(true); // Manually connect to WiFi WiFi.begin(ssid, password); // Wait for connection @@ -72,7 +71,7 @@ void setup() { OnOffLight.begin(); // Associate a callback to the Matter Controller - OnOffLight.onChange(matterCB); + OnOffLight.onChange(onOffLightCallback); // Matter beginning - Last step, after all EndPoints are initialized Matter.begin(); diff --git a/libraries/Matter/examples/MatterOccupancySensor/MatterOccupancySensor.ino b/libraries/Matter/examples/MatterOccupancySensor/MatterOccupancySensor.ino new file mode 100644 index 00000000000..e88a9a8986b --- /dev/null +++ b/libraries/Matter/examples/MatterOccupancySensor/MatterOccupancySensor.ino @@ -0,0 +1,128 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT 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 example is an example code that will create a Matter Device which can be + * commissioned and controlled from a Matter Environment APP. + * Additionally the ESP32 will send debug messages indicating the Matter activity. + * Turning DEBUG Level ON may be useful to following Matter Accessory and Controller messages. + * + * The example will create a Matter Occupancy Sensor Device. + * The Occupancy Sensor will be simulated to change its state every 2 minutes. + * + * The onboard button can be kept pressed for 5 seconds to decommission the Matter Node. + * The example will also show the manual commissioning code and QR code to be used in the Matter environment. + * + */ + +// Matter Manager +#include +#include + +// List of Matter Endpoints for this Node +// Matter Occupancy Sensor Endpoint +MatterOccupancySensor OccupancySensor; + +// WiFi is manually set and started +const char *ssid = "your-ssid"; // Change this to your WiFi SSID +const char *password = "your-password"; // Change this to your WiFi password + +// set your board USER BUTTON pin here - decommissioning only +const uint8_t buttonPin = BOOT_PIN; // Set your pin here. Using BOOT Button. + +// Button control +uint32_t button_time_stamp = 0; // debouncing control +bool button_state = false; // false = released | true = pressed +const uint32_t decommissioningTimeout = 5000; // keep the button pressed for 5s, or longer, to decommission + +void setup() { + // Initialize the USER BUTTON (Boot button) that will be used to decommission the Matter Node + pinMode(buttonPin, INPUT_PULLUP); + + Serial.begin(115200); + + // Manually connect to WiFi + WiFi.begin(ssid, password); + // Wait for connection + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(); + + // set initial occupancy sensor state as false and connected to a PIR sensor type (default) + OccupancySensor.begin(); + + // Matter beginning - Last step, after all EndPoints are initialized + Matter.begin(); + + // Check Matter Accessory Commissioning state, which may change during execution of loop() + if (!Matter.isDeviceCommissioned()) { + Serial.println(""); + Serial.println("Matter Node is not commissioned yet."); + Serial.println("Initiate the device discovery in your Matter environment."); + Serial.println("Commission it to your Matter hub with the manual pairing code or QR code"); + Serial.printf("Manual pairing code: %s\r\n", Matter.getManualPairingCode().c_str()); + Serial.printf("QR code URL: %s\r\n", Matter.getOnboardingQRCodeUrl().c_str()); + // waits for Matter Occupancy Sensor Commissioning. + uint32_t timeCount = 0; + while (!Matter.isDeviceCommissioned()) { + delay(100); + if ((timeCount++ % 50) == 0) { // 50*100ms = 5 sec + Serial.println("Matter Node not commissioned yet. Waiting for commissioning."); + } + } + Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use."); + } +} + +bool simulatedHWOccupancySensor() { + // Simulated Occupancy Sensor + static bool occupancyState = false; + static uint32_t lastTime = millis(); + const uint32_t occupancyTimeout = 120000; // 2 minutes to toggle the state + + // Simulate a Occupancy Sensor state change every 2 minutes + if (millis() - lastTime > occupancyTimeout) { + occupancyState = !occupancyState; + lastTime = millis(); + } + return occupancyState; +} + +void loop() { + // Check if the button has been pressed + if (digitalRead(buttonPin) == LOW && !button_state) { + // deals with button debouncing + button_time_stamp = millis(); // record the time while the button is pressed. + button_state = true; // pressed. + } + + if (button_state && digitalRead(buttonPin) == HIGH) { + button_state = false; // released + } + + // Onboard User Button is kept pressed for longer than 5 seconds in order to decommission matter node + uint32_t time_diff = millis() - button_time_stamp; + if (button_state && time_diff > decommissioningTimeout) { + Serial.println("Decommissioning the Generic Switch Matter Accessory. It shall be commissioned again."); + Matter.decommission(); + button_time_stamp = millis(); // avoid running decommissining again, reboot takes a second or so + } + + // Check Simulated Occupancy Sensor and set Matter Attribute + OccupancySensor.setOccupancy(simulatedHWOccupancySensor()); + + delay(50); +} diff --git a/libraries/Matter/examples/MatterOccupancySensor/ci.json b/libraries/Matter/examples/MatterOccupancySensor/ci.json new file mode 100644 index 00000000000..556a8a9ee6b --- /dev/null +++ b/libraries/Matter/examples/MatterOccupancySensor/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y" + ] +} diff --git a/libraries/Matter/examples/MatterOnIdentify/MatterOnIdentify.ino b/libraries/Matter/examples/MatterOnIdentify/MatterOnIdentify.ino new file mode 100644 index 00000000000..b2e77900e95 --- /dev/null +++ b/libraries/Matter/examples/MatterOnIdentify/MatterOnIdentify.ino @@ -0,0 +1,164 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT 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 example is the smallest code that will create a Matter Device which can be + * commissioned and controlled from a Matter Environment APP. + * It controls a GPIO that could be attached to a LED for visualization. + * Additionally the ESP32 will send debug messages indicating the Matter activity. + * Turning DEBUG Level ON may be useful to following Matter Accessory and Controller messages. + * + * This example is a simple Matter On/Off Light that can be controlled by a Matter Controller. + * It demonstrates how to use On Identify callback when the Identify Cluster is called. + * The Matter user APP can be used to request the device to identify itself by blinking the LED. + */ + +// Matter Manager +#include +#include + +// List of Matter Endpoints for this Node +// Single On/Off Light Endpoint - at least one per node +MatterOnOffLight OnOffLight; + +// WiFi is manually set and started +const char *ssid = "your-ssid"; // Change this to your WiFi SSID +const char *password = "your-password"; // Change this to your WiFi password + +// Light GPIO that can be controlled by Matter APP +#ifdef LED_BUILTIN +const uint8_t ledPin = LED_BUILTIN; +#else +const uint8_t ledPin = 2; // Set your pin here if your board has not defined LED_BUILTIN +#endif + +// set your board USER BUTTON pin here - decommissioning button +const uint8_t buttonPin = BOOT_PIN; // Set your pin here. Using BOOT Button. + +// Button control - decommision the Matter Node +uint32_t button_time_stamp = 0; // debouncing control +bool button_state = false; // false = released | true = pressed +const uint32_t decommissioningTimeout = 5000; // keep the button pressed for 5s, or longer, to decommission + +// Identify Flag and blink time - Blink the LED +const uint8_t identifyLedPin = ledPin; // uses the same LED as the Light - change if needed +volatile bool identifyFlag = false; // Flag to start the Blink when in Identify state +bool identifyBlink = false; // Blink state when in Identify state + +// Matter Protocol Endpoint (On/OFF Light) Callback +bool onOffLightCallback(bool state) { + digitalWrite(ledPin, state ? HIGH : LOW); + // This callback must return the success state to Matter core + return true; +} + +// Identification shall be done by Blink in Red or just the GPIO when no LED_BUILTIN is not defined +bool onIdentifyLightCallback(bool identifyIsActive) { + Serial.printf("Identify Cluster is %s\r\n", identifyIsActive ? "Active" : "Inactive"); + if (identifyIsActive) { + // Start Blinking the light in loop() + identifyFlag = true; + identifyBlink = !OnOffLight; // Start with the inverted light state + } else { + // Stop Blinking and restore the light to the its last state + identifyFlag = false; + // force returning to the original state by toggling the light twice + OnOffLight.toggle(); + OnOffLight.toggle(); + } + return true; +} + +void setup() { + // Initialize the USER BUTTON (Boot button) that will be used to decommission the Matter Node + pinMode(buttonPin, INPUT_PULLUP); + // Initialize the LED GPIO + pinMode(ledPin, OUTPUT); + + Serial.begin(115200); + + // Manually connect to WiFi + WiFi.begin(ssid, password); + // Wait for connection + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(); + + // Initialize at least one Matter EndPoint + OnOffLight.begin(); + + // On Identify Callback - Blink the LED + OnOffLight.onIdentify(onIdentifyLightCallback); + + // Associate a callback to the Matter Controller + OnOffLight.onChange(onOffLightCallback); + + // Matter beginning - Last step, after all EndPoints are initialized + Matter.begin(); + + // Check Matter Accessory Commissioning state, which may change during execution of loop() + if (!Matter.isDeviceCommissioned()) { + Serial.println(""); + Serial.println("Matter Node is not commissioned yet."); + Serial.println("Initiate the device discovery in your Matter environment."); + Serial.println("Commission it to your Matter hub with the manual pairing code or QR code"); + Serial.printf("Manual pairing code: %s\r\n", Matter.getManualPairingCode().c_str()); + Serial.printf("QR code URL: %s\r\n", Matter.getOnboardingQRCodeUrl().c_str()); + // waits for Matter Occupancy Sensor Commissioning. + uint32_t timeCount = 0; + while (!Matter.isDeviceCommissioned()) { + delay(100); + if ((timeCount++ % 50) == 0) { // 50*100ms = 5 sec + Serial.println("Matter Node not commissioned yet. Waiting for commissioning."); + } + } + Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use."); + } +} + +void loop() { + // check if the Light is in identify state and blink it every 500ms (delay loop time) + if (identifyFlag) { +#ifdef LED_BUILTIN + uint8_t brightness = 32 * identifyBlink; + rgbLedWrite(identifyLedPin, brightness, 0, 0); +#else + digitalWrite(identifyLedPin, identifyBlink ? HIGH : LOW); +#endif + identifyBlink = !identifyBlink; + } + + // Check if the button has been pressed + if (digitalRead(buttonPin) == LOW && !button_state) { + // deals with button debouncing + button_time_stamp = millis(); // record the time while the button is pressed. + button_state = true; // pressed. + } + + if (digitalRead(buttonPin) == HIGH && button_state) { + button_state = false; // released + } + + // Onboard User Button is kept pressed for longer than 5 seconds in order to decommission matter node + uint32_t time_diff = millis() - button_time_stamp; + if (button_state && time_diff > decommissioningTimeout) { + Serial.println("Decommissioning the Light Matter Accessory. It shall be commissioned again."); + Matter.decommission(); + button_time_stamp = millis(); // avoid running decommissining again, reboot takes a second or so + } + + delay(500); // works as a debounce for the button and also for the LED blink +} diff --git a/libraries/Matter/examples/MatterOnIdentify/ci.json b/libraries/Matter/examples/MatterOnIdentify/ci.json new file mode 100644 index 00000000000..556a8a9ee6b --- /dev/null +++ b/libraries/Matter/examples/MatterOnIdentify/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y" + ] +} diff --git a/libraries/Matter/examples/MatterOnOffLight/MatterOnOffLight.ino b/libraries/Matter/examples/MatterOnOffLight/MatterOnOffLight.ino index c7b8757f37b..5faa0a385b0 100644 --- a/libraries/Matter/examples/MatterOnOffLight/MatterOnOffLight.ino +++ b/libraries/Matter/examples/MatterOnOffLight/MatterOnOffLight.ino @@ -17,6 +17,10 @@ #include #include +// WiFi is manually set and started +const char *ssid = "your-ssid"; // Change this to your WiFi SSID +const char *password = "your-password"; // Change this to your WiFi password + // List of Matter Endpoints for this Node // On/Off Light Endpoint MatterOnOffLight OnOffLight; @@ -42,10 +46,6 @@ bool button_state = false; // false = released | true = pres const uint32_t debouceTime = 250; // button debouncing time (ms) const uint32_t decommissioningTimeout = 5000; // keep the button pressed for 5s, or longer, to decommission -// WiFi is manually set and started -const char *ssid = "your-ssid"; // Change this to your WiFi SSID -const char *password = "your-password"; // Change this to your WiFi password - // Matter Protocol Endpoint Callback bool setLightOnOff(bool state) { Serial.printf("User Callback :: New Light State = %s\r\n", state ? "ON" : "OFF"); @@ -67,15 +67,10 @@ void setup() { pinMode(ledPin, OUTPUT); Serial.begin(115200); - while (!Serial) { - delay(100); - } // We start by connecting to a WiFi network Serial.print("Connecting to "); Serial.println(ssid); - // enable IPv6 - WiFi.enableIPv6(true); // Manually connect to WiFi WiFi.begin(ssid, password); // Wait for connection diff --git a/libraries/Matter/examples/MatterOnOffPlugin/MatterOnOffPlugin.ino b/libraries/Matter/examples/MatterOnOffPlugin/MatterOnOffPlugin.ino new file mode 100644 index 00000000000..d14e2189ec1 --- /dev/null +++ b/libraries/Matter/examples/MatterOnOffPlugin/MatterOnOffPlugin.ino @@ -0,0 +1,142 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Matter Manager +#include +#include +#include + +// List of Matter Endpoints for this Node +// On/Off Plugin Endpoint +MatterOnOffPlugin OnOffPlugin; + +// WiFi is manually set and started +const char *ssid = "your-ssid"; // Change this to your WiFi SSID +const char *password = "your-password"; // Change this to your WiFi password + +// it will keep last OnOff state stored, using Preferences +Preferences matterPref; +const char *onOffPrefKey = "OnOff"; + +// set your board Power Relay pin here - this example uses the built-in LED for easy visualization +#ifdef LED_BUILTIN +const uint8_t onoffPin = LED_BUILTIN; +#else +const uint8_t onoffPin = 2; // Set your pin here - usually a power relay +#warning "Do not forget to set the Power Relay pin" +#endif + +// board USER BUTTON pin necessary for Decommissioning +const uint8_t buttonPin = BOOT_PIN; // Set your pin here. Using BOOT Button. + +// Button control +uint32_t button_time_stamp = 0; // debouncing control +bool button_state = false; // false = released | true = pressed +const uint32_t decommissioningTimeout = 5000; // keep the button pressed for 5s, or longer, to decommission + +// Matter Protocol Endpoint Callback +bool setPluginOnOff(bool state) { + Serial.printf("User Callback :: New Plugin State = %s\r\n", state ? "ON" : "OFF"); + if (state) { + digitalWrite(onoffPin, HIGH); + } else { + digitalWrite(onoffPin, LOW); + } + // store last OnOff state for when the Plugin is restarted / power goes off + matterPref.putBool(onOffPrefKey, state); + // This callback must return the success state to Matter core + return true; +} + +void setup() { + // Initialize the USER BUTTON + pinMode(buttonPin, INPUT_PULLUP); + // Initialize the Power Relay (plugin) GPIO + pinMode(onoffPin, OUTPUT); + + Serial.begin(115200); + + // We start by connecting to a WiFi network + Serial.print("Connecting to "); + Serial.println(ssid); + WiFi.begin(ssid, password); + // Wait for connection + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println("\r\nWiFi connected"); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); + delay(500); + + // Initialize Matter EndPoint + matterPref.begin("MatterPrefs", false); + bool lastOnOffState = matterPref.getBool(onOffPrefKey, false); + OnOffPlugin.begin(lastOnOffState); + OnOffPlugin.onChange(setPluginOnOff); + + // Matter beginning - Last step, after all EndPoints are initialized + Matter.begin(); + // This may be a restart of a already commissioned Matter accessory + if (Matter.isDeviceCommissioned()) { + Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use."); + Serial.printf("Initial state: %s\r\n", OnOffPlugin.getOnOff() ? "ON" : "OFF"); + OnOffPlugin.updateAccessory(); // configure the Plugin based on initial state + } +} + +void loop() { + // Check Matter Plugin Commissioning state, which may change during execution of loop() + if (!Matter.isDeviceCommissioned()) { + Serial.println(""); + Serial.println("Matter Node is not commissioned yet."); + Serial.println("Initiate the device discovery in your Matter environment."); + Serial.println("Commission it to your Matter hub with the manual pairing code or QR code"); + Serial.printf("Manual pairing code: %s\r\n", Matter.getManualPairingCode().c_str()); + Serial.printf("QR code URL: %s\r\n", Matter.getOnboardingQRCodeUrl().c_str()); + // waits for Matter Plugin Commissioning. + uint32_t timeCount = 0; + while (!Matter.isDeviceCommissioned()) { + delay(100); + if ((timeCount++ % 50) == 0) { // 50*100ms = 5 sec + Serial.println("Matter Node not commissioned yet. Waiting for commissioning."); + } + } + Serial.printf("Initial state: %s\r\n", OnOffPlugin.getOnOff() ? "ON" : "OFF"); + OnOffPlugin.updateAccessory(); // configure the Plugin based on initial state + Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use."); + } + + // Check if the button has been pressed + if (digitalRead(buttonPin) == LOW && !button_state) { + // deals with button debouncing + button_time_stamp = millis(); // record the time while the button is pressed. + button_state = true; // pressed. + } + + // Onboard User Button is used to decommission the Matter Node + if (button_state && digitalRead(buttonPin) == HIGH) { + button_state = false; // released + } + + // Onboard User Button is kept pressed for longer than 5 seconds in order to decommission matter node + uint32_t time_diff = millis() - button_time_stamp; + if (button_state && time_diff > decommissioningTimeout) { + Serial.println("Decommissioning the Plugin Matter Accessory. It shall be commissioned again."); + OnOffPlugin.setOnOff(false); // turn the plugin off + Matter.decommission(); + button_time_stamp = millis(); // avoid running decommissining again, reboot takes a second or so + } +} diff --git a/libraries/Matter/examples/MatterOnOffPlugin/ci.json b/libraries/Matter/examples/MatterOnOffPlugin/ci.json new file mode 100644 index 00000000000..556a8a9ee6b --- /dev/null +++ b/libraries/Matter/examples/MatterOnOffPlugin/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y" + ] +} diff --git a/libraries/Matter/examples/MatterPressureSensor/MatterPressureSensor.ino b/libraries/Matter/examples/MatterPressureSensor/MatterPressureSensor.ino index aa6b28f199f..394a217b87a 100644 --- a/libraries/Matter/examples/MatterPressureSensor/MatterPressureSensor.ino +++ b/libraries/Matter/examples/MatterPressureSensor/MatterPressureSensor.ino @@ -27,13 +27,13 @@ // Matter Pressure Sensor Endpoint MatterPressureSensor SimulatedPressureSensor; -// set your board USER BUTTON pin here - decommissioning button -const uint8_t buttonPin = BOOT_PIN; // Set your pin here. Using BOOT Button. - // WiFi is manually set and started const char *ssid = "your-ssid"; // Change this to your WiFi SSID const char *password = "your-password"; // Change this to your WiFi password +// set your board USER BUTTON pin here - decommissioning button +const uint8_t buttonPin = BOOT_PIN; // Set your pin here. Using BOOT Button. + // Button control - decommision the Matter Node uint32_t button_time_stamp = 0; // debouncing control bool button_state = false; // false = released | true = pressed diff --git a/libraries/Matter/examples/MatterSmartButon/MatterSmartButon.ino b/libraries/Matter/examples/MatterSmartButon/MatterSmartButon.ino index 929c13c1663..f8da970595d 100644 --- a/libraries/Matter/examples/MatterSmartButon/MatterSmartButon.ino +++ b/libraries/Matter/examples/MatterSmartButon/MatterSmartButon.ino @@ -20,6 +20,10 @@ // Generic Switch Endpoint - works as a smart button with a single click MatterGenericSwitch SmartButton; +// WiFi is manually set and started +const char *ssid = "your-ssid"; // Change this to your WiFi SSID +const char *password = "your-password"; // Change this to your WiFi password + // set your board USER BUTTON pin here const uint8_t buttonPin = BOOT_PIN; // Set your pin here. Using BOOT Button. @@ -29,24 +33,16 @@ bool button_state = false; // false = released | true = pres const uint32_t debouceTime = 250; // button debouncing time (ms) const uint32_t decommissioningTimeout = 5000; // keep the button pressed for 5s, or longer, to decommission -// WiFi is manually set and started -const char *ssid = "your-ssid"; // Change this to your WiFi SSID -const char *password = "your-password"; // Change this to your WiFi password - void setup() { // Initialize the USER BUTTON (Boot button) GPIO that will act as a smart button or to decommission the Matter Node pinMode(buttonPin, INPUT_PULLUP); Serial.begin(115200); - while (!Serial) { - delay(100); - } // We start by connecting to a WiFi network Serial.print("Connecting to "); Serial.println(ssid); - // enable IPv6 - WiFi.enableIPv6(true); + // Manually connect to WiFi WiFi.begin(ssid, password); // Wait for connection diff --git a/libraries/Matter/examples/MatterTemperatureLight/MatterTemperatureLight.ino b/libraries/Matter/examples/MatterTemperatureLight/MatterTemperatureLight.ino index 7937303de54..b814ba89704 100644 --- a/libraries/Matter/examples/MatterTemperatureLight/MatterTemperatureLight.ino +++ b/libraries/Matter/examples/MatterTemperatureLight/MatterTemperatureLight.ino @@ -21,6 +21,10 @@ // Color Temperature CW/WW Light Endpoint MatterColorTemperatureLight CW_WW_Light; +// WiFi is manually set and started +const char *ssid = "your-ssid"; // Change this to your WiFi SSID +const char *password = "your-password"; // Change this to your WiFi password + // it will keep last OnOff & Brightness state stored, using Preferences Preferences matterPref; const char *onOffPrefKey = "OnOff"; @@ -44,10 +48,6 @@ bool button_state = false; // false = released | true = pres const uint32_t debouceTime = 250; // button debouncing time (ms) const uint32_t decommissioningTimeout = 5000; // keep the button pressed for 5s, or longer, to decommission -// WiFi is manually set and started -const char *ssid = "your-ssid"; // Change this to your WiFi SSID -const char *password = "your-password"; // Change this to your WiFi password - // Set the RGB LED Light based on the current state of the Color Temperature Light bool setLightState(bool state, uint8_t brightness, uint16_t temperature_Mireds) { @@ -83,15 +83,10 @@ void setup() { pinMode(ledPin, OUTPUT); Serial.begin(115200); - while (!Serial) { - delay(100); - } // We start by connecting to a WiFi network Serial.print("Connecting to "); Serial.println(ssid); - // enable IPv6 - WiFi.enableIPv6(true); // Manually connect to WiFi WiFi.begin(ssid, password); // Wait for connection diff --git a/libraries/Matter/examples/MatterTemperatureSensor/MatterTemperatureSensor.ino b/libraries/Matter/examples/MatterTemperatureSensor/MatterTemperatureSensor.ino index 86055be26ee..e8513f12aaa 100644 --- a/libraries/Matter/examples/MatterTemperatureSensor/MatterTemperatureSensor.ino +++ b/libraries/Matter/examples/MatterTemperatureSensor/MatterTemperatureSensor.ino @@ -27,6 +27,10 @@ // Matter Temperature Sensor Endpoint MatterTemperatureSensor SimulatedTemperatureSensor; +// WiFi is manually set and started +const char *ssid = "your-ssid"; // Change this to your WiFi SSID +const char *password = "your-password"; // Change this to your WiFi password + // set your board USER BUTTON pin here - decommissioning button const uint8_t buttonPin = BOOT_PIN; // Set your pin here. Using BOOT Button. @@ -35,10 +39,6 @@ uint32_t button_time_stamp = 0; // debouncing control bool button_state = false; // false = released | true = pressed const uint32_t decommissioningTimeout = 5000; // keep the button pressed for 5s, or longer, to decommission -// WiFi is manually set and started -const char *ssid = "your-ssid"; // Change this to your WiFi SSID -const char *password = "your-password"; // Change this to your WiFi password - // Simulate a temperature sensor - add your preferred temperature sensor library code here float getSimulatedTemperature() { // The Endpoint implementation keeps an int16_t as internal value information, diff --git a/libraries/Matter/keywords.txt b/libraries/Matter/keywords.txt index d75e9888afd..3f40e598ada 100644 --- a/libraries/Matter/keywords.txt +++ b/libraries/Matter/keywords.txt @@ -22,6 +22,8 @@ MatterTemperatureSensor KEYWORD1 MatterHumiditySensor KEYWORD1 MatterContactSensor KEYWORD1 MatterPressureSensor KEYWORD1 +MatterOccupancySensor KEYWORD1 +MatterOnOffPlugin KEYWORD1 ####################################### # Methods and Functions (KEYWORD2) @@ -74,6 +76,8 @@ setContact KEYWORD2 getContact KEYWORD2 setPressure KEYWORD2 getPressure KEYWORD2 +setOccupancy KEYWORD2 +getOccupancy KEYWORD2 ####################################### # Constants (LITERAL1) diff --git a/libraries/Matter/src/Matter.cpp b/libraries/Matter/src/Matter.cpp index 89ef87b4db3..af7c4c8657e 100644 --- a/libraries/Matter/src/Matter.cpp +++ b/libraries/Matter/src/Matter.cpp @@ -21,6 +21,7 @@ using namespace esp_matter; using namespace esp_matter::attribute; using namespace esp_matter::endpoint; +using namespace esp_matter::identification; using namespace chip::app::Clusters; constexpr auto k_timeout_seconds = 300; @@ -29,11 +30,6 @@ static bool _matter_has_started = false; static node::config_t node_config; static node_t *deviceNode = NULL; -typedef void *app_driver_handle_t; -esp_err_t matter_light_attribute_update( - app_driver_handle_t driver_handle, uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val -); - // This callback is called for every attribute update. The callback implementation shall // handle the desired attributes and return an appropriate error code. If the attribute // is not of your interest, please do not return an error code and strictly return ESP_OK. @@ -67,8 +63,26 @@ static esp_err_t app_attribute_update_cb( // This callback is invoked when clients interact with the Identify Cluster. // In the callback implementation, an endpoint can identify itself. (e.g., by flashing an LED or light). static esp_err_t app_identification_cb(identification::callback_type_t type, uint16_t endpoint_id, uint8_t effect_id, uint8_t effect_variant, void *priv_data) { - log_i("Identification callback: type: %u, effect: %u, variant: %u", type, effect_id, effect_variant); - return ESP_OK; + log_d("Identification callback to endpoint %d: type: %u, effect: %u, variant: %u", endpoint_id, type, effect_id, effect_variant); + esp_err_t err = ESP_OK; + MatterEndPoint *ep = (MatterEndPoint *)priv_data; // endpoint pointer to base class + // Identify the endpoint sending a counter to the application + bool identifyIsActive = false; + + if (type == identification::callback_type_t::START) { + log_v("Identification callback: START"); + identifyIsActive = true; + } else if (type == identification::callback_type_t::EFFECT) { + log_v("Identification callback: EFFECT"); + } else if (type == identification::callback_type_t::STOP) { + identifyIsActive = false; + log_v("Identification callback: STOP"); + } + if (ep != NULL) { + err = ep->endpointIdentifyCB(endpoint_id, identifyIsActive) ? ESP_OK : ESP_FAIL; + } + + return err; } // This callback is invoked for all Matter events. The application can handle the events as required. diff --git a/libraries/Matter/src/Matter.h b/libraries/Matter/src/Matter.h index 02571dbcf40..7fcab363f11 100644 --- a/libraries/Matter/src/Matter.h +++ b/libraries/Matter/src/Matter.h @@ -30,6 +30,8 @@ #include #include #include +#include +#include using namespace esp_matter; @@ -66,6 +68,8 @@ class ArduinoMatter { friend class MatterHumiditySensor; friend class MatterContactSensor; friend class MatterPressureSensor; + friend class MatterOccupancySensor; + friend class MatterOnOffPlugin; protected: static void _init(); diff --git a/libraries/Matter/src/MatterEndPoint.h b/libraries/Matter/src/MatterEndPoint.h index 99bff8470d3..6f99aa7cd33 100644 --- a/libraries/Matter/src/MatterEndPoint.h +++ b/libraries/Matter/src/MatterEndPoint.h @@ -102,7 +102,21 @@ class MatterEndPoint { // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. virtual bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) = 0; + // This callback is invoked when clients interact with the Identify Cluster of an specific endpoint. + bool endpointIdentifyCB(uint16_t endpoint_id, bool identifyIsEnabled) { + if (_onEndPointIdentifyCB) { + return _onEndPointIdentifyCB(identifyIsEnabled); + } + return true; + } + // User callaback for the Identify Cluster functionality + using EndPointIdentifyCB = std::function; + void onIdentify(EndPointIdentifyCB onEndPointIdentifyCB) { + _onEndPointIdentifyCB = onEndPointIdentifyCB; + } + protected: uint16_t endpoint_id = 0; + EndPointIdentifyCB _onEndPointIdentifyCB = NULL; }; #endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterColorLight.cpp b/libraries/Matter/src/MatterEndpoints/MatterColorLight.cpp index b67cf6a23b1..eaaf0bf2ffe 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterColorLight.cpp +++ b/libraries/Matter/src/MatterEndpoints/MatterColorLight.cpp @@ -162,8 +162,13 @@ MatterColorLight::~MatterColorLight() { bool MatterColorLight::begin(bool initialState, espHsvColor_t _colorHSV) { ArduinoMatter::_init(); - rgb_color_light::config_t light_config; + if (getEndPointId() != 0) { + log_e("Matter RGB Color Light with Endpoint Id %d device has already been created.", getEndPointId()); + return false; + } + + rgb_color_light::config_t light_config; light_config.on_off.on_off = initialState; light_config.on_off.lighting.start_up_on_off = nullptr; onOffState = initialState; @@ -206,7 +211,7 @@ bool MatterColorLight::setOnOff(bool newState) { return false; } - // avoid processing the a "no-change" + // avoid processing if there was no change if (onOffState == newState) { return true; } @@ -256,7 +261,7 @@ bool MatterColorLight::setColorHSV(espHsvColor_t _hsvColor) { return false; } - // avoid processing the a "no-change" + // avoid processing if there was no change if (colorHSV.h == _hsvColor.h && colorHSV.s == _hsvColor.s && colorHSV.v == _hsvColor.v) { return true; } diff --git a/libraries/Matter/src/MatterEndpoints/MatterColorLight.h b/libraries/Matter/src/MatterEndpoints/MatterColorLight.h index 13ff0decbc2..b896afa9b7a 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterColorLight.h +++ b/libraries/Matter/src/MatterEndpoints/MatterColorLight.h @@ -37,16 +37,6 @@ class MatterColorLight : public MatterEndPoint { bool setColorHSV(espHsvColor_t hsvColor); // returns true if successful espHsvColor_t getColorHSV(); // returns current HSV Color - // used to update the state of the light using the current Matter Light internal state - // It is necessary to set a user callback function using onChange() to handle the physical light state - void updateAccessory(); - - operator bool(); // returns current on/off light state - void operator=(bool state); // turns light on or off - - // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. - bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); - // User Callback for whenever the Light On/Off state is changed by the Matter Controller using EndPointOnOffCB = std::function; void onChangeOnOff(EndPointOnOffCB onChangeCB) { @@ -64,6 +54,16 @@ class MatterColorLight : public MatterEndPoint { _onChangeCB = onChangeCB; } + // used to update the state of the light using the current Matter Light internal state + // It is necessary to set a user callback function using onChange() to handle the physical light state + void updateAccessory(); + + operator bool(); // returns current on/off light state + void operator=(bool state); // turns light on or off + + // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. + bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); + protected: bool started = false; bool onOffState = false; // default initial state is off, but it can be changed by begin(bool) diff --git a/libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.cpp b/libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.cpp index 7bbcb83dcfe..5ef69749bb1 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.cpp +++ b/libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.cpp @@ -26,17 +26,17 @@ using namespace chip::app::Clusters; bool MatterColorTemperatureLight::attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) { bool ret = true; if (!started) { - log_e("Matter CW_WW Light device has not begun."); + log_e("Matter Temperature Light device has not begun."); return false; } - log_d("CW_WW Attr update callback: endpoint: %u, cluster: %u, attribute: %u, val: %u", endpoint_id, cluster_id, attribute_id, val->val.u32); + log_d("Temperature Attr update callback: endpoint: %u, cluster: %u, attribute: %u, val: %u", endpoint_id, cluster_id, attribute_id, val->val.u32); if (endpoint_id == getEndPointId()) { switch (cluster_id) { case OnOff::Id: if (attribute_id == OnOff::Attributes::OnOff::Id) { - log_d("CW_WW Light On/Off State changed to %d", val->val.b); + log_d("Temperature Light On/Off State changed to %d", val->val.b); if (_onChangeOnOffCB != NULL) { ret &= _onChangeOnOffCB(val->val.b); } @@ -50,7 +50,7 @@ bool MatterColorTemperatureLight::attributeChangeCB(uint16_t endpoint_id, uint32 break; case LevelControl::Id: if (attribute_id == LevelControl::Attributes::CurrentLevel::Id) { - log_d("CW_WW Light Brightness changed to %d", val->val.u8); + log_d("Temperature Light Brightness changed to %d", val->val.u8); if (_onChangeBrightnessCB != NULL) { ret &= _onChangeBrightnessCB(val->val.u8); } @@ -64,7 +64,7 @@ bool MatterColorTemperatureLight::attributeChangeCB(uint16_t endpoint_id, uint32 break; case ColorControl::Id: if (attribute_id == ColorControl::Attributes::ColorTemperatureMireds::Id) { - log_d("CW_WW Light Temperature changed to %d", val->val.u16); + log_d("Temperature Light Temperature changed to %d", val->val.u16); if (_onChangeTemperatureCB != NULL) { ret &= _onChangeTemperatureCB(val->val.u16); } @@ -89,8 +89,13 @@ MatterColorTemperatureLight::~MatterColorTemperatureLight() { bool MatterColorTemperatureLight::begin(bool initialState, uint8_t brightness, uint16_t ColorTemperature) { ArduinoMatter::_init(); - color_temperature_light::config_t light_config; + if (getEndPointId() != 0) { + log_e("Matter Temperature Light with Endpoint Id %d device has already been created.", getEndPointId()); + return false; + } + + color_temperature_light::config_t light_config; light_config.on_off.on_off = initialState; light_config.on_off.lighting.start_up_on_off = nullptr; onOffState = initialState; @@ -108,12 +113,12 @@ bool MatterColorTemperatureLight::begin(bool initialState, uint8_t brightness, u // endpoint handles can be used to add/modify clusters. endpoint_t *endpoint = color_temperature_light::create(node::get(), &light_config, ENDPOINT_FLAG_NONE, (void *)this); if (endpoint == nullptr) { - log_e("Failed to create CW_WW light endpoint"); + log_e("Failed to create Temperature Light endpoint"); return false; } setEndPointId(endpoint::get_id(endpoint)); - log_i("CW_WW Light created with endpoint_id %d", getEndPointId()); + log_i("Temperature Light created with endpoint_id %d", getEndPointId()); /* Mark deferred persistence for some attributes that might be changed rapidly */ cluster_t *level_control_cluster = cluster::get(endpoint, LevelControl::Id); @@ -134,11 +139,11 @@ void MatterColorTemperatureLight::end() { bool MatterColorTemperatureLight::setOnOff(bool newState) { if (!started) { - log_e("Matter CW_WW Light device has not begun."); + log_e("Matter Temperature Light device has not begun."); return false; } - // avoid processing the a "no-change" + // avoid processing if there was no change if (onOffState == newState) { return true; } @@ -175,11 +180,11 @@ bool MatterColorTemperatureLight::toggle() { bool MatterColorTemperatureLight::setBrightness(uint8_t newBrightness) { if (!started) { - log_w("Matter CW_WW Light device has not begun."); + log_w("Matter Temperature Light device has not begun."); return false; } - // avoid processing the a "no-change" + // avoid processing if there was no change if (brightnessLevel == newBrightness) { return true; } @@ -206,11 +211,11 @@ uint8_t MatterColorTemperatureLight::getBrightness() { bool MatterColorTemperatureLight::setColorTemperature(uint16_t newTemperature) { if (!started) { - log_w("Matter CW_WW Light device has not begun."); + log_w("Matter Temperature Light device has not begun."); return false; } - // avoid processing the a "no-change" + // avoid processing if there was no change if (colorTemperatureLevel == newTemperature) { return true; } diff --git a/libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.h b/libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.h index e886a184182..539bc386e92 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.h +++ b/libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.h @@ -42,16 +42,6 @@ class MatterColorTemperatureLight : public MatterEndPoint { bool setColorTemperature(uint16_t newTemperature); // returns true if successful uint16_t getColorTemperature(); // returns current temperature - // used to update the state of the light using the current Matter Light internal state - // It is necessary to set a user callback function using onChange() to handle the physical light state - void updateAccessory(); - - operator bool(); // returns current on/off light state - void operator=(bool state); // turns light on or off - - // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. - bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); - // User Callback for whenever the Light On/Off state is changed by the Matter Controller using EndPointOnOffCB = std::function; void onChangeOnOff(EndPointOnOffCB onChangeCB) { @@ -76,6 +66,16 @@ class MatterColorTemperatureLight : public MatterEndPoint { _onChangeCB = onChangeCB; } + // used to update the state of the light using the current Matter Light internal state + // It is necessary to set a user callback function using onChange() to handle the physical light state + void updateAccessory(); + + operator bool(); // returns current on/off light state + void operator=(bool state); // turns light on or off + + // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. + bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); + protected: bool started = false; bool onOffState = false; // default initial state is off, but it can be changed by begin(bool) diff --git a/libraries/Matter/src/MatterEndpoints/MatterContactSensor.cpp b/libraries/Matter/src/MatterEndpoints/MatterContactSensor.cpp index 44ba1c75a44..17b0fe7a247 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterContactSensor.cpp +++ b/libraries/Matter/src/MatterEndpoints/MatterContactSensor.cpp @@ -43,6 +43,11 @@ MatterContactSensor::~MatterContactSensor() { bool MatterContactSensor::begin(bool _contactState) { ArduinoMatter::_init(); + if (getEndPointId() != 0) { + log_e("Matter Contact Sensor with Endpoint Id %d device has already been created.", getEndPointId()); + return false; + } + contact_sensor::config_t contact_sensor_config; contact_sensor_config.boolean_state.state_value = _contactState; @@ -69,7 +74,7 @@ bool MatterContactSensor::setContact(bool _contactState) { return false; } - // avoid processing the a "no-change" + // avoid processing if there was no change if (contactState == _contactState) { return true; } diff --git a/libraries/Matter/src/MatterEndpoints/MatterDimmableLight.cpp b/libraries/Matter/src/MatterEndpoints/MatterDimmableLight.cpp index c3991e0c0f3..9f6f872ca3e 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterDimmableLight.cpp +++ b/libraries/Matter/src/MatterEndpoints/MatterDimmableLight.cpp @@ -75,8 +75,12 @@ MatterDimmableLight::~MatterDimmableLight() { bool MatterDimmableLight::begin(bool initialState, uint8_t brightness) { ArduinoMatter::_init(); - dimmable_light::config_t light_config; + if (getEndPointId() != 0) { + log_e("Matter Dimmable Light with Endpoint Id %d device has already been created.", getEndPointId()); + return false; + } + dimmable_light::config_t light_config; light_config.on_off.on_off = initialState; light_config.on_off.lighting.start_up_on_off = nullptr; onOffState = initialState; @@ -114,7 +118,7 @@ bool MatterDimmableLight::setOnOff(bool newState) { return false; } - // avoid processing the a "no-change" + // avoid processing if there was no change if (onOffState == newState) { return true; } @@ -155,7 +159,7 @@ bool MatterDimmableLight::setBrightness(uint8_t newBrightness) { return false; } - // avoid processing the a "no-change" + // avoid processing if there was no change if (brightnessLevel == newBrightness) { return true; } diff --git a/libraries/Matter/src/MatterEndpoints/MatterDimmableLight.h b/libraries/Matter/src/MatterEndpoints/MatterDimmableLight.h index aacce883277..4497edd2fe2 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterDimmableLight.h +++ b/libraries/Matter/src/MatterEndpoints/MatterDimmableLight.h @@ -37,19 +37,12 @@ class MatterDimmableLight : public MatterEndPoint { bool setBrightness(uint8_t newBrightness); // returns true if successful uint8_t getBrightness(); // returns current brightness - // used to update the state of the light using the current Matter Light internal state - // It is necessary to set a user callback function using onChange() to handle the physical light state - void updateAccessory(); - - operator bool(); // returns current on/off light state - void operator=(bool state); // turns light on or off - // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. - bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); // User Callback for whenever the Light On/Off state is changed by the Matter Controller using EndPointOnOffCB = std::function; void onChangeOnOff(EndPointOnOffCB onChangeCB) { _onChangeOnOffCB = onChangeCB; } + // User Callback for whenever the Light brightness value [0..255] is changed by the Matter Controller using EndPointBrightnessCB = std::function; void onChangeBrightness(EndPointBrightnessCB onChangeCB) { @@ -62,6 +55,15 @@ class MatterDimmableLight : public MatterEndPoint { _onChangeCB = onChangeCB; } + // used to update the state of the light using the current Matter Light internal state + // It is necessary to set a user callback function using onChange() to handle the physical light state + void updateAccessory(); + + operator bool(); // returns current on/off light state + void operator=(bool state); // turns light on or off + // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. + bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); + protected: bool started = false; bool onOffState = false; // default initial state is off, but it can be changed by begin(bool) diff --git a/libraries/Matter/src/MatterEndpoints/MatterEnhancedColorLight.cpp b/libraries/Matter/src/MatterEndpoints/MatterEnhancedColorLight.cpp index 423a6a7d2ef..022e62654df 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterEnhancedColorLight.cpp +++ b/libraries/Matter/src/MatterEndpoints/MatterEnhancedColorLight.cpp @@ -178,8 +178,13 @@ MatterEnhancedColorLight::~MatterEnhancedColorLight() { bool MatterEnhancedColorLight::begin(bool initialState, espHsvColor_t _colorHSV, uint8_t brightness, uint16_t ColorTemperature) { ArduinoMatter::_init(); - enhanced_color_light::config_t light_config; + if (getEndPointId() != 0) { + log_e("Matter Enhanced ColorLight with Endpoint Id %d device has already been created.", getEndPointId()); + return false; + } + + enhanced_color_light::config_t light_config; light_config.on_off.on_off = initialState; light_config.on_off.lighting.start_up_on_off = nullptr; onOffState = initialState; @@ -226,7 +231,7 @@ bool MatterEnhancedColorLight::setOnOff(bool newState) { return false; } - // avoid processing the a "no-change" + // avoid processing if there was no change if (onOffState == newState) { return true; } @@ -267,7 +272,7 @@ bool MatterEnhancedColorLight::setBrightness(uint8_t newBrightness) { return false; } - // avoid processing the a "no-change" + // avoid processing if there was no change if (brightnessLevel == newBrightness) { return true; } @@ -298,7 +303,7 @@ bool MatterEnhancedColorLight::setColorTemperature(uint16_t newTemperature) { return false; } - // avoid processing the a "no-change" + // avoid processing if there was no change if (colorTemperatureLevel == newTemperature) { return true; } @@ -338,7 +343,7 @@ bool MatterEnhancedColorLight::setColorHSV(espHsvColor_t _hsvColor) { return false; } - // avoid processing the a "no-change" + // avoid processing if there was no change if (colorHSV.h == _hsvColor.h && colorHSV.s == _hsvColor.s && colorHSV.v == _hsvColor.v) { return true; } diff --git a/libraries/Matter/src/MatterEndpoints/MatterEnhancedColorLight.h b/libraries/Matter/src/MatterEndpoints/MatterEnhancedColorLight.h index 66ed1943b8d..ff6e69e3e65 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterEnhancedColorLight.h +++ b/libraries/Matter/src/MatterEndpoints/MatterEnhancedColorLight.h @@ -47,16 +47,6 @@ class MatterEnhancedColorLight : public MatterEndPoint { bool setColorHSV(espHsvColor_t hsvColor); // returns true if successful espHsvColor_t getColorHSV(); // returns current HSV Color - // used to update the state of the light using the current Matter Light internal state - // It is necessary to set a user callback function using onChange() to handle the physical light state - void updateAccessory(); - - operator bool(); // returns current on/off light state - void operator=(bool state); // turns light on or off - - // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. - bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); - // User Callback for whenever the Light On/Off state is changed by the Matter Controller using EndPointOnOffCB = std::function; void onChangeOnOff(EndPointOnOffCB onChangeCB) { @@ -87,6 +77,16 @@ class MatterEnhancedColorLight : public MatterEndPoint { _onChangeCB = onChangeCB; } + // used to update the state of the light using the current Matter Light internal state + // It is necessary to set a user callback function using onChange() to handle the physical light state + void updateAccessory(); + + operator bool(); // returns current on/off light state + void operator=(bool state); // turns light on or off + + // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. + bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); + protected: bool started = false; bool onOffState = false; // default initial state is off, but it can be changed by begin(bool) diff --git a/libraries/Matter/src/MatterEndpoints/MatterFan.cpp b/libraries/Matter/src/MatterEndpoints/MatterFan.cpp index 8db6a317ead..1647490aa05 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterFan.cpp +++ b/libraries/Matter/src/MatterEndpoints/MatterFan.cpp @@ -85,6 +85,11 @@ bool MatterFan::attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uin bool MatterFan::begin(uint8_t percent, FanMode_t fanMode, FanModeSequence_t fanModeSeq) { ArduinoMatter::_init(); + if (getEndPointId() != 0) { + log_e("Matter Fan with Endpoint Id %d device has already been created.", getEndPointId()); + return false; + } + // endpoint handles can be used to add/modify clusters. fan::config_t fan_config; fan_config.fan_control.fan_mode = fanMode; @@ -118,7 +123,7 @@ bool MatterFan::setMode(FanMode_t newMode, bool performUpdate) { log_w("Matter Fan device has not begun."); return false; } - // avoid processing the a "no-change" + // avoid processing if there was no change if (currentFanMode == newMode) { return true; } @@ -159,7 +164,7 @@ bool MatterFan::setSpeedPercent(uint8_t newPercent, bool performUpdate) { log_w("Matter Fan device has not begun."); return false; } - // avoid processing the a "no-change" + // avoid processing if there was no change if (currentPercent == newPercent) { return true; } @@ -193,7 +198,7 @@ bool MatterFan::setOnOff(bool newState, bool performUpdate) { log_w("Matter Fan device has not begun."); return false; } - // avoid processing the a "no-change" + // avoid processing if there was no change if (getOnOff() == newState) { return true; } diff --git a/libraries/Matter/src/MatterEndpoints/MatterFan.h b/libraries/Matter/src/MatterEndpoints/MatterFan.h index 232577b7bef..a1cd6e42423 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterFan.h +++ b/libraries/Matter/src/MatterEndpoints/MatterFan.h @@ -98,13 +98,6 @@ class MatterFan : public MatterEndPoint { operator uint8_t() { return getSpeedPercent(); } - // sets Fan speed percent - void operator=(uint8_t speedPercent) { - setSpeedPercent(speedPercent); - } - - // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. - bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); // User Callback for whenever the Fan Mode (state) is changed by the Matter Controller using EndPointModeCB = std::function; @@ -124,6 +117,14 @@ class MatterFan : public MatterEndPoint { _onChangeCB = onChangeCB; } + // sets Fan speed percent + void operator=(uint8_t speedPercent) { + setSpeedPercent(speedPercent); + } + + // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. + bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); + protected: bool started = false; uint8_t validFanModes = 0; // bitmap for valid Fan Modes - index of fanModeSequence[] diff --git a/libraries/Matter/src/MatterEndpoints/MatterGenericSwitch.cpp b/libraries/Matter/src/MatterEndpoints/MatterGenericSwitch.cpp index bbf72af0a95..e20479af088 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterGenericSwitch.cpp +++ b/libraries/Matter/src/MatterEndpoints/MatterGenericSwitch.cpp @@ -42,12 +42,17 @@ bool MatterGenericSwitch::attributeChangeCB(uint16_t endpoint_id, uint32_t clust bool MatterGenericSwitch::begin() { ArduinoMatter::_init(); - generic_switch::config_t switch_config; + if (getEndPointId() != 0) { + log_e("Matter Generic Switch with Endpoint Id %d device has already been created.", getEndPointId()); + return false; + } + + generic_switch::config_t switch_config; // endpoint handles can be used to add/modify clusters. endpoint_t *endpoint = generic_switch::create(node::get(), &switch_config, ENDPOINT_FLAG_NONE, (void *)this); if (endpoint == nullptr) { - log_e("Failed to create Generic switch endpoint"); + log_e("Failed to create Generic Switch endpoint"); return false; } // Add group cluster to the switch endpoint diff --git a/libraries/Matter/src/MatterEndpoints/MatterHumiditySensor.cpp b/libraries/Matter/src/MatterEndpoints/MatterHumiditySensor.cpp index 3e911606074..d31d0e43728 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterHumiditySensor.cpp +++ b/libraries/Matter/src/MatterEndpoints/MatterHumiditySensor.cpp @@ -43,6 +43,11 @@ MatterHumiditySensor::~MatterHumiditySensor() { bool MatterHumiditySensor::begin(uint16_t _rawHumidity) { ArduinoMatter::_init(); + if (getEndPointId() != 0) { + log_e("Matter Humidity Sensor with Endpoint Id %d device has already been created.", getEndPointId()); + return false; + } + // is it a valid percentage value? if (_rawHumidity > 10000) { log_e("Humidity Sensor Percentage value out of range [0..100]."); @@ -82,7 +87,7 @@ bool MatterHumiditySensor::setRawHumidity(uint16_t _rawHumidity) { return false; } - // avoid processing the a "no-change" + // avoid processing if there was no change if (rawHumidity == _rawHumidity) { return true; } @@ -98,7 +103,7 @@ bool MatterHumiditySensor::setRawHumidity(uint16_t _rawHumidity) { bool ret; ret = updateAttributeVal(RelativeHumidityMeasurement::Id, RelativeHumidityMeasurement::Attributes::MeasuredValue::Id, &humidityVal); if (!ret) { - log_e("Failed to update Fan Speed Percent Attribute."); + log_e("Failed to update Humidity Sensor Attribute."); return false; } rawHumidity = _rawHumidity; diff --git a/libraries/Matter/src/MatterEndpoints/MatterOccupancySensor.cpp b/libraries/Matter/src/MatterEndpoints/MatterOccupancySensor.cpp new file mode 100644 index 00000000000..0d55c37708a --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterOccupancySensor.cpp @@ -0,0 +1,114 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT 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 +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include +#include + +using namespace esp_matter; +using namespace esp_matter::endpoint; +using namespace chip::app::Clusters; + +// clang-format off +const uint8_t MatterOccupancySensor::occupancySensorTypeBitmap[4] = { + MatterOccupancySensor::occupancySensorTypePir, + MatterOccupancySensor::occupancySensorTypePir | MatterOccupancySensor::occupancySensorTypeUltrasonic, + MatterOccupancySensor::occupancySensorTypeUltrasonic, + MatterOccupancySensor::occupancySensorTypePhysicalContact +}; +// clang-format on + +bool MatterOccupancySensor::attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) { + bool ret = true; + if (!started) { + log_e("Matter Occupancy Sensor device has not begun."); + return false; + } + + log_d("Occupancy Sensor Attr update callback: endpoint: %u, cluster: %u, attribute: %u, val: %u", endpoint_id, cluster_id, attribute_id, val->val.u32); + return ret; +} + +MatterOccupancySensor::MatterOccupancySensor() {} + +MatterOccupancySensor::~MatterOccupancySensor() { + end(); +} + +bool MatterOccupancySensor::begin(bool _occupancyState, OccupancySensorType_t _occupancySensorType) { + ArduinoMatter::_init(); + + if (getEndPointId() != 0) { + log_e("Matter Occupancy Sensor with Endpoint Id %d device has already been created.", getEndPointId()); + return false; + } + + occupancy_sensor::config_t occupancy_sensor_config; + occupancy_sensor_config.occupancy_sensing.occupancy = _occupancyState; + occupancy_sensor_config.occupancy_sensing.occupancy_sensor_type = _occupancySensorType; + occupancy_sensor_config.occupancy_sensing.occupancy_sensor_type_bitmap = occupancySensorTypeBitmap[_occupancySensorType]; + + // endpoint handles can be used to add/modify clusters. + endpoint_t *endpoint = occupancy_sensor::create(node::get(), &occupancy_sensor_config, ENDPOINT_FLAG_NONE, (void *)this); + if (endpoint == nullptr) { + log_e("Failed to create Occupancy Sensor endpoint"); + return false; + } + occupancyState = _occupancyState; + setEndPointId(endpoint::get_id(endpoint)); + log_i("Occupancy Sensor created with endpoint_id %d", getEndPointId()); + started = true; + return true; +} + +void MatterOccupancySensor::end() { + started = false; +} + +bool MatterOccupancySensor::setOccupancy(bool _occupancyState) { + if (!started) { + log_e("Matter Occupancy Sensor device has not begun."); + return false; + } + + // avoid processing if there was no change + if (occupancyState == _occupancyState) { + return true; + } + + esp_matter_attr_val_t occupancyVal = esp_matter_invalid(NULL); + + if (!getAttributeVal(OccupancySensing::Id, OccupancySensing::Attributes::Occupancy::Id, &occupancyVal)) { + log_e("Failed to get Occupancy Sensor Attribute."); + return false; + } + if (occupancyVal.val.u8 != _occupancyState) { + occupancyVal.val.u8 = _occupancyState; + bool ret; + ret = updateAttributeVal(OccupancySensing::Id, OccupancySensing::Attributes::Occupancy::Id, &occupancyVal); + if (!ret) { + log_e("Failed to update Occupancy Sensor Attribute."); + return false; + } + occupancyState = _occupancyState; + } + log_v("Occupancy Sensor set to %s", _occupancyState ? "Occupied" : "Vacant"); + + return true; +} + +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterOccupancySensor.h b/libraries/Matter/src/MatterEndpoints/MatterOccupancySensor.h new file mode 100644 index 00000000000..30f312a9841 --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterOccupancySensor.h @@ -0,0 +1,73 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT 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 +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include +#include + +using namespace chip::app::Clusters::OccupancySensing; + +class MatterOccupancySensor : public MatterEndPoint { +public: + // Different Occupancy Sensor Types + enum OccupancySensorType_t { + OCCUPANCY_SENSOR_TYPE_PIR = (uint8_t)OccupancySensorTypeEnum::kPir, + OCCUPANCY_SENSOR_TYPE_ULTRASONIC = (uint8_t)OccupancySensorTypeEnum::kUltrasonic, + OCCUPANCY_SENSOR_TYPE_PIR_AND_ULTRASONIC = (uint8_t)OccupancySensorTypeEnum::kPIRAndUltrasonic, + OCCUPANCY_SENSOR_TYPE_PHYSICAL_CONTACT = (uint8_t)OccupancySensorTypeEnum::kPhysicalContact + }; + + MatterOccupancySensor(); + ~MatterOccupancySensor(); + // begin Matter Occupancy Sensor endpoint with initial occupancy state and default PIR sensor type + bool begin(bool _occupancyState = false, OccupancySensorType_t _occupancySensorType = OCCUPANCY_SENSOR_TYPE_PIR); + // this will just stop processing Occupancy Sensor Matter events + void end(); + + // set the occupancy state + bool setOccupancy(bool _occupancyState); + // returns the occupancy state + bool getOccupancy() { + return occupancyState; + } + + // bool conversion operator + void operator=(bool _occupancyState) { + setOccupancy(_occupancyState); + } + // bool conversion operator + operator bool() { + return getOccupancy(); + } + + // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. + bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); + +protected: + // bitmap for Occupancy Sensor Types + static const uint8_t occupancySensorTypePir = 0x01; + static const uint8_t occupancySensorTypeUltrasonic = 0x02; + static const uint8_t occupancySensorTypePhysicalContact = 0x04; + + // bitmap for Occupancy Sensor Type Bitmap mapped array + static const uint8_t occupancySensorTypeBitmap[4]; + + bool started = false; + bool occupancyState = false; +}; +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterOnOffLight.cpp b/libraries/Matter/src/MatterEndpoints/MatterOnOffLight.cpp index 3f71ff1eb76..3faba821528 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterOnOffLight.cpp +++ b/libraries/Matter/src/MatterEndpoints/MatterOnOffLight.cpp @@ -59,8 +59,13 @@ MatterOnOffLight::~MatterOnOffLight() { bool MatterOnOffLight::begin(bool initialState) { ArduinoMatter::_init(); - on_off_light::config_t light_config; + if (getEndPointId() != 0) { + log_e("Matter On-Off Light with Endpoint Id %d device has already been created.", getEndPointId()); + return false; + } + + on_off_light::config_t light_config; light_config.on_off.on_off = initialState; light_config.on_off.lighting.start_up_on_off = nullptr; onOffState = initialState; @@ -94,7 +99,7 @@ bool MatterOnOffLight::setOnOff(bool newState) { return false; } - // avoid processing the a "no-change" + // avoid processing if there was no change if (onOffState == newState) { return true; } diff --git a/libraries/Matter/src/MatterEndpoints/MatterOnOffLight.h b/libraries/Matter/src/MatterEndpoints/MatterOnOffLight.h index 6d140a9948e..ec524d2c300 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterOnOffLight.h +++ b/libraries/Matter/src/MatterEndpoints/MatterOnOffLight.h @@ -30,23 +30,27 @@ class MatterOnOffLight : public MatterEndPoint { bool getOnOff(); // returns current light state bool toggle(); // returns true if successful - // used to update the state of the light using the current Matter Light internal state - // It is necessary to set a user callback function using onChange() to handle the physical light state - void updateAccessory(); - - operator bool(); // returns current light state - void operator=(bool state); // turns light on or off - // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. - bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); // User Callback for whenever the Light state is changed by the Matter Controller using EndPointCB = std::function; void onChange(EndPointCB onChangeCB) { _onChangeCB = onChangeCB; } + + // User Callback for whenever the Light On/Off state is changed by the Matter Controller void onChangeOnOff(EndPointCB onChangeCB) { _onChangeOnOffCB = onChangeCB; } + // used to update the state of the light using the current Matter Light internal state + // It is necessary to set a user callback function using onChange() to handle the physical light state + void updateAccessory(); + + operator bool(); // returns current light state + void operator=(bool state); // turns light on or off + + // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. + bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); + protected: bool started = false; bool onOffState = false; // default initial state is off, but it can be changed by begin(bool) diff --git a/libraries/Matter/src/MatterEndpoints/MatterOnOffPlugin.cpp b/libraries/Matter/src/MatterEndpoints/MatterOnOffPlugin.cpp new file mode 100644 index 00000000000..9b08958684c --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterOnOffPlugin.cpp @@ -0,0 +1,141 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT 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 +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include +#include + +using namespace esp_matter; +using namespace esp_matter::endpoint; +using namespace chip::app::Clusters; + +bool MatterOnOffPlugin::attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) { + bool ret = true; + if (!started) { + log_e("Matter On-Off Plugin device has not begun."); + return false; + } + + log_d("OnOff Attr update callback: endpoint: %u, cluster: %u, attribute: %u, val: %u", endpoint_id, cluster_id, attribute_id, val->val.u32); + + if (endpoint_id == getEndPointId()) { + log_d("OnOffPlugin state changed to %d", val->val.b); + if (cluster_id == OnOff::Id) { + if (attribute_id == OnOff::Attributes::OnOff::Id) { + if (_onChangeOnOffCB != NULL) { + ret &= _onChangeOnOffCB(val->val.b); + } + if (_onChangeCB != NULL) { + ret &= _onChangeCB(val->val.b); + } + if (ret == true) { + onOffState = val->val.b; + } + } + } + } + return ret; +} + +MatterOnOffPlugin::MatterOnOffPlugin() {} + +MatterOnOffPlugin::~MatterOnOffPlugin() { + end(); +} + +bool MatterOnOffPlugin::begin(bool initialState) { + ArduinoMatter::_init(); + + if (getEndPointId() != 0) { + log_e("Matter On-Off Plugin with Endpoint Id %d device has already been created.", getEndPointId()); + return false; + } + + on_off_plugin_unit::config_t plugin_config; + plugin_config.on_off.on_off = initialState; + plugin_config.on_off.lighting.start_up_on_off = nullptr; + + // endpoint handles can be used to add/modify clusters. + endpoint_t *endpoint = on_off_plugin_unit::create(node::get(), &plugin_config, ENDPOINT_FLAG_NONE, (void *)this); + if (endpoint == nullptr) { + log_e("Failed to create on-off plugin endpoint"); + return false; + } + onOffState = initialState; + setEndPointId(endpoint::get_id(endpoint)); + log_i("On-Off Plugin created with endpoint_id %d", getEndPointId()); + started = true; + return true; +} + +void MatterOnOffPlugin::end() { + started = false; +} + +void MatterOnOffPlugin::updateAccessory() { + if (_onChangeCB != NULL) { + _onChangeCB(onOffState); + } +} + +bool MatterOnOffPlugin::setOnOff(bool newState) { + if (!started) { + log_e("Matter On-Off Plugin device has not begun."); + return false; + } + + // avoid processing if there was no change + if (onOffState == newState) { + return true; + } + + esp_matter_attr_val_t onoffVal = esp_matter_invalid(NULL); + + if (!getAttributeVal(OnOff::Id, OnOff::Attributes::OnOff::Id, &onoffVal)) { + log_e("Failed to get Pressure Sensor Attribute."); + return false; + } + if (onoffVal.val.b != newState) { + onoffVal.val.b = newState; + bool ret; + ret = updateAttributeVal(OnOff::Id, OnOff::Attributes::OnOff::Id, &onoffVal); + if (!ret) { + log_e("Failed to update Pressure Sensor Measurement Attribute."); + return false; + } + onOffState = newState; + } + log_v("Plugin OnOff state set to %s", newState ? "ON" : "OFF"); + return true; +} + +bool MatterOnOffPlugin::getOnOff() { + return onOffState; +} + +bool MatterOnOffPlugin::toggle() { + return setOnOff(!onOffState); +} + +MatterOnOffPlugin::operator bool() { + return getOnOff(); +} + +void MatterOnOffPlugin::operator=(bool newState) { + setOnOff(newState); +} +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterOnOffPlugin.h b/libraries/Matter/src/MatterEndpoints/MatterOnOffPlugin.h new file mode 100644 index 00000000000..0b05c0944c4 --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterOnOffPlugin.h @@ -0,0 +1,60 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT 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 +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include + +class MatterOnOffPlugin : public MatterEndPoint { +public: + MatterOnOffPlugin(); + ~MatterOnOffPlugin(); + virtual bool begin(bool initialState = false); // default initial state is off + void end(); // this will just stop processing Plugin Matter events + + bool setOnOff(bool newState); // returns true if successful + bool getOnOff(); // returns current plugin state + bool toggle(); // returns true if successful + + // User Callback for whenever the Plugin state is changed by the Matter Controller + using EndPointCB = std::function; + void onChange(EndPointCB onChangeCB) { + _onChangeCB = onChangeCB; + } + + // User Callback for whenever the On/Off state is changed by the Matter Controller + void onChangeOnOff(EndPointCB onChangeCB) { + _onChangeOnOffCB = onChangeCB; + } + + // used to update the state of the plugin using the current Matter Plugin internal state + // It is necessary to set a user callback function using onChange() to handle the physical plugin state + void updateAccessory(); + + operator bool(); // returns current plugin state + void operator=(bool state); // turns plugin on or off + + // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. + bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); + +protected: + bool started = false; + bool onOffState = false; // default initial state is off, but it can be changed by begin(bool) + EndPointCB _onChangeCB = NULL; + EndPointCB _onChangeOnOffCB = NULL; +}; +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterPressureSensor.cpp b/libraries/Matter/src/MatterEndpoints/MatterPressureSensor.cpp index a157469c980..86d245d4041 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterPressureSensor.cpp +++ b/libraries/Matter/src/MatterEndpoints/MatterPressureSensor.cpp @@ -42,6 +42,11 @@ MatterPressureSensor::~MatterPressureSensor() { bool MatterPressureSensor::begin(int16_t _rawPressure) { ArduinoMatter::_init(); + if (getEndPointId() != 0) { + log_e("Matter Pressure Sensor with Endpoint Id %d device has already been created.", getEndPointId()); + return false; + } + pressure_sensor::config_t pressure_sensor_config; pressure_sensor_config.pressure_measurement.pressure_measured_value = _rawPressure; pressure_sensor_config.pressure_measurement.pressure_min_measured_value = nullptr; @@ -70,7 +75,7 @@ bool MatterPressureSensor::setRawPressure(int16_t _rawPressure) { return false; } - // avoid processing the a "no-change" + // avoid processing if there was no change if (rawPressure == _rawPressure) { return true; } diff --git a/libraries/Matter/src/MatterEndpoints/MatterPressureSensor.h b/libraries/Matter/src/MatterEndpoints/MatterPressureSensor.h index 9fdd90c6ebe..0715c05609d 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterPressureSensor.h +++ b/libraries/Matter/src/MatterEndpoints/MatterPressureSensor.h @@ -39,6 +39,7 @@ class MatterPressureSensor : public MatterEndPoint { double getPressure() { return (double)rawPressure; } + // double conversion operator void operator=(double pressure) { setPressure(pressure); diff --git a/libraries/Matter/src/MatterEndpoints/MatterTemperatureSensor.cpp b/libraries/Matter/src/MatterEndpoints/MatterTemperatureSensor.cpp index 4a43650f924..903e6b98d98 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterTemperatureSensor.cpp +++ b/libraries/Matter/src/MatterEndpoints/MatterTemperatureSensor.cpp @@ -42,6 +42,11 @@ MatterTemperatureSensor::~MatterTemperatureSensor() { bool MatterTemperatureSensor::begin(int16_t _rawTemperature) { ArduinoMatter::_init(); + if (getEndPointId() != 0) { + log_e("Temperature Sensor with Endpoint Id %d device has already been created.", getEndPointId()); + return false; + } + temperature_sensor::config_t temperature_sensor_config; temperature_sensor_config.temperature_measurement.measured_value = _rawTemperature; temperature_sensor_config.temperature_measurement.min_measured_value = nullptr; @@ -70,7 +75,7 @@ bool MatterTemperatureSensor::setRawTemperature(int16_t _rawTemperature) { return false; } - // avoid processing the a "no-change" + // avoid processing if there was no change if (rawTemperature == _rawTemperature) { return true; } @@ -86,7 +91,7 @@ bool MatterTemperatureSensor::setRawTemperature(int16_t _rawTemperature) { bool ret; ret = updateAttributeVal(TemperatureMeasurement::Id, TemperatureMeasurement::Attributes::MeasuredValue::Id, &temperatureVal); if (!ret) { - log_e("Failed to update Fan Speed Percent Attribute."); + log_e("Failed to update Temperature Sensor Attribute."); return false; } rawTemperature = _rawTemperature; diff --git a/libraries/Matter/src/MatterEndpoints/MatterTemperatureSensor.h b/libraries/Matter/src/MatterEndpoints/MatterTemperatureSensor.h index 826abac9a2a..27c61fdb978 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterTemperatureSensor.h +++ b/libraries/Matter/src/MatterEndpoints/MatterTemperatureSensor.h @@ -40,6 +40,7 @@ class MatterTemperatureSensor : public MatterEndPoint { double getTemperature() { return (double)rawTemperature / 100.0; } + // double conversion operator void operator=(double temperature) { setTemperature(temperature); diff --git a/libraries/Network/src/NetworkClient.h b/libraries/Network/src/NetworkClient.h index add886146b4..1baf8b36139 100644 --- a/libraries/Network/src/NetworkClient.h +++ b/libraries/Network/src/NetworkClient.h @@ -33,13 +33,13 @@ class ESPLwIPClient : public Client { class NetworkClient : public ESPLwIPClient { protected: - std::shared_ptr clientSocketHandle; - std::shared_ptr _rxBuffer; - bool _connected; - bool _sse; + std::shared_ptr clientSocketHandle = nullptr; + std::shared_ptr _rxBuffer = nullptr; + bool _connected = false; + bool _sse = false; int _timeout; - int _lastWriteTimeout; - int _lastReadTimeout; + int _lastWriteTimeout = 0; + int _lastReadTimeout = 0; public: NetworkClient *next; diff --git a/libraries/WebServer/src/Parsing.cpp b/libraries/WebServer/src/Parsing.cpp index 875ca305753..040338bb749 100644 --- a/libraries/WebServer/src/Parsing.cpp +++ b/libraries/WebServer/src/Parsing.cpp @@ -187,7 +187,8 @@ bool WebServer::_parseRequest(NetworkClient &client) { _currentRaw->status = RAW_WRITE; while (_currentRaw->totalSize < _clientContentLength) { - _currentRaw->currentSize = client.readBytes(_currentRaw->buf, HTTP_RAW_BUFLEN); + size_t read_len = std::min(_clientContentLength - _currentRaw->totalSize, (size_t)HTTP_RAW_BUFLEN); + _currentRaw->currentSize = client.readBytes(_currentRaw->buf, read_len); _currentRaw->totalSize += _currentRaw->currentSize; if (_currentRaw->currentSize == 0) { _currentRaw->status = RAW_ABORTED; diff --git a/libraries/Zigbee/examples/Zigbee_CarbonDioxide_Sensor/README.md b/libraries/Zigbee/examples/Zigbee_CarbonDioxide_Sensor/README.md new file mode 100644 index 00000000000..88c8bf04a65 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_CarbonDioxide_Sensor/README.md @@ -0,0 +1,72 @@ +# Arduino-ESP32 Carbon dioxide (CO2) Sensor Example + +This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) simple sensor device type with carbon dioxide measuring. + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## Pressure + Flow Sensor Functions + + * After this board first starts up, it would be configured locally to report the carbon dioxide on every 30 seconds. + * By clicking the button (BOOT) on this board, this board will immediately send a report of the current measured carbon dioxide to the network. + +## Hardware Required + +* A USB cable for power supply and programming + +### Configure the Project + +In this example, the internal temperature sensor is used to demonstrate reading of the carbon dioxide sensors. +Set the Button GPIO by changing the `button` variable. By default, it's the pin `BOOT_PIN` (BOOT button on ESP32-C6 and ESP32-H2). + +#### Using Arduino IDE + +To get more information about the Espressif boards see [Espressif Development Kits](https://www.espressif.com/en/products/devkits). + +* Before Compile/Verify, select the correct board: `Tools -> Board`. +* Select the End device Zigbee mode: `Tools -> Zigbee mode: Zigbee ED (end device)` +* Select Partition Scheme for Zigbee: `Tools -> Partition Scheme: Zigbee 4MB with spiffs` +* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. +* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. + +## Troubleshooting + +If the End device flashed with this example is not connecting to the coordinator, erase the flash of the End device before flashing the example to the board. It is recommended to do this if you re-flash the coordinator. +You can do the following: + +* In the Arduino IDE go to the Tools menu and set `Erase All Flash Before Sketch Upload` to `Enabled`. +* Add to the sketch `Zigbee.factoryReset();` to reset the device and Zigbee stack. + +By default, the coordinator network is closed after rebooting or flashing new firmware. +To open the network you have 2 options: + +* Open network after reboot by setting `Zigbee.setRebootOpenNetwork(time);` before calling `Zigbee.begin();`. +* In application you can anytime call `Zigbee.openNetwork(time);` to open the network for devices to join. + +***Important: Make sure you are using a good quality USB cable and that you have a reliable power source*** + +* **LED not blinking:** Check the wiring connection and the IO selection. +* **Programming Fail:** If the programming/flash procedure fails, try reducing the serial connection speed. +* **COM port not detected:** Check the USB cable and the USB to Serial driver installation. + +If the error persists, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute). + +## Contribute + +To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst) + +If you have any **feedback** or **issue** to report on this example/library, please open an issue or fix it by creating a new PR. Contributions are more than welcome! + +Before creating a new issue, be sure to try Troubleshooting and check if the same issue was already created by someone else. + +## Resources + +* Official ESP32 Forum: [Link](https://esp32.com) +* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) +* ESP32-C6 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf) +* ESP32-H2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-h2_datasheet_en.pdf) +* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) diff --git a/libraries/Zigbee/examples/Zigbee_CarbonDioxide_Sensor/Zigbee_CarbonDioxide_Sensor.ino b/libraries/Zigbee/examples/Zigbee_CarbonDioxide_Sensor/Zigbee_CarbonDioxide_Sensor.ino new file mode 100644 index 00000000000..47b9a05493f --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_CarbonDioxide_Sensor/Zigbee_CarbonDioxide_Sensor.ino @@ -0,0 +1,106 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @brief This example demonstrates Zigbee carbon dioxide sensor. + * + * The example demonstrates how to use Zigbee library to create a end device carbon dioxide sensor. + * + * Proper Zigbee mode must be selected in Tools->Zigbee mode + * and also the correct partition scheme must be selected in Tools->Partition Scheme. + * + * Please check the README.md for instructions and more detailed description. + * + * Created by Jan Procházka (https://github.com/P-R-O-C-H-Y/) + */ + +#ifndef ZIGBEE_MODE_ED +#error "Zigbee end device mode is not selected in Tools->Zigbee mode" +#endif + +#include "Zigbee.h" + +/* Zigbee carbon dioxide sensor configuration */ +#define CARBON_DIOXIDE_SENSOR_ENDPOINT_NUMBER 10 +uint8_t button = BOOT_PIN; + +ZigbeeCarbonDioxideSensor zbCarbonDioxideSensor = ZigbeeCarbonDioxideSensor(CARBON_DIOXIDE_SENSOR_ENDPOINT_NUMBER); + +void setup() { + Serial.begin(115200); + + // Init button switch + pinMode(button, INPUT_PULLUP); + + // Optional: set Zigbee device name and model + zbCarbonDioxideSensor.setManufacturerAndModel("Espressif", "ZigbeeCarbonDioxideSensor"); + + // Set minimum and maximum carbon dioxide measurement value in ppm + zbCarbonDioxideSensor.setMinMaxValue(0, 1500); + + // Add endpoints to Zigbee Core + Zigbee.addEndpoint(&zbCarbonDioxideSensor); + + Serial.println("Starting Zigbee..."); + // When all EPs are registered, start Zigbee in End Device mode + if (!Zigbee.begin()) { + Serial.println("Zigbee failed to start!"); + Serial.println("Rebooting..."); + ESP.restart(); + } else { + Serial.println("Zigbee started successfully!"); + } + Serial.println("Connecting to network"); + while (!Zigbee.connected()) { + Serial.print("."); + delay(100); + } + Serial.println(); + + // Set reporting interval for carbon dioxide measurement to be done every 30 seconds, must be called after Zigbee.begin() + // min_interval and max_interval in seconds, delta (carbon dioxide change in ppm) + // if min = 1 and max = 0, reporting is sent only when carbon dioxide changes by delta + // if min = 0 and max = 10, reporting is sent every 10 seconds or when carbon dioxide changes by delta + // if min = 0, max = 10 and delta = 0, reporting is sent every 10 seconds regardless of delta change + zbCarbonDioxideSensor.setReporting(0, 30, 0); +} + +void loop() { + static uint32_t timeCounter = 0; + // Read carbon dioxide sensor every 2s + if (!(timeCounter++ % 20)) { // delaying for 100ms x 20 = 2s + // Read sensor value - here is chip temperature used + 300 as a dummy value for demonstration + uint16_t carbon_dioxide_value = 300 + (uint16_t)temperatureRead(); + Serial.printf("Updating carbon dioxide sensor value to %d ppm\r\n", carbon_dioxide_value); + zbCarbonDioxideSensor.setCarbonDioxide(carbon_dioxide_value); + } + + // Checking button for factory reset and reporting + if (digitalRead(button) == LOW) { // Push button pressed + // Key debounce handling + delay(100); + int startTime = millis(); + while (digitalRead(button) == LOW) { + delay(50); + if ((millis() - startTime) > 3000) { + // If key pressed for more than 3secs, factory reset Zigbee and reboot + Serial.println("Resetting Zigbee to factory and rebooting in 1s."); + delay(1000); + Zigbee.factoryReset(); + } + } + zbCarbonDioxideSensor.report(); + } + delay(100); +} diff --git a/libraries/Zigbee/examples/Zigbee_CarbonDioxide_Sensor/ci.json b/libraries/Zigbee/examples/Zigbee_CarbonDioxide_Sensor/ci.json new file mode 100644 index 00000000000..7b7ccef8ed7 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_CarbonDioxide_Sensor/ci.json @@ -0,0 +1,6 @@ +{ + "fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] +} diff --git a/libraries/Zigbee/examples/Zigbee_Dimmable_Light/README.md b/libraries/Zigbee/examples/Zigbee_Dimmable_Light/README.md new file mode 100644 index 00000000000..e5bf51b660c --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Dimmable_Light/README.md @@ -0,0 +1,68 @@ +# Arduino-ESP32 Zigbee Dimmable Light Example + +This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) dimmable light. + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## Hardware Required + +* A USB cable for power supply and programming +* Board (ESP32-H2 or ESP32-C6) as Zigbee end device and upload the Zigbee_Dimmable_Light example +* Zigbee network / coordinator (Other board with switch examples or Zigbee2mqtt or ZigbeeHomeAssistant like application) + +### Configure the Project + +Set the LED GPIO by changing the `LED_PIN` definition. By default, the LED_PIN is `RGB_BUILTIN`. + +#### Using Arduino IDE + +To get more information about the Espressif boards see [Espressif Development Kits](https://www.espressif.com/en/products/devkits). + +* Before Compile/Verify, select the correct board: `Tools -> Board`. +* Select the End device Zigbee mode: `Tools -> Zigbee mode: Zigbee ED (end device)` +* Select Partition Scheme for Zigbee: `Tools -> Partition Scheme: Zigbee 4MB with spiffs` +* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. +* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. + +## Troubleshooting + +If the End device flashed with this example is not connecting to the coordinator, erase the flash of the End device before flashing the example to the board. It is recommended to do this if you re-flash the coordinator. +You can do the following: + +* In the Arduino IDE go to the Tools menu and set `Erase All Flash Before Sketch Upload` to `Enabled`. +* Add to the sketch `Zigbee.factoryReset();` to reset the device and Zigbee stack. + +By default, the coordinator network is closed after rebooting or flashing new firmware. +To open the network you have 2 options: + +* Open network after reboot by setting `Zigbee.setRebootOpenNetwork(time);` before calling `Zigbee.begin();`. +* In application you can anytime call `Zigbee.openNetwork(time);` to open the network for devices to join. + +***Important: Make sure you are using a good quality USB cable and that you have a reliable power source*** + +* **LED not blinking:** Check the wiring connection and the IO selection. +* **Programming Fail:** If the programming/flash procedure fails, try reducing the serial connection speed. +* **COM port not detected:** Check the USB cable and the USB to Serial driver installation. + +If the error persists, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute). + +## Contribute + +To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst) + +If you have any **feedback** or **issue** to report on this example/library, please open an issue or fix it by creating a new PR. Contributions are more than welcome! + +Before creating a new issue, be sure to try Troubleshooting and check if the same issue was already created by someone else. + +## Resources + +* Official ESP32 Forum: [Link](https://esp32.com) +* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) +* ESP32-C6 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf) +* ESP32-H2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-h2_datasheet_en.pdf) +* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) diff --git a/libraries/Zigbee/examples/Zigbee_Dimmable_Light/Zigbee_Dimmable_Light.ino b/libraries/Zigbee/examples/Zigbee_Dimmable_Light/Zigbee_Dimmable_Light.ino new file mode 100644 index 00000000000..c77a7e742d1 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Dimmable_Light/Zigbee_Dimmable_Light.ino @@ -0,0 +1,121 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @brief This example demonstrates Zigbee Dimmable light bulb. + * + * The example demonstrates how to use Zigbee library to create an end device with + * dimmable light end point. + * The light bulb is a Zigbee end device, which is controlled by a Zigbee coordinator. + * + * Proper Zigbee mode must be selected in Tools->Zigbee mode + * and also the correct partition scheme must be selected in Tools->Partition Scheme. + * + * Please check the README.md for instructions and more detailed description. + * + * Created by [FaBjE](https://github.com/FaBjE) based on examples by [Jan Procházka](https://github.com/P-R-O-C-H-Y/) + */ + +#ifndef ZIGBEE_MODE_ED +#error "Zigbee end device mode is not selected in Tools->Zigbee mode" +#endif + +#include "Zigbee.h" + +/* Zigbee dimmable light configuration */ +#define ZIGBEE_LIGHT_ENDPOINT 10 +uint8_t led = RGB_BUILTIN; +uint8_t button = BOOT_PIN; + +ZigbeeDimmableLight zbDimmableLight = ZigbeeDimmableLight(ZIGBEE_LIGHT_ENDPOINT); + +/********************* RGB LED functions **************************/ +void setLight(bool state, uint8_t level) { + if (!state) { + rgbLedWrite(led, 0, 0, 0); + return; + } + rgbLedWrite(led, level, level, level); +} + +// Create a task on identify call to handle the identify function +void identify(uint16_t time) { + static uint8_t blink = 1; + log_d("Identify called for %d seconds", time); + if (time == 0) { + // If identify time is 0, stop blinking and restore light as it was used for identify + zbDimmableLight.restoreLight(); + return; + } + rgbLedWrite(led, 255 * blink, 255 * blink, 255 * blink); + blink = !blink; +} + +/********************* Arduino functions **************************/ +void setup() { + Serial.begin(115200); + + // Init RMT and leave light OFF + rgbLedWrite(led, 0, 0, 0); + + // Init button for factory reset + pinMode(button, INPUT_PULLUP); + + // Set callback function for light change + zbDimmableLight.onLightChange(setLight); + + // Optional: Set callback function for device identify + zbDimmableLight.onIdentify(identify); + + // Optional: Set Zigbee device name and model + zbDimmableLight.setManufacturerAndModel("Espressif", "ZBLightBulb"); + + // Add endpoint to Zigbee Core + Serial.println("Adding ZigbeeLight endpoint to Zigbee Core"); + Zigbee.addEndpoint(&zbDimmableLight); + + // When all EPs are registered, start Zigbee in End Device mode + if (!Zigbee.begin()) { + Serial.println("Zigbee failed to start!"); + Serial.println("Rebooting..."); + ESP.restart(); + } + Serial.println("Connecting to network"); + while (!Zigbee.connected()) { + Serial.print("."); + delay(100); + } + Serial.println(); +} + +void loop() { + // Checking button for factory reset + if (digitalRead(button) == LOW) { // Push button pressed + // Key debounce handling + delay(100); + int startTime = millis(); + while (digitalRead(button) == LOW) { + delay(50); + if ((millis() - startTime) > 3000) { + // If key pressed for more than 3secs, factory reset Zigbee and reboot + Serial.println("Resetting Zigbee to factory and rebooting in 1s."); + delay(1000); + Zigbee.factoryReset(); + } + } + // Increase blightness by 50 every time the button is pressed + zbDimmableLight.setLightLevel(zbDimmableLight.getLightLevel() + 50); + } + delay(100); +} diff --git a/libraries/Zigbee/examples/Zigbee_Dimmable_Light/ci.json b/libraries/Zigbee/examples/Zigbee_Dimmable_Light/ci.json new file mode 100644 index 00000000000..7b7ccef8ed7 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Dimmable_Light/ci.json @@ -0,0 +1,6 @@ +{ + "fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] +} diff --git a/libraries/Zigbee/examples/Zigbee_Occupancy_Sensor/README.md b/libraries/Zigbee/examples/Zigbee_Occupancy_Sensor/README.md new file mode 100644 index 00000000000..0c5dcd013f2 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Occupancy_Sensor/README.md @@ -0,0 +1,57 @@ +# Arduino-ESP32 Zigbee Occupancy Sensor Example + +This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) occupancy sensor (PIR). + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## Hardware Required + +* A USB cable for power supply and programming + +### Configure the Project + +Set the Button GPIO by changing the `button` variable. By default, it's the pin `BOOT_PIN` (BOOT button on ESP32-C6 and ESP32-H2). +Set the Sensor GPIO by changing the `sensor_pin` variable. + +#### Using Arduino IDE + +To get more information about the Espressif boards see [Espressif Development Kits](https://www.espressif.com/en/products/devkits). + +* Before Compile/Verify, select the correct board: `Tools -> Board`. +* Select the End device Zigbee mode: `Tools -> Zigbee mode: Zigbee ED (end device)` +* Select Partition Scheme for Zigbee: `Tools -> Partition Scheme: Zigbee 4MB with spiffs` +* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. +* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. + +## Troubleshooting + +If the End device flashed with this example is not connecting to the coordinator, erase the flash of the End device before flashing the example to the board. + +***Important: Make sure you are using a good quality USB cable and that you have a reliable power source*** + +* **LED not blinking:** Check the wiring connection and the IO selection. +* **Programming Fail:** If the programming/flash procedure fails, try reducing the serial connection speed. +* **COM port not detected:** Check the USB cable and the USB to Serial driver installation. + +If the error persists, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute). + +## Contribute + +To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst) + +If you have any **feedback** or **issue** to report on this example/library, please open an issue or fix it by creating a new PR. Contributions are more than welcome! + +Before creating a new issue, be sure to try Troubleshooting and check if the same issue was already created by someone else. + +## Resources + +* Official ESP32 Forum: [Link](https://esp32.com) +* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) +* ESP32-C6 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf) +* ESP32-H2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-h2_datasheet_en.pdf) +* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) diff --git a/libraries/Zigbee/examples/Zigbee_Occupancy_Sensor/Zigbee_Occupancy_Sensor.ino b/libraries/Zigbee/examples/Zigbee_Occupancy_Sensor/Zigbee_Occupancy_Sensor.ino new file mode 100644 index 00000000000..46afdf3d273 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Occupancy_Sensor/Zigbee_Occupancy_Sensor.ino @@ -0,0 +1,103 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @brief This example demonstrates Zigbee occupancy sensor. + * + * The example demonstrates how to use Zigbee library to create a end device occupancy sensor. + * The occupancy sensor is a Zigbee end device, which is reporting data to the Zigbee network. + * Tested with PIR sensor HC-SR501 connected to GPIO4. + * + * Proper Zigbee mode must be selected in Tools->Zigbee mode + * and also the correct partition scheme must be selected in Tools->Partition Scheme. + * + * Please check the README.md for instructions and more detailed description. + * + * Created by Jan Procházka (https://github.com/P-R-O-C-H-Y/) + */ + +#ifndef ZIGBEE_MODE_ED +#error "Zigbee end device mode is not selected in Tools->Zigbee mode" +#endif + +#include "Zigbee.h" + +/* Zigbee occupancy sensor configuration */ +#define OCCUPANCY_SENSOR_ENDPOINT_NUMBER 10 +uint8_t button = BOOT_PIN; +uint8_t sensor_pin = 4; + +ZigbeeOccupancySensor zbOccupancySensor = ZigbeeOccupancySensor(OCCUPANCY_SENSOR_ENDPOINT_NUMBER); + +void setup() { + Serial.begin(115200); + + // Init button + PIR sensor + pinMode(button, INPUT_PULLUP); + pinMode(sensor_pin, INPUT); + + // Optional: set Zigbee device name and model + zbOccupancySensor.setManufacturerAndModel("Espressif", "ZigbeeOccupancyPIRSensor"); + + // Add endpoint to Zigbee Core + Zigbee.addEndpoint(&zbOccupancySensor); + + Serial.println("Starting Zigbee..."); + // When all EPs are registered, start Zigbee in End Device mode + if (!Zigbee.begin()) { + Serial.println("Zigbee failed to start!"); + Serial.println("Rebooting..."); + ESP.restart(); + } else { + Serial.println("Zigbee started successfully!"); + } + Serial.println("Connecting to network"); + while (!Zigbee.connected()) { + Serial.print("."); + delay(100); + } + Serial.println(); +} + +void loop() { + // Checking PIR sensor for occupancy change + static bool occupancy = false; + if (digitalRead(sensor_pin) == HIGH && !occupancy) { + // Update occupancy sensor value + zbOccupancySensor.setOccupancy(true); + zbOccupancySensor.report(); + occupancy = true; + } else if (digitalRead(sensor_pin) == LOW && occupancy) { + zbOccupancySensor.setOccupancy(false); + zbOccupancySensor.report(); + occupancy = false; + } + + // Checking button for factory reset + if (digitalRead(button) == LOW) { // Push button pressed + // Key debounce handling + delay(100); + int startTime = millis(); + while (digitalRead(button) == LOW) { + delay(50); + if ((millis() - startTime) > 3000) { + // If key pressed for more than 3secs, factory reset Zigbee and reboot + Serial.println("Resetting Zigbee to factory and rebooting in 1s."); + delay(1000); + Zigbee.factoryReset(); + } + } + } + delay(100); +} diff --git a/libraries/Zigbee/examples/Zigbee_Occupancy_Sensor/ci.json b/libraries/Zigbee/examples/Zigbee_Occupancy_Sensor/ci.json new file mode 100644 index 00000000000..7b7ccef8ed7 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Occupancy_Sensor/ci.json @@ -0,0 +1,6 @@ +{ + "fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] +} diff --git a/libraries/Zigbee/examples/Zigbee_Pressure_Flow_Sensor/README.md b/libraries/Zigbee/examples/Zigbee_Pressure_Flow_Sensor/README.md new file mode 100644 index 00000000000..964c7503027 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Pressure_Flow_Sensor/README.md @@ -0,0 +1,72 @@ +# Arduino-ESP32 Zigbee Pressure + Flow Sensor Example + +This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) simple sensor device type with pressure and flow measuring. + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## Pressure + Flow Sensor Functions + + * After this board first starts up, it would be configured locally to report the pressure and flow on change or every 30 seconds. + * By clicking the button (BOOT) on this board, this board will immediately send a report of the current measured flow and pressure to the network. + +## Hardware Required + +* A USB cable for power supply and programming + +### Configure the Project + +In this example, the internal temperature sensor is used to demonstrate reading of the flow and pressure sensors. +Set the Button GPIO by changing the `button` variable. By default, it's the pin `BOOT_PIN` (BOOT button on ESP32-C6 and ESP32-H2). + +#### Using Arduino IDE + +To get more information about the Espressif boards see [Espressif Development Kits](https://www.espressif.com/en/products/devkits). + +* Before Compile/Verify, select the correct board: `Tools -> Board`. +* Select the End device Zigbee mode: `Tools -> Zigbee mode: Zigbee ED (end device)` +* Select Partition Scheme for Zigbee: `Tools -> Partition Scheme: Zigbee 4MB with spiffs` +* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. +* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. + +## Troubleshooting + +If the End device flashed with this example is not connecting to the coordinator, erase the flash of the End device before flashing the example to the board. It is recommended to do this if you re-flash the coordinator. +You can do the following: + +* In the Arduino IDE go to the Tools menu and set `Erase All Flash Before Sketch Upload` to `Enabled`. +* Add to the sketch `Zigbee.factoryReset();` to reset the device and Zigbee stack. + +By default, the coordinator network is closed after rebooting or flashing new firmware. +To open the network you have 2 options: + +* Open network after reboot by setting `Zigbee.setRebootOpenNetwork(time);` before calling `Zigbee.begin();`. +* In application you can anytime call `Zigbee.openNetwork(time);` to open the network for devices to join. + +***Important: Make sure you are using a good quality USB cable and that you have a reliable power source*** + +* **LED not blinking:** Check the wiring connection and the IO selection. +* **Programming Fail:** If the programming/flash procedure fails, try reducing the serial connection speed. +* **COM port not detected:** Check the USB cable and the USB to Serial driver installation. + +If the error persists, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute). + +## Contribute + +To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst) + +If you have any **feedback** or **issue** to report on this example/library, please open an issue or fix it by creating a new PR. Contributions are more than welcome! + +Before creating a new issue, be sure to try Troubleshooting and check if the same issue was already created by someone else. + +## Resources + +* Official ESP32 Forum: [Link](https://esp32.com) +* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) +* ESP32-C6 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf) +* ESP32-H2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-h2_datasheet_en.pdf) +* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) diff --git a/libraries/Zigbee/examples/Zigbee_Pressure_Flow_Sensor/Zigbee_Pressure_Flow_Sensor.ino b/libraries/Zigbee/examples/Zigbee_Pressure_Flow_Sensor/Zigbee_Pressure_Flow_Sensor.ino new file mode 100644 index 00000000000..a652a22c493 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Pressure_Flow_Sensor/Zigbee_Pressure_Flow_Sensor.ino @@ -0,0 +1,128 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @brief This example demonstrates Zigbee temperature sensor. + * + * The example demonstrates how to use Zigbee library to create a end device temperature sensor. + * The temperature sensor is a Zigbee end device, which is controlled by a Zigbee coordinator. + * + * Proper Zigbee mode must be selected in Tools->Zigbee mode + * and also the correct partition scheme must be selected in Tools->Partition Scheme. + * + * Please check the README.md for instructions and more detailed description. + * + * Created by Jan Procházka (https://github.com/P-R-O-C-H-Y/) + */ + +#ifndef ZIGBEE_MODE_ED +#error "Zigbee end device mode is not selected in Tools->Zigbee mode" +#endif + +#include "Zigbee.h" + +/* Zigbee flow + pressure sensor configuration */ +#define FLOW_SENSOR_ENDPOINT_NUMBER 10 +#define PRESSURE_SENSOR_ENDPOINT_NUMBER 11 + +uint8_t button = BOOT_PIN; + +ZigbeeFlowSensor zbFlowSensor = ZigbeeFlowSensor(FLOW_SENSOR_ENDPOINT_NUMBER); +ZigbeePressureSensor zbPressureSensor = ZigbeePressureSensor(PRESSURE_SENSOR_ENDPOINT_NUMBER); + +void setup() { + Serial.begin(115200); + + // Init button switch + pinMode(button, INPUT_PULLUP); + + // Optional: set Zigbee device name and model + zbFlowSensor.setManufacturerAndModel("Espressif", "ZigbeeFlowSensor"); + + // Set minimum and maximum flow measurement value in 0,1 m3/h + zbFlowSensor.setMinMaxValue(0.0, 100.0); + + // Optional: Set tolerance for flow measurement in 0,1 m3/h + zbFlowSensor.setTolerance(1.0); + + // Optional: set Zigbee device name and model + zbPressureSensor.setManufacturerAndModel("Espressif", "ZigbeePressureSensor"); + + // Set minimum and maximum pressure measurement value in hPa + zbPressureSensor.setMinMaxValue(0, 10000); + + // Optional: Set tolerance for pressure measurement in hPa + zbPressureSensor.setTolerance(1); + + // Add endpoints to Zigbee Core + Zigbee.addEndpoint(&zbFlowSensor); + Zigbee.addEndpoint(&zbPressureSensor); + + Serial.println("Starting Zigbee..."); + // When all EPs are registered, start Zigbee in End Device mode + if (!Zigbee.begin()) { + Serial.println("Zigbee failed to start!"); + Serial.println("Rebooting..."); + ESP.restart(); + } else { + Serial.println("Zigbee started successfully!"); + } + Serial.println("Connecting to network"); + while (!Zigbee.connected()) { + Serial.print("."); + delay(100); + } + Serial.println(); + + // Set reporting interval for flow and pressure measurement in seconds, must be called after Zigbee.begin() + // min_interval and max_interval in seconds, delta (pressure change in hPa, flow change in 0,1 m3/h) + // if min = 1 and max = 0, reporting is sent only when temperature changes by delta + // if min = 0 and max = 10, reporting is sent every 10 seconds or temperature changes by delta + // if min = 0, max = 10 and delta = 0, reporting is sent every 10 seconds regardless of delta change + zbFlowSensor.setReporting(0, 30, 1.0); + zbPressureSensor.setReporting(0, 30, 1); +} + +void loop() { + static uint32_t timeCounter = 0; + + // Read flow and pressure sensors every 2s + if (!(timeCounter++ % 20)) { // delaying for 100ms x 20 = 2s + float flow_value = temperatureRead(); + uint16_t pressure_value = (uint16_t)temperatureRead() * 100; //*100 for demonstration so the value is in 1000-3000hPa + Serial.printf("Updating flow sensor value to %.2f m3/h\r\n", flow_value); + zbFlowSensor.setFlow(flow_value); + Serial.printf("Updating pressure sensor value to %d hPa\r\n", pressure_value); + zbPressureSensor.setPressure(pressure_value); + } + + // Checking button for factory reset and reporting + if (digitalRead(button) == LOW) { // Push button pressed + // Key debounce handling + delay(100); + int startTime = millis(); + while (digitalRead(button) == LOW) { + delay(50); + if ((millis() - startTime) > 3000) { + // If key pressed for more than 3secs, factory reset Zigbee and reboot + Serial.println("Resetting Zigbee to factory and rebooting in 1s."); + delay(1000); + Zigbee.factoryReset(); + } + } + zbFlowSensor.report(); + zbPressureSensor.report(); + } + delay(100); +} diff --git a/libraries/Zigbee/examples/Zigbee_Pressure_Flow_Sensor/ci.json b/libraries/Zigbee/examples/Zigbee_Pressure_Flow_Sensor/ci.json new file mode 100644 index 00000000000..7b7ccef8ed7 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Pressure_Flow_Sensor/ci.json @@ -0,0 +1,6 @@ +{ + "fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y" + ] +} diff --git a/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/README.md b/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/README.md index d88b01cda3a..afaa12c0bfa 100644 --- a/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/README.md +++ b/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/README.md @@ -24,7 +24,7 @@ Currently, this example supports the following targets. ### Configure the Project In this example, to demonstrate the functionality the chip temperature is used and reported as temperature and humidity. -Set the Button GPIO by changing the `BUTTON_PIN` definition. By default, it's the pin `9` (BOOT button on ESP32-C6 and ESP32-H2). +Set the Button GPIO by changing the `button` variable. By default, it's the pin `BOOT_PIN` (BOOT button on ESP32-C6 and ESP32-H2). #### Using Arduino IDE diff --git a/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/Zigbee_Temp_Hum_Sensor_Sleepy.ino b/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/Zigbee_Temp_Hum_Sensor_Sleepy.ino index 2b342161199..60bd784cca9 100644 --- a/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/Zigbee_Temp_Hum_Sensor_Sleepy.ino +++ b/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/Zigbee_Temp_Hum_Sensor_Sleepy.ino @@ -55,11 +55,12 @@ void meausureAndSleep() { zbTempSensor.setHumidity(humidity); // Report temperature and humidity values - zbTempSensor.reportTemperature(); - zbTempSensor.reportHumidity(); - + zbTempSensor.report(); Serial.printf("Reported temperature: %.2f°C, Humidity: %.2f%%\r\n", temperature, humidity); + // Add small delay to allow the data to be sent before going to sleep + delay(100); + // Put device to deep sleep Serial.println("Going to sleep now"); esp_deep_sleep_start(); diff --git a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/README.md b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/README.md index f3dd9248f87..577bd7c8058 100644 --- a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/README.md +++ b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/README.md @@ -28,7 +28,7 @@ Functions: ### Configure the Project In this example, the internal temperature sensor task is reading the chip temperature. -Set the Button GPIO by changing the `BUTTON_PIN` definition. By default, it's the pin `9` (BOOT button on ESP32-C6 and ESP32-H2). +Set the Button GPIO by changing the `button` variable. By default, it's the pin `BOOT_PIN` (BOOT button on ESP32-C6 and ESP32-H2). #### Using Arduino IDE diff --git a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino index 22b0c6fbeed..27aa2db97bd 100644 --- a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino +++ b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino @@ -63,7 +63,7 @@ void setup() { // Set minimum and maximum temperature measurement value (10-50°C is default range for chip temperature measurement) zbTempSensor.setMinMaxValue(10, 50); - // Set tolerance for temperature measurement in °C (lowest possible value is 0.01°C) + // Optional: Set tolerance for temperature measurement in °C (lowest possible value is 0.01°C) zbTempSensor.setTolerance(1); // Add endpoint to Zigbee Core @@ -89,7 +89,7 @@ void setup() { xTaskCreate(temp_sensor_value_update, "temp_sensor_update", 2048, NULL, 10, NULL); // Set reporting interval for temperature measurement in seconds, must be called after Zigbee.begin() - // min_interval and max_interval in seconds, delta (temp change in °C) + // min_interval and max_interval in seconds, delta (temp change in 0,1 °C) // if min = 1 and max = 0, reporting is sent only when temperature changes by delta // if min = 0 and max = 10, reporting is sent every 10 seconds or temperature changes by delta // if min = 0, max = 10 and delta = 0, reporting is sent every 10 seconds regardless of temperature change diff --git a/libraries/Zigbee/keywords.txt b/libraries/Zigbee/keywords.txt index 40e5dcec004..483d54eb712 100644 --- a/libraries/Zigbee/keywords.txt +++ b/libraries/Zigbee/keywords.txt @@ -18,6 +18,9 @@ ZigbeeColorDimmableLight KEYWORD1 ZigbeeColorDimmerSwitch KEYWORD1 ZigbeeTempSensor KEYWORD1 ZigbeeThermostat KEYWORD1 +ZigbeeFlowSensor KEYWORD1 +ZigbeePressureSensor KEYWORD1 +ZigbeeOccupancySensor KEYWORD1 # Other zigbee_role_t KEYWORD1 @@ -89,23 +92,39 @@ lightOnWithSceneRecall KEYWORD2 setLightLevel KEYWORD2 setLightColor KEYWORD2 -# ZigbeeTempSensor + humidity -setTemperature KEYWORD2 +# ZigbeeThermostat +onTempRecieve KEYWORD2 +onConfigRecieve KEYWORD2 +getTemperature KEYWORD2 +getSensorSettings KEYWORD2 +setTemperatureReporting KEYWORD2 + +# Common Zigbee Sensor setMinMaxValue KEYWORD2 setTolerance KEYWORD2 setReporting KEYWORD2 +report KEYWORD2 + +# ZigbeeTempSensor + humidity +setTemperature KEYWORD2 reportTemperature KEYWORD2 addHumiditySensor KEYWORD2 setHumidity KEYWORD2 setHumidityReporting KEYWORD2 reportHumidity KEYWORD2 -# ZigbeeThermostat -onTempRecieve KEYWORD2 -onConfigRecieve KEYWORD2 -getTemperature KEYWORD2 -getSensorSettings KEYWORD2 -setTemperatureReporting KEYWORD2 +# ZigbeeFlowSensor +setFlow KEYWORD2 + +# ZigbeePressureSensor +setPressure KEYWORD2 + +# ZigbeeOccupancySensor +setOccupancy KEYWORD2 +setSensorType KEYWORD2 + +# ZigbeeCarbonDioxideSensor +setCarbonDioxide KEYWORD2 ####################################### # Constants (LITERAL1) diff --git a/libraries/Zigbee/library.properties b/libraries/Zigbee/library.properties index 4d66f470378..2b1f041fc94 100644 --- a/libraries/Zigbee/library.properties +++ b/libraries/Zigbee/library.properties @@ -1,5 +1,5 @@ name=Zigbee -version=3.0.5 +version=3.1.0 author=P-R-O-C-H-Y maintainer=Jan Procházka sentence=Enables zigbee connection with the ESP32 diff --git a/libraries/Zigbee/src/Zigbee.h b/libraries/Zigbee/src/Zigbee.h index 98674a9d115..cf58dc8d5d8 100644 --- a/libraries/Zigbee/src/Zigbee.h +++ b/libraries/Zigbee/src/Zigbee.h @@ -9,7 +9,12 @@ // Endpoints #include "ep/ZigbeeLight.h" #include "ep/ZigbeeSwitch.h" +#include "ep/ZigbeeDimmableLight.h" #include "ep/ZigbeeColorDimmableLight.h" #include "ep/ZigbeeColorDimmerSwitch.h" #include "ep/ZigbeeTempSensor.h" #include "ep/ZigbeeThermostat.h" +#include "ep/ZigbeePressureSensor.h" +#include "ep/ZigbeeFlowSensor.h" +#include "ep/ZigbeeOccupancySensor.h" +#include "ep/ZigbeeCarbonDioxideSensor.h" diff --git a/libraries/Zigbee/src/ep/ZigbeeCarbonDioxideSensor.cpp b/libraries/Zigbee/src/ep/ZigbeeCarbonDioxideSensor.cpp new file mode 100644 index 00000000000..89454c057e3 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeCarbonDioxideSensor.cpp @@ -0,0 +1,109 @@ +#include "ZigbeeCarbonDioxideSensor.h" +#if SOC_IEEE802154_SUPPORTED && CONFIG_ZB_ENABLED + +esp_zb_cluster_list_t *zigbee_carbon_dioxide_sensor_clusters_create(zigbee_carbon_dioxide_sensor_cfg_t *carbon_dioxide_sensor) { + esp_zb_basic_cluster_cfg_t *basic_cfg = carbon_dioxide_sensor ? &(carbon_dioxide_sensor->basic_cfg) : NULL; + esp_zb_identify_cluster_cfg_t *identify_cfg = carbon_dioxide_sensor ? &(carbon_dioxide_sensor->identify_cfg) : NULL; + esp_zb_carbon_dioxide_measurement_cluster_cfg_t *carbon_dioxide_meas_cfg = carbon_dioxide_sensor ? &(carbon_dioxide_sensor->carbon_dioxide_meas_cfg) : NULL; + esp_zb_cluster_list_t *cluster_list = esp_zb_zcl_cluster_list_create(); + esp_zb_cluster_list_add_basic_cluster(cluster_list, esp_zb_basic_cluster_create(basic_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_identify_cluster_create(identify_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_carbon_dioxide_measurement_cluster( + cluster_list, esp_zb_carbon_dioxide_measurement_cluster_create(carbon_dioxide_meas_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE + ); + esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + return cluster_list; +} + +ZigbeeCarbonDioxideSensor::ZigbeeCarbonDioxideSensor(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID; + + //Create custom pressure sensor configuration + zigbee_carbon_dioxide_sensor_cfg_t carbon_dioxide_sensor_cfg = ZIGBEE_DEFAULT_CARBON_DIOXIDE_SENSOR_CONFIG(); + _cluster_list = zigbee_carbon_dioxide_sensor_clusters_create(&carbon_dioxide_sensor_cfg); + + _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID, .app_device_version = 0}; +} + +void ZigbeeCarbonDioxideSensor::setMinMaxValue(float min, float max) { + float zb_min = min / 1000000.0f; + float zb_max = max / 1000000.0f; + esp_zb_attribute_list_t *carbon_dioxide_measure_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_CARBON_DIOXIDE_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_update_attr(carbon_dioxide_measure_cluster, ESP_ZB_ZCL_ATTR_CARBON_DIOXIDE_MEASUREMENT_MIN_MEASURED_VALUE_ID, (void *)&zb_min); + esp_zb_cluster_update_attr(carbon_dioxide_measure_cluster, ESP_ZB_ZCL_ATTR_CARBON_DIOXIDE_MEASUREMENT_MAX_MEASURED_VALUE_ID, (void *)&zb_max); +} + +void ZigbeeCarbonDioxideSensor::setTolerance(float tolerance) { + float zb_tolerance = tolerance / 1000000.0f; + esp_zb_attribute_list_t *carbon_dioxide_measure_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_CARBON_DIOXIDE_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_temperature_meas_cluster_add_attr(carbon_dioxide_measure_cluster, ESP_ZB_ZCL_ATTR_CARBON_DIOXIDE_MEASUREMENT_TOLERANCE_ID, (void *)&zb_tolerance); +} + +void ZigbeeCarbonDioxideSensor::setReporting(uint16_t min_interval, uint16_t max_interval, uint16_t delta) { + if (delta > 0) { + log_e("Delta reporting is currently not supported by the carbon dioxide sensor"); + } + // clang-format off + esp_zb_zcl_reporting_info_t reporting_info = { + .direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV, + .ep = _endpoint, + .cluster_id = ESP_ZB_ZCL_CLUSTER_ID_CARBON_DIOXIDE_MEASUREMENT, + .cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, + .attr_id = ESP_ZB_ZCL_ATTR_CARBON_DIOXIDE_MEASUREMENT_MEASURED_VALUE_ID, + .u = + { + .send_info = + { + .min_interval = min_interval, + .max_interval = max_interval, + .delta = + { + .u16 = delta, + }, + .def_min_interval = min_interval, + .def_max_interval = max_interval, + }, + }, + .dst = + { + .profile_id = ESP_ZB_AF_HA_PROFILE_ID, + }, + .manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC, + }; + // clang-format on + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_update_reporting_info(&reporting_info); + esp_zb_lock_release(); +} + +void ZigbeeCarbonDioxideSensor::setCarbonDioxide(float carbon_dioxide) { + float zb_carbon_dioxide = carbon_dioxide / 1000000.0f; + log_v("Updating carbon dioxide sensor value..."); + /* Update carbon dioxide sensor measured value */ + log_d("Setting carbon dioxide to %0.1f", carbon_dioxide); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_CARBON_DIOXIDE_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_CARBON_DIOXIDE_MEASUREMENT_MEASURED_VALUE_ID, + &zb_carbon_dioxide, false + ); + esp_zb_lock_release(); +} + +void ZigbeeCarbonDioxideSensor::report() { + /* Send report attributes command */ + esp_zb_zcl_report_attr_cmd_t report_attr_cmd; + report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + report_attr_cmd.attributeID = ESP_ZB_ZCL_ATTR_CARBON_DIOXIDE_MEASUREMENT_MEASURED_VALUE_ID; + report_attr_cmd.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_CLI; + report_attr_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_CARBON_DIOXIDE_MEASUREMENT; + report_attr_cmd.zcl_basic_cmd.src_endpoint = _endpoint; + + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd); + esp_zb_lock_release(); + log_v("Carbon dioxide report sent"); +} + +#endif //SOC_IEEE802154_SUPPORTED && CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeCarbonDioxideSensor.h b/libraries/Zigbee/src/ep/ZigbeeCarbonDioxideSensor.h new file mode 100644 index 00000000000..71c353d4695 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeCarbonDioxideSensor.h @@ -0,0 +1,61 @@ +/* Class of Zigbee Pressure sensor endpoint inherited from common EP class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if SOC_IEEE802154_SUPPORTED && CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +// clang-format off +#define ZIGBEE_DEFAULT_CARBON_DIOXIDE_SENSOR_CONFIG() \ + { \ + .basic_cfg = \ + { \ + .zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, \ + .power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE, \ + }, \ + .identify_cfg = \ + { \ + .identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE, \ + }, \ + .carbon_dioxide_meas_cfg = \ + { \ + .measured_value = 0.0, \ + .min_measured_value = 0.0, \ + .max_measured_value = 1.0, \ + }, \ + } +// clang-format on + +typedef struct zigbee_carbon_dioxide_sensor_cfg_s { + esp_zb_basic_cluster_cfg_t basic_cfg; + esp_zb_identify_cluster_cfg_t identify_cfg; + esp_zb_carbon_dioxide_measurement_cluster_cfg_t carbon_dioxide_meas_cfg; +} zigbee_carbon_dioxide_sensor_cfg_t; + +class ZigbeeCarbonDioxideSensor : public ZigbeeEP { +public: + ZigbeeCarbonDioxideSensor(uint8_t endpoint); + ~ZigbeeCarbonDioxideSensor(); + + // Set the carbon dioxide value in ppm + void setCarbonDioxide(float carbon_dioxide); + + // Set the min and max value for the carbon dioxide sensor in ppm + void setMinMaxValue(float min, float max); + + // Set the tolerance value for the carbon dioxide sensor in ppm + void setTolerance(float tolerance); + + // Set the reporting interval for carbon dioxide measurement in seconds and delta (carbon dioxide change in ppm) + // NOTE: Delta reporting is currently not supported by the carbon dioxide sensor + void setReporting(uint16_t min_interval, uint16_t max_interval, uint16_t delta); + + // Report the carbon dioxide value + void report(); +}; + +#endif //SOC_IEEE802154_SUPPORTED && CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeDimmableLight.cpp b/libraries/Zigbee/src/ep/ZigbeeDimmableLight.cpp new file mode 100644 index 00000000000..00d3aac3752 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeDimmableLight.cpp @@ -0,0 +1,103 @@ + +#include "ZigbeeDimmableLight.h" +#if SOC_IEEE802154_SUPPORTED && CONFIG_ZB_ENABLED + +#include "esp_zigbee_cluster.h" + +ZigbeeDimmableLight::ZigbeeDimmableLight(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_DIMMABLE_LIGHT_DEVICE_ID; + + zigbee_dimmable_light_cfg_t light_cfg = ZIGBEE_DEFAULT_DIMMABLE_LIGHT_CONFIG(); + _cluster_list = zigbee_dimmable_light_clusters_create(&light_cfg); + + _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_DIMMABLE_LIGHT_DEVICE_ID, .app_device_version = 0}; + + // set default values + _current_state = false; + _current_level = 255; +} + +// set attribute method -> method overridden in child class +void ZigbeeDimmableLight::zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) { + // check the data and call right method + if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { + if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { + if (_current_state != *(bool *)message->attribute.data.value) { + _current_state = *(bool *)message->attribute.data.value; + lightChanged(); + } + return; + } else { + log_w("Received message ignored. Attribute ID: %d not supported for On/Off Light", message->attribute.id); + } + } else if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL) { + if (message->attribute.id == ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) { + if (_current_level != *(uint8_t *)message->attribute.data.value) { + _current_level = *(uint8_t *)message->attribute.data.value; + lightChanged(); + } + return; + } else { + log_w("Received message ignored. Attribute ID: %d not supported for Level Control", message->attribute.id); + // TODO: implement more attributes -> includes/zcl/esp_zigbee_zcl_level.h + } + } else { + log_w("Received message ignored. Cluster ID: %d not supported for dimmable Light", message->info.cluster); + } +} + +void ZigbeeDimmableLight::lightChanged() { + if (_on_light_change) { + _on_light_change(_current_state, _current_level); + } +} + +void ZigbeeDimmableLight::setLight(bool state, uint8_t level) { + // Update all attributes + _current_state = state; + _current_level = level; + lightChanged(); + + log_v("Updating on/off light state to %d", state); + /* Update light clusters */ + esp_zb_lock_acquire(portMAX_DELAY); + // set on/off state + esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_ON_OFF, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID, &_current_state, false + ); + // set level + esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID, &_current_level, false + ); + esp_zb_lock_release(); +} + +void ZigbeeDimmableLight::setLightState(bool state) { + setLight(state, _current_level); +} + +void ZigbeeDimmableLight::setLightLevel(uint8_t level) { + setLight(_current_state, level); +} + +esp_zb_cluster_list_t *ZigbeeDimmableLight::zigbee_dimmable_light_clusters_create(zigbee_dimmable_light_cfg_t *light_cfg) { + esp_zb_attribute_list_t *esp_zb_basic_cluster = esp_zb_basic_cluster_create(&light_cfg->basic_cfg); + esp_zb_attribute_list_t *esp_zb_identify_cluster = esp_zb_identify_cluster_create(&light_cfg->identify_cfg); + esp_zb_attribute_list_t *esp_zb_groups_cluster = esp_zb_groups_cluster_create(&light_cfg->groups_cfg); + esp_zb_attribute_list_t *esp_zb_scenes_cluster = esp_zb_scenes_cluster_create(&light_cfg->scenes_cfg); + esp_zb_attribute_list_t *esp_zb_on_off_cluster = esp_zb_on_off_cluster_create(&light_cfg->on_off_cfg); + esp_zb_attribute_list_t *esp_zb_level_cluster = esp_zb_level_cluster_create(&light_cfg->level_cfg); + + // ------------------------------ Create cluster list ------------------------------ + esp_zb_cluster_list_t *esp_zb_cluster_list = esp_zb_zcl_cluster_list_create(); + esp_zb_cluster_list_add_basic_cluster(esp_zb_cluster_list, esp_zb_basic_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(esp_zb_cluster_list, esp_zb_identify_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_groups_cluster(esp_zb_cluster_list, esp_zb_groups_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_scenes_cluster(esp_zb_cluster_list, esp_zb_scenes_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_on_off_cluster(esp_zb_cluster_list, esp_zb_on_off_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_level_cluster(esp_zb_cluster_list, esp_zb_level_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + + return esp_zb_cluster_list; +} + +#endif // SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeDimmableLight.h b/libraries/Zigbee/src/ep/ZigbeeDimmableLight.h new file mode 100644 index 00000000000..034c34899b4 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeDimmableLight.h @@ -0,0 +1,113 @@ +/* Class of Zigbee On/Off Light endpoint inherited from common EP class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if SOC_IEEE802154_SUPPORTED && CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +/** + * @brief Zigbee HA standard dimmable light device clusters. + * Added here as not supported by ESP Zigbee library. + * + * + */ +typedef struct zigbee_dimmable_light_cfg_s { + esp_zb_basic_cluster_cfg_t basic_cfg; /*!< Basic cluster configuration, @ref esp_zb_basic_cluster_cfg_s */ + esp_zb_identify_cluster_cfg_t identify_cfg; /*!< Identify cluster configuration, @ref esp_zb_identify_cluster_cfg_s */ + esp_zb_groups_cluster_cfg_t groups_cfg; /*!< Groups cluster configuration, @ref esp_zb_groups_cluster_cfg_s */ + esp_zb_scenes_cluster_cfg_t scenes_cfg; /*!< Scenes cluster configuration, @ref esp_zb_scenes_cluster_cfg_s */ + esp_zb_on_off_cluster_cfg_t on_off_cfg; /*!< On off cluster configuration, @ref esp_zb_on_off_cluster_cfg_s */ + esp_zb_level_cluster_cfg_t level_cfg; /*!< Level cluster configuration, @ref esp_zb_level_cluster_cfg_s */ +} zigbee_dimmable_light_cfg_t; + +/** + * @brief Zigbee HA standard dimmable light device default config value. + * Added here as not supported by ESP Zigbee library. + * + */ +// clang-format off +#define ZIGBEE_DEFAULT_DIMMABLE_LIGHT_CONFIG() \ + { \ + .basic_cfg = \ + { \ + .zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, \ + .power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE, \ + }, \ + .identify_cfg = \ + { \ + .identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE, \ + }, \ + .groups_cfg = \ + { \ + .groups_name_support_id = ESP_ZB_ZCL_GROUPS_NAME_SUPPORT_DEFAULT_VALUE, \ + }, \ + .scenes_cfg = \ + { \ + .scenes_count = ESP_ZB_ZCL_SCENES_SCENE_COUNT_DEFAULT_VALUE, \ + .current_scene = ESP_ZB_ZCL_SCENES_CURRENT_SCENE_DEFAULT_VALUE, \ + .current_group = ESP_ZB_ZCL_SCENES_CURRENT_GROUP_DEFAULT_VALUE, \ + .scene_valid = ESP_ZB_ZCL_SCENES_SCENE_VALID_DEFAULT_VALUE, \ + .name_support = ESP_ZB_ZCL_SCENES_NAME_SUPPORT_DEFAULT_VALUE, \ + }, \ + .on_off_cfg = \ + { \ + .on_off = ESP_ZB_ZCL_ON_OFF_ON_OFF_DEFAULT_VALUE, \ + }, \ + .level_cfg = \ + { \ + .current_level = ESP_ZB_ZCL_LEVEL_CONTROL_CURRENT_LEVEL_DEFAULT_VALUE, \ + }, \ + } +// clang-format on + +class ZigbeeDimmableLight : public ZigbeeEP { +public: + ZigbeeDimmableLight(uint8_t endpoint); + ~ZigbeeDimmableLight(); + + void onLightChange(void (*callback)(bool, uint8_t)) { + _on_light_change = callback; + } + void restoreLight() { + lightChanged(); + } + + void setLightState(bool state); + void setLightLevel(uint8_t level); + void setLight(bool state, uint8_t level); + + bool getLightState() { + return _current_state; + } + uint8_t getLightLevel() { + return _current_level; + } + +private: + void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) override; + + void lightChanged(); + // callback function to be called on light change (State, Level) + void (*_on_light_change)(bool, uint8_t); + + /** + * @brief Create a standard HA dimmable light cluster list. + * Added here as not supported by ESP Zigbee library. + * + * @note This contains basic, identify, groups, scenes, on-off, level, as server side. + * @param[in] light_cfg Configuration parameters for this cluster lists defined by @ref zigbee_dimmable_light_cfg_t + * + * @return Pointer to cluster list @ref esp_zb_cluster_list_s + * + */ + esp_zb_cluster_list_t *zigbee_dimmable_light_clusters_create(zigbee_dimmable_light_cfg_t *light_cfg); + + bool _current_state; + uint8_t _current_level; +}; + +#endif // SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeFlowSensor.cpp b/libraries/Zigbee/src/ep/ZigbeeFlowSensor.cpp new file mode 100644 index 00000000000..6adf8172194 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeFlowSensor.cpp @@ -0,0 +1,104 @@ +#include "ZigbeeFlowSensor.h" +#if SOC_IEEE802154_SUPPORTED && CONFIG_ZB_ENABLED + +esp_zb_cluster_list_t *zigbee_flow_sensor_clusters_create(zigbee_flow_sensor_cfg_t *flow_sensor) { + esp_zb_basic_cluster_cfg_t *basic_cfg = flow_sensor ? &(flow_sensor->basic_cfg) : NULL; + esp_zb_identify_cluster_cfg_t *identify_cfg = flow_sensor ? &(flow_sensor->identify_cfg) : NULL; + esp_zb_flow_meas_cluster_cfg_t *flow_meas_cfg = flow_sensor ? &(flow_sensor->flow_meas_cfg) : NULL; + esp_zb_cluster_list_t *cluster_list = esp_zb_zcl_cluster_list_create(); + esp_zb_cluster_list_add_basic_cluster(cluster_list, esp_zb_basic_cluster_create(basic_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_identify_cluster_create(identify_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_flow_meas_cluster(cluster_list, esp_zb_flow_meas_cluster_create(flow_meas_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + return cluster_list; +} + +ZigbeeFlowSensor::ZigbeeFlowSensor(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID; + + //Create custom pressure sensor configuration + zigbee_flow_sensor_cfg_t flow_sensor_cfg = ZIGBEE_DEFAULT_FLOW_SENSOR_CONFIG(); + _cluster_list = zigbee_flow_sensor_clusters_create(&flow_sensor_cfg); + + _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID, .app_device_version = 0}; +} + +void ZigbeeFlowSensor::setMinMaxValue(float min, float max) { + uint16_t zb_min = (uint16_t)(min * 10); + uint16_t zb_max = (uint16_t)(max * 10); + esp_zb_attribute_list_t *flow_measure_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_FLOW_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_update_attr(flow_measure_cluster, ESP_ZB_ZCL_ATTR_FLOW_MEASUREMENT_MIN_VALUE_ID, (void *)&zb_min); + esp_zb_cluster_update_attr(flow_measure_cluster, ESP_ZB_ZCL_ATTR_FLOW_MEASUREMENT_MAX_VALUE_ID, (void *)&zb_max); +} + +void ZigbeeFlowSensor::setTolerance(float tolerance) { + // Convert tolerance to ZCL uint16_t + uint16_t zb_tolerance = (uint16_t)(tolerance * 10); + esp_zb_attribute_list_t *flow_measure_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_FLOW_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_flow_meas_cluster_add_attr(flow_measure_cluster, ESP_ZB_ZCL_ATTR_FLOW_MEASUREMENT_TOLERANCE_ID, (void *)&zb_tolerance); +} + +void ZigbeeFlowSensor::setReporting(uint16_t min_interval, uint16_t max_interval, float delta) { + // clang-format off + esp_zb_zcl_reporting_info_t reporting_info = { + .direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV, + .ep = _endpoint, + .cluster_id = ESP_ZB_ZCL_CLUSTER_ID_FLOW_MEASUREMENT, + .cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, + .attr_id = ESP_ZB_ZCL_ATTR_FLOW_MEASUREMENT_VALUE_ID, + .u = + { + .send_info = + { + .min_interval = min_interval, + .max_interval = max_interval, + .delta = + { + .u16 = (uint16_t)(delta * 10), // Convert delta to ZCL uint16_t + }, + .def_min_interval = min_interval, + .def_max_interval = max_interval, + }, + }, + .dst = + { + .profile_id = ESP_ZB_AF_HA_PROFILE_ID, + }, + .manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC, + }; + // clang-format on + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_update_reporting_info(&reporting_info); + esp_zb_lock_release(); +} + +void ZigbeeFlowSensor::setFlow(float flow) { + uint16_t zb_flow = (uint16_t)(flow * 10); + log_v("Updating flow sensor value..."); + /* Update temperature sensor measured value */ + log_d("Setting flow to %d", zb_flow); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_FLOW_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_FLOW_MEASUREMENT_VALUE_ID, &zb_flow, false + ); + esp_zb_lock_release(); +} + +void ZigbeeFlowSensor::report() { + /* Send report attributes command */ + esp_zb_zcl_report_attr_cmd_t report_attr_cmd; + report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + report_attr_cmd.attributeID = ESP_ZB_ZCL_ATTR_FLOW_MEASUREMENT_VALUE_ID; + report_attr_cmd.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_CLI; + report_attr_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_FLOW_MEASUREMENT; + report_attr_cmd.zcl_basic_cmd.src_endpoint = _endpoint; + + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd); + esp_zb_lock_release(); + log_v("Flow report sent"); +} + +#endif //SOC_IEEE802154_SUPPORTED && CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeFlowSensor.h b/libraries/Zigbee/src/ep/ZigbeeFlowSensor.h new file mode 100644 index 00000000000..3514e2fcc1b --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeFlowSensor.h @@ -0,0 +1,60 @@ +/* Class of Zigbee Flow sensor endpoint inherited from common EP class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if SOC_IEEE802154_SUPPORTED && CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +// clang-format off +#define ZIGBEE_DEFAULT_FLOW_SENSOR_CONFIG() \ + { \ + .basic_cfg = \ + { \ + .zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, \ + .power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE, \ + }, \ + .identify_cfg = \ + { \ + .identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE, \ + }, \ + .flow_meas_cfg = \ + { \ + .measured_value = 0, \ + .min_value = 0, \ + .max_value = 0x7FFF, \ + }, \ + } +// clang-format on + +typedef struct zigbee_flow_sensor_cfg_s { + esp_zb_basic_cluster_cfg_t basic_cfg; + esp_zb_identify_cluster_cfg_t identify_cfg; + esp_zb_flow_meas_cluster_cfg_t flow_meas_cfg; +} zigbee_flow_sensor_cfg_t; + +class ZigbeeFlowSensor : public ZigbeeEP { +public: + ZigbeeFlowSensor(uint8_t endpoint); + ~ZigbeeFlowSensor(); + + // Set the flow value in 0,1 m3/h + void setFlow(float value); + + // Set the min and max value for the flow sensor in 0,1 m3/h + void setMinMaxValue(float min, float max); + + // Set the tolerance value for the flow sensor in 0,01 m3/h + void setTolerance(float tolerance); + + // Set the reporting interval for flow measurement in seconds and delta (temp change in 0,1 m3/h) + void setReporting(uint16_t min_interval, uint16_t max_interval, float delta); + + // Report the flow value + void report(); +}; + +#endif //SOC_IEEE802154_SUPPORTED && CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeOccupancySensor.cpp b/libraries/Zigbee/src/ep/ZigbeeOccupancySensor.cpp new file mode 100644 index 00000000000..3a7acee040c --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeOccupancySensor.cpp @@ -0,0 +1,60 @@ +#include "ZigbeeOccupancySensor.h" +#if SOC_IEEE802154_SUPPORTED && CONFIG_ZB_ENABLED + +esp_zb_cluster_list_t *zigbee_occupancy_sensor_clusters_create(zigbee_occupancy_sensor_cfg_t *occupancy_sensor) { + esp_zb_basic_cluster_cfg_t *basic_cfg = occupancy_sensor ? &(occupancy_sensor->basic_cfg) : NULL; + esp_zb_identify_cluster_cfg_t *identify_cfg = occupancy_sensor ? &(occupancy_sensor->identify_cfg) : NULL; + esp_zb_occupancy_sensing_cluster_cfg_t *occupancy_meas_cfg = occupancy_sensor ? &(occupancy_sensor->occupancy_meas_cfg) : NULL; + esp_zb_cluster_list_t *cluster_list = esp_zb_zcl_cluster_list_create(); + esp_zb_cluster_list_add_basic_cluster(cluster_list, esp_zb_basic_cluster_create(basic_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_identify_cluster_create(identify_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_occupancy_sensing_cluster(cluster_list, esp_zb_occupancy_sensing_cluster_create(occupancy_meas_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + return cluster_list; +} + +ZigbeeOccupancySensor::ZigbeeOccupancySensor(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID; + + //Create custom occupancy sensor configuration + zigbee_occupancy_sensor_cfg_t occupancy_sensor_cfg = ZIGBEE_DEFAULT_OCCUPANCY_SENSOR_CONFIG(); + _cluster_list = zigbee_occupancy_sensor_clusters_create(&occupancy_sensor_cfg); + + _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID, .app_device_version = 0}; +} + +void ZigbeeOccupancySensor::setSensorType(uint8_t sensor_type) { + uint8_t sensor_type_bitmap = 1 << sensor_type; + esp_zb_attribute_list_t *occupancy_sens_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_OCCUPANCY_SENSING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_update_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_OCCUPANCY_SENSOR_TYPE_ID, (void *)&sensor_type); + esp_zb_cluster_update_attr(occupancy_sens_cluster, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_OCCUPANCY_SENSOR_TYPE_BITMAP_ID, (void *)&sensor_type_bitmap); +} + +void ZigbeeOccupancySensor::setOccupancy(bool occupied) { + log_v("Updating occupancy sensor value..."); + /* Update occupancy sensor value */ + log_d("Setting occupancy to %d", occupied); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_OCCUPANCY_SENSING, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_OCCUPANCY_ID, &occupied, false + ); + esp_zb_lock_release(); +} + +void ZigbeeOccupancySensor::report() { + /* Send report attributes command */ + esp_zb_zcl_report_attr_cmd_t report_attr_cmd; + report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + report_attr_cmd.attributeID = ESP_ZB_ZCL_ATTR_OCCUPANCY_SENSING_OCCUPANCY_ID; + report_attr_cmd.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_CLI; + report_attr_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_OCCUPANCY_SENSING; + report_attr_cmd.zcl_basic_cmd.src_endpoint = _endpoint; + + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd); + esp_zb_lock_release(); + log_v("Occupancy report sent"); +} + +#endif //SOC_IEEE802154_SUPPORTED && CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeOccupancySensor.h b/libraries/Zigbee/src/ep/ZigbeeOccupancySensor.h new file mode 100644 index 00000000000..e4b25c063e5 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeOccupancySensor.h @@ -0,0 +1,54 @@ +/* Class of Zigbee Pressure sensor endpoint inherited from common EP class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if SOC_IEEE802154_SUPPORTED && CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +// clang-format off +#define ZIGBEE_DEFAULT_OCCUPANCY_SENSOR_CONFIG() \ + { \ + .basic_cfg = \ + { \ + .zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, \ + .power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE, \ + }, \ + .identify_cfg = \ + { \ + .identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE, \ + }, \ + .occupancy_meas_cfg = \ + { \ + .occupancy = ESP_ZB_ZCL_OCCUPANCY_SENSING_OCCUPANCY_UNOCCUPIED, \ + .sensor_type = ESP_ZB_ZCL_OCCUPANCY_SENSING_OCCUPANCY_SENSOR_TYPE_PIR, \ + .sensor_type_bitmap = (1 << ESP_ZB_ZCL_OCCUPANCY_SENSING_OCCUPANCY_SENSOR_TYPE_PIR), \ + }, \ + } +// clang-format on + +typedef struct zigbee_occupancy_sensor_cfg_s { + esp_zb_basic_cluster_cfg_t basic_cfg; + esp_zb_identify_cluster_cfg_t identify_cfg; + esp_zb_occupancy_sensing_cluster_cfg_t occupancy_meas_cfg; +} zigbee_occupancy_sensor_cfg_t; + +class ZigbeeOccupancySensor : public ZigbeeEP { +public: + ZigbeeOccupancySensor(uint8_t endpoint); + ~ZigbeeOccupancySensor(); + + // Set the occupancy value. True for occupied, false for unoccupied + void setOccupancy(bool occupied); + + // Set the sensor type, see esp_zb_zcl_occupancy_sensing_occupancy_sensor_type_t + void setSensorType(uint8_t sensor_type); + + // Report the occupancy value + void report(); +}; + +#endif //SOC_IEEE802154_SUPPORTED && CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeePressureSensor.cpp b/libraries/Zigbee/src/ep/ZigbeePressureSensor.cpp new file mode 100644 index 00000000000..9415502215d --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeePressureSensor.cpp @@ -0,0 +1,100 @@ +#include "ZigbeePressureSensor.h" +#if SOC_IEEE802154_SUPPORTED && CONFIG_ZB_ENABLED + +esp_zb_cluster_list_t *zigbee_pressure_sensor_clusters_create(zigbee_pressure_sensor_cfg_t *pressure_sensor) { + esp_zb_basic_cluster_cfg_t *basic_cfg = pressure_sensor ? &(pressure_sensor->basic_cfg) : NULL; + esp_zb_identify_cluster_cfg_t *identify_cfg = pressure_sensor ? &(pressure_sensor->identify_cfg) : NULL; + esp_zb_pressure_meas_cluster_cfg_t *pressure_meas_cfg = pressure_sensor ? &(pressure_sensor->pressure_meas_cfg) : NULL; + esp_zb_cluster_list_t *cluster_list = esp_zb_zcl_cluster_list_create(); + esp_zb_cluster_list_add_basic_cluster(cluster_list, esp_zb_basic_cluster_create(basic_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_identify_cluster_create(identify_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_pressure_meas_cluster(cluster_list, esp_zb_pressure_meas_cluster_create(pressure_meas_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + return cluster_list; +} + +ZigbeePressureSensor::ZigbeePressureSensor(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID; + + //Create custom pressure sensor configuration + zigbee_pressure_sensor_cfg_t presssure_sensor_cfg = ZIGBEE_DEFAULT_PRESSURE_SENSOR_CONFIG(); + _cluster_list = zigbee_pressure_sensor_clusters_create(&presssure_sensor_cfg); + + _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID, .app_device_version = 0}; +} + +void ZigbeePressureSensor::setMinMaxValue(int16_t min, int16_t max) { + + esp_zb_attribute_list_t *pressure_measure_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_PRESSURE_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_update_attr(pressure_measure_cluster, ESP_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MIN_VALUE_ID, (void *)&min); + esp_zb_cluster_update_attr(pressure_measure_cluster, ESP_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_MAX_VALUE_ID, (void *)&max); +} + +void ZigbeePressureSensor::setTolerance(uint16_t tolerance) { + esp_zb_attribute_list_t *pressure_measure_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_PRESSURE_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_temperature_meas_cluster_add_attr(pressure_measure_cluster, ESP_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_TOLERANCE_ID, (void *)&tolerance); +} + +void ZigbeePressureSensor::setReporting(uint16_t min_interval, uint16_t max_interval, uint16_t delta) { + // clang-format off + esp_zb_zcl_reporting_info_t reporting_info = { + .direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV, + .ep = _endpoint, + .cluster_id = ESP_ZB_ZCL_CLUSTER_ID_PRESSURE_MEASUREMENT, + .cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, + .attr_id = ESP_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_VALUE_ID, + .u = + { + .send_info = + { + .min_interval = min_interval, + .max_interval = max_interval, + .delta = + { + .u16 = delta, // x hPa + }, + .def_min_interval = min_interval, + .def_max_interval = max_interval, + }, + }, + .dst = + { + .profile_id = ESP_ZB_AF_HA_PROFILE_ID, + }, + .manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC, + }; + // clang-format on + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_update_reporting_info(&reporting_info); + esp_zb_lock_release(); +} + +void ZigbeePressureSensor::setPressure(int16_t pressure) { + log_v("Updating pressure sensor value..."); + /* Update temperature sensor measured value */ + log_d("Setting pressure to %d hPa", pressure); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_PRESSURE_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_VALUE_ID, &pressure, false + ); + esp_zb_lock_release(); +} + +void ZigbeePressureSensor::report() { + /* Send report attributes command */ + esp_zb_zcl_report_attr_cmd_t report_attr_cmd; + report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + report_attr_cmd.attributeID = ESP_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_VALUE_ID; + report_attr_cmd.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_CLI; + report_attr_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_PRESSURE_MEASUREMENT; + report_attr_cmd.zcl_basic_cmd.src_endpoint = _endpoint; + + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd); + esp_zb_lock_release(); + log_v("Pressure report sent"); +} + +#endif //SOC_IEEE802154_SUPPORTED && CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeePressureSensor.h b/libraries/Zigbee/src/ep/ZigbeePressureSensor.h new file mode 100644 index 00000000000..f088c033bb9 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeePressureSensor.h @@ -0,0 +1,60 @@ +/* Class of Zigbee Pressure sensor endpoint inherited from common EP class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if SOC_IEEE802154_SUPPORTED && CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +// clang-format off +#define ZIGBEE_DEFAULT_PRESSURE_SENSOR_CONFIG() \ + { \ + .basic_cfg = \ + { \ + .zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, \ + .power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE, \ + }, \ + .identify_cfg = \ + { \ + .identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE, \ + }, \ + .pressure_meas_cfg = \ + { \ + .measured_value = ESP_ZB_ZCL_ATTR_PRESSURE_MEASUREMENT_VALUE_DEFAULT_VALUE, \ + .min_value = ESP_ZB_ZCL_PATTR_RESSURE_MEASUREMENT_MIN_VALUE_DEFAULT_VALUE, \ + .max_value = ESP_ZB_ZCL_PATTR_RESSURE_MEASUREMENT_MAX_VALUE_DEFAULT_VALUE, \ + }, \ + } +// clang-format on + +typedef struct zigbee_pressure_sensor_cfg_s { + esp_zb_basic_cluster_cfg_t basic_cfg; + esp_zb_identify_cluster_cfg_t identify_cfg; + esp_zb_pressure_meas_cluster_cfg_t pressure_meas_cfg; +} zigbee_pressure_sensor_cfg_t; + +class ZigbeePressureSensor : public ZigbeeEP { +public: + ZigbeePressureSensor(uint8_t endpoint); + ~ZigbeePressureSensor(); + + // Set the pressure value in 1 hPa + void setPressure(int16_t value); + + // Set the min and max value for the pressure sensor in 1 hPa + void setMinMaxValue(int16_t min, int16_t max); + + // Set the tolerance value for the pressure sensor in 1 hPa + void setTolerance(uint16_t tolerance); + + // Set the reporting interval for pressure measurement in seconds and delta (pressure change in 1 hPa) + void setReporting(uint16_t min_interval, uint16_t max_interval, uint16_t delta); + + // Report the pressure value + void report(); +}; + +#endif //SOC_IEEE802154_SUPPORTED && CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp b/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp index 3dfac0489dd..98a3793fbad 100644 --- a/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp @@ -3,6 +3,7 @@ ZigbeeTempSensor::ZigbeeTempSensor(uint8_t endpoint) : ZigbeeEP(endpoint) { _device_id = ESP_ZB_HA_TEMPERATURE_SENSOR_DEVICE_ID; + _humidity_sensor = false; esp_zb_temperature_sensor_cfg_t temp_sensor_cfg = ESP_ZB_DEFAULT_TEMPERATURE_SENSOR_CONFIG(); _cluster_list = esp_zb_temperature_sensor_clusters_create(&temp_sensor_cfg); @@ -103,6 +104,7 @@ void ZigbeeTempSensor::addHumiditySensor(float min, float max, float tolerance) esp_zb_humidity_meas_cluster_add_attr(humidity_cluster, ESP_ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MAX_VALUE_ID, &zb_max); esp_zb_humidity_meas_cluster_add_attr(humidity_cluster, ESP_ZB_ZCL_ATTR_REL_HUMIDITY_TOLERANCE_ID, &zb_tolerance); esp_zb_cluster_list_add_humidity_meas_cluster(_cluster_list, humidity_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + _humidity_sensor = true; } void ZigbeeTempSensor::setHumidity(float humidity) { @@ -165,4 +167,11 @@ void ZigbeeTempSensor::setHumidityReporting(uint16_t min_interval, uint16_t max_ esp_zb_lock_release(); } +void ZigbeeTempSensor::report() { + reportTemperature(); + if (_humidity_sensor) { + reportHumidity(); + } +} + #endif //SOC_IEEE802154_SUPPORTED && CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeTempSensor.h b/libraries/Zigbee/src/ep/ZigbeeTempSensor.h index d868034280d..2951d4b7628 100644 --- a/libraries/Zigbee/src/ep/ZigbeeTempSensor.h +++ b/libraries/Zigbee/src/ep/ZigbeeTempSensor.h @@ -40,6 +40,12 @@ class ZigbeeTempSensor : public ZigbeeEP { // Report the humidity value void reportHumidity(); + + // Report the temperature and humidity values if humidity sensor is added + void report(); + +private: + bool _humidity_sensor; }; #endif //SOC_IEEE802154_SUPPORTED && CONFIG_ZB_ENABLED diff --git a/package/package_esp32_index.template.json b/package/package_esp32_index.template.json index 63bb102549b..310c28fad7d 100644 --- a/package/package_esp32_index.template.json +++ b/package/package_esp32_index.template.json @@ -42,7 +42,7 @@ { "packager": "esp32", "name": "esp32-arduino-libs", - "version": "idf-release_v5.3-083aad99-v1" + "version": "idf-release_v5.3-083aad99-v2" }, { "packager": "esp32", @@ -72,7 +72,7 @@ { "packager": "esp32", "name": "esptool_py", - "version": "4.9.dev1" + "version": "4.9.dev3" }, { "packager": "esp32", @@ -95,63 +95,63 @@ "tools": [ { "name": "esp32-arduino-libs", - "version": "idf-release_v5.3-083aad99-v1", + "version": "idf-release_v5.3-083aad99-v2", "systems": [ { "host": "i686-mingw32", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-083aad99-v1.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-083aad99-v1.zip", - "checksum": "SHA-256:5aabafdd3bdc2cfc4a409efc00202aee4d8b1bcb1efaf5021c02ac2e90473603", - "size": "341111216" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-083aad99-v2.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-083aad99-v2.zip", + "checksum": "SHA-256:4c6cae2e34df7e85a149615a6c18169777faf9460f708fc51d93616a117973c2", + "size": "341175680" }, { "host": "x86_64-mingw32", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-083aad99-v1.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-083aad99-v1.zip", - "checksum": "SHA-256:5aabafdd3bdc2cfc4a409efc00202aee4d8b1bcb1efaf5021c02ac2e90473603", - "size": "341111216" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-083aad99-v2.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-083aad99-v2.zip", + "checksum": "SHA-256:4c6cae2e34df7e85a149615a6c18169777faf9460f708fc51d93616a117973c2", + "size": "341175680" }, { "host": "arm64-apple-darwin", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-083aad99-v1.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-083aad99-v1.zip", - "checksum": "SHA-256:5aabafdd3bdc2cfc4a409efc00202aee4d8b1bcb1efaf5021c02ac2e90473603", - "size": "341111216" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-083aad99-v2.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-083aad99-v2.zip", + "checksum": "SHA-256:4c6cae2e34df7e85a149615a6c18169777faf9460f708fc51d93616a117973c2", + "size": "341175680" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-083aad99-v1.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-083aad99-v1.zip", - "checksum": "SHA-256:5aabafdd3bdc2cfc4a409efc00202aee4d8b1bcb1efaf5021c02ac2e90473603", - "size": "341111216" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-083aad99-v2.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-083aad99-v2.zip", + "checksum": "SHA-256:4c6cae2e34df7e85a149615a6c18169777faf9460f708fc51d93616a117973c2", + "size": "341175680" }, { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-083aad99-v1.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-083aad99-v1.zip", - "checksum": "SHA-256:5aabafdd3bdc2cfc4a409efc00202aee4d8b1bcb1efaf5021c02ac2e90473603", - "size": "341111216" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-083aad99-v2.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-083aad99-v2.zip", + "checksum": "SHA-256:4c6cae2e34df7e85a149615a6c18169777faf9460f708fc51d93616a117973c2", + "size": "341175680" }, { "host": "i686-pc-linux-gnu", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-083aad99-v1.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-083aad99-v1.zip", - "checksum": "SHA-256:5aabafdd3bdc2cfc4a409efc00202aee4d8b1bcb1efaf5021c02ac2e90473603", - "size": "341111216" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-083aad99-v2.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-083aad99-v2.zip", + "checksum": "SHA-256:4c6cae2e34df7e85a149615a6c18169777faf9460f708fc51d93616a117973c2", + "size": "341175680" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-083aad99-v1.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-083aad99-v1.zip", - "checksum": "SHA-256:5aabafdd3bdc2cfc4a409efc00202aee4d8b1bcb1efaf5021c02ac2e90473603", - "size": "341111216" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-083aad99-v2.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-083aad99-v2.zip", + "checksum": "SHA-256:4c6cae2e34df7e85a149615a6c18169777faf9460f708fc51d93616a117973c2", + "size": "341175680" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-083aad99-v1.zip", - "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-083aad99-v1.zip", - "checksum": "SHA-256:5aabafdd3bdc2cfc4a409efc00202aee4d8b1bcb1efaf5021c02ac2e90473603", - "size": "341111216" + "url": "https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.3/esp32-arduino-libs-idf-release_v5.3-083aad99-v2.zip", + "archiveFileName": "esp32-arduino-libs-idf-release_v5.3-083aad99-v2.zip", + "checksum": "SHA-256:4c6cae2e34df7e85a149615a6c18169777faf9460f708fc51d93616a117973c2", + "size": "341175680" } ] }, @@ -460,56 +460,56 @@ }, { "name": "esptool_py", - "version": "4.9.dev1", + "version": "4.9.dev3", "systems": [ { "host": "x86_64-pc-linux-gnu", - "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC2/esptool-v4.9.dev1-linux-amd64.tar.gz", - "archiveFileName": "esptool-v4.9.dev1-linux-amd64.tar.gz", - "checksum": "SHA-256:21f6c2155f0ec9e5b475c8a4bf59803d8cfb4d74f4e488a80f97da3d77542bba", - "size": "64632960" + "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC3/esptool-v4.9.dev3-linux-amd64.tar.gz", + "archiveFileName": "esptool-v4.9.dev3-linux-amd64.tar.gz", + "checksum": "SHA-256:4ecaf51836cbf4ea3c19840018bfef3b0b8cd8fc3c95f6e1e043ca5bbeab9bf0", + "size": "64958202" }, { "host": "arm-linux-gnueabihf", - "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC2/esptool-v4.9.dev1-linux-arm32.tar.gz", - "archiveFileName": "esptool-v4.9.dev1-linux-arm32.tar.gz", - "checksum": "SHA-256:818477f10814b2bd82078fc6695663ac84220d3947722ce1880a6c867d5c2997", - "size": "46042432" + "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC3/esptool-v4.9.dev3-linux-armv7.tar.gz", + "archiveFileName": "esptool-v4.9.dev3-linux-armv7.tar.gz", + "checksum": "SHA-256:fff818573bce483ee793ac83c8211f6abf764aa3350f198228859f696a0a0b36", + "size": "31530030" }, { "host": "aarch64-linux-gnu", - "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC2/esptool-v4.9.dev1-linux-arm64.tar.gz", - "archiveFileName": "esptool-v4.9.dev1-linux-arm64.tar.gz", - "checksum": "SHA-256:b377a130a4dca58f3a31c66ed0b9858cc057c998741222cccdb6e5a724651a1f", - "size": "54459357" + "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC3/esptool-v4.9.dev3-linux-aarch64.tar.gz", + "archiveFileName": "esptool-v4.9.dev3-linux-aarch64.tar.gz", + "checksum": "SHA-256:5b274bdff2f62e6a07c3c1dfa51b1128924621f661747eca3dbe0f77972f2f06", + "size": "33663882" }, { "host": "x86_64-apple-darwin", - "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC2/esptool-v4.9.dev1-macos-amd64.tar.gz", - "archiveFileName": "esptool-v4.9.dev1-macos-amd64.tar.gz", - "checksum": "SHA-256:25cc246b20230afc287ffdfe95f57b3fab23cec88a6dde3b5092ec05926b5431", - "size": "32386336" + "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC3/esptool-v4.9.dev3-macos-amd64.tar.gz", + "archiveFileName": "esptool-v4.9.dev3-macos-amd64.tar.gz", + "checksum": "SHA-256:c733c83b58fcf5f642fbb2fddb8ff24640c2c785126cba0821fb70c4a5ceea7a", + "size": "32767836" }, { "host": "arm64-apple-darwin", - "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC2/esptool-v4.9.dev1-macos-arm64.tar.gz", - "archiveFileName": "esptool-v4.9.dev1-macos-arm64.tar.gz", - "checksum": "SHA-256:b845d678db1d1559d82894e68366683a7fc3809371a5f5def67c30c9dee15912", - "size": "29841092" + "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC3/esptool-v4.9.dev3-macos-arm64.tar.gz", + "archiveFileName": "esptool-v4.9.dev3-macos-arm64.tar.gz", + "checksum": "SHA-256:83c195a15981e6a5e7a130db2ccfb21e2d8093912e5b003681f9a5abadd71af7", + "size": "30121441" }, { "host": "i686-mingw32", - "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC2/esptool-v4.9.dev1-win64.zip", - "archiveFileName": "esptool-v4.9.dev1-win64.zip", - "checksum": "SHA-256:f649a212e086b06ca6ee595feffd7a4706696ea43a2cd1a4f49352829e8ac96e", - "size": "35812159" + "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC3/esptool-v4.9.dev3-win64.zip", + "archiveFileName": "esptool-v4.9.dev3-win64.zip", + "checksum": "SHA-256:890051a4fdc684ff6f4af18d0bb27d274ca940ee0eef716a9455f8c64b25b215", + "size": "36072564" }, { "host": "x86_64-mingw32", - "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC2/esptool-v4.9.dev1-win64.zip", - "archiveFileName": "esptool-v4.9.dev1-win64.zip", - "checksum": "SHA-256:f649a212e086b06ca6ee595feffd7a4706696ea43a2cd1a4f49352829e8ac96e", - "size": "35812159" + "url": "https://github.com/espressif/arduino-esp32/releases/download/3.1.0-RC3/esptool-v4.9.dev3-win64.zip", + "archiveFileName": "esptool-v4.9.dev3-win64.zip", + "checksum": "SHA-256:890051a4fdc684ff6f4af18d0bb27d274ca940ee0eef716a9455f8c64b25b215", + "size": "36072564" } ] }, diff --git a/tools/get.exe b/tools/get.exe index 4a5e209cacf..b56f2b98384 100644 Binary files a/tools/get.exe and b/tools/get.exe differ diff --git a/tools/get.py b/tools/get.py index 058c69badb1..c791020b7e9 100755 --- a/tools/get.py +++ b/tools/get.py @@ -243,11 +243,11 @@ def unpack(filename, destination, force_extract, checksum): # noqa: C901 if filename.endswith("tar.gz"): if not cfile: cfile = tarfile.open(filename, "r:gz") - cfile.extractall(destination) + cfile.extractall(destination, filter="tar") elif filename.endswith("tar.xz"): if not cfile: cfile = tarfile.open(filename, "r:xz") - cfile.extractall(destination) + cfile.extractall(destination, filter="tar") elif filename.endswith("zip"): if not cfile: cfile = zipfile.ZipFile(filename) diff --git a/variants/yb_esp32s3_eth/pins_arduino.h b/variants/yb_esp32s3_eth/pins_arduino.h new file mode 100644 index 00000000000..77fcf6923fc --- /dev/null +++ b/variants/yb_esp32s3_eth/pins_arduino.h @@ -0,0 +1,63 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define USB_VID 0x303A +#define USB_PID 0x1001 + +static const uint8_t LED_BUILTIN = 47; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t SDA = 8; +static const uint8_t SCL = 9; + +static const uint8_t SS = 10; +static const uint8_t MOSI = 11; +static const uint8_t MISO = 13; +static const uint8_t SCK = 12; + +// Definitions for onboard WIZnet W5500 ethernet controller chip +static const uint8_t W5500_SS = 14; // W5500 chip select +static const uint8_t W5500_INT = 18; // available only if solder bridge "INT" is closed (default open) +static const uint8_t W5500_RST = 21; // set GPIO21 to INPUT (high impedance) if RST signal is unused + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +#endif /* Pins_Arduino_h */