mirror of
				https://github.com/esphome/esphome.git
				synced 2025-11-04 09:01:49 +00:00 
			
		
		
		
	Compare commits
	
		
			158 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					8bf0448f41 | ||
| 
						 | 
					14e04eb231 | ||
| 
						 | 
					1be9bac3a9 | ||
| 
						 | 
					02b5a3efb8 | ||
| 
						 | 
					bd457f64d8 | ||
| 
						 | 
					9efeea14f2 | ||
| 
						 | 
					d2cd65f5db | ||
| 
						 | 
					2735f96516 | ||
| 
						 | 
					6847645782 | ||
| 
						 | 
					b0bc898278 | ||
| 
						 | 
					c0f6af7213 | ||
| 
						 | 
					5edebaf468 | ||
| 
						 | 
					d436409153 | ||
| 
						 | 
					8c41fc2b1d | ||
| 
						 | 
					46f17bea66 | ||
| 
						 | 
					11477dbc03 | ||
| 
						 | 
					947c104eff | ||
| 
						 | 
					e5366dbbe7 | ||
| 
						 | 
					d3375193a9 | ||
| 
						 | 
					6144ce1fe0 | ||
| 
						 | 
					1771e673d2 | ||
| 
						 | 
					d258e06fd7 | ||
| 
						 | 
					854f4a8896 | ||
| 
						 | 
					f94c221a9a | ||
| 
						 | 
					6a2f0f5143 | ||
| 
						 | 
					183e2a8471 | ||
| 
						 | 
					c6c2842bdb | ||
| 
						 | 
					f26767b65e | ||
| 
						 | 
					98d32876b5 | ||
| 
						 | 
					e5d0f3c036 | ||
| 
						 | 
					cc15aaacbb | ||
| 
						 | 
					553df1d57b | ||
| 
						 | 
					b92311402a | ||
| 
						 | 
					93796491af | ||
| 
						 | 
					c038cf27a7 | ||
| 
						 | 
					1f42d32eb5 | ||
| 
						 | 
					06bde559da | ||
| 
						 | 
					922f7167f5 | ||
| 
						 | 
					90c0d3e12f | ||
| 
						 | 
					bf5f846fc6 | ||
| 
						 | 
					926bcc71ae | ||
| 
						 | 
					ea4a458214 | ||
| 
						 | 
					b3ae3e1feb | ||
| 
						 | 
					fe7af21c91 | ||
| 
						 | 
					29f72037fe | ||
| 
						 | 
					1d6b4bfcef | ||
| 
						 | 
					5bfac5ec09 | ||
| 
						 | 
					dfffaace26 | ||
| 
						 | 
					1d5f628c7a | ||
| 
						 | 
					cb8a6f66fa | ||
| 
						 | 
					cb21c7c18d | ||
| 
						 | 
					0d104776bc | ||
| 
						 | 
					5f27757039 | ||
| 
						 | 
					532907219b | ||
| 
						 | 
					eeaba74553 | ||
| 
						 | 
					dd637582a4 | ||
| 
						 | 
					b0d12aeea1 | ||
| 
						 | 
					bdbd813455 | ||
| 
						 | 
					a6fac2b175 | ||
| 
						 | 
					5ce923ea90 | ||
| 
						 | 
					29f0508dc2 | ||
| 
						 | 
					3ffa59f0cd | ||
| 
						 | 
					790d6ef94c | ||
| 
						 | 
					7828f48b9a | ||
| 
						 | 
					768c71830b | ||
| 
						 | 
					ceb0564ebf | ||
| 
						 | 
					20f7eb7327 | ||
| 
						 | 
					441d5bd44d | ||
| 
						 | 
					9fa19df2ff | ||
| 
						 | 
					39f64f597e | ||
| 
						 | 
					160429eb24 | ||
| 
						 | 
					6516c64e67 | ||
| 
						 | 
					4c8a703084 | ||
| 
						 | 
					335210d788 | ||
| 
						 | 
					9b04e657db | ||
| 
						 | 
					f7311aa025 | ||
| 
						 | 
					fb24e55c8d | ||
| 
						 | 
					b58ca46a46 | ||
| 
						 | 
					76991cdcc4 | ||
| 
						 | 
					69c7cf783e | ||
| 
						 | 
					f751c3828e | ||
| 
						 | 
					5c65f9f9ad | ||
| 
						 | 
					81ae6709e4 | ||
| 
						 | 
					593a3d48fb | ||
| 
						 | 
					a8b90283d8 | ||
| 
						 | 
					80076f935d | ||
| 
						 | 
					9fbb3659a6 | ||
| 
						 | 
					fee446c28a | ||
| 
						 | 
					1d56f0b035 | ||
| 
						 | 
					34e8979d40 | ||
| 
						 | 
					2966a62429 | ||
| 
						 | 
					5983ccc55c | ||
| 
						 | 
					de382b704c | ||
| 
						 | 
					16dbbfabc6 | ||
| 
						 | 
					af8d04818d | ||
| 
						 | 
					ee19ef1aac | ||
| 
						 | 
					5e2d4e332a | ||
| 
						 | 
					c6c857dfff | ||
| 
						 | 
					8dbac20f8b | ||
| 
						 | 
					341fddb9aa | ||
| 
						 | 
					456824669f | ||
| 
						 | 
					62f3039d82 | ||
| 
						 | 
					be4c718859 | ||
| 
						 | 
					c2f9ed7c59 | ||
| 
						 | 
					bfac6607d1 | ||
| 
						 | 
					513066ba52 | ||
| 
						 | 
					316777f757 | ||
| 
						 | 
					246950159d | ||
| 
						 | 
					31d6a54b06 | ||
| 
						 | 
					5c3a6164bb | ||
| 
						 | 
					1652914d39 | ||
| 
						 | 
					618cfd9ec5 | ||
| 
						 | 
					f97cfe9916 | ||
| 
						 | 
					b9259a0238 | ||
| 
						 | 
					5abbe385c5 | ||
| 
						 | 
					b0a3891498 | ||
| 
						 | 
					2a9e3d84fd | ||
| 
						 | 
					a3dcac62f9 | ||
| 
						 | 
					6b535b11f8 | ||
| 
						 | 
					d9f09a7523 | ||
| 
						 | 
					159744e09e | ||
| 
						 | 
					c2637a76f7 | ||
| 
						 | 
					237edd75d1 | ||
| 
						 | 
					a34d5e3901 | ||
| 
						 | 
					1dd43a75f2 | ||
| 
						 | 
					1f5cbca509 | ||
| 
						 | 
					3749c11f21 | ||
| 
						 | 
					66cdb761dc | ||
| 
						 | 
					f0d9ad6a4e | ||
| 
						 | 
					03e317d052 | ||
| 
						 | 
					ba461e51a8 | ||
| 
						 | 
					80949521b6 | ||
| 
						 | 
					acbb8e9fd0 | ||
| 
						 | 
					90394a50df | ||
| 
						 | 
					5379794f16 | ||
| 
						 | 
					0a32321c85 | ||
| 
						 | 
					c9062599df | ||
| 
						 | 
					fc42f14448 | ||
| 
						 | 
					3e65e6c69a | ||
| 
						 | 
					3b3297d269 | ||
| 
						 | 
					fc0deb642a | ||
| 
						 | 
					9f2b2f51ff | ||
| 
						 | 
					01a4b4e82f | ||
| 
						 | 
					766866197b | ||
| 
						 | 
					9b5a3cbcd3 | ||
| 
						 | 
					d2ed3b9bec | ||
| 
						 | 
					99d2db42cd | ||
| 
						 | 
					7619507e6c | ||
| 
						 | 
					71d9d64a02 | ||
| 
						 | 
					2e49fd7b48 | ||
| 
						 | 
					06912b492f | ||
| 
						 | 
					442e58b07a | ||
| 
						 | 
					799f04efc0 | ||
| 
						 | 
					cc7dbeada6 | ||
| 
						 | 
					45d368e3a1 | ||
| 
						 | 
					628a94bad3 | ||
| 
						 | 
					0651716b96 | ||
| 
						 | 
					0992609bf4 | 
@@ -14,7 +14,12 @@ Checks: >-
 | 
			
		||||
  -cert-str34-c,
 | 
			
		||||
  -clang-analyzer-optin.cplusplus.UninitializedObject,
 | 
			
		||||
  -clang-analyzer-osx.*,
 | 
			
		||||
  -clang-diagnostic-delete-abstract-non-virtual-dtor,
 | 
			
		||||
  -clang-diagnostic-delete-non-abstract-non-virtual-dtor,
 | 
			
		||||
  -clang-diagnostic-shadow-field,
 | 
			
		||||
  -clang-diagnostic-sign-compare,
 | 
			
		||||
  -clang-diagnostic-unused-variable,
 | 
			
		||||
  -clang-diagnostic-unused-const-variable,
 | 
			
		||||
  -cppcoreguidelines-avoid-c-arrays,
 | 
			
		||||
  -cppcoreguidelines-avoid-goto,
 | 
			
		||||
  -cppcoreguidelines-avoid-magic-numbers,
 | 
			
		||||
@@ -80,7 +85,6 @@ Checks: >-
 | 
			
		||||
  -readability-use-anyofallof,
 | 
			
		||||
  -warnings-as-errors
 | 
			
		||||
WarningsAsErrors: '*'
 | 
			
		||||
HeaderFilterRegex: '^.*/src/esphome/.*'
 | 
			
		||||
AnalyzeTemporaryDtors: false
 | 
			
		||||
FormatStyle:     google
 | 
			
		||||
CheckOptions:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							@@ -36,26 +36,27 @@ jobs:
 | 
			
		||||
    container: ghcr.io/esphome/esphome-lint:1.1
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v2
 | 
			
		||||
      # Set up the pio project so that the cpp checks know how files are compiled
 | 
			
		||||
      # (build flags, libraries etc)
 | 
			
		||||
      - name: Set up platformio environment
 | 
			
		||||
        run: pio init --ide atom
 | 
			
		||||
 | 
			
		||||
      - name: Register problem matchers
 | 
			
		||||
        run: |
 | 
			
		||||
          echo "::add-matcher::.github/workflows/matchers/clang-tidy.json"
 | 
			
		||||
          echo "::add-matcher::.github/workflows/matchers/gcc.json"
 | 
			
		||||
 | 
			
		||||
      # Also run git-diff-index so that the step is marked as failed on formatting errors,
 | 
			
		||||
      # since clang-format doesn't do anything but change files if -i is passed.
 | 
			
		||||
      - name: Run clang-format
 | 
			
		||||
        run: script/clang-format -i
 | 
			
		||||
        run: |
 | 
			
		||||
          script/clang-format -i
 | 
			
		||||
          git diff-index --quiet HEAD --
 | 
			
		||||
        if: ${{ matrix.id == 'clang-format' }}
 | 
			
		||||
 | 
			
		||||
      - name: Run clang-tidy
 | 
			
		||||
        run: script/clang-tidy --all-headers --fix --split-num 4 --split-at ${{ matrix.split }}
 | 
			
		||||
        if: ${{ matrix.id == 'clang-tidy' }}
 | 
			
		||||
 | 
			
		||||
      - name: Suggest changes
 | 
			
		||||
      - name: Suggested changes
 | 
			
		||||
        run: script/ci-suggest-changes
 | 
			
		||||
        if: always()
 | 
			
		||||
 | 
			
		||||
  ci:
 | 
			
		||||
    # Don't use the esphome-lint docker image because it may contain outdated requirements.
 | 
			
		||||
@@ -82,6 +83,9 @@ jobs:
 | 
			
		||||
          - id: test
 | 
			
		||||
            file: tests/test4.yaml
 | 
			
		||||
            name: Test tests/test4.yaml
 | 
			
		||||
          - id: test
 | 
			
		||||
            file: tests/test5.yaml
 | 
			
		||||
            name: Test tests/test5.yaml
 | 
			
		||||
          - id: pytest
 | 
			
		||||
            name: Run pytest
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -125,4 +125,5 @@ config/
 | 
			
		||||
tests/build/
 | 
			
		||||
tests/.esphome/
 | 
			
		||||
/.temp-clang-tidy.cpp
 | 
			
		||||
/.temp/
 | 
			
		||||
.pio/
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								.vscode/tasks.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.vscode/tasks.json
									
									
									
									
										vendored
									
									
								
							@@ -10,7 +10,7 @@
 | 
			
		||||
    {
 | 
			
		||||
      "label": "clang-tidy",
 | 
			
		||||
      "type": "shell",
 | 
			
		||||
      "command": "test -f .gcc-flags.json || pio init --silent --ide atom; ./script/clang-tidy",
 | 
			
		||||
      "command": "./script/clang-tidy",
 | 
			
		||||
      "problemMatcher": [
 | 
			
		||||
        {
 | 
			
		||||
          "owner": "clang-tidy",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										18
									
								
								CODEOWNERS
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								CODEOWNERS
									
									
									
									
									
								
							@@ -14,6 +14,8 @@ esphome/core/* @esphome/core
 | 
			
		||||
esphome/components/ac_dimmer/* @glmnet
 | 
			
		||||
esphome/components/adc/* @esphome/core
 | 
			
		||||
esphome/components/addressable_light/* @justfalter
 | 
			
		||||
esphome/components/am43/* @buxtronix
 | 
			
		||||
esphome/components/am43/cover/* @buxtronix
 | 
			
		||||
esphome/components/animation/* @syndlex
 | 
			
		||||
esphome/components/anova/* @buxtronix
 | 
			
		||||
esphome/components/api/* @OttoWinter
 | 
			
		||||
@@ -29,6 +31,7 @@ esphome/components/canbus/* @danielschramm @mvturnho
 | 
			
		||||
esphome/components/captive_portal/* @OttoWinter
 | 
			
		||||
esphome/components/climate/* @esphome/core
 | 
			
		||||
esphome/components/climate_ir/* @glmnet
 | 
			
		||||
esphome/components/color_temperature/* @jesserockz
 | 
			
		||||
esphome/components/coolix/* @glmnet
 | 
			
		||||
esphome/components/cover/* @esphome/core
 | 
			
		||||
esphome/components/cs5460a/* @balrog-kun
 | 
			
		||||
@@ -37,6 +40,7 @@ esphome/components/debug/* @OttoWinter
 | 
			
		||||
esphome/components/dfplayer/* @glmnet
 | 
			
		||||
esphome/components/dht/* @OttoWinter
 | 
			
		||||
esphome/components/ds1307/* @badbadc0ffee
 | 
			
		||||
esphome/components/dsmr/* @glmnet @zuidwijk
 | 
			
		||||
esphome/components/esp32_ble/* @jesserockz
 | 
			
		||||
esphome/components/esp32_ble_server/* @jesserockz
 | 
			
		||||
esphome/components/esp32_improv/* @jesserockz
 | 
			
		||||
@@ -48,7 +52,9 @@ esphome/components/globals/* @esphome/core
 | 
			
		||||
esphome/components/gpio/* @esphome/core
 | 
			
		||||
esphome/components/gps/* @coogle
 | 
			
		||||
esphome/components/havells_solar/* @sourabhjaiswal
 | 
			
		||||
esphome/components/hitachi_ac424/* @sourabhjaiswal
 | 
			
		||||
esphome/components/homeassistant/* @OttoWinter
 | 
			
		||||
esphome/components/hrxl_maxsonar_wr/* @netmikey
 | 
			
		||||
esphome/components/i2c/* @esphome/core
 | 
			
		||||
esphome/components/improv/* @jesserockz
 | 
			
		||||
esphome/components/inkbird_ibsth1_mini/* @fkirill
 | 
			
		||||
@@ -83,19 +89,26 @@ esphome/components/number/* @esphome/core
 | 
			
		||||
esphome/components/ota/* @esphome/core
 | 
			
		||||
esphome/components/output/* @esphome/core
 | 
			
		||||
esphome/components/pid/* @OttoWinter
 | 
			
		||||
esphome/components/pipsolar/* @andreashergert1984
 | 
			
		||||
esphome/components/pmsa003i/* @sjtrny
 | 
			
		||||
esphome/components/pn532/* @OttoWinter @jesserockz
 | 
			
		||||
esphome/components/pn532_i2c/* @OttoWinter @jesserockz
 | 
			
		||||
esphome/components/pn532_spi/* @OttoWinter @jesserockz
 | 
			
		||||
esphome/components/power_supply/* @esphome/core
 | 
			
		||||
esphome/components/pulse_meter/* @stevebaxter
 | 
			
		||||
esphome/components/pvvx_mithermometer/* @pasiz
 | 
			
		||||
esphome/components/rc522/* @glmnet
 | 
			
		||||
esphome/components/rc522_i2c/* @glmnet
 | 
			
		||||
esphome/components/rc522_spi/* @glmnet
 | 
			
		||||
esphome/components/restart/* @esphome/core
 | 
			
		||||
esphome/components/rf_bridge/* @jesserockz
 | 
			
		||||
esphome/components/rgbct/* @jesserockz
 | 
			
		||||
esphome/components/rtttl/* @glmnet
 | 
			
		||||
esphome/components/script/* @esphome/core
 | 
			
		||||
esphome/components/sdm_meter/* @jesserockz @polyfaces
 | 
			
		||||
esphome/components/sdp3x/* @Azimath
 | 
			
		||||
esphome/components/selec_meter/* @sourabhjaiswal
 | 
			
		||||
esphome/components/select/* @esphome/core
 | 
			
		||||
esphome/components/sensor/* @esphome/core
 | 
			
		||||
esphome/components/sgp40/* @SenexCrenshaw
 | 
			
		||||
esphome/components/sht4x/* @sjtrny
 | 
			
		||||
@@ -119,14 +132,19 @@ esphome/components/st7789v/* @kbx81
 | 
			
		||||
esphome/components/substitutions/* @esphome/core
 | 
			
		||||
esphome/components/sun/* @OttoWinter
 | 
			
		||||
esphome/components/switch/* @esphome/core
 | 
			
		||||
esphome/components/t6615/* @tylermenezes
 | 
			
		||||
esphome/components/tca9548a/* @andreashergert1984
 | 
			
		||||
esphome/components/tcl112/* @glmnet
 | 
			
		||||
esphome/components/teleinfo/* @0hax
 | 
			
		||||
esphome/components/thermostat/* @kbx81
 | 
			
		||||
esphome/components/time/* @OttoWinter
 | 
			
		||||
esphome/components/tlc5947/* @rnauber
 | 
			
		||||
esphome/components/tm1637/* @glmnet
 | 
			
		||||
esphome/components/tmp102/* @timsavage
 | 
			
		||||
esphome/components/tmp117/* @Azimath
 | 
			
		||||
esphome/components/tof10120/* @wstrzalka
 | 
			
		||||
esphome/components/toshiba/* @kbx81
 | 
			
		||||
esphome/components/tsl2591/* @wjcarpenter
 | 
			
		||||
esphome/components/tuya/binary_sensor/* @jesserockz
 | 
			
		||||
esphome/components/tuya/climate/* @jesserockz
 | 
			
		||||
esphome/components/tuya/sensor/* @jesserockz
 | 
			
		||||
 
 | 
			
		||||
@@ -1,23 +0,0 @@
 | 
			
		||||
#!/usr/bin/with-contenv bashio
 | 
			
		||||
# ==============================================================================
 | 
			
		||||
# Community Hass.io Add-ons: ESPHome
 | 
			
		||||
# This files installs the user ESPHome version if specified
 | 
			
		||||
# ==============================================================================
 | 
			
		||||
 | 
			
		||||
declare esphome_version
 | 
			
		||||
 | 
			
		||||
if bashio::config.has_value 'esphome_version'; then
 | 
			
		||||
    esphome_version=$(bashio::config 'esphome_version')
 | 
			
		||||
    if [[ $esphome_version == *":"* ]]; then
 | 
			
		||||
      IFS=':' read -r -a array <<< "$esphome_version"
 | 
			
		||||
      username=${array[0]}
 | 
			
		||||
      ref=${array[1]}
 | 
			
		||||
    else
 | 
			
		||||
      username="esphome"
 | 
			
		||||
      ref=$esphome_version
 | 
			
		||||
    fi
 | 
			
		||||
    full_url="https://github.com/${username}/esphome/archive/${ref}.zip"
 | 
			
		||||
    bashio::log.info "Installing esphome version '${esphome_version}' (${full_url})..."
 | 
			
		||||
    pip3 install -U --no-cache-dir "${full_url}" \
 | 
			
		||||
      || bashio::exit.nok "Failed installing esphome pinned version."
 | 
			
		||||
fi
 | 
			
		||||
@@ -1,11 +0,0 @@
 | 
			
		||||
#!/usr/bin/with-contenv bashio
 | 
			
		||||
# ==============================================================================
 | 
			
		||||
# Community Hass.io Add-ons: ESPHome
 | 
			
		||||
# This files migrates the esphome config directory from the old path
 | 
			
		||||
# ==============================================================================
 | 
			
		||||
 | 
			
		||||
if [[ ! -d /config/esphome && -d /config/esphomeyaml ]]; then
 | 
			
		||||
    echo "Moving config directory from /config/esphomeyaml to /config/esphome"
 | 
			
		||||
    mv /config/esphomeyaml /config/esphome
 | 
			
		||||
    mv /config/esphome/.esphomeyaml /config/esphome/.esphome
 | 
			
		||||
fi
 | 
			
		||||
@@ -11,6 +11,7 @@ from esphome.config import iter_components, read_config, strip_default_ids
 | 
			
		||||
from esphome.const import (
 | 
			
		||||
    CONF_BAUD_RATE,
 | 
			
		||||
    CONF_BROKER,
 | 
			
		||||
    CONF_DEASSERT_RTS_DTR,
 | 
			
		||||
    CONF_LOGGER,
 | 
			
		||||
    CONF_OTA,
 | 
			
		||||
    CONF_PASSWORD,
 | 
			
		||||
@@ -99,10 +100,21 @@ def run_miniterm(config, port):
 | 
			
		||||
    baud_rate = config["logger"][CONF_BAUD_RATE]
 | 
			
		||||
    if baud_rate == 0:
 | 
			
		||||
        _LOGGER.info("UART logging is disabled (baud_rate=0). Not starting UART logs.")
 | 
			
		||||
        return
 | 
			
		||||
    _LOGGER.info("Starting log output from %s with baud rate %s", port, baud_rate)
 | 
			
		||||
 | 
			
		||||
    backtrace_state = False
 | 
			
		||||
    with serial.Serial(port, baudrate=baud_rate) as ser:
 | 
			
		||||
    ser = serial.Serial()
 | 
			
		||||
    ser.baudrate = baud_rate
 | 
			
		||||
    ser.port = port
 | 
			
		||||
 | 
			
		||||
    # We can't set to False by default since it leads to toggling and hence
 | 
			
		||||
    # ESP32 resets on some platforms.
 | 
			
		||||
    if config["logger"][CONF_DEASSERT_RTS_DTR]:
 | 
			
		||||
        ser.dtr = False
 | 
			
		||||
        ser.rts = False
 | 
			
		||||
 | 
			
		||||
    with ser:
 | 
			
		||||
        while True:
 | 
			
		||||
            try:
 | 
			
		||||
                raw = ser.readline()
 | 
			
		||||
@@ -284,7 +296,6 @@ def command_vscode(args):
 | 
			
		||||
 | 
			
		||||
    logging.disable(logging.INFO)
 | 
			
		||||
    logging.disable(logging.WARNING)
 | 
			
		||||
    CORE.config_path = args.configuration
 | 
			
		||||
    vscode.read_config(args)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -394,7 +405,7 @@ def command_update_all(args):
 | 
			
		||||
    import click
 | 
			
		||||
 | 
			
		||||
    success = {}
 | 
			
		||||
    files = list_yaml_files(args.configuration[0])
 | 
			
		||||
    files = list_yaml_files(args.configuration)
 | 
			
		||||
    twidth = 60
 | 
			
		||||
 | 
			
		||||
    def print_bar(middle_text):
 | 
			
		||||
@@ -408,7 +419,7 @@ def command_update_all(args):
 | 
			
		||||
        print("-" * twidth)
 | 
			
		||||
        print()
 | 
			
		||||
        rc = run_external_process(
 | 
			
		||||
            "esphome", "--dashboard", "run", "--no-logs", "--device", "OTA", f
 | 
			
		||||
            "esphome", "--dashboard", "run", f, "--no-logs", "--device", "OTA"
 | 
			
		||||
        )
 | 
			
		||||
        if rc == 0:
 | 
			
		||||
            print_bar("[{}] {}".format(color(Fore.BOLD_GREEN, "SUCCESS"), f))
 | 
			
		||||
@@ -505,6 +516,7 @@ def parse_args(argv):
 | 
			
		||||
            "clean",
 | 
			
		||||
            "dashboard",
 | 
			
		||||
            "vscode",
 | 
			
		||||
            "update-all",
 | 
			
		||||
        ],
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
@@ -681,14 +693,12 @@ def parse_args(argv):
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    parser_vscode = subparsers.add_parser("vscode")
 | 
			
		||||
    parser_vscode.add_argument(
 | 
			
		||||
        "configuration", help="Your YAML configuration file.", nargs=1
 | 
			
		||||
    )
 | 
			
		||||
    parser_vscode.add_argument("configuration", help="Your YAML configuration file.")
 | 
			
		||||
    parser_vscode.add_argument("--ace", action="store_true")
 | 
			
		||||
 | 
			
		||||
    parser_update = subparsers.add_parser("update-all")
 | 
			
		||||
    parser_update.add_argument(
 | 
			
		||||
        "configuration", help="Your YAML configuration file directory.", nargs=1
 | 
			
		||||
        "configuration", help="Your YAML configuration file directories.", nargs="+"
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    return parser.parse_args(argv[1:])
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										875
									
								
								esphome/boards.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										875
									
								
								esphome/boards.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,875 @@
 | 
			
		||||
ESP8266_BASE_PINS = {
 | 
			
		||||
    "A0": 17,
 | 
			
		||||
    "SS": 15,
 | 
			
		||||
    "MOSI": 13,
 | 
			
		||||
    "MISO": 12,
 | 
			
		||||
    "SCK": 14,
 | 
			
		||||
    "SDA": 4,
 | 
			
		||||
    "SCL": 5,
 | 
			
		||||
    "RX": 3,
 | 
			
		||||
    "TX": 1,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ESP8266_BOARD_PINS = {
 | 
			
		||||
    "d1": {
 | 
			
		||||
        "D0": 3,
 | 
			
		||||
        "D1": 1,
 | 
			
		||||
        "D2": 16,
 | 
			
		||||
        "D3": 5,
 | 
			
		||||
        "D4": 4,
 | 
			
		||||
        "D5": 14,
 | 
			
		||||
        "D6": 12,
 | 
			
		||||
        "D7": 13,
 | 
			
		||||
        "D8": 0,
 | 
			
		||||
        "D9": 2,
 | 
			
		||||
        "D10": 15,
 | 
			
		||||
        "D11": 13,
 | 
			
		||||
        "D12": 14,
 | 
			
		||||
        "D13": 14,
 | 
			
		||||
        "D14": 4,
 | 
			
		||||
        "D15": 5,
 | 
			
		||||
        "LED": 2,
 | 
			
		||||
    },
 | 
			
		||||
    "d1_mini": {
 | 
			
		||||
        "D0": 16,
 | 
			
		||||
        "D1": 5,
 | 
			
		||||
        "D2": 4,
 | 
			
		||||
        "D3": 0,
 | 
			
		||||
        "D4": 2,
 | 
			
		||||
        "D5": 14,
 | 
			
		||||
        "D6": 12,
 | 
			
		||||
        "D7": 13,
 | 
			
		||||
        "D8": 15,
 | 
			
		||||
        "LED": 2,
 | 
			
		||||
    },
 | 
			
		||||
    "d1_mini_lite": "d1_mini",
 | 
			
		||||
    "d1_mini_pro": "d1_mini",
 | 
			
		||||
    "esp01": {},
 | 
			
		||||
    "esp01_1m": {},
 | 
			
		||||
    "esp07": {},
 | 
			
		||||
    "esp12e": {},
 | 
			
		||||
    "esp210": {},
 | 
			
		||||
    "esp8285": {},
 | 
			
		||||
    "esp_wroom_02": {},
 | 
			
		||||
    "espduino": {"LED": 16},
 | 
			
		||||
    "espectro": {"LED": 15, "BUTTON": 2},
 | 
			
		||||
    "espino": {"LED": 2, "LED_RED": 2, "LED_GREEN": 4, "LED_BLUE": 5, "BUTTON": 0},
 | 
			
		||||
    "espinotee": {"LED": 16},
 | 
			
		||||
    "espresso_lite_v1": {"LED": 16},
 | 
			
		||||
    "espresso_lite_v2": {"LED": 2},
 | 
			
		||||
    "gen4iod": {},
 | 
			
		||||
    "heltec_wifi_kit_8": "d1_mini",
 | 
			
		||||
    "huzzah": {
 | 
			
		||||
        "LED": 0,
 | 
			
		||||
        "LED_RED": 0,
 | 
			
		||||
        "LED_BLUE": 2,
 | 
			
		||||
        "D4": 4,
 | 
			
		||||
        "D5": 5,
 | 
			
		||||
        "D12": 12,
 | 
			
		||||
        "D13": 13,
 | 
			
		||||
        "D14": 14,
 | 
			
		||||
        "D15": 15,
 | 
			
		||||
        "D16": 16,
 | 
			
		||||
    },
 | 
			
		||||
    "inventone": {},
 | 
			
		||||
    "modwifi": {},
 | 
			
		||||
    "nodemcu": {
 | 
			
		||||
        "D0": 16,
 | 
			
		||||
        "D1": 5,
 | 
			
		||||
        "D2": 4,
 | 
			
		||||
        "D3": 0,
 | 
			
		||||
        "D4": 2,
 | 
			
		||||
        "D5": 14,
 | 
			
		||||
        "D6": 12,
 | 
			
		||||
        "D7": 13,
 | 
			
		||||
        "D8": 15,
 | 
			
		||||
        "D9": 3,
 | 
			
		||||
        "D10": 1,
 | 
			
		||||
        "LED": 16,
 | 
			
		||||
    },
 | 
			
		||||
    "nodemcuv2": "nodemcu",
 | 
			
		||||
    "oak": {
 | 
			
		||||
        "P0": 2,
 | 
			
		||||
        "P1": 5,
 | 
			
		||||
        "P2": 0,
 | 
			
		||||
        "P3": 3,
 | 
			
		||||
        "P4": 1,
 | 
			
		||||
        "P5": 4,
 | 
			
		||||
        "P6": 15,
 | 
			
		||||
        "P7": 13,
 | 
			
		||||
        "P8": 12,
 | 
			
		||||
        "P9": 14,
 | 
			
		||||
        "P10": 16,
 | 
			
		||||
        "P11": 17,
 | 
			
		||||
        "LED": 5,
 | 
			
		||||
    },
 | 
			
		||||
    "phoenix_v1": {"LED": 16},
 | 
			
		||||
    "phoenix_v2": {"LED": 2},
 | 
			
		||||
    "sparkfunBlynk": "thing",
 | 
			
		||||
    "thing": {"LED": 5, "SDA": 2, "SCL": 14},
 | 
			
		||||
    "thingdev": "thing",
 | 
			
		||||
    "wifi_slot": {"LED": 2},
 | 
			
		||||
    "wifiduino": {
 | 
			
		||||
        "D0": 3,
 | 
			
		||||
        "D1": 1,
 | 
			
		||||
        "D2": 2,
 | 
			
		||||
        "D3": 0,
 | 
			
		||||
        "D4": 4,
 | 
			
		||||
        "D5": 5,
 | 
			
		||||
        "D6": 16,
 | 
			
		||||
        "D7": 14,
 | 
			
		||||
        "D8": 12,
 | 
			
		||||
        "D9": 13,
 | 
			
		||||
        "D10": 15,
 | 
			
		||||
        "D11": 13,
 | 
			
		||||
        "D12": 12,
 | 
			
		||||
        "D13": 14,
 | 
			
		||||
    },
 | 
			
		||||
    "wifinfo": {
 | 
			
		||||
        "LED": 12,
 | 
			
		||||
        "D0": 16,
 | 
			
		||||
        "D1": 5,
 | 
			
		||||
        "D2": 4,
 | 
			
		||||
        "D3": 0,
 | 
			
		||||
        "D4": 2,
 | 
			
		||||
        "D5": 14,
 | 
			
		||||
        "D6": 12,
 | 
			
		||||
        "D7": 13,
 | 
			
		||||
        "D8": 15,
 | 
			
		||||
        "D9": 3,
 | 
			
		||||
        "D10": 1,
 | 
			
		||||
    },
 | 
			
		||||
    "wio_link": {"LED": 2, "GROVE": 15, "D0": 14, "D1": 12, "D2": 13, "BUTTON": 0},
 | 
			
		||||
    "wio_node": {"LED": 2, "GROVE": 15, "D0": 3, "D1": 5, "BUTTON": 0},
 | 
			
		||||
    "xinabox_cw01": {"SDA": 2, "SCL": 14, "LED": 5, "LED_RED": 12, "LED_GREEN": 13},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FLASH_SIZE_1_MB = 2 ** 20
 | 
			
		||||
FLASH_SIZE_512_KB = FLASH_SIZE_1_MB // 2
 | 
			
		||||
FLASH_SIZE_2_MB = 2 * FLASH_SIZE_1_MB
 | 
			
		||||
FLASH_SIZE_4_MB = 4 * FLASH_SIZE_1_MB
 | 
			
		||||
FLASH_SIZE_16_MB = 16 * FLASH_SIZE_1_MB
 | 
			
		||||
 | 
			
		||||
ESP8266_FLASH_SIZES = {
 | 
			
		||||
    "d1": FLASH_SIZE_4_MB,
 | 
			
		||||
    "d1_mini": FLASH_SIZE_4_MB,
 | 
			
		||||
    "d1_mini_lite": FLASH_SIZE_1_MB,
 | 
			
		||||
    "d1_mini_pro": FLASH_SIZE_16_MB,
 | 
			
		||||
    "esp01": FLASH_SIZE_512_KB,
 | 
			
		||||
    "esp01_1m": FLASH_SIZE_1_MB,
 | 
			
		||||
    "esp07": FLASH_SIZE_4_MB,
 | 
			
		||||
    "esp12e": FLASH_SIZE_4_MB,
 | 
			
		||||
    "esp210": FLASH_SIZE_4_MB,
 | 
			
		||||
    "esp8285": FLASH_SIZE_1_MB,
 | 
			
		||||
    "esp_wroom_02": FLASH_SIZE_2_MB,
 | 
			
		||||
    "espduino": FLASH_SIZE_4_MB,
 | 
			
		||||
    "espectro": FLASH_SIZE_4_MB,
 | 
			
		||||
    "espino": FLASH_SIZE_4_MB,
 | 
			
		||||
    "espinotee": FLASH_SIZE_4_MB,
 | 
			
		||||
    "espresso_lite_v1": FLASH_SIZE_4_MB,
 | 
			
		||||
    "espresso_lite_v2": FLASH_SIZE_4_MB,
 | 
			
		||||
    "gen4iod": FLASH_SIZE_512_KB,
 | 
			
		||||
    "heltec_wifi_kit_8": FLASH_SIZE_4_MB,
 | 
			
		||||
    "huzzah": FLASH_SIZE_4_MB,
 | 
			
		||||
    "inventone": FLASH_SIZE_4_MB,
 | 
			
		||||
    "modwifi": FLASH_SIZE_2_MB,
 | 
			
		||||
    "nodemcu": FLASH_SIZE_4_MB,
 | 
			
		||||
    "nodemcuv2": FLASH_SIZE_4_MB,
 | 
			
		||||
    "oak": FLASH_SIZE_4_MB,
 | 
			
		||||
    "phoenix_v1": FLASH_SIZE_4_MB,
 | 
			
		||||
    "phoenix_v2": FLASH_SIZE_4_MB,
 | 
			
		||||
    "sparkfunBlynk": FLASH_SIZE_4_MB,
 | 
			
		||||
    "thing": FLASH_SIZE_512_KB,
 | 
			
		||||
    "thingdev": FLASH_SIZE_512_KB,
 | 
			
		||||
    "wifi_slot": FLASH_SIZE_1_MB,
 | 
			
		||||
    "wifiduino": FLASH_SIZE_4_MB,
 | 
			
		||||
    "wifinfo": FLASH_SIZE_1_MB,
 | 
			
		||||
    "wio_link": FLASH_SIZE_4_MB,
 | 
			
		||||
    "wio_node": FLASH_SIZE_4_MB,
 | 
			
		||||
    "xinabox_cw01": FLASH_SIZE_4_MB,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ESP8266_LD_SCRIPTS = {
 | 
			
		||||
    FLASH_SIZE_512_KB: ("eagle.flash.512k0.ld", "eagle.flash.512k.ld"),
 | 
			
		||||
    FLASH_SIZE_1_MB: ("eagle.flash.1m0.ld", "eagle.flash.1m.ld"),
 | 
			
		||||
    FLASH_SIZE_2_MB: ("eagle.flash.2m.ld", "eagle.flash.2m.ld"),
 | 
			
		||||
    FLASH_SIZE_4_MB: ("eagle.flash.4m.ld", "eagle.flash.4m.ld"),
 | 
			
		||||
    FLASH_SIZE_16_MB: ("eagle.flash.16m.ld", "eagle.flash.16m14m.ld"),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ESP32_BASE_PINS = {
 | 
			
		||||
    "TX": 1,
 | 
			
		||||
    "RX": 3,
 | 
			
		||||
    "SDA": 21,
 | 
			
		||||
    "SCL": 22,
 | 
			
		||||
    "SS": 5,
 | 
			
		||||
    "MOSI": 23,
 | 
			
		||||
    "MISO": 19,
 | 
			
		||||
    "SCK": 18,
 | 
			
		||||
    "A0": 36,
 | 
			
		||||
    "A3": 39,
 | 
			
		||||
    "A4": 32,
 | 
			
		||||
    "A5": 33,
 | 
			
		||||
    "A6": 34,
 | 
			
		||||
    "A7": 35,
 | 
			
		||||
    "A10": 4,
 | 
			
		||||
    "A11": 0,
 | 
			
		||||
    "A12": 2,
 | 
			
		||||
    "A13": 15,
 | 
			
		||||
    "A14": 13,
 | 
			
		||||
    "A15": 12,
 | 
			
		||||
    "A16": 14,
 | 
			
		||||
    "A17": 27,
 | 
			
		||||
    "A18": 25,
 | 
			
		||||
    "A19": 26,
 | 
			
		||||
    "T0": 4,
 | 
			
		||||
    "T1": 0,
 | 
			
		||||
    "T2": 2,
 | 
			
		||||
    "T3": 15,
 | 
			
		||||
    "T4": 13,
 | 
			
		||||
    "T5": 12,
 | 
			
		||||
    "T6": 14,
 | 
			
		||||
    "T7": 27,
 | 
			
		||||
    "T8": 33,
 | 
			
		||||
    "T9": 32,
 | 
			
		||||
    "DAC1": 25,
 | 
			
		||||
    "DAC2": 26,
 | 
			
		||||
    "SVP": 36,
 | 
			
		||||
    "SVN": 39,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ESP32_BOARD_PINS = {
 | 
			
		||||
    "alksesp32": {
 | 
			
		||||
        "A0": 32,
 | 
			
		||||
        "A1": 33,
 | 
			
		||||
        "A2": 25,
 | 
			
		||||
        "A3": 26,
 | 
			
		||||
        "A4": 27,
 | 
			
		||||
        "A5": 14,
 | 
			
		||||
        "A6": 12,
 | 
			
		||||
        "A7": 15,
 | 
			
		||||
        "D0": 40,
 | 
			
		||||
        "D1": 41,
 | 
			
		||||
        "D10": 19,
 | 
			
		||||
        "D11": 21,
 | 
			
		||||
        "D12": 22,
 | 
			
		||||
        "D13": 23,
 | 
			
		||||
        "D2": 15,
 | 
			
		||||
        "D3": 2,
 | 
			
		||||
        "D4": 0,
 | 
			
		||||
        "D5": 4,
 | 
			
		||||
        "D6": 16,
 | 
			
		||||
        "D7": 17,
 | 
			
		||||
        "D8": 5,
 | 
			
		||||
        "D9": 18,
 | 
			
		||||
        "DHT_PIN": 26,
 | 
			
		||||
        "LED": 23,
 | 
			
		||||
        "L_B": 5,
 | 
			
		||||
        "L_G": 17,
 | 
			
		||||
        "L_R": 22,
 | 
			
		||||
        "L_RGB_B": 16,
 | 
			
		||||
        "L_RGB_G": 21,
 | 
			
		||||
        "L_RGB_R": 4,
 | 
			
		||||
        "L_Y": 23,
 | 
			
		||||
        "MISO": 22,
 | 
			
		||||
        "MOSI": 21,
 | 
			
		||||
        "PHOTO": 25,
 | 
			
		||||
        "PIEZO1": 19,
 | 
			
		||||
        "PIEZO2": 18,
 | 
			
		||||
        "POT1": 32,
 | 
			
		||||
        "POT2": 33,
 | 
			
		||||
        "S1": 4,
 | 
			
		||||
        "S2": 16,
 | 
			
		||||
        "S3": 18,
 | 
			
		||||
        "S4": 19,
 | 
			
		||||
        "S5": 21,
 | 
			
		||||
        "SCK": 23,
 | 
			
		||||
        "SCL": 14,
 | 
			
		||||
        "SDA": 27,
 | 
			
		||||
        "SS": 19,
 | 
			
		||||
        "SW1": 15,
 | 
			
		||||
        "SW2": 2,
 | 
			
		||||
        "SW3": 0,
 | 
			
		||||
    },
 | 
			
		||||
    "bpi-bit": {
 | 
			
		||||
        "BUTTON_A": 35,
 | 
			
		||||
        "BUTTON_B": 27,
 | 
			
		||||
        "BUZZER": 25,
 | 
			
		||||
        "LIGHT_SENSOR1": 36,
 | 
			
		||||
        "LIGHT_SENSOR2": 39,
 | 
			
		||||
        "MPU9250_INT": 0,
 | 
			
		||||
        "P0": 25,
 | 
			
		||||
        "P1": 32,
 | 
			
		||||
        "P10": 26,
 | 
			
		||||
        "P11": 27,
 | 
			
		||||
        "P12": 2,
 | 
			
		||||
        "P13": 18,
 | 
			
		||||
        "P14": 19,
 | 
			
		||||
        "P15": 23,
 | 
			
		||||
        "P16": 5,
 | 
			
		||||
        "P19": 22,
 | 
			
		||||
        "P2": 33,
 | 
			
		||||
        "P20": 21,
 | 
			
		||||
        "P3": 13,
 | 
			
		||||
        "P4": 15,
 | 
			
		||||
        "P5": 35,
 | 
			
		||||
        "P6": 12,
 | 
			
		||||
        "P7": 14,
 | 
			
		||||
        "P8": 16,
 | 
			
		||||
        "P9": 17,
 | 
			
		||||
        "RGB_LED": 4,
 | 
			
		||||
        "TEMPERATURE_SENSOR": 34,
 | 
			
		||||
    },
 | 
			
		||||
    "d-duino-32": {
 | 
			
		||||
        "D1": 5,
 | 
			
		||||
        "D10": 1,
 | 
			
		||||
        "D2": 4,
 | 
			
		||||
        "D3": 0,
 | 
			
		||||
        "D4": 2,
 | 
			
		||||
        "D5": 14,
 | 
			
		||||
        "D6": 12,
 | 
			
		||||
        "D7": 13,
 | 
			
		||||
        "D8": 15,
 | 
			
		||||
        "D9": 3,
 | 
			
		||||
        "MISO": 12,
 | 
			
		||||
        "MOSI": 13,
 | 
			
		||||
        "SCK": 14,
 | 
			
		||||
        "SCL": 4,
 | 
			
		||||
        "SDA": 5,
 | 
			
		||||
        "SS": 15,
 | 
			
		||||
    },
 | 
			
		||||
    "esp-wrover-kit": {},
 | 
			
		||||
    "esp32-devkitlipo": {},
 | 
			
		||||
    "esp32-evb": {
 | 
			
		||||
        "BUTTON": 34,
 | 
			
		||||
        "MISO": 15,
 | 
			
		||||
        "MOSI": 2,
 | 
			
		||||
        "SCK": 14,
 | 
			
		||||
        "SCL": 16,
 | 
			
		||||
        "SDA": 13,
 | 
			
		||||
        "SS": 17,
 | 
			
		||||
    },
 | 
			
		||||
    "esp32-gateway": {"BUTTON": 34, "LED": 33, "SCL": 16, "SDA": 32},
 | 
			
		||||
    "esp32-poe-iso": {
 | 
			
		||||
        "BUTTON": 34,
 | 
			
		||||
        "MISO": 15,
 | 
			
		||||
        "MOSI": 2,
 | 
			
		||||
        "SCK": 14,
 | 
			
		||||
        "SCL": 16,
 | 
			
		||||
        "SDA": 13,
 | 
			
		||||
    },
 | 
			
		||||
    "esp32-poe": {"BUTTON": 34, "MISO": 15, "MOSI": 2, "SCK": 14, "SCL": 16, "SDA": 13},
 | 
			
		||||
    "esp32-pro": {
 | 
			
		||||
        "BUTTON": 34,
 | 
			
		||||
        "MISO": 15,
 | 
			
		||||
        "MOSI": 2,
 | 
			
		||||
        "SCK": 14,
 | 
			
		||||
        "SCL": 16,
 | 
			
		||||
        "SDA": 13,
 | 
			
		||||
        "SS": 17,
 | 
			
		||||
    },
 | 
			
		||||
    "esp320": {
 | 
			
		||||
        "LED": 5,
 | 
			
		||||
        "MISO": 12,
 | 
			
		||||
        "MOSI": 13,
 | 
			
		||||
        "SCK": 14,
 | 
			
		||||
        "SCL": 14,
 | 
			
		||||
        "SDA": 2,
 | 
			
		||||
        "SS": 15,
 | 
			
		||||
    },
 | 
			
		||||
    "esp32cam": {},
 | 
			
		||||
    "esp32dev": {},
 | 
			
		||||
    "esp32doit-devkit-v1": {"LED": 2},
 | 
			
		||||
    "esp32thing": {"BUTTON": 0, "LED": 5, "SS": 2},
 | 
			
		||||
    "esp32vn-iot-uno": {},
 | 
			
		||||
    "espea32": {"BUTTON": 0, "LED": 5},
 | 
			
		||||
    "espectro32": {"LED": 15, "SD_SS": 33},
 | 
			
		||||
    "espino32": {"BUTTON": 0, "LED": 16},
 | 
			
		||||
    "featheresp32": {
 | 
			
		||||
        "A0": 26,
 | 
			
		||||
        "A1": 25,
 | 
			
		||||
        "A10": 27,
 | 
			
		||||
        "A11": 12,
 | 
			
		||||
        "A12": 13,
 | 
			
		||||
        "A13": 35,
 | 
			
		||||
        "A2": 34,
 | 
			
		||||
        "A4": 36,
 | 
			
		||||
        "A5": 4,
 | 
			
		||||
        "A6": 14,
 | 
			
		||||
        "A7": 32,
 | 
			
		||||
        "A8": 15,
 | 
			
		||||
        "A9": 33,
 | 
			
		||||
        "Ax": 2,
 | 
			
		||||
        "LED": 13,
 | 
			
		||||
        "MOSI": 18,
 | 
			
		||||
        "RX": 16,
 | 
			
		||||
        "SCK": 5,
 | 
			
		||||
        "SDA": 23,
 | 
			
		||||
        "SS": 33,
 | 
			
		||||
        "TX": 17,
 | 
			
		||||
    },
 | 
			
		||||
    "firebeetle32": {"LED": 2},
 | 
			
		||||
    "fm-devkit": {
 | 
			
		||||
        "D0": 34,
 | 
			
		||||
        "D1": 35,
 | 
			
		||||
        "D10": 0,
 | 
			
		||||
        "D2": 32,
 | 
			
		||||
        "D3": 33,
 | 
			
		||||
        "D4": 27,
 | 
			
		||||
        "D5": 14,
 | 
			
		||||
        "D6": 12,
 | 
			
		||||
        "D7": 13,
 | 
			
		||||
        "D8": 15,
 | 
			
		||||
        "D9": 23,
 | 
			
		||||
        "I2S_DOUT": 22,
 | 
			
		||||
        "I2S_LRCLK": 25,
 | 
			
		||||
        "I2S_MCLK": 2,
 | 
			
		||||
        "I2S_SCLK": 26,
 | 
			
		||||
        "LED": 5,
 | 
			
		||||
        "SCL": 17,
 | 
			
		||||
        "SDA": 16,
 | 
			
		||||
        "SW1": 4,
 | 
			
		||||
        "SW2": 18,
 | 
			
		||||
        "SW3": 19,
 | 
			
		||||
        "SW4": 21,
 | 
			
		||||
    },
 | 
			
		||||
    "frogboard": {},
 | 
			
		||||
    "heltec_wifi_kit_32": {
 | 
			
		||||
        "A1": 37,
 | 
			
		||||
        "A2": 38,
 | 
			
		||||
        "BUTTON": 0,
 | 
			
		||||
        "LED": 25,
 | 
			
		||||
        "RST_OLED": 16,
 | 
			
		||||
        "SCL_OLED": 15,
 | 
			
		||||
        "SDA_OLED": 4,
 | 
			
		||||
        "Vext": 21,
 | 
			
		||||
    },
 | 
			
		||||
    "heltec_wifi_lora_32": {
 | 
			
		||||
        "BUTTON": 0,
 | 
			
		||||
        "DIO0": 26,
 | 
			
		||||
        "DIO1": 33,
 | 
			
		||||
        "DIO2": 32,
 | 
			
		||||
        "LED": 25,
 | 
			
		||||
        "MOSI": 27,
 | 
			
		||||
        "RST_LoRa": 14,
 | 
			
		||||
        "RST_OLED": 16,
 | 
			
		||||
        "SCK": 5,
 | 
			
		||||
        "SCL_OLED": 15,
 | 
			
		||||
        "SDA_OLED": 4,
 | 
			
		||||
        "SS": 18,
 | 
			
		||||
        "Vext": 21,
 | 
			
		||||
    },
 | 
			
		||||
    "heltec_wifi_lora_32_V2": {
 | 
			
		||||
        "BUTTON": 0,
 | 
			
		||||
        "DIO0": 26,
 | 
			
		||||
        "DIO1": 35,
 | 
			
		||||
        "DIO2": 34,
 | 
			
		||||
        "LED": 25,
 | 
			
		||||
        "MOSI": 27,
 | 
			
		||||
        "RST_LoRa": 14,
 | 
			
		||||
        "RST_OLED": 16,
 | 
			
		||||
        "SCK": 5,
 | 
			
		||||
        "SCL_OLED": 15,
 | 
			
		||||
        "SDA_OLED": 4,
 | 
			
		||||
        "SS": 18,
 | 
			
		||||
        "Vext": 21,
 | 
			
		||||
    },
 | 
			
		||||
    "heltec_wireless_stick": {
 | 
			
		||||
        "BUTTON": 0,
 | 
			
		||||
        "DIO0": 26,
 | 
			
		||||
        "DIO1": 35,
 | 
			
		||||
        "DIO2": 34,
 | 
			
		||||
        "LED": 25,
 | 
			
		||||
        "MOSI": 27,
 | 
			
		||||
        "RST_LoRa": 14,
 | 
			
		||||
        "RST_OLED": 16,
 | 
			
		||||
        "SCK": 5,
 | 
			
		||||
        "SCL_OLED": 15,
 | 
			
		||||
        "SDA_OLED": 4,
 | 
			
		||||
        "SS": 18,
 | 
			
		||||
        "Vext": 21,
 | 
			
		||||
    },
 | 
			
		||||
    "hornbill32dev": {"BUTTON": 0, "LED": 13},
 | 
			
		||||
    "hornbill32minima": {"SS": 2},
 | 
			
		||||
    "intorobot": {
 | 
			
		||||
        "A1": 39,
 | 
			
		||||
        "A2": 35,
 | 
			
		||||
        "A3": 25,
 | 
			
		||||
        "A4": 26,
 | 
			
		||||
        "A5": 14,
 | 
			
		||||
        "A6": 12,
 | 
			
		||||
        "A7": 15,
 | 
			
		||||
        "A8": 13,
 | 
			
		||||
        "A9": 2,
 | 
			
		||||
        "BUTTON": 0,
 | 
			
		||||
        "D0": 19,
 | 
			
		||||
        "D1": 23,
 | 
			
		||||
        "D2": 18,
 | 
			
		||||
        "D3": 17,
 | 
			
		||||
        "D4": 16,
 | 
			
		||||
        "D5": 5,
 | 
			
		||||
        "D6": 4,
 | 
			
		||||
        "LED": 4,
 | 
			
		||||
        "MISO": 17,
 | 
			
		||||
        "MOSI": 16,
 | 
			
		||||
        "RGB_B_BUILTIN": 22,
 | 
			
		||||
        "RGB_G_BUILTIN": 21,
 | 
			
		||||
        "RGB_R_BUILTIN": 27,
 | 
			
		||||
        "SCL": 19,
 | 
			
		||||
        "SDA": 23,
 | 
			
		||||
        "T0": 19,
 | 
			
		||||
        "T1": 23,
 | 
			
		||||
        "T2": 18,
 | 
			
		||||
        "T3": 17,
 | 
			
		||||
        "T4": 16,
 | 
			
		||||
        "T5": 5,
 | 
			
		||||
        "T6": 4,
 | 
			
		||||
    },
 | 
			
		||||
    "iotaap_magnolia": {},
 | 
			
		||||
    "iotbusio": {},
 | 
			
		||||
    "iotbusproteus": {},
 | 
			
		||||
    "lolin32": {"LED": 5},
 | 
			
		||||
    "lolin32_lite": {"LED": 22},
 | 
			
		||||
    "lolin_d32": {"LED": 5, "_VBAT": 35},
 | 
			
		||||
    "lolin_d32_pro": {"LED": 5, "_VBAT": 35},
 | 
			
		||||
    "lopy": {
 | 
			
		||||
        "A1": 37,
 | 
			
		||||
        "A2": 38,
 | 
			
		||||
        "LED": 0,
 | 
			
		||||
        "MISO": 37,
 | 
			
		||||
        "MOSI": 22,
 | 
			
		||||
        "SCK": 13,
 | 
			
		||||
        "SCL": 13,
 | 
			
		||||
        "SDA": 12,
 | 
			
		||||
        "SS": 17,
 | 
			
		||||
    },
 | 
			
		||||
    "lopy4": {
 | 
			
		||||
        "A1": 37,
 | 
			
		||||
        "A2": 38,
 | 
			
		||||
        "LED": 0,
 | 
			
		||||
        "MISO": 37,
 | 
			
		||||
        "MOSI": 22,
 | 
			
		||||
        "SCK": 13,
 | 
			
		||||
        "SCL": 13,
 | 
			
		||||
        "SDA": 12,
 | 
			
		||||
        "SS": 18,
 | 
			
		||||
    },
 | 
			
		||||
    "m5stack-core-esp32": {
 | 
			
		||||
        "ADC1": 35,
 | 
			
		||||
        "ADC2": 36,
 | 
			
		||||
        "G0": 0,
 | 
			
		||||
        "G1": 1,
 | 
			
		||||
        "G12": 12,
 | 
			
		||||
        "G13": 13,
 | 
			
		||||
        "G15": 15,
 | 
			
		||||
        "G16": 16,
 | 
			
		||||
        "G17": 17,
 | 
			
		||||
        "G18": 18,
 | 
			
		||||
        "G19": 19,
 | 
			
		||||
        "G2": 2,
 | 
			
		||||
        "G21": 21,
 | 
			
		||||
        "G22": 22,
 | 
			
		||||
        "G23": 23,
 | 
			
		||||
        "G25": 25,
 | 
			
		||||
        "G26": 26,
 | 
			
		||||
        "G3": 3,
 | 
			
		||||
        "G34": 34,
 | 
			
		||||
        "G35": 35,
 | 
			
		||||
        "G36": 36,
 | 
			
		||||
        "G5": 5,
 | 
			
		||||
        "RXD2": 16,
 | 
			
		||||
        "TXD2": 17,
 | 
			
		||||
    },
 | 
			
		||||
    "m5stack-fire": {
 | 
			
		||||
        "ADC1": 35,
 | 
			
		||||
        "ADC2": 36,
 | 
			
		||||
        "G0": 0,
 | 
			
		||||
        "G1": 1,
 | 
			
		||||
        "G12": 12,
 | 
			
		||||
        "G13": 13,
 | 
			
		||||
        "G15": 15,
 | 
			
		||||
        "G16": 16,
 | 
			
		||||
        "G17": 17,
 | 
			
		||||
        "G18": 18,
 | 
			
		||||
        "G19": 19,
 | 
			
		||||
        "G2": 2,
 | 
			
		||||
        "G21": 21,
 | 
			
		||||
        "G22": 22,
 | 
			
		||||
        "G23": 23,
 | 
			
		||||
        "G25": 25,
 | 
			
		||||
        "G26": 26,
 | 
			
		||||
        "G3": 3,
 | 
			
		||||
        "G34": 34,
 | 
			
		||||
        "G35": 35,
 | 
			
		||||
        "G36": 36,
 | 
			
		||||
        "G5": 5,
 | 
			
		||||
    },
 | 
			
		||||
    "m5stack-grey": {
 | 
			
		||||
        "ADC1": 35,
 | 
			
		||||
        "ADC2": 36,
 | 
			
		||||
        "G0": 0,
 | 
			
		||||
        "G1": 1,
 | 
			
		||||
        "G12": 12,
 | 
			
		||||
        "G13": 13,
 | 
			
		||||
        "G15": 15,
 | 
			
		||||
        "G16": 16,
 | 
			
		||||
        "G17": 17,
 | 
			
		||||
        "G18": 18,
 | 
			
		||||
        "G19": 19,
 | 
			
		||||
        "G2": 2,
 | 
			
		||||
        "G21": 21,
 | 
			
		||||
        "G22": 22,
 | 
			
		||||
        "G23": 23,
 | 
			
		||||
        "G25": 25,
 | 
			
		||||
        "G26": 26,
 | 
			
		||||
        "G3": 3,
 | 
			
		||||
        "G34": 34,
 | 
			
		||||
        "G35": 35,
 | 
			
		||||
        "G36": 36,
 | 
			
		||||
        "G5": 5,
 | 
			
		||||
        "RXD2": 16,
 | 
			
		||||
        "TXD2": 17,
 | 
			
		||||
    },
 | 
			
		||||
    "m5stick-c": {
 | 
			
		||||
        "ADC1": 35,
 | 
			
		||||
        "ADC2": 36,
 | 
			
		||||
        "G0": 0,
 | 
			
		||||
        "G10": 10,
 | 
			
		||||
        "G26": 26,
 | 
			
		||||
        "G32": 32,
 | 
			
		||||
        "G33": 33,
 | 
			
		||||
        "G36": 36,
 | 
			
		||||
        "G37": 37,
 | 
			
		||||
        "G39": 39,
 | 
			
		||||
        "G9": 9,
 | 
			
		||||
        "MISO": 36,
 | 
			
		||||
        "MOSI": 15,
 | 
			
		||||
        "SCK": 13,
 | 
			
		||||
        "SCL": 33,
 | 
			
		||||
        "SDA": 32,
 | 
			
		||||
    },
 | 
			
		||||
    "magicbit": {
 | 
			
		||||
        "BLUE_LED": 17,
 | 
			
		||||
        "BUZZER": 25,
 | 
			
		||||
        "GREEN_LED": 16,
 | 
			
		||||
        "LDR": 36,
 | 
			
		||||
        "LED": 16,
 | 
			
		||||
        "LEFT_BUTTON": 35,
 | 
			
		||||
        "MOTOR1A": 27,
 | 
			
		||||
        "MOTOR1B": 18,
 | 
			
		||||
        "MOTOR2A": 16,
 | 
			
		||||
        "MOTOR2B": 17,
 | 
			
		||||
        "POT": 39,
 | 
			
		||||
        "RED_LED": 27,
 | 
			
		||||
        "RIGHT_PUTTON": 34,
 | 
			
		||||
        "YELLOW_LED": 18,
 | 
			
		||||
    },
 | 
			
		||||
    "mhetesp32devkit": {"LED": 2},
 | 
			
		||||
    "mhetesp32minikit": {"LED": 2},
 | 
			
		||||
    "microduino-core-esp32": {
 | 
			
		||||
        "A0": 12,
 | 
			
		||||
        "A1": 13,
 | 
			
		||||
        "A10": 25,
 | 
			
		||||
        "A11": 26,
 | 
			
		||||
        "A12": 27,
 | 
			
		||||
        "A13": 14,
 | 
			
		||||
        "A2": 15,
 | 
			
		||||
        "A3": 4,
 | 
			
		||||
        "A6": 38,
 | 
			
		||||
        "A7": 37,
 | 
			
		||||
        "A8": 32,
 | 
			
		||||
        "A9": 33,
 | 
			
		||||
        "D0": 3,
 | 
			
		||||
        "D1": 1,
 | 
			
		||||
        "D10": 5,
 | 
			
		||||
        "D11": 23,
 | 
			
		||||
        "D12": 19,
 | 
			
		||||
        "D13": 18,
 | 
			
		||||
        "D14": 12,
 | 
			
		||||
        "D15": 13,
 | 
			
		||||
        "D16": 15,
 | 
			
		||||
        "D17": 4,
 | 
			
		||||
        "D18": 22,
 | 
			
		||||
        "D19": 21,
 | 
			
		||||
        "D2": 16,
 | 
			
		||||
        "D20": 38,
 | 
			
		||||
        "D21": 37,
 | 
			
		||||
        "D3": 17,
 | 
			
		||||
        "D4": 32,
 | 
			
		||||
        "D5": 33,
 | 
			
		||||
        "D6": 25,
 | 
			
		||||
        "D7": 26,
 | 
			
		||||
        "D8": 27,
 | 
			
		||||
        "D9": 14,
 | 
			
		||||
        "SCL": 21,
 | 
			
		||||
        "SCL1": 13,
 | 
			
		||||
        "SDA": 22,
 | 
			
		||||
        "SDA1": 12,
 | 
			
		||||
    },
 | 
			
		||||
    "nano32": {"BUTTON": 0, "LED": 16},
 | 
			
		||||
    "nina_w10": {
 | 
			
		||||
        "D0": 3,
 | 
			
		||||
        "D1": 1,
 | 
			
		||||
        "D10": 5,
 | 
			
		||||
        "D11": 19,
 | 
			
		||||
        "D12": 23,
 | 
			
		||||
        "D13": 18,
 | 
			
		||||
        "D14": 13,
 | 
			
		||||
        "D15": 12,
 | 
			
		||||
        "D16": 32,
 | 
			
		||||
        "D17": 33,
 | 
			
		||||
        "D18": 21,
 | 
			
		||||
        "D19": 34,
 | 
			
		||||
        "D2": 26,
 | 
			
		||||
        "D20": 36,
 | 
			
		||||
        "D21": 39,
 | 
			
		||||
        "D3": 25,
 | 
			
		||||
        "D4": 35,
 | 
			
		||||
        "D5": 27,
 | 
			
		||||
        "D6": 22,
 | 
			
		||||
        "D7": 0,
 | 
			
		||||
        "D8": 15,
 | 
			
		||||
        "D9": 14,
 | 
			
		||||
        "LED_BLUE": 21,
 | 
			
		||||
        "LED_GREEN": 33,
 | 
			
		||||
        "LED_RED": 23,
 | 
			
		||||
        "SCL": 13,
 | 
			
		||||
        "SDA": 12,
 | 
			
		||||
        "SW1": 33,
 | 
			
		||||
        "SW2": 27,
 | 
			
		||||
    },
 | 
			
		||||
    "node32s": {},
 | 
			
		||||
    "nodemcu-32s": {"BUTTON": 0, "LED": 2},
 | 
			
		||||
    "odroid_esp32": {"ADC1": 35, "ADC2": 36, "LED": 2, "SCL": 4, "SDA": 15, "SS": 22},
 | 
			
		||||
    "onehorse32dev": {"A1": 37, "A2": 38, "BUTTON": 0, "LED": 5},
 | 
			
		||||
    "oroca_edubot": {
 | 
			
		||||
        "A0": 34,
 | 
			
		||||
        "A1": 39,
 | 
			
		||||
        "A2": 36,
 | 
			
		||||
        "A3": 33,
 | 
			
		||||
        "D0": 4,
 | 
			
		||||
        "D1": 16,
 | 
			
		||||
        "D2": 17,
 | 
			
		||||
        "D3": 22,
 | 
			
		||||
        "D4": 23,
 | 
			
		||||
        "D5": 5,
 | 
			
		||||
        "D6": 18,
 | 
			
		||||
        "D7": 19,
 | 
			
		||||
        "D8": 33,
 | 
			
		||||
        "LED": 13,
 | 
			
		||||
        "MOSI": 18,
 | 
			
		||||
        "RX": 16,
 | 
			
		||||
        "SCK": 5,
 | 
			
		||||
        "SDA": 23,
 | 
			
		||||
        "SS": 2,
 | 
			
		||||
        "TX": 17,
 | 
			
		||||
        "VBAT": 35,
 | 
			
		||||
    },
 | 
			
		||||
    "pico32": {},
 | 
			
		||||
    "pocket_32": {"LED": 16},
 | 
			
		||||
    "pycom_gpy": {
 | 
			
		||||
        "A1": 37,
 | 
			
		||||
        "A2": 38,
 | 
			
		||||
        "LED": 0,
 | 
			
		||||
        "MISO": 37,
 | 
			
		||||
        "MOSI": 22,
 | 
			
		||||
        "SCK": 13,
 | 
			
		||||
        "SCL": 13,
 | 
			
		||||
        "SDA": 12,
 | 
			
		||||
        "SS": 17,
 | 
			
		||||
    },
 | 
			
		||||
    "quantum": {},
 | 
			
		||||
    "sparkfun_lora_gateway_1-channel": {"MISO": 12, "MOSI": 13, "SCK": 14, "SS": 16},
 | 
			
		||||
    "tinypico": {},
 | 
			
		||||
    "ttgo-lora32-v1": {
 | 
			
		||||
        "A1": 37,
 | 
			
		||||
        "A2": 38,
 | 
			
		||||
        "BUTTON": 0,
 | 
			
		||||
        "LED": 2,
 | 
			
		||||
        "MOSI": 27,
 | 
			
		||||
        "SCK": 5,
 | 
			
		||||
        "SS": 18,
 | 
			
		||||
    },
 | 
			
		||||
    "ttgo-t-beam": {"BUTTON": 39, "LED": 14, "MOSI": 27, "SCK": 5, "SS": 18},
 | 
			
		||||
    "ttgo-t-watch": {"BUTTON": 36, "MISO": 2, "MOSI": 15, "SCK": 14, "SS": 13},
 | 
			
		||||
    "ttgo-t1": {"LED": 22, "MISO": 2, "MOSI": 15, "SCK": 14, "SCL": 23, "SS": 13},
 | 
			
		||||
    "ttgo-t7-v13-mini32": {"LED": 22},
 | 
			
		||||
    "ttgo-t7-v14-mini32": {"LED": 19},
 | 
			
		||||
    "turta_iot_node": {},
 | 
			
		||||
    "vintlabs-devkit-v1": {
 | 
			
		||||
        "LED": 2,
 | 
			
		||||
        "PWM0": 12,
 | 
			
		||||
        "PWM1": 13,
 | 
			
		||||
        "PWM2": 14,
 | 
			
		||||
        "PWM3": 15,
 | 
			
		||||
        "PWM4": 16,
 | 
			
		||||
        "PWM5": 17,
 | 
			
		||||
        "PWM6": 18,
 | 
			
		||||
        "PWM7": 19,
 | 
			
		||||
    },
 | 
			
		||||
    "wemos_d1_mini32": {
 | 
			
		||||
        "D0": 26,
 | 
			
		||||
        "D1": 22,
 | 
			
		||||
        "D2": 21,
 | 
			
		||||
        "D3": 17,
 | 
			
		||||
        "D4": 16,
 | 
			
		||||
        "D5": 18,
 | 
			
		||||
        "D6": 19,
 | 
			
		||||
        "D7": 23,
 | 
			
		||||
        "D8": 5,
 | 
			
		||||
        "LED": 2,
 | 
			
		||||
        "RXD": 3,
 | 
			
		||||
        "TXD": 1,
 | 
			
		||||
        "_VBAT": 35,
 | 
			
		||||
    },
 | 
			
		||||
    "wemosbat": {"LED": 16},
 | 
			
		||||
    "wesp32": {"MISO": 32, "SCL": 4, "SDA": 15},
 | 
			
		||||
    "widora-air": {
 | 
			
		||||
        "A1": 39,
 | 
			
		||||
        "A2": 35,
 | 
			
		||||
        "A3": 25,
 | 
			
		||||
        "A4": 26,
 | 
			
		||||
        "A5": 14,
 | 
			
		||||
        "A6": 12,
 | 
			
		||||
        "A7": 15,
 | 
			
		||||
        "A8": 13,
 | 
			
		||||
        "A9": 2,
 | 
			
		||||
        "BUTTON": 0,
 | 
			
		||||
        "D0": 19,
 | 
			
		||||
        "D1": 23,
 | 
			
		||||
        "D2": 18,
 | 
			
		||||
        "D3": 17,
 | 
			
		||||
        "D4": 16,
 | 
			
		||||
        "D5": 5,
 | 
			
		||||
        "D6": 4,
 | 
			
		||||
        "LED": 25,
 | 
			
		||||
        "MISO": 17,
 | 
			
		||||
        "MOSI": 16,
 | 
			
		||||
        "SCL": 19,
 | 
			
		||||
        "SDA": 23,
 | 
			
		||||
        "T0": 19,
 | 
			
		||||
        "T1": 23,
 | 
			
		||||
        "T2": 18,
 | 
			
		||||
        "T3": 17,
 | 
			
		||||
        "T4": 16,
 | 
			
		||||
        "T5": 5,
 | 
			
		||||
        "T6": 4,
 | 
			
		||||
    },
 | 
			
		||||
    "xinabox_cw02": {"LED": 27},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ESP32_C3_BASE_PINS = {
 | 
			
		||||
    "TX": 21,
 | 
			
		||||
    "RX": 20,
 | 
			
		||||
    "ADC1_0": 0,
 | 
			
		||||
    "ADC1_1": 1,
 | 
			
		||||
    "ADC1_2": 2,
 | 
			
		||||
    "ADC1_3": 3,
 | 
			
		||||
    "ADC1_4": 4,
 | 
			
		||||
    "ADC2_0": 5,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ESP32_C3_BOARD_PINS = {
 | 
			
		||||
    "esp32-c3-devkitm-1": {"LED": 8},
 | 
			
		||||
    "esp32-c3-devkitc-02": "esp32-c3-devkitm-1",
 | 
			
		||||
}
 | 
			
		||||
@@ -125,7 +125,7 @@ void ICACHE_RAM_ATTR HOT AcDimmerDataStore::gpio_intr() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ICACHE_RAM_ATTR HOT AcDimmerDataStore::s_gpio_intr(AcDimmerDataStore *store) {
 | 
			
		||||
  // Attaching pin interrupts on the same pin will override the previous interupt
 | 
			
		||||
  // Attaching pin interrupts on the same pin will override the previous interrupt
 | 
			
		||||
  // However, the user expects that multiple dimmers sharing the same ZC pin will work.
 | 
			
		||||
  // We solve this in a bit of a hacky way: On each pin interrupt, we check all dimmers
 | 
			
		||||
  // if any of them are using the same ZC pin, and also trigger the interrupt for *them*.
 | 
			
		||||
 
 | 
			
		||||
@@ -42,7 +42,7 @@ void AdalightLightEffect::reset_frame_(light::AddressableLight &it) {
 | 
			
		||||
 | 
			
		||||
void AdalightLightEffect::blank_all_leds_(light::AddressableLight &it) {
 | 
			
		||||
  for (int led = it.size(); led-- > 0;) {
 | 
			
		||||
    it[led].set(COLOR_BLACK);
 | 
			
		||||
    it[led].set(Color::BLACK);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@ static const char *const TAG = "adc";
 | 
			
		||||
void ADCSensor::set_attenuation(adc_atten_t attenuation) { this->attenuation_ = attenuation; }
 | 
			
		||||
 | 
			
		||||
inline adc1_channel_t gpio_to_adc1(uint8_t pin) {
 | 
			
		||||
#if CONFIG_IDF_TARGET_ESP32
 | 
			
		||||
  switch (pin) {
 | 
			
		||||
    case 36:
 | 
			
		||||
      return ADC1_CHANNEL_0;
 | 
			
		||||
@@ -34,6 +35,22 @@ inline adc1_channel_t gpio_to_adc1(uint8_t pin) {
 | 
			
		||||
    default:
 | 
			
		||||
      return ADC1_CHANNEL_MAX;
 | 
			
		||||
  }
 | 
			
		||||
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
 | 
			
		||||
  switch (pin) {
 | 
			
		||||
    case 0:
 | 
			
		||||
      return ADC1_CHANNEL_0;
 | 
			
		||||
    case 1:
 | 
			
		||||
      return ADC1_CHANNEL_1;
 | 
			
		||||
    case 2:
 | 
			
		||||
      return ADC1_CHANNEL_2;
 | 
			
		||||
    case 3:
 | 
			
		||||
      return ADC1_CHANNEL_3;
 | 
			
		||||
    case 4:
 | 
			
		||||
      return ADC1_CHANNEL_4;
 | 
			
		||||
    default:
 | 
			
		||||
      return ADC1_CHANNEL_MAX;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@@ -46,8 +63,10 @@ void ADCSensor::setup() {
 | 
			
		||||
#ifdef ARDUINO_ARCH_ESP32
 | 
			
		||||
  adc1_config_channel_atten(gpio_to_adc1(pin_), attenuation_);
 | 
			
		||||
  adc1_config_width(ADC_WIDTH_BIT_12);
 | 
			
		||||
#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2
 | 
			
		||||
  adc_gpio_init(ADC_UNIT_1, (adc_channel_t) gpio_to_adc1(pin_));
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
void ADCSensor::dump_config() {
 | 
			
		||||
  LOG_SENSOR("", "ADC Sensor", this);
 | 
			
		||||
@@ -89,6 +108,7 @@ float ADCSensor::sample() {
 | 
			
		||||
#ifdef ARDUINO_ARCH_ESP32
 | 
			
		||||
  int raw = adc1_get_raw(gpio_to_adc1(pin_));
 | 
			
		||||
  float value_v = raw / 4095.0f;
 | 
			
		||||
#if CONFIG_IDF_TARGET_ESP32
 | 
			
		||||
  switch (this->attenuation_) {
 | 
			
		||||
    case ADC_ATTEN_DB_0:
 | 
			
		||||
      value_v *= 1.1;
 | 
			
		||||
@@ -105,6 +125,24 @@ float ADCSensor::sample() {
 | 
			
		||||
    default:  // This is to satisfy the unused ADC_ATTEN_MAX
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
 | 
			
		||||
  switch (this->attenuation_) {
 | 
			
		||||
    case ADC_ATTEN_DB_0:
 | 
			
		||||
      value_v *= 0.84;
 | 
			
		||||
      break;
 | 
			
		||||
    case ADC_ATTEN_DB_2_5:
 | 
			
		||||
      value_v *= 1.13;
 | 
			
		||||
      break;
 | 
			
		||||
    case ADC_ATTEN_DB_6:
 | 
			
		||||
      value_v *= 1.56;
 | 
			
		||||
      break;
 | 
			
		||||
    case ADC_ATTEN_DB_11:
 | 
			
		||||
      value_v *= 3.0;
 | 
			
		||||
      break;
 | 
			
		||||
    default:  // This is to satisfy the unused ADC_ATTEN_MAX
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
  return value_v;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,6 @@ from esphome.const import (
 | 
			
		||||
    CONF_ID,
 | 
			
		||||
    CONF_PIN,
 | 
			
		||||
    DEVICE_CLASS_VOLTAGE,
 | 
			
		||||
    ICON_EMPTY,
 | 
			
		||||
    STATE_CLASS_MEASUREMENT,
 | 
			
		||||
    UNIT_VOLT,
 | 
			
		||||
)
 | 
			
		||||
@@ -37,7 +36,10 @@ ADCSensor = adc_ns.class_(
 | 
			
		||||
 | 
			
		||||
CONFIG_SCHEMA = (
 | 
			
		||||
    sensor.sensor_schema(
 | 
			
		||||
        UNIT_VOLT, ICON_EMPTY, 2, DEVICE_CLASS_VOLTAGE, STATE_CLASS_MEASUREMENT
 | 
			
		||||
        unit_of_measurement=UNIT_VOLT,
 | 
			
		||||
        accuracy_decimals=2,
 | 
			
		||||
        device_class=DEVICE_CLASS_VOLTAGE,
 | 
			
		||||
        state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
    )
 | 
			
		||||
    .extend(
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,6 @@ from esphome.const import (
 | 
			
		||||
    DEVICE_CLASS_CURRENT,
 | 
			
		||||
    DEVICE_CLASS_POWER,
 | 
			
		||||
    DEVICE_CLASS_VOLTAGE,
 | 
			
		||||
    ICON_EMPTY,
 | 
			
		||||
    STATE_CLASS_MEASUREMENT,
 | 
			
		||||
    UNIT_VOLT,
 | 
			
		||||
    UNIT_AMPERE,
 | 
			
		||||
@@ -32,27 +31,34 @@ CONFIG_SCHEMA = (
 | 
			
		||||
            cv.GenerateID(): cv.declare_id(ADE7953),
 | 
			
		||||
            cv.Optional(CONF_IRQ_PIN): pins.input_pin,
 | 
			
		||||
            cv.Optional(CONF_VOLTAGE): sensor.sensor_schema(
 | 
			
		||||
                UNIT_VOLT, ICON_EMPTY, 1, DEVICE_CLASS_VOLTAGE, STATE_CLASS_MEASUREMENT
 | 
			
		||||
                unit_of_measurement=UNIT_VOLT,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_VOLTAGE,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_CURRENT_A): sensor.sensor_schema(
 | 
			
		||||
                UNIT_AMPERE,
 | 
			
		||||
                ICON_EMPTY,
 | 
			
		||||
                2,
 | 
			
		||||
                DEVICE_CLASS_CURRENT,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_AMPERE,
 | 
			
		||||
                accuracy_decimals=2,
 | 
			
		||||
                device_class=DEVICE_CLASS_CURRENT,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_CURRENT_B): sensor.sensor_schema(
 | 
			
		||||
                UNIT_AMPERE,
 | 
			
		||||
                ICON_EMPTY,
 | 
			
		||||
                2,
 | 
			
		||||
                DEVICE_CLASS_CURRENT,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_AMPERE,
 | 
			
		||||
                accuracy_decimals=2,
 | 
			
		||||
                device_class=DEVICE_CLASS_CURRENT,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_ACTIVE_POWER_A): sensor.sensor_schema(
 | 
			
		||||
                UNIT_WATT, ICON_EMPTY, 1, DEVICE_CLASS_POWER, STATE_CLASS_MEASUREMENT
 | 
			
		||||
                unit_of_measurement=UNIT_WATT,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_POWER,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_ACTIVE_POWER_B): sensor.sensor_schema(
 | 
			
		||||
                UNIT_WATT, ICON_EMPTY, 1, DEVICE_CLASS_POWER, STATE_CLASS_MEASUREMENT
 | 
			
		||||
                unit_of_measurement=UNIT_WATT,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_POWER,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ from esphome.const import (
 | 
			
		||||
    CONF_GAIN,
 | 
			
		||||
    CONF_MULTIPLEXER,
 | 
			
		||||
    DEVICE_CLASS_VOLTAGE,
 | 
			
		||||
    ICON_EMPTY,
 | 
			
		||||
    STATE_CLASS_MEASUREMENT,
 | 
			
		||||
    UNIT_VOLT,
 | 
			
		||||
    CONF_ID,
 | 
			
		||||
@@ -53,7 +52,10 @@ ADS1115Sensor = ads1115_ns.class_(
 | 
			
		||||
CONF_ADS1115_ID = "ads1115_id"
 | 
			
		||||
CONFIG_SCHEMA = (
 | 
			
		||||
    sensor.sensor_schema(
 | 
			
		||||
        UNIT_VOLT, ICON_EMPTY, 3, DEVICE_CLASS_VOLTAGE, STATE_CLASS_MEASUREMENT
 | 
			
		||||
        unit_of_measurement=UNIT_VOLT,
 | 
			
		||||
        accuracy_decimals=3,
 | 
			
		||||
        device_class=DEVICE_CLASS_VOLTAGE,
 | 
			
		||||
        state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
    )
 | 
			
		||||
    .extend(
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@
 | 
			
		||||
//
 | 
			
		||||
// According to the datasheet, the component is supposed to respond in more than 75ms. In fact, it can answer almost
 | 
			
		||||
// immediately for temperature. But for humidity, it takes >90ms to get a valid data. From experience, we have best
 | 
			
		||||
// results making successive requests; the current implementation make 3 attemps with a delay of 30ms each time.
 | 
			
		||||
// results making successive requests; the current implementation makes 3 attempts with a delay of 30ms each time.
 | 
			
		||||
 | 
			
		||||
#include "aht10.h"
 | 
			
		||||
#include "esphome/core/log.h"
 | 
			
		||||
@@ -23,7 +23,7 @@ static const uint8_t AHT10_CALIBRATE_CMD[] = {0xE1};
 | 
			
		||||
static const uint8_t AHT10_MEASURE_CMD[] = {0xAC, 0x33, 0x00};
 | 
			
		||||
static const uint8_t AHT10_DEFAULT_DELAY = 5;    // ms, for calibration and temperature measurement
 | 
			
		||||
static const uint8_t AHT10_HUMIDITY_DELAY = 30;  // ms
 | 
			
		||||
static const uint8_t AHT10_ATTEMPS = 3;          // safety margin, normally 3 attemps are enough: 3*30=90ms
 | 
			
		||||
static const uint8_t AHT10_ATTEMPTS = 3;         // safety margin, normally 3 attempts are enough: 3*30=90ms
 | 
			
		||||
 | 
			
		||||
void AHT10Component::setup() {
 | 
			
		||||
  ESP_LOGCONFIG(TAG, "Setting up AHT10...");
 | 
			
		||||
@@ -58,8 +58,8 @@ void AHT10Component::update() {
 | 
			
		||||
  uint8_t delay = AHT10_DEFAULT_DELAY;
 | 
			
		||||
  if (this->humidity_sensor_ != nullptr)
 | 
			
		||||
    delay = AHT10_HUMIDITY_DELAY;
 | 
			
		||||
  for (int i = 0; i < AHT10_ATTEMPS; ++i) {
 | 
			
		||||
    ESP_LOGVV(TAG, "Attemps %u at %6ld", i, millis());
 | 
			
		||||
  for (int i = 0; i < AHT10_ATTEMPTS; ++i) {
 | 
			
		||||
    ESP_LOGVV(TAG, "Attempt %u at %6ld", i, millis());
 | 
			
		||||
    delay_microseconds_accurate(4);
 | 
			
		||||
    if (!this->read_bytes(0, data, 6, delay)) {
 | 
			
		||||
      ESP_LOGD(TAG, "Communication with AHT10 failed, waiting...");
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,6 @@ from esphome.const import (
 | 
			
		||||
    CONF_TEMPERATURE,
 | 
			
		||||
    DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
    DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
    ICON_EMPTY,
 | 
			
		||||
    STATE_CLASS_MEASUREMENT,
 | 
			
		||||
    UNIT_CELSIUS,
 | 
			
		||||
    UNIT_PERCENT,
 | 
			
		||||
@@ -23,18 +22,16 @@ CONFIG_SCHEMA = (
 | 
			
		||||
        {
 | 
			
		||||
            cv.GenerateID(): cv.declare_id(AHT10Component),
 | 
			
		||||
            cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
 | 
			
		||||
                UNIT_CELSIUS,
 | 
			
		||||
                ICON_EMPTY,
 | 
			
		||||
                2,
 | 
			
		||||
                DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_CELSIUS,
 | 
			
		||||
                accuracy_decimals=2,
 | 
			
		||||
                device_class=DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(
 | 
			
		||||
                UNIT_PERCENT,
 | 
			
		||||
                ICON_EMPTY,
 | 
			
		||||
                2,
 | 
			
		||||
                DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_PERCENT,
 | 
			
		||||
                accuracy_decimals=2,
 | 
			
		||||
                device_class=DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,6 @@ from esphome.const import (
 | 
			
		||||
    DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
    STATE_CLASS_MEASUREMENT,
 | 
			
		||||
    UNIT_CELSIUS,
 | 
			
		||||
    ICON_EMPTY,
 | 
			
		||||
    UNIT_PERCENT,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -25,18 +24,16 @@ CONFIG_SCHEMA = (
 | 
			
		||||
        {
 | 
			
		||||
            cv.GenerateID(): cv.declare_id(AM2320Component),
 | 
			
		||||
            cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
 | 
			
		||||
                UNIT_CELSIUS,
 | 
			
		||||
                ICON_EMPTY,
 | 
			
		||||
                1,
 | 
			
		||||
                DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_CELSIUS,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(
 | 
			
		||||
                UNIT_PERCENT,
 | 
			
		||||
                ICON_EMPTY,
 | 
			
		||||
                1,
 | 
			
		||||
                DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_PERCENT,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										0
									
								
								esphome/components/am43/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								esphome/components/am43/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										115
									
								
								esphome/components/am43/am43.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								esphome/components/am43/am43.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,115 @@
 | 
			
		||||
#include "am43.h"
 | 
			
		||||
#include "esphome/core/log.h"
 | 
			
		||||
 | 
			
		||||
#ifdef ARDUINO_ARCH_ESP32
 | 
			
		||||
 | 
			
		||||
namespace esphome {
 | 
			
		||||
namespace am43 {
 | 
			
		||||
 | 
			
		||||
static const char *TAG = "am43";
 | 
			
		||||
 | 
			
		||||
void Am43::dump_config() {
 | 
			
		||||
  ESP_LOGCONFIG(TAG, "AM43");
 | 
			
		||||
  LOG_SENSOR(" ", "Battery", this->battery_);
 | 
			
		||||
  LOG_SENSOR(" ", "Illuminance", this->illuminance_);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Am43::setup() {
 | 
			
		||||
  this->encoder_ = new Am43Encoder();
 | 
			
		||||
  this->decoder_ = new Am43Decoder();
 | 
			
		||||
  this->logged_in_ = false;
 | 
			
		||||
  this->last_battery_update_ = 0;
 | 
			
		||||
  this->current_sensor_ = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Am43::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) {
 | 
			
		||||
  switch (event) {
 | 
			
		||||
    case ESP_GATTC_OPEN_EVT: {
 | 
			
		||||
      this->logged_in_ = false;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case ESP_GATTC_DISCONNECT_EVT: {
 | 
			
		||||
      this->logged_in_ = false;
 | 
			
		||||
      this->node_state = espbt::ClientState::Idle;
 | 
			
		||||
      if (this->battery_ != nullptr)
 | 
			
		||||
        this->battery_->publish_state(NAN);
 | 
			
		||||
      if (this->illuminance_ != nullptr)
 | 
			
		||||
        this->illuminance_->publish_state(NAN);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case ESP_GATTC_SEARCH_CMPL_EVT: {
 | 
			
		||||
      auto chr = this->parent_->get_characteristic(AM43_SERVICE_UUID, AM43_CHARACTERISTIC_UUID);
 | 
			
		||||
      if (chr == nullptr) {
 | 
			
		||||
        if (this->parent_->get_characteristic(AM43_TUYA_SERVICE_UUID, AM43_TUYA_CHARACTERISTIC_UUID) != nullptr) {
 | 
			
		||||
          ESP_LOGE(TAG, "[%s] Detected a Tuya AM43 which is not supported, sorry.",
 | 
			
		||||
                   this->parent_->address_str().c_str());
 | 
			
		||||
        } else {
 | 
			
		||||
          ESP_LOGE(TAG, "[%s] No control service found at device, not an AM43..?",
 | 
			
		||||
                   this->parent_->address_str().c_str());
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      this->char_handle_ = chr->handle;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
 | 
			
		||||
      this->node_state = espbt::ClientState::Established;
 | 
			
		||||
      this->update();
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case ESP_GATTC_NOTIFY_EVT: {
 | 
			
		||||
      if (param->notify.handle != this->char_handle_)
 | 
			
		||||
        break;
 | 
			
		||||
      this->decoder_->decode(param->notify.value, param->notify.value_len);
 | 
			
		||||
 | 
			
		||||
      if (this->battery_ != nullptr && this->decoder_->has_battery_level() &&
 | 
			
		||||
          millis() - this->last_battery_update_ > 10000) {
 | 
			
		||||
        this->battery_->publish_state(this->decoder_->battery_level_);
 | 
			
		||||
        this->last_battery_update_ = millis();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (this->illuminance_ != nullptr && this->decoder_->has_light_level()) {
 | 
			
		||||
        this->illuminance_->publish_state(this->decoder_->light_level_);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (this->current_sensor_ > 0) {
 | 
			
		||||
        if (this->illuminance_ != nullptr) {
 | 
			
		||||
          auto packet = this->encoder_->get_light_level_request();
 | 
			
		||||
          auto status = esp_ble_gattc_write_char(this->parent_->gattc_if, this->parent_->conn_id, this->char_handle_,
 | 
			
		||||
                                                 packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP,
 | 
			
		||||
                                                 ESP_GATT_AUTH_REQ_NONE);
 | 
			
		||||
          if (status)
 | 
			
		||||
            ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(),
 | 
			
		||||
                     status);
 | 
			
		||||
        }
 | 
			
		||||
        this->current_sensor_ = 0;
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Am43::update() {
 | 
			
		||||
  if (this->node_state != espbt::ClientState::Established) {
 | 
			
		||||
    ESP_LOGW(TAG, "[%s] Cannot poll, not connected", this->parent_->address_str().c_str());
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  if (this->current_sensor_ == 0) {
 | 
			
		||||
    if (this->battery_ != nullptr) {
 | 
			
		||||
      auto packet = this->encoder_->get_battery_level_request();
 | 
			
		||||
      auto status =
 | 
			
		||||
          esp_ble_gattc_write_char(this->parent_->gattc_if, this->parent_->conn_id, this->char_handle_, packet->length,
 | 
			
		||||
                                   packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
 | 
			
		||||
      if (status)
 | 
			
		||||
        ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(), status);
 | 
			
		||||
    }
 | 
			
		||||
    this->current_sensor_++;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace am43
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										45
									
								
								esphome/components/am43/am43.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								esphome/components/am43/am43.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "esphome/core/component.h"
 | 
			
		||||
#include "esphome/components/ble_client/ble_client.h"
 | 
			
		||||
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
 | 
			
		||||
#include "esphome/components/sensor/sensor.h"
 | 
			
		||||
#include "esphome/components/am43/am43_base.h"
 | 
			
		||||
 | 
			
		||||
#ifdef ARDUINO_ARCH_ESP32
 | 
			
		||||
 | 
			
		||||
#include <esp_gattc_api.h>
 | 
			
		||||
 | 
			
		||||
namespace esphome {
 | 
			
		||||
namespace am43 {
 | 
			
		||||
 | 
			
		||||
namespace espbt = esphome::esp32_ble_tracker;
 | 
			
		||||
 | 
			
		||||
class Am43 : public esphome::ble_client::BLEClientNode, public PollingComponent {
 | 
			
		||||
 public:
 | 
			
		||||
  void setup() override;
 | 
			
		||||
  void update() override;
 | 
			
		||||
  void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
 | 
			
		||||
                           esp_ble_gattc_cb_param_t *param) override;
 | 
			
		||||
  void dump_config() override;
 | 
			
		||||
  float get_setup_priority() const override { return setup_priority::DATA; }
 | 
			
		||||
  void set_battery(sensor::Sensor *battery) { battery_ = battery; }
 | 
			
		||||
  void set_illuminance(sensor::Sensor *illuminance) { illuminance_ = illuminance; }
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  uint16_t char_handle_;
 | 
			
		||||
  Am43Encoder *encoder_;
 | 
			
		||||
  Am43Decoder *decoder_;
 | 
			
		||||
  bool logged_in_;
 | 
			
		||||
  sensor::Sensor *battery_{nullptr};
 | 
			
		||||
  sensor::Sensor *illuminance_{nullptr};
 | 
			
		||||
  uint8_t current_sensor_;
 | 
			
		||||
  // The AM43 often gets into a state where it spams loads of battery update
 | 
			
		||||
  // notifications. Here we will limit to no more than every 10s.
 | 
			
		||||
  uint8_t last_battery_update_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace am43
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										142
									
								
								esphome/components/am43/am43_base.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								esphome/components/am43/am43_base.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,142 @@
 | 
			
		||||
#include "am43_base.h"
 | 
			
		||||
 | 
			
		||||
namespace esphome {
 | 
			
		||||
namespace am43 {
 | 
			
		||||
 | 
			
		||||
const uint8_t START_PACKET[5] = {0x00, 0xff, 0x00, 0x00, 0x9a};
 | 
			
		||||
 | 
			
		||||
std::string pkt_to_hex(const uint8_t *data, uint16_t len) {
 | 
			
		||||
  char buf[64];
 | 
			
		||||
  memset(buf, 0, 64);
 | 
			
		||||
  for (int i = 0; i < len; i++)
 | 
			
		||||
    sprintf(&buf[i * 2], "%02x", data[i]);
 | 
			
		||||
  std::string ret = buf;
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Am43Packet *Am43Encoder::get_battery_level_request() {
 | 
			
		||||
  uint8_t data = 0x1;
 | 
			
		||||
  return this->encode_(0xA2, &data, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Am43Packet *Am43Encoder::get_light_level_request() {
 | 
			
		||||
  uint8_t data = 0x1;
 | 
			
		||||
  return this->encode_(0xAA, &data, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Am43Packet *Am43Encoder::get_position_request() {
 | 
			
		||||
  uint8_t data = 0x1;
 | 
			
		||||
  return this->encode_(CMD_GET_POSITION, &data, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Am43Packet *Am43Encoder::get_send_pin_request(uint16_t pin) {
 | 
			
		||||
  uint8_t data[2];
 | 
			
		||||
  data[0] = (pin & 0xFF00) >> 8;
 | 
			
		||||
  data[1] = pin & 0xFF;
 | 
			
		||||
  return this->encode_(CMD_SEND_PIN, data, 2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Am43Packet *Am43Encoder::get_open_request() {
 | 
			
		||||
  uint8_t data = 0xDD;
 | 
			
		||||
  return this->encode_(CMD_SET_STATE, &data, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Am43Packet *Am43Encoder::get_close_request() {
 | 
			
		||||
  uint8_t data = 0xEE;
 | 
			
		||||
  return this->encode_(CMD_SET_STATE, &data, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Am43Packet *Am43Encoder::get_stop_request() {
 | 
			
		||||
  uint8_t data = 0xCC;
 | 
			
		||||
  return this->encode_(CMD_SET_STATE, &data, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Am43Packet *Am43Encoder::get_set_position_request(uint8_t position) {
 | 
			
		||||
  return this->encode_(CMD_SET_POSITION, &position, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Am43Encoder::checksum_() {
 | 
			
		||||
  uint8_t checksum = 0;
 | 
			
		||||
  int i = 0;
 | 
			
		||||
  for (i = 0; i < this->packet_.length; i++)
 | 
			
		||||
    checksum = checksum ^ this->packet_.data[i];
 | 
			
		||||
  this->packet_.data[i] = checksum ^ 0xff;
 | 
			
		||||
  this->packet_.length++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Am43Packet *Am43Encoder::encode_(uint8_t command, uint8_t *data, uint8_t length) {
 | 
			
		||||
  memcpy(this->packet_.data, START_PACKET, 5);
 | 
			
		||||
  this->packet_.data[5] = command;
 | 
			
		||||
  this->packet_.data[6] = length;
 | 
			
		||||
  memcpy(&this->packet_.data[7], data, length);
 | 
			
		||||
  this->packet_.length = length + 7;
 | 
			
		||||
  this->checksum_();
 | 
			
		||||
  ESP_LOGV("am43", "ENC(%d): 0x%s", packet_.length, pkt_to_hex(packet_.data, packet_.length).c_str());
 | 
			
		||||
  return &this->packet_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define VERIFY_MIN_LENGTH(x) \
 | 
			
		||||
  if (length < (x)) \
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
void Am43Decoder::decode(const uint8_t *data, uint16_t length) {
 | 
			
		||||
  this->has_battery_level_ = false;
 | 
			
		||||
  this->has_light_level_ = false;
 | 
			
		||||
  this->has_set_position_response_ = false;
 | 
			
		||||
  this->has_set_state_response_ = false;
 | 
			
		||||
  this->has_position_ = false;
 | 
			
		||||
  this->has_pin_response_ = false;
 | 
			
		||||
  ESP_LOGV("am43", "DEC(%d): 0x%s", length, pkt_to_hex(data, length).c_str());
 | 
			
		||||
 | 
			
		||||
  if (length < 2 || data[0] != 0x9a)
 | 
			
		||||
    return;
 | 
			
		||||
  switch (data[1]) {
 | 
			
		||||
    case CMD_GET_BATTERY_LEVEL: {
 | 
			
		||||
      VERIFY_MIN_LENGTH(8);
 | 
			
		||||
      this->battery_level_ = data[7];
 | 
			
		||||
      this->has_battery_level_ = true;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case CMD_GET_LIGHT_LEVEL: {
 | 
			
		||||
      VERIFY_MIN_LENGTH(5);
 | 
			
		||||
      this->light_level_ = 100 * ((float) data[4] / 9);
 | 
			
		||||
      this->has_light_level_ = true;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case CMD_GET_POSITION: {
 | 
			
		||||
      VERIFY_MIN_LENGTH(6);
 | 
			
		||||
      this->position_ = data[5];
 | 
			
		||||
      this->has_position_ = true;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case CMD_NOTIFY_POSITION: {
 | 
			
		||||
      VERIFY_MIN_LENGTH(5);
 | 
			
		||||
      this->position_ = data[4];
 | 
			
		||||
      this->has_position_ = true;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case CMD_SEND_PIN: {
 | 
			
		||||
      VERIFY_MIN_LENGTH(4);
 | 
			
		||||
      this->pin_ok_ = data[3] == RESPONSE_ACK;
 | 
			
		||||
      this->has_pin_response_ = true;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case CMD_SET_POSITION: {
 | 
			
		||||
      VERIFY_MIN_LENGTH(4);
 | 
			
		||||
      this->set_position_ok_ = data[3] == RESPONSE_ACK;
 | 
			
		||||
      this->has_set_position_response_ = true;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case CMD_SET_STATE: {
 | 
			
		||||
      VERIFY_MIN_LENGTH(4);
 | 
			
		||||
      this->set_state_ok_ = data[3] == RESPONSE_ACK;
 | 
			
		||||
      this->has_set_state_response_ = true;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace am43
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
							
								
								
									
										78
									
								
								esphome/components/am43/am43_base.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								esphome/components/am43/am43_base.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,78 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "esphome/core/log.h"
 | 
			
		||||
#include "esphome/core/helpers.h"
 | 
			
		||||
 | 
			
		||||
namespace esphome {
 | 
			
		||||
namespace am43 {
 | 
			
		||||
 | 
			
		||||
static const uint16_t AM43_SERVICE_UUID = 0xFE50;
 | 
			
		||||
static const uint16_t AM43_CHARACTERISTIC_UUID = 0xFE51;
 | 
			
		||||
//
 | 
			
		||||
// Tuya identifiers, only to detect and warn users as they are incompatible.
 | 
			
		||||
static const uint16_t AM43_TUYA_SERVICE_UUID = 0x1910;
 | 
			
		||||
static const uint16_t AM43_TUYA_CHARACTERISTIC_UUID = 0x2b11;
 | 
			
		||||
 | 
			
		||||
struct Am43Packet {
 | 
			
		||||
  uint8_t length;
 | 
			
		||||
  uint8_t data[24];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const uint8_t CMD_GET_BATTERY_LEVEL = 0xA2;
 | 
			
		||||
static const uint8_t CMD_GET_LIGHT_LEVEL = 0xAA;
 | 
			
		||||
static const uint8_t CMD_GET_POSITION = 0xA7;
 | 
			
		||||
static const uint8_t CMD_SEND_PIN = 0x17;
 | 
			
		||||
static const uint8_t CMD_SET_STATE = 0x0A;
 | 
			
		||||
static const uint8_t CMD_SET_POSITION = 0x0D;
 | 
			
		||||
static const uint8_t CMD_NOTIFY_POSITION = 0xA1;
 | 
			
		||||
 | 
			
		||||
static const uint8_t RESPONSE_ACK = 0x5A;
 | 
			
		||||
static const uint8_t RESPONSE_NACK = 0xA5;
 | 
			
		||||
 | 
			
		||||
class Am43Encoder {
 | 
			
		||||
 public:
 | 
			
		||||
  Am43Packet *get_battery_level_request();
 | 
			
		||||
  Am43Packet *get_light_level_request();
 | 
			
		||||
  Am43Packet *get_position_request();
 | 
			
		||||
  Am43Packet *get_send_pin_request(uint16_t pin);
 | 
			
		||||
  Am43Packet *get_open_request();
 | 
			
		||||
  Am43Packet *get_close_request();
 | 
			
		||||
  Am43Packet *get_stop_request();
 | 
			
		||||
  Am43Packet *get_set_position_request(uint8_t position);
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  void checksum_();
 | 
			
		||||
  Am43Packet *encode_(uint8_t command, uint8_t *data, uint8_t length);
 | 
			
		||||
  Am43Packet packet_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class Am43Decoder {
 | 
			
		||||
 public:
 | 
			
		||||
  void decode(const uint8_t *data, uint16_t length);
 | 
			
		||||
  bool has_battery_level() { return this->has_battery_level_; }
 | 
			
		||||
  bool has_light_level() { return this->has_light_level_; }
 | 
			
		||||
  bool has_set_position_response() { return this->has_set_position_response_; }
 | 
			
		||||
  bool has_set_state_response() { return this->has_set_state_response_; }
 | 
			
		||||
  bool has_position() { return this->has_position_; }
 | 
			
		||||
  bool has_pin_response() { return this->has_pin_response_; }
 | 
			
		||||
 | 
			
		||||
  union {
 | 
			
		||||
    uint8_t position_;
 | 
			
		||||
    uint8_t battery_level_;
 | 
			
		||||
    float light_level_;
 | 
			
		||||
    uint8_t set_position_ok_;
 | 
			
		||||
    uint8_t set_state_ok_;
 | 
			
		||||
    uint8_t pin_ok_;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool has_battery_level_;
 | 
			
		||||
  bool has_light_level_;
 | 
			
		||||
  bool has_set_position_response_;
 | 
			
		||||
  bool has_set_state_response_;
 | 
			
		||||
  bool has_position_;
 | 
			
		||||
  bool has_pin_response_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace am43
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
							
								
								
									
										36
									
								
								esphome/components/am43/cover/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								esphome/components/am43/cover/__init__.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
import esphome.codegen as cg
 | 
			
		||||
import esphome.config_validation as cv
 | 
			
		||||
from esphome.components import cover, ble_client
 | 
			
		||||
from esphome.const import CONF_ID, CONF_PIN
 | 
			
		||||
 | 
			
		||||
CODEOWNERS = ["@buxtronix"]
 | 
			
		||||
DEPENDENCIES = ["ble_client"]
 | 
			
		||||
AUTO_LOAD = ["am43"]
 | 
			
		||||
 | 
			
		||||
CONF_INVERT_POSITION = "invert_position"
 | 
			
		||||
 | 
			
		||||
am43_ns = cg.esphome_ns.namespace("am43")
 | 
			
		||||
Am43Component = am43_ns.class_(
 | 
			
		||||
    "Am43Component", cover.Cover, ble_client.BLEClientNode, cg.Component
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
CONFIG_SCHEMA = (
 | 
			
		||||
    cover.COVER_SCHEMA.extend(
 | 
			
		||||
        {
 | 
			
		||||
            cv.GenerateID(): cv.declare_id(Am43Component),
 | 
			
		||||
            cv.Optional(CONF_PIN, default=8888): cv.int_range(min=0, max=0xFFFF),
 | 
			
		||||
            cv.Optional(CONF_INVERT_POSITION, default=False): cv.boolean,
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
    .extend(ble_client.BLE_CLIENT_SCHEMA)
 | 
			
		||||
    .extend(cv.COMPONENT_SCHEMA)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def to_code(config):
 | 
			
		||||
    var = cg.new_Pvariable(config[CONF_ID])
 | 
			
		||||
    cg.add(var.set_pin(config[CONF_PIN]))
 | 
			
		||||
    cg.add(var.set_invert_position(config[CONF_INVERT_POSITION]))
 | 
			
		||||
    yield cg.register_component(var, config)
 | 
			
		||||
    yield cover.register_cover(var, config)
 | 
			
		||||
    yield ble_client.register_ble_node(var, config)
 | 
			
		||||
							
								
								
									
										149
									
								
								esphome/components/am43/cover/am43_cover.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								esphome/components/am43/cover/am43_cover.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,149 @@
 | 
			
		||||
#include "am43_cover.h"
 | 
			
		||||
#include "esphome/core/log.h"
 | 
			
		||||
 | 
			
		||||
#ifdef ARDUINO_ARCH_ESP32
 | 
			
		||||
 | 
			
		||||
namespace esphome {
 | 
			
		||||
namespace am43 {
 | 
			
		||||
 | 
			
		||||
static const char *TAG = "am43_cover";
 | 
			
		||||
 | 
			
		||||
using namespace esphome::cover;
 | 
			
		||||
 | 
			
		||||
void Am43Component::dump_config() {
 | 
			
		||||
  LOG_COVER("", "AM43 Cover", this);
 | 
			
		||||
  ESP_LOGCONFIG(TAG, "  Device Pin: %d", this->pin_);
 | 
			
		||||
  ESP_LOGCONFIG(TAG, "  Invert Position: %d", (int) this->invert_position_);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Am43Component::setup() {
 | 
			
		||||
  this->position = COVER_OPEN;
 | 
			
		||||
  this->encoder_ = new Am43Encoder();
 | 
			
		||||
  this->decoder_ = new Am43Decoder();
 | 
			
		||||
  this->logged_in_ = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Am43Component::loop() {
 | 
			
		||||
  if (this->node_state == espbt::ClientState::Established && !this->logged_in_) {
 | 
			
		||||
    auto packet = this->encoder_->get_send_pin_request(this->pin_);
 | 
			
		||||
    auto status =
 | 
			
		||||
        esp_ble_gattc_write_char(this->parent_->gattc_if, this->parent_->conn_id, this->char_handle_, packet->length,
 | 
			
		||||
                                 packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
 | 
			
		||||
    ESP_LOGI(TAG, "[%s] Logging into AM43", this->get_name().c_str());
 | 
			
		||||
    if (status)
 | 
			
		||||
      ESP_LOGW(TAG, "[%s] Error writing set_pin to device, error = %d", this->get_name().c_str(), status);
 | 
			
		||||
    else
 | 
			
		||||
      this->logged_in_ = true;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CoverTraits Am43Component::get_traits() {
 | 
			
		||||
  auto traits = CoverTraits();
 | 
			
		||||
  traits.set_supports_position(true);
 | 
			
		||||
  traits.set_supports_tilt(false);
 | 
			
		||||
  traits.set_is_assumed_state(false);
 | 
			
		||||
  return traits;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Am43Component::control(const CoverCall &call) {
 | 
			
		||||
  if (this->node_state != espbt::ClientState::Established) {
 | 
			
		||||
    ESP_LOGW(TAG, "[%s] Cannot send cover control, not connected", this->get_name().c_str());
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  if (call.get_stop()) {
 | 
			
		||||
    auto packet = this->encoder_->get_stop_request();
 | 
			
		||||
    auto status =
 | 
			
		||||
        esp_ble_gattc_write_char(this->parent_->gattc_if, this->parent_->conn_id, this->char_handle_, packet->length,
 | 
			
		||||
                                 packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
 | 
			
		||||
    if (status)
 | 
			
		||||
      ESP_LOGW(TAG, "[%s] Error writing stop command to device, error = %d", this->get_name().c_str(), status);
 | 
			
		||||
  }
 | 
			
		||||
  if (call.get_position().has_value()) {
 | 
			
		||||
    auto pos = *call.get_position();
 | 
			
		||||
 | 
			
		||||
    if (this->invert_position_)
 | 
			
		||||
      pos = 1 - pos;
 | 
			
		||||
    auto packet = this->encoder_->get_set_position_request(100 - (uint8_t)(pos * 100));
 | 
			
		||||
    auto status =
 | 
			
		||||
        esp_ble_gattc_write_char(this->parent_->gattc_if, this->parent_->conn_id, this->char_handle_, packet->length,
 | 
			
		||||
                                 packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
 | 
			
		||||
    if (status)
 | 
			
		||||
      ESP_LOGW(TAG, "[%s] Error writing set_position command to device, error = %d", this->get_name().c_str(), status);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Am43Component::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
 | 
			
		||||
                                        esp_ble_gattc_cb_param_t *param) {
 | 
			
		||||
  switch (event) {
 | 
			
		||||
    case ESP_GATTC_DISCONNECT_EVT: {
 | 
			
		||||
      this->logged_in_ = false;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case ESP_GATTC_SEARCH_CMPL_EVT: {
 | 
			
		||||
      auto chr = this->parent_->get_characteristic(AM43_SERVICE_UUID, AM43_CHARACTERISTIC_UUID);
 | 
			
		||||
      if (chr == nullptr) {
 | 
			
		||||
        if (this->parent_->get_characteristic(AM43_TUYA_SERVICE_UUID, AM43_TUYA_CHARACTERISTIC_UUID) != nullptr) {
 | 
			
		||||
          ESP_LOGE(TAG, "[%s] Detected a Tuya AM43 which is not supported, sorry.", this->get_name().c_str());
 | 
			
		||||
        } else {
 | 
			
		||||
          ESP_LOGE(TAG, "[%s] No control service found at device, not an AM43..?", this->get_name().c_str());
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      this->char_handle_ = chr->handle;
 | 
			
		||||
 | 
			
		||||
      auto status = esp_ble_gattc_register_for_notify(this->parent_->gattc_if, this->parent_->remote_bda, chr->handle);
 | 
			
		||||
      if (status) {
 | 
			
		||||
        ESP_LOGW(TAG, "[%s] esp_ble_gattc_register_for_notify failed, status=%d", this->get_name().c_str(), status);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
 | 
			
		||||
      this->node_state = espbt::ClientState::Established;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case ESP_GATTC_NOTIFY_EVT: {
 | 
			
		||||
      if (param->notify.handle != this->char_handle_)
 | 
			
		||||
        break;
 | 
			
		||||
      this->decoder_->decode(param->notify.value, param->notify.value_len);
 | 
			
		||||
 | 
			
		||||
      if (this->decoder_->has_position()) {
 | 
			
		||||
        this->position = ((float) this->decoder_->position_ / 100.0);
 | 
			
		||||
        if (!this->invert_position_)
 | 
			
		||||
          this->position = 1 - this->position;
 | 
			
		||||
        if (this->position > 0.97)
 | 
			
		||||
          this->position = 1.0;
 | 
			
		||||
        if (this->position < 0.02)
 | 
			
		||||
          this->position = 0.0;
 | 
			
		||||
        this->publish_state();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (this->decoder_->has_pin_response()) {
 | 
			
		||||
        if (this->decoder_->pin_ok_) {
 | 
			
		||||
          ESP_LOGI(TAG, "[%s] AM43 pin accepted.", this->get_name().c_str());
 | 
			
		||||
          auto packet = this->encoder_->get_position_request();
 | 
			
		||||
          auto status = esp_ble_gattc_write_char(this->parent_->gattc_if, this->parent_->conn_id, this->char_handle_,
 | 
			
		||||
                                                 packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP,
 | 
			
		||||
                                                 ESP_GATT_AUTH_REQ_NONE);
 | 
			
		||||
          if (status)
 | 
			
		||||
            ESP_LOGW(TAG, "[%s] Error writing set_position to device, error = %d", this->get_name().c_str(), status);
 | 
			
		||||
        } else {
 | 
			
		||||
          ESP_LOGW(TAG, "[%s] AM43 pin rejected!", this->get_name().c_str());
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (this->decoder_->has_set_position_response() && !this->decoder_->set_position_ok_)
 | 
			
		||||
        ESP_LOGW(TAG, "[%s] Got nack after sending set_position. Bad pin?", this->get_name().c_str());
 | 
			
		||||
 | 
			
		||||
      if (this->decoder_->has_set_state_response() && !this->decoder_->set_state_ok_)
 | 
			
		||||
        ESP_LOGW(TAG, "[%s] Got nack after sending set_state. Bad pin?", this->get_name().c_str());
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace am43
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										45
									
								
								esphome/components/am43/cover/am43_cover.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								esphome/components/am43/cover/am43_cover.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "esphome/core/component.h"
 | 
			
		||||
#include "esphome/components/ble_client/ble_client.h"
 | 
			
		||||
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
 | 
			
		||||
#include "esphome/components/cover/cover.h"
 | 
			
		||||
#include "esphome/components/am43/am43_base.h"
 | 
			
		||||
 | 
			
		||||
#ifdef ARDUINO_ARCH_ESP32
 | 
			
		||||
 | 
			
		||||
#include <esp_gattc_api.h>
 | 
			
		||||
 | 
			
		||||
namespace esphome {
 | 
			
		||||
namespace am43 {
 | 
			
		||||
 | 
			
		||||
namespace espbt = esphome::esp32_ble_tracker;
 | 
			
		||||
 | 
			
		||||
class Am43Component : public cover::Cover, public esphome::ble_client::BLEClientNode, public Component {
 | 
			
		||||
 public:
 | 
			
		||||
  void setup() override;
 | 
			
		||||
  void loop() override;
 | 
			
		||||
  void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
 | 
			
		||||
                           esp_ble_gattc_cb_param_t *param) override;
 | 
			
		||||
  void dump_config() override;
 | 
			
		||||
  float get_setup_priority() const override { return setup_priority::DATA; }
 | 
			
		||||
  cover::CoverTraits get_traits() override;
 | 
			
		||||
  void set_pin(uint16_t pin) { this->pin_ = pin; }
 | 
			
		||||
  void set_invert_position(bool invert_position) { this->invert_position_ = invert_position; }
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  void control(const cover::CoverCall &call) override;
 | 
			
		||||
  uint16_t char_handle_;
 | 
			
		||||
  uint16_t pin_;
 | 
			
		||||
  bool invert_position_;
 | 
			
		||||
  Am43Encoder *encoder_;
 | 
			
		||||
  Am43Decoder *decoder_;
 | 
			
		||||
  bool logged_in_;
 | 
			
		||||
 | 
			
		||||
  float position_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace am43
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										46
									
								
								esphome/components/am43/sensor.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								esphome/components/am43/sensor.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
import esphome.codegen as cg
 | 
			
		||||
import esphome.config_validation as cv
 | 
			
		||||
from esphome.components import sensor, ble_client
 | 
			
		||||
from esphome.const import (
 | 
			
		||||
    CONF_ID,
 | 
			
		||||
    CONF_BATTERY_LEVEL,
 | 
			
		||||
    ICON_BATTERY,
 | 
			
		||||
    CONF_ILLUMINANCE,
 | 
			
		||||
    ICON_BRIGHTNESS_5,
 | 
			
		||||
    UNIT_PERCENT,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
CODEOWNERS = ["@buxtronix"]
 | 
			
		||||
 | 
			
		||||
am43_ns = cg.esphome_ns.namespace("am43")
 | 
			
		||||
Am43 = am43_ns.class_("Am43", ble_client.BLEClientNode, cg.PollingComponent)
 | 
			
		||||
 | 
			
		||||
CONFIG_SCHEMA = (
 | 
			
		||||
    cv.Schema(
 | 
			
		||||
        {
 | 
			
		||||
            cv.GenerateID(): cv.declare_id(Am43),
 | 
			
		||||
            cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema(
 | 
			
		||||
                UNIT_PERCENT, ICON_BATTERY, 0
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_ILLUMINANCE): sensor.sensor_schema(
 | 
			
		||||
                UNIT_PERCENT, ICON_BRIGHTNESS_5, 0
 | 
			
		||||
            ),
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
    .extend(ble_client.BLE_CLIENT_SCHEMA)
 | 
			
		||||
    .extend(cv.polling_component_schema("120s"))
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def to_code(config):
 | 
			
		||||
    var = cg.new_Pvariable(config[CONF_ID])
 | 
			
		||||
    yield cg.register_component(var, config)
 | 
			
		||||
    yield ble_client.register_ble_node(var, config)
 | 
			
		||||
 | 
			
		||||
    if CONF_BATTERY_LEVEL in config:
 | 
			
		||||
        sens = yield sensor.new_sensor(config[CONF_BATTERY_LEVEL])
 | 
			
		||||
        cg.add(var.set_battery(sens))
 | 
			
		||||
 | 
			
		||||
    if CONF_ILLUMINANCE in config:
 | 
			
		||||
        sens = yield sensor.new_sensor(config[CONF_ILLUMINANCE])
 | 
			
		||||
        cg.add(var.set_illuminance(sens))
 | 
			
		||||
@@ -90,19 +90,24 @@ void Anova::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_
 | 
			
		||||
      if (this->codec_->has_running()) {
 | 
			
		||||
        this->mode = this->codec_->running_ ? climate::CLIMATE_MODE_HEAT : climate::CLIMATE_MODE_OFF;
 | 
			
		||||
      }
 | 
			
		||||
      if (this->codec_->has_unit()) {
 | 
			
		||||
        this->fahrenheit_ = (this->codec_->unit_ == 'f');
 | 
			
		||||
        ESP_LOGD(TAG, "Anova units is %s", this->fahrenheit_ ? "fahrenheit" : "celcius");
 | 
			
		||||
        this->current_request_++;
 | 
			
		||||
      }
 | 
			
		||||
      this->publish_state();
 | 
			
		||||
 | 
			
		||||
      if (this->current_request_ > 0) {
 | 
			
		||||
      if (this->current_request_ > 1) {
 | 
			
		||||
        AnovaPacket *pkt = nullptr;
 | 
			
		||||
        switch (this->current_request_++) {
 | 
			
		||||
          case 1:
 | 
			
		||||
          case 2:
 | 
			
		||||
            pkt = this->codec_->get_read_target_temp_request();
 | 
			
		||||
            break;
 | 
			
		||||
          case 2:
 | 
			
		||||
          case 3:
 | 
			
		||||
            pkt = this->codec_->get_read_current_temp_request();
 | 
			
		||||
            break;
 | 
			
		||||
          default:
 | 
			
		||||
            this->current_request_ = 0;
 | 
			
		||||
            this->current_request_ = 1;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        if (pkt != nullptr) {
 | 
			
		||||
@@ -121,12 +126,16 @@ void Anova::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Anova::set_unit_of_measurement(const char *unit) { this->fahrenheit_ = !strncmp(unit, "f", 1); }
 | 
			
		||||
 | 
			
		||||
void Anova::update() {
 | 
			
		||||
  if (this->node_state != espbt::ClientState::Established)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  if (this->current_request_ == 0) {
 | 
			
		||||
  if (this->current_request_ < 2) {
 | 
			
		||||
    auto pkt = this->codec_->get_read_device_status_request();
 | 
			
		||||
    if (this->current_request_ == 0)
 | 
			
		||||
      auto pkt = this->codec_->get_set_unit_request(this->fahrenheit_ ? 'f' : 'c');
 | 
			
		||||
    auto status = esp_ble_gattc_write_char(this->parent_->gattc_if, this->parent_->conn_id, this->char_handle_,
 | 
			
		||||
                                           pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
 | 
			
		||||
    if (status)
 | 
			
		||||
 
 | 
			
		||||
@@ -36,12 +36,14 @@ class Anova : public climate::Climate, public esphome::ble_client::BLEClientNode
 | 
			
		||||
    traits.set_visual_temperature_step(0.1);
 | 
			
		||||
    return traits;
 | 
			
		||||
  }
 | 
			
		||||
  void set_unit_of_measurement(const char *);
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  AnovaCodec *codec_;
 | 
			
		||||
  void control(const climate::ClimateCall &call) override;
 | 
			
		||||
  uint16_t char_handle_;
 | 
			
		||||
  uint8_t current_request_;
 | 
			
		||||
  bool fahrenheit_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace anova
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,10 @@
 | 
			
		||||
namespace esphome {
 | 
			
		||||
namespace anova {
 | 
			
		||||
 | 
			
		||||
float ftoc(float f) { return (f - 32.0) * (5.0f / 9.0f); }
 | 
			
		||||
 | 
			
		||||
float ctof(float c) { return (c * 9.0f / 5.0f) + 32.0; }
 | 
			
		||||
 | 
			
		||||
AnovaPacket *AnovaCodec::clean_packet_() {
 | 
			
		||||
  this->packet_.length = strlen((char *) this->packet_.data);
 | 
			
		||||
  this->packet_.data[this->packet_.length] = '\0';
 | 
			
		||||
@@ -42,6 +46,8 @@ AnovaPacket *AnovaCodec::get_read_data_request() {
 | 
			
		||||
 | 
			
		||||
AnovaPacket *AnovaCodec::get_set_target_temp_request(float temperature) {
 | 
			
		||||
  this->current_query_ = SET_TARGET_TEMPERATURE;
 | 
			
		||||
  if (this->fahrenheit_)
 | 
			
		||||
    temperature = ctof(temperature);
 | 
			
		||||
  sprintf((char *) this->packet_.data, CMD_SET_TARGET_TEMP, temperature);
 | 
			
		||||
  return this->clean_packet_();
 | 
			
		||||
}
 | 
			
		||||
@@ -67,7 +73,6 @@ AnovaPacket *AnovaCodec::get_stop_request() {
 | 
			
		||||
void AnovaCodec::decode(const uint8_t *data, uint16_t length) {
 | 
			
		||||
  memset(this->buf_, 0, 32);
 | 
			
		||||
  strncpy(this->buf_, (char *) data, length);
 | 
			
		||||
  ESP_LOGV("anova", "Received: %s\n", this->buf_);
 | 
			
		||||
  this->has_target_temp_ = this->has_current_temp_ = this->has_unit_ = this->has_running_ = false;
 | 
			
		||||
  switch (this->current_query_) {
 | 
			
		||||
    case READ_DEVICE_STATUS: {
 | 
			
		||||
@@ -97,19 +102,32 @@ void AnovaCodec::decode(const uint8_t *data, uint16_t length) {
 | 
			
		||||
    }
 | 
			
		||||
    case READ_TARGET_TEMPERATURE: {
 | 
			
		||||
      this->target_temp_ = strtof(this->buf_, nullptr);
 | 
			
		||||
      if (this->fahrenheit_)
 | 
			
		||||
        this->target_temp_ = ftoc(this->target_temp_);
 | 
			
		||||
      this->has_target_temp_ = true;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case SET_TARGET_TEMPERATURE: {
 | 
			
		||||
      this->target_temp_ = strtof(this->buf_, nullptr);
 | 
			
		||||
      if (this->fahrenheit_)
 | 
			
		||||
        this->target_temp_ = ftoc(this->target_temp_);
 | 
			
		||||
      this->has_target_temp_ = true;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case READ_CURRENT_TEMPERATURE: {
 | 
			
		||||
      this->current_temp_ = strtof(this->buf_, nullptr);
 | 
			
		||||
      if (this->fahrenheit_)
 | 
			
		||||
        this->current_temp_ = ftoc(this->current_temp_);
 | 
			
		||||
      this->has_current_temp_ = true;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case SET_UNIT:
 | 
			
		||||
    case READ_UNIT: {
 | 
			
		||||
      this->unit_ = this->buf_[0];
 | 
			
		||||
      this->fahrenheit_ = this->buf_[0] == 'f';
 | 
			
		||||
      this->has_unit_ = true;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -71,6 +71,7 @@ class AnovaCodec {
 | 
			
		||||
  bool has_unit_;
 | 
			
		||||
  bool has_running_;
 | 
			
		||||
  char buf_[32];
 | 
			
		||||
  bool fahrenheit_;
 | 
			
		||||
 | 
			
		||||
  CurrentQuery current_query_;
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,12 @@
 | 
			
		||||
import esphome.codegen as cg
 | 
			
		||||
import esphome.config_validation as cv
 | 
			
		||||
from esphome.components import climate, ble_client
 | 
			
		||||
from esphome.const import CONF_ID
 | 
			
		||||
from esphome.const import CONF_ID, CONF_UNIT_OF_MEASUREMENT
 | 
			
		||||
 | 
			
		||||
UNITS = {
 | 
			
		||||
    "f": "f",
 | 
			
		||||
    "c": "c",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CODEOWNERS = ["@buxtronix"]
 | 
			
		||||
DEPENDENCIES = ["ble_client"]
 | 
			
		||||
@@ -12,14 +17,20 @@ Anova = anova_ns.class_(
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
CONFIG_SCHEMA = (
 | 
			
		||||
    climate.CLIMATE_SCHEMA.extend({cv.GenerateID(): cv.declare_id(Anova)})
 | 
			
		||||
    climate.CLIMATE_SCHEMA.extend(
 | 
			
		||||
        {
 | 
			
		||||
            cv.GenerateID(): cv.declare_id(Anova),
 | 
			
		||||
            cv.Required(CONF_UNIT_OF_MEASUREMENT): cv.enum(UNITS),
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
    .extend(ble_client.BLE_CLIENT_SCHEMA)
 | 
			
		||||
    .extend(cv.polling_component_schema("60s"))
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def to_code(config):
 | 
			
		||||
async def to_code(config):
 | 
			
		||||
    var = cg.new_Pvariable(config[CONF_ID])
 | 
			
		||||
    yield cg.register_component(var, config)
 | 
			
		||||
    yield climate.register_climate(var, config)
 | 
			
		||||
    yield ble_client.register_ble_node(var, config)
 | 
			
		||||
    await cg.register_component(var, config)
 | 
			
		||||
    await climate.register_climate(var, config)
 | 
			
		||||
    await ble_client.register_ble_node(var, config)
 | 
			
		||||
    cg.add(var.set_unit_of_measurement(config[CONF_UNIT_OF_MEASUREMENT]))
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,6 @@ import esphome.config_validation as cv
 | 
			
		||||
from esphome.components import sensor
 | 
			
		||||
from esphome.const import (
 | 
			
		||||
    CONF_TYPE,
 | 
			
		||||
    DEVICE_CLASS_EMPTY,
 | 
			
		||||
    STATE_CLASS_MEASUREMENT,
 | 
			
		||||
    UNIT_PERCENT,
 | 
			
		||||
    ICON_LIGHTBULB,
 | 
			
		||||
@@ -21,7 +20,10 @@ TYPES = {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CONFIG_SCHEMA = sensor.sensor_schema(
 | 
			
		||||
    UNIT_PERCENT, ICON_LIGHTBULB, 1, DEVICE_CLASS_EMPTY, STATE_CLASS_MEASUREMENT
 | 
			
		||||
    unit_of_measurement=UNIT_PERCENT,
 | 
			
		||||
    icon=ICON_LIGHTBULB,
 | 
			
		||||
    accuracy_decimals=1,
 | 
			
		||||
    state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
).extend(
 | 
			
		||||
    {
 | 
			
		||||
        cv.Required(CONF_TYPE): cv.one_of(*TYPES, upper=True),
 | 
			
		||||
 
 | 
			
		||||
@@ -39,6 +39,7 @@ service APIConnection {
 | 
			
		||||
  rpc camera_image (CameraImageRequest) returns (void) {}
 | 
			
		||||
  rpc climate_command (ClimateCommandRequest) returns (void) {}
 | 
			
		||||
  rpc number_command (NumberCommandRequest) returns (void) {}
 | 
			
		||||
  rpc select_command (SelectCommandRequest) returns (void) {}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -213,6 +214,7 @@ message ListEntitiesBinarySensorResponse {
 | 
			
		||||
 | 
			
		||||
  string device_class = 5;
 | 
			
		||||
  bool is_status_binary_sensor = 6;
 | 
			
		||||
  bool disabled_by_default = 7;
 | 
			
		||||
}
 | 
			
		||||
message BinarySensorStateResponse {
 | 
			
		||||
  option (id) = 21;
 | 
			
		||||
@@ -242,6 +244,7 @@ message ListEntitiesCoverResponse {
 | 
			
		||||
  bool supports_position = 6;
 | 
			
		||||
  bool supports_tilt = 7;
 | 
			
		||||
  string device_class = 8;
 | 
			
		||||
  bool disabled_by_default = 9;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum LegacyCoverState {
 | 
			
		||||
@@ -309,6 +312,7 @@ message ListEntitiesFanResponse {
 | 
			
		||||
  bool supports_speed = 6;
 | 
			
		||||
  bool supports_direction = 7;
 | 
			
		||||
  int32 supported_speed_count = 8;
 | 
			
		||||
  bool disabled_by_default = 9;
 | 
			
		||||
}
 | 
			
		||||
enum FanSpeed {
 | 
			
		||||
  FAN_SPEED_LOW = 0;
 | 
			
		||||
@@ -352,6 +356,18 @@ message FanCommandRequest {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ==================== LIGHT ====================
 | 
			
		||||
enum ColorMode {
 | 
			
		||||
  COLOR_MODE_UNKNOWN = 0;
 | 
			
		||||
  COLOR_MODE_ON_OFF = 1;
 | 
			
		||||
  COLOR_MODE_BRIGHTNESS = 2;
 | 
			
		||||
  COLOR_MODE_WHITE = 7;
 | 
			
		||||
  COLOR_MODE_COLOR_TEMPERATURE = 11;
 | 
			
		||||
  COLOR_MODE_COLD_WARM_WHITE = 19;
 | 
			
		||||
  COLOR_MODE_RGB = 35;
 | 
			
		||||
  COLOR_MODE_RGB_WHITE = 39;
 | 
			
		||||
  COLOR_MODE_RGB_COLOR_TEMPERATURE = 47;
 | 
			
		||||
  COLOR_MODE_RGB_COLD_WARM_WHITE = 51;
 | 
			
		||||
}
 | 
			
		||||
message ListEntitiesLightResponse {
 | 
			
		||||
  option (id) = 15;
 | 
			
		||||
  option (source) = SOURCE_SERVER;
 | 
			
		||||
@@ -362,13 +378,16 @@ message ListEntitiesLightResponse {
 | 
			
		||||
  string name = 3;
 | 
			
		||||
  string unique_id = 4;
 | 
			
		||||
 | 
			
		||||
  bool supports_brightness = 5;
 | 
			
		||||
  bool supports_rgb = 6;
 | 
			
		||||
  bool supports_white_value = 7;
 | 
			
		||||
  bool supports_color_temperature = 8;
 | 
			
		||||
  repeated ColorMode supported_color_modes = 12;
 | 
			
		||||
  // next four supports_* are for legacy clients, newer clients should use color modes
 | 
			
		||||
  bool legacy_supports_brightness = 5 [deprecated=true];
 | 
			
		||||
  bool legacy_supports_rgb = 6 [deprecated=true];
 | 
			
		||||
  bool legacy_supports_white_value = 7 [deprecated=true];
 | 
			
		||||
  bool legacy_supports_color_temperature = 8 [deprecated=true];
 | 
			
		||||
  float min_mireds = 9;
 | 
			
		||||
  float max_mireds = 10;
 | 
			
		||||
  repeated string effects = 11;
 | 
			
		||||
  bool disabled_by_default = 13;
 | 
			
		||||
}
 | 
			
		||||
message LightStateResponse {
 | 
			
		||||
  option (id) = 24;
 | 
			
		||||
@@ -379,12 +398,15 @@ message LightStateResponse {
 | 
			
		||||
  fixed32 key = 1;
 | 
			
		||||
  bool state = 2;
 | 
			
		||||
  float brightness = 3;
 | 
			
		||||
  ColorMode color_mode = 11;
 | 
			
		||||
  float color_brightness = 10;
 | 
			
		||||
  float red = 4;
 | 
			
		||||
  float green = 5;
 | 
			
		||||
  float blue = 6;
 | 
			
		||||
  float white = 7;
 | 
			
		||||
  float color_temperature = 8;
 | 
			
		||||
  float cold_white = 12;
 | 
			
		||||
  float warm_white = 13;
 | 
			
		||||
  string effect = 9;
 | 
			
		||||
}
 | 
			
		||||
message LightCommandRequest {
 | 
			
		||||
@@ -398,6 +420,8 @@ message LightCommandRequest {
 | 
			
		||||
  bool state = 3;
 | 
			
		||||
  bool has_brightness = 4;
 | 
			
		||||
  float brightness = 5;
 | 
			
		||||
  bool has_color_mode = 22;
 | 
			
		||||
  ColorMode color_mode = 23;
 | 
			
		||||
  bool has_color_brightness = 20;
 | 
			
		||||
  float color_brightness = 21;
 | 
			
		||||
  bool has_rgb = 6;
 | 
			
		||||
@@ -408,6 +432,10 @@ message LightCommandRequest {
 | 
			
		||||
  float white = 11;
 | 
			
		||||
  bool has_color_temperature = 12;
 | 
			
		||||
  float color_temperature = 13;
 | 
			
		||||
  bool has_cold_white = 24;
 | 
			
		||||
  float cold_white = 25;
 | 
			
		||||
  bool has_warm_white = 26;
 | 
			
		||||
  float warm_white = 27;
 | 
			
		||||
  bool has_transition_length = 14;
 | 
			
		||||
  uint32 transition_length = 15;
 | 
			
		||||
  bool has_flash_length = 16;
 | 
			
		||||
@@ -445,6 +473,7 @@ message ListEntitiesSensorResponse {
 | 
			
		||||
  string device_class = 9;
 | 
			
		||||
  SensorStateClass state_class = 10;
 | 
			
		||||
  SensorLastResetType last_reset_type = 11;
 | 
			
		||||
  bool disabled_by_default = 12;
 | 
			
		||||
}
 | 
			
		||||
message SensorStateResponse {
 | 
			
		||||
  option (id) = 25;
 | 
			
		||||
@@ -472,6 +501,7 @@ message ListEntitiesSwitchResponse {
 | 
			
		||||
 | 
			
		||||
  string icon = 5;
 | 
			
		||||
  bool assumed_state = 6;
 | 
			
		||||
  bool disabled_by_default = 7;
 | 
			
		||||
}
 | 
			
		||||
message SwitchStateResponse {
 | 
			
		||||
  option (id) = 26;
 | 
			
		||||
@@ -504,6 +534,7 @@ message ListEntitiesTextSensorResponse {
 | 
			
		||||
  string unique_id = 4;
 | 
			
		||||
 | 
			
		||||
  string icon = 5;
 | 
			
		||||
  bool disabled_by_default = 6;
 | 
			
		||||
}
 | 
			
		||||
message TextSensorStateResponse {
 | 
			
		||||
  option (id) = 27;
 | 
			
		||||
@@ -524,9 +555,10 @@ enum LogLevel {
 | 
			
		||||
  LOG_LEVEL_ERROR = 1;
 | 
			
		||||
  LOG_LEVEL_WARN = 2;
 | 
			
		||||
  LOG_LEVEL_INFO = 3;
 | 
			
		||||
  LOG_LEVEL_DEBUG = 4;
 | 
			
		||||
  LOG_LEVEL_VERBOSE = 5;
 | 
			
		||||
  LOG_LEVEL_VERY_VERBOSE = 6;
 | 
			
		||||
  LOG_LEVEL_CONFIG = 4;
 | 
			
		||||
  LOG_LEVEL_DEBUG = 5;
 | 
			
		||||
  LOG_LEVEL_VERBOSE = 6;
 | 
			
		||||
  LOG_LEVEL_VERY_VERBOSE = 7;
 | 
			
		||||
}
 | 
			
		||||
message SubscribeLogsRequest {
 | 
			
		||||
  option (id) = 28;
 | 
			
		||||
@@ -541,7 +573,6 @@ message SubscribeLogsResponse {
 | 
			
		||||
  option (no_delay) = false;
 | 
			
		||||
 | 
			
		||||
  LogLevel level = 1;
 | 
			
		||||
  string tag = 2;
 | 
			
		||||
  string message = 3;
 | 
			
		||||
  bool send_failed = 4;
 | 
			
		||||
}
 | 
			
		||||
@@ -663,6 +694,7 @@ message ListEntitiesCameraResponse {
 | 
			
		||||
  fixed32 key = 2;
 | 
			
		||||
  string name = 3;
 | 
			
		||||
  string unique_id = 4;
 | 
			
		||||
  bool disabled_by_default = 5;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message CameraImageResponse {
 | 
			
		||||
@@ -755,6 +787,7 @@ message ListEntitiesClimateResponse {
 | 
			
		||||
  repeated string supported_custom_fan_modes = 15;
 | 
			
		||||
  repeated ClimatePreset supported_presets = 16;
 | 
			
		||||
  repeated string supported_custom_presets = 17;
 | 
			
		||||
  bool disabled_by_default = 18;
 | 
			
		||||
}
 | 
			
		||||
message ClimateStateResponse {
 | 
			
		||||
  option (id) = 47;
 | 
			
		||||
@@ -822,6 +855,7 @@ message ListEntitiesNumberResponse {
 | 
			
		||||
  float min_value = 6;
 | 
			
		||||
  float max_value = 7;
 | 
			
		||||
  float step = 8;
 | 
			
		||||
  bool disabled_by_default = 9;
 | 
			
		||||
}
 | 
			
		||||
message NumberStateResponse {
 | 
			
		||||
  option (id) = 50;
 | 
			
		||||
@@ -844,3 +878,40 @@ message NumberCommandRequest {
 | 
			
		||||
  fixed32 key = 1;
 | 
			
		||||
  float state = 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ==================== SELECT ====================
 | 
			
		||||
message ListEntitiesSelectResponse {
 | 
			
		||||
  option (id) = 52;
 | 
			
		||||
  option (source) = SOURCE_SERVER;
 | 
			
		||||
  option (ifdef) = "USE_SELECT";
 | 
			
		||||
 | 
			
		||||
  string object_id = 1;
 | 
			
		||||
  fixed32 key = 2;
 | 
			
		||||
  string name = 3;
 | 
			
		||||
  string unique_id = 4;
 | 
			
		||||
 | 
			
		||||
  string icon = 5;
 | 
			
		||||
  repeated string options = 6;
 | 
			
		||||
  bool disabled_by_default = 7;
 | 
			
		||||
}
 | 
			
		||||
message SelectStateResponse {
 | 
			
		||||
  option (id) = 53;
 | 
			
		||||
  option (source) = SOURCE_SERVER;
 | 
			
		||||
  option (ifdef) = "USE_SELECT";
 | 
			
		||||
  option (no_delay) = true;
 | 
			
		||||
 | 
			
		||||
  fixed32 key = 1;
 | 
			
		||||
  string state = 2;
 | 
			
		||||
  // If the select does not have a valid state yet.
 | 
			
		||||
  // Equivalent to `!obj->has_state()` - inverse logic to make state packets smaller
 | 
			
		||||
  bool missing_state = 3;
 | 
			
		||||
}
 | 
			
		||||
message SelectCommandRequest {
 | 
			
		||||
  option (id) = 54;
 | 
			
		||||
  option (source) = SOURCE_CLIENT;
 | 
			
		||||
  option (ifdef) = "USE_SELECT";
 | 
			
		||||
  option (no_delay) = true;
 | 
			
		||||
 | 
			
		||||
  fixed32 key = 1;
 | 
			
		||||
  string state = 2;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -176,6 +176,7 @@ bool APIConnection::send_binary_sensor_info(binary_sensor::BinarySensor *binary_
 | 
			
		||||
  msg.unique_id = get_default_unique_id("binary_sensor", binary_sensor);
 | 
			
		||||
  msg.device_class = binary_sensor->get_device_class();
 | 
			
		||||
  msg.is_status_binary_sensor = binary_sensor->is_status_binary_sensor();
 | 
			
		||||
  msg.disabled_by_default = binary_sensor->is_disabled_by_default();
 | 
			
		||||
  return this->send_list_entities_binary_sensor_response(msg);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
@@ -207,6 +208,7 @@ bool APIConnection::send_cover_info(cover::Cover *cover) {
 | 
			
		||||
  msg.supports_position = traits.get_supports_position();
 | 
			
		||||
  msg.supports_tilt = traits.get_supports_tilt();
 | 
			
		||||
  msg.device_class = cover->get_device_class();
 | 
			
		||||
  msg.disabled_by_default = cover->is_disabled_by_default();
 | 
			
		||||
  return this->send_list_entities_cover_response(msg);
 | 
			
		||||
}
 | 
			
		||||
void APIConnection::cover_command(const CoverCommandRequest &msg) {
 | 
			
		||||
@@ -268,6 +270,7 @@ bool APIConnection::send_fan_info(fan::FanState *fan) {
 | 
			
		||||
  msg.supports_speed = traits.supports_speed();
 | 
			
		||||
  msg.supports_direction = traits.supports_direction();
 | 
			
		||||
  msg.supported_speed_count = traits.supported_speed_count();
 | 
			
		||||
  msg.disabled_by_default = fan->is_disabled_by_default();
 | 
			
		||||
  return this->send_list_entities_fan_response(msg);
 | 
			
		||||
}
 | 
			
		||||
void APIConnection::fan_command(const FanCommandRequest &msg) {
 | 
			
		||||
@@ -301,22 +304,21 @@ bool APIConnection::send_light_state(light::LightState *light) {
 | 
			
		||||
 | 
			
		||||
  auto traits = light->get_traits();
 | 
			
		||||
  auto values = light->remote_values;
 | 
			
		||||
  auto color_mode = values.get_color_mode();
 | 
			
		||||
  LightStateResponse resp{};
 | 
			
		||||
 | 
			
		||||
  resp.key = light->get_object_id_hash();
 | 
			
		||||
  resp.state = values.is_on();
 | 
			
		||||
  if (traits.get_supports_brightness())
 | 
			
		||||
    resp.brightness = values.get_brightness();
 | 
			
		||||
  if (traits.get_supports_rgb()) {
 | 
			
		||||
    resp.color_brightness = values.get_color_brightness();
 | 
			
		||||
    resp.red = values.get_red();
 | 
			
		||||
    resp.green = values.get_green();
 | 
			
		||||
    resp.blue = values.get_blue();
 | 
			
		||||
  }
 | 
			
		||||
  if (traits.get_supports_rgb_white_value())
 | 
			
		||||
    resp.white = values.get_white();
 | 
			
		||||
  if (traits.get_supports_color_temperature())
 | 
			
		||||
    resp.color_temperature = values.get_color_temperature();
 | 
			
		||||
  resp.color_mode = static_cast<enums::ColorMode>(color_mode);
 | 
			
		||||
  resp.brightness = values.get_brightness();
 | 
			
		||||
  resp.color_brightness = values.get_color_brightness();
 | 
			
		||||
  resp.red = values.get_red();
 | 
			
		||||
  resp.green = values.get_green();
 | 
			
		||||
  resp.blue = values.get_blue();
 | 
			
		||||
  resp.white = values.get_white();
 | 
			
		||||
  resp.color_temperature = values.get_color_temperature();
 | 
			
		||||
  resp.cold_white = values.get_cold_white();
 | 
			
		||||
  resp.warm_white = values.get_warm_white();
 | 
			
		||||
  if (light->supports_effects())
 | 
			
		||||
    resp.effect = light->get_effect_name();
 | 
			
		||||
  return this->send_light_state_response(resp);
 | 
			
		||||
@@ -328,11 +330,21 @@ bool APIConnection::send_light_info(light::LightState *light) {
 | 
			
		||||
  msg.object_id = light->get_object_id();
 | 
			
		||||
  msg.name = light->get_name();
 | 
			
		||||
  msg.unique_id = get_default_unique_id("light", light);
 | 
			
		||||
  msg.supports_brightness = traits.get_supports_brightness();
 | 
			
		||||
  msg.supports_rgb = traits.get_supports_rgb();
 | 
			
		||||
  msg.supports_white_value = traits.get_supports_rgb_white_value();
 | 
			
		||||
  msg.supports_color_temperature = traits.get_supports_color_temperature();
 | 
			
		||||
  if (msg.supports_color_temperature) {
 | 
			
		||||
 | 
			
		||||
  msg.disabled_by_default = light->is_disabled_by_default();
 | 
			
		||||
 | 
			
		||||
  for (auto mode : traits.get_supported_color_modes())
 | 
			
		||||
    msg.supported_color_modes.push_back(static_cast<enums::ColorMode>(mode));
 | 
			
		||||
 | 
			
		||||
  msg.legacy_supports_brightness = traits.supports_color_capability(light::ColorCapability::BRIGHTNESS);
 | 
			
		||||
  msg.legacy_supports_rgb = traits.supports_color_capability(light::ColorCapability::RGB);
 | 
			
		||||
  msg.legacy_supports_white_value =
 | 
			
		||||
      msg.legacy_supports_rgb && (traits.supports_color_capability(light::ColorCapability::WHITE) ||
 | 
			
		||||
                                  traits.supports_color_capability(light::ColorCapability::COLD_WARM_WHITE));
 | 
			
		||||
  msg.legacy_supports_color_temperature = traits.supports_color_capability(light::ColorCapability::COLOR_TEMPERATURE) ||
 | 
			
		||||
                                          traits.supports_color_capability(light::ColorCapability::COLD_WARM_WHITE);
 | 
			
		||||
 | 
			
		||||
  if (msg.legacy_supports_color_temperature) {
 | 
			
		||||
    msg.min_mireds = traits.get_min_mireds();
 | 
			
		||||
    msg.max_mireds = traits.get_max_mireds();
 | 
			
		||||
  }
 | 
			
		||||
@@ -353,6 +365,8 @@ void APIConnection::light_command(const LightCommandRequest &msg) {
 | 
			
		||||
    call.set_state(msg.state);
 | 
			
		||||
  if (msg.has_brightness)
 | 
			
		||||
    call.set_brightness(msg.brightness);
 | 
			
		||||
  if (msg.has_color_mode)
 | 
			
		||||
    call.set_color_mode(static_cast<light::ColorMode>(msg.color_mode));
 | 
			
		||||
  if (msg.has_color_brightness)
 | 
			
		||||
    call.set_color_brightness(msg.color_brightness);
 | 
			
		||||
  if (msg.has_rgb) {
 | 
			
		||||
@@ -364,6 +378,10 @@ void APIConnection::light_command(const LightCommandRequest &msg) {
 | 
			
		||||
    call.set_white(msg.white);
 | 
			
		||||
  if (msg.has_color_temperature)
 | 
			
		||||
    call.set_color_temperature(msg.color_temperature);
 | 
			
		||||
  if (msg.has_cold_white)
 | 
			
		||||
    call.set_cold_white(msg.cold_white);
 | 
			
		||||
  if (msg.has_warm_white)
 | 
			
		||||
    call.set_warm_white(msg.warm_white);
 | 
			
		||||
  if (msg.has_transition_length)
 | 
			
		||||
    call.set_transition_length(msg.transition_length);
 | 
			
		||||
  if (msg.has_flash_length)
 | 
			
		||||
@@ -400,6 +418,7 @@ bool APIConnection::send_sensor_info(sensor::Sensor *sensor) {
 | 
			
		||||
  msg.device_class = sensor->get_device_class();
 | 
			
		||||
  msg.state_class = static_cast<enums::SensorStateClass>(sensor->state_class);
 | 
			
		||||
  msg.last_reset_type = static_cast<enums::SensorLastResetType>(sensor->last_reset_type);
 | 
			
		||||
  msg.disabled_by_default = sensor->is_disabled_by_default();
 | 
			
		||||
 | 
			
		||||
  return this->send_list_entities_sensor_response(msg);
 | 
			
		||||
}
 | 
			
		||||
@@ -423,6 +442,7 @@ bool APIConnection::send_switch_info(switch_::Switch *a_switch) {
 | 
			
		||||
  msg.unique_id = get_default_unique_id("switch", a_switch);
 | 
			
		||||
  msg.icon = a_switch->get_icon();
 | 
			
		||||
  msg.assumed_state = a_switch->assumed_state();
 | 
			
		||||
  msg.disabled_by_default = a_switch->is_disabled_by_default();
 | 
			
		||||
  return this->send_list_entities_switch_response(msg);
 | 
			
		||||
}
 | 
			
		||||
void APIConnection::switch_command(const SwitchCommandRequest &msg) {
 | 
			
		||||
@@ -457,6 +477,7 @@ bool APIConnection::send_text_sensor_info(text_sensor::TextSensor *text_sensor)
 | 
			
		||||
  if (msg.unique_id.empty())
 | 
			
		||||
    msg.unique_id = get_default_unique_id("text_sensor", text_sensor);
 | 
			
		||||
  msg.icon = text_sensor->get_icon();
 | 
			
		||||
  msg.disabled_by_default = text_sensor->is_disabled_by_default();
 | 
			
		||||
  return this->send_list_entities_text_sensor_response(msg);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
@@ -500,6 +521,9 @@ bool APIConnection::send_climate_info(climate::Climate *climate) {
 | 
			
		||||
  msg.object_id = climate->get_object_id();
 | 
			
		||||
  msg.name = climate->get_name();
 | 
			
		||||
  msg.unique_id = get_default_unique_id("climate", climate);
 | 
			
		||||
 | 
			
		||||
  msg.disabled_by_default = climate->is_disabled_by_default();
 | 
			
		||||
 | 
			
		||||
  msg.supports_current_temperature = traits.get_supports_current_temperature();
 | 
			
		||||
  msg.supports_two_point_target_temperature = traits.get_supports_two_point_target_temperature();
 | 
			
		||||
 | 
			
		||||
@@ -572,6 +596,7 @@ bool APIConnection::send_number_info(number::Number *number) {
 | 
			
		||||
  msg.name = number->get_name();
 | 
			
		||||
  msg.unique_id = get_default_unique_id("number", number);
 | 
			
		||||
  msg.icon = number->traits.get_icon();
 | 
			
		||||
  msg.disabled_by_default = number->is_disabled_by_default();
 | 
			
		||||
 | 
			
		||||
  msg.min_value = number->traits.get_min_value();
 | 
			
		||||
  msg.max_value = number->traits.get_max_value();
 | 
			
		||||
@@ -590,6 +615,42 @@ void APIConnection::number_command(const NumberCommandRequest &msg) {
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_SELECT
 | 
			
		||||
bool APIConnection::send_select_state(select::Select *select, std::string state) {
 | 
			
		||||
  if (!this->state_subscription_)
 | 
			
		||||
    return false;
 | 
			
		||||
 | 
			
		||||
  SelectStateResponse resp{};
 | 
			
		||||
  resp.key = select->get_object_id_hash();
 | 
			
		||||
  resp.state = std::move(state);
 | 
			
		||||
  resp.missing_state = !select->has_state();
 | 
			
		||||
  return this->send_select_state_response(resp);
 | 
			
		||||
}
 | 
			
		||||
bool APIConnection::send_select_info(select::Select *select) {
 | 
			
		||||
  ListEntitiesSelectResponse msg;
 | 
			
		||||
  msg.key = select->get_object_id_hash();
 | 
			
		||||
  msg.object_id = select->get_object_id();
 | 
			
		||||
  msg.name = select->get_name();
 | 
			
		||||
  msg.unique_id = get_default_unique_id("select", select);
 | 
			
		||||
  msg.icon = select->traits.get_icon();
 | 
			
		||||
  msg.disabled_by_default = select->is_disabled_by_default();
 | 
			
		||||
 | 
			
		||||
  for (const auto &option : select->traits.get_options())
 | 
			
		||||
    msg.options.push_back(option);
 | 
			
		||||
 | 
			
		||||
  return this->send_list_entities_select_response(msg);
 | 
			
		||||
}
 | 
			
		||||
void APIConnection::select_command(const SelectCommandRequest &msg) {
 | 
			
		||||
  select::Select *select = App.get_select_by_key(msg.key);
 | 
			
		||||
  if (select == nullptr)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  auto call = select->make_call();
 | 
			
		||||
  call.set_option(msg.state);
 | 
			
		||||
  call.perform();
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_ESP32_CAMERA
 | 
			
		||||
void APIConnection::send_camera_state(std::shared_ptr<esp32_camera::CameraImage> image) {
 | 
			
		||||
  if (!this->state_subscription_)
 | 
			
		||||
@@ -604,6 +665,7 @@ bool APIConnection::send_camera_info(esp32_camera::ESP32Camera *camera) {
 | 
			
		||||
  msg.object_id = camera->get_object_id();
 | 
			
		||||
  msg.name = camera->get_name();
 | 
			
		||||
  msg.unique_id = get_default_unique_id("camera", camera);
 | 
			
		||||
  msg.disabled_by_default = camera->is_disabled_by_default();
 | 
			
		||||
  return this->send_list_entities_camera_response(msg);
 | 
			
		||||
}
 | 
			
		||||
void APIConnection::camera_image(const CameraImageRequest &msg) {
 | 
			
		||||
@@ -632,8 +694,6 @@ bool APIConnection::send_log_message(int level, const char *tag, const char *lin
 | 
			
		||||
  auto buffer = this->create_buffer();
 | 
			
		||||
  // LogLevel level = 1;
 | 
			
		||||
  buffer.encode_uint32(1, static_cast<uint32_t>(level));
 | 
			
		||||
  // string tag = 2;
 | 
			
		||||
  // buffer.encode_string(2, tag, strlen(tag));
 | 
			
		||||
  // string message = 3;
 | 
			
		||||
  buffer.encode_string(3, line, strlen(line));
 | 
			
		||||
  // SubscribeLogsResponse - 29
 | 
			
		||||
@@ -655,7 +715,7 @@ HelloResponse APIConnection::hello(const HelloRequest &msg) {
 | 
			
		||||
 | 
			
		||||
  HelloResponse resp;
 | 
			
		||||
  resp.api_version_major = 1;
 | 
			
		||||
  resp.api_version_minor = 5;
 | 
			
		||||
  resp.api_version_minor = 6;
 | 
			
		||||
  resp.server_info = App.get_name() + " (esphome v" ESPHOME_VERSION ")";
 | 
			
		||||
  this->connection_state_ = ConnectionState::CONNECTED;
 | 
			
		||||
  return resp;
 | 
			
		||||
 
 | 
			
		||||
@@ -67,6 +67,11 @@ class APIConnection : public APIServerConnection {
 | 
			
		||||
  bool send_number_state(number::Number *number, float state);
 | 
			
		||||
  bool send_number_info(number::Number *number);
 | 
			
		||||
  void number_command(const NumberCommandRequest &msg) override;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_SELECT
 | 
			
		||||
  bool send_select_state(select::Select *select, std::string state);
 | 
			
		||||
  bool send_select_info(select::Select *select);
 | 
			
		||||
  void select_command(const SelectCommandRequest &msg) override;
 | 
			
		||||
#endif
 | 
			
		||||
  bool send_log_message(int level, const char *tag, const char *line);
 | 
			
		||||
  void send_homeassistant_service_call(const HomeassistantServiceResponse &call) {
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -32,6 +32,18 @@ enum FanDirection : uint32_t {
 | 
			
		||||
  FAN_DIRECTION_FORWARD = 0,
 | 
			
		||||
  FAN_DIRECTION_REVERSE = 1,
 | 
			
		||||
};
 | 
			
		||||
enum ColorMode : uint32_t {
 | 
			
		||||
  COLOR_MODE_UNKNOWN = 0,
 | 
			
		||||
  COLOR_MODE_ON_OFF = 1,
 | 
			
		||||
  COLOR_MODE_BRIGHTNESS = 2,
 | 
			
		||||
  COLOR_MODE_WHITE = 7,
 | 
			
		||||
  COLOR_MODE_COLOR_TEMPERATURE = 11,
 | 
			
		||||
  COLOR_MODE_COLD_WARM_WHITE = 19,
 | 
			
		||||
  COLOR_MODE_RGB = 35,
 | 
			
		||||
  COLOR_MODE_RGB_WHITE = 39,
 | 
			
		||||
  COLOR_MODE_RGB_COLOR_TEMPERATURE = 47,
 | 
			
		||||
  COLOR_MODE_RGB_COLD_WARM_WHITE = 51,
 | 
			
		||||
};
 | 
			
		||||
enum SensorStateClass : uint32_t {
 | 
			
		||||
  STATE_CLASS_NONE = 0,
 | 
			
		||||
  STATE_CLASS_MEASUREMENT = 1,
 | 
			
		||||
@@ -46,9 +58,10 @@ enum LogLevel : uint32_t {
 | 
			
		||||
  LOG_LEVEL_ERROR = 1,
 | 
			
		||||
  LOG_LEVEL_WARN = 2,
 | 
			
		||||
  LOG_LEVEL_INFO = 3,
 | 
			
		||||
  LOG_LEVEL_DEBUG = 4,
 | 
			
		||||
  LOG_LEVEL_VERBOSE = 5,
 | 
			
		||||
  LOG_LEVEL_VERY_VERBOSE = 6,
 | 
			
		||||
  LOG_LEVEL_CONFIG = 4,
 | 
			
		||||
  LOG_LEVEL_DEBUG = 5,
 | 
			
		||||
  LOG_LEVEL_VERBOSE = 6,
 | 
			
		||||
  LOG_LEVEL_VERY_VERBOSE = 7,
 | 
			
		||||
};
 | 
			
		||||
enum ServiceArgType : uint32_t {
 | 
			
		||||
  SERVICE_ARG_TYPE_BOOL = 0,
 | 
			
		||||
@@ -111,7 +124,9 @@ class HelloRequest : public ProtoMessage {
 | 
			
		||||
 public:
 | 
			
		||||
  std::string client_info{};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
			
		||||
@@ -122,7 +137,9 @@ class HelloResponse : public ProtoMessage {
 | 
			
		||||
  uint32_t api_version_minor{0};
 | 
			
		||||
  std::string server_info{};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
			
		||||
@@ -132,7 +149,9 @@ class ConnectRequest : public ProtoMessage {
 | 
			
		||||
 public:
 | 
			
		||||
  std::string password{};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
			
		||||
@@ -141,7 +160,9 @@ class ConnectResponse : public ProtoMessage {
 | 
			
		||||
 public:
 | 
			
		||||
  bool invalid_password{false};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
			
		||||
@@ -149,35 +170,45 @@ class ConnectResponse : public ProtoMessage {
 | 
			
		||||
class DisconnectRequest : public ProtoMessage {
 | 
			
		||||
 public:
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
};
 | 
			
		||||
class DisconnectResponse : public ProtoMessage {
 | 
			
		||||
 public:
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
};
 | 
			
		||||
class PingRequest : public ProtoMessage {
 | 
			
		||||
 public:
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
};
 | 
			
		||||
class PingResponse : public ProtoMessage {
 | 
			
		||||
 public:
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
};
 | 
			
		||||
class DeviceInfoRequest : public ProtoMessage {
 | 
			
		||||
 public:
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
};
 | 
			
		||||
@@ -193,7 +224,9 @@ class DeviceInfoResponse : public ProtoMessage {
 | 
			
		||||
  std::string project_name{};
 | 
			
		||||
  std::string project_version{};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
			
		||||
@@ -202,21 +235,27 @@ class DeviceInfoResponse : public ProtoMessage {
 | 
			
		||||
class ListEntitiesRequest : public ProtoMessage {
 | 
			
		||||
 public:
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
};
 | 
			
		||||
class ListEntitiesDoneResponse : public ProtoMessage {
 | 
			
		||||
 public:
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
};
 | 
			
		||||
class SubscribeStatesRequest : public ProtoMessage {
 | 
			
		||||
 public:
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
};
 | 
			
		||||
@@ -228,8 +267,11 @@ class ListEntitiesBinarySensorResponse : public ProtoMessage {
 | 
			
		||||
  std::string unique_id{};
 | 
			
		||||
  std::string device_class{};
 | 
			
		||||
  bool is_status_binary_sensor{false};
 | 
			
		||||
  bool disabled_by_default{false};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
@@ -242,7 +284,9 @@ class BinarySensorStateResponse : public ProtoMessage {
 | 
			
		||||
  bool state{false};
 | 
			
		||||
  bool missing_state{false};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
@@ -258,8 +302,11 @@ class ListEntitiesCoverResponse : public ProtoMessage {
 | 
			
		||||
  bool supports_position{false};
 | 
			
		||||
  bool supports_tilt{false};
 | 
			
		||||
  std::string device_class{};
 | 
			
		||||
  bool disabled_by_default{false};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
@@ -274,7 +321,9 @@ class CoverStateResponse : public ProtoMessage {
 | 
			
		||||
  float tilt{0.0f};
 | 
			
		||||
  enums::CoverOperation current_operation{};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
@@ -291,7 +340,9 @@ class CoverCommandRequest : public ProtoMessage {
 | 
			
		||||
  float tilt{0.0f};
 | 
			
		||||
  bool stop{false};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
@@ -307,8 +358,11 @@ class ListEntitiesFanResponse : public ProtoMessage {
 | 
			
		||||
  bool supports_speed{false};
 | 
			
		||||
  bool supports_direction{false};
 | 
			
		||||
  int32_t supported_speed_count{0};
 | 
			
		||||
  bool disabled_by_default{false};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
@@ -324,7 +378,9 @@ class FanStateResponse : public ProtoMessage {
 | 
			
		||||
  enums::FanDirection direction{};
 | 
			
		||||
  int32_t speed_level{0};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
@@ -344,7 +400,9 @@ class FanCommandRequest : public ProtoMessage {
 | 
			
		||||
  bool has_speed_level{false};
 | 
			
		||||
  int32_t speed_level{0};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
@@ -356,15 +414,19 @@ class ListEntitiesLightResponse : public ProtoMessage {
 | 
			
		||||
  uint32_t key{0};
 | 
			
		||||
  std::string name{};
 | 
			
		||||
  std::string unique_id{};
 | 
			
		||||
  bool supports_brightness{false};
 | 
			
		||||
  bool supports_rgb{false};
 | 
			
		||||
  bool supports_white_value{false};
 | 
			
		||||
  bool supports_color_temperature{false};
 | 
			
		||||
  std::vector<enums::ColorMode> supported_color_modes{};
 | 
			
		||||
  bool legacy_supports_brightness{false};
 | 
			
		||||
  bool legacy_supports_rgb{false};
 | 
			
		||||
  bool legacy_supports_white_value{false};
 | 
			
		||||
  bool legacy_supports_color_temperature{false};
 | 
			
		||||
  float min_mireds{0.0f};
 | 
			
		||||
  float max_mireds{0.0f};
 | 
			
		||||
  std::vector<std::string> effects{};
 | 
			
		||||
  bool disabled_by_default{false};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
@@ -376,15 +438,20 @@ class LightStateResponse : public ProtoMessage {
 | 
			
		||||
  uint32_t key{0};
 | 
			
		||||
  bool state{false};
 | 
			
		||||
  float brightness{0.0f};
 | 
			
		||||
  enums::ColorMode color_mode{};
 | 
			
		||||
  float color_brightness{0.0f};
 | 
			
		||||
  float red{0.0f};
 | 
			
		||||
  float green{0.0f};
 | 
			
		||||
  float blue{0.0f};
 | 
			
		||||
  float white{0.0f};
 | 
			
		||||
  float color_temperature{0.0f};
 | 
			
		||||
  float cold_white{0.0f};
 | 
			
		||||
  float warm_white{0.0f};
 | 
			
		||||
  std::string effect{};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
@@ -398,6 +465,8 @@ class LightCommandRequest : public ProtoMessage {
 | 
			
		||||
  bool state{false};
 | 
			
		||||
  bool has_brightness{false};
 | 
			
		||||
  float brightness{0.0f};
 | 
			
		||||
  bool has_color_mode{false};
 | 
			
		||||
  enums::ColorMode color_mode{};
 | 
			
		||||
  bool has_color_brightness{false};
 | 
			
		||||
  float color_brightness{0.0f};
 | 
			
		||||
  bool has_rgb{false};
 | 
			
		||||
@@ -408,6 +477,10 @@ class LightCommandRequest : public ProtoMessage {
 | 
			
		||||
  float white{0.0f};
 | 
			
		||||
  bool has_color_temperature{false};
 | 
			
		||||
  float color_temperature{0.0f};
 | 
			
		||||
  bool has_cold_white{false};
 | 
			
		||||
  float cold_white{0.0f};
 | 
			
		||||
  bool has_warm_white{false};
 | 
			
		||||
  float warm_white{0.0f};
 | 
			
		||||
  bool has_transition_length{false};
 | 
			
		||||
  uint32_t transition_length{0};
 | 
			
		||||
  bool has_flash_length{false};
 | 
			
		||||
@@ -415,7 +488,9 @@ class LightCommandRequest : public ProtoMessage {
 | 
			
		||||
  bool has_effect{false};
 | 
			
		||||
  std::string effect{};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
@@ -435,8 +510,11 @@ class ListEntitiesSensorResponse : public ProtoMessage {
 | 
			
		||||
  std::string device_class{};
 | 
			
		||||
  enums::SensorStateClass state_class{};
 | 
			
		||||
  enums::SensorLastResetType last_reset_type{};
 | 
			
		||||
  bool disabled_by_default{false};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
@@ -449,7 +527,9 @@ class SensorStateResponse : public ProtoMessage {
 | 
			
		||||
  float state{0.0f};
 | 
			
		||||
  bool missing_state{false};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
@@ -463,8 +543,11 @@ class ListEntitiesSwitchResponse : public ProtoMessage {
 | 
			
		||||
  std::string unique_id{};
 | 
			
		||||
  std::string icon{};
 | 
			
		||||
  bool assumed_state{false};
 | 
			
		||||
  bool disabled_by_default{false};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
@@ -476,7 +559,9 @@ class SwitchStateResponse : public ProtoMessage {
 | 
			
		||||
  uint32_t key{0};
 | 
			
		||||
  bool state{false};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
@@ -487,7 +572,9 @@ class SwitchCommandRequest : public ProtoMessage {
 | 
			
		||||
  uint32_t key{0};
 | 
			
		||||
  bool state{false};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
@@ -500,12 +587,16 @@ class ListEntitiesTextSensorResponse : public ProtoMessage {
 | 
			
		||||
  std::string name{};
 | 
			
		||||
  std::string unique_id{};
 | 
			
		||||
  std::string icon{};
 | 
			
		||||
  bool disabled_by_default{false};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
			
		||||
  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
			
		||||
};
 | 
			
		||||
class TextSensorStateResponse : public ProtoMessage {
 | 
			
		||||
 public:
 | 
			
		||||
@@ -513,7 +604,9 @@ class TextSensorStateResponse : public ProtoMessage {
 | 
			
		||||
  std::string state{};
 | 
			
		||||
  bool missing_state{false};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
@@ -525,7 +618,9 @@ class SubscribeLogsRequest : public ProtoMessage {
 | 
			
		||||
  enums::LogLevel level{};
 | 
			
		||||
  bool dump_config{false};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
			
		||||
@@ -533,11 +628,12 @@ class SubscribeLogsRequest : public ProtoMessage {
 | 
			
		||||
class SubscribeLogsResponse : public ProtoMessage {
 | 
			
		||||
 public:
 | 
			
		||||
  enums::LogLevel level{};
 | 
			
		||||
  std::string tag{};
 | 
			
		||||
  std::string message{};
 | 
			
		||||
  bool send_failed{false};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
			
		||||
@@ -546,7 +642,9 @@ class SubscribeLogsResponse : public ProtoMessage {
 | 
			
		||||
class SubscribeHomeassistantServicesRequest : public ProtoMessage {
 | 
			
		||||
 public:
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
};
 | 
			
		||||
@@ -555,7 +653,9 @@ class HomeassistantServiceMap : public ProtoMessage {
 | 
			
		||||
  std::string key{};
 | 
			
		||||
  std::string value{};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
			
		||||
@@ -568,7 +668,9 @@ class HomeassistantServiceResponse : public ProtoMessage {
 | 
			
		||||
  std::vector<HomeassistantServiceMap> variables{};
 | 
			
		||||
  bool is_event{false};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
			
		||||
@@ -577,7 +679,9 @@ class HomeassistantServiceResponse : public ProtoMessage {
 | 
			
		||||
class SubscribeHomeAssistantStatesRequest : public ProtoMessage {
 | 
			
		||||
 public:
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
};
 | 
			
		||||
@@ -586,7 +690,9 @@ class SubscribeHomeAssistantStateResponse : public ProtoMessage {
 | 
			
		||||
  std::string entity_id{};
 | 
			
		||||
  std::string attribute{};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
			
		||||
@@ -597,7 +703,9 @@ class HomeAssistantStateResponse : public ProtoMessage {
 | 
			
		||||
  std::string state{};
 | 
			
		||||
  std::string attribute{};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
			
		||||
@@ -605,7 +713,9 @@ class HomeAssistantStateResponse : public ProtoMessage {
 | 
			
		||||
class GetTimeRequest : public ProtoMessage {
 | 
			
		||||
 public:
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
};
 | 
			
		||||
@@ -613,7 +723,9 @@ class GetTimeResponse : public ProtoMessage {
 | 
			
		||||
 public:
 | 
			
		||||
  uint32_t epoch_seconds{0};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
@@ -623,7 +735,9 @@ class ListEntitiesServicesArgument : public ProtoMessage {
 | 
			
		||||
  std::string name{};
 | 
			
		||||
  enums::ServiceArgType type{};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
			
		||||
@@ -635,7 +749,9 @@ class ListEntitiesServicesResponse : public ProtoMessage {
 | 
			
		||||
  uint32_t key{0};
 | 
			
		||||
  std::vector<ListEntitiesServicesArgument> args{};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
@@ -653,7 +769,9 @@ class ExecuteServiceArgument : public ProtoMessage {
 | 
			
		||||
  std::vector<float> float_array{};
 | 
			
		||||
  std::vector<std::string> string_array{};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
@@ -665,7 +783,9 @@ class ExecuteServiceRequest : public ProtoMessage {
 | 
			
		||||
  uint32_t key{0};
 | 
			
		||||
  std::vector<ExecuteServiceArgument> args{};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
@@ -677,12 +797,16 @@ class ListEntitiesCameraResponse : public ProtoMessage {
 | 
			
		||||
  uint32_t key{0};
 | 
			
		||||
  std::string name{};
 | 
			
		||||
  std::string unique_id{};
 | 
			
		||||
  bool disabled_by_default{false};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
			
		||||
  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
			
		||||
};
 | 
			
		||||
class CameraImageResponse : public ProtoMessage {
 | 
			
		||||
 public:
 | 
			
		||||
@@ -690,7 +814,9 @@ class CameraImageResponse : public ProtoMessage {
 | 
			
		||||
  std::string data{};
 | 
			
		||||
  bool done{false};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
@@ -702,7 +828,9 @@ class CameraImageRequest : public ProtoMessage {
 | 
			
		||||
  bool single{false};
 | 
			
		||||
  bool stream{false};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
			
		||||
@@ -726,8 +854,11 @@ class ListEntitiesClimateResponse : public ProtoMessage {
 | 
			
		||||
  std::vector<std::string> supported_custom_fan_modes{};
 | 
			
		||||
  std::vector<enums::ClimatePreset> supported_presets{};
 | 
			
		||||
  std::vector<std::string> supported_custom_presets{};
 | 
			
		||||
  bool disabled_by_default{false};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
@@ -750,7 +881,9 @@ class ClimateStateResponse : public ProtoMessage {
 | 
			
		||||
  enums::ClimatePreset preset{};
 | 
			
		||||
  std::string custom_preset{};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
@@ -781,7 +914,9 @@ class ClimateCommandRequest : public ProtoMessage {
 | 
			
		||||
  bool has_custom_preset{false};
 | 
			
		||||
  std::string custom_preset{};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
@@ -798,12 +933,16 @@ class ListEntitiesNumberResponse : public ProtoMessage {
 | 
			
		||||
  float min_value{0.0f};
 | 
			
		||||
  float max_value{0.0f};
 | 
			
		||||
  float step{0.0f};
 | 
			
		||||
  bool disabled_by_default{false};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
			
		||||
  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
			
		||||
};
 | 
			
		||||
class NumberStateResponse : public ProtoMessage {
 | 
			
		||||
 public:
 | 
			
		||||
@@ -811,7 +950,9 @@ class NumberStateResponse : public ProtoMessage {
 | 
			
		||||
  float state{0.0f};
 | 
			
		||||
  bool missing_state{false};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
@@ -822,11 +963,60 @@ class NumberCommandRequest : public ProtoMessage {
 | 
			
		||||
  uint32_t key{0};
 | 
			
		||||
  float state{0.0f};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
};
 | 
			
		||||
class ListEntitiesSelectResponse : public ProtoMessage {
 | 
			
		||||
 public:
 | 
			
		||||
  std::string object_id{};
 | 
			
		||||
  uint32_t key{0};
 | 
			
		||||
  std::string name{};
 | 
			
		||||
  std::string unique_id{};
 | 
			
		||||
  std::string icon{};
 | 
			
		||||
  std::vector<std::string> options{};
 | 
			
		||||
  bool disabled_by_default{false};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
			
		||||
  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
			
		||||
};
 | 
			
		||||
class SelectStateResponse : public ProtoMessage {
 | 
			
		||||
 public:
 | 
			
		||||
  uint32_t key{0};
 | 
			
		||||
  std::string state{};
 | 
			
		||||
  bool missing_state{false};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
			
		||||
  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
			
		||||
};
 | 
			
		||||
class SelectCommandRequest : public ProtoMessage {
 | 
			
		||||
 public:
 | 
			
		||||
  uint32_t key{0};
 | 
			
		||||
  std::string state{};
 | 
			
		||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  void dump_to(std::string &out) const override;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
			
		||||
  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace api
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
 
 | 
			
		||||
@@ -9,58 +9,82 @@ namespace api {
 | 
			
		||||
static const char *const TAG = "api.service";
 | 
			
		||||
 | 
			
		||||
bool APIServerConnectionBase::send_hello_response(const HelloResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_hello_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<HelloResponse>(msg, 2);
 | 
			
		||||
}
 | 
			
		||||
bool APIServerConnectionBase::send_connect_response(const ConnectResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_connect_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<ConnectResponse>(msg, 4);
 | 
			
		||||
}
 | 
			
		||||
bool APIServerConnectionBase::send_disconnect_request(const DisconnectRequest &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_disconnect_request: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<DisconnectRequest>(msg, 5);
 | 
			
		||||
}
 | 
			
		||||
bool APIServerConnectionBase::send_disconnect_response(const DisconnectResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_disconnect_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<DisconnectResponse>(msg, 6);
 | 
			
		||||
}
 | 
			
		||||
bool APIServerConnectionBase::send_ping_request(const PingRequest &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_ping_request: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<PingRequest>(msg, 7);
 | 
			
		||||
}
 | 
			
		||||
bool APIServerConnectionBase::send_ping_response(const PingResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_ping_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<PingResponse>(msg, 8);
 | 
			
		||||
}
 | 
			
		||||
bool APIServerConnectionBase::send_device_info_response(const DeviceInfoResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_device_info_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<DeviceInfoResponse>(msg, 10);
 | 
			
		||||
}
 | 
			
		||||
bool APIServerConnectionBase::send_list_entities_done_response(const ListEntitiesDoneResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_list_entities_done_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<ListEntitiesDoneResponse>(msg, 19);
 | 
			
		||||
}
 | 
			
		||||
#ifdef USE_BINARY_SENSOR
 | 
			
		||||
bool APIServerConnectionBase::send_list_entities_binary_sensor_response(const ListEntitiesBinarySensorResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_list_entities_binary_sensor_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<ListEntitiesBinarySensorResponse>(msg, 12);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_BINARY_SENSOR
 | 
			
		||||
bool APIServerConnectionBase::send_binary_sensor_state_response(const BinarySensorStateResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_binary_sensor_state_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<BinarySensorStateResponse>(msg, 21);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_COVER
 | 
			
		||||
bool APIServerConnectionBase::send_list_entities_cover_response(const ListEntitiesCoverResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_list_entities_cover_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<ListEntitiesCoverResponse>(msg, 13);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_COVER
 | 
			
		||||
bool APIServerConnectionBase::send_cover_state_response(const CoverStateResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_cover_state_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<CoverStateResponse>(msg, 22);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
@@ -68,13 +92,17 @@ bool APIServerConnectionBase::send_cover_state_response(const CoverStateResponse
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_FAN
 | 
			
		||||
bool APIServerConnectionBase::send_list_entities_fan_response(const ListEntitiesFanResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_list_entities_fan_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<ListEntitiesFanResponse>(msg, 14);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_FAN
 | 
			
		||||
bool APIServerConnectionBase::send_fan_state_response(const FanStateResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_fan_state_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<FanStateResponse>(msg, 23);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
@@ -82,13 +110,17 @@ bool APIServerConnectionBase::send_fan_state_response(const FanStateResponse &ms
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_LIGHT
 | 
			
		||||
bool APIServerConnectionBase::send_list_entities_light_response(const ListEntitiesLightResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_list_entities_light_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<ListEntitiesLightResponse>(msg, 15);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_LIGHT
 | 
			
		||||
bool APIServerConnectionBase::send_light_state_response(const LightStateResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_light_state_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<LightStateResponse>(msg, 24);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
@@ -96,25 +128,33 @@ bool APIServerConnectionBase::send_light_state_response(const LightStateResponse
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_SENSOR
 | 
			
		||||
bool APIServerConnectionBase::send_list_entities_sensor_response(const ListEntitiesSensorResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_list_entities_sensor_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<ListEntitiesSensorResponse>(msg, 16);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_SENSOR
 | 
			
		||||
bool APIServerConnectionBase::send_sensor_state_response(const SensorStateResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_sensor_state_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<SensorStateResponse>(msg, 25);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_SWITCH
 | 
			
		||||
bool APIServerConnectionBase::send_list_entities_switch_response(const ListEntitiesSwitchResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_list_entities_switch_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<ListEntitiesSwitchResponse>(msg, 17);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_SWITCH
 | 
			
		||||
bool APIServerConnectionBase::send_switch_state_response(const SwitchStateResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_switch_state_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<SwitchStateResponse>(msg, 26);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
@@ -122,13 +162,17 @@ bool APIServerConnectionBase::send_switch_state_response(const SwitchStateRespon
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_TEXT_SENSOR
 | 
			
		||||
bool APIServerConnectionBase::send_list_entities_text_sensor_response(const ListEntitiesTextSensorResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_list_entities_text_sensor_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<ListEntitiesTextSensorResponse>(msg, 18);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_TEXT_SENSOR
 | 
			
		||||
bool APIServerConnectionBase::send_text_sensor_state_response(const TextSensorStateResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_text_sensor_state_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<TextSensorStateResponse>(msg, 27);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
@@ -136,35 +180,49 @@ bool APIServerConnectionBase::send_subscribe_logs_response(const SubscribeLogsRe
 | 
			
		||||
  return this->send_message_<SubscribeLogsResponse>(msg, 29);
 | 
			
		||||
}
 | 
			
		||||
bool APIServerConnectionBase::send_homeassistant_service_response(const HomeassistantServiceResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_homeassistant_service_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<HomeassistantServiceResponse>(msg, 35);
 | 
			
		||||
}
 | 
			
		||||
bool APIServerConnectionBase::send_subscribe_home_assistant_state_response(
 | 
			
		||||
    const SubscribeHomeAssistantStateResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_subscribe_home_assistant_state_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<SubscribeHomeAssistantStateResponse>(msg, 39);
 | 
			
		||||
}
 | 
			
		||||
bool APIServerConnectionBase::send_get_time_request(const GetTimeRequest &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_get_time_request: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<GetTimeRequest>(msg, 36);
 | 
			
		||||
}
 | 
			
		||||
bool APIServerConnectionBase::send_get_time_response(const GetTimeResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_get_time_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<GetTimeResponse>(msg, 37);
 | 
			
		||||
}
 | 
			
		||||
bool APIServerConnectionBase::send_list_entities_services_response(const ListEntitiesServicesResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_list_entities_services_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<ListEntitiesServicesResponse>(msg, 41);
 | 
			
		||||
}
 | 
			
		||||
#ifdef USE_ESP32_CAMERA
 | 
			
		||||
bool APIServerConnectionBase::send_list_entities_camera_response(const ListEntitiesCameraResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_list_entities_camera_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<ListEntitiesCameraResponse>(msg, 43);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_ESP32_CAMERA
 | 
			
		||||
bool APIServerConnectionBase::send_camera_image_response(const CameraImageResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_camera_image_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<CameraImageResponse>(msg, 44);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
@@ -172,13 +230,17 @@ bool APIServerConnectionBase::send_camera_image_response(const CameraImageRespon
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_CLIMATE
 | 
			
		||||
bool APIServerConnectionBase::send_list_entities_climate_response(const ListEntitiesClimateResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_list_entities_climate_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<ListEntitiesClimateResponse>(msg, 46);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_CLIMATE
 | 
			
		||||
bool APIServerConnectionBase::send_climate_state_response(const ClimateStateResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_climate_state_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<ClimateStateResponse>(msg, 47);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
@@ -186,87 +248,129 @@ bool APIServerConnectionBase::send_climate_state_response(const ClimateStateResp
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_NUMBER
 | 
			
		||||
bool APIServerConnectionBase::send_list_entities_number_response(const ListEntitiesNumberResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_list_entities_number_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<ListEntitiesNumberResponse>(msg, 49);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_NUMBER
 | 
			
		||||
bool APIServerConnectionBase::send_number_state_response(const NumberStateResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_number_state_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<NumberStateResponse>(msg, 50);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_NUMBER
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_SELECT
 | 
			
		||||
bool APIServerConnectionBase::send_list_entities_select_response(const ListEntitiesSelectResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_list_entities_select_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<ListEntitiesSelectResponse>(msg, 52);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_SELECT
 | 
			
		||||
bool APIServerConnectionBase::send_select_state_response(const SelectStateResponse &msg) {
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  ESP_LOGVV(TAG, "send_select_state_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
  return this->send_message_<SelectStateResponse>(msg, 53);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_SELECT
 | 
			
		||||
#endif
 | 
			
		||||
bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) {
 | 
			
		||||
  switch (msg_type) {
 | 
			
		||||
    case 1: {
 | 
			
		||||
      HelloRequest msg;
 | 
			
		||||
      msg.decode(msg_data, msg_size);
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
      ESP_LOGVV(TAG, "on_hello_request: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
      this->on_hello_request(msg);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case 3: {
 | 
			
		||||
      ConnectRequest msg;
 | 
			
		||||
      msg.decode(msg_data, msg_size);
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
      ESP_LOGVV(TAG, "on_connect_request: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
      this->on_connect_request(msg);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case 5: {
 | 
			
		||||
      DisconnectRequest msg;
 | 
			
		||||
      msg.decode(msg_data, msg_size);
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
      ESP_LOGVV(TAG, "on_disconnect_request: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
      this->on_disconnect_request(msg);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case 6: {
 | 
			
		||||
      DisconnectResponse msg;
 | 
			
		||||
      msg.decode(msg_data, msg_size);
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
      ESP_LOGVV(TAG, "on_disconnect_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
      this->on_disconnect_response(msg);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case 7: {
 | 
			
		||||
      PingRequest msg;
 | 
			
		||||
      msg.decode(msg_data, msg_size);
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
      ESP_LOGVV(TAG, "on_ping_request: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
      this->on_ping_request(msg);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case 8: {
 | 
			
		||||
      PingResponse msg;
 | 
			
		||||
      msg.decode(msg_data, msg_size);
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
      ESP_LOGVV(TAG, "on_ping_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
      this->on_ping_response(msg);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case 9: {
 | 
			
		||||
      DeviceInfoRequest msg;
 | 
			
		||||
      msg.decode(msg_data, msg_size);
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
      ESP_LOGVV(TAG, "on_device_info_request: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
      this->on_device_info_request(msg);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case 11: {
 | 
			
		||||
      ListEntitiesRequest msg;
 | 
			
		||||
      msg.decode(msg_data, msg_size);
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
      ESP_LOGVV(TAG, "on_list_entities_request: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
      this->on_list_entities_request(msg);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case 20: {
 | 
			
		||||
      SubscribeStatesRequest msg;
 | 
			
		||||
      msg.decode(msg_data, msg_size);
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
      ESP_LOGVV(TAG, "on_subscribe_states_request: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
      this->on_subscribe_states_request(msg);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case 28: {
 | 
			
		||||
      SubscribeLogsRequest msg;
 | 
			
		||||
      msg.decode(msg_data, msg_size);
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
      ESP_LOGVV(TAG, "on_subscribe_logs_request: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
      this->on_subscribe_logs_request(msg);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
@@ -274,7 +378,9 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
 | 
			
		||||
#ifdef USE_COVER
 | 
			
		||||
      CoverCommandRequest msg;
 | 
			
		||||
      msg.decode(msg_data, msg_size);
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
      ESP_LOGVV(TAG, "on_cover_command_request: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
      this->on_cover_command_request(msg);
 | 
			
		||||
#endif
 | 
			
		||||
      break;
 | 
			
		||||
@@ -283,7 +389,9 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
 | 
			
		||||
#ifdef USE_FAN
 | 
			
		||||
      FanCommandRequest msg;
 | 
			
		||||
      msg.decode(msg_data, msg_size);
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
      ESP_LOGVV(TAG, "on_fan_command_request: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
      this->on_fan_command_request(msg);
 | 
			
		||||
#endif
 | 
			
		||||
      break;
 | 
			
		||||
@@ -292,7 +400,9 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
 | 
			
		||||
#ifdef USE_LIGHT
 | 
			
		||||
      LightCommandRequest msg;
 | 
			
		||||
      msg.decode(msg_data, msg_size);
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
      ESP_LOGVV(TAG, "on_light_command_request: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
      this->on_light_command_request(msg);
 | 
			
		||||
#endif
 | 
			
		||||
      break;
 | 
			
		||||
@@ -301,7 +411,9 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
 | 
			
		||||
#ifdef USE_SWITCH
 | 
			
		||||
      SwitchCommandRequest msg;
 | 
			
		||||
      msg.decode(msg_data, msg_size);
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
      ESP_LOGVV(TAG, "on_switch_command_request: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
      this->on_switch_command_request(msg);
 | 
			
		||||
#endif
 | 
			
		||||
      break;
 | 
			
		||||
@@ -309,42 +421,54 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
 | 
			
		||||
    case 34: {
 | 
			
		||||
      SubscribeHomeassistantServicesRequest msg;
 | 
			
		||||
      msg.decode(msg_data, msg_size);
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
      ESP_LOGVV(TAG, "on_subscribe_homeassistant_services_request: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
      this->on_subscribe_homeassistant_services_request(msg);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case 36: {
 | 
			
		||||
      GetTimeRequest msg;
 | 
			
		||||
      msg.decode(msg_data, msg_size);
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
      ESP_LOGVV(TAG, "on_get_time_request: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
      this->on_get_time_request(msg);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case 37: {
 | 
			
		||||
      GetTimeResponse msg;
 | 
			
		||||
      msg.decode(msg_data, msg_size);
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
      ESP_LOGVV(TAG, "on_get_time_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
      this->on_get_time_response(msg);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case 38: {
 | 
			
		||||
      SubscribeHomeAssistantStatesRequest msg;
 | 
			
		||||
      msg.decode(msg_data, msg_size);
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
      ESP_LOGVV(TAG, "on_subscribe_home_assistant_states_request: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
      this->on_subscribe_home_assistant_states_request(msg);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case 40: {
 | 
			
		||||
      HomeAssistantStateResponse msg;
 | 
			
		||||
      msg.decode(msg_data, msg_size);
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
      ESP_LOGVV(TAG, "on_home_assistant_state_response: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
      this->on_home_assistant_state_response(msg);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case 42: {
 | 
			
		||||
      ExecuteServiceRequest msg;
 | 
			
		||||
      msg.decode(msg_data, msg_size);
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
      ESP_LOGVV(TAG, "on_execute_service_request: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
      this->on_execute_service_request(msg);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
@@ -352,7 +476,9 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
 | 
			
		||||
#ifdef USE_ESP32_CAMERA
 | 
			
		||||
      CameraImageRequest msg;
 | 
			
		||||
      msg.decode(msg_data, msg_size);
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
      ESP_LOGVV(TAG, "on_camera_image_request: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
      this->on_camera_image_request(msg);
 | 
			
		||||
#endif
 | 
			
		||||
      break;
 | 
			
		||||
@@ -361,7 +487,9 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
 | 
			
		||||
#ifdef USE_CLIMATE
 | 
			
		||||
      ClimateCommandRequest msg;
 | 
			
		||||
      msg.decode(msg_data, msg_size);
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
      ESP_LOGVV(TAG, "on_climate_command_request: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
      this->on_climate_command_request(msg);
 | 
			
		||||
#endif
 | 
			
		||||
      break;
 | 
			
		||||
@@ -370,8 +498,21 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
 | 
			
		||||
#ifdef USE_NUMBER
 | 
			
		||||
      NumberCommandRequest msg;
 | 
			
		||||
      msg.decode(msg_data, msg_size);
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
      ESP_LOGVV(TAG, "on_number_command_request: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
      this->on_number_command_request(msg);
 | 
			
		||||
#endif
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case 54: {
 | 
			
		||||
#ifdef USE_SELECT
 | 
			
		||||
      SelectCommandRequest msg;
 | 
			
		||||
      msg.decode(msg_data, msg_size);
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
      ESP_LOGVV(TAG, "on_select_command_request: %s", msg.dump().c_str());
 | 
			
		||||
#endif
 | 
			
		||||
      this->on_select_command_request(msg);
 | 
			
		||||
#endif
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
@@ -583,6 +724,19 @@ void APIServerConnection::on_number_command_request(const NumberCommandRequest &
 | 
			
		||||
  this->number_command(msg);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_SELECT
 | 
			
		||||
void APIServerConnection::on_select_command_request(const SelectCommandRequest &msg) {
 | 
			
		||||
  if (!this->is_connection_setup()) {
 | 
			
		||||
    this->on_no_setup_connection();
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  if (!this->is_authenticated()) {
 | 
			
		||||
    this->on_unauthenticated_access();
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  this->select_command(msg);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
}  // namespace api
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
 
 | 
			
		||||
@@ -120,6 +120,15 @@ class APIServerConnectionBase : public ProtoService {
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_NUMBER
 | 
			
		||||
  virtual void on_number_command_request(const NumberCommandRequest &value){};
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_SELECT
 | 
			
		||||
  bool send_list_entities_select_response(const ListEntitiesSelectResponse &msg);
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_SELECT
 | 
			
		||||
  bool send_select_state_response(const SelectStateResponse &msg);
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_SELECT
 | 
			
		||||
  virtual void on_select_command_request(const SelectCommandRequest &value){};
 | 
			
		||||
#endif
 | 
			
		||||
 protected:
 | 
			
		||||
  bool read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) override;
 | 
			
		||||
@@ -159,6 +168,9 @@ class APIServerConnection : public APIServerConnectionBase {
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_NUMBER
 | 
			
		||||
  virtual void number_command(const NumberCommandRequest &msg) = 0;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_SELECT
 | 
			
		||||
  virtual void select_command(const SelectCommandRequest &msg) = 0;
 | 
			
		||||
#endif
 | 
			
		||||
 protected:
 | 
			
		||||
  void on_hello_request(const HelloRequest &msg) override;
 | 
			
		||||
@@ -194,6 +206,9 @@ class APIServerConnection : public APIServerConnectionBase {
 | 
			
		||||
#ifdef USE_NUMBER
 | 
			
		||||
  void on_number_command_request(const NumberCommandRequest &msg) override;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_SELECT
 | 
			
		||||
  void on_select_command_request(const SelectCommandRequest &msg) override;
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace api
 | 
			
		||||
 
 | 
			
		||||
@@ -206,6 +206,15 @@ void APIServer::on_number_update(number::Number *obj, float state) {
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_SELECT
 | 
			
		||||
void APIServer::on_select_update(select::Select *obj, const std::string &state) {
 | 
			
		||||
  if (obj->is_internal())
 | 
			
		||||
    return;
 | 
			
		||||
  for (auto *c : this->clients_)
 | 
			
		||||
    c->send_select_state(obj, state);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
float APIServer::get_setup_priority() const { return setup_priority::AFTER_WIFI; }
 | 
			
		||||
void APIServer::set_port(uint16_t port) { this->port_ = port; }
 | 
			
		||||
APIServer *global_api_server = nullptr;  // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,6 @@
 | 
			
		||||
#include "util.h"
 | 
			
		||||
#include "list_entities.h"
 | 
			
		||||
#include "subscribe_state.h"
 | 
			
		||||
#include "homeassistant_service.h"
 | 
			
		||||
#include "user_services.h"
 | 
			
		||||
 | 
			
		||||
#ifdef ARDUINO_ARCH_ESP32
 | 
			
		||||
@@ -63,6 +62,9 @@ class APIServer : public Component, public Controller {
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_NUMBER
 | 
			
		||||
  void on_number_update(number::Number *obj, float state) override;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_SELECT
 | 
			
		||||
  void on_select_update(select::Select *obj, const std::string &state) override;
 | 
			
		||||
#endif
 | 
			
		||||
  void send_homeassistant_service_call(const HomeassistantServiceResponse &call);
 | 
			
		||||
  void register_user_service(UserServiceDescriptor *descriptor) { this->user_services_.push_back(descriptor); }
 | 
			
		||||
 
 | 
			
		||||
@@ -55,5 +55,9 @@ bool ListEntitiesIterator::on_climate(climate::Climate *climate) { return this->
 | 
			
		||||
bool ListEntitiesIterator::on_number(number::Number *number) { return this->client_->send_number_info(number); }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_SELECT
 | 
			
		||||
bool ListEntitiesIterator::on_select(select::Select *select) { return this->client_->send_select_info(select); }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
}  // namespace api
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
 
 | 
			
		||||
@@ -42,6 +42,9 @@ class ListEntitiesIterator : public ComponentIterator {
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_NUMBER
 | 
			
		||||
  bool on_number(number::Number *number) override;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_SELECT
 | 
			
		||||
  bool on_select(select::Select *select) override;
 | 
			
		||||
#endif
 | 
			
		||||
  bool on_end() override;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -80,11 +80,13 @@ void ProtoMessage::decode(const uint8_t *buffer, size_t length) {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
std::string ProtoMessage::dump() const {
 | 
			
		||||
  std::string out;
 | 
			
		||||
  this->dump_to(out);
 | 
			
		||||
  return out;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
}  // namespace api
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,13 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "esphome/core/component.h"
 | 
			
		||||
#include "esphome/core/log.h"
 | 
			
		||||
#include "esphome/core/helpers.h"
 | 
			
		||||
 | 
			
		||||
#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
 | 
			
		||||
#define HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace esphome {
 | 
			
		||||
namespace api {
 | 
			
		||||
 | 
			
		||||
@@ -243,8 +248,10 @@ class ProtoMessage {
 | 
			
		||||
 public:
 | 
			
		||||
  virtual void encode(ProtoWriteBuffer buffer) const = 0;
 | 
			
		||||
  void decode(const uint8_t *buffer, size_t length);
 | 
			
		||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
			
		||||
  std::string dump() const;
 | 
			
		||||
  virtual void dump_to(std::string &out) const = 0;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  virtual bool decode_varint(uint32_t field_id, ProtoVarInt value) { return false; }
 | 
			
		||||
 
 | 
			
		||||
@@ -42,6 +42,11 @@ bool InitialStateIterator::on_number(number::Number *number) {
 | 
			
		||||
  return this->client_->send_number_state(number, number->state);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_SELECT
 | 
			
		||||
bool InitialStateIterator::on_select(select::Select *select) {
 | 
			
		||||
  return this->client_->send_select_state(select, select->state);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
InitialStateIterator::InitialStateIterator(APIServer *server, APIConnection *client)
 | 
			
		||||
    : ComponentIterator(server), client_(client) {}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -39,6 +39,9 @@ class InitialStateIterator : public ComponentIterator {
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_NUMBER
 | 
			
		||||
  bool on_number(number::Number *number) override;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_SELECT
 | 
			
		||||
  bool on_select(select::Select *select) override;
 | 
			
		||||
#endif
 | 
			
		||||
 protected:
 | 
			
		||||
  APIConnection *client_;
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ template<> std::string get_execute_arg_value<std::string>(const ExecuteServiceAr
 | 
			
		||||
template<> std::vector<bool> get_execute_arg_value<std::vector<bool>>(const ExecuteServiceArgument &arg) {
 | 
			
		||||
  return arg.bool_array;
 | 
			
		||||
}
 | 
			
		||||
template<> std::vector<int> get_execute_arg_value<std::vector<int>>(const ExecuteServiceArgument &arg) {
 | 
			
		||||
template<> std::vector<int32_t> get_execute_arg_value<std::vector<int32_t>>(const ExecuteServiceArgument &arg) {
 | 
			
		||||
  return arg.int_array;
 | 
			
		||||
}
 | 
			
		||||
template<> std::vector<float> get_execute_arg_value<std::vector<float>>(const ExecuteServiceArgument &arg) {
 | 
			
		||||
 
 | 
			
		||||
@@ -182,6 +182,21 @@ void ComponentIterator::advance() {
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_SELECT
 | 
			
		||||
    case IteratorState::SELECT:
 | 
			
		||||
      if (this->at_ >= App.get_selects().size()) {
 | 
			
		||||
        advance_platform = true;
 | 
			
		||||
      } else {
 | 
			
		||||
        auto *select = App.get_selects()[this->at_];
 | 
			
		||||
        if (select->is_internal()) {
 | 
			
		||||
          success = true;
 | 
			
		||||
          break;
 | 
			
		||||
        } else {
 | 
			
		||||
          success = this->on_select(select);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
#endif
 | 
			
		||||
    case IteratorState::MAX:
 | 
			
		||||
      if (this->on_end()) {
 | 
			
		||||
 
 | 
			
		||||
@@ -50,6 +50,9 @@ class ComponentIterator {
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_NUMBER
 | 
			
		||||
  virtual bool on_number(number::Number *number) = 0;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_SELECT
 | 
			
		||||
  virtual bool on_select(select::Select *select) = 0;
 | 
			
		||||
#endif
 | 
			
		||||
  virtual bool on_end();
 | 
			
		||||
 | 
			
		||||
@@ -87,6 +90,9 @@ class ComponentIterator {
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_NUMBER
 | 
			
		||||
    NUMBER,
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_SELECT
 | 
			
		||||
    SELECT,
 | 
			
		||||
#endif
 | 
			
		||||
    MAX,
 | 
			
		||||
  } state_{IteratorState::NONE};
 | 
			
		||||
 
 | 
			
		||||
@@ -4,10 +4,8 @@ from esphome.components import sensor
 | 
			
		||||
from esphome.const import (
 | 
			
		||||
    CONF_DISTANCE,
 | 
			
		||||
    CONF_LIGHTNING_ENERGY,
 | 
			
		||||
    DEVICE_CLASS_EMPTY,
 | 
			
		||||
    STATE_CLASS_NONE,
 | 
			
		||||
    UNIT_KILOMETER,
 | 
			
		||||
    UNIT_EMPTY,
 | 
			
		||||
    ICON_SIGNAL_DISTANCE_VARIANT,
 | 
			
		||||
    ICON_FLASH,
 | 
			
		||||
)
 | 
			
		||||
@@ -19,14 +17,15 @@ CONFIG_SCHEMA = cv.Schema(
 | 
			
		||||
    {
 | 
			
		||||
        cv.GenerateID(CONF_AS3935_ID): cv.use_id(AS3935),
 | 
			
		||||
        cv.Optional(CONF_DISTANCE): sensor.sensor_schema(
 | 
			
		||||
            UNIT_KILOMETER,
 | 
			
		||||
            ICON_SIGNAL_DISTANCE_VARIANT,
 | 
			
		||||
            1,
 | 
			
		||||
            DEVICE_CLASS_EMPTY,
 | 
			
		||||
            STATE_CLASS_NONE,
 | 
			
		||||
            unit_of_measurement=UNIT_KILOMETER,
 | 
			
		||||
            icon=ICON_SIGNAL_DISTANCE_VARIANT,
 | 
			
		||||
            accuracy_decimals=1,
 | 
			
		||||
            state_class=STATE_CLASS_NONE,
 | 
			
		||||
        ),
 | 
			
		||||
        cv.Optional(CONF_LIGHTNING_ENERGY): sensor.sensor_schema(
 | 
			
		||||
            UNIT_EMPTY, ICON_FLASH, 1, DEVICE_CLASS_EMPTY, STATE_CLASS_NONE
 | 
			
		||||
            icon=ICON_FLASH,
 | 
			
		||||
            accuracy_decimals=1,
 | 
			
		||||
            state_class=STATE_CLASS_NONE,
 | 
			
		||||
        ),
 | 
			
		||||
    }
 | 
			
		||||
).extend(cv.COMPONENT_SCHEMA)
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,6 @@ from esphome.const import (
 | 
			
		||||
    DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
    DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
    DEVICE_CLASS_VOLTAGE,
 | 
			
		||||
    ICON_EMPTY,
 | 
			
		||||
    STATE_CLASS_MEASUREMENT,
 | 
			
		||||
    UNIT_CELSIUS,
 | 
			
		||||
    UNIT_PERCENT,
 | 
			
		||||
@@ -34,28 +33,28 @@ CONFIG_SCHEMA = (
 | 
			
		||||
            cv.GenerateID(): cv.declare_id(ATCMiThermometer),
 | 
			
		||||
            cv.Required(CONF_MAC_ADDRESS): cv.mac_address,
 | 
			
		||||
            cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
 | 
			
		||||
                UNIT_CELSIUS,
 | 
			
		||||
                ICON_EMPTY,
 | 
			
		||||
                1,
 | 
			
		||||
                DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_CELSIUS,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(
 | 
			
		||||
                UNIT_PERCENT,
 | 
			
		||||
                ICON_EMPTY,
 | 
			
		||||
                0,
 | 
			
		||||
                DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_PERCENT,
 | 
			
		||||
                accuracy_decimals=0,
 | 
			
		||||
                device_class=DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema(
 | 
			
		||||
                UNIT_PERCENT,
 | 
			
		||||
                ICON_EMPTY,
 | 
			
		||||
                0,
 | 
			
		||||
                DEVICE_CLASS_BATTERY,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_PERCENT,
 | 
			
		||||
                accuracy_decimals=0,
 | 
			
		||||
                device_class=DEVICE_CLASS_BATTERY,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_BATTERY_VOLTAGE): sensor.sensor_schema(
 | 
			
		||||
                UNIT_VOLT, ICON_EMPTY, 3, DEVICE_CLASS_VOLTAGE, STATE_CLASS_MEASUREMENT
 | 
			
		||||
                unit_of_measurement=UNIT_VOLT,
 | 
			
		||||
                accuracy_decimals=3,
 | 
			
		||||
                device_class=DEVICE_CLASS_VOLTAGE,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
 
 | 
			
		||||
@@ -39,7 +39,7 @@ static const uint16_t ATM90E32_STATUS_S0_OVPHASEBST = 1 << 11;  // Over voltage
 | 
			
		||||
static const uint16_t ATM90E32_STATUS_S0_OVPHASECST = 1 << 10;  // Over voltage on phase C
 | 
			
		||||
static const uint16_t ATM90E32_STATUS_S0_UREVWNST = 1 << 9;     // Voltage Phase Sequence Error status
 | 
			
		||||
static const uint16_t ATM90E32_STATUS_S0_IREVWNST = 1 << 8;     // Current Phase Sequence Error status
 | 
			
		||||
static const uint16_t ATM90E32_STATUS_S0_INOV0ST = 1 << 7;      // Calculated N line current greater tha INWarnTh reg
 | 
			
		||||
static const uint16_t ATM90E32_STATUS_S0_INOV0ST = 1 << 7;      // Calculated N line current greater than INWarnTh reg
 | 
			
		||||
static const uint16_t ATM90E32_STATUS_S0_TQNOLOADST = 1 << 6;   // All phase sum reactive power no-load condition status
 | 
			
		||||
static const uint16_t ATM90E32_STATUS_S0_TPNOLOADST = 1 << 5;   // All phase sum active power no-load condition status
 | 
			
		||||
static const uint16_t ATM90E32_STATUS_S0_TASNOLOADST = 1 << 4;  // All phase sum apparent power no-load status
 | 
			
		||||
 
 | 
			
		||||
@@ -12,13 +12,11 @@ from esphome.const import (
 | 
			
		||||
    CONF_FORWARD_ACTIVE_ENERGY,
 | 
			
		||||
    CONF_REVERSE_ACTIVE_ENERGY,
 | 
			
		||||
    DEVICE_CLASS_CURRENT,
 | 
			
		||||
    DEVICE_CLASS_EMPTY,
 | 
			
		||||
    DEVICE_CLASS_ENERGY,
 | 
			
		||||
    DEVICE_CLASS_POWER,
 | 
			
		||||
    DEVICE_CLASS_POWER_FACTOR,
 | 
			
		||||
    DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
    DEVICE_CLASS_VOLTAGE,
 | 
			
		||||
    ICON_EMPTY,
 | 
			
		||||
    ICON_LIGHTBULB,
 | 
			
		||||
    ICON_CURRENT_AC,
 | 
			
		||||
    LAST_RESET_TYPE_AUTO,
 | 
			
		||||
@@ -27,7 +25,6 @@ from esphome.const import (
 | 
			
		||||
    UNIT_VOLT,
 | 
			
		||||
    UNIT_AMPERE,
 | 
			
		||||
    UNIT_WATT,
 | 
			
		||||
    UNIT_EMPTY,
 | 
			
		||||
    UNIT_CELSIUS,
 | 
			
		||||
    UNIT_VOLT_AMPS_REACTIVE,
 | 
			
		||||
    UNIT_WATT_HOURS,
 | 
			
		||||
@@ -65,47 +62,47 @@ ATM90E32Component = atm90e32_ns.class_(
 | 
			
		||||
ATM90E32_PHASE_SCHEMA = cv.Schema(
 | 
			
		||||
    {
 | 
			
		||||
        cv.Optional(CONF_VOLTAGE): sensor.sensor_schema(
 | 
			
		||||
            UNIT_VOLT,
 | 
			
		||||
            ICON_EMPTY,
 | 
			
		||||
            2,
 | 
			
		||||
            DEVICE_CLASS_VOLTAGE,
 | 
			
		||||
            STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            unit_of_measurement=UNIT_VOLT,
 | 
			
		||||
            accuracy_decimals=2,
 | 
			
		||||
            device_class=DEVICE_CLASS_VOLTAGE,
 | 
			
		||||
            state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
        ),
 | 
			
		||||
        cv.Optional(CONF_CURRENT): sensor.sensor_schema(
 | 
			
		||||
            UNIT_AMPERE, ICON_EMPTY, 2, DEVICE_CLASS_CURRENT, STATE_CLASS_MEASUREMENT
 | 
			
		||||
            unit_of_measurement=UNIT_AMPERE,
 | 
			
		||||
            accuracy_decimals=2,
 | 
			
		||||
            device_class=DEVICE_CLASS_CURRENT,
 | 
			
		||||
            state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
        ),
 | 
			
		||||
        cv.Optional(CONF_POWER): sensor.sensor_schema(
 | 
			
		||||
            UNIT_WATT, ICON_EMPTY, 2, DEVICE_CLASS_POWER, STATE_CLASS_MEASUREMENT
 | 
			
		||||
            unit_of_measurement=UNIT_WATT,
 | 
			
		||||
            accuracy_decimals=2,
 | 
			
		||||
            device_class=DEVICE_CLASS_POWER,
 | 
			
		||||
            state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
        ),
 | 
			
		||||
        cv.Optional(CONF_REACTIVE_POWER): sensor.sensor_schema(
 | 
			
		||||
            UNIT_VOLT_AMPS_REACTIVE,
 | 
			
		||||
            ICON_LIGHTBULB,
 | 
			
		||||
            2,
 | 
			
		||||
            DEVICE_CLASS_EMPTY,
 | 
			
		||||
            STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            unit_of_measurement=UNIT_VOLT_AMPS_REACTIVE,
 | 
			
		||||
            icon=ICON_LIGHTBULB,
 | 
			
		||||
            accuracy_decimals=2,
 | 
			
		||||
            state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
        ),
 | 
			
		||||
        cv.Optional(CONF_POWER_FACTOR): sensor.sensor_schema(
 | 
			
		||||
            UNIT_EMPTY,
 | 
			
		||||
            ICON_EMPTY,
 | 
			
		||||
            2,
 | 
			
		||||
            DEVICE_CLASS_POWER_FACTOR,
 | 
			
		||||
            STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            accuracy_decimals=2,
 | 
			
		||||
            device_class=DEVICE_CLASS_POWER_FACTOR,
 | 
			
		||||
            state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
        ),
 | 
			
		||||
        cv.Optional(CONF_FORWARD_ACTIVE_ENERGY): sensor.sensor_schema(
 | 
			
		||||
            UNIT_WATT_HOURS,
 | 
			
		||||
            ICON_EMPTY,
 | 
			
		||||
            2,
 | 
			
		||||
            DEVICE_CLASS_ENERGY,
 | 
			
		||||
            STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            LAST_RESET_TYPE_AUTO,
 | 
			
		||||
            unit_of_measurement=UNIT_WATT_HOURS,
 | 
			
		||||
            accuracy_decimals=2,
 | 
			
		||||
            device_class=DEVICE_CLASS_ENERGY,
 | 
			
		||||
            state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            last_reset_type=LAST_RESET_TYPE_AUTO,
 | 
			
		||||
        ),
 | 
			
		||||
        cv.Optional(CONF_REVERSE_ACTIVE_ENERGY): sensor.sensor_schema(
 | 
			
		||||
            UNIT_WATT_HOURS,
 | 
			
		||||
            ICON_EMPTY,
 | 
			
		||||
            2,
 | 
			
		||||
            DEVICE_CLASS_ENERGY,
 | 
			
		||||
            STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            LAST_RESET_TYPE_AUTO,
 | 
			
		||||
            unit_of_measurement=UNIT_WATT_HOURS,
 | 
			
		||||
            accuracy_decimals=2,
 | 
			
		||||
            device_class=DEVICE_CLASS_ENERGY,
 | 
			
		||||
            state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            last_reset_type=LAST_RESET_TYPE_AUTO,
 | 
			
		||||
        ),
 | 
			
		||||
        cv.Optional(CONF_GAIN_VOLTAGE, default=7305): cv.uint16_t,
 | 
			
		||||
        cv.Optional(CONF_GAIN_CT, default=27961): cv.uint16_t,
 | 
			
		||||
@@ -120,18 +117,16 @@ CONFIG_SCHEMA = (
 | 
			
		||||
            cv.Optional(CONF_PHASE_B): ATM90E32_PHASE_SCHEMA,
 | 
			
		||||
            cv.Optional(CONF_PHASE_C): ATM90E32_PHASE_SCHEMA,
 | 
			
		||||
            cv.Optional(CONF_FREQUENCY): sensor.sensor_schema(
 | 
			
		||||
                UNIT_HERTZ,
 | 
			
		||||
                ICON_CURRENT_AC,
 | 
			
		||||
                1,
 | 
			
		||||
                DEVICE_CLASS_EMPTY,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_HERTZ,
 | 
			
		||||
                icon=ICON_CURRENT_AC,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_CHIP_TEMPERATURE): sensor.sensor_schema(
 | 
			
		||||
                UNIT_CELSIUS,
 | 
			
		||||
                ICON_EMPTY,
 | 
			
		||||
                1,
 | 
			
		||||
                DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_CELSIUS,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Required(CONF_LINE_FREQUENCY): cv.enum(LINE_FREQS, upper=True),
 | 
			
		||||
            cv.Optional(CONF_CURRENT_PHASES, default="3"): cv.enum(
 | 
			
		||||
 
 | 
			
		||||
@@ -47,7 +47,7 @@ bool BParasite::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
 | 
			
		||||
  uint16_t battery_millivolt = data[2] << 8 | data[3];
 | 
			
		||||
  float battery_voltage = battery_millivolt / 1000.0f;
 | 
			
		||||
 | 
			
		||||
  // Temperature in 1000 * Celcius.
 | 
			
		||||
  // Temperature in 1000 * Celsius.
 | 
			
		||||
  uint16_t temp_millicelcius = data[4] << 8 | data[5];
 | 
			
		||||
  float temp_celcius = temp_millicelcius / 1000.0f;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,6 @@ from esphome.const import (
 | 
			
		||||
    DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
    DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
    DEVICE_CLASS_VOLTAGE,
 | 
			
		||||
    ICON_EMPTY,
 | 
			
		||||
    STATE_CLASS_MEASUREMENT,
 | 
			
		||||
    UNIT_CELSIUS,
 | 
			
		||||
    UNIT_PERCENT,
 | 
			
		||||
@@ -33,28 +32,28 @@ CONFIG_SCHEMA = (
 | 
			
		||||
            cv.GenerateID(): cv.declare_id(BParasite),
 | 
			
		||||
            cv.Required(CONF_MAC_ADDRESS): cv.mac_address,
 | 
			
		||||
            cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
 | 
			
		||||
                UNIT_CELSIUS,
 | 
			
		||||
                ICON_EMPTY,
 | 
			
		||||
                1,
 | 
			
		||||
                DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_CELSIUS,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(
 | 
			
		||||
                UNIT_PERCENT,
 | 
			
		||||
                ICON_EMPTY,
 | 
			
		||||
                1,
 | 
			
		||||
                DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_PERCENT,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_BATTERY_VOLTAGE): sensor.sensor_schema(
 | 
			
		||||
                UNIT_VOLT, ICON_EMPTY, 3, DEVICE_CLASS_VOLTAGE, STATE_CLASS_MEASUREMENT
 | 
			
		||||
                unit_of_measurement=UNIT_VOLT,
 | 
			
		||||
                accuracy_decimals=3,
 | 
			
		||||
                device_class=DEVICE_CLASS_VOLTAGE,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_MOISTURE): sensor.sensor_schema(
 | 
			
		||||
                UNIT_PERCENT,
 | 
			
		||||
                ICON_EMPTY,
 | 
			
		||||
                1,
 | 
			
		||||
                DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_PERCENT,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ from esphome.const import (
 | 
			
		||||
    CONF_ID,
 | 
			
		||||
    CONF_RESOLUTION,
 | 
			
		||||
    DEVICE_CLASS_ILLUMINANCE,
 | 
			
		||||
    ICON_EMPTY,
 | 
			
		||||
    STATE_CLASS_MEASUREMENT,
 | 
			
		||||
    UNIT_LUX,
 | 
			
		||||
    CONF_MEASUREMENT_DURATION,
 | 
			
		||||
@@ -28,7 +27,10 @@ BH1750Sensor = bh1750_ns.class_(
 | 
			
		||||
CONF_MEASUREMENT_TIME = "measurement_time"
 | 
			
		||||
CONFIG_SCHEMA = (
 | 
			
		||||
    sensor.sensor_schema(
 | 
			
		||||
        UNIT_LUX, ICON_EMPTY, 1, DEVICE_CLASS_ILLUMINANCE, STATE_CLASS_MEASUREMENT
 | 
			
		||||
        unit_of_measurement=UNIT_LUX,
 | 
			
		||||
        accuracy_decimals=1,
 | 
			
		||||
        device_class=DEVICE_CLASS_ILLUMINANCE,
 | 
			
		||||
        state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
    )
 | 
			
		||||
    .extend(
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@ class BinaryLightOutput : public light::LightOutput {
 | 
			
		||||
  void set_output(output::BinaryOutput *output) { output_ = output; }
 | 
			
		||||
  light::LightTraits get_traits() override {
 | 
			
		||||
    auto traits = light::LightTraits();
 | 
			
		||||
    traits.set_supports_brightness(false);
 | 
			
		||||
    traits.set_supported_color_modes({light::ColorMode::ON_OFF});
 | 
			
		||||
    return traits;
 | 
			
		||||
  }
 | 
			
		||||
  void write_state(light::LightState *state) override {
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ from esphome.components import mqtt
 | 
			
		||||
from esphome.const import (
 | 
			
		||||
    CONF_DELAY,
 | 
			
		||||
    CONF_DEVICE_CLASS,
 | 
			
		||||
    CONF_DISABLED_BY_DEFAULT,
 | 
			
		||||
    CONF_FILTERS,
 | 
			
		||||
    CONF_ID,
 | 
			
		||||
    CONF_INTERNAL,
 | 
			
		||||
@@ -315,7 +316,7 @@ def validate_multi_click_timing(value):
 | 
			
		||||
 | 
			
		||||
device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space="_")
 | 
			
		||||
 | 
			
		||||
BINARY_SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend(
 | 
			
		||||
BINARY_SENSOR_SCHEMA = cv.NAMEABLE_SCHEMA.extend(cv.MQTT_COMPONENT_SCHEMA).extend(
 | 
			
		||||
    {
 | 
			
		||||
        cv.GenerateID(): cv.declare_id(BinarySensor),
 | 
			
		||||
        cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(
 | 
			
		||||
@@ -377,6 +378,7 @@ BINARY_SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend(
 | 
			
		||||
 | 
			
		||||
async def setup_binary_sensor_core_(var, config):
 | 
			
		||||
    cg.add(var.set_name(config[CONF_NAME]))
 | 
			
		||||
    cg.add(var.set_disabled_by_default(config[CONF_DISABLED_BY_DEFAULT]))
 | 
			
		||||
    if CONF_INTERNAL in config:
 | 
			
		||||
        cg.add(var.set_internal(config[CONF_INTERNAL]))
 | 
			
		||||
    if CONF_DEVICE_CLASS in config:
 | 
			
		||||
 
 | 
			
		||||
@@ -7,8 +7,6 @@ from esphome.const import (
 | 
			
		||||
    CONF_CHANNELS,
 | 
			
		||||
    CONF_VALUE,
 | 
			
		||||
    CONF_TYPE,
 | 
			
		||||
    DEVICE_CLASS_EMPTY,
 | 
			
		||||
    UNIT_EMPTY,
 | 
			
		||||
    ICON_CHECK_CIRCLE_OUTLINE,
 | 
			
		||||
    CONF_BINARY_SENSOR,
 | 
			
		||||
    CONF_GROUP,
 | 
			
		||||
@@ -35,11 +33,9 @@ entry = {
 | 
			
		||||
CONFIG_SCHEMA = cv.typed_schema(
 | 
			
		||||
    {
 | 
			
		||||
        CONF_GROUP: sensor.sensor_schema(
 | 
			
		||||
            UNIT_EMPTY,
 | 
			
		||||
            ICON_CHECK_CIRCLE_OUTLINE,
 | 
			
		||||
            0,
 | 
			
		||||
            DEVICE_CLASS_EMPTY,
 | 
			
		||||
            STATE_CLASS_NONE,
 | 
			
		||||
            icon=ICON_CHECK_CIRCLE_OUTLINE,
 | 
			
		||||
            accuracy_decimals=0,
 | 
			
		||||
            state_class=STATE_CLASS_NONE,
 | 
			
		||||
        ).extend(
 | 
			
		||||
            {
 | 
			
		||||
                cv.GenerateID(): cv.declare_id(BinarySensorMap),
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ class BLEClientNode {
 | 
			
		||||
 public:
 | 
			
		||||
  virtual void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
 | 
			
		||||
                                   esp_ble_gattc_cb_param_t *param) = 0;
 | 
			
		||||
  virtual void loop() = 0;
 | 
			
		||||
  virtual void loop(){};
 | 
			
		||||
  void set_address(uint64_t address) { address_ = address; }
 | 
			
		||||
  espbt::ESPBTClient *client;
 | 
			
		||||
  // This should be transitioned to Established once the node no longer needs
 | 
			
		||||
 
 | 
			
		||||
@@ -2,12 +2,9 @@ import esphome.codegen as cg
 | 
			
		||||
import esphome.config_validation as cv
 | 
			
		||||
from esphome.components import sensor, ble_client, esp32_ble_tracker
 | 
			
		||||
from esphome.const import (
 | 
			
		||||
    DEVICE_CLASS_EMPTY,
 | 
			
		||||
    CONF_ID,
 | 
			
		||||
    CONF_LAMBDA,
 | 
			
		||||
    STATE_CLASS_NONE,
 | 
			
		||||
    UNIT_EMPTY,
 | 
			
		||||
    ICON_EMPTY,
 | 
			
		||||
    CONF_TRIGGER_ID,
 | 
			
		||||
    CONF_SERVICE_UUID,
 | 
			
		||||
)
 | 
			
		||||
@@ -34,7 +31,8 @@ BLESensorNotifyTrigger = ble_client_ns.class_(
 | 
			
		||||
 | 
			
		||||
CONFIG_SCHEMA = cv.All(
 | 
			
		||||
    sensor.sensor_schema(
 | 
			
		||||
        UNIT_EMPTY, ICON_EMPTY, 0, DEVICE_CLASS_EMPTY, STATE_CLASS_NONE
 | 
			
		||||
        accuracy_decimals=0,
 | 
			
		||||
        state_class=STATE_CLASS_NONE,
 | 
			
		||||
    )
 | 
			
		||||
    .extend(
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,6 @@ from esphome.const import (
 | 
			
		||||
    DEVICE_CLASS_SIGNAL_STRENGTH,
 | 
			
		||||
    STATE_CLASS_MEASUREMENT,
 | 
			
		||||
    UNIT_DECIBEL,
 | 
			
		||||
    ICON_EMPTY,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
DEPENDENCIES = ["esp32_ble_tracker"]
 | 
			
		||||
@@ -20,11 +19,10 @@ BLERSSISensor = ble_rssi_ns.class_(
 | 
			
		||||
 | 
			
		||||
CONFIG_SCHEMA = cv.All(
 | 
			
		||||
    sensor.sensor_schema(
 | 
			
		||||
        UNIT_DECIBEL,
 | 
			
		||||
        ICON_EMPTY,
 | 
			
		||||
        0,
 | 
			
		||||
        DEVICE_CLASS_SIGNAL_STRENGTH,
 | 
			
		||||
        STATE_CLASS_MEASUREMENT,
 | 
			
		||||
        unit_of_measurement=UNIT_DECIBEL,
 | 
			
		||||
        accuracy_decimals=0,
 | 
			
		||||
        device_class=DEVICE_CLASS_SIGNAL_STRENGTH,
 | 
			
		||||
        state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
    )
 | 
			
		||||
    .extend(
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,6 @@ from esphome.const import (
 | 
			
		||||
    DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
    DEVICE_CLASS_PRESSURE,
 | 
			
		||||
    DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
    ICON_EMPTY,
 | 
			
		||||
    STATE_CLASS_MEASUREMENT,
 | 
			
		||||
    UNIT_CELSIUS,
 | 
			
		||||
    UNIT_HECTOPASCAL,
 | 
			
		||||
@@ -49,11 +48,10 @@ CONFIG_SCHEMA = (
 | 
			
		||||
        {
 | 
			
		||||
            cv.GenerateID(): cv.declare_id(BME280Component),
 | 
			
		||||
            cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
 | 
			
		||||
                UNIT_CELSIUS,
 | 
			
		||||
                ICON_EMPTY,
 | 
			
		||||
                1,
 | 
			
		||||
                DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_CELSIUS,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ).extend(
 | 
			
		||||
                {
 | 
			
		||||
                    cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum(
 | 
			
		||||
@@ -62,11 +60,10 @@ CONFIG_SCHEMA = (
 | 
			
		||||
                }
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_PRESSURE): sensor.sensor_schema(
 | 
			
		||||
                UNIT_HECTOPASCAL,
 | 
			
		||||
                ICON_EMPTY,
 | 
			
		||||
                1,
 | 
			
		||||
                DEVICE_CLASS_PRESSURE,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_HECTOPASCAL,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_PRESSURE,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ).extend(
 | 
			
		||||
                {
 | 
			
		||||
                    cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum(
 | 
			
		||||
@@ -75,11 +72,10 @@ CONFIG_SCHEMA = (
 | 
			
		||||
                }
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(
 | 
			
		||||
                UNIT_PERCENT,
 | 
			
		||||
                ICON_EMPTY,
 | 
			
		||||
                1,
 | 
			
		||||
                DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_PERCENT,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ).extend(
 | 
			
		||||
                {
 | 
			
		||||
                    cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum(
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,6 @@ from esphome.const import (
 | 
			
		||||
    CONF_OVERSAMPLING,
 | 
			
		||||
    CONF_PRESSURE,
 | 
			
		||||
    CONF_TEMPERATURE,
 | 
			
		||||
    DEVICE_CLASS_EMPTY,
 | 
			
		||||
    DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
    DEVICE_CLASS_PRESSURE,
 | 
			
		||||
    DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
@@ -20,7 +19,6 @@ from esphome.const import (
 | 
			
		||||
    UNIT_OHM,
 | 
			
		||||
    ICON_GAS_CYLINDER,
 | 
			
		||||
    UNIT_CELSIUS,
 | 
			
		||||
    ICON_EMPTY,
 | 
			
		||||
    UNIT_HECTOPASCAL,
 | 
			
		||||
    UNIT_PERCENT,
 | 
			
		||||
)
 | 
			
		||||
@@ -59,11 +57,10 @@ CONFIG_SCHEMA = (
 | 
			
		||||
        {
 | 
			
		||||
            cv.GenerateID(): cv.declare_id(BME680Component),
 | 
			
		||||
            cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
 | 
			
		||||
                UNIT_CELSIUS,
 | 
			
		||||
                ICON_EMPTY,
 | 
			
		||||
                1,
 | 
			
		||||
                DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_CELSIUS,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ).extend(
 | 
			
		||||
                {
 | 
			
		||||
                    cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum(
 | 
			
		||||
@@ -72,11 +69,10 @@ CONFIG_SCHEMA = (
 | 
			
		||||
                }
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_PRESSURE): sensor.sensor_schema(
 | 
			
		||||
                UNIT_HECTOPASCAL,
 | 
			
		||||
                ICON_EMPTY,
 | 
			
		||||
                1,
 | 
			
		||||
                DEVICE_CLASS_PRESSURE,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_HECTOPASCAL,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_PRESSURE,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ).extend(
 | 
			
		||||
                {
 | 
			
		||||
                    cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum(
 | 
			
		||||
@@ -85,11 +81,10 @@ CONFIG_SCHEMA = (
 | 
			
		||||
                }
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(
 | 
			
		||||
                UNIT_PERCENT,
 | 
			
		||||
                ICON_EMPTY,
 | 
			
		||||
                1,
 | 
			
		||||
                DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_PERCENT,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ).extend(
 | 
			
		||||
                {
 | 
			
		||||
                    cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum(
 | 
			
		||||
@@ -98,11 +93,10 @@ CONFIG_SCHEMA = (
 | 
			
		||||
                }
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_GAS_RESISTANCE): sensor.sensor_schema(
 | 
			
		||||
                UNIT_OHM,
 | 
			
		||||
                ICON_GAS_CYLINDER,
 | 
			
		||||
                1,
 | 
			
		||||
                DEVICE_CLASS_EMPTY,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_OHM,
 | 
			
		||||
                icon=ICON_GAS_CYLINDER,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_IIR_FILTER, default="OFF"): cv.enum(
 | 
			
		||||
                IIR_FILTER_OPTIONS, upper=True
 | 
			
		||||
 
 | 
			
		||||
@@ -6,13 +6,11 @@ from esphome.const import (
 | 
			
		||||
    CONF_HUMIDITY,
 | 
			
		||||
    CONF_PRESSURE,
 | 
			
		||||
    CONF_TEMPERATURE,
 | 
			
		||||
    DEVICE_CLASS_EMPTY,
 | 
			
		||||
    DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
    DEVICE_CLASS_PRESSURE,
 | 
			
		||||
    DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
    STATE_CLASS_MEASUREMENT,
 | 
			
		||||
    UNIT_CELSIUS,
 | 
			
		||||
    UNIT_EMPTY,
 | 
			
		||||
    UNIT_HECTOPASCAL,
 | 
			
		||||
    UNIT_OHM,
 | 
			
		||||
    UNIT_PARTS_PER_MILLION,
 | 
			
		||||
@@ -54,54 +52,60 @@ CONFIG_SCHEMA = cv.Schema(
 | 
			
		||||
    {
 | 
			
		||||
        cv.GenerateID(CONF_BME680_BSEC_ID): cv.use_id(BME680BSECComponent),
 | 
			
		||||
        cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
 | 
			
		||||
            UNIT_CELSIUS,
 | 
			
		||||
            ICON_THERMOMETER,
 | 
			
		||||
            1,
 | 
			
		||||
            DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
            STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            unit_of_measurement=UNIT_CELSIUS,
 | 
			
		||||
            icon=ICON_THERMOMETER,
 | 
			
		||||
            accuracy_decimals=1,
 | 
			
		||||
            device_class=DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
            state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
        ).extend(
 | 
			
		||||
            {cv.Optional(CONF_SAMPLE_RATE): cv.enum(SAMPLE_RATE_OPTIONS, upper=True)}
 | 
			
		||||
        ),
 | 
			
		||||
        cv.Optional(CONF_PRESSURE): sensor.sensor_schema(
 | 
			
		||||
            UNIT_HECTOPASCAL,
 | 
			
		||||
            ICON_GAUGE,
 | 
			
		||||
            1,
 | 
			
		||||
            DEVICE_CLASS_PRESSURE,
 | 
			
		||||
            STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            unit_of_measurement=UNIT_HECTOPASCAL,
 | 
			
		||||
            icon=ICON_GAUGE,
 | 
			
		||||
            accuracy_decimals=1,
 | 
			
		||||
            device_class=DEVICE_CLASS_PRESSURE,
 | 
			
		||||
            state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
        ).extend(
 | 
			
		||||
            {cv.Optional(CONF_SAMPLE_RATE): cv.enum(SAMPLE_RATE_OPTIONS, upper=True)}
 | 
			
		||||
        ),
 | 
			
		||||
        cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(
 | 
			
		||||
            UNIT_PERCENT,
 | 
			
		||||
            ICON_WATER_PERCENT,
 | 
			
		||||
            1,
 | 
			
		||||
            DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
            STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            unit_of_measurement=UNIT_PERCENT,
 | 
			
		||||
            icon=ICON_WATER_PERCENT,
 | 
			
		||||
            accuracy_decimals=1,
 | 
			
		||||
            device_class=DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
            state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
        ).extend(
 | 
			
		||||
            {cv.Optional(CONF_SAMPLE_RATE): cv.enum(SAMPLE_RATE_OPTIONS, upper=True)}
 | 
			
		||||
        ),
 | 
			
		||||
        cv.Optional(CONF_GAS_RESISTANCE): sensor.sensor_schema(
 | 
			
		||||
            UNIT_OHM, ICON_GAS_CYLINDER, 0, DEVICE_CLASS_EMPTY, STATE_CLASS_MEASUREMENT
 | 
			
		||||
            unit_of_measurement=UNIT_OHM,
 | 
			
		||||
            icon=ICON_GAS_CYLINDER,
 | 
			
		||||
            accuracy_decimals=0,
 | 
			
		||||
            state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
        ),
 | 
			
		||||
        cv.Optional(CONF_IAQ): sensor.sensor_schema(
 | 
			
		||||
            UNIT_IAQ, ICON_GAUGE, 0, DEVICE_CLASS_EMPTY, STATE_CLASS_MEASUREMENT
 | 
			
		||||
            unit_of_measurement=UNIT_IAQ,
 | 
			
		||||
            icon=ICON_GAUGE,
 | 
			
		||||
            accuracy_decimals=0,
 | 
			
		||||
            state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
        ),
 | 
			
		||||
        cv.Optional(CONF_IAQ_ACCURACY): sensor.sensor_schema(
 | 
			
		||||
            UNIT_EMPTY, ICON_ACCURACY, 0, DEVICE_CLASS_EMPTY, STATE_CLASS_MEASUREMENT
 | 
			
		||||
            icon=ICON_ACCURACY,
 | 
			
		||||
            accuracy_decimals=0,
 | 
			
		||||
            state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
        ),
 | 
			
		||||
        cv.Optional(CONF_CO2_EQUIVALENT): sensor.sensor_schema(
 | 
			
		||||
            UNIT_PARTS_PER_MILLION,
 | 
			
		||||
            ICON_TEST_TUBE,
 | 
			
		||||
            1,
 | 
			
		||||
            DEVICE_CLASS_EMPTY,
 | 
			
		||||
            STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            unit_of_measurement=UNIT_PARTS_PER_MILLION,
 | 
			
		||||
            icon=ICON_TEST_TUBE,
 | 
			
		||||
            accuracy_decimals=1,
 | 
			
		||||
            state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
        ),
 | 
			
		||||
        cv.Optional(CONF_BREATH_VOC_EQUIVALENT): sensor.sensor_schema(
 | 
			
		||||
            UNIT_PARTS_PER_MILLION,
 | 
			
		||||
            ICON_TEST_TUBE,
 | 
			
		||||
            1,
 | 
			
		||||
            DEVICE_CLASS_EMPTY,
 | 
			
		||||
            STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            unit_of_measurement=UNIT_PARTS_PER_MILLION,
 | 
			
		||||
            icon=ICON_TEST_TUBE,
 | 
			
		||||
            accuracy_decimals=1,
 | 
			
		||||
            state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
        ),
 | 
			
		||||
    }
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,6 @@ from esphome.const import (
 | 
			
		||||
    DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
    STATE_CLASS_MEASUREMENT,
 | 
			
		||||
    UNIT_CELSIUS,
 | 
			
		||||
    ICON_EMPTY,
 | 
			
		||||
    UNIT_HECTOPASCAL,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -25,18 +24,16 @@ CONFIG_SCHEMA = (
 | 
			
		||||
        {
 | 
			
		||||
            cv.GenerateID(): cv.declare_id(BMP085Component),
 | 
			
		||||
            cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
 | 
			
		||||
                UNIT_CELSIUS,
 | 
			
		||||
                ICON_EMPTY,
 | 
			
		||||
                1,
 | 
			
		||||
                DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_CELSIUS,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_PRESSURE): sensor.sensor_schema(
 | 
			
		||||
                UNIT_HECTOPASCAL,
 | 
			
		||||
                ICON_EMPTY,
 | 
			
		||||
                1,
 | 
			
		||||
                DEVICE_CLASS_PRESSURE,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_HECTOPASCAL,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_PRESSURE,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,6 @@ from esphome.const import (
 | 
			
		||||
    DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
    STATE_CLASS_MEASUREMENT,
 | 
			
		||||
    UNIT_CELSIUS,
 | 
			
		||||
    ICON_EMPTY,
 | 
			
		||||
    UNIT_HECTOPASCAL,
 | 
			
		||||
    CONF_IIR_FILTER,
 | 
			
		||||
    CONF_OVERSAMPLING,
 | 
			
		||||
@@ -46,11 +45,10 @@ CONFIG_SCHEMA = (
 | 
			
		||||
        {
 | 
			
		||||
            cv.GenerateID(): cv.declare_id(BMP280Component),
 | 
			
		||||
            cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
 | 
			
		||||
                UNIT_CELSIUS,
 | 
			
		||||
                ICON_EMPTY,
 | 
			
		||||
                1,
 | 
			
		||||
                DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_CELSIUS,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ).extend(
 | 
			
		||||
                {
 | 
			
		||||
                    cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum(
 | 
			
		||||
@@ -59,11 +57,10 @@ CONFIG_SCHEMA = (
 | 
			
		||||
                }
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_PRESSURE): sensor.sensor_schema(
 | 
			
		||||
                UNIT_HECTOPASCAL,
 | 
			
		||||
                ICON_EMPTY,
 | 
			
		||||
                1,
 | 
			
		||||
                DEVICE_CLASS_PRESSURE,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_HECTOPASCAL,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_PRESSURE,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ).extend(
 | 
			
		||||
                {
 | 
			
		||||
                    cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum(
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,6 @@ import esphome.config_validation as cv
 | 
			
		||||
from esphome.components import i2c, sensor
 | 
			
		||||
from esphome.const import (
 | 
			
		||||
    CONF_ID,
 | 
			
		||||
    DEVICE_CLASS_EMPTY,
 | 
			
		||||
    ICON_RADIATOR,
 | 
			
		||||
    STATE_CLASS_MEASUREMENT,
 | 
			
		||||
    UNIT_PARTS_PER_MILLION,
 | 
			
		||||
@@ -28,18 +27,16 @@ CONFIG_SCHEMA = (
 | 
			
		||||
        {
 | 
			
		||||
            cv.GenerateID(): cv.declare_id(CCS811Component),
 | 
			
		||||
            cv.Required(CONF_ECO2): sensor.sensor_schema(
 | 
			
		||||
                UNIT_PARTS_PER_MILLION,
 | 
			
		||||
                ICON_MOLECULE_CO2,
 | 
			
		||||
                0,
 | 
			
		||||
                DEVICE_CLASS_EMPTY,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_PARTS_PER_MILLION,
 | 
			
		||||
                icon=ICON_MOLECULE_CO2,
 | 
			
		||||
                accuracy_decimals=0,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Required(CONF_TVOC): sensor.sensor_schema(
 | 
			
		||||
                UNIT_PARTS_PER_BILLION,
 | 
			
		||||
                ICON_RADIATOR,
 | 
			
		||||
                0,
 | 
			
		||||
                DEVICE_CLASS_EMPTY,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_PARTS_PER_BILLION,
 | 
			
		||||
                icon=ICON_RADIATOR,
 | 
			
		||||
                accuracy_decimals=0,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_BASELINE): cv.hex_uint16_t,
 | 
			
		||||
            cv.Optional(CONF_TEMPERATURE): cv.use_id(sensor.Sensor),
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ from esphome.const import (
 | 
			
		||||
    CONF_AWAY,
 | 
			
		||||
    CONF_CUSTOM_FAN_MODE,
 | 
			
		||||
    CONF_CUSTOM_PRESET,
 | 
			
		||||
    CONF_DISABLED_BY_DEFAULT,
 | 
			
		||||
    CONF_ID,
 | 
			
		||||
    CONF_INTERNAL,
 | 
			
		||||
    CONF_MAX_TEMPERATURE,
 | 
			
		||||
@@ -86,7 +87,7 @@ validate_climate_swing_mode = cv.enum(CLIMATE_SWING_MODES, upper=True)
 | 
			
		||||
# Actions
 | 
			
		||||
ControlAction = climate_ns.class_("ControlAction", automation.Action)
 | 
			
		||||
 | 
			
		||||
CLIMATE_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend(
 | 
			
		||||
CLIMATE_SCHEMA = cv.NAMEABLE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).extend(
 | 
			
		||||
    {
 | 
			
		||||
        cv.GenerateID(): cv.declare_id(Climate),
 | 
			
		||||
        cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTClimateComponent),
 | 
			
		||||
@@ -104,6 +105,7 @@ CLIMATE_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend(
 | 
			
		||||
 | 
			
		||||
async def setup_climate_core_(var, config):
 | 
			
		||||
    cg.add(var.set_name(config[CONF_NAME]))
 | 
			
		||||
    cg.add(var.set_disabled_by_default(config[CONF_DISABLED_BY_DEFAULT]))
 | 
			
		||||
    if CONF_INTERNAL in config:
 | 
			
		||||
        cg.add(var.set_internal(config[CONF_INTERNAL]))
 | 
			
		||||
    visual = config[CONF_VISUAL]
 | 
			
		||||
 
 | 
			
		||||
@@ -312,8 +312,12 @@ void Climate::add_on_state_callback(std::function<void()> &&callback) {
 | 
			
		||||
  this->state_callback_.add(std::move(callback));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Random 32bit value; If this changes existing restore preferences are invalidated
 | 
			
		||||
static const uint32_t RESTORE_STATE_VERSION = 0x848EA6ADUL;
 | 
			
		||||
 | 
			
		||||
optional<ClimateDeviceRestoreState> Climate::restore_state_() {
 | 
			
		||||
  this->rtc_ = global_preferences.make_preference<ClimateDeviceRestoreState>(this->get_object_id_hash());
 | 
			
		||||
  this->rtc_ =
 | 
			
		||||
      global_preferences.make_preference<ClimateDeviceRestoreState>(this->get_object_id_hash() ^ RESTORE_STATE_VERSION);
 | 
			
		||||
  ClimateDeviceRestoreState recovered{};
 | 
			
		||||
  if (!this->rtc_.load(&recovered))
 | 
			
		||||
    return {};
 | 
			
		||||
 
 | 
			
		||||
@@ -63,9 +63,9 @@ class ClimateCall {
 | 
			
		||||
   * For climate devices with two point target temperature control
 | 
			
		||||
   */
 | 
			
		||||
  ClimateCall &set_target_temperature_high(optional<float> target_temperature_high);
 | 
			
		||||
  ESPDEPRECATED("set_away() is deprecated, please use .set_preset(CLIMATE_PRESET_AWAY) instead")
 | 
			
		||||
  ESPDEPRECATED("set_away() is deprecated, please use .set_preset(CLIMATE_PRESET_AWAY) instead", "v1.20")
 | 
			
		||||
  ClimateCall &set_away(bool away);
 | 
			
		||||
  ESPDEPRECATED("set_away() is deprecated, please use .set_preset(CLIMATE_PRESET_AWAY) instead")
 | 
			
		||||
  ESPDEPRECATED("set_away() is deprecated, please use .set_preset(CLIMATE_PRESET_AWAY) instead", "v1.20")
 | 
			
		||||
  ClimateCall &set_away(optional<bool> away);
 | 
			
		||||
  /// Set the fan mode of the climate device.
 | 
			
		||||
  ClimateCall &set_fan_mode(ClimateFanMode fan_mode);
 | 
			
		||||
@@ -96,7 +96,7 @@ class ClimateCall {
 | 
			
		||||
  const optional<float> &get_target_temperature() const;
 | 
			
		||||
  const optional<float> &get_target_temperature_low() const;
 | 
			
		||||
  const optional<float> &get_target_temperature_high() const;
 | 
			
		||||
  ESPDEPRECATED("get_away() is deprecated, please use .get_preset() instead")
 | 
			
		||||
  ESPDEPRECATED("get_away() is deprecated, please use .get_preset() instead", "v1.20")
 | 
			
		||||
  optional<bool> get_away() const;
 | 
			
		||||
  const optional<ClimateFanMode> &get_fan_mode() const;
 | 
			
		||||
  const optional<ClimateSwingMode> &get_swing_mode() const;
 | 
			
		||||
@@ -120,6 +120,7 @@ class ClimateCall {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// Struct used to save the state of the climate device in restore memory.
 | 
			
		||||
/// Make sure to update RESTORE_STATE_VERSION when changing the struct entries.
 | 
			
		||||
struct ClimateDeviceRestoreState {
 | 
			
		||||
  ClimateMode mode;
 | 
			
		||||
  bool uses_custom_fan_mode{false};
 | 
			
		||||
@@ -192,7 +193,7 @@ class Climate : public Nameable {
 | 
			
		||||
   * Away allows climate devices to have two different target temperature configs:
 | 
			
		||||
   * one for normal mode and one for away mode.
 | 
			
		||||
   */
 | 
			
		||||
  ESPDEPRECATED("away is deprecated, use preset instead")
 | 
			
		||||
  ESPDEPRECATED("away is deprecated, use preset instead", "v1.20")
 | 
			
		||||
  bool away{false};
 | 
			
		||||
 | 
			
		||||
  /// The active fan mode of the climate device.
 | 
			
		||||
 
 | 
			
		||||
@@ -50,19 +50,19 @@ class ClimateTraits {
 | 
			
		||||
  }
 | 
			
		||||
  void set_supported_modes(std::set<ClimateMode> modes) { supported_modes_ = std::move(modes); }
 | 
			
		||||
  void add_supported_mode(ClimateMode mode) { supported_modes_.insert(mode); }
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_modes() instead")
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_modes() instead", "v1.20")
 | 
			
		||||
  void set_supports_auto_mode(bool supports_auto_mode) { set_mode_support_(CLIMATE_MODE_AUTO, supports_auto_mode); }
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_modes() instead")
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_modes() instead", "v1.20")
 | 
			
		||||
  void set_supports_cool_mode(bool supports_cool_mode) { set_mode_support_(CLIMATE_MODE_COOL, supports_cool_mode); }
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_modes() instead")
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_modes() instead", "v1.20")
 | 
			
		||||
  void set_supports_heat_mode(bool supports_heat_mode) { set_mode_support_(CLIMATE_MODE_HEAT, supports_heat_mode); }
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_modes() instead")
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_modes() instead", "v1.20")
 | 
			
		||||
  void set_supports_heat_cool_mode(bool supported) { set_mode_support_(CLIMATE_MODE_HEAT_COOL, supported); }
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_modes() instead")
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_modes() instead", "v1.20")
 | 
			
		||||
  void set_supports_fan_only_mode(bool supports_fan_only_mode) {
 | 
			
		||||
    set_mode_support_(CLIMATE_MODE_FAN_ONLY, supports_fan_only_mode);
 | 
			
		||||
  }
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_modes() instead")
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_modes() instead", "v1.20")
 | 
			
		||||
  void set_supports_dry_mode(bool supports_dry_mode) { set_mode_support_(CLIMATE_MODE_DRY, supports_dry_mode); }
 | 
			
		||||
  bool supports_mode(ClimateMode mode) const { return supported_modes_.count(mode); }
 | 
			
		||||
  const std::set<ClimateMode> get_supported_modes() const { return supported_modes_; }
 | 
			
		||||
@@ -72,23 +72,23 @@ class ClimateTraits {
 | 
			
		||||
 | 
			
		||||
  void set_supported_fan_modes(std::set<ClimateFanMode> modes) { supported_fan_modes_ = std::move(modes); }
 | 
			
		||||
  void add_supported_fan_mode(ClimateFanMode mode) { supported_fan_modes_.insert(mode); }
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_fan_modes() instead")
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_fan_modes() instead", "v1.20")
 | 
			
		||||
  void set_supports_fan_mode_on(bool supported) { set_fan_mode_support_(CLIMATE_FAN_ON, supported); }
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_fan_modes() instead")
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_fan_modes() instead", "v1.20")
 | 
			
		||||
  void set_supports_fan_mode_off(bool supported) { set_fan_mode_support_(CLIMATE_FAN_OFF, supported); }
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_fan_modes() instead")
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_fan_modes() instead", "v1.20")
 | 
			
		||||
  void set_supports_fan_mode_auto(bool supported) { set_fan_mode_support_(CLIMATE_FAN_AUTO, supported); }
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_fan_modes() instead")
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_fan_modes() instead", "v1.20")
 | 
			
		||||
  void set_supports_fan_mode_low(bool supported) { set_fan_mode_support_(CLIMATE_FAN_LOW, supported); }
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_fan_modes() instead")
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_fan_modes() instead", "v1.20")
 | 
			
		||||
  void set_supports_fan_mode_medium(bool supported) { set_fan_mode_support_(CLIMATE_FAN_MEDIUM, supported); }
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_fan_modes() instead")
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_fan_modes() instead", "v1.20")
 | 
			
		||||
  void set_supports_fan_mode_high(bool supported) { set_fan_mode_support_(CLIMATE_FAN_HIGH, supported); }
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_fan_modes() instead")
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_fan_modes() instead", "v1.20")
 | 
			
		||||
  void set_supports_fan_mode_middle(bool supported) { set_fan_mode_support_(CLIMATE_FAN_MIDDLE, supported); }
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_fan_modes() instead")
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_fan_modes() instead", "v1.20")
 | 
			
		||||
  void set_supports_fan_mode_focus(bool supported) { set_fan_mode_support_(CLIMATE_FAN_FOCUS, supported); }
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_fan_modes() instead")
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_fan_modes() instead", "v1.20")
 | 
			
		||||
  void set_supports_fan_mode_diffuse(bool supported) { set_fan_mode_support_(CLIMATE_FAN_DIFFUSE, supported); }
 | 
			
		||||
  bool supports_fan_mode(ClimateFanMode fan_mode) const { return supported_fan_modes_.count(fan_mode); }
 | 
			
		||||
  bool get_supports_fan_modes() const { return !supported_fan_modes_.empty() || !supported_custom_fan_modes_.empty(); }
 | 
			
		||||
@@ -115,25 +115,25 @@ class ClimateTraits {
 | 
			
		||||
  bool supports_custom_preset(const std::string &custom_preset) const {
 | 
			
		||||
    return supported_custom_presets_.count(custom_preset);
 | 
			
		||||
  }
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_presets() instead")
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_presets() instead", "v1.20")
 | 
			
		||||
  void set_supports_away(bool supports) {
 | 
			
		||||
    if (supports) {
 | 
			
		||||
      supported_presets_.insert(CLIMATE_PRESET_AWAY);
 | 
			
		||||
      supported_presets_.insert(CLIMATE_PRESET_HOME);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use supports_preset() instead")
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use supports_preset() instead", "v1.20")
 | 
			
		||||
  bool get_supports_away() const { return supports_preset(CLIMATE_PRESET_AWAY); }
 | 
			
		||||
 | 
			
		||||
  void set_supported_swing_modes(std::set<ClimateSwingMode> modes) { supported_swing_modes_ = std::move(modes); }
 | 
			
		||||
  void add_supported_swing_mode(ClimateSwingMode mode) { supported_swing_modes_.insert(mode); }
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_swing_modes() instead")
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_swing_modes() instead", "v1.20")
 | 
			
		||||
  void set_supports_swing_mode_off(bool supported) { set_swing_mode_support_(CLIMATE_SWING_OFF, supported); }
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_swing_modes() instead")
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_swing_modes() instead", "v1.20")
 | 
			
		||||
  void set_supports_swing_mode_both(bool supported) { set_swing_mode_support_(CLIMATE_SWING_BOTH, supported); }
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_swing_modes() instead")
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_swing_modes() instead", "v1.20")
 | 
			
		||||
  void set_supports_swing_mode_vertical(bool supported) { set_swing_mode_support_(CLIMATE_SWING_VERTICAL, supported); }
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_swing_modes() instead")
 | 
			
		||||
  ESPDEPRECATED("This method is deprecated, use set_supported_swing_modes() instead", "v1.20")
 | 
			
		||||
  void set_supports_swing_mode_horizontal(bool supported) {
 | 
			
		||||
    set_swing_mode_support_(CLIMATE_SWING_HORIZONTAL, supported);
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										0
									
								
								esphome/components/color_temperature/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								esphome/components/color_temperature/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										38
									
								
								esphome/components/color_temperature/ct_light_output.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								esphome/components/color_temperature/ct_light_output.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "esphome/components/light/light_output.h"
 | 
			
		||||
#include "esphome/components/output/float_output.h"
 | 
			
		||||
#include "esphome/core/component.h"
 | 
			
		||||
 | 
			
		||||
namespace esphome {
 | 
			
		||||
namespace color_temperature {
 | 
			
		||||
 | 
			
		||||
class CTLightOutput : public light::LightOutput {
 | 
			
		||||
 public:
 | 
			
		||||
  void set_color_temperature(output::FloatOutput *color_temperature) { color_temperature_ = color_temperature; }
 | 
			
		||||
  void set_brightness(output::FloatOutput *brightness) { brightness_ = brightness; }
 | 
			
		||||
  void set_cold_white_temperature(float cold_white_temperature) { cold_white_temperature_ = cold_white_temperature; }
 | 
			
		||||
  void set_warm_white_temperature(float warm_white_temperature) { warm_white_temperature_ = warm_white_temperature; }
 | 
			
		||||
  light::LightTraits get_traits() override {
 | 
			
		||||
    auto traits = light::LightTraits();
 | 
			
		||||
    traits.set_supported_color_modes({light::ColorMode::COLOR_TEMPERATURE});
 | 
			
		||||
    traits.set_min_mireds(this->cold_white_temperature_);
 | 
			
		||||
    traits.set_max_mireds(this->warm_white_temperature_);
 | 
			
		||||
    return traits;
 | 
			
		||||
  }
 | 
			
		||||
  void write_state(light::LightState *state) override {
 | 
			
		||||
    float color_temperature, brightness;
 | 
			
		||||
    state->current_values_as_ct(&color_temperature, &brightness);
 | 
			
		||||
    this->color_temperature_->set_level(color_temperature);
 | 
			
		||||
    this->brightness_->set_level(brightness);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  output::FloatOutput *color_temperature_;
 | 
			
		||||
  output::FloatOutput *brightness_;
 | 
			
		||||
  float cold_white_temperature_;
 | 
			
		||||
  float warm_white_temperature_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace color_temperature
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
							
								
								
									
										42
									
								
								esphome/components/color_temperature/light.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								esphome/components/color_temperature/light.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
import esphome.codegen as cg
 | 
			
		||||
import esphome.config_validation as cv
 | 
			
		||||
from esphome.components import light, output
 | 
			
		||||
from esphome.const import (
 | 
			
		||||
    CONF_BRIGHTNESS,
 | 
			
		||||
    CONF_COLOR_TEMPERATURE,
 | 
			
		||||
    CONF_OUTPUT_ID,
 | 
			
		||||
    CONF_COLD_WHITE_COLOR_TEMPERATURE,
 | 
			
		||||
    CONF_WARM_WHITE_COLOR_TEMPERATURE,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
CODEOWNERS = ["@jesserockz"]
 | 
			
		||||
 | 
			
		||||
color_temperature_ns = cg.esphome_ns.namespace("color_temperature")
 | 
			
		||||
CTLightOutput = color_temperature_ns.class_("CTLightOutput", light.LightOutput)
 | 
			
		||||
 | 
			
		||||
CONFIG_SCHEMA = cv.All(
 | 
			
		||||
    light.RGB_LIGHT_SCHEMA.extend(
 | 
			
		||||
        {
 | 
			
		||||
            cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(CTLightOutput),
 | 
			
		||||
            cv.Required(CONF_COLOR_TEMPERATURE): cv.use_id(output.FloatOutput),
 | 
			
		||||
            cv.Required(CONF_BRIGHTNESS): cv.use_id(output.FloatOutput),
 | 
			
		||||
            cv.Required(CONF_COLD_WHITE_COLOR_TEMPERATURE): cv.color_temperature,
 | 
			
		||||
            cv.Required(CONF_WARM_WHITE_COLOR_TEMPERATURE): cv.color_temperature,
 | 
			
		||||
        }
 | 
			
		||||
    ),
 | 
			
		||||
    light.validate_color_temperature_channels,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async def to_code(config):
 | 
			
		||||
    var = cg.new_Pvariable(config[CONF_OUTPUT_ID])
 | 
			
		||||
    await light.register_light(var, config)
 | 
			
		||||
 | 
			
		||||
    color_temperature = await cg.get_variable(config[CONF_COLOR_TEMPERATURE])
 | 
			
		||||
    cg.add(var.set_color_temperature(color_temperature))
 | 
			
		||||
 | 
			
		||||
    brightness = await cg.get_variable(config[CONF_BRIGHTNESS])
 | 
			
		||||
    cg.add(var.set_brightness(brightness))
 | 
			
		||||
 | 
			
		||||
    cg.add(var.set_cold_white_temperature(config[CONF_COLD_WHITE_COLOR_TEMPERATURE]))
 | 
			
		||||
    cg.add(var.set_warm_white_temperature(config[CONF_WARM_WHITE_COLOR_TEMPERATURE]))
 | 
			
		||||
@@ -4,6 +4,7 @@ from esphome import automation
 | 
			
		||||
from esphome.automation import maybe_simple_id, Condition
 | 
			
		||||
from esphome.components import mqtt
 | 
			
		||||
from esphome.const import (
 | 
			
		||||
    CONF_DISABLED_BY_DEFAULT,
 | 
			
		||||
    CONF_ID,
 | 
			
		||||
    CONF_INTERNAL,
 | 
			
		||||
    CONF_DEVICE_CLASS,
 | 
			
		||||
@@ -63,7 +64,7 @@ CoverPublishAction = cover_ns.class_("CoverPublishAction", automation.Action)
 | 
			
		||||
CoverIsOpenCondition = cover_ns.class_("CoverIsOpenCondition", Condition)
 | 
			
		||||
CoverIsClosedCondition = cover_ns.class_("CoverIsClosedCondition", Condition)
 | 
			
		||||
 | 
			
		||||
COVER_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend(
 | 
			
		||||
COVER_SCHEMA = cv.NAMEABLE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).extend(
 | 
			
		||||
    {
 | 
			
		||||
        cv.GenerateID(): cv.declare_id(Cover),
 | 
			
		||||
        cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTCoverComponent),
 | 
			
		||||
@@ -75,6 +76,7 @@ COVER_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend(
 | 
			
		||||
 | 
			
		||||
async def setup_cover_core_(var, config):
 | 
			
		||||
    cg.add(var.set_name(config[CONF_NAME]))
 | 
			
		||||
    cg.add(var.set_disabled_by_default(config[CONF_DISABLED_BY_DEFAULT]))
 | 
			
		||||
    if CONF_INTERNAL in config:
 | 
			
		||||
        cg.add(var.set_internal(config[CONF_INTERNAL]))
 | 
			
		||||
    if CONF_DEVICE_CLASS in config:
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,6 @@ from esphome.const import (
 | 
			
		||||
    UNIT_VOLT,
 | 
			
		||||
    UNIT_AMPERE,
 | 
			
		||||
    UNIT_WATT,
 | 
			
		||||
    ICON_EMPTY,
 | 
			
		||||
    DEVICE_CLASS_POWER,
 | 
			
		||||
    DEVICE_CLASS_CURRENT,
 | 
			
		||||
    DEVICE_CLASS_VOLTAGE,
 | 
			
		||||
@@ -80,13 +79,19 @@ CONFIG_SCHEMA = cv.All(
 | 
			
		||||
            cv.Optional(CONF_VOLTAGE_HPF, default=True): cv.boolean,
 | 
			
		||||
            cv.Optional(CONF_PULSE_ENERGY, default=10.0): validate_energy,
 | 
			
		||||
            cv.Optional(CONF_VOLTAGE): sensor.sensor_schema(
 | 
			
		||||
                UNIT_VOLT, ICON_EMPTY, 0, DEVICE_CLASS_VOLTAGE
 | 
			
		||||
                unit_of_measurement=UNIT_VOLT,
 | 
			
		||||
                accuracy_decimals=0,
 | 
			
		||||
                device_class=DEVICE_CLASS_VOLTAGE,
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_CURRENT): sensor.sensor_schema(
 | 
			
		||||
                UNIT_AMPERE, ICON_EMPTY, 1, DEVICE_CLASS_CURRENT
 | 
			
		||||
                unit_of_measurement=UNIT_AMPERE,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_CURRENT,
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_POWER): sensor.sensor_schema(
 | 
			
		||||
                UNIT_WATT, ICON_EMPTY, 0, DEVICE_CLASS_POWER
 | 
			
		||||
                unit_of_measurement=UNIT_WATT,
 | 
			
		||||
                accuracy_decimals=0,
 | 
			
		||||
                device_class=DEVICE_CLASS_POWER,
 | 
			
		||||
            ),
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,6 @@ from esphome.const import (
 | 
			
		||||
    DEVICE_CLASS_CURRENT,
 | 
			
		||||
    DEVICE_CLASS_POWER,
 | 
			
		||||
    DEVICE_CLASS_VOLTAGE,
 | 
			
		||||
    ICON_EMPTY,
 | 
			
		||||
    STATE_CLASS_MEASUREMENT,
 | 
			
		||||
    UNIT_VOLT,
 | 
			
		||||
    UNIT_AMPERE,
 | 
			
		||||
@@ -28,17 +27,22 @@ CONFIG_SCHEMA = (
 | 
			
		||||
        {
 | 
			
		||||
            cv.GenerateID(): cv.declare_id(CSE7766Component),
 | 
			
		||||
            cv.Optional(CONF_VOLTAGE): sensor.sensor_schema(
 | 
			
		||||
                UNIT_VOLT, ICON_EMPTY, 1, DEVICE_CLASS_VOLTAGE, STATE_CLASS_MEASUREMENT
 | 
			
		||||
                unit_of_measurement=UNIT_VOLT,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_VOLTAGE,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_CURRENT): sensor.sensor_schema(
 | 
			
		||||
                UNIT_AMPERE,
 | 
			
		||||
                ICON_EMPTY,
 | 
			
		||||
                2,
 | 
			
		||||
                DEVICE_CLASS_CURRENT,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_AMPERE,
 | 
			
		||||
                accuracy_decimals=2,
 | 
			
		||||
                device_class=DEVICE_CLASS_CURRENT,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_POWER): sensor.sensor_schema(
 | 
			
		||||
                UNIT_WATT, ICON_EMPTY, 1, DEVICE_CLASS_POWER, STATE_CLASS_MEASUREMENT
 | 
			
		||||
                unit_of_measurement=UNIT_WATT,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_POWER,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ from esphome.const import (
 | 
			
		||||
    CONF_SENSOR,
 | 
			
		||||
    CONF_ID,
 | 
			
		||||
    DEVICE_CLASS_CURRENT,
 | 
			
		||||
    ICON_EMPTY,
 | 
			
		||||
    STATE_CLASS_MEASUREMENT,
 | 
			
		||||
    UNIT_AMPERE,
 | 
			
		||||
)
 | 
			
		||||
@@ -20,7 +19,10 @@ CTClampSensor = ct_clamp_ns.class_("CTClampSensor", sensor.Sensor, cg.PollingCom
 | 
			
		||||
 | 
			
		||||
CONFIG_SCHEMA = (
 | 
			
		||||
    sensor.sensor_schema(
 | 
			
		||||
        UNIT_AMPERE, ICON_EMPTY, 2, DEVICE_CLASS_CURRENT, STATE_CLASS_MEASUREMENT
 | 
			
		||||
        unit_of_measurement=UNIT_AMPERE,
 | 
			
		||||
        accuracy_decimals=2,
 | 
			
		||||
        device_class=DEVICE_CLASS_CURRENT,
 | 
			
		||||
        state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
    )
 | 
			
		||||
    .extend(
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -16,10 +16,7 @@ class CWWWLightOutput : public light::LightOutput {
 | 
			
		||||
  void set_constant_brightness(bool constant_brightness) { constant_brightness_ = constant_brightness; }
 | 
			
		||||
  light::LightTraits get_traits() override {
 | 
			
		||||
    auto traits = light::LightTraits();
 | 
			
		||||
    traits.set_supports_brightness(true);
 | 
			
		||||
    traits.set_supports_rgb(false);
 | 
			
		||||
    traits.set_supports_rgb_white_value(false);
 | 
			
		||||
    traits.set_supports_color_temperature(true);
 | 
			
		||||
    traits.set_supported_color_modes({light::ColorMode::COLD_WARM_WHITE});
 | 
			
		||||
    traits.set_min_mireds(this->cold_white_temperature_);
 | 
			
		||||
    traits.set_max_mireds(this->warm_white_temperature_);
 | 
			
		||||
    return traits;
 | 
			
		||||
@@ -34,8 +31,8 @@ class CWWWLightOutput : public light::LightOutput {
 | 
			
		||||
 protected:
 | 
			
		||||
  output::FloatOutput *cold_white_;
 | 
			
		||||
  output::FloatOutput *warm_white_;
 | 
			
		||||
  float cold_white_temperature_;
 | 
			
		||||
  float warm_white_temperature_;
 | 
			
		||||
  float cold_white_temperature_{0};
 | 
			
		||||
  float warm_white_temperature_{0};
 | 
			
		||||
  bool constant_brightness_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@ import esphome.codegen as cg
 | 
			
		||||
import esphome.config_validation as cv
 | 
			
		||||
from esphome.components import light, output
 | 
			
		||||
from esphome.const import (
 | 
			
		||||
    CONF_CONSTANT_BRIGHTNESS,
 | 
			
		||||
    CONF_OUTPUT_ID,
 | 
			
		||||
    CONF_COLD_WHITE,
 | 
			
		||||
    CONF_WARM_WHITE,
 | 
			
		||||
@@ -12,19 +13,20 @@ from esphome.const import (
 | 
			
		||||
cwww_ns = cg.esphome_ns.namespace("cwww")
 | 
			
		||||
CWWWLightOutput = cwww_ns.class_("CWWWLightOutput", light.LightOutput)
 | 
			
		||||
 | 
			
		||||
CONF_CONSTANT_BRIGHTNESS = "constant_brightness"
 | 
			
		||||
 | 
			
		||||
CONFIG_SCHEMA = cv.All(
 | 
			
		||||
    light.RGB_LIGHT_SCHEMA.extend(
 | 
			
		||||
        {
 | 
			
		||||
            cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(CWWWLightOutput),
 | 
			
		||||
            cv.Required(CONF_COLD_WHITE): cv.use_id(output.FloatOutput),
 | 
			
		||||
            cv.Required(CONF_WARM_WHITE): cv.use_id(output.FloatOutput),
 | 
			
		||||
            cv.Required(CONF_COLD_WHITE_COLOR_TEMPERATURE): cv.color_temperature,
 | 
			
		||||
            cv.Required(CONF_WARM_WHITE_COLOR_TEMPERATURE): cv.color_temperature,
 | 
			
		||||
            cv.Optional(CONF_COLD_WHITE_COLOR_TEMPERATURE): cv.color_temperature,
 | 
			
		||||
            cv.Optional(CONF_WARM_WHITE_COLOR_TEMPERATURE): cv.color_temperature,
 | 
			
		||||
            cv.Optional(CONF_CONSTANT_BRIGHTNESS, default=False): cv.boolean,
 | 
			
		||||
        }
 | 
			
		||||
    ),
 | 
			
		||||
    cv.has_none_or_all_keys(
 | 
			
		||||
        [CONF_COLD_WHITE_COLOR_TEMPERATURE, CONF_WARM_WHITE_COLOR_TEMPERATURE]
 | 
			
		||||
    ),
 | 
			
		||||
    light.validate_color_temperature_channels,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -32,11 +34,19 @@ CONFIG_SCHEMA = cv.All(
 | 
			
		||||
async def to_code(config):
 | 
			
		||||
    var = cg.new_Pvariable(config[CONF_OUTPUT_ID])
 | 
			
		||||
    await light.register_light(var, config)
 | 
			
		||||
 | 
			
		||||
    cwhite = await cg.get_variable(config[CONF_COLD_WHITE])
 | 
			
		||||
    cg.add(var.set_cold_white(cwhite))
 | 
			
		||||
    cg.add(var.set_cold_white_temperature(config[CONF_COLD_WHITE_COLOR_TEMPERATURE]))
 | 
			
		||||
    if CONF_COLD_WHITE_COLOR_TEMPERATURE in config:
 | 
			
		||||
        cg.add(
 | 
			
		||||
            var.set_cold_white_temperature(config[CONF_COLD_WHITE_COLOR_TEMPERATURE])
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    wwhite = await cg.get_variable(config[CONF_WARM_WHITE])
 | 
			
		||||
    cg.add(var.set_warm_white(wwhite))
 | 
			
		||||
    cg.add(var.set_warm_white_temperature(config[CONF_WARM_WHITE_COLOR_TEMPERATURE]))
 | 
			
		||||
    if CONF_WARM_WHITE_COLOR_TEMPERATURE in config:
 | 
			
		||||
        cg.add(
 | 
			
		||||
            var.set_warm_white_temperature(config[CONF_WARM_WHITE_COLOR_TEMPERATURE])
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    cg.add(var.set_constant_brightness(config[CONF_CONSTANT_BRIGHTNESS]))
 | 
			
		||||
 
 | 
			
		||||
@@ -137,7 +137,7 @@ void DallasComponent::update() {
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (!res) {
 | 
			
		||||
        ESP_LOGW(TAG, "'%s' - Reseting bus for read failed!", sensor->get_name().c_str());
 | 
			
		||||
        ESP_LOGW(TAG, "'%s' - Resetting bus for read failed!", sensor->get_name().c_str());
 | 
			
		||||
        sensor->publish_state(NAN);
 | 
			
		||||
        this->status_set_warning();
 | 
			
		||||
        return;
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,6 @@ from esphome.const import (
 | 
			
		||||
    CONF_INDEX,
 | 
			
		||||
    CONF_RESOLUTION,
 | 
			
		||||
    DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
    ICON_EMPTY,
 | 
			
		||||
    STATE_CLASS_MEASUREMENT,
 | 
			
		||||
    UNIT_CELSIUS,
 | 
			
		||||
    CONF_ID,
 | 
			
		||||
@@ -18,7 +17,10 @@ DallasTemperatureSensor = dallas_ns.class_("DallasTemperatureSensor", sensor.Sen
 | 
			
		||||
 | 
			
		||||
CONFIG_SCHEMA = cv.All(
 | 
			
		||||
    sensor.sensor_schema(
 | 
			
		||||
        UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE, STATE_CLASS_MEASUREMENT
 | 
			
		||||
        unit_of_measurement=UNIT_CELSIUS,
 | 
			
		||||
        accuracy_decimals=1,
 | 
			
		||||
        device_class=DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
        state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
    ).extend(
 | 
			
		||||
        {
 | 
			
		||||
            cv.GenerateID(): cv.declare_id(DallasTemperatureSensor),
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										451
									
								
								esphome/components/demo/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										451
									
								
								esphome/components/demo/__init__.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,451 @@
 | 
			
		||||
import esphome.codegen as cg
 | 
			
		||||
import esphome.config_validation as cv
 | 
			
		||||
from esphome.components import (
 | 
			
		||||
    binary_sensor,
 | 
			
		||||
    climate,
 | 
			
		||||
    cover,
 | 
			
		||||
    fan,
 | 
			
		||||
    light,
 | 
			
		||||
    number,
 | 
			
		||||
    sensor,
 | 
			
		||||
    switch,
 | 
			
		||||
    text_sensor,
 | 
			
		||||
)
 | 
			
		||||
from esphome.const import (
 | 
			
		||||
    CONF_ACCURACY_DECIMALS,
 | 
			
		||||
    CONF_BINARY_SENSORS,
 | 
			
		||||
    CONF_DEVICE_CLASS,
 | 
			
		||||
    CONF_FORCE_UPDATE,
 | 
			
		||||
    CONF_ICON,
 | 
			
		||||
    CONF_ID,
 | 
			
		||||
    CONF_INVERTED,
 | 
			
		||||
    CONF_LAST_RESET_TYPE,
 | 
			
		||||
    CONF_MAX_VALUE,
 | 
			
		||||
    CONF_MIN_VALUE,
 | 
			
		||||
    CONF_NAME,
 | 
			
		||||
    CONF_OUTPUT_ID,
 | 
			
		||||
    CONF_SENSORS,
 | 
			
		||||
    CONF_STATE_CLASS,
 | 
			
		||||
    CONF_STEP,
 | 
			
		||||
    CONF_SWITCHES,
 | 
			
		||||
    CONF_TEXT_SENSORS,
 | 
			
		||||
    CONF_TYPE,
 | 
			
		||||
    CONF_UNIT_OF_MEASUREMENT,
 | 
			
		||||
    DEVICE_CLASS_ENERGY,
 | 
			
		||||
    DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
    DEVICE_CLASS_MOISTURE,
 | 
			
		||||
    DEVICE_CLASS_MOTION,
 | 
			
		||||
    DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
    ICON_BLUETOOTH,
 | 
			
		||||
    ICON_BLUR,
 | 
			
		||||
    ICON_EMPTY,
 | 
			
		||||
    ICON_THERMOMETER,
 | 
			
		||||
    LAST_RESET_TYPE_AUTO,
 | 
			
		||||
    STATE_CLASS_MEASUREMENT,
 | 
			
		||||
    UNIT_CELSIUS,
 | 
			
		||||
    UNIT_EMPTY,
 | 
			
		||||
    UNIT_PERCENT,
 | 
			
		||||
    UNIT_WATT_HOURS,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
AUTO_LOAD = [
 | 
			
		||||
    "binary_sensor",
 | 
			
		||||
    "climate",
 | 
			
		||||
    "cover",
 | 
			
		||||
    "fan",
 | 
			
		||||
    "light",
 | 
			
		||||
    "number",
 | 
			
		||||
    "sensor",
 | 
			
		||||
    "switch",
 | 
			
		||||
    "text_sensor",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
demo_ns = cg.esphome_ns.namespace("demo")
 | 
			
		||||
DemoBinarySensor = demo_ns.class_(
 | 
			
		||||
    "DemoBinarySensor", binary_sensor.BinarySensor, cg.PollingComponent
 | 
			
		||||
)
 | 
			
		||||
DemoClimate = demo_ns.class_("DemoClimate", climate.Climate, cg.Component)
 | 
			
		||||
DemoClimateType = demo_ns.enum("DemoClimateType", is_class=True)
 | 
			
		||||
DemoCover = demo_ns.class_("DemoCover", cover.Cover, cg.Component)
 | 
			
		||||
DemoCoverType = demo_ns.enum("DemoCoverType", is_class=True)
 | 
			
		||||
DemoFan = demo_ns.class_("DemoFan", cg.Component)
 | 
			
		||||
DemoFanType = demo_ns.enum("DemoFanType", is_class=True)
 | 
			
		||||
DemoLight = demo_ns.class_("DemoLight", light.LightOutput, cg.Component)
 | 
			
		||||
DemoLightType = demo_ns.enum("DemoLightType", is_class=True)
 | 
			
		||||
DemoNumber = demo_ns.class_("DemoNumber", number.Number, cg.Component)
 | 
			
		||||
DemoNumberType = demo_ns.enum("DemoNumberType", is_class=True)
 | 
			
		||||
DemoSensor = demo_ns.class_("DemoSensor", sensor.Sensor, cg.PollingComponent)
 | 
			
		||||
DemoSwitch = demo_ns.class_("DemoSwitch", switch.Switch, cg.Component)
 | 
			
		||||
DemoTextSensor = demo_ns.class_(
 | 
			
		||||
    "DemoTextSensor", text_sensor.TextSensor, cg.PollingComponent
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
CLIMATE_TYPES = {
 | 
			
		||||
    1: DemoClimateType.TYPE_1,
 | 
			
		||||
    2: DemoClimateType.TYPE_2,
 | 
			
		||||
    3: DemoClimateType.TYPE_3,
 | 
			
		||||
}
 | 
			
		||||
COVER_TYPES = {
 | 
			
		||||
    1: DemoCoverType.TYPE_1,
 | 
			
		||||
    2: DemoCoverType.TYPE_2,
 | 
			
		||||
    3: DemoCoverType.TYPE_3,
 | 
			
		||||
    4: DemoCoverType.TYPE_4,
 | 
			
		||||
}
 | 
			
		||||
FAN_TYPES = {
 | 
			
		||||
    1: DemoFanType.TYPE_1,
 | 
			
		||||
    2: DemoFanType.TYPE_2,
 | 
			
		||||
    3: DemoFanType.TYPE_3,
 | 
			
		||||
    4: DemoFanType.TYPE_4,
 | 
			
		||||
}
 | 
			
		||||
LIGHT_TYPES = {
 | 
			
		||||
    1: DemoLightType.TYPE_1,
 | 
			
		||||
    2: DemoLightType.TYPE_2,
 | 
			
		||||
    3: DemoLightType.TYPE_3,
 | 
			
		||||
    4: DemoLightType.TYPE_4,
 | 
			
		||||
    5: DemoLightType.TYPE_5,
 | 
			
		||||
    6: DemoLightType.TYPE_6,
 | 
			
		||||
    7: DemoLightType.TYPE_7,
 | 
			
		||||
}
 | 
			
		||||
NUMBER_TYPES = {
 | 
			
		||||
    1: DemoNumberType.TYPE_1,
 | 
			
		||||
    2: DemoNumberType.TYPE_2,
 | 
			
		||||
    3: DemoNumberType.TYPE_3,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
CONF_CLIMATES = "climates"
 | 
			
		||||
CONF_COVERS = "covers"
 | 
			
		||||
CONF_FANS = "fans"
 | 
			
		||||
CONF_LIGHTS = "lights"
 | 
			
		||||
CONF_NUMBERS = "numbers"
 | 
			
		||||
 | 
			
		||||
CONFIG_SCHEMA = cv.Schema(
 | 
			
		||||
    {
 | 
			
		||||
        cv.Optional(
 | 
			
		||||
            CONF_BINARY_SENSORS,
 | 
			
		||||
            default=[
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo Basement Floor Wet",
 | 
			
		||||
                    CONF_DEVICE_CLASS: DEVICE_CLASS_MOISTURE,
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo Movement Backyard",
 | 
			
		||||
                    CONF_DEVICE_CLASS: DEVICE_CLASS_MOTION,
 | 
			
		||||
                },
 | 
			
		||||
            ],
 | 
			
		||||
        ): [
 | 
			
		||||
            binary_sensor.BINARY_SENSOR_SCHEMA.extend(
 | 
			
		||||
                cv.polling_component_schema("60s")
 | 
			
		||||
            ).extend(
 | 
			
		||||
                {
 | 
			
		||||
                    cv.GenerateID(): cv.declare_id(DemoBinarySensor),
 | 
			
		||||
                }
 | 
			
		||||
            )
 | 
			
		||||
        ],
 | 
			
		||||
        cv.Optional(
 | 
			
		||||
            CONF_CLIMATES,
 | 
			
		||||
            default=[
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo Heatpump",
 | 
			
		||||
                    CONF_TYPE: 1,
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo HVAC",
 | 
			
		||||
                    CONF_TYPE: 2,
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo Ecobee",
 | 
			
		||||
                    CONF_TYPE: 3,
 | 
			
		||||
                },
 | 
			
		||||
            ],
 | 
			
		||||
        ): [
 | 
			
		||||
            climate.CLIMATE_SCHEMA.extend(cv.COMPONENT_SCHEMA).extend(
 | 
			
		||||
                {
 | 
			
		||||
                    cv.GenerateID(): cv.declare_id(DemoClimate),
 | 
			
		||||
                    cv.Required(CONF_TYPE): cv.enum(CLIMATE_TYPES, int=True),
 | 
			
		||||
                }
 | 
			
		||||
            )
 | 
			
		||||
        ],
 | 
			
		||||
        cv.Optional(
 | 
			
		||||
            CONF_COVERS,
 | 
			
		||||
            default=[
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo Kitchen Window",
 | 
			
		||||
                    CONF_TYPE: 1,
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo Garage Door",
 | 
			
		||||
                    CONF_TYPE: 2,
 | 
			
		||||
                    CONF_DEVICE_CLASS: "garage",
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo Living Room Window",
 | 
			
		||||
                    CONF_TYPE: 3,
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo Hall Window",
 | 
			
		||||
                    CONF_TYPE: 4,
 | 
			
		||||
                    CONF_DEVICE_CLASS: "window",
 | 
			
		||||
                },
 | 
			
		||||
            ],
 | 
			
		||||
        ): [
 | 
			
		||||
            cover.COVER_SCHEMA.extend(cv.COMPONENT_SCHEMA).extend(
 | 
			
		||||
                {
 | 
			
		||||
                    cv.GenerateID(): cv.declare_id(DemoCover),
 | 
			
		||||
                    cv.Required(CONF_TYPE): cv.enum(COVER_TYPES, int=True),
 | 
			
		||||
                }
 | 
			
		||||
            )
 | 
			
		||||
        ],
 | 
			
		||||
        cv.Optional(
 | 
			
		||||
            CONF_FANS,
 | 
			
		||||
            default=[
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo Living Room Fan",
 | 
			
		||||
                    CONF_TYPE: 1,
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo Ceiling Fan",
 | 
			
		||||
                    CONF_TYPE: 2,
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo Percentage Limited Fan",
 | 
			
		||||
                    CONF_TYPE: 3,
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo Percentage Full Fan",
 | 
			
		||||
                    CONF_TYPE: 4,
 | 
			
		||||
                },
 | 
			
		||||
            ],
 | 
			
		||||
        ): [
 | 
			
		||||
            fan.FAN_SCHEMA.extend(cv.COMPONENT_SCHEMA).extend(
 | 
			
		||||
                {
 | 
			
		||||
                    cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(DemoFan),
 | 
			
		||||
                    cv.Required(CONF_TYPE): cv.enum(FAN_TYPES, int=True),
 | 
			
		||||
                }
 | 
			
		||||
            )
 | 
			
		||||
        ],
 | 
			
		||||
        cv.Optional(
 | 
			
		||||
            CONF_LIGHTS,
 | 
			
		||||
            default=[
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo Binary Light",
 | 
			
		||||
                    CONF_TYPE: 1,
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo Brightness Light",
 | 
			
		||||
                    CONF_TYPE: 2,
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo RGB Light",
 | 
			
		||||
                    CONF_TYPE: 3,
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo RGBW Light",
 | 
			
		||||
                    CONF_TYPE: 4,
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo RGBWW Light",
 | 
			
		||||
                    CONF_TYPE: 5,
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo CWWW Light",
 | 
			
		||||
                    CONF_TYPE: 6,
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo RGBW interlock Light",
 | 
			
		||||
                    CONF_TYPE: 7,
 | 
			
		||||
                },
 | 
			
		||||
            ],
 | 
			
		||||
        ): [
 | 
			
		||||
            light.RGB_LIGHT_SCHEMA.extend(cv.COMPONENT_SCHEMA).extend(
 | 
			
		||||
                {
 | 
			
		||||
                    cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(DemoLight),
 | 
			
		||||
                    cv.Required(CONF_TYPE): cv.enum(LIGHT_TYPES, int=True),
 | 
			
		||||
                }
 | 
			
		||||
            )
 | 
			
		||||
        ],
 | 
			
		||||
        cv.Optional(
 | 
			
		||||
            CONF_NUMBERS,
 | 
			
		||||
            default=[
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo Number 0-100",
 | 
			
		||||
                    CONF_TYPE: 1,
 | 
			
		||||
                    CONF_MIN_VALUE: 0,
 | 
			
		||||
                    CONF_MAX_VALUE: 100,
 | 
			
		||||
                    CONF_STEP: 1,
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo Number -50-50",
 | 
			
		||||
                    CONF_TYPE: 2,
 | 
			
		||||
                    CONF_MIN_VALUE: -50,
 | 
			
		||||
                    CONF_MAX_VALUE: 50,
 | 
			
		||||
                    CONF_STEP: 5,
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo Number 40-60",
 | 
			
		||||
                    CONF_TYPE: 3,
 | 
			
		||||
                    CONF_MIN_VALUE: 40,
 | 
			
		||||
                    CONF_MAX_VALUE: 60,
 | 
			
		||||
                    CONF_STEP: 0.2,
 | 
			
		||||
                },
 | 
			
		||||
            ],
 | 
			
		||||
        ): [
 | 
			
		||||
            number.NUMBER_SCHEMA.extend(cv.COMPONENT_SCHEMA).extend(
 | 
			
		||||
                {
 | 
			
		||||
                    cv.GenerateID(): cv.declare_id(DemoNumber),
 | 
			
		||||
                    cv.Required(CONF_TYPE): cv.enum(NUMBER_TYPES, int=True),
 | 
			
		||||
                    cv.Required(CONF_MIN_VALUE): cv.float_,
 | 
			
		||||
                    cv.Required(CONF_MAX_VALUE): cv.float_,
 | 
			
		||||
                    cv.Required(CONF_STEP): cv.float_,
 | 
			
		||||
                }
 | 
			
		||||
            )
 | 
			
		||||
        ],
 | 
			
		||||
        cv.Optional(
 | 
			
		||||
            CONF_SENSORS,
 | 
			
		||||
            default=[
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo Plain Sensor",
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo Temperature Sensor",
 | 
			
		||||
                    CONF_UNIT_OF_MEASUREMENT: UNIT_CELSIUS,
 | 
			
		||||
                    CONF_ICON: ICON_THERMOMETER,
 | 
			
		||||
                    CONF_ACCURACY_DECIMALS: 1,
 | 
			
		||||
                    CONF_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
                    CONF_STATE_CLASS: STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo Temperature Sensor",
 | 
			
		||||
                    CONF_UNIT_OF_MEASUREMENT: UNIT_CELSIUS,
 | 
			
		||||
                    CONF_ICON: ICON_THERMOMETER,
 | 
			
		||||
                    CONF_ACCURACY_DECIMALS: 1,
 | 
			
		||||
                    CONF_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
                    CONF_STATE_CLASS: STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo Force Update Sensor",
 | 
			
		||||
                    CONF_UNIT_OF_MEASUREMENT: UNIT_PERCENT,
 | 
			
		||||
                    CONF_ACCURACY_DECIMALS: 0,
 | 
			
		||||
                    CONF_DEVICE_CLASS: DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
                    CONF_STATE_CLASS: STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                    CONF_FORCE_UPDATE: True,
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo Energy Sensor",
 | 
			
		||||
                    CONF_UNIT_OF_MEASUREMENT: UNIT_WATT_HOURS,
 | 
			
		||||
                    CONF_ACCURACY_DECIMALS: 0,
 | 
			
		||||
                    CONF_DEVICE_CLASS: DEVICE_CLASS_ENERGY,
 | 
			
		||||
                    CONF_STATE_CLASS: STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                    CONF_LAST_RESET_TYPE: LAST_RESET_TYPE_AUTO,
 | 
			
		||||
                },
 | 
			
		||||
            ],
 | 
			
		||||
        ): [
 | 
			
		||||
            sensor.sensor_schema(UNIT_EMPTY, ICON_EMPTY, 0)
 | 
			
		||||
            .extend(cv.polling_component_schema("60s"))
 | 
			
		||||
            .extend(
 | 
			
		||||
                {
 | 
			
		||||
                    cv.GenerateID(): cv.declare_id(DemoSensor),
 | 
			
		||||
                }
 | 
			
		||||
            )
 | 
			
		||||
        ],
 | 
			
		||||
        cv.Optional(
 | 
			
		||||
            CONF_SWITCHES,
 | 
			
		||||
            default=[
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo Switch 1",
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo Switch 2",
 | 
			
		||||
                    CONF_INVERTED: True,
 | 
			
		||||
                    CONF_ICON: ICON_BLUETOOTH,
 | 
			
		||||
                },
 | 
			
		||||
            ],
 | 
			
		||||
        ): [
 | 
			
		||||
            switch.SWITCH_SCHEMA.extend(cv.COMPONENT_SCHEMA).extend(
 | 
			
		||||
                {
 | 
			
		||||
                    cv.GenerateID(): cv.declare_id(DemoSwitch),
 | 
			
		||||
                }
 | 
			
		||||
            )
 | 
			
		||||
        ],
 | 
			
		||||
        cv.Optional(
 | 
			
		||||
            CONF_TEXT_SENSORS,
 | 
			
		||||
            default=[
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo Text Sensor 1",
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    CONF_NAME: "Demo Text Sensor 2",
 | 
			
		||||
                    CONF_ICON: ICON_BLUR,
 | 
			
		||||
                },
 | 
			
		||||
            ],
 | 
			
		||||
        ): [
 | 
			
		||||
            text_sensor.TEXT_SENSOR_SCHEMA.extend(
 | 
			
		||||
                cv.polling_component_schema("60s")
 | 
			
		||||
            ).extend(
 | 
			
		||||
                {
 | 
			
		||||
                    cv.GenerateID(): cv.declare_id(DemoTextSensor),
 | 
			
		||||
                }
 | 
			
		||||
            )
 | 
			
		||||
        ],
 | 
			
		||||
    }
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async def to_code(config):
 | 
			
		||||
    for conf in config[CONF_BINARY_SENSORS]:
 | 
			
		||||
        var = cg.new_Pvariable(conf[CONF_ID])
 | 
			
		||||
        await cg.register_component(var, conf)
 | 
			
		||||
        await binary_sensor.register_binary_sensor(var, conf)
 | 
			
		||||
 | 
			
		||||
    for conf in config[CONF_CLIMATES]:
 | 
			
		||||
        var = cg.new_Pvariable(conf[CONF_ID])
 | 
			
		||||
        await cg.register_component(var, conf)
 | 
			
		||||
        await climate.register_climate(var, conf)
 | 
			
		||||
        cg.add(var.set_type(conf[CONF_TYPE]))
 | 
			
		||||
 | 
			
		||||
    for conf in config[CONF_COVERS]:
 | 
			
		||||
        var = cg.new_Pvariable(conf[CONF_ID])
 | 
			
		||||
        await cg.register_component(var, conf)
 | 
			
		||||
        await cover.register_cover(var, conf)
 | 
			
		||||
        cg.add(var.set_type(conf[CONF_TYPE]))
 | 
			
		||||
 | 
			
		||||
    for conf in config[CONF_FANS]:
 | 
			
		||||
        var = cg.new_Pvariable(conf[CONF_OUTPUT_ID])
 | 
			
		||||
        await cg.register_component(var, conf)
 | 
			
		||||
        fan_ = await fan.create_fan_state(conf)
 | 
			
		||||
        cg.add(var.set_fan(fan_))
 | 
			
		||||
        cg.add(var.set_type(conf[CONF_TYPE]))
 | 
			
		||||
 | 
			
		||||
    for conf in config[CONF_LIGHTS]:
 | 
			
		||||
        var = cg.new_Pvariable(conf[CONF_OUTPUT_ID])
 | 
			
		||||
        await cg.register_component(var, conf)
 | 
			
		||||
        await light.register_light(var, conf)
 | 
			
		||||
        cg.add(var.set_type(conf[CONF_TYPE]))
 | 
			
		||||
 | 
			
		||||
    for conf in config[CONF_NUMBERS]:
 | 
			
		||||
        var = cg.new_Pvariable(conf[CONF_ID])
 | 
			
		||||
        await cg.register_component(var, conf)
 | 
			
		||||
        await number.register_number(
 | 
			
		||||
            var,
 | 
			
		||||
            conf,
 | 
			
		||||
            min_value=conf[CONF_MIN_VALUE],
 | 
			
		||||
            max_value=conf[CONF_MAX_VALUE],
 | 
			
		||||
            step=conf[CONF_STEP],
 | 
			
		||||
        )
 | 
			
		||||
        cg.add(var.set_type(conf[CONF_TYPE]))
 | 
			
		||||
 | 
			
		||||
    for conf in config[CONF_SENSORS]:
 | 
			
		||||
        var = cg.new_Pvariable(conf[CONF_ID])
 | 
			
		||||
        await cg.register_component(var, conf)
 | 
			
		||||
        await sensor.register_sensor(var, conf)
 | 
			
		||||
 | 
			
		||||
    for conf in config[CONF_SWITCHES]:
 | 
			
		||||
        var = cg.new_Pvariable(conf[CONF_ID])
 | 
			
		||||
        await cg.register_component(var, conf)
 | 
			
		||||
        await switch.register_switch(var, conf)
 | 
			
		||||
 | 
			
		||||
    for conf in config[CONF_TEXT_SENSORS]:
 | 
			
		||||
        var = cg.new_Pvariable(conf[CONF_ID])
 | 
			
		||||
        await cg.register_component(var, conf)
 | 
			
		||||
        await text_sensor.register_text_sensor(var, conf)
 | 
			
		||||
							
								
								
									
										22
									
								
								esphome/components/demo/demo_binary_sensor.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								esphome/components/demo/demo_binary_sensor.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "esphome/core/component.h"
 | 
			
		||||
#include "esphome/components/binary_sensor/binary_sensor.h"
 | 
			
		||||
 | 
			
		||||
namespace esphome {
 | 
			
		||||
namespace demo {
 | 
			
		||||
 | 
			
		||||
class DemoBinarySensor : public binary_sensor::BinarySensor, public PollingComponent {
 | 
			
		||||
 public:
 | 
			
		||||
  void setup() override { this->publish_initial_state(false); }
 | 
			
		||||
  void update() override {
 | 
			
		||||
    bool new_state = last_state_ = !last_state_;
 | 
			
		||||
    this->publish_state(new_state);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool last_state_ = false;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace demo
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
							
								
								
									
										157
									
								
								esphome/components/demo/demo_climate.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								esphome/components/demo/demo_climate.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,157 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "esphome/core/component.h"
 | 
			
		||||
#include "esphome/components/climate/climate.h"
 | 
			
		||||
 | 
			
		||||
namespace esphome {
 | 
			
		||||
namespace demo {
 | 
			
		||||
 | 
			
		||||
enum class DemoClimateType {
 | 
			
		||||
  TYPE_1,
 | 
			
		||||
  TYPE_2,
 | 
			
		||||
  TYPE_3,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class DemoClimate : public climate::Climate, public Component {
 | 
			
		||||
 public:
 | 
			
		||||
  void set_type(DemoClimateType type) { type_ = type; }
 | 
			
		||||
  void setup() override {
 | 
			
		||||
    switch (type_) {
 | 
			
		||||
      case DemoClimateType::TYPE_1:
 | 
			
		||||
        this->current_temperature = 20.0;
 | 
			
		||||
        this->target_temperature = 21.0;
 | 
			
		||||
        this->mode = climate::CLIMATE_MODE_HEAT;
 | 
			
		||||
        this->action = climate::CLIMATE_ACTION_HEATING;
 | 
			
		||||
        break;
 | 
			
		||||
      case DemoClimateType::TYPE_2:
 | 
			
		||||
        this->target_temperature = 21.5;
 | 
			
		||||
        this->mode = climate::CLIMATE_MODE_AUTO;
 | 
			
		||||
        this->action = climate::CLIMATE_ACTION_COOLING;
 | 
			
		||||
        this->fan_mode = climate::CLIMATE_FAN_HIGH;
 | 
			
		||||
        this->custom_preset = {"My Preset"};
 | 
			
		||||
        break;
 | 
			
		||||
      case DemoClimateType::TYPE_3:
 | 
			
		||||
        this->current_temperature = 21.5;
 | 
			
		||||
        this->target_temperature_low = 21.0;
 | 
			
		||||
        this->target_temperature_high = 22.5;
 | 
			
		||||
        this->mode = climate::CLIMATE_MODE_HEAT_COOL;
 | 
			
		||||
        this->custom_fan_mode = {"Auto Low"};
 | 
			
		||||
        this->swing_mode = climate::CLIMATE_SWING_HORIZONTAL;
 | 
			
		||||
        this->preset = climate::CLIMATE_PRESET_AWAY;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    this->publish_state();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  void control(const climate::ClimateCall &call) override {
 | 
			
		||||
    if (call.get_mode().has_value()) {
 | 
			
		||||
      this->mode = *call.get_mode();
 | 
			
		||||
    }
 | 
			
		||||
    if (call.get_target_temperature().has_value()) {
 | 
			
		||||
      this->target_temperature = *call.get_target_temperature();
 | 
			
		||||
    }
 | 
			
		||||
    if (call.get_target_temperature_low().has_value()) {
 | 
			
		||||
      this->target_temperature_low = *call.get_target_temperature_low();
 | 
			
		||||
    }
 | 
			
		||||
    if (call.get_target_temperature_high().has_value()) {
 | 
			
		||||
      this->target_temperature_high = *call.get_target_temperature_high();
 | 
			
		||||
    }
 | 
			
		||||
    if (call.get_fan_mode().has_value()) {
 | 
			
		||||
      this->fan_mode = *call.get_fan_mode();
 | 
			
		||||
      this->custom_fan_mode.reset();
 | 
			
		||||
    }
 | 
			
		||||
    if (call.get_swing_mode().has_value()) {
 | 
			
		||||
      this->swing_mode = *call.get_swing_mode();
 | 
			
		||||
    }
 | 
			
		||||
    if (call.get_custom_fan_mode().has_value()) {
 | 
			
		||||
      this->custom_fan_mode = *call.get_custom_fan_mode();
 | 
			
		||||
      this->fan_mode.reset();
 | 
			
		||||
    }
 | 
			
		||||
    if (call.get_preset().has_value()) {
 | 
			
		||||
      this->preset = *call.get_preset();
 | 
			
		||||
      this->custom_preset.reset();
 | 
			
		||||
    }
 | 
			
		||||
    if (call.get_custom_preset().has_value()) {
 | 
			
		||||
      this->custom_preset = *call.get_custom_preset();
 | 
			
		||||
      this->preset.reset();
 | 
			
		||||
    }
 | 
			
		||||
    this->publish_state();
 | 
			
		||||
  }
 | 
			
		||||
  climate::ClimateTraits traits() override {
 | 
			
		||||
    climate::ClimateTraits traits{};
 | 
			
		||||
    switch (type_) {
 | 
			
		||||
      case DemoClimateType::TYPE_1:
 | 
			
		||||
        traits.set_supports_current_temperature(true);
 | 
			
		||||
        traits.set_supported_modes({
 | 
			
		||||
            climate::CLIMATE_MODE_OFF,
 | 
			
		||||
            climate::CLIMATE_MODE_HEAT,
 | 
			
		||||
        });
 | 
			
		||||
        traits.set_supports_action(true);
 | 
			
		||||
        traits.set_visual_temperature_step(0.5);
 | 
			
		||||
        break;
 | 
			
		||||
      case DemoClimateType::TYPE_2:
 | 
			
		||||
        traits.set_supports_current_temperature(false);
 | 
			
		||||
        traits.set_supported_modes({
 | 
			
		||||
            climate::CLIMATE_MODE_OFF,
 | 
			
		||||
            climate::CLIMATE_MODE_HEAT,
 | 
			
		||||
            climate::CLIMATE_MODE_COOL,
 | 
			
		||||
            climate::CLIMATE_MODE_AUTO,
 | 
			
		||||
            climate::CLIMATE_MODE_DRY,
 | 
			
		||||
            climate::CLIMATE_MODE_FAN_ONLY,
 | 
			
		||||
        });
 | 
			
		||||
        traits.set_supports_action(true);
 | 
			
		||||
        traits.set_supported_fan_modes({
 | 
			
		||||
            climate::CLIMATE_FAN_ON,
 | 
			
		||||
            climate::CLIMATE_FAN_OFF,
 | 
			
		||||
            climate::CLIMATE_FAN_AUTO,
 | 
			
		||||
            climate::CLIMATE_FAN_LOW,
 | 
			
		||||
            climate::CLIMATE_FAN_MEDIUM,
 | 
			
		||||
            climate::CLIMATE_FAN_HIGH,
 | 
			
		||||
            climate::CLIMATE_FAN_MIDDLE,
 | 
			
		||||
            climate::CLIMATE_FAN_FOCUS,
 | 
			
		||||
            climate::CLIMATE_FAN_DIFFUSE,
 | 
			
		||||
        });
 | 
			
		||||
        traits.set_supported_custom_fan_modes({"Auto Low", "Auto High"});
 | 
			
		||||
        traits.set_supported_swing_modes({
 | 
			
		||||
            climate::CLIMATE_SWING_OFF,
 | 
			
		||||
            climate::CLIMATE_SWING_BOTH,
 | 
			
		||||
            climate::CLIMATE_SWING_VERTICAL,
 | 
			
		||||
            climate::CLIMATE_SWING_HORIZONTAL,
 | 
			
		||||
        });
 | 
			
		||||
        traits.set_supported_custom_presets({"My Preset"});
 | 
			
		||||
        break;
 | 
			
		||||
      case DemoClimateType::TYPE_3:
 | 
			
		||||
        traits.set_supports_current_temperature(true);
 | 
			
		||||
        traits.set_supports_two_point_target_temperature(true);
 | 
			
		||||
        traits.set_supported_modes({
 | 
			
		||||
            climate::CLIMATE_MODE_OFF,
 | 
			
		||||
            climate::CLIMATE_MODE_COOL,
 | 
			
		||||
            climate::CLIMATE_MODE_HEAT,
 | 
			
		||||
            climate::CLIMATE_MODE_HEAT_COOL,
 | 
			
		||||
        });
 | 
			
		||||
        traits.set_supported_custom_fan_modes({"Auto Low", "Auto High"});
 | 
			
		||||
        traits.set_supported_swing_modes({
 | 
			
		||||
            climate::CLIMATE_SWING_OFF,
 | 
			
		||||
            climate::CLIMATE_SWING_HORIZONTAL,
 | 
			
		||||
        });
 | 
			
		||||
        traits.set_supported_presets({
 | 
			
		||||
            climate::CLIMATE_PRESET_NONE,
 | 
			
		||||
            climate::CLIMATE_PRESET_HOME,
 | 
			
		||||
            climate::CLIMATE_PRESET_AWAY,
 | 
			
		||||
            climate::CLIMATE_PRESET_BOOST,
 | 
			
		||||
            climate::CLIMATE_PRESET_COMFORT,
 | 
			
		||||
            climate::CLIMATE_PRESET_ECO,
 | 
			
		||||
            climate::CLIMATE_PRESET_SLEEP,
 | 
			
		||||
            climate::CLIMATE_PRESET_ACTIVITY,
 | 
			
		||||
        });
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    return traits;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  DemoClimateType type_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace demo
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
							
								
								
									
										86
									
								
								esphome/components/demo/demo_cover.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								esphome/components/demo/demo_cover.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,86 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "esphome/core/component.h"
 | 
			
		||||
#include "esphome/components/cover/cover.h"
 | 
			
		||||
 | 
			
		||||
namespace esphome {
 | 
			
		||||
namespace demo {
 | 
			
		||||
 | 
			
		||||
enum class DemoCoverType {
 | 
			
		||||
  TYPE_1,
 | 
			
		||||
  TYPE_2,
 | 
			
		||||
  TYPE_3,
 | 
			
		||||
  TYPE_4,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class DemoCover : public cover::Cover, public Component {
 | 
			
		||||
 public:
 | 
			
		||||
  void set_type(DemoCoverType type) { type_ = type; }
 | 
			
		||||
  void setup() override {
 | 
			
		||||
    switch (type_) {
 | 
			
		||||
      case DemoCoverType::TYPE_1:
 | 
			
		||||
        this->position = cover::COVER_OPEN;
 | 
			
		||||
        break;
 | 
			
		||||
      case DemoCoverType::TYPE_2:
 | 
			
		||||
        this->position = 0.7;
 | 
			
		||||
        break;
 | 
			
		||||
      case DemoCoverType::TYPE_3:
 | 
			
		||||
        this->position = 0.1;
 | 
			
		||||
        this->tilt = 0.8;
 | 
			
		||||
        break;
 | 
			
		||||
      case DemoCoverType::TYPE_4:
 | 
			
		||||
        this->position = cover::COVER_CLOSED;
 | 
			
		||||
        this->tilt = 1.0;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    this->publish_state();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  void control(const cover::CoverCall &call) override {
 | 
			
		||||
    if (call.get_position().has_value()) {
 | 
			
		||||
      float target = *call.get_position();
 | 
			
		||||
      this->current_operation =
 | 
			
		||||
          target > this->position ? cover::COVER_OPERATION_OPENING : cover::COVER_OPERATION_CLOSING;
 | 
			
		||||
 | 
			
		||||
      this->set_timeout("move", 2000, [this, target]() {
 | 
			
		||||
        this->current_operation = cover::COVER_OPERATION_IDLE;
 | 
			
		||||
        this->position = target;
 | 
			
		||||
        this->publish_state();
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
    if (call.get_tilt().has_value()) {
 | 
			
		||||
      this->tilt = *call.get_tilt();
 | 
			
		||||
    }
 | 
			
		||||
    if (call.get_stop()) {
 | 
			
		||||
      this->cancel_timeout("move");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this->publish_state();
 | 
			
		||||
  }
 | 
			
		||||
  cover::CoverTraits get_traits() override {
 | 
			
		||||
    cover::CoverTraits traits{};
 | 
			
		||||
    switch (type_) {
 | 
			
		||||
      case DemoCoverType::TYPE_1:
 | 
			
		||||
        traits.set_is_assumed_state(true);
 | 
			
		||||
        break;
 | 
			
		||||
      case DemoCoverType::TYPE_2:
 | 
			
		||||
        traits.set_supports_position(true);
 | 
			
		||||
        break;
 | 
			
		||||
      case DemoCoverType::TYPE_3:
 | 
			
		||||
        traits.set_supports_position(true);
 | 
			
		||||
        traits.set_supports_tilt(true);
 | 
			
		||||
        break;
 | 
			
		||||
      case DemoCoverType::TYPE_4:
 | 
			
		||||
        traits.set_is_assumed_state(true);
 | 
			
		||||
        traits.set_supports_tilt(true);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    return traits;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  DemoCoverType type_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace demo
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
							
								
								
									
										54
									
								
								esphome/components/demo/demo_fan.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								esphome/components/demo/demo_fan.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "esphome/core/component.h"
 | 
			
		||||
#include "esphome/components/fan/fan_state.h"
 | 
			
		||||
 | 
			
		||||
namespace esphome {
 | 
			
		||||
namespace demo {
 | 
			
		||||
 | 
			
		||||
enum class DemoFanType {
 | 
			
		||||
  TYPE_1,
 | 
			
		||||
  TYPE_2,
 | 
			
		||||
  TYPE_3,
 | 
			
		||||
  TYPE_4,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class DemoFan : public Component {
 | 
			
		||||
 public:
 | 
			
		||||
  void set_type(DemoFanType type) { type_ = type; }
 | 
			
		||||
  void set_fan(fan::FanState *fan) { fan_ = fan; }
 | 
			
		||||
  void setup() override {
 | 
			
		||||
    fan::FanTraits traits{};
 | 
			
		||||
 | 
			
		||||
    // oscillation
 | 
			
		||||
    // speed
 | 
			
		||||
    // direction
 | 
			
		||||
    // speed_count
 | 
			
		||||
    switch (type_) {
 | 
			
		||||
      case DemoFanType::TYPE_1:
 | 
			
		||||
        break;
 | 
			
		||||
      case DemoFanType::TYPE_2:
 | 
			
		||||
        traits.set_oscillation(true);
 | 
			
		||||
        break;
 | 
			
		||||
      case DemoFanType::TYPE_3:
 | 
			
		||||
        traits.set_direction(true);
 | 
			
		||||
        traits.set_speed(true);
 | 
			
		||||
        traits.set_supported_speed_count(5);
 | 
			
		||||
        break;
 | 
			
		||||
      case DemoFanType::TYPE_4:
 | 
			
		||||
        traits.set_direction(true);
 | 
			
		||||
        traits.set_speed(true);
 | 
			
		||||
        traits.set_supported_speed_count(100);
 | 
			
		||||
        traits.set_oscillation(true);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this->fan_->set_traits(traits);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  fan::FanState *fan_;
 | 
			
		||||
  DemoFanType type_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace demo
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
							
								
								
									
										68
									
								
								esphome/components/demo/demo_light.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								esphome/components/demo/demo_light.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "esphome/core/component.h"
 | 
			
		||||
#include "esphome/components/light/light_output.h"
 | 
			
		||||
 | 
			
		||||
namespace esphome {
 | 
			
		||||
namespace demo {
 | 
			
		||||
 | 
			
		||||
enum class DemoLightType {
 | 
			
		||||
  // binary
 | 
			
		||||
  TYPE_1,
 | 
			
		||||
  // brightness
 | 
			
		||||
  TYPE_2,
 | 
			
		||||
  // RGB
 | 
			
		||||
  TYPE_3,
 | 
			
		||||
  // RGBW
 | 
			
		||||
  TYPE_4,
 | 
			
		||||
  // RGBWW
 | 
			
		||||
  TYPE_5,
 | 
			
		||||
  // CWWW
 | 
			
		||||
  TYPE_6,
 | 
			
		||||
  // RGBW + color_interlock
 | 
			
		||||
  TYPE_7,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class DemoLight : public light::LightOutput, public Component {
 | 
			
		||||
 public:
 | 
			
		||||
  void set_type(DemoLightType type) { type_ = type; }
 | 
			
		||||
  light::LightTraits get_traits() override {
 | 
			
		||||
    light::LightTraits traits{};
 | 
			
		||||
    switch (type_) {
 | 
			
		||||
      case DemoLightType::TYPE_1:
 | 
			
		||||
        traits.set_supported_color_modes({light::ColorMode::ON_OFF});
 | 
			
		||||
        break;
 | 
			
		||||
      case DemoLightType::TYPE_2:
 | 
			
		||||
        traits.set_supported_color_modes({light::ColorMode::BRIGHTNESS});
 | 
			
		||||
        break;
 | 
			
		||||
      case DemoLightType::TYPE_3:
 | 
			
		||||
        traits.set_supported_color_modes({light::ColorMode::RGB});
 | 
			
		||||
        break;
 | 
			
		||||
      case DemoLightType::TYPE_4:
 | 
			
		||||
        traits.set_supported_color_modes({light::ColorMode::RGB_WHITE});
 | 
			
		||||
        break;
 | 
			
		||||
      case DemoLightType::TYPE_5:
 | 
			
		||||
        traits.set_supported_color_modes({light::ColorMode::RGB_COLOR_TEMPERATURE});
 | 
			
		||||
        traits.set_min_mireds(153);
 | 
			
		||||
        traits.set_max_mireds(500);
 | 
			
		||||
        break;
 | 
			
		||||
      case DemoLightType::TYPE_6:
 | 
			
		||||
        traits.set_supported_color_modes({light::ColorMode::COLD_WARM_WHITE});
 | 
			
		||||
        traits.set_min_mireds(153);
 | 
			
		||||
        traits.set_max_mireds(500);
 | 
			
		||||
        break;
 | 
			
		||||
      case DemoLightType::TYPE_7:
 | 
			
		||||
        traits.set_supported_color_modes({light::ColorMode::RGB, light::ColorMode::WHITE});
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    return traits;
 | 
			
		||||
  }
 | 
			
		||||
  void write_state(light::LightState *state) override {
 | 
			
		||||
    // do nothing
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  DemoLightType type_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace demo
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
							
								
								
									
										39
									
								
								esphome/components/demo/demo_number.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								esphome/components/demo/demo_number.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "esphome/core/component.h"
 | 
			
		||||
#include "esphome/components/number/number.h"
 | 
			
		||||
 | 
			
		||||
namespace esphome {
 | 
			
		||||
namespace demo {
 | 
			
		||||
 | 
			
		||||
enum class DemoNumberType {
 | 
			
		||||
  TYPE_1,
 | 
			
		||||
  TYPE_2,
 | 
			
		||||
  TYPE_3,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class DemoNumber : public number::Number, public Component {
 | 
			
		||||
 public:
 | 
			
		||||
  void set_type(DemoNumberType type) { type_ = type; }
 | 
			
		||||
  void setup() override {
 | 
			
		||||
    switch (type_) {
 | 
			
		||||
      case DemoNumberType::TYPE_1:
 | 
			
		||||
        this->publish_state(50);
 | 
			
		||||
        break;
 | 
			
		||||
      case DemoNumberType::TYPE_2:
 | 
			
		||||
        this->publish_state(-10);
 | 
			
		||||
        break;
 | 
			
		||||
      case DemoNumberType::TYPE_3:
 | 
			
		||||
        this->publish_state(42);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  void control(float value) override { this->publish_state(value); }
 | 
			
		||||
 | 
			
		||||
  DemoNumberType type_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace demo
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
							
								
								
									
										28
									
								
								esphome/components/demo/demo_sensor.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								esphome/components/demo/demo_sensor.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "esphome/core/component.h"
 | 
			
		||||
#include "esphome/core/helpers.h"
 | 
			
		||||
#include "esphome/components/sensor/sensor.h"
 | 
			
		||||
 | 
			
		||||
namespace esphome {
 | 
			
		||||
namespace demo {
 | 
			
		||||
 | 
			
		||||
class DemoSensor : public sensor::Sensor, public PollingComponent {
 | 
			
		||||
 public:
 | 
			
		||||
  void update() override {
 | 
			
		||||
    float val = random_float();
 | 
			
		||||
    bool is_auto = this->last_reset_type == sensor::LAST_RESET_TYPE_AUTO;
 | 
			
		||||
    if (is_auto) {
 | 
			
		||||
      float base = isnan(this->state) ? 0.0f : this->state;
 | 
			
		||||
      this->publish_state(base + val * 10);
 | 
			
		||||
    } else {
 | 
			
		||||
      if (val < 0.1)
 | 
			
		||||
        this->publish_state(NAN);
 | 
			
		||||
      else
 | 
			
		||||
        this->publish_state(val * 100);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace demo
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
							
								
								
									
										22
									
								
								esphome/components/demo/demo_switch.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								esphome/components/demo/demo_switch.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "esphome/core/component.h"
 | 
			
		||||
#include "esphome/core/helpers.h"
 | 
			
		||||
#include "esphome/components/switch/switch.h"
 | 
			
		||||
 | 
			
		||||
namespace esphome {
 | 
			
		||||
namespace demo {
 | 
			
		||||
 | 
			
		||||
class DemoSwitch : public switch_::Switch, public Component {
 | 
			
		||||
 public:
 | 
			
		||||
  void setup() override {
 | 
			
		||||
    bool initial = random_float() < 0.5;
 | 
			
		||||
    this->publish_state(initial);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  void write_state(bool state) override { this->publish_state(state); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace demo
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
							
								
								
									
										25
									
								
								esphome/components/demo/demo_text_sensor.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								esphome/components/demo/demo_text_sensor.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "esphome/core/component.h"
 | 
			
		||||
#include "esphome/core/helpers.h"
 | 
			
		||||
#include "esphome/components/text_sensor/text_sensor.h"
 | 
			
		||||
 | 
			
		||||
namespace esphome {
 | 
			
		||||
namespace demo {
 | 
			
		||||
 | 
			
		||||
class DemoTextSensor : public text_sensor::TextSensor, public PollingComponent {
 | 
			
		||||
 public:
 | 
			
		||||
  void update() override {
 | 
			
		||||
    float val = random_float();
 | 
			
		||||
    if (val < 0.33) {
 | 
			
		||||
      this->publish_state("foo");
 | 
			
		||||
    } else if (val < 0.66) {
 | 
			
		||||
      this->publish_state("bar");
 | 
			
		||||
    } else {
 | 
			
		||||
      this->publish_state("foobar");
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace demo
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
@@ -116,7 +116,7 @@ DFPLAYER_SIMPLE_ACTION(PreviousAction, previous)
 | 
			
		||||
template<typename... Ts> class PlayFileAction : public Action<Ts...>, public Parented<DFPlayer> {
 | 
			
		||||
 public:
 | 
			
		||||
  TEMPLATABLE_VALUE(uint16_t, file)
 | 
			
		||||
  TEMPLATABLE_VALUE(boolean, loop)
 | 
			
		||||
  TEMPLATABLE_VALUE(bool, loop)
 | 
			
		||||
 | 
			
		||||
  void play(Ts... x) override {
 | 
			
		||||
    auto file = this->file_.value(x...);
 | 
			
		||||
@@ -133,7 +133,7 @@ template<typename... Ts> class PlayFolderAction : public Action<Ts...>, public P
 | 
			
		||||
 public:
 | 
			
		||||
  TEMPLATABLE_VALUE(uint16_t, folder)
 | 
			
		||||
  TEMPLATABLE_VALUE(uint16_t, file)
 | 
			
		||||
  TEMPLATABLE_VALUE(boolean, loop)
 | 
			
		||||
  TEMPLATABLE_VALUE(bool, loop)
 | 
			
		||||
 | 
			
		||||
  void play(Ts... x) override {
 | 
			
		||||
    auto folder = this->folder_.value(x...);
 | 
			
		||||
 
 | 
			
		||||
@@ -203,7 +203,7 @@ bool HOT ICACHE_RAM_ATTR DHT::read_sensor_(float *temperature, float *humidity,
 | 
			
		||||
      const uint16_t raw_humidity = uint16_t(data[0]) * 10 + data[1];
 | 
			
		||||
      *humidity = raw_humidity / 10.0f;
 | 
			
		||||
    } else {
 | 
			
		||||
      // For compatibily with DHT11 models which might only use 2 bytes checksums, only use the data from these two
 | 
			
		||||
      // For compatibility with DHT11 models which might only use 2 bytes checksums, only use the data from these two
 | 
			
		||||
      // bytes
 | 
			
		||||
      *temperature = data[2];
 | 
			
		||||
      *humidity = data[0];
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,6 @@ from esphome.const import (
 | 
			
		||||
    CONF_MODEL,
 | 
			
		||||
    CONF_PIN,
 | 
			
		||||
    CONF_TEMPERATURE,
 | 
			
		||||
    ICON_EMPTY,
 | 
			
		||||
    STATE_CLASS_MEASUREMENT,
 | 
			
		||||
    UNIT_CELSIUS,
 | 
			
		||||
    UNIT_PERCENT,
 | 
			
		||||
@@ -36,14 +35,16 @@ CONFIG_SCHEMA = cv.Schema(
 | 
			
		||||
        cv.GenerateID(): cv.declare_id(DHT),
 | 
			
		||||
        cv.Required(CONF_PIN): pins.gpio_input_pin_schema,
 | 
			
		||||
        cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
 | 
			
		||||
            UNIT_CELSIUS,
 | 
			
		||||
            ICON_EMPTY,
 | 
			
		||||
            1,
 | 
			
		||||
            DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
            STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            unit_of_measurement=UNIT_CELSIUS,
 | 
			
		||||
            accuracy_decimals=1,
 | 
			
		||||
            device_class=DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
            state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
        ),
 | 
			
		||||
        cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(
 | 
			
		||||
            UNIT_PERCENT, ICON_EMPTY, 0, DEVICE_CLASS_HUMIDITY, STATE_CLASS_MEASUREMENT
 | 
			
		||||
            unit_of_measurement=UNIT_PERCENT,
 | 
			
		||||
            accuracy_decimals=0,
 | 
			
		||||
            device_class=DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
            state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
        ),
 | 
			
		||||
        cv.Optional(CONF_MODEL, default="auto detect"): cv.enum(
 | 
			
		||||
            DHT_MODELS, upper=True, space="_"
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,6 @@ from esphome.const import (
 | 
			
		||||
    CONF_TEMPERATURE,
 | 
			
		||||
    STATE_CLASS_MEASUREMENT,
 | 
			
		||||
    UNIT_CELSIUS,
 | 
			
		||||
    ICON_EMPTY,
 | 
			
		||||
    UNIT_PERCENT,
 | 
			
		||||
    DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
    DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
@@ -23,18 +22,16 @@ CONFIG_SCHEMA = (
 | 
			
		||||
        {
 | 
			
		||||
            cv.GenerateID(): cv.declare_id(DHT12Component),
 | 
			
		||||
            cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
 | 
			
		||||
                UNIT_CELSIUS,
 | 
			
		||||
                ICON_EMPTY,
 | 
			
		||||
                1,
 | 
			
		||||
                DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_CELSIUS,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(
 | 
			
		||||
                UNIT_PERCENT,
 | 
			
		||||
                ICON_EMPTY,
 | 
			
		||||
                1,
 | 
			
		||||
                DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
                STATE_CLASS_MEASUREMENT,
 | 
			
		||||
                unit_of_measurement=UNIT_PERCENT,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
 
 | 
			
		||||
@@ -31,7 +31,9 @@ DisplayPageShowPrevAction = display_ns.class_(
 | 
			
		||||
DisplayIsDisplayingPageCondition = display_ns.class_(
 | 
			
		||||
    "DisplayIsDisplayingPageCondition", automation.Condition
 | 
			
		||||
)
 | 
			
		||||
DisplayOnPageChangeTrigger = display_ns.class_("DisplayOnPageChangeTrigger")
 | 
			
		||||
DisplayOnPageChangeTrigger = display_ns.class_(
 | 
			
		||||
    "DisplayOnPageChangeTrigger", automation.Trigger
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
CONF_ON_PAGE_CHANGE = "on_page_change"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user