diff --git a/.github/workflows/build-esp-web-tools.yml b/.github/workflows/build-esp-web-tools.yml new file mode 100644 index 00000000..84a4a311 --- /dev/null +++ b/.github/workflows/build-esp-web-tools.yml @@ -0,0 +1,45 @@ +name: Build ESP Web Tools + +on: + push: + branches: + - main + pull_request: + paths: + - 'esp-web-tools/**' + - '.github/workflows/build-esp-web-tools.yml' + workflow_dispatch: + release: + types: [published] + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + build-firmware: + name: Build ESP Web Tools Firmware + uses: esphome/workflows/.github/workflows/build.yml@main + with: + files: | + esp-web-tools/esp32.yaml + esp-web-tools/esp32c3.yaml + esp-web-tools/esp32s2.yaml + esp-web-tools/esp32s3.yaml + esp-web-tools/esp8266.yaml + esphome-version: 2024.7.3 + combined-name: esp-web-tools + release-summary: ${{ github.event_name == 'release' && github.event.release.body || '' }} + release-url: ${{ github.event_name == 'release' && github.event.release.url || '' }} + release-version: ${{ github.event_name == 'release' && github.event.release.tag_name || '' }} + + upload: + if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') + name: Upload to R2 + needs: + - build-firmware + uses: esphome/workflows/.github/workflows/upload.yml@main + with: + name: esp-web-tools + version: ${{ needs.build-firmware.outputs.version }} + secrets: inherit diff --git a/.github/workflows/build-esphome-web.yml b/.github/workflows/build-esphome-web.yml new file mode 100644 index 00000000..5ee9e2bb --- /dev/null +++ b/.github/workflows/build-esphome-web.yml @@ -0,0 +1,46 @@ +name: Build ESPHome Web + +on: + push: + branches: + - main + pull_request: + paths: + - 'esphome-web/**' + - '.github/workflows/build-esphome-web.yml' + workflow_dispatch: + release: + types: [published] + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + build-firmware: + name: Build ESPHome Web Firmware + uses: esphome/workflows/.github/workflows/build.yml@main + with: + files: | + esphome-web/esp32.yaml + esphome-web/esp32c3.yaml + esphome-web/esp32s2.yaml + esphome-web/esp32s3.yaml + esphome-web/esp8266.yaml + esphome-web/pico-w.yaml + esphome-version: 2024.7.3 + combined-name: esphome-web + release-summary: ${{ github.event_name == 'release' && github.event.release.body || '' }} + release-url: ${{ github.event_name == 'release' && github.event.release.url || '' }} + release-version: ${{ github.event_name == 'release' && github.event.release.tag_name || '' }} + + upload: + if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') + name: Upload to R2 + needs: + - build-firmware + uses: esphome/workflows/.github/workflows/upload.yml@main + with: + name: esphome-web + version: ${{ needs.build-firmware.outputs.version }} + secrets: inherit diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 2a2b616d..00000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,194 +0,0 @@ -name: Build - -# yamllint disable-line rule:truthy -on: - release: - types: [published] - workflow_dispatch: - pull_request: - -concurrency: - # yamllint disable-line rule:line-length - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -env: - FIRMWARES: esp-web-tools esphome-web voice-assistant wake-word-voice-assistant bluetooth-proxy media-player - # VOICE_ASSISTANT_VERSION: 2024.4.2 - # WAKE_WORD_VOICE_ASSISTANT_VERSION: 2024.4.2 - -jobs: - prepare: - name: Prepare matrix - runs-on: ubuntu-latest - outputs: - matrix: ${{ steps.prepare-matrix.outputs.matrix }} - steps: - - uses: actions/checkout@v4 - - name: Get changed files - id: changes - uses: masesgroup/retrieve-changed-files@v3 - if: github.event_name == 'pull_request' - - name: Prepare matrix - id: prepare-matrix - run: |- - matrix="" - full_run=$(! [[ "${{ github.event_name }}" != "pull_request" || "${{ steps.changes.outputs.modified }}" == *".github/workflows/build.yml"* ]]; echo $?) - for firmware in $FIRMWARES; do - for device in $firmware/*.yaml; do - # If pull_request event type and changed files do not contain the device, skip it - if [[ $full_run -eq 0 && "${{ steps.changes.outputs.added_modified }}" != *"${device}"* ]]; then - continue - fi - device=${device##*/} - device=${device%.yaml} - version="latest" - fw=${firmware//-/_} - fw=${fw^^} - fw_version=${fw}_VERSION - if [[ -n "${!fw_version}" ]]; then - version=${!fw_version} - fi - matrix="$matrix{\"firmware\":\"$firmware\",\"device\":\"$device\", \"version\":\"$version\"}," - done - done - matrix=${matrix%?} - matrix="{\"include\":[$matrix]}" - echo matrix=$matrix >> $GITHUB_OUTPUT - - build: - name: ${{ matrix.firmware }} / ${{ matrix.device }} - runs-on: ubuntu-latest - needs: prepare - strategy: - max-parallel: 5 - fail-fast: false - matrix: ${{ fromJson(needs.prepare.outputs.matrix) }} - steps: - - uses: actions/checkout@v4 - - name: Build Firmware - uses: esphome/build-action@v3.2.0 - id: esphome-build - with: - yaml_file: ${{ matrix.firmware }}/${{ matrix.device }}.yaml - version: ${{ matrix.version || 'latest' }} - cache: true - - name: Move generated files to output - run: | - mkdir -p output/${{ matrix.device }} - mv ${{ steps.esphome-build.outputs.name }}/* output/${{ matrix.device }}/ - echo ${{ steps.esphome-build.outputs.version }} > output/${{ matrix.device }}/version - echo ${{ steps.esphome-build.outputs.project-version }} > output/${{ matrix.device }}/project_version - - name: Alter manifest path - if: ${{ matrix.device != 'pico-w' }} - run: | - sed -i 's/${{ steps.esphome-build.outputs.name }}\//\/${{ matrix.firmware }}\/${{ matrix.device }}\//g' output/${{ matrix.device }}/manifest.json - - uses: actions/upload-artifact@v4.3.4 - if: ${{ ! contains(matrix.device, 'adopted') }} - with: - name: build-${{ matrix.firmware }}-${{ matrix.device }} - path: output - retention-days: 1 - - combined-manifests: - name: Combine ${{ matrix.project }} manifests - runs-on: ubuntu-latest - needs: build - strategy: - fail-fast: false - matrix: - include: - - project: esp-web-tools - name: ESP Web Tools Example - - project: esphome-web - name: ESPHome Web - steps: - - uses: actions/download-artifact@v4.1.8 - with: - pattern: build-${{ matrix.project }}-* - merge-multiple: true - path: files - - name: Generate manifest.json - run: | - version=$(cat files/*/version | sort -V | tail -n 1) - jq -s --arg version "$version" '{"name": "${{ matrix.name }}", "version": $version, "home_assistant_domain": "esphome", "builds":.}' files/*/manifest.json > files/manifest.json - - uses: actions/upload-artifact@v4.3.4 - with: - name: ${{ matrix.project }} - path: files - retention-days: 1 - - full-manifests: - name: Create ${{ matrix.project }} manifest - runs-on: ubuntu-latest - needs: build - strategy: - fail-fast: false - matrix: - include: - - project: voice-assistant - name: Voice Assistant - - project: wake-word-voice-assistant - name: Voice Assistant - - project: bluetooth-proxy - name: Bluetooth Proxy - - project: media-player - name: Media Player - steps: - - uses: actions/download-artifact@v4.1.8 - with: - pattern: build-${{ matrix.project }}-* - merge-multiple: true - path: files - - name: Generate manifest.json files - run: | - cd files - for device in */; do - mkdir -p ../output/$device - pushd $device - version=$(cat project_version) - jq --arg version "$version" '{"name": "${{ matrix.name }}", "version": $version, "home_assistant_domain": "esphome", "new_install_skip_erase": false, "builds":[.]}' manifest.json > manifest.tmp.json - mv manifest.tmp.json manifest.json - popd - done - - uses: actions/upload-artifact@v4.3.4 - with: - name: ${{ matrix.project }} - path: files - retention-days: 1 - - consolidate: - name: Consolidate firmwares - runs-on: ubuntu-latest - needs: - - combined-manifests - - full-manifests - steps: - - uses: actions/checkout@v4 - - uses: actions/download-artifact@v4.1.8 - with: - pattern: "!build-*" - path: output - - run: cp -R static/* output/ - - uses: actions/upload-pages-artifact@v3.0.1 - with: - path: output - retention-days: 1 - - deploy: - if: (github.event_name == 'workflow_dispatch' && startsWith(github.ref, 'refs/tags/')) || github.event_name == 'release' - name: Deploy to GitHub Pages - runs-on: ubuntu-latest - needs: consolidate - permissions: - pages: write - id-token: write - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - steps: - - name: Setup Pages - uses: actions/configure-pages@v5 - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@v4.0.5 diff --git a/.github/workflows/yaml-lint.yml b/.github/workflows/yaml-lint.yml index 20e92be0..161495e5 100644 --- a/.github/workflows/yaml-lint.yml +++ b/.github/workflows/yaml-lint.yml @@ -1,6 +1,5 @@ name: YAML lint -# yamllint disable-line rule:truthy on: push: branches: [main] @@ -14,12 +13,10 @@ on: jobs: yamllint: - name: yamllint + name: 🧹 yamllint runs-on: ubuntu-latest steps: - - name: Check out code from GitHub - uses: actions/checkout@v4.1.1 - - name: Run yamllint - uses: frenck/action-yamllint@v1.5.0 - with: - strict: true + - name: ⤵️ Check out configuration from GitHub + uses: actions/checkout@v4.1.7 + - name: 🚀 Run yamllint + run: yamllint --strict . diff --git a/.yamllint b/.yamllint index a85a6387..22e9237f 100644 --- a/.yamllint +++ b/.yamllint @@ -1,5 +1,4 @@ --- - extends: default ignore-from-file: .gitignore @@ -17,3 +16,4 @@ rules: indent-sequences: true check-multi-line-strings: false line-length: disable + truthy: disable diff --git a/bluetooth-proxy/esp32-generic-c3.yaml b/bluetooth-proxy/esp32-generic-c3.yaml index d5490113..823a66d5 100644 --- a/bluetooth-proxy/esp32-generic-c3.yaml +++ b/bluetooth-proxy/esp32-generic-c3.yaml @@ -1,67 +1,2 @@ -substitutions: - name: esp32-bluetooth-proxy - friendly_name: Bluetooth Proxy - -esphome: - name: ${name} - friendly_name: ${friendly_name} - min_version: 2024.6.0 - name_add_mac_suffix: true - project: - name: esphome.bluetooth-proxy - version: "24.7.4.1" - platformio_options: - board_build.f_flash: 40000000L - board_build.flash_mode: dio - board_build.flash_size: 4MB - -esp32: - board: esp32-c3-devkitm-1 - framework: - type: esp-idf - sdkconfig_options: - CONFIG_BT_BLE_42_FEATURES_SUPPORTED: y - CONFIG_BT_BLE_50_FEATURES_SUPPORTED: n - -wifi: - ap: - -api: -logger: -improv_serial: - -ota: - - platform: esphome - id: ota_esphome - - platform: http_request - id: ota_http_request - -update: - - platform: http_request - id: update_http_request - name: Firmware - source: https://firmware.esphome.io/bluetooth-proxy/esp32-generic-c3/manifest.json - -http_request: - -dashboard_import: - package_import_url: github://esphome/firmware/bluetooth-proxy/esp32-generic-c3.yaml@main - -esp32_ble_tracker: - scan_parameters: - # We currently use the defaults to ensure Bluetooth - # can co-exist with WiFi In the future we may be able to - # enable the built-in coexistence logic in ESP-IDF - active: true - -bluetooth_proxy: - active: true - -button: - - platform: safe_mode - id: button_safe_mode - name: Safe Mode Boot - - - platform: factory_reset - id: factory_reset_btn - name: Factory reset +packages: + moved: github://esphome/bluetooth-proxies/esp32-generic/esp32-generic-c3.yaml@main diff --git a/bluetooth-proxy/esp32-generic.yaml b/bluetooth-proxy/esp32-generic.yaml index 591996e3..6e6e85bc 100644 --- a/bluetooth-proxy/esp32-generic.yaml +++ b/bluetooth-proxy/esp32-generic.yaml @@ -1,60 +1,2 @@ -substitutions: - name: esp32-bluetooth-proxy - friendly_name: Bluetooth Proxy - -esphome: - name: ${name} - friendly_name: ${friendly_name} - min_version: 2024.6.0 - name_add_mac_suffix: true - project: - name: esphome.bluetooth-proxy - version: "24.7.4.1" - -esp32: - board: esp32dev - framework: - type: esp-idf - -wifi: - ap: - -api: -logger: -improv_serial: - -ota: - - platform: esphome - id: ota_esphome - - platform: http_request - id: ota_http_request - -update: - - platform: http_request - id: update_http_request - name: Firmware - source: https://firmware.esphome.io/bluetooth-proxy/esp32-generic/manifest.json - -http_request: - -dashboard_import: - package_import_url: github://esphome/firmware/bluetooth-proxy/esp32-generic.yaml@main - -esp32_ble_tracker: - scan_parameters: - # We currently use the defaults to ensure Bluetooth - # can co-exist with WiFi In the future we may be able to - # enable the built-in coexistence logic in ESP-IDF - active: true - -bluetooth_proxy: - active: true - -button: - - platform: safe_mode - id: button_safe_mode - name: Safe Mode Boot - - - platform: factory_reset - id: factory_reset_btn - name: Factory reset +packages: + moved: github://esphome/bluetooth-proxies/esp32-generic/esp32-generic.yaml@main diff --git a/bluetooth-proxy/gl-s10.yaml b/bluetooth-proxy/gl-s10.yaml index 6b4fcb42..3171520b 100644 --- a/bluetooth-proxy/gl-s10.yaml +++ b/bluetooth-proxy/gl-s10.yaml @@ -1,125 +1,2 @@ -# Instructions on opening and wiring for flashing on https://blakadder.com/gl-s10 - -substitutions: - name: gl-s10-bt-proxy - friendly_name: Bluetooth Proxy - -esphome: - name: ${name} - friendly_name: ${friendly_name} - min_version: 2024.6.0 - name_add_mac_suffix: true - project: - name: esphome.bluetooth-proxy - version: "24.7.4.1" - # turn on Power LED when esphome boots - on_boot: - then: - - output.turn_on: power_led - -esp32: - board: esp32doit-devkit-v1 - framework: - type: esp-idf - -# Configuration fo V2.3 hardware revision -ethernet: - type: IP101 - mdc_pin: GPIO23 - mdio_pin: GPIO18 - clk_mode: GPIO0_IN - phy_addr: 1 - power_pin: GPIO5 - -# Comment the above and use this instead for V1.0 revision of the hardware -# ethernet: -# type: LAN8720 -# mdc_pin: GPIO23 -# mdio_pin: GPIO18 -# clk_mode: GPIO17_OUT -# phy_addr: 1 - -api: -logger: -ota: - - platform: esphome - id: ota_esphome - - platform: http_request - id: ota_http_request - -update: - - platform: http_request - id: update_http_request - name: Firmware - source: https://firmware.esphome.io/bluetooth-proxy/gl-s10/manifest.json - -http_request: - -dashboard_import: - package_import_url: github://esphome/firmware/bluetooth-proxy/gl-s10.yaml@main - -esp32_ble_tracker: - scan_parameters: - interval: 1100ms - window: 1100ms - active: true -# -# The LED is disabled for ESPHome 2023.6.0+ since we do not -# decode the advertising packets on device anymore, and adding -# the LED blink would force the device to decode the packets -# just to blink the LED. -# -# Bluetooth LED blinks when receiving Bluetooth advertising -# on_ble_advertise: -# then: -# - output.turn_on: bluetooth_led -# - delay: 0.5s -# - output.turn_off: bluetooth_led - -bluetooth_proxy: - active: true - -button: - - platform: safe_mode - id: button_safe_mode - name: Safe Mode Boot - - - platform: factory_reset - id: factory_reset_btn - name: Factory reset - -## DEVICE SPECIFIC CONFIGURATION -# network LED (white one) configured as status led -status_led: - pin: - number: GPIO32 - inverted: true - -# button on the side labeled RESET -binary_sensor: - - platform: gpio - pin: - number: GPIO33 - inverted: true - name: "Reset Button" - id: binary_sensor_reset_button - -# output settings for LED's marked Power and Bluetooth -# power LED use: see code line 15 -# bluetooth LED use: see code line 60 -output: - - platform: gpio - pin: GPIO14 - inverted: true - id: power_led - - platform: gpio - pin: GPIO12 - inverted: true - id: bluetooth_led - -# since these pins are broken out inside and labeled as I2C pins they're configured here -i2c: - - id: i2c_bus - sda: 15 - scl: 13 - scan: true +packages: + moved: github://esphome/bluetooth-proxies/gl-inet/gl-s10.yaml@main diff --git a/bluetooth-proxy/lilygo-t-eth-poe.yaml b/bluetooth-proxy/lilygo-t-eth-poe.yaml index 57f267bd..e3008c82 100644 --- a/bluetooth-proxy/lilygo-t-eth-poe.yaml +++ b/bluetooth-proxy/lilygo-t-eth-poe.yaml @@ -1,65 +1,2 @@ -substitutions: - name: "lilygo-ttgo-poe-bt-proxy" - friendly_name: Bluetooth Proxy - -esphome: - name: ${name} - friendly_name: ${friendly_name} - min_version: 2024.6.0 - name_add_mac_suffix: true - project: - name: esphome.bluetooth-proxy - version: "24.7.4.1" - -esp32: - # Platform.io does not have an explicit profile for the module. - # We can treat it like a standard dev board based around a standard WROOM module. - # See: https://github.com/Xinyuan-LilyGO/LilyGO-T-ETH-POE - board: esp32dev - framework: - type: esp-idf - -# See: https://esphome.io/components/ethernet.html#configuration-for-lilygo-ttgo-t-internet-poe-esp32-wroom-lan8270a-chip -ethernet: - type: LAN8720 - mdc_pin: GPIO23 - mdio_pin: GPIO18 - clk_mode: GPIO17_OUT - phy_addr: 0 - -api: -logger: -ota: - - platform: esphome - id: ota_esphome - - platform: http_request - id: ota_http_request - -update: - - platform: http_request - id: update_http_request - name: Firmware - source: https://firmware.esphome.io/bluetooth-proxy/lilygo-t-eth-poe/manifest.json - -http_request: - -dashboard_import: - package_import_url: github://esphome/firmware/bluetooth-proxy/lilygo-t-eth-poe.yaml@main - -esp32_ble_tracker: - scan_parameters: - interval: 1100ms - window: 1100ms - active: true - -bluetooth_proxy: - active: true - -button: - - platform: safe_mode - id: button_safe_mode - name: Safe Mode Boot - - - platform: factory_reset - id: factory_reset_btn - name: Factory reset +packages: + moved: github://esphome/bluetooth-proxies/lilygo/lilygo-t-eth-poe.yaml@main diff --git a/bluetooth-proxy/m5stack-atom-lite.yaml b/bluetooth-proxy/m5stack-atom-lite.yaml index f79e0a1d..937aace4 100644 --- a/bluetooth-proxy/m5stack-atom-lite.yaml +++ b/bluetooth-proxy/m5stack-atom-lite.yaml @@ -1,60 +1,2 @@ -substitutions: - name: atom-bluetooth-proxy - friendly_name: Bluetooth Proxy - -esphome: - name: ${name} - friendly_name: ${friendly_name} - min_version: 2024.6.0 - name_add_mac_suffix: true - project: - name: esphome.bluetooth-proxy - version: "24.7.4.1" - -esp32: - board: m5stack-atom - framework: - type: esp-idf - -wifi: - ap: - -api: -logger: -improv_serial: - -ota: - - platform: esphome - id: ota_esphome - - platform: http_request - id: ota_http_request - -update: - - platform: http_request - id: update_http_request - name: Firmware - source: https://firmware.esphome.io/bluetooth-proxy/m5stack-atom-lite/manifest.json - -http_request: - -dashboard_import: - package_import_url: github://esphome/firmware/bluetooth-proxy/m5stack-atom-lite.yaml@main - -esp32_ble_tracker: - scan_parameters: - # We currently use the defaults to ensure Bluetooth - # can co-exist with WiFi In the future we may be able to - # enable the built-in coexistence logic in ESP-IDF - active: true - -bluetooth_proxy: - active: true - -button: - - platform: safe_mode - id: button_safe_mode - name: Safe Mode Boot - - - platform: factory_reset - id: factory_reset_btn - name: Factory reset +packages: + moved: github://esphome/bluetooth-proxies/m5stack/m5stack-atom-lite.yaml@main diff --git a/bluetooth-proxy/m5stack-atomS3.yaml b/bluetooth-proxy/m5stack-atomS3.yaml index 219146b8..100b3f60 100644 --- a/bluetooth-proxy/m5stack-atomS3.yaml +++ b/bluetooth-proxy/m5stack-atomS3.yaml @@ -1,63 +1,2 @@ -substitutions: - name: atom-bluetooth-proxy - friendly_name: Bluetooth Proxy - -esphome: - name: ${name} - friendly_name: ${friendly_name} - min_version: 2024.6.0 - name_add_mac_suffix: true - project: - name: esphome.bluetooth-proxy - version: "24.7.4.1" - -esp32: - board: m5stack-atoms3 - variant: esp32s3 - framework: - type: esp-idf - version: 5.0.2 - platform_version: 6.3.2 - -wifi: - ap: - -api: -logger: -improv_serial: - -ota: - - platform: esphome - id: ota_esphome - - platform: http_request - id: ota_http_request - -update: - - platform: http_request - id: update_http_request - name: Firmware - source: https://firmware.esphome.io/bluetooth-proxy/m5stack-atomS3/manifest.json - -http_request: - -dashboard_import: - package_import_url: github://esphome/firmware/bluetooth-proxy/m5stack-atomS3.yaml@main - -esp32_ble_tracker: - scan_parameters: - # We currently use the defaults to ensure Bluetooth - # can co-exist with WiFi In the future we may be able to - # enable the built-in coexistence logic in ESP-IDF - active: true - -bluetooth_proxy: - active: true - -button: - - platform: safe_mode - id: button_safe_mode - name: Safe Mode Boot - - - platform: factory_reset - id: factory_reset_btn - name: Factory reset +packages: + moved: github://esphome/bluetooth-proxies/m5stack/m5stack-atom-s3.yaml@main diff --git a/bluetooth-proxy/olimex-esp32-poe-iso.yaml b/bluetooth-proxy/olimex-esp32-poe-iso.yaml index 0ff3ea08..a3c465d5 100644 --- a/bluetooth-proxy/olimex-esp32-poe-iso.yaml +++ b/bluetooth-proxy/olimex-esp32-poe-iso.yaml @@ -1,62 +1,2 @@ -substitutions: - name: olimex-bluetooth-proxy - friendly_name: Bluetooth Proxy - -esphome: - name: ${name} - friendly_name: ${friendly_name} - min_version: 2024.6.0 - name_add_mac_suffix: true - project: - name: esphome.bluetooth-proxy - version: "24.7.4.1" - -esp32: - board: esp32-poe-iso - framework: - type: esp-idf - -ethernet: - type: LAN8720 - mdc_pin: GPIO23 - mdio_pin: GPIO18 - clk_mode: GPIO17_OUT - phy_addr: 0 - power_pin: GPIO12 - -api: -logger: -ota: - - platform: esphome - id: ota_esphome - - platform: http_request - id: ota_http_request - -update: - - platform: http_request - id: update_http_request - name: Firmware - source: https://firmware.esphome.io/bluetooth-proxy/olimex-esp32-poe-iso/manifest.json - -http_request: - -dashboard_import: - package_import_url: github://esphome/firmware/bluetooth-proxy/olimex-esp32-poe-iso.yaml@main - -esp32_ble_tracker: - scan_parameters: - interval: 1100ms - window: 1100ms - active: true - -bluetooth_proxy: - active: true - -button: - - platform: safe_mode - id: button_safe_mode - name: Safe Mode Boot - - - platform: factory_reset - id: factory_reset_btn - name: Factory reset +packages: + moved: github://esphome/bluetooth-proxies/olimex/olimex-esp32-poe-iso.yaml@main diff --git a/bluetooth-proxy/wt32-eth01.yaml b/bluetooth-proxy/wt32-eth01.yaml index 9e090728..6c43eb42 100644 --- a/bluetooth-proxy/wt32-eth01.yaml +++ b/bluetooth-proxy/wt32-eth01.yaml @@ -1,62 +1,2 @@ -substitutions: - name: wt32-eth01-bt-proxy - friendly_name: Bluetooth Proxy - -esphome: - name: ${name} - friendly_name: ${friendly_name} - min_version: 2024.6.0 - name_add_mac_suffix: true - project: - name: esphome.bluetooth-proxy - version: "24.7.4.1" - -esp32: - board: wt32-eth01 - framework: - type: esp-idf - -ethernet: - type: LAN8720 - mdc_pin: GPIO23 - mdio_pin: GPIO18 - clk_mode: GPIO0_IN - phy_addr: 1 - power_pin: GPIO16 - -api: -logger: -ota: - - platform: esphome - id: ota_esphome - - platform: http_request - id: ota_http_request - -update: - - platform: http_request - id: update_http_request - name: Firmware - source: https://firmware.esphome.io/bluetooth-proxy/wt32-eth01/manifest.json - -http_request: - -dashboard_import: - package_import_url: github://esphome/firmware/bluetooth-proxy/wt32-eth01.yaml@main - -esp32_ble_tracker: - scan_parameters: - interval: 1100ms - window: 1100ms - active: true - -bluetooth_proxy: - active: true - -button: - - platform: safe_mode - id: button_safe_mode - name: Safe Mode Boot - - - platform: factory_reset - id: factory_reset_btn - name: Factory reset +packages: + moved: github://esphome/bluetooth-proxies/wt32/wt32-eth01.yaml@main diff --git a/esp-web-tools/esp32.yaml b/esp-web-tools/esp32.yaml index 04ea938c..58b58217 100644 --- a/esp-web-tools/esp32.yaml +++ b/esp-web-tools/esp32.yaml @@ -9,7 +9,7 @@ esphome: name_add_mac_suffix: true project: name: esphome.esp_web_tools_example - version: "1.0" + version: dev esp32: board: esp32dev diff --git a/esp-web-tools/esp32c3.yaml b/esp-web-tools/esp32c3.yaml index 2b296dbb..8b69d4b2 100644 --- a/esp-web-tools/esp32c3.yaml +++ b/esp-web-tools/esp32c3.yaml @@ -9,7 +9,7 @@ esphome: name_add_mac_suffix: true project: name: esphome.esp_web_tools_example - version: "1.0" + version: dev esp32: board: esp32-c3-devkitm-1 diff --git a/esp-web-tools/esp32s2.yaml b/esp-web-tools/esp32s2.yaml index 565267f5..ba683ffb 100644 --- a/esp-web-tools/esp32s2.yaml +++ b/esp-web-tools/esp32s2.yaml @@ -11,7 +11,7 @@ esphome: board_build.flash_mode: dio project: name: esphome.esp_web_tools_example - version: "1.0" + version: dev esp32: board: esp32-s2-saola-1 diff --git a/esp-web-tools/esp32s3.yaml b/esp-web-tools/esp32s3.yaml index 14a57564..ec6c388d 100644 --- a/esp-web-tools/esp32s3.yaml +++ b/esp-web-tools/esp32s3.yaml @@ -11,7 +11,7 @@ esphome: board_build.flash_mode: dio project: name: esphome.esp_web_tools_example - version: "1.0" + version: dev esp32: board: esp32-s3-devkitc-1 diff --git a/esp-web-tools/esp8266.yaml b/esp-web-tools/esp8266.yaml index f5eb2a91..e206a198 100644 --- a/esp-web-tools/esp8266.yaml +++ b/esp-web-tools/esp8266.yaml @@ -9,7 +9,7 @@ esphome: name_add_mac_suffix: true project: name: esphome.esp_web_tools_example - version: "1.0" + version: dev esp8266: board: esp01_1m diff --git a/esphome-web/esp32.yaml b/esphome-web/esp32.yaml index 2cc8ce7a..aa3d361c 100644 --- a/esphome-web/esp32.yaml +++ b/esphome-web/esp32.yaml @@ -9,7 +9,7 @@ esphome: name_add_mac_suffix: true project: name: esphome.web - version: "1.0" + version: dev esp32: board: esp32dev diff --git a/esphome-web/esp32c3.yaml b/esphome-web/esp32c3.yaml index 5ac2e24d..8f7c7cc0 100644 --- a/esphome-web/esp32c3.yaml +++ b/esphome-web/esp32c3.yaml @@ -9,7 +9,7 @@ esphome: name_add_mac_suffix: true project: name: esphome.web - version: "1.0" + version: dev esp32: board: esp32-c3-devkitm-1 diff --git a/esphome-web/esp32s2.yaml b/esphome-web/esp32s2.yaml index a1e486f7..c6dfb807 100644 --- a/esphome-web/esp32s2.yaml +++ b/esphome-web/esp32s2.yaml @@ -11,7 +11,7 @@ esphome: board_build.flash_mode: dio project: name: esphome.web - version: "1.0" + version: dev esp32: board: esp32-s2-saola-1 diff --git a/esphome-web/esp32s3.yaml b/esphome-web/esp32s3.yaml index d63f68d8..edeba6c5 100644 --- a/esphome-web/esp32s3.yaml +++ b/esphome-web/esp32s3.yaml @@ -11,7 +11,7 @@ esphome: board_build.flash_mode: dio project: name: esphome.web - version: "1.0" + version: dev esp32: board: esp32-s3-devkitc-1 diff --git a/esphome-web/esp8266.yaml b/esphome-web/esp8266.yaml index 023c9179..6489c56b 100644 --- a/esphome-web/esp8266.yaml +++ b/esphome-web/esp8266.yaml @@ -9,7 +9,7 @@ esphome: name_add_mac_suffix: true project: name: esphome.web - version: "1.0" + version: dev esp8266: board: esp01_1m diff --git a/esphome-web/pico-w.yaml b/esphome-web/pico-w.yaml index 027b97c1..22f3e709 100644 --- a/esphome-web/pico-w.yaml +++ b/esphome-web/pico-w.yaml @@ -9,7 +9,7 @@ esphome: name_add_mac_suffix: true project: name: esphome.web - version: "1.0" + version: dev rp2040: board: rpipicow diff --git a/media-player/m5stack-atom-echo.yaml b/media-player/m5stack-atom-echo.yaml index 7e95be0f..34458e03 100644 --- a/media-player/m5stack-atom-echo.yaml +++ b/media-player/m5stack-atom-echo.yaml @@ -1,153 +1,2 @@ -esphome: - name: m5stack-atom-echo - friendly_name: M5Stack Atom Echo - min_version: 2024.6.0 - name_add_mac_suffix: true - project: - name: m5stack.atom-echo - version: "24.7.4.1" - -esp32: - board: m5stack-atom - framework: - type: arduino - -logger: -api: - -ota: - - platform: esphome - id: ota_esphome - - platform: http_request - id: ota_http_request - -update: - - platform: http_request - id: update_http_request - name: Firmware - source: https://firmware.esphome.io/media-player/m5stack-atom-echo/manifest.json - -http_request: - verify_ssl: false - -dashboard_import: - package_import_url: github://esphome/firmware/media-player/m5stack-atom-echo.yaml@main - -wifi: - ap: - -captive_portal: - -improv_serial: - -i2s_audio: - - id: i2s_audio_bus - i2s_lrclk_pin: GPIO33 - i2s_bclk_pin: GPIO19 - -microphone: - - platform: i2s_audio - id: echo_microphone - i2s_din_pin: GPIO23 - adc_type: external - pdm: true - -voice_assistant: - microphone: echo_microphone - on_start: - - light.turn_on: - id: led - blue: 100% - red: 0% - green: 0% - effect: none - on_tts_start: - - light.turn_on: - id: led - blue: 0% - red: 0% - green: 100% - effect: none - on_tts_end: - - media_player.play_media: !lambda return x; - - light.turn_on: - id: led - blue: 0% - red: 0% - green: 100% - effect: pulse - on_end: - - delay: 1s - - wait_until: - not: - media_player.is_playing: media_out - - light.turn_off: led - on_error: - - light.turn_on: - id: led - blue: 0% - red: 100% - green: 0% - effect: none - - delay: 1s - - light.turn_off: led - -binary_sensor: - - platform: gpio - pin: - number: GPIO39 - inverted: true - name: Button - id: echo_button - on_multi_click: - - timing: - - ON FOR AT MOST 350ms - - OFF FOR AT LEAST 10ms - then: - - media_player.toggle: media_out - - timing: - - ON FOR AT LEAST 350ms - then: - - if: - condition: - media_player.is_playing: media_out - then: - - media_player.stop: media_out - - voice_assistant.start: - - timing: - - ON FOR AT LEAST 350ms - - OFF FOR AT LEAST 10ms - then: - - voice_assistant.stop: - -media_player: - - platform: i2s_audio - id: media_out - name: None - dac_type: external - i2s_dout_pin: GPIO22 - mode: mono - -light: - - platform: esp32_rmt_led_strip - id: led - name: None - pin: GPIO27 - default_transition_length: 0s - chipset: SK6812 - num_leds: 1 - rgb_order: grb - rmt_channel: 0 - effects: - - pulse: - transition_length: 250ms - update_interval: 250ms - -button: - - platform: safe_mode - id: button_safe_mode - name: Safe Mode Boot - - - platform: factory_reset - id: factory_reset_btn - name: Factory reset +packages: + moved: github://esphome/media-players/m5stack/m5stack-atom-echo.yaml@main diff --git a/media-player/m5stack-atom-speaker-kit.yaml b/media-player/m5stack-atom-speaker-kit.yaml index 4c6ee9f9..f0d0c9bb 100644 --- a/media-player/m5stack-atom-speaker-kit.yaml +++ b/media-player/m5stack-atom-speaker-kit.yaml @@ -1,82 +1,2 @@ -esphome: - name: m5stack-atom-speaker-kit - friendly_name: M5Stack Atom Speaker Kit - min_version: 2024.6.0 - name_add_mac_suffix: true - project: - name: m5stack.atom-speaker-kit - version: "24.7.4.1" - -esp32: - board: m5stack-atom - framework: - type: arduino - -logger: -api: - -ota: - - platform: esphome - id: ota_esphome - - platform: http_request - id: ota_http_request - -update: - - platform: http_request - id: update_http_request - name: Firmware - source: https://firmware.esphome.io/media-player/m5stack-atom-speaker-kit/manifest.json - -http_request: - verify_ssl: false - -dashboard_import: - package_import_url: github://esphome/firmware/media-player/m5stack-atom-speaker-kit.yaml@main - -wifi: - ap: - -captive_portal: - -improv_serial: - -i2s_audio: - - id: i2s_audio_bus - i2s_lrclk_pin: GPIO21 - i2s_bclk_pin: GPIO22 - -media_player: - - platform: i2s_audio - id: media_out - name: None - dac_type: external - i2s_dout_pin: GPIO25 - mode: mono - -binary_sensor: - - platform: gpio - pin: - number: GPIO39 - inverted: true - id: top_button - name: Button - on_click: - - media_player.toggle: media_out - -light: - - platform: fastled_clockless - id: led - name: None - pin: GPIO27 - chipset: SK6812 - num_leds: 1 - rgb_order: grb - -button: - - platform: safe_mode - id: button_safe_mode - name: Safe Mode Boot - - - platform: factory_reset - id: factory_reset_btn - name: Factory reset +packages: + moved: github://esphome/media-players/m5stack/m5stack-atom-speaker-kit.yaml@main diff --git a/media-player/onju-voice.yaml b/media-player/onju-voice.yaml index 95ce950f..1d3f3c20 100644 --- a/media-player/onju-voice.yaml +++ b/media-player/onju-voice.yaml @@ -1,500 +1,2 @@ -esphome: - name: onju-voice - friendly_name: Onju Voice - min_version: 2024.6.0 - name_add_mac_suffix: true - project: - name: onju.voice-voice-assistant - version: "24.7.4.1" - on_boot: - then: - - light.turn_on: - id: top_led - effect: slow_pulse - red: 100% - green: 60% - blue: 0% - - wait_until: - condition: - wifi.connected: - - light.turn_on: - id: top_led - effect: pulse - red: 0% - green: 100% - blue: 0% - - wait_until: - condition: - api.connected: - - light.turn_on: - id: top_led - effect: none - red: 0% - green: 100% - blue: 0% - - delay: 1s - - script.execute: reset_led - -esp32: - board: esp32-s3-devkitc-1 - framework: - type: arduino - -logger: - -api: - services: - - service: start_va - then: - - voice_assistant.start - - service: stop_va - then: - - voice_assistant.stop - -ota: - - platform: esphome - id: ota_esphome - - platform: http_request - id: ota_http_request - -update: - - platform: http_request - id: update_http_request - name: Firmware - source: https://firmware.esphome.io/media-player/onju-voice/manifest.json - -http_request: - verify_ssl: false - -dashboard_import: - package_import_url: github://esphome/firmware/voice-assistant/onju-voice.yaml@main - -wifi: - ap: - -improv_serial: - -globals: - - id: thresh_percent - type: float - initial_value: "0.03" - restore_value: false - - id: touch_calibration_values_left - type: uint32_t[5] - restore_value: false - - id: touch_calibration_values_center - type: uint32_t[5] - restore_value: false - - id: touch_calibration_values_right - type: uint32_t[5] - restore_value: false - -interval: - - interval: 1s - then: - - script.execute: - id: calibrate_touch - button: 0 - - script.execute: - id: calibrate_touch - button: 1 - - script.execute: - id: calibrate_touch - button: 2 - -i2s_audio: - - id: i2s_audio_bus - i2s_lrclk_pin: GPIO13 - i2s_bclk_pin: GPIO18 - -media_player: - - platform: i2s_audio - name: None - id: onju_out - dac_type: external - i2s_dout_pin: GPIO12 - mode: mono - mute_pin: - number: GPIO21 - inverted: true - -microphone: - - platform: i2s_audio - id: onju_microphone - i2s_din_pin: GPIO17 - adc_type: external - pdm: false - -voice_assistant: - id: va - microphone: onju_microphone - media_player: onju_out - use_wake_word: true - on_start: - - light.turn_on: - id: top_led - blue: 100% - red: 0% - green: 0% - effect: none - on_listening: - - light.turn_on: - id: top_led - blue: 100% - red: 0% - green: 0% - brightness: 100% - effect: pulse - on_tts_end: - - media_player.play_media: !lambda return x; - - light.turn_on: - id: top_led - blue: 0% - red: 20% - green: 100% - effect: pulse - on_end: - - delay: 100ms - - wait_until: - not: - media_player.is_playing: onju_out - - script.execute: reset_led - on_client_connected: - - if: - condition: - and: - - switch.is_on: use_wake_word - - binary_sensor.is_off: mute_switch - then: - - voice_assistant.start_continuous: - on_client_disconnected: - - if: - condition: - and: - - switch.is_on: use_wake_word - - binary_sensor.is_off: mute_switch - then: - - voice_assistant.stop: - -esp32_touch: - setup_mode: false - sleep_duration: 2ms - measurement_duration: 800us - low_voltage_reference: 0.8V - high_voltage_reference: 2.4V - - filter_mode: IIR_16 - debounce_count: 2 - noise_threshold: 0 - jitter_step: 0 - smooth_mode: IIR_2 - - denoise_grade: BIT8 - denoise_cap_level: L0 - -binary_sensor: - - platform: esp32_touch - id: volume_down - pin: GPIO4 - threshold: 539000 # will automatically be tuned at runtime - on_press: - then: - - light.turn_on: left_led - - script.execute: - id: set_volume - volume: -0.05 - - delay: 1s - - while: - condition: - binary_sensor.is_on: volume_down - then: - - script.execute: - id: set_volume - volume: -0.05 - - delay: 150ms - on_release: - then: - - light.turn_off: left_led - - - platform: esp32_touch - id: volume_up - pin: GPIO2 - threshold: 580000 # will automatically be tuned at runtime - on_press: - then: - - light.turn_on: right_led - - script.execute: - id: set_volume - volume: 0.05 - - delay: 1s - - while: - condition: - binary_sensor.is_on: volume_up - then: - - script.execute: - id: set_volume - volume: 0.05 - - delay: 150ms - on_release: - then: - - light.turn_off: right_led - - - platform: esp32_touch - id: action - pin: GPIO3 - threshold: 751000 # will automatically be tuned at runtime - on_click: - - if: - condition: - or: - - switch.is_off: use_wake_word - - binary_sensor.is_on: mute_switch - then: - - if: - condition: voice_assistant.is_running - then: - - voice_assistant.stop: - - script.execute: reset_led - else: - - voice_assistant.start: - else: - - voice_assistant.stop - - delay: 1s - - script.execute: reset_led - - script.wait: reset_led - - voice_assistant.start_continuous: - - - platform: gpio - id: mute_switch - pin: - number: GPIO38 - mode: INPUT_PULLUP - name: Disable wake word - on_press: - - script.execute: turn_on_wake_word - on_release: - - script.execute: turn_off_wake_word - -light: - - platform: esp32_rmt_led_strip - id: leds - pin: GPIO11 - chipset: SK6812 - num_leds: 6 - rgb_order: grb - rmt_channel: 0 - default_transition_length: 0s - gamma_correct: 2.8 - - platform: partition - id: left_led - segments: - - id: leds - from: 0 - to: 0 - default_transition_length: 100ms - - platform: partition - id: top_led - segments: - - id: leds - from: 1 - to: 4 - default_transition_length: 100ms - effects: - - pulse: - name: pulse - transition_length: 250ms - update_interval: 250ms - - pulse: - name: slow_pulse - transition_length: 1s - update_interval: 2s - - addressable_lambda: - name: show_volume - update_interval: 50ms - lambda: |- - int int_volume = int(id(onju_out).volume * 100.0f * it.size()); - int full_leds = int_volume / 100; - int last_brightness = int_volume % 100; - int i = 0; - for(; i < full_leds; i++) { - it[i] = Color::WHITE; - } - if(i < 4) { - it[i++] = Color(0,0,0).fade_to_white(last_brightness*256/100); - } - for(; i < it.size(); i++) { - it[i] = Color::BLACK; - } - - platform: partition - id: right_led - segments: - - id: leds - from: 5 - to: 5 - default_transition_length: 100ms - -number: - - platform: template - name: "Touch threshold percentage" - id: touch_threshold_percentage - disabled_by_default: true - update_interval: never - entity_category: config - initial_value: 1.25 - min_value: 0.25 - max_value: 5 - step: 0.25 - optimistic: true - on_value: - then: - - lambda: !lambda |- - id(thresh_percent) = 0.01 * x; - -script: - - id: reset_led - then: - - if: - condition: - and: - - switch.is_on: use_wake_word - - binary_sensor.is_off: mute_switch - then: - - light.turn_on: - id: top_led - blue: 100% - red: 100% - green: 0% - brightness: 100% - effect: none - else: - - light.turn_off: top_led - - id: set_volume - mode: restart - parameters: - volume: float - then: - - media_player.volume_set: - id: onju_out - volume: !lambda return clamp(id(onju_out).volume+volume, 0.0f, 1.0f); - - light.turn_on: - id: top_led - effect: show_volume - - delay: 1s - - script.execute: reset_led - - id: turn_on_wake_word - then: - - if: - condition: - and: - - binary_sensor.is_off: mute_switch - - switch.is_on: use_wake_word - then: - - lambda: id(va).set_use_wake_word(true); - - if: - condition: - not: - - voice_assistant.is_running - then: - - voice_assistant.start_continuous - - script.execute: reset_led - - id: turn_off_wake_word - then: - - voice_assistant.stop - - lambda: id(va).set_use_wake_word(false); - - script.execute: reset_led - - id: calibrate_touch - parameters: - button: int - then: - - lambda: |- - static byte thresh_indices[3] = {0, 0, 0}; - static uint32_t sums[3] = {0, 0, 0}; - static byte qsizes[3] = {0, 0, 0}; - static int consecutive_anomalies_per_button[3] = {0, 0, 0}; - - uint32_t newval; - uint32_t* calibration_values; - switch(button) { - case 0: - newval = id(volume_down).get_value(); - calibration_values = id(touch_calibration_values_left); - break; - case 1: - newval = id(action).get_value(); - calibration_values = id(touch_calibration_values_center); - break; - case 2: - newval = id(volume_up).get_value(); - calibration_values = id(touch_calibration_values_right); - break; - default: - ESP_LOGE("touch_calibration", "Invalid button ID (%d)", button); - return; - } - - if(newval == 0) return; - - //ESP_LOGD("touch_calibration", "[%d] qsize %d, sum %d, thresh_index %d, consecutive_anomalies %d", button, qsizes[button], sums[button], thresh_indices[button], consecutive_anomalies_per_button[button]); - //ESP_LOGD("touch_calibration", "[%d] New value is %d", button, newval); - - if(qsizes[button] == 5) { - float avg = float(sums[button])/float(qsizes[button]); - if((fabs(float(newval)-avg)/avg) > id(thresh_percent)) { - consecutive_anomalies_per_button[button]++; - //ESP_LOGD("touch_calibration", "[%d] %d anomalies detected.", button, consecutive_anomalies_per_button[button]); - if(consecutive_anomalies_per_button[button] < 10) - return; - } - } - - //ESP_LOGD("touch_calibration", "[%d] Resetting consecutive anomalies counter.", button); - consecutive_anomalies_per_button[button] = 0; - - if(qsizes[button] == 5) { - //ESP_LOGD("touch_calibration", "[%d] Queue full, removing %d.", button, id(touch_calibration_values)[thresh_indices[button]]); - sums[button] -= (uint32_t) *(calibration_values+thresh_indices[button]);// id(touch_calibration_values)[thresh_indices[button]]; - qsizes[button]--; - } - *(calibration_values+thresh_indices[button]) = newval; - sums[button] += newval; - qsizes[button]++; - thresh_indices[button] = (thresh_indices[button] + 1) % 5; - - //ESP_LOGD("touch_calibration", "[%d] Average value is %d", button, sums[button]/qsizes[button]); - uint32_t newthresh = uint32_t((sums[button]/qsizes[button]) * (1.0 + id(thresh_percent))); - //ESP_LOGD("touch_calibration", "[%d] Setting threshold %d", button, newthresh); - - switch(button) { - case 0: - id(volume_down).set_threshold(newthresh); - break; - case 1: - id(action).set_threshold(newthresh); - break; - case 2: - id(volume_up).set_threshold(newthresh); - break; - default: - ESP_LOGE("touch_calibration", "Invalid button ID (%d)", button); - return; - } - -switch: - - platform: template - name: Use Wake Word - id: use_wake_word - optimistic: true - restore_mode: RESTORE_DEFAULT_ON - on_turn_on: - - script.execute: turn_on_wake_word - on_turn_off: - - script.execute: turn_off_wake_word - -button: - - platform: safe_mode - id: button_safe_mode - name: Safe Mode Boot - - - platform: factory_reset - id: factory_reset_btn - name: Factory reset +packages: + moved: github://esphome/media-players/onju-voice/onju-voice.yaml@main diff --git a/media-player/raspiaudio-muse-luxe.yaml b/media-player/raspiaudio-muse-luxe.yaml index aa93d4b7..86924ca2 100644 --- a/media-player/raspiaudio-muse-luxe.yaml +++ b/media-player/raspiaudio-muse-luxe.yaml @@ -1,208 +1,2 @@ -esphome: - name: raspiaudio-muse-luxe - friendly_name: RaspiAudio Muse Luxe - min_version: 2024.6.0 - name_add_mac_suffix: true - project: - name: raspiaudio.muse-luxe - version: "24.7.4.1" - -esp32: - board: esp-wrover-kit - framework: - type: arduino - -logger: -api: - -ota: - - platform: esphome - id: ota_esphome - - platform: http_request - id: ota_http_request - -update: - - platform: http_request - id: update_http_request - name: Firmware - source: https://firmware.esphome.io/media-player/raspiaudio-muse-luxe/manifest.json - -http_request: - verify_ssl: false - -i2c: - - id: i2c_bus - sda: GPIO18 - scl: GPIO23 - -dashboard_import: - package_import_url: github://esphome/firmware/media-player/raspiaudio-muse-luxe.yaml@main - -wifi: - ap: - -captive_portal: - -improv_serial: - -external_components: - - source: github://pr#3552 # DAC support https://github.com/esphome/esphome/pull/3552 - components: [es8388] - refresh: 0s - -es8388: - -i2s_audio: - - id: i2s_audio_bus - i2s_lrclk_pin: GPIO25 - i2s_bclk_pin: GPIO5 - -media_player: - - platform: i2s_audio - name: None - id: luxe_out - dac_type: external - i2s_dout_pin: GPIO26 - mode: stereo - mute_pin: - number: GPIO21 - inverted: true - -microphone: - - platform: i2s_audio - id: luxe_microphone - i2s_din_pin: GPIO35 - adc_type: external - pdm: false - -voice_assistant: - microphone: luxe_microphone - on_start: - - light.turn_on: - id: top_led - blue: 100% - red: 0% - green: 0% - effect: none - on_tts_start: - - light.turn_on: - id: top_led - blue: 60% - red: 20% - green: 20% - effect: none - on_tts_end: - - media_player.play_media: !lambda return x; - - light.turn_on: - id: top_led - blue: 60% - red: 20% - green: 20% - effect: pulse - on_end: - - delay: 1s - - wait_until: - not: - media_player.is_playing: luxe_out - - light.turn_off: top_led - on_error: - - light.turn_on: - id: top_led - blue: 0% - red: 100% - green: 0% - effect: none - - delay: 1s - - light.turn_off: top_led - -sensor: - - platform: adc - id: battery_sensor - pin: GPIO33 - name: Battery - icon: "mdi:battery-outline" - device_class: voltage - state_class: measurement - entity_category: diagnostic - unit_of_measurement: V - update_interval: 15s - accuracy_decimals: 3 - attenuation: 11db - raw: true - filters: - - multiply: 0.00173913 # 2300 -> 4, for attenuation 11db, based on Olivier's code - - exponential_moving_average: - alpha: 0.2 - send_every: 2 - - delta: 0.002 - -binary_sensor: - - platform: gpio - pin: - number: GPIO19 - inverted: true - mode: - input: true - pullup: true - name: Volume Up - id: volume_up - on_click: - - media_player.volume_up: luxe_out - - platform: gpio - pin: - number: GPIO32 - inverted: true - mode: - input: true - pullup: true - name: Volume Down - id: volume_down - on_click: - - media_player.volume_down: luxe_out - - platform: gpio - pin: - number: GPIO12 - inverted: true - mode: - input: true - pullup: true - name: Action - id: action_button - on_multi_click: - - timing: - - ON FOR AT MOST 350ms - - OFF FOR AT LEAST 10ms - then: - - media_player.toggle: luxe_out - - timing: - - ON FOR AT LEAST 350ms - then: - - voice_assistant.start: - - timing: - - ON FOR AT LEAST 350ms - - OFF FOR AT LEAST 10ms - then: - - voice_assistant.stop: - -light: - - platform: fastled_clockless - name: None - id: top_led - pin: GPIO22 - chipset: SK6812 - num_leds: 1 - rgb_order: grb - gamma_correct: 2.8 - effects: - - pulse: - transition_length: 250ms - update_interval: 250ms - -button: - - platform: safe_mode - id: button_safe_mode - name: Safe Mode Boot - - - platform: factory_reset - id: factory_reset_btn - name: Factory reset +packages: + moved: github://esphome/media-players/raspiaudio/raspiaudio-muse-luxe.yaml@main diff --git a/media-player/raspiaudio-muse-proto.yaml b/media-player/raspiaudio-muse-proto.yaml index 7c1dfb6c..081e912e 100644 --- a/media-player/raspiaudio-muse-proto.yaml +++ b/media-player/raspiaudio-muse-proto.yaml @@ -1,167 +1,2 @@ -esphome: - name: raspiaudio-muse-proto - friendly_name: RaspiAudio Muse Proto - min_version: 2024.6.0 - name_add_mac_suffix: true - project: - name: raspiaudio.muse-proto - version: "24.7.4.1" - -esp32: - board: esp-wrover-kit - framework: - type: arduino - -logger: -api: - -ota: - - platform: esphome - id: ota_esphome - - platform: http_request - id: ota_http_request - -update: - - platform: http_request - id: update_http_request - name: Firmware - source: https://firmware.esphome.io/media-player/raspiaudio-muse-proto/manifest.json - -http_request: - verify_ssl: false - -dashboard_import: - package_import_url: github://esphome/firmware/media-player/raspiaudio-muse-proto.yaml@main - -wifi: - ap: - -captive_portal: - -improv_serial: - -i2s_audio: - - id: i2s_audio_bus - i2s_lrclk_pin: GPIO25 - i2s_bclk_pin: GPIO5 - -microphone: - - platform: i2s_audio - id: board_microphone - channel: left - i2s_din_pin: GPIO35 - adc_type: external - pdm: false - -speaker: - - platform: i2s_audio - id: board_external_speakers - dac_type: external - i2s_dout_pin: - number: GPIO26 - allow_other_uses: true - mode: mono - -media_player: - - platform: i2s_audio - id: media_out - name: None - dac_type: external - i2s_dout_pin: - number: GPIO26 - allow_other_uses: true - mode: mono - mute_pin: - number: GPIO21 - inverted: true - -voice_assistant: - microphone: board_microphone - speaker: board_external_speakers - on_start: - - light.turn_on: - id: board_led - blue: 100% - red: 0% - green: 0% - effect: none - on_tts_start: - - light.turn_on: - id: board_led - blue: 60% - red: 20% - green: 20% - effect: none - on_tts_end: - - light.turn_on: - id: board_led - blue: 60% - red: 20% - green: 20% - effect: pulse - on_end: - - delay: 1s - - wait_until: - not: - speaker.is_playing: - - light.turn_off: board_led - on_error: - - light.turn_on: - id: board_led - blue: 0% - red: 100% - green: 0% - effect: none - - delay: 1s - - light.turn_off: board_led - -binary_sensor: - - platform: gpio - pin: - number: GPIO0 - inverted: true - mode: - input: true - pullup: true - name: Action - id: action_button - on_multi_click: - - timing: - - ON FOR AT MOST 350ms - - OFF FOR AT LEAST 10ms - then: - - media_player.toggle: media_out - - timing: - - ON FOR AT LEAST 350ms - then: - - voice_assistant.start: - - timing: - - ON FOR AT LEAST 350ms - - OFF FOR AT LEAST 10ms - then: - - voice_assistant.stop: - -light: - - platform: esp32_rmt_led_strip - id: board_led - name: None - disabled_by_default: true - pin: GPIO22 - default_transition_length: 0s - chipset: WS2812 - num_leds: 1 - rgb_order: grb - rmt_channel: 0 - effects: - - pulse: - transition_length: 250ms - update_interval: 250ms - -button: - - platform: safe_mode - id: button_safe_mode - name: Safe Mode Boot - - - platform: factory_reset - id: factory_reset_btn - name: Factory reset +packages: + moved: github://esphome/media-players/raspiaudio/raspiaudio-muse-proto.yaml@main diff --git a/wake-word-voice-assistant/esp32-s3-box-3.yaml b/wake-word-voice-assistant/esp32-s3-box-3.yaml index deeb8fc6..d7c74d60 100644 --- a/wake-word-voice-assistant/esp32-s3-box-3.yaml +++ b/wake-word-voice-assistant/esp32-s3-box-3.yaml @@ -1,778 +1,2 @@ ---- -substitutions: - name: esp32-s3-box-3 - friendly_name: ESP32 S3 Box 3 - loading_illustration_file: https://github.com/esphome/firmware/raw/main/voice-assistant/casita/loading_320_240.png - idle_illustration_file: https://github.com/esphome/firmware/raw/main/voice-assistant/casita/idle_320_240.png - listening_illustration_file: https://github.com/esphome/firmware/raw/main/voice-assistant/casita/listening_320_240.png - thinking_illustration_file: https://github.com/esphome/firmware/raw/main/voice-assistant/casita/thinking_320_240.png - replying_illustration_file: https://github.com/esphome/firmware/raw/main/voice-assistant/casita/replying_320_240.png - error_illustration_file: https://github.com/esphome/firmware/raw/main/voice-assistant/casita/error_320_240.png - timer_finished_illustration_file: https://github.com/esphome/firmware/raw/main/voice-assistant/casita/timer_finished_320_240.png - - loading_illustration_background_color: "000000" - idle_illustration_background_color: "000000" - listening_illustration_background_color: "FFFFFF" - thinking_illustration_background_color: "FFFFFF" - replying_illustration_background_color: "FFFFFF" - error_illustration_background_color: "000000" - - voice_assist_idle_phase_id: "1" - voice_assist_listening_phase_id: "2" - voice_assist_thinking_phase_id: "3" - voice_assist_replying_phase_id: "4" - voice_assist_not_ready_phase_id: "10" - voice_assist_error_phase_id: "11" - voice_assist_muted_phase_id: "12" - voice_assist_timer_finished_phase_id: "20" - - # These unique characters have been extracted from every test file of every language available on https://github.com/home-assistant/intents (14 March 2024) - allowed_characters: " !#%'()+,-./0123456789:;<>?@ABCDEFGHIJKLMNOPQRSTUVWYZ[]_abcdefghijklmnopqrstuvwxyz{|}°²³µ¿ÁÂÄÅÉÖÚßàáâãäåæçèéêëìíîðñòóôõöøùúûüýþāăąćčďĐđēėęěğĮįıļľŁłńňőřśšťũūůűųźŻżŽžơưșțΆΈΌΐΑΒΓΔΕΖΗΘΚΜΝΠΡΣΤΥΦάέήίαβγδεζηθικλμνξοπρςστυφχψωϊόύώАБВГДЕЖЗИКЛМНОПРСТУХЦЧШЪЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяёђєіїјљњћאבגדהוזחטיכלםמןנסעפץצקרשת،ءآأإئابةتجحخدذرزسشصضطظعغفقكلمنهوىيٹپچڈکگںھہیےংকচতধনফবযরলশষস়ািু্చయలిెొ్ംഅആഇഈഉഎഓകഗങചജഞടഡണതദധനപഫബഭമയരറലളവശസഹാിീുൂെേൈ്ൺൻർൽൾაბგდევზთილმნოპრსტუფქყშჩცძჭხạảấầẩậắặẹẽếềểệỉịọỏốồổỗộớờởợụủứừửữựỳ—、一上不个中为主乾了些亮人任低佔何作供依侧係個側偵充光入全关冇冷几切到制前動區卧厅厨及口另右吊后吗启吸呀咗哪唔問啟嗎嘅嘛器圍在场執場外多大始安定客室家密寵对將小少左已帘常幫幾库度庫廊廚廳开式後恆感態成我戲戶户房所扇手打执把拔换掉控插摄整斯新明是景暗更最會有未本模機檯櫃欄次正氏水沒没洗活派温測源溫漏潮激濕灯為無煙照熱燈燥物狀玄现現瓦用發的盞目着睡私空窗立笛管節簾籬紅線红罐置聚聲脚腦腳臥色节著行衣解設調請謝警设调走路車车运連遊運過道邊部都量鎖锁門閂閉開關门闭除隱離電震霧面音頂題顏颜風风食餅餵가간감갔강개거게겨결경고공과관그금급기길깥꺼껐꼽나난내네놀누는능니다닫담대더데도동됐되된됨둡드든등디때떤뜨라래러렇렌려로료른를리림링마많명몇모무문물뭐바밝방배변보부불블빨뽑사산상색서설성세센션소쇼수스습시신실싱아안않알았애야어얼업없었에여연열옆오온완외왼요운움워원위으은을음의이인일임입있작잠장재전절정제져조족종주줄중줘지직진짐쪽차창천최추출충치침커컴켜켰쿠크키탁탄태탬터텔통트튼티파팬퍼폰표퓨플핑한함해했행혀현화활후휴힘,?" - - micro_wake_word_model: okay_nabu - -esphome: - name: ${name} - friendly_name: ${friendly_name} - min_version: 2024.7.0 - name_add_mac_suffix: true - platformio_options: - board_build.flash_mode: dio - project: - name: esphome.voice-assistant - version: "24.8.1" - on_boot: - priority: 600 - then: - - script.execute: draw_display - - delay: 30s - - if: - condition: - lambda: return id(init_in_progress); - then: - - lambda: id(init_in_progress) = false; - - script.execute: draw_display - -esp32: - board: esp32s3box - flash_size: 16MB - framework: - type: esp-idf - sdkconfig_options: - CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240: "y" - CONFIG_ESP32S3_DATA_CACHE_64KB: "y" - CONFIG_ESP32S3_DATA_CACHE_LINE_64B: "y" - CONFIG_AUDIO_BOARD_CUSTOM: "y" - CONFIG_ESP32_S3_BOX_3_BOARD: "y" - components: - - name: esp32_s3_box_3_board - source: github://jesserockz/esp32-s3-box-3-board@main - refresh: 0s - -psram: - mode: octal - speed: 80MHz - -external_components: - - source: github://pr#5230 - components: esp_adf - refresh: 0s - - source: github://jesserockz/esphome-components - components: [file] - refresh: 0s - -api: - on_client_connected: - - script.execute: draw_display - on_client_disconnected: - - script.execute: draw_display - -ota: - - platform: esphome - id: ota_esphome - - platform: http_request - id: ota_http_request - -update: - - platform: http_request - id: update_http_request - name: Firmware - source: https://firmware.esphome.io/wake-word-voice-assistant/esp32-s3-box-3/manifest.json - -http_request: - -logger: - hardware_uart: USB_SERIAL_JTAG - -dashboard_import: - package_import_url: github://esphome/firmware/wake-word-voice-assistant/esp32-s3-box-3.yaml@main - -wifi: - ap: - on_connect: - - script.execute: draw_display - - delay: 5s # Gives time for improv results to be transmitted - - ble.disable: - on_disconnect: - - script.execute: draw_display - - ble.enable: - -improv_serial: - -esp32_improv: - authorizer: none - -button: - - platform: factory_reset - id: factory_reset_btn - internal: true - -binary_sensor: - - platform: gpio - pin: - number: GPIO0 - mode: INPUT_PULLUP - inverted: true - id: top_left_button - internal: true - on_multi_click: - - timing: - - ON for at least 50ms - - OFF for at least 50ms - then: - - switch.turn_off: timer_ringing - - timing: - - ON for at least 10s - then: - - button.press: factory_reset_btn - -output: - - platform: ledc - pin: GPIO47 - id: backlight_output - -light: - - platform: monochromatic - id: led - name: Screen - icon: "mdi:television" - entity_category: config - output: backlight_output - restore_mode: RESTORE_DEFAULT_ON - default_transition_length: 250ms - -esp_adf: - board: esp32s3box3 - -microphone: - - platform: esp_adf - id: box_mic - -speaker: - - platform: esp_adf - id: box_speaker - -micro_wake_word: - models: - - ${micro_wake_word_model} - on_wake_word_detected: - - voice_assistant.start: - wake_word: !lambda return wake_word; - -voice_assistant: - id: va - microphone: box_mic - speaker: box_speaker - noise_suppression_level: 2 - auto_gain: 31dBFS - volume_multiplier: 2.0 - vad_threshold: 3 - on_listening: - - lambda: id(voice_assistant_phase) = ${voice_assist_listening_phase_id}; - - text_sensor.template.publish: - id: text_request - state: "..." - - text_sensor.template.publish: - id: text_response - state: "..." - - script.execute: draw_display - on_stt_vad_end: - - lambda: id(voice_assistant_phase) = ${voice_assist_thinking_phase_id}; - - script.execute: draw_display - on_stt_end: - - text_sensor.template.publish: - id: text_request - state: !lambda return x; - - script.execute: draw_display - on_tts_start: - - text_sensor.template.publish: - id: text_response - state: !lambda return x; - on_tts_stream_start: - - lambda: id(voice_assistant_phase) = ${voice_assist_replying_phase_id}; - - script.execute: draw_display - on_tts_stream_end: - - if: - condition: - switch.is_off: mute - then: - - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id}; - else: - - lambda: id(voice_assistant_phase) = ${voice_assist_muted_phase_id}; - - script.execute: draw_display - on_end: - - wait_until: - not: - voice_assistant.is_running: - - if: - condition: - and: - - switch.is_off: mute - - lambda: return id(wake_word_engine_location).state == "On device"; - - lambda: return id(voice_assistant_phase) != ${voice_assist_timer_finished_phase_id}; - then: - - micro_wake_word.start: - on_error: - - if: - condition: - lambda: return !id(init_in_progress); - then: - - lambda: id(voice_assistant_phase) = ${voice_assist_error_phase_id}; - - script.execute: draw_display - - delay: 1s - - if: - condition: - switch.is_off: mute - then: - - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id}; - else: - - lambda: id(voice_assistant_phase) = ${voice_assist_muted_phase_id}; - - script.execute: draw_display - on_client_connected: - - wait_until: - not: ble.enabled - - lambda: id(init_in_progress) = false; - - script.execute: start_voice_assistant - - script.execute: draw_display - on_client_disconnected: - - script.execute: stop_voice_assistant - - script.execute: draw_display - on_timer_started: - - script.execute: draw_display - on_timer_cancelled: - - script.execute: draw_display - on_timer_updated: - - script.execute: draw_display - on_timer_tick: - - script.execute: draw_display - on_timer_finished: - - script.execute: stop_voice_assistant - - lambda: id(voice_assistant_phase) = ${voice_assist_timer_finished_phase_id}; - - switch.turn_on: timer_ringing - - script.execute: draw_display - - wait_until: - not: - microphone.is_capturing: - - while: - condition: - switch.is_on: timer_ringing - then: - - lambda: id(box_speaker).play(id(timer_finished_wave_file), sizeof(id(timer_finished_wave_file))); - - delay: 1s - - wait_until: - not: - speaker.is_playing: - - switch.turn_off: timer_ringing - - script.execute: start_voice_assistant - - script.execute: draw_display - -script: - - id: draw_display - then: - - if: - condition: - lambda: return !id(init_in_progress); - then: - - if: - condition: - wifi.connected: - then: - - if: - condition: - api.connected: - then: - - lambda: | - switch(id(voice_assistant_phase)) { - case ${voice_assist_listening_phase_id}: - id(s3_box_lcd).show_page(listening_page); - id(s3_box_lcd).update(); - break; - case ${voice_assist_thinking_phase_id}: - id(s3_box_lcd).show_page(thinking_page); - id(s3_box_lcd).update(); - break; - case ${voice_assist_replying_phase_id}: - id(s3_box_lcd).show_page(replying_page); - id(s3_box_lcd).update(); - break; - case ${voice_assist_error_phase_id}: - id(s3_box_lcd).show_page(error_page); - id(s3_box_lcd).update(); - break; - case ${voice_assist_muted_phase_id}: - id(s3_box_lcd).show_page(muted_page); - id(s3_box_lcd).update(); - break; - case ${voice_assist_not_ready_phase_id}: - id(s3_box_lcd).show_page(no_ha_page); - id(s3_box_lcd).update(); - break; - case ${voice_assist_timer_finished_phase_id}: - id(s3_box_lcd).show_page(timer_finished_page); - id(s3_box_lcd).update(); - break; - default: - id(s3_box_lcd).show_page(idle_page); - id(s3_box_lcd).update(); - } - else: - - display.page.show: no_ha_page - - component.update: s3_box_lcd - else: - - display.page.show: no_wifi_page - - component.update: s3_box_lcd - else: - - display.page.show: initializing_page - - component.update: s3_box_lcd - - - id: fetch_first_active_timer - then: - - lambda: | - const auto timers = id(va).get_timers(); - auto output_timer = timers.begin()->second; - for (auto &iterable_timer : timers) { - if (iterable_timer.second.is_active && iterable_timer.second.seconds_left <= output_timer.seconds_left) { - output_timer = iterable_timer.second; - } - } - id(global_first_active_timer) = output_timer; - - id: check_if_timers_active - then: - - lambda: | - const auto timers = id(va).get_timers(); - bool output = false; - if (timers.size() > 0) { - for (auto &iterable_timer : timers) { - if(iterable_timer.second.is_active) { - output = true; - } - } - } - id(global_is_timer_active) = output; - - id: fetch_first_timer - then: - - lambda: | - const auto timers = id(va).get_timers(); - auto output_timer = timers.begin()->second; - for (auto &iterable_timer : timers) { - if (iterable_timer.second.seconds_left <= output_timer.seconds_left) { - output_timer = iterable_timer.second; - } - } - id(global_first_timer) = output_timer; - - id: check_if_timers - then: - - lambda: | - const auto timers = id(va).get_timers(); - bool output = false; - if (timers.size() > 0) { - output = true; - } - id(global_is_timer) = output; - - - id: draw_timer_timeline - then: - - lambda: | - id(check_if_timers_active).execute(); - id(check_if_timers).execute(); - if (id(global_is_timer_active)){ - id(fetch_first_active_timer).execute(); - int active_pixels = round( 320 * id(global_first_active_timer).seconds_left / max(id(global_first_active_timer).total_seconds , static_cast(1)) ); - if (active_pixels > 0){ - id(s3_box_lcd).filled_rectangle(0 , 225 , 320 , 15 , Color::WHITE ); - id(s3_box_lcd).filled_rectangle(0 , 226 , active_pixels , 13 , id(active_timer_color) ); - } - } else if (id(global_is_timer)){ - id(fetch_first_timer).execute(); - int active_pixels = round( 320 * id(global_first_timer).seconds_left / max(id(global_first_timer).total_seconds , static_cast(1))); - if (active_pixels > 0){ - id(s3_box_lcd).filled_rectangle(0 , 225 , 320 , 15 , Color::WHITE ); - id(s3_box_lcd).filled_rectangle(0 , 226 , active_pixels , 13 , id(paused_timer_color) ); - } - } - - id: draw_active_timer_widget - then: - - lambda: | - id(check_if_timers_active).execute(); - if (id(global_is_timer_active)){ - id(s3_box_lcd).filled_rectangle(80 , 40 , 160 , 50 , Color::WHITE ); - id(s3_box_lcd).rectangle(80 , 40 , 160 , 50 , Color::BLACK ); - - id(fetch_first_active_timer).execute(); - int hours_left = floor(id(global_first_active_timer).seconds_left / 3600); - int minutes_left = floor((id(global_first_active_timer).seconds_left - hours_left * 3600) / 60); - int seconds_left = id(global_first_active_timer).seconds_left - hours_left * 3600 - minutes_left * 60 ; - auto display_hours = (hours_left < 10 ? "0" : "") + std::to_string(hours_left); - auto display_minute = (minutes_left < 10 ? "0" : "") + std::to_string(minutes_left); - auto display_seconds = (seconds_left < 10 ? "0" : "") + std::to_string(seconds_left) ; - - std::string display_string = ""; - if (hours_left > 0) { - display_string = display_hours + ":" + display_minute; - } else { - display_string = display_minute + ":" + display_seconds; - } - id(s3_box_lcd).printf(120, 47, id(font_timer), Color::BLACK, "%s", display_string.c_str()); - } - - - id: start_voice_assistant - then: - - if: - condition: - switch.is_off: mute - then: - - if: - condition: - lambda: return id(wake_word_engine_location).state == "In Home Assistant"; - then: - - lambda: id(va).set_use_wake_word(true); - - voice_assistant.start_continuous: - - if: - condition: - lambda: return id(wake_word_engine_location).state == "On device"; - then: - - lambda: id(va).set_use_wake_word(false); - - micro_wake_word.start - - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id}; - else: - - lambda: id(voice_assistant_phase) = ${voice_assist_muted_phase_id}; - - - id: stop_voice_assistant - then: - - if: - condition: - lambda: return id(wake_word_engine_location).state == "In Home Assistant"; - then: - - lambda: id(va).set_use_wake_word(false); - - voice_assistant.stop: - - if: - condition: - lambda: return id(wake_word_engine_location).state == "On device"; - then: - - voice_assistant.stop: - - micro_wake_word.stop: - - lambda: id(voice_assistant_phase) = ${voice_assist_not_ready_phase_id}; - -switch: - - platform: template - name: Mute - id: mute - icon: "mdi:microphone-off" - optimistic: true - restore_mode: RESTORE_DEFAULT_OFF - entity_category: config - on_turn_off: - - if: - condition: - lambda: return !id(init_in_progress); - then: - - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id}; - - if: - condition: - not: - - voice_assistant.is_running - then: - - if: - condition: - lambda: return id(wake_word_engine_location).state == "In Home Assistant"; - then: - - lambda: id(va).set_use_wake_word(true); - - voice_assistant.start_continuous - - if: - condition: - lambda: return id(wake_word_engine_location).state == "On device"; - then: - - lambda: id(va).set_use_wake_word(false); - - micro_wake_word.start - - script.execute: draw_display - on_turn_on: - - if: - condition: - lambda: return !id(init_in_progress); - then: - - lambda: id(va).set_use_wake_word(false); - - voice_assistant.stop - - micro_wake_word.stop - - lambda: id(voice_assistant_phase) = ${voice_assist_muted_phase_id}; - - script.execute: draw_display - - - platform: template - id: timer_ringing - optimistic: true - internal: true - restore_mode: ALWAYS_OFF - on_turn_on: - - delay: 15min - - switch.turn_off: timer_ringing - -select: - - platform: template - entity_category: config - name: Wake word engine location - id: wake_word_engine_location - icon: "mdi:account-voice" - optimistic: true - restore_value: true - options: - - In Home Assistant - - On device - initial_option: On device - on_value: - - if: - condition: - lambda: return !id(init_in_progress); - then: - - wait_until: - lambda: return id(voice_assistant_phase) == ${voice_assist_muted_phase_id} || id(voice_assistant_phase) == ${voice_assist_idle_phase_id}; - - if: - condition: - lambda: return x == "In Home Assistant"; - then: - - micro_wake_word.stop - - delay: 500ms - - if: - condition: - switch.is_off: mute - then: - - lambda: id(va).set_use_wake_word(true); - - voice_assistant.start_continuous: - - if: - condition: - lambda: return x == "On device"; - then: - - lambda: id(va).set_use_wake_word(false); - - voice_assistant.stop - - delay: 500ms - - if: - condition: - switch.is_off: mute - then: - - micro_wake_word.start - -globals: - - id: init_in_progress - type: bool - restore_value: false - initial_value: "true" - - id: voice_assistant_phase - type: int - restore_value: false - initial_value: ${voice_assist_not_ready_phase_id} - - id: global_first_active_timer - type: voice_assistant::Timer - restore_value: false - - id: global_is_timer_active - type: bool - restore_value: false - - id: global_first_timer - type: voice_assistant::Timer - restore_value: false - - id: global_is_timer - type: bool - restore_value: false - -image: - - file: ${error_illustration_file} - id: casita_error - resize: 320x240 - type: RGB24 - use_transparency: true - - file: ${idle_illustration_file} - id: casita_idle - resize: 320x240 - type: RGB24 - use_transparency: true - - file: ${listening_illustration_file} - id: casita_listening - resize: 320x240 - type: RGB24 - use_transparency: true - - file: ${thinking_illustration_file} - id: casita_thinking - resize: 320x240 - type: RGB24 - use_transparency: true - - file: ${replying_illustration_file} - id: casita_replying - resize: 320x240 - type: RGB24 - use_transparency: true - - file: ${timer_finished_illustration_file} - id: casita_timer_finished - resize: 320x240 - type: RGB24 - use_transparency: true - - file: ${loading_illustration_file} - id: casita_initializing - resize: 320x240 - type: RGB24 - use_transparency: true - - file: https://github.com/esphome/firmware/raw/main/voice-assistant/error_box_illustrations/error-no-wifi.png - id: error_no_wifi - resize: 320x240 - type: RGB24 - use_transparency: true - - file: https://github.com/esphome/firmware/raw/main/voice-assistant/error_box_illustrations/error-no-ha.png - id: error_no_ha - resize: 320x240 - type: RGB24 - use_transparency: true - -font: - - file: - type: gfonts - family: Figtree - weight: 300 - italic: true - glyphs: ${allowed_characters} - id: font_request - size: 15 - - file: - type: gfonts - family: Figtree - weight: 300 - glyphs: ${allowed_characters} - id: font_response - size: 15 - - file: - type: gfonts - family: Figtree - weight: 300 - glyphs: ${allowed_characters} - id: font_timer - size: 30 - -text_sensor: - - id: text_request - platform: template - on_value: - lambda: |- - if(id(text_request).state.length()>32) { - std::string name = id(text_request).state.c_str(); - std::string truncated = esphome::str_truncate(name.c_str(),31); - id(text_request).state = (truncated+"...").c_str(); - } - - - id: text_response - platform: template - on_value: - lambda: |- - if(id(text_response).state.length()>32) { - std::string name = id(text_response).state.c_str(); - std::string truncated = esphome::str_truncate(name.c_str(),31); - id(text_response).state = (truncated+"...").c_str(); - } - -color: - - id: idle_color - hex: ${idle_illustration_background_color} - - id: listening_color - hex: ${listening_illustration_background_color} - - id: thinking_color - hex: ${thinking_illustration_background_color} - - id: replying_color - hex: ${replying_illustration_background_color} - - id: loading_color - hex: ${loading_illustration_background_color} - - id: error_color - hex: ${error_illustration_background_color} - - id: active_timer_color - hex: "26ed3a" - - id: paused_timer_color - hex: "3b89e3" - -file: - - id: timer_finished_wave_file - file: https://github.com/esphome/firmware/raw/main/voice-assistant/sounds/timer_finished.wav - -spi: - - id: spi_bus - clk_pin: 7 - mosi_pin: 6 - -display: - - platform: ili9xxx - id: s3_box_lcd - model: S3BOX - data_rate: 40MHz - cs_pin: 5 - dc_pin: 4 - reset_pin: - number: 48 - inverted: true - update_interval: never - pages: - - id: idle_page - lambda: |- - it.fill(id(idle_color)); - it.image((it.get_width() / 2), (it.get_height() / 2), id(casita_idle), ImageAlign::CENTER); - id(draw_timer_timeline).execute(); - id(draw_active_timer_widget).execute(); - - id: listening_page - lambda: |- - it.fill(id(listening_color)); - it.image((it.get_width() / 2), (it.get_height() / 2), id(casita_listening), ImageAlign::CENTER); - id(draw_timer_timeline).execute(); - - id: thinking_page - lambda: |- - it.fill(id(thinking_color)); - it.image((it.get_width() / 2), (it.get_height() / 2), id(casita_thinking), ImageAlign::CENTER); - it.filled_rectangle(20 , 20 , 280 , 30 , Color::WHITE ); - it.rectangle(20 , 20 , 280 , 30 , Color::BLACK ); - it.printf(30, 25, id(font_request), Color::BLACK, "%s", id(text_request).state.c_str()); - - id(draw_timer_timeline).execute(); - - id: replying_page - lambda: |- - it.fill(id(replying_color)); - it.image((it.get_width() / 2), (it.get_height() / 2), id(casita_replying), ImageAlign::CENTER); - it.filled_rectangle(20 , 20 , 280 , 30 , Color::WHITE ); - it.rectangle(20 , 20 , 280 , 30 , Color::BLACK ); - it.filled_rectangle(20 , 190 , 280 , 30 , Color::WHITE ); - it.rectangle(20 , 190 , 280 , 30 , Color::BLACK ); - it.printf(30, 25, id(font_request), Color::BLACK, "%s", id(text_request).state.c_str()); - it.printf(30, 195, id(font_response), Color::BLACK, "%s", id(text_response).state.c_str()); - id(draw_timer_timeline).execute(); - - id: timer_finished_page - lambda: |- - it.fill(id(idle_color)); - it.image((it.get_width() / 2), (it.get_height() / 2), id(casita_timer_finished), ImageAlign::CENTER); - - id: error_page - lambda: |- - it.fill(id(error_color)); - it.image((it.get_width() / 2), (it.get_height() / 2), id(casita_error), ImageAlign::CENTER); - - id: no_ha_page - lambda: |- - it.image((it.get_width() / 2), (it.get_height() / 2), id(error_no_ha), ImageAlign::CENTER); - - id: no_wifi_page - lambda: |- - it.image((it.get_width() / 2), (it.get_height() / 2), id(error_no_wifi), ImageAlign::CENTER); - - id: initializing_page - lambda: |- - it.fill(id(loading_color)); - it.image((it.get_width() / 2), (it.get_height() / 2), id(casita_initializing), ImageAlign::CENTER); - - id: muted_page - lambda: |- - it.fill(Color::BLACK); - id(draw_timer_timeline).execute(); - id(draw_active_timer_widget).execute(); +packages: + moved: github://esphome/wake-word-voice-assistants/esp32-s3-box-3/esp32-s3-box-3.yaml@main diff --git a/wake-word-voice-assistant/esp32-s3-box-lite.yaml b/wake-word-voice-assistant/esp32-s3-box-lite.yaml index 9c7736cd..e2d2fad3 100644 --- a/wake-word-voice-assistant/esp32-s3-box-lite.yaml +++ b/wake-word-voice-assistant/esp32-s3-box-lite.yaml @@ -1,838 +1,2 @@ ---- -substitutions: - name: esp32-s3-box-lite - friendly_name: ESP32 S3 Box Lite - loading_illustration_file: https://github.com/esphome/firmware/raw/main/voice-assistant/casita/loading_320_240.png - idle_illustration_file: https://github.com/esphome/firmware/raw/main/voice-assistant/casita/idle_320_240.png - listening_illustration_file: https://github.com/esphome/firmware/raw/main/voice-assistant/casita/listening_320_240.png - thinking_illustration_file: https://github.com/esphome/firmware/raw/main/voice-assistant/casita/thinking_320_240.png - replying_illustration_file: https://github.com/esphome/firmware/raw/main/voice-assistant/casita/replying_320_240.png - error_illustration_file: https://github.com/esphome/firmware/raw/main/voice-assistant/casita/error_320_240.png - timer_finished_illustration_file: https://github.com/esphome/firmware/raw/main/voice-assistant/casita/timer_finished_320_240.png - - loading_illustration_background_color: "000000" - idle_illustration_background_color: "000000" - listening_illustration_background_color: "FFFFFF" - thinking_illustration_background_color: "FFFFFF" - replying_illustration_background_color: "FFFFFF" - error_illustration_background_color: "000000" - - voice_assist_idle_phase_id: "1" - voice_assist_listening_phase_id: "2" - voice_assist_thinking_phase_id: "3" - voice_assist_replying_phase_id: "4" - voice_assist_not_ready_phase_id: "10" - voice_assist_error_phase_id: "11" - voice_assist_muted_phase_id: "12" - voice_assist_timer_finished_phase_id: "20" - - # These unique characters have been extracted from every test file of every language available on https://github.com/home-assistant/intents (14 March 2024) - allowed_characters: " !#%'()+,-./0123456789:;<>?@ABCDEFGHIJKLMNOPQRSTUVWYZ[]_abcdefghijklmnopqrstuvwxyz{|}°²³µ¿ÁÂÄÅÉÖÚßàáâãäåæçèéêëìíîðñòóôõöøùúûüýþāăąćčďĐđēėęěğĮįıļľŁłńňőřśšťũūůűųźŻżŽžơưșțΆΈΌΐΑΒΓΔΕΖΗΘΚΜΝΠΡΣΤΥΦάέήίαβγδεζηθικλμνξοπρςστυφχψωϊόύώАБВГДЕЖЗИКЛМНОПРСТУХЦЧШЪЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяёђєіїјљњћאבגדהוזחטיכלםמןנסעפץצקרשת،ءآأإئابةتجحخدذرزسشصضطظعغفقكلمنهوىيٹپچڈکگںھہیےংকচতধনফবযরলশষস়ািু্చయలిెొ్ംഅആഇഈഉഎഓകഗങചജഞടഡണതദധനപഫബഭമയരറലളവശസഹാിീുൂെേൈ്ൺൻർൽൾაბგდევზთილმნოპრსტუფქყშჩცძჭხạảấầẩậắặẹẽếềểệỉịọỏốồổỗộớờởợụủứừửữựỳ—、一上不个中为主乾了些亮人任低佔何作供依侧係個側偵充光入全关冇冷几切到制前動區卧厅厨及口另右吊后吗启吸呀咗哪唔問啟嗎嘅嘛器圍在场執場外多大始安定客室家密寵对將小少左已帘常幫幾库度庫廊廚廳开式後恆感態成我戲戶户房所扇手打执把拔换掉控插摄整斯新明是景暗更最會有未本模機檯櫃欄次正氏水沒没洗活派温測源溫漏潮激濕灯為無煙照熱燈燥物狀玄现現瓦用發的盞目着睡私空窗立笛管節簾籬紅線红罐置聚聲脚腦腳臥色节著行衣解設調請謝警设调走路車车运連遊運過道邊部都量鎖锁門閂閉開關门闭除隱離電震霧面音頂題顏颜風风食餅餵가간감갔강개거게겨결경고공과관그금급기길깥꺼껐꼽나난내네놀누는능니다닫담대더데도동됐되된됨둡드든등디때떤뜨라래러렇렌려로료른를리림링마많명몇모무문물뭐바밝방배변보부불블빨뽑사산상색서설성세센션소쇼수스습시신실싱아안않알았애야어얼업없었에여연열옆오온완외왼요운움워원위으은을음의이인일임입있작잠장재전절정제져조족종주줄중줘지직진짐쪽차창천최추출충치침커컴켜켰쿠크키탁탄태탬터텔통트튼티파팬퍼폰표퓨플핑한함해했행혀현화활후휴힘,?" - - micro_wake_word_model: okay_nabu - -esphome: - name: ${name} - friendly_name: ${friendly_name} - min_version: 2024.7.0 - name_add_mac_suffix: true - platformio_options: - board_build.flash_mode: dio - project: - name: esphome.voice-assistant - version: "24.8.1" - on_boot: - priority: 600 - then: - - script.execute: draw_display - - delay: 30s - - if: - condition: - lambda: return id(init_in_progress); - then: - - lambda: id(init_in_progress) = false; - - script.execute: draw_display - -esp32: - board: esp32s3box - flash_size: 16MB - framework: - type: esp-idf - sdkconfig_options: - CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240: "y" - CONFIG_ESP32S3_DATA_CACHE_64KB: "y" - CONFIG_ESP32S3_DATA_CACHE_LINE_64B: "y" - -psram: - mode: octal - speed: 80MHz - -external_components: - - source: github://pr#5230 - components: esp_adf - refresh: 0s - - source: github://jesserockz/esphome-components - components: [file] - refresh: 0s - -api: - on_client_connected: - - script.execute: draw_display - on_client_disconnected: - - script.execute: draw_display - -ota: - - platform: esphome - id: ota_esphome - - platform: http_request - id: ota_http_request - -update: - - platform: http_request - id: update_http_request - name: Firmware - source: https://firmware.esphome.io/wake-word-voice-assistant/esp32-s3-box-lite/manifest.json - -http_request: - -logger: - hardware_uart: USB_SERIAL_JTAG - logs: - sensor: INFO - -dashboard_import: - package_import_url: github://esphome/firmware/wake-word-voice-assistant/esp32-s3-box-lite.yaml@main - -wifi: - ap: - on_connect: - - script.execute: draw_display - - delay: 5s # Gives time for improv results to be transmitted - - ble.disable: - on_disconnect: - - script.execute: draw_display - - ble.enable: - -improv_serial: - -esp32_improv: - authorizer: none - -button: - - platform: factory_reset - id: factory_reset_btn - internal: true - -sensor: - - platform: adc - pin: GPIO1 - id: front_buttons - internal: true - update_interval: 16ms - attenuation: 11db - on_value: - - lambda: |- - // none: 3.121 - // left: 2.392 - // middle: 1.965 - // left+middle: 1.600 - // right: 0.794 - // left+right: 0.726 - // middle+right: 0.682 - // all: 0.632 - if (x > 3) { - id(left).publish_state(false); - id(middle).publish_state(false); - id(right).publish_state(false); - } else if (x > 2.3) { - id(left).publish_state(true); - id(middle).publish_state(false); - id(right).publish_state(false); - } else if (x > 1.9) { - id(left).publish_state(false); - id(middle).publish_state(true); - id(right).publish_state(false); - } else if (x > 1) { - id(left).publish_state(true); - id(middle).publish_state(true); - id(right).publish_state(false); - } else if (x > 0.73) { - id(left).publish_state(false); - id(middle).publish_state(false); - id(right).publish_state(true); - } else if (x > 0.7) { - id(left).publish_state(true); - id(middle).publish_state(false); - id(right).publish_state(true); - } else if (x > 0.65) { - id(left).publish_state(false); - id(middle).publish_state(true); - id(right).publish_state(true); - } else { - id(left).publish_state(true); - id(middle).publish_state(true); - id(right).publish_state(true); - } - -binary_sensor: - - platform: template - id: left - internal: true - on_press: - - switch.turn_off: timer_ringing - - platform: template - id: middle - internal: true - on_press: - - switch.turn_off: timer_ringing - - platform: template - id: right - internal: true - on_press: - - switch.turn_off: timer_ringing - - - platform: gpio - pin: - number: GPIO0 - mode: INPUT_PULLUP - inverted: true - id: left_top_button - internal: true - on_multi_click: - - timing: - - ON for at least 50ms - - OFF for at least 50ms - then: - - switch.turn_off: timer_ringing - - timing: - - ON for at least 10s - then: - - button.press: factory_reset_btn - -output: - - platform: ledc - pin: GPIO45 - inverted: true - id: backlight_output - -light: - - platform: monochromatic - id: led - name: Screen - icon: "mdi:television" - entity_category: config - output: backlight_output - restore_mode: RESTORE_DEFAULT_ON - default_transition_length: 250ms - -esp_adf: - board: esp32s3boxlite - -microphone: - - platform: esp_adf - id: box_mic - -speaker: - - platform: esp_adf - id: box_speaker - -micro_wake_word: - models: - - ${micro_wake_word_model} - on_wake_word_detected: - - voice_assistant.start: - wake_word: !lambda return wake_word; - -voice_assistant: - id: va - microphone: box_mic - speaker: box_speaker - noise_suppression_level: 2 - auto_gain: 31dBFS - volume_multiplier: 2.0 - vad_threshold: 3 - on_listening: - - lambda: id(voice_assistant_phase) = ${voice_assist_listening_phase_id}; - - text_sensor.template.publish: - id: text_request - state: "..." - - text_sensor.template.publish: - id: text_response - state: "..." - - script.execute: draw_display - on_stt_vad_end: - - lambda: id(voice_assistant_phase) = ${voice_assist_thinking_phase_id}; - - script.execute: draw_display - on_stt_end: - - text_sensor.template.publish: - id: text_request - state: !lambda return x; - - script.execute: draw_display - on_tts_start: - - text_sensor.template.publish: - id: text_response - state: !lambda return x; - on_tts_stream_start: - - lambda: id(voice_assistant_phase) = ${voice_assist_replying_phase_id}; - - script.execute: draw_display - on_tts_stream_end: - - if: - condition: - switch.is_off: mute - then: - - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id}; - else: - - lambda: id(voice_assistant_phase) = ${voice_assist_muted_phase_id}; - - script.execute: draw_display - on_end: - - wait_until: - not: - voice_assistant.is_running: - - if: - condition: - and: - - switch.is_off: mute - - lambda: return id(wake_word_engine_location).state == "On device"; - then: - - micro_wake_word.start: - on_error: - - if: - condition: - lambda: return !id(init_in_progress); - then: - - lambda: id(voice_assistant_phase) = ${voice_assist_error_phase_id}; - - script.execute: draw_display - - delay: 1s - - if: - condition: - switch.is_off: mute - then: - - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id}; - else: - - lambda: id(voice_assistant_phase) = ${voice_assist_muted_phase_id}; - - script.execute: draw_display - on_client_connected: - - wait_until: - not: ble.enabled - - lambda: id(init_in_progress) = false; - - script.execute: start_voice_assistant - - script.execute: draw_display - on_client_disconnected: - - script.execute: stop_voice_assistant - - script.execute: draw_display - on_timer_started: - - script.execute: draw_display - on_timer_cancelled: - - script.execute: draw_display - on_timer_updated: - - script.execute: draw_display - on_timer_tick: - - script.execute: draw_display - on_timer_finished: - - script.execute: stop_voice_assistant - - lambda: id(voice_assistant_phase) = ${voice_assist_timer_finished_phase_id}; - - switch.turn_on: timer_ringing - - script.execute: draw_display - - wait_until: - not: - microphone.is_capturing: - - while: - condition: - switch.is_on: timer_ringing - then: - - lambda: id(box_speaker).play(id(timer_finished_wave_file), sizeof(id(timer_finished_wave_file))); - - delay: 1s - - wait_until: - not: - speaker.is_playing: - - switch.turn_off: timer_ringing - - script.execute: start_voice_assistant - - script.execute: draw_display - -script: - - id: draw_display - then: - - if: - condition: - lambda: return !id(init_in_progress); - then: - - if: - condition: - wifi.connected: - then: - - if: - condition: - api.connected: - then: - - lambda: | - switch(id(voice_assistant_phase)) { - case ${voice_assist_listening_phase_id}: - id(s3_box_lcd).show_page(listening_page); - id(s3_box_lcd).update(); - break; - case ${voice_assist_thinking_phase_id}: - id(s3_box_lcd).show_page(thinking_page); - id(s3_box_lcd).update(); - break; - case ${voice_assist_replying_phase_id}: - id(s3_box_lcd).show_page(replying_page); - id(s3_box_lcd).update(); - break; - case ${voice_assist_error_phase_id}: - id(s3_box_lcd).show_page(error_page); - id(s3_box_lcd).update(); - break; - case ${voice_assist_muted_phase_id}: - id(s3_box_lcd).show_page(muted_page); - id(s3_box_lcd).update(); - break; - case ${voice_assist_not_ready_phase_id}: - id(s3_box_lcd).show_page(no_ha_page); - id(s3_box_lcd).update(); - break; - case ${voice_assist_timer_finished_phase_id}: - id(s3_box_lcd).show_page(timer_finished_page); - id(s3_box_lcd).update(); - break; - default: - id(s3_box_lcd).show_page(idle_page); - id(s3_box_lcd).update(); - } - else: - - display.page.show: no_ha_page - - component.update: s3_box_lcd - else: - - display.page.show: no_wifi_page - - component.update: s3_box_lcd - else: - - display.page.show: initializing_page - - component.update: s3_box_lcd - - - id: fetch_first_active_timer - then: - - lambda: | - const auto timers = id(va).get_timers(); - auto output_timer = timers.begin()->second; - for (auto &iterable_timer : timers) { - if (iterable_timer.second.is_active && iterable_timer.second.seconds_left <= output_timer.seconds_left) { - output_timer = iterable_timer.second; - } - } - id(global_first_active_timer) = output_timer; - - id: check_if_timers_active - then: - - lambda: | - const auto timers = id(va).get_timers(); - bool output = false; - if (timers.size() > 0) { - for (auto &iterable_timer : timers) { - if(iterable_timer.second.is_active) { - output = true; - } - } - } - id(global_is_timer_active) = output; - - id: fetch_first_timer - then: - - lambda: | - const auto timers = id(va).get_timers(); - auto output_timer = timers.begin()->second; - for (auto &iterable_timer : timers) { - if (iterable_timer.second.seconds_left <= output_timer.seconds_left) { - output_timer = iterable_timer.second; - } - } - id(global_first_timer) = output_timer; - - id: check_if_timers - then: - - lambda: | - const auto timers = id(va).get_timers(); - bool output = false; - if (timers.size() > 0) { - output = true; - } - id(global_is_timer) = output; - - - id: draw_timer_timeline - then: - - lambda: | - id(check_if_timers_active).execute(); - id(check_if_timers).execute(); - if (id(global_is_timer_active)){ - id(fetch_first_active_timer).execute(); - int active_pixels = round( 320 * id(global_first_active_timer).seconds_left / max(id(global_first_active_timer).total_seconds , static_cast(1)) ); - if (active_pixels > 0){ - id(s3_box_lcd).filled_rectangle(0 , 225 , 320 , 15 , Color::WHITE ); - id(s3_box_lcd).filled_rectangle(0 , 226 , active_pixels , 13 , id(active_timer_color) ); - } - } else if (id(global_is_timer)){ - id(fetch_first_timer).execute(); - int active_pixels = round( 320 * id(global_first_timer).seconds_left / max(id(global_first_timer).total_seconds , static_cast(1))); - if (active_pixels > 0){ - id(s3_box_lcd).filled_rectangle(0 , 225 , 320 , 15 , Color::WHITE ); - id(s3_box_lcd).filled_rectangle(0 , 226 , active_pixels , 13 , id(paused_timer_color) ); - } - } - - id: draw_active_timer_widget - then: - - lambda: | - id(check_if_timers_active).execute(); - if (id(global_is_timer_active)){ - id(s3_box_lcd).filled_rectangle(80 , 40 , 160 , 50 , Color::WHITE ); - id(s3_box_lcd).rectangle(80 , 40 , 160 , 50 , Color::BLACK ); - - id(fetch_first_active_timer).execute(); - int hours_left = floor(id(global_first_active_timer).seconds_left / 3600); - int minutes_left = floor((id(global_first_active_timer).seconds_left - hours_left * 3600) / 60); - int seconds_left = id(global_first_active_timer).seconds_left - hours_left * 3600 - minutes_left * 60 ; - auto display_hours = (hours_left < 10 ? "0" : "") + std::to_string(hours_left); - auto display_minute = (minutes_left < 10 ? "0" : "") + std::to_string(minutes_left); - auto display_seconds = (seconds_left < 10 ? "0" : "") + std::to_string(seconds_left) ; - - std::string display_string = ""; - if (hours_left > 0) { - display_string = display_hours + ":" + display_minute; - } else { - display_string = display_minute + ":" + display_seconds; - } - id(s3_box_lcd).printf(120, 47, id(font_timer), Color::BLACK, "%s", display_string.c_str()); - } - - - id: start_voice_assistant - then: - - if: - condition: - switch.is_off: mute - then: - - if: - condition: - lambda: return id(wake_word_engine_location).state == "In Home Assistant"; - then: - - lambda: id(va).set_use_wake_word(true); - - voice_assistant.start_continuous: - - if: - condition: - lambda: return id(wake_word_engine_location).state == "On device"; - then: - - lambda: id(va).set_use_wake_word(false); - - micro_wake_word.start - - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id}; - else: - - lambda: id(voice_assistant_phase) = ${voice_assist_muted_phase_id}; - - - id: stop_voice_assistant - then: - - if: - condition: - lambda: return id(wake_word_engine_location).state == "In Home Assistant"; - then: - - lambda: id(va).set_use_wake_word(false); - - voice_assistant.stop: - - if: - condition: - lambda: return id(wake_word_engine_location).state == "On device"; - then: - - voice_assistant.stop: - - micro_wake_word.stop: - - lambda: id(voice_assistant_phase) = ${voice_assist_not_ready_phase_id}; - -switch: - - platform: template - name: Mute - id: mute - icon: "mdi:microphone-off" - optimistic: true - restore_mode: RESTORE_DEFAULT_OFF - entity_category: config - on_turn_off: - - if: - condition: - lambda: return !id(init_in_progress); - then: - - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id}; - - if: - condition: - not: - - voice_assistant.is_running - then: - - if: - condition: - lambda: return id(wake_word_engine_location).state == "In Home Assistant"; - then: - - lambda: id(va).set_use_wake_word(true); - - voice_assistant.start_continuous - - if: - condition: - lambda: return id(wake_word_engine_location).state == "On device"; - then: - - lambda: id(va).set_use_wake_word(false); - - micro_wake_word.start - - script.execute: draw_display - on_turn_on: - - if: - condition: - lambda: return !id(init_in_progress); - then: - - lambda: id(va).set_use_wake_word(false); - - voice_assistant.stop - - micro_wake_word.stop - - lambda: id(voice_assistant_phase) = ${voice_assist_muted_phase_id}; - - script.execute: draw_display - - - platform: template - id: timer_ringing - optimistic: true - internal: true - restore_mode: ALWAYS_OFF - on_turn_on: - - delay: 15min - - switch.turn_off: timer_ringing - -select: - - platform: template - entity_category: config - name: Wake word engine location - id: wake_word_engine_location - icon: "mdi:account-voice" - optimistic: true - restore_value: true - options: - - In Home Assistant - - On device - initial_option: On device - on_value: - - if: - condition: - lambda: return !id(init_in_progress); - then: - - wait_until: - lambda: return id(voice_assistant_phase) == ${voice_assist_muted_phase_id} || id(voice_assistant_phase) == ${voice_assist_idle_phase_id}; - - if: - condition: - lambda: return x == "In Home Assistant"; - then: - - micro_wake_word.stop - - delay: 500ms - - if: - condition: - switch.is_off: mute - then: - - lambda: id(va).set_use_wake_word(true); - - voice_assistant.start_continuous: - - if: - condition: - lambda: return x == "On device"; - then: - - lambda: id(va).set_use_wake_word(false); - - voice_assistant.stop - - delay: 500ms - - if: - condition: - switch.is_off: mute - then: - - micro_wake_word.start - -globals: - - id: init_in_progress - type: bool - restore_value: false - initial_value: "true" - - id: voice_assistant_phase - type: int - restore_value: false - initial_value: ${voice_assist_not_ready_phase_id} - - id: global_first_active_timer - type: voice_assistant::Timer - restore_value: false - - id: global_is_timer_active - type: bool - restore_value: false - - id: global_first_timer - type: voice_assistant::Timer - restore_value: false - - id: global_is_timer - type: bool - restore_value: false - -image: - - file: ${error_illustration_file} - id: casita_error - resize: 320x240 - type: RGB24 - use_transparency: true - - file: ${idle_illustration_file} - id: casita_idle - resize: 320x240 - type: RGB24 - use_transparency: true - - file: ${listening_illustration_file} - id: casita_listening - resize: 320x240 - type: RGB24 - use_transparency: true - - file: ${thinking_illustration_file} - id: casita_thinking - resize: 320x240 - type: RGB24 - use_transparency: true - - file: ${replying_illustration_file} - id: casita_replying - resize: 320x240 - type: RGB24 - use_transparency: true - - file: ${timer_finished_illustration_file} - id: casita_timer_finished - resize: 320x240 - type: RGB24 - use_transparency: true - - file: ${loading_illustration_file} - id: casita_initializing - resize: 320x240 - type: RGB24 - use_transparency: true - - file: https://github.com/esphome/firmware/raw/main/voice-assistant/error_box_illustrations/error-no-wifi.png - id: error_no_wifi - resize: 320x240 - type: RGB24 - use_transparency: true - - file: https://github.com/esphome/firmware/raw/main/voice-assistant/error_box_illustrations/error-no-ha.png - id: error_no_ha - resize: 320x240 - type: RGB24 - use_transparency: true - -font: - - file: - type: gfonts - family: Figtree - weight: 300 - italic: true - glyphs: ${allowed_characters} - id: font_request - size: 15 - - file: - type: gfonts - family: Figtree - weight: 300 - glyphs: ${allowed_characters} - id: font_response - size: 15 - - file: - type: gfonts - family: Figtree - weight: 300 - glyphs: ${allowed_characters} - id: font_timer - size: 30 - -text_sensor: - - id: text_request - platform: template - on_value: - lambda: |- - if(id(text_request).state.length()>32) { - std::string name = id(text_request).state.c_str(); - std::string truncated = esphome::str_truncate(name.c_str(),31); - id(text_request).state = (truncated+"...").c_str(); - } - - - id: text_response - platform: template - on_value: - lambda: |- - if(id(text_response).state.length()>32) { - std::string name = id(text_response).state.c_str(); - std::string truncated = esphome::str_truncate(name.c_str(),31); - id(text_response).state = (truncated+"...").c_str(); - } - -color: - - id: idle_color - hex: ${idle_illustration_background_color} - - id: listening_color - hex: ${listening_illustration_background_color} - - id: thinking_color - hex: ${thinking_illustration_background_color} - - id: replying_color - hex: ${replying_illustration_background_color} - - id: loading_color - hex: ${loading_illustration_background_color} - - id: error_color - hex: ${error_illustration_background_color} - - id: active_timer_color - hex: "26ed3a" - - id: paused_timer_color - hex: "3b89e3" - -file: - - id: timer_finished_wave_file - file: https://github.com/esphome/firmware/raw/main/voice-assistant/sounds/timer_finished.wav - -spi: - - id: spi_bus - clk_pin: 7 - mosi_pin: 6 - -display: - - platform: ili9xxx - id: s3_box_lcd - model: S3BOX_LITE - data_rate: 40MHz - cs_pin: 5 - dc_pin: 4 - reset_pin: 48 - update_interval: never - pages: - - id: idle_page - lambda: |- - it.fill(id(idle_color)); - it.image((it.get_width() / 2), (it.get_height() / 2), id(casita_idle), ImageAlign::CENTER); - id(draw_timer_timeline).execute(); - id(draw_active_timer_widget).execute(); - - id: listening_page - lambda: |- - it.fill(id(listening_color)); - it.image((it.get_width() / 2), (it.get_height() / 2), id(casita_listening), ImageAlign::CENTER); - id(draw_timer_timeline).execute(); - - id: thinking_page - lambda: |- - it.fill(id(thinking_color)); - it.image((it.get_width() / 2), (it.get_height() / 2), id(casita_thinking), ImageAlign::CENTER); - it.filled_rectangle(20 , 20 , 280 , 30 , Color::WHITE ); - it.rectangle(20 , 20 , 280 , 30 , Color::BLACK ); - it.printf(30, 25, id(font_request), Color::BLACK, "%s", id(text_request).state.c_str()); - id(draw_timer_timeline).execute(); - - id: replying_page - lambda: |- - it.fill(id(replying_color)); - it.image((it.get_width() / 2), (it.get_height() / 2), id(casita_replying), ImageAlign::CENTER); - it.filled_rectangle(20 , 20 , 280 , 30 , Color::WHITE ); - it.rectangle(20 , 20 , 280 , 30 , Color::BLACK ); - it.filled_rectangle(20 , 190 , 280 , 30 , Color::WHITE ); - it.rectangle(20 , 190 , 280 , 30 , Color::BLACK ); - it.printf(30, 25, id(font_request), Color::BLACK, "%s", id(text_request).state.c_str()); - it.printf(30, 195, id(font_response), Color::BLACK, "%s", id(text_response).state.c_str()); - id(draw_timer_timeline).execute(); - - id: timer_finished_page - lambda: |- - it.fill(id(idle_color)); - it.image((it.get_width() / 2), (it.get_height() / 2), id(casita_timer_finished), ImageAlign::CENTER); - - id: error_page - lambda: |- - it.fill(id(error_color)); - it.image((it.get_width() / 2), (it.get_height() / 2), id(casita_error), ImageAlign::CENTER); - - id: no_ha_page - lambda: |- - it.image((it.get_width() / 2), (it.get_height() / 2), id(error_no_ha), ImageAlign::CENTER); - - id: no_wifi_page - lambda: |- - it.image((it.get_width() / 2), (it.get_height() / 2), id(error_no_wifi), ImageAlign::CENTER); - - id: initializing_page - lambda: |- - it.fill(id(loading_color)); - it.image((it.get_width() / 2), (it.get_height() / 2), id(casita_initializing), ImageAlign::CENTER); - - id: muted_page - lambda: |- - it.fill(Color::BLACK); - id(draw_timer_timeline).execute(); - id(draw_active_timer_widget).execute(); +packages: + moved: github://esphome/wake-word-voice-assistants/esp32-s3-box-lite/esp32-s3-box-lite.yaml@main diff --git a/wake-word-voice-assistant/esp32-s3-box.yaml b/wake-word-voice-assistant/esp32-s3-box.yaml index c1428e35..58a47c77 100644 --- a/wake-word-voice-assistant/esp32-s3-box.yaml +++ b/wake-word-voice-assistant/esp32-s3-box.yaml @@ -1,767 +1,2 @@ ---- -substitutions: - name: esp32-s3-box - friendly_name: ESP32 S3 Box - loading_illustration_file: https://github.com/esphome/firmware/raw/main/voice-assistant/casita/loading_320_240.png - idle_illustration_file: https://github.com/esphome/firmware/raw/main/voice-assistant/casita/idle_320_240.png - listening_illustration_file: https://github.com/esphome/firmware/raw/main/voice-assistant/casita/listening_320_240.png - thinking_illustration_file: https://github.com/esphome/firmware/raw/main/voice-assistant/casita/thinking_320_240.png - replying_illustration_file: https://github.com/esphome/firmware/raw/main/voice-assistant/casita/replying_320_240.png - error_illustration_file: https://github.com/esphome/firmware/raw/main/voice-assistant/casita/error_320_240.png - timer_finished_illustration_file: https://github.com/esphome/firmware/raw/main/voice-assistant/casita/timer_finished_320_240.png - - loading_illustration_background_color: "000000" - idle_illustration_background_color: "000000" - listening_illustration_background_color: "FFFFFF" - thinking_illustration_background_color: "FFFFFF" - replying_illustration_background_color: "FFFFFF" - error_illustration_background_color: "000000" - - voice_assist_idle_phase_id: "1" - voice_assist_listening_phase_id: "2" - voice_assist_thinking_phase_id: "3" - voice_assist_replying_phase_id: "4" - voice_assist_not_ready_phase_id: "10" - voice_assist_error_phase_id: "11" - voice_assist_muted_phase_id: "12" - voice_assist_timer_finished_phase_id: "20" - - # These unique characters have been extracted from every test file of every language available on https://github.com/home-assistant/intents (14 March 2024) - allowed_characters: " !#%'()+,-./0123456789:;<>?@ABCDEFGHIJKLMNOPQRSTUVWYZ[]_abcdefghijklmnopqrstuvwxyz{|}°²³µ¿ÁÂÄÅÉÖÚßàáâãäåæçèéêëìíîðñòóôõöøùúûüýþāăąćčďĐđēėęěğĮįıļľŁłńňőřśšťũūůűųźŻżŽžơưșțΆΈΌΐΑΒΓΔΕΖΗΘΚΜΝΠΡΣΤΥΦάέήίαβγδεζηθικλμνξοπρςστυφχψωϊόύώАБВГДЕЖЗИКЛМНОПРСТУХЦЧШЪЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяёђєіїјљњћאבגדהוזחטיכלםמןנסעפץצקרשת،ءآأإئابةتجحخدذرزسشصضطظعغفقكلمنهوىيٹپچڈکگںھہیےংকচতধনফবযরলশষস়ািু্చయలిెొ్ംഅആഇഈഉഎഓകഗങചജഞടഡണതദധനപഫബഭമയരറലളവശസഹാിീുൂെേൈ്ൺൻർൽൾაბგდევზთილმნოპრსტუფქყშჩცძჭხạảấầẩậắặẹẽếềểệỉịọỏốồổỗộớờởợụủứừửữựỳ—、一上不个中为主乾了些亮人任低佔何作供依侧係個側偵充光入全关冇冷几切到制前動區卧厅厨及口另右吊后吗启吸呀咗哪唔問啟嗎嘅嘛器圍在场執場外多大始安定客室家密寵对將小少左已帘常幫幾库度庫廊廚廳开式後恆感態成我戲戶户房所扇手打执把拔换掉控插摄整斯新明是景暗更最會有未本模機檯櫃欄次正氏水沒没洗活派温測源溫漏潮激濕灯為無煙照熱燈燥物狀玄现現瓦用發的盞目着睡私空窗立笛管節簾籬紅線红罐置聚聲脚腦腳臥色节著行衣解設調請謝警设调走路車车运連遊運過道邊部都量鎖锁門閂閉開關门闭除隱離電震霧面音頂題顏颜風风食餅餵가간감갔강개거게겨결경고공과관그금급기길깥꺼껐꼽나난내네놀누는능니다닫담대더데도동됐되된됨둡드든등디때떤뜨라래러렇렌려로료른를리림링마많명몇모무문물뭐바밝방배변보부불블빨뽑사산상색서설성세센션소쇼수스습시신실싱아안않알았애야어얼업없었에여연열옆오온완외왼요운움워원위으은을음의이인일임입있작잠장재전절정제져조족종주줄중줘지직진짐쪽차창천최추출충치침커컴켜켰쿠크키탁탄태탬터텔통트튼티파팬퍼폰표퓨플핑한함해했행혀현화활후휴힘,?" - - micro_wake_word_model: okay_nabu - -esphome: - name: ${name} - friendly_name: ${friendly_name} - min_version: 2024.7.0 - name_add_mac_suffix: true - platformio_options: - board_build.flash_mode: dio - project: - name: esphome.voice-assistant - version: "24.8.1" - on_boot: - priority: 600 - then: - - script.execute: draw_display - - delay: 30s - - if: - condition: - lambda: return id(init_in_progress); - then: - - lambda: id(init_in_progress) = false; - - script.execute: draw_display - -esp32: - board: esp32s3box - flash_size: 16MB - framework: - type: esp-idf - sdkconfig_options: - CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240: "y" - CONFIG_ESP32S3_DATA_CACHE_64KB: "y" - CONFIG_ESP32S3_DATA_CACHE_LINE_64B: "y" - -psram: - mode: octal - speed: 80MHz - -external_components: - - source: github://pr#5230 - components: esp_adf - refresh: 0s - - source: github://jesserockz/esphome-components - components: [file] - refresh: 0s - -api: - on_client_connected: - - script.execute: draw_display - on_client_disconnected: - - script.execute: draw_display - -ota: - - platform: esphome - id: ota_esphome - - platform: http_request - id: ota_http_request - -update: - - platform: http_request - id: update_http_request - name: Firmware - source: https://firmware.esphome.io/wake-word-voice-assistant/esp32-s3-box/manifest.json - -http_request: - -logger: - hardware_uart: USB_SERIAL_JTAG - -dashboard_import: - package_import_url: github://esphome/firmware/wake-word-voice-assistant/esp32-s3-box.yaml@main - -wifi: - ap: - on_connect: - - script.execute: draw_display - - delay: 5s # Gives time for improv results to be transmitted - - ble.disable: - on_disconnect: - - script.execute: draw_display - - ble.enable: - -improv_serial: - -esp32_improv: - authorizer: none - -button: - - platform: factory_reset - id: factory_reset_btn - internal: true - -binary_sensor: - - platform: gpio - pin: - number: GPIO0 - mode: INPUT_PULLUP - inverted: true - id: top_left_button - internal: true - on_multi_click: - - timing: - - ON for at least 50ms - - OFF for at least 50ms - then: - - switch.turn_off: timer_ringing - - timing: - - ON for at least 10s - then: - - button.press: factory_reset_btn - -output: - - platform: ledc - pin: GPIO45 - id: backlight_output - -light: - - platform: monochromatic - id: led - name: Screen - icon: "mdi:television" - entity_category: config - output: backlight_output - restore_mode: RESTORE_DEFAULT_ON - default_transition_length: 250ms - -esp_adf: - -microphone: - - platform: esp_adf - id: box_mic - -speaker: - - platform: esp_adf - id: box_speaker - -micro_wake_word: - models: - - ${micro_wake_word_model} - on_wake_word_detected: - - voice_assistant.start: - wake_word: !lambda return wake_word; - -voice_assistant: - id: va - microphone: box_mic - speaker: box_speaker - noise_suppression_level: 2 - auto_gain: 31dBFS - volume_multiplier: 2.0 - vad_threshold: 3 - on_listening: - - lambda: id(voice_assistant_phase) = ${voice_assist_listening_phase_id}; - - text_sensor.template.publish: - id: text_request - state: "..." - - text_sensor.template.publish: - id: text_response - state: "..." - - script.execute: draw_display - on_stt_vad_end: - - lambda: id(voice_assistant_phase) = ${voice_assist_thinking_phase_id}; - - script.execute: draw_display - on_stt_end: - - text_sensor.template.publish: - id: text_request - state: !lambda return x; - - script.execute: draw_display - on_tts_start: - - text_sensor.template.publish: - id: text_response - state: !lambda return x; - on_tts_stream_start: - - lambda: id(voice_assistant_phase) = ${voice_assist_replying_phase_id}; - - script.execute: draw_display - on_tts_stream_end: - - if: - condition: - switch.is_off: mute - then: - - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id}; - else: - - lambda: id(voice_assistant_phase) = ${voice_assist_muted_phase_id}; - - script.execute: draw_display - on_end: - - wait_until: - not: - voice_assistant.is_running: - - if: - condition: - and: - - switch.is_off: mute - - lambda: return id(wake_word_engine_location).state == "On device"; - then: - - micro_wake_word.start: - on_error: - - if: - condition: - lambda: return !id(init_in_progress); - then: - - lambda: id(voice_assistant_phase) = ${voice_assist_error_phase_id}; - - script.execute: draw_display - - delay: 1s - - if: - condition: - switch.is_off: mute - then: - - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id}; - else: - - lambda: id(voice_assistant_phase) = ${voice_assist_muted_phase_id}; - - script.execute: draw_display - on_client_connected: - - wait_until: - not: ble.enabled - - lambda: id(init_in_progress) = false; - - script.execute: start_voice_assistant - - script.execute: draw_display - on_client_disconnected: - - script.execute: stop_voice_assistant - - script.execute: draw_display - on_timer_started: - - script.execute: draw_display - on_timer_cancelled: - - script.execute: draw_display - on_timer_updated: - - script.execute: draw_display - on_timer_tick: - - script.execute: draw_display - on_timer_finished: - - script.execute: stop_voice_assistant - - lambda: id(voice_assistant_phase) = ${voice_assist_timer_finished_phase_id}; - - switch.turn_on: timer_ringing - - script.execute: draw_display - - wait_until: - not: - microphone.is_capturing: - - while: - condition: - switch.is_on: timer_ringing - then: - - lambda: id(box_speaker).play(id(timer_finished_wave_file), sizeof(id(timer_finished_wave_file))); - - delay: 1s - - wait_until: - not: - speaker.is_playing: - - switch.turn_off: timer_ringing - - script.execute: start_voice_assistant - - script.execute: draw_display - -script: - - id: draw_display - then: - - if: - condition: - lambda: return !id(init_in_progress); - then: - - if: - condition: - wifi.connected: - then: - - if: - condition: - api.connected: - then: - - lambda: | - switch(id(voice_assistant_phase)) { - case ${voice_assist_listening_phase_id}: - id(s3_box_lcd).show_page(listening_page); - id(s3_box_lcd).update(); - break; - case ${voice_assist_thinking_phase_id}: - id(s3_box_lcd).show_page(thinking_page); - id(s3_box_lcd).update(); - break; - case ${voice_assist_replying_phase_id}: - id(s3_box_lcd).show_page(replying_page); - id(s3_box_lcd).update(); - break; - case ${voice_assist_error_phase_id}: - id(s3_box_lcd).show_page(error_page); - id(s3_box_lcd).update(); - break; - case ${voice_assist_muted_phase_id}: - id(s3_box_lcd).show_page(muted_page); - id(s3_box_lcd).update(); - break; - case ${voice_assist_not_ready_phase_id}: - id(s3_box_lcd).show_page(no_ha_page); - id(s3_box_lcd).update(); - break; - case ${voice_assist_timer_finished_phase_id}: - id(s3_box_lcd).show_page(timer_finished_page); - id(s3_box_lcd).update(); - break; - default: - id(s3_box_lcd).show_page(idle_page); - id(s3_box_lcd).update(); - } - else: - - display.page.show: no_ha_page - - component.update: s3_box_lcd - else: - - display.page.show: no_wifi_page - - component.update: s3_box_lcd - else: - - display.page.show: initializing_page - - component.update: s3_box_lcd - - - id: fetch_first_active_timer - then: - - lambda: | - const auto timers = id(va).get_timers(); - auto output_timer = timers.begin()->second; - for (auto &iterable_timer : timers) { - if (iterable_timer.second.is_active && iterable_timer.second.seconds_left <= output_timer.seconds_left) { - output_timer = iterable_timer.second; - } - } - id(global_first_active_timer) = output_timer; - - id: check_if_timers_active - then: - - lambda: | - const auto timers = id(va).get_timers(); - bool output = false; - if (timers.size() > 0) { - for (auto &iterable_timer : timers) { - if(iterable_timer.second.is_active) { - output = true; - } - } - } - id(global_is_timer_active) = output; - - id: fetch_first_timer - then: - - lambda: | - const auto timers = id(va).get_timers(); - auto output_timer = timers.begin()->second; - for (auto &iterable_timer : timers) { - if (iterable_timer.second.seconds_left <= output_timer.seconds_left) { - output_timer = iterable_timer.second; - } - } - id(global_first_timer) = output_timer; - - id: check_if_timers - then: - - lambda: | - const auto timers = id(va).get_timers(); - bool output = false; - if (timers.size() > 0) { - output = true; - } - id(global_is_timer) = output; - - - id: draw_timer_timeline - then: - - lambda: | - id(check_if_timers_active).execute(); - id(check_if_timers).execute(); - if (id(global_is_timer_active)){ - id(fetch_first_active_timer).execute(); - int active_pixels = round( 320 * id(global_first_active_timer).seconds_left / max(id(global_first_active_timer).total_seconds , static_cast(1)) ); - if (active_pixels > 0){ - id(s3_box_lcd).filled_rectangle(0 , 225 , 320 , 15 , Color::WHITE ); - id(s3_box_lcd).filled_rectangle(0 , 226 , active_pixels , 13 , id(active_timer_color) ); - } - } else if (id(global_is_timer)){ - id(fetch_first_timer).execute(); - int active_pixels = round( 320 * id(global_first_timer).seconds_left / max(id(global_first_timer).total_seconds , static_cast(1))); - if (active_pixels > 0){ - id(s3_box_lcd).filled_rectangle(0 , 225 , 320 , 15 , Color::WHITE ); - id(s3_box_lcd).filled_rectangle(0 , 226 , active_pixels , 13 , id(paused_timer_color) ); - } - } - - id: draw_active_timer_widget - then: - - lambda: | - id(check_if_timers_active).execute(); - if (id(global_is_timer_active)){ - id(s3_box_lcd).filled_rectangle(80 , 40 , 160 , 50 , Color::WHITE ); - id(s3_box_lcd).rectangle(80 , 40 , 160 , 50 , Color::BLACK ); - - id(fetch_first_active_timer).execute(); - int hours_left = floor(id(global_first_active_timer).seconds_left / 3600); - int minutes_left = floor((id(global_first_active_timer).seconds_left - hours_left * 3600) / 60); - int seconds_left = id(global_first_active_timer).seconds_left - hours_left * 3600 - minutes_left * 60 ; - auto display_hours = (hours_left < 10 ? "0" : "") + std::to_string(hours_left); - auto display_minute = (minutes_left < 10 ? "0" : "") + std::to_string(minutes_left); - auto display_seconds = (seconds_left < 10 ? "0" : "") + std::to_string(seconds_left) ; - - std::string display_string = ""; - if (hours_left > 0) { - display_string = display_hours + ":" + display_minute; - } else { - display_string = display_minute + ":" + display_seconds; - } - id(s3_box_lcd).printf(120, 47, id(font_timer), Color::BLACK, "%s", display_string.c_str()); - } - - - id: start_voice_assistant - then: - - if: - condition: - switch.is_off: mute - then: - - if: - condition: - lambda: return id(wake_word_engine_location).state == "In Home Assistant"; - then: - - lambda: id(va).set_use_wake_word(true); - - voice_assistant.start_continuous: - - if: - condition: - lambda: return id(wake_word_engine_location).state == "On device"; - then: - - lambda: id(va).set_use_wake_word(false); - - micro_wake_word.start - - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id}; - else: - - lambda: id(voice_assistant_phase) = ${voice_assist_muted_phase_id}; - - - id: stop_voice_assistant - then: - - if: - condition: - lambda: return id(wake_word_engine_location).state == "In Home Assistant"; - then: - - lambda: id(va).set_use_wake_word(false); - - voice_assistant.stop: - - if: - condition: - lambda: return id(wake_word_engine_location).state == "On device"; - then: - - voice_assistant.stop: - - micro_wake_word.stop: - - lambda: id(voice_assistant_phase) = ${voice_assist_not_ready_phase_id}; - -switch: - - platform: template - name: Mute - id: mute - icon: "mdi:microphone-off" - optimistic: true - restore_mode: RESTORE_DEFAULT_OFF - entity_category: config - on_turn_off: - - if: - condition: - lambda: return !id(init_in_progress); - then: - - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id}; - - if: - condition: - not: - - voice_assistant.is_running - then: - - if: - condition: - lambda: return id(wake_word_engine_location).state == "In Home Assistant"; - then: - - lambda: id(va).set_use_wake_word(true); - - voice_assistant.start_continuous - - if: - condition: - lambda: return id(wake_word_engine_location).state == "On device"; - then: - - lambda: id(va).set_use_wake_word(false); - - micro_wake_word.start - - script.execute: draw_display - on_turn_on: - - if: - condition: - lambda: return !id(init_in_progress); - then: - - lambda: id(va).set_use_wake_word(false); - - voice_assistant.stop - - micro_wake_word.stop - - lambda: id(voice_assistant_phase) = ${voice_assist_muted_phase_id}; - - script.execute: draw_display - - - platform: template - id: timer_ringing - optimistic: true - internal: true - restore_mode: ALWAYS_OFF - on_turn_on: - - delay: 15min - - switch.turn_off: timer_ringing - -select: - - platform: template - entity_category: config - name: Wake word engine location - id: wake_word_engine_location - icon: "mdi:account-voice" - optimistic: true - restore_value: true - options: - - In Home Assistant - - On device - initial_option: On device - on_value: - - if: - condition: - lambda: return !id(init_in_progress); - then: - - wait_until: - lambda: return id(voice_assistant_phase) == ${voice_assist_muted_phase_id} || id(voice_assistant_phase) == ${voice_assist_idle_phase_id}; - - if: - condition: - lambda: return x == "In Home Assistant"; - then: - - micro_wake_word.stop - - delay: 500ms - - if: - condition: - switch.is_off: mute - then: - - lambda: id(va).set_use_wake_word(true); - - voice_assistant.start_continuous: - - if: - condition: - lambda: return x == "On device"; - then: - - lambda: id(va).set_use_wake_word(false); - - voice_assistant.stop - - delay: 500ms - - if: - condition: - switch.is_off: mute - then: - - micro_wake_word.start - -globals: - - id: init_in_progress - type: bool - restore_value: false - initial_value: "true" - - id: voice_assistant_phase - type: int - restore_value: false - initial_value: ${voice_assist_not_ready_phase_id} - - id: global_first_active_timer - type: voice_assistant::Timer - restore_value: false - - id: global_is_timer_active - type: bool - restore_value: false - - id: global_first_timer - type: voice_assistant::Timer - restore_value: false - - id: global_is_timer - type: bool - restore_value: false - -image: - - file: ${error_illustration_file} - id: casita_error - resize: 320x240 - type: RGB24 - use_transparency: true - - file: ${idle_illustration_file} - id: casita_idle - resize: 320x240 - type: RGB24 - use_transparency: true - - file: ${listening_illustration_file} - id: casita_listening - resize: 320x240 - type: RGB24 - use_transparency: true - - file: ${thinking_illustration_file} - id: casita_thinking - resize: 320x240 - type: RGB24 - use_transparency: true - - file: ${replying_illustration_file} - id: casita_replying - resize: 320x240 - type: RGB24 - use_transparency: true - - file: ${timer_finished_illustration_file} - id: casita_timer_finished - resize: 320x240 - type: RGB24 - use_transparency: true - - file: ${loading_illustration_file} - id: casita_initializing - resize: 320x240 - type: RGB24 - use_transparency: true - - file: https://github.com/esphome/firmware/raw/main/voice-assistant/error_box_illustrations/error-no-wifi.png - id: error_no_wifi - resize: 320x240 - type: RGB24 - use_transparency: true - - file: https://github.com/esphome/firmware/raw/main/voice-assistant/error_box_illustrations/error-no-ha.png - id: error_no_ha - resize: 320x240 - type: RGB24 - use_transparency: true - -font: - - file: - type: gfonts - family: Figtree - weight: 300 - italic: true - glyphs: ${allowed_characters} - id: font_request - size: 15 - - file: - type: gfonts - family: Figtree - weight: 300 - glyphs: ${allowed_characters} - id: font_response - size: 15 - - file: - type: gfonts - family: Figtree - weight: 300 - glyphs: ${allowed_characters} - id: font_timer - size: 30 - -text_sensor: - - id: text_request - platform: template - on_value: - lambda: |- - if(id(text_request).state.length()>32) { - std::string name = id(text_request).state.c_str(); - std::string truncated = esphome::str_truncate(name.c_str(),31); - id(text_request).state = (truncated+"...").c_str(); - } - - - id: text_response - platform: template - on_value: - lambda: |- - if(id(text_response).state.length()>32) { - std::string name = id(text_response).state.c_str(); - std::string truncated = esphome::str_truncate(name.c_str(),31); - id(text_response).state = (truncated+"...").c_str(); - } - -color: - - id: idle_color - hex: ${idle_illustration_background_color} - - id: listening_color - hex: ${listening_illustration_background_color} - - id: thinking_color - hex: ${thinking_illustration_background_color} - - id: replying_color - hex: ${replying_illustration_background_color} - - id: loading_color - hex: ${loading_illustration_background_color} - - id: error_color - hex: ${error_illustration_background_color} - - id: active_timer_color - hex: "26ed3a" - - id: paused_timer_color - hex: "3b89e3" - -file: - - id: timer_finished_wave_file - file: https://github.com/esphome/firmware/raw/main/voice-assistant/sounds/timer_finished.wav - -spi: - - id: spi_bus - clk_pin: 7 - mosi_pin: 6 - -display: - - platform: ili9xxx - id: s3_box_lcd - model: S3BOX - data_rate: 40MHz - cs_pin: 5 - dc_pin: 4 - reset_pin: 48 - update_interval: never - pages: - - id: idle_page - lambda: |- - it.fill(id(idle_color)); - it.image((it.get_width() / 2), (it.get_height() / 2), id(casita_idle), ImageAlign::CENTER); - id(draw_timer_timeline).execute(); - id(draw_active_timer_widget).execute(); - - id: listening_page - lambda: |- - it.fill(id(listening_color)); - it.image((it.get_width() / 2), (it.get_height() / 2), id(casita_listening), ImageAlign::CENTER); - id(draw_timer_timeline).execute(); - - id: thinking_page - lambda: |- - it.fill(id(thinking_color)); - it.image((it.get_width() / 2), (it.get_height() / 2), id(casita_thinking), ImageAlign::CENTER); - it.filled_rectangle(20 , 20 , 280 , 30 , Color::WHITE ); - it.rectangle(20 , 20 , 280 , 30 , Color::BLACK ); - it.printf(30, 25, id(font_request), Color::BLACK, "%s", id(text_request).state.c_str()); - id(draw_timer_timeline).execute(); - - id: replying_page - lambda: |- - it.fill(id(replying_color)); - it.image((it.get_width() / 2), (it.get_height() / 2), id(casita_replying), ImageAlign::CENTER); - it.filled_rectangle(20 , 20 , 280 , 30 , Color::WHITE ); - it.rectangle(20 , 20 , 280 , 30 , Color::BLACK ); - it.filled_rectangle(20 , 190 , 280 , 30 , Color::WHITE ); - it.rectangle(20 , 190 , 280 , 30 , Color::BLACK ); - it.printf(30, 25, id(font_request), Color::BLACK, "%s", id(text_request).state.c_str()); - it.printf(30, 195, id(font_response), Color::BLACK, "%s", id(text_response).state.c_str()); - id(draw_timer_timeline).execute(); - - id: timer_finished_page - lambda: |- - it.fill(id(idle_color)); - it.image((it.get_width() / 2), (it.get_height() / 2), id(casita_timer_finished), ImageAlign::CENTER); - - id: error_page - lambda: |- - it.fill(id(error_color)); - it.image((it.get_width() / 2), (it.get_height() / 2), id(casita_error), ImageAlign::CENTER); - - id: no_ha_page - lambda: |- - it.image((it.get_width() / 2), (it.get_height() / 2), id(error_no_ha), ImageAlign::CENTER); - - id: no_wifi_page - lambda: |- - it.image((it.get_width() / 2), (it.get_height() / 2), id(error_no_wifi), ImageAlign::CENTER); - - id: initializing_page - lambda: |- - it.fill(id(loading_color)); - it.image((it.get_width() / 2), (it.get_height() / 2), id(casita_initializing), ImageAlign::CENTER); - - id: muted_page - lambda: |- - it.fill(Color::BLACK); - id(draw_timer_timeline).execute(); - id(draw_active_timer_widget).execute(); +packages: + moved: github://esphome/wake-word-voice-assistants/esp32-s3-box/esp32-s3-box.yaml@main diff --git a/wake-word-voice-assistant/m5stack-atom-echo.adopted.yaml b/wake-word-voice-assistant/m5stack-atom-echo.adopted.yaml index 5138221e..00d9a66f 100644 --- a/wake-word-voice-assistant/m5stack-atom-echo.adopted.yaml +++ b/wake-word-voice-assistant/m5stack-atom-echo.adopted.yaml @@ -1,331 +1,2 @@ -substitutions: - name: m5stack-atom-echo - friendly_name: M5Stack Atom Echo - micro_wake_word_model: okay_nabu # alexa, hey_jarvis, hey_mycroft are also supported - -esphome: - name: ${name} - name_add_mac_suffix: true - friendly_name: ${friendly_name} - min_version: 2024.7.1 - -esp32: - board: m5stack-atom - framework: - type: esp-idf - -logger: -api: - -ota: - - platform: esphome - id: ota_esphome - -wifi: - ap: - -captive_portal: - -button: - - platform: factory_reset - id: factory_reset_btn - name: Factory reset - -i2s_audio: - - id: i2s_audio_bus - i2s_lrclk_pin: GPIO33 - i2s_bclk_pin: GPIO19 - -microphone: - - platform: i2s_audio - id: echo_microphone - i2s_din_pin: GPIO23 - adc_type: external - pdm: true - -speaker: - - platform: i2s_audio - id: echo_speaker - i2s_dout_pin: GPIO22 - dac_type: external - mode: mono - -voice_assistant: - id: va - microphone: echo_microphone - speaker: echo_speaker - noise_suppression_level: 2 - auto_gain: 31dBFS - volume_multiplier: 2.0 - vad_threshold: 3 - on_listening: - - light.turn_on: - id: led - blue: 100% - red: 0% - green: 0% - effect: "Slow Pulse" - on_stt_vad_end: - - light.turn_on: - id: led - blue: 100% - red: 0% - green: 0% - effect: "Fast Pulse" - on_tts_start: - - light.turn_on: - id: led - blue: 100% - red: 0% - green: 0% - brightness: 100% - effect: none - on_end: - - delay: 100ms - - voice_assistant.stop: - - wait_until: - not: - voice_assistant.is_running: - - wait_until: - not: - switch.is_on: timer_ringing - - if: - condition: - lambda: return id(wake_word_engine_location).state == "On device"; - then: - - micro_wake_word.start: - - script.execute: reset_led - else: - - voice_assistant.start_continuous: - - script.execute: reset_led - on_error: - - light.turn_on: - id: led - red: 100% - green: 0% - blue: 0% - brightness: 100% - effect: none - - delay: 2s - - script.execute: reset_led - on_client_connected: - - delay: 2s # Give the api server time to settle - - if: - condition: - lambda: return id(wake_word_engine_location).state == "On device"; - then: - - micro_wake_word.start: - else: - - voice_assistant.start_continuous: - - script.execute: reset_led - on_client_disconnected: - - voice_assistant.stop: - - micro_wake_word.stop: - on_timer_finished: - - voice_assistant.stop: - - micro_wake_word.stop: - - switch.turn_on: timer_ringing - - wait_until: - not: - microphone.is_capturing: - - light.turn_on: - id: led - red: 0% - green: 100% - blue: 0% - brightness: 100% - effect: "Fast Pulse" - - while: - condition: - switch.is_on: timer_ringing - then: - - lambda: id(echo_speaker).play(id(timer_finished_wave_file), sizeof(id(timer_finished_wave_file))); - - delay: 1s - - wait_until: - not: - speaker.is_playing: - - light.turn_off: led - - switch.turn_off: timer_ringing - - if: - condition: - lambda: return id(wake_word_engine_location).state == "On device"; - then: - - micro_wake_word.start: - - script.execute: reset_led - else: - - voice_assistant.start_continuous: - - script.execute: reset_led - -binary_sensor: - # button does the following: - # short click - stop a timer - # if no timer then restart either microwakeword or voice assistant continuous - - platform: gpio - pin: - number: GPIO39 - inverted: true - name: Button - disabled_by_default: true - entity_category: diagnostic - id: echo_button - on_multi_click: - - timing: - - ON for at least 50ms - - OFF for at least 50ms - then: - - if: - condition: - switch.is_on: timer_ringing - then: - - switch.turn_off: timer_ringing - else: - - if: - condition: - lambda: return id(wake_word_engine_location).state == "On device"; - then: - - voice_assistant.stop - - micro_wake_word.stop: - - delay: 1s - - script.execute: reset_led - - script.wait: reset_led - - micro_wake_word.start: - else: - - if: - condition: voice_assistant.is_running - then: - - voice_assistant.stop: - - script.execute: reset_led - - voice_assistant.start_continuous: - - timing: - - ON for at least 10s - then: - - button.press: factory_reset_btn - -light: - - platform: esp32_rmt_led_strip - id: led - name: None - disabled_by_default: true - entity_category: config - pin: GPIO27 - default_transition_length: 0s - chipset: SK6812 - num_leds: 1 - rgb_order: grb - rmt_channel: 0 - effects: - - pulse: - name: "Slow Pulse" - transition_length: 250ms - update_interval: 250ms - min_brightness: 50% - max_brightness: 100% - - pulse: - name: "Fast Pulse" - transition_length: 100ms - update_interval: 100ms - min_brightness: 50% - max_brightness: 100% - -script: - - id: reset_led - then: - - if: - condition: - - lambda: return id(wake_word_engine_location).state == "On device"; - - switch.is_on: use_listen_light - then: - - light.turn_on: - id: led - red: 100% - green: 89% - blue: 71% - brightness: 60% - effect: none - else: - - if: - condition: - - lambda: return id(wake_word_engine_location).state != "On device"; - - switch.is_on: use_listen_light - then: - - light.turn_on: - id: led - red: 0% - green: 100% - blue: 100% - brightness: 60% - effect: none - else: - - light.turn_off: led - -switch: - - platform: template - name: Use listen light - id: use_listen_light - optimistic: true - restore_mode: RESTORE_DEFAULT_ON - entity_category: config - on_turn_on: - - script.execute: reset_led - on_turn_off: - - script.execute: reset_led - - platform: template - id: timer_ringing - optimistic: true - internal: true - restore_mode: ALWAYS_OFF - on_turn_on: - - delay: 15min - - switch.turn_off: timer_ringing - -select: - - platform: template - entity_category: config - name: Wake word engine location - id: wake_word_engine_location - optimistic: true - restore_value: true - options: - - In Home Assistant - - On device - initial_option: On device - on_value: - - if: - condition: - lambda: return x == "In Home Assistant"; - then: - - micro_wake_word.stop - - delay: 500ms - - lambda: id(va).set_use_wake_word(true); - - voice_assistant.start_continuous: - - if: - condition: - lambda: return x == "On device"; - then: - - lambda: id(va).set_use_wake_word(false); - - voice_assistant.stop - - delay: 500ms - - micro_wake_word.start - -external_components: - - source: github://pr#5230 - components: - - esp_adf - refresh: 0s - - source: github://jesserockz/esphome-components - components: [file] - refresh: 0s - -esp_adf: - -file: - - id: timer_finished_wave_file - file: https://github.com/esphome/firmware/raw/main/voice-assistant/sounds/timer_finished.wav - -micro_wake_word: - on_wake_word_detected: - - voice_assistant.start: - wake_word: !lambda return wake_word; - vad: - models: - - model: ${micro_wake_word_model} +packages: + moved: github://esphome/wake-word-voice-assistants/m5stack-atom-echo/m5stack-atom-echo.yaml@main diff --git a/wake-word-voice-assistant/m5stack-atom-echo.yaml b/wake-word-voice-assistant/m5stack-atom-echo.yaml index 48d8652e..00d9a66f 100644 --- a/wake-word-voice-assistant/m5stack-atom-echo.yaml +++ b/wake-word-voice-assistant/m5stack-atom-echo.yaml @@ -1,349 +1,2 @@ -substitutions: - name: m5stack-atom-echo - friendly_name: M5Stack Atom Echo - micro_wake_word_model: okay_nabu # alexa, hey_jarvis, hey_mycroft are also supported - -esphome: - name: ${name} - name_add_mac_suffix: true - friendly_name: ${friendly_name} - min_version: 2024.7.1 - project: - name: m5stack.atom-echo-wake-word-voice-assistant - version: "24.8.1" - -esp32: - board: m5stack-atom - framework: - type: esp-idf - -logger: -api: - -ota: - - platform: esphome - id: ota_esphome - - platform: http_request - id: ota_http_request - -update: - - platform: http_request - id: update_http_request - name: Firmware - source: https://firmware.esphome.io/wake-word-voice-assistant/m5stack-atom-echo/manifest.json - -http_request: - -dashboard_import: - package_import_url: github://esphome/firmware/wake-word-voice-assistant/m5stack-atom-echo.adopted.yaml@main - -wifi: - ap: - -improv_serial: - -captive_portal: - -button: - - platform: factory_reset - id: factory_reset_btn - name: Factory reset - -i2s_audio: - - id: i2s_audio_bus - i2s_lrclk_pin: GPIO33 - i2s_bclk_pin: GPIO19 - -microphone: - - platform: i2s_audio - id: echo_microphone - i2s_din_pin: GPIO23 - adc_type: external - pdm: true - -speaker: - - platform: i2s_audio - id: echo_speaker - i2s_dout_pin: GPIO22 - dac_type: external - mode: mono - -voice_assistant: - id: va - microphone: echo_microphone - speaker: echo_speaker - noise_suppression_level: 2 - auto_gain: 31dBFS - volume_multiplier: 2.0 - vad_threshold: 3 - on_listening: - - light.turn_on: - id: led - blue: 100% - red: 0% - green: 0% - effect: "Slow Pulse" - on_stt_vad_end: - - light.turn_on: - id: led - blue: 100% - red: 0% - green: 0% - effect: "Fast Pulse" - on_tts_start: - - light.turn_on: - id: led - blue: 100% - red: 0% - green: 0% - brightness: 100% - effect: none - on_end: - - delay: 100ms - - voice_assistant.stop: - - wait_until: - not: - voice_assistant.is_running: - - wait_until: - not: - switch.is_on: timer_ringing - - if: - condition: - lambda: return id(wake_word_engine_location).state == "On device"; - then: - - micro_wake_word.start: - - script.execute: reset_led - else: - - voice_assistant.start_continuous: - - script.execute: reset_led - on_error: - - light.turn_on: - id: led - red: 100% - green: 0% - blue: 0% - brightness: 100% - effect: none - - delay: 2s - - script.execute: reset_led - on_client_connected: - - delay: 2s # Give the api server time to settle - - if: - condition: - lambda: return id(wake_word_engine_location).state == "On device"; - then: - - micro_wake_word.start: - else: - - voice_assistant.start_continuous: - - script.execute: reset_led - on_client_disconnected: - - voice_assistant.stop: - - micro_wake_word.stop: - on_timer_finished: - - voice_assistant.stop: - - micro_wake_word.stop: - - switch.turn_on: timer_ringing - - wait_until: - not: - microphone.is_capturing: - - light.turn_on: - id: led - red: 0% - green: 100% - blue: 0% - brightness: 100% - effect: "Fast Pulse" - - while: - condition: - switch.is_on: timer_ringing - then: - - lambda: id(echo_speaker).play(id(timer_finished_wave_file), sizeof(id(timer_finished_wave_file))); - - delay: 1s - - wait_until: - not: - speaker.is_playing: - - light.turn_off: led - - switch.turn_off: timer_ringing - - if: - condition: - lambda: return id(wake_word_engine_location).state == "On device"; - then: - - micro_wake_word.start: - - script.execute: reset_led - else: - - voice_assistant.start_continuous: - - script.execute: reset_led - -binary_sensor: - # button does the following: - # short click - stop a timer - # if no timer then restart either microwakeword or voice assistant continuous - - platform: gpio - pin: - number: GPIO39 - inverted: true - name: Button - disabled_by_default: true - entity_category: diagnostic - id: echo_button - on_multi_click: - - timing: - - ON for at least 50ms - - OFF for at least 50ms - then: - - if: - condition: - switch.is_on: timer_ringing - then: - - switch.turn_off: timer_ringing - else: - - if: - condition: - lambda: return id(wake_word_engine_location).state == "On device"; - then: - - voice_assistant.stop - - micro_wake_word.stop: - - delay: 1s - - script.execute: reset_led - - script.wait: reset_led - - micro_wake_word.start: - else: - - if: - condition: voice_assistant.is_running - then: - - voice_assistant.stop: - - script.execute: reset_led - - voice_assistant.start_continuous: - - timing: - - ON for at least 10s - then: - - button.press: factory_reset_btn - -light: - - platform: esp32_rmt_led_strip - id: led - name: None - disabled_by_default: true - entity_category: config - pin: GPIO27 - default_transition_length: 0s - chipset: SK6812 - num_leds: 1 - rgb_order: grb - rmt_channel: 0 - effects: - - pulse: - name: "Slow Pulse" - transition_length: 250ms - update_interval: 250ms - min_brightness: 50% - max_brightness: 100% - - pulse: - name: "Fast Pulse" - transition_length: 100ms - update_interval: 100ms - min_brightness: 50% - max_brightness: 100% - -script: - - id: reset_led - then: - - if: - condition: - - lambda: return id(wake_word_engine_location).state == "On device"; - - switch.is_on: use_listen_light - then: - - light.turn_on: - id: led - red: 100% - green: 89% - blue: 71% - brightness: 60% - effect: none - else: - - if: - condition: - - lambda: return id(wake_word_engine_location).state != "On device"; - - switch.is_on: use_listen_light - then: - - light.turn_on: - id: led - red: 0% - green: 100% - blue: 100% - brightness: 60% - effect: none - else: - - light.turn_off: led - -switch: - - platform: template - name: Use listen light - id: use_listen_light - optimistic: true - restore_mode: RESTORE_DEFAULT_ON - entity_category: config - on_turn_on: - - script.execute: reset_led - on_turn_off: - - script.execute: reset_led - - platform: template - id: timer_ringing - optimistic: true - internal: true - restore_mode: ALWAYS_OFF - on_turn_on: - - delay: 15min - - switch.turn_off: timer_ringing - -select: - - platform: template - entity_category: config - name: Wake word engine location - id: wake_word_engine_location - optimistic: true - restore_value: true - options: - - In Home Assistant - - On device - initial_option: On device - on_value: - - if: - condition: - lambda: return x == "In Home Assistant"; - then: - - micro_wake_word.stop - - delay: 500ms - - lambda: id(va).set_use_wake_word(true); - - voice_assistant.start_continuous: - - if: - condition: - lambda: return x == "On device"; - then: - - lambda: id(va).set_use_wake_word(false); - - voice_assistant.stop - - delay: 500ms - - micro_wake_word.start - -external_components: - - source: github://pr#5230 - components: - - esp_adf - refresh: 0s - - source: github://jesserockz/esphome-components - components: [file] - refresh: 0s - -esp_adf: - -file: - - id: timer_finished_wave_file - file: https://github.com/esphome/firmware/raw/main/voice-assistant/sounds/timer_finished.wav - -micro_wake_word: - on_wake_word_detected: - - voice_assistant.start: - wake_word: !lambda return wake_word; - vad: - models: - - model: ${micro_wake_word_model} +packages: + moved: github://esphome/wake-word-voice-assistants/m5stack-atom-echo/m5stack-atom-echo.yaml@main