mirror of
				https://github.com/esphome/esphome.git
				synced 2025-11-04 00:51:49 +00:00 
			
		
		
		
	Compare commits
	
		
			93 Commits
		
	
	
		
			oral-b-bru
			...
			2021.10.3
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					d2ebfd2833 | ||
| 
						 | 
					bd782fc828 | ||
| 
						 | 
					23560e608c | ||
| 
						 | 
					f1377b560e | ||
| 
						 | 
					72108684ea | ||
| 
						 | 
					c6adaaea97 | ||
| 
						 | 
					91999a38ca | ||
| 
						 | 
					b34eed125d | ||
| 
						 | 
					2abe09529a | ||
| 
						 | 
					9aaaf4dd4b | ||
| 
						 | 
					cbfbcf7f1b | ||
| 
						 | 
					c7651dc40d | ||
| 
						 | 
					eda1c471ad | ||
| 
						 | 
					c7ef18fbc4 | ||
| 
						 | 
					901ec918b1 | ||
| 
						 | 
					6bdae55ee1 | ||
| 
						 | 
					dfb96e4b7f | ||
| 
						 | 
					ff2c316b18 | ||
| 
						 | 
					5be52f71f9 | ||
| 
						 | 
					42873dd37c | ||
| 
						 | 
					f93e7d4e3a | ||
| 
						 | 
					bbcd523967 | ||
| 
						 | 
					68cbe58d00 | ||
| 
						 | 
					115bca98f1 | ||
| 
						 | 
					ed0b34b2fe | ||
| 
						 | 
					ab34401421 | ||
| 
						 | 
					eed0c18d65 | ||
| 
						 | 
					e5a38ce748 | ||
| 
						 | 
					7d9d9fcf36 | ||
| 
						 | 
					f0aba6ceb2 | ||
| 
						 | 
					ab07ee57c6 | ||
| 
						 | 
					eae3d72a4d | ||
| 
						 | 
					7b8d826704 | ||
| 
						 | 
					e7baa42e63 | ||
| 
						 | 
					2f32833a22 | ||
| 
						 | 
					f6935a4b4b | ||
| 
						 | 
					332c9e891b | ||
| 
						 | 
					b91ee4847f | ||
| 
						 | 
					625463d871 | ||
| 
						 | 
					6433a01e07 | ||
| 
						 | 
					56cc31e8e7 | ||
| 
						 | 
					3af297aa76 | ||
| 
						 | 
					996ec59d28 | ||
| 
						 | 
					95593eeeab | ||
| 
						 | 
					dad244fb7a | ||
| 
						 | 
					adb5d27d95 | ||
| 
						 | 
					8456a8cecb | ||
| 
						 | 
					b9f66373c1 | ||
| 
						 | 
					9ac365feef | ||
| 
						 | 
					43bbd58a44 | ||
| 
						 | 
					7feffa64f3 | ||
| 
						 | 
					ea0977abb4 | ||
| 
						 | 
					4c83dc7c28 | ||
| 
						 | 
					e10ab1da78 | ||
| 
						 | 
					1b0e60374b | ||
| 
						 | 
					3a760fbb44 | ||
| 
						 | 
					6ef57a2973 | ||
| 
						 | 
					3e9c7f2e9f | ||
| 
						 | 
					430598b7a1 | ||
| 
						 | 
					91611b09b4 | ||
| 
						 | 
					ecd115851f | ||
| 
						 | 
					4a1e50fed1 | ||
| 
						 | 
					d6d037047b | ||
| 
						 | 
					b5734c2b20 | ||
| 
						 | 
					723fb7eaac | ||
| 
						 | 
					63a9acaa19 | ||
| 
						 | 
					0524f8c677 | ||
| 
						 | 
					70b62f272e | ||
| 
						 | 
					f0089b7940 | ||
| 
						 | 
					4b44280d53 | ||
| 
						 | 
					f045382d20 | ||
| 
						 | 
					db3fa1ade7 | ||
| 
						 | 
					f83950fd75 | ||
| 
						 | 
					4dd1bf920d | ||
| 
						 | 
					98755f3621 | ||
| 
						 | 
					c3a8a044b9 | ||
| 
						 | 
					15b5ea43a7 | ||
| 
						 | 
					ec683fc227 | ||
| 
						 | 
					d4e65eb82a | ||
| 
						 | 
					10c6601b0a | ||
| 
						 | 
					73940bc1bd | ||
| 
						 | 
					9b7fb829f9 | ||
| 
						 | 
					c51d8c9021 | ||
| 
						 | 
					d8a6dfe5ce | ||
| 
						 | 
					5f7cef0b06 | ||
| 
						 | 
					48ff2ffc68 | ||
| 
						 | 
					b3b9ccd314 | ||
| 
						 | 
					e63c7b483b | ||
| 
						 | 
					f57980b069 | ||
| 
						 | 
					7006aa0d2a | ||
| 
						 | 
					8051c1ca99 | ||
| 
						 | 
					a779592414 | ||
| 
						 | 
					112215848d | 
							
								
								
									
										15
									
								
								.clang-tidy
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								.clang-tidy
									
									
									
									
									
								
							@@ -5,8 +5,11 @@ Checks: >-
 | 
				
			|||||||
  -altera-*,
 | 
					  -altera-*,
 | 
				
			||||||
  -android-*,
 | 
					  -android-*,
 | 
				
			||||||
  -boost-*,
 | 
					  -boost-*,
 | 
				
			||||||
 | 
					  -bugprone-branch-clone,
 | 
				
			||||||
 | 
					  -bugprone-easily-swappable-parameters,
 | 
				
			||||||
  -bugprone-narrowing-conversions,
 | 
					  -bugprone-narrowing-conversions,
 | 
				
			||||||
  -bugprone-signed-char-misuse,
 | 
					  -bugprone-signed-char-misuse,
 | 
				
			||||||
 | 
					  -bugprone-too-small-loop-variable,
 | 
				
			||||||
  -cert-dcl50-cpp,
 | 
					  -cert-dcl50-cpp,
 | 
				
			||||||
  -cert-err58-cpp,
 | 
					  -cert-err58-cpp,
 | 
				
			||||||
  -cert-oop57-cpp,
 | 
					  -cert-oop57-cpp,
 | 
				
			||||||
@@ -16,10 +19,12 @@ Checks: >-
 | 
				
			|||||||
  -clang-diagnostic-delete-abstract-non-virtual-dtor,
 | 
					  -clang-diagnostic-delete-abstract-non-virtual-dtor,
 | 
				
			||||||
  -clang-diagnostic-delete-non-abstract-non-virtual-dtor,
 | 
					  -clang-diagnostic-delete-non-abstract-non-virtual-dtor,
 | 
				
			||||||
  -clang-diagnostic-shadow-field,
 | 
					  -clang-diagnostic-shadow-field,
 | 
				
			||||||
 | 
					  -clang-diagnostic-sign-compare,
 | 
				
			||||||
 | 
					  -clang-diagnostic-unused-variable,
 | 
				
			||||||
  -clang-diagnostic-unused-const-variable,
 | 
					  -clang-diagnostic-unused-const-variable,
 | 
				
			||||||
  -clang-diagnostic-unused-parameter,
 | 
					 | 
				
			||||||
  -concurrency-*,
 | 
					  -concurrency-*,
 | 
				
			||||||
  -cppcoreguidelines-avoid-c-arrays,
 | 
					  -cppcoreguidelines-avoid-c-arrays,
 | 
				
			||||||
 | 
					  -cppcoreguidelines-avoid-goto,
 | 
				
			||||||
  -cppcoreguidelines-avoid-magic-numbers,
 | 
					  -cppcoreguidelines-avoid-magic-numbers,
 | 
				
			||||||
  -cppcoreguidelines-init-variables,
 | 
					  -cppcoreguidelines-init-variables,
 | 
				
			||||||
  -cppcoreguidelines-macro-usage,
 | 
					  -cppcoreguidelines-macro-usage,
 | 
				
			||||||
@@ -36,6 +41,7 @@ Checks: >-
 | 
				
			|||||||
  -cppcoreguidelines-pro-type-union-access,
 | 
					  -cppcoreguidelines-pro-type-union-access,
 | 
				
			||||||
  -cppcoreguidelines-pro-type-vararg,
 | 
					  -cppcoreguidelines-pro-type-vararg,
 | 
				
			||||||
  -cppcoreguidelines-special-member-functions,
 | 
					  -cppcoreguidelines-special-member-functions,
 | 
				
			||||||
 | 
					  -fuchsia-default-arguments,
 | 
				
			||||||
  -fuchsia-multiple-inheritance,
 | 
					  -fuchsia-multiple-inheritance,
 | 
				
			||||||
  -fuchsia-overloaded-operator,
 | 
					  -fuchsia-overloaded-operator,
 | 
				
			||||||
  -fuchsia-statically-constructed-objects,
 | 
					  -fuchsia-statically-constructed-objects,
 | 
				
			||||||
@@ -45,7 +51,6 @@ Checks: >-
 | 
				
			|||||||
  -google-explicit-constructor,
 | 
					  -google-explicit-constructor,
 | 
				
			||||||
  -google-readability-braces-around-statements,
 | 
					  -google-readability-braces-around-statements,
 | 
				
			||||||
  -google-readability-casting,
 | 
					  -google-readability-casting,
 | 
				
			||||||
  -google-readability-namespace-comments,
 | 
					 | 
				
			||||||
  -google-readability-todo,
 | 
					  -google-readability-todo,
 | 
				
			||||||
  -google-runtime-references,
 | 
					  -google-runtime-references,
 | 
				
			||||||
  -hicpp-*,
 | 
					  -hicpp-*,
 | 
				
			||||||
@@ -92,11 +97,9 @@ CheckOptions:
 | 
				
			|||||||
    value:           '1'
 | 
					    value:           '1'
 | 
				
			||||||
  - key:             google-readability-function-size.StatementThreshold
 | 
					  - key:             google-readability-function-size.StatementThreshold
 | 
				
			||||||
    value:           '800'
 | 
					    value:           '800'
 | 
				
			||||||
  - key:             google-runtime-int.TypeSuffix
 | 
					  - key:             google-readability-namespace-comments.ShortNamespaceLines
 | 
				
			||||||
    value:           '_t'
 | 
					 | 
				
			||||||
  - key:             llvm-namespace-comment.ShortNamespaceLines
 | 
					 | 
				
			||||||
    value:           '10'
 | 
					    value:           '10'
 | 
				
			||||||
  - key:             llvm-namespace-comment.SpacesBeforeComments
 | 
					  - key:             google-readability-namespace-comments.SpacesBeforeComments
 | 
				
			||||||
    value:           '2'
 | 
					    value:           '2'
 | 
				
			||||||
  - key:             modernize-loop-convert.MaxCopySize
 | 
					  - key:             modernize-loop-convert.MaxCopySize
 | 
				
			||||||
    value:           '16'
 | 
					    value:           '16'
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								.github/PULL_REQUEST_TEMPLATE.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/PULL_REQUEST_TEMPLATE.md
									
									
									
									
										vendored
									
									
								
							@@ -16,7 +16,6 @@ Quick description and explanation of changes
 | 
				
			|||||||
## Test Environment
 | 
					## Test Environment
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- [ ] ESP32
 | 
					- [ ] ESP32
 | 
				
			||||||
- [ ] ESP32 IDF
 | 
					 | 
				
			||||||
- [ ] ESP8266
 | 
					- [ ] ESP8266
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Example entry for `config.yaml`:
 | 
					## Example entry for `config.yaml`:
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										7
									
								
								.github/issue-close-app.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								.github/issue-close-app.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					comment: >-
 | 
				
			||||||
 | 
					  https://github.com/esphome/esphome/issues/430
 | 
				
			||||||
 | 
					issueConfigs:
 | 
				
			||||||
 | 
					- content:
 | 
				
			||||||
 | 
					  - "OTHERWISE THE ISSUE WILL BE CLOSED AUTOMATICALLY"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					caseInsensitive: false
 | 
				
			||||||
							
								
								
									
										36
									
								
								.github/lock.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								.github/lock.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					# Configuration for Lock Threads - https://github.com/dessant/lock-threads
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Number of days of inactivity before a closed issue or pull request is locked
 | 
				
			||||||
 | 
					daysUntilLock: 7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Skip issues and pull requests created before a given timestamp. Timestamp must
 | 
				
			||||||
 | 
					# follow ISO 8601 (`YYYY-MM-DD`). Set to `false` to disable
 | 
				
			||||||
 | 
					skipCreatedBefore: false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Issues and pull requests with these labels will be ignored. Set to `[]` to disable
 | 
				
			||||||
 | 
					exemptLabels:
 | 
				
			||||||
 | 
					  - keep-open
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Label to add before locking, such as `outdated`. Set to `false` to disable
 | 
				
			||||||
 | 
					lockLabel: false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Comment to post before locking. Set to `false` to disable
 | 
				
			||||||
 | 
					lockComment: false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Assign `resolved` as the reason for locking. Set to `false` to disable
 | 
				
			||||||
 | 
					setLockReason: false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Limit to only `issues` or `pulls`
 | 
				
			||||||
 | 
					# only: issues
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Optionally, specify configuration settings just for `issues` or `pulls`
 | 
				
			||||||
 | 
					# issues:
 | 
				
			||||||
 | 
					#   exemptLabels:
 | 
				
			||||||
 | 
					#     - help-wanted
 | 
				
			||||||
 | 
					#   lockLabel: outdated
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# pulls:
 | 
				
			||||||
 | 
					#   daysUntilLock: 30
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Repository to extend settings from
 | 
				
			||||||
 | 
					# _extends: repo
 | 
				
			||||||
							
								
								
									
										4
									
								
								.github/workflows/ci-docker.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/ci-docker.yml
									
									
									
									
										vendored
									
									
								
							@@ -17,10 +17,6 @@ on:
 | 
				
			|||||||
      - 'requirements*.txt'
 | 
					      - 'requirements*.txt'
 | 
				
			||||||
      - 'platformio.ini'
 | 
					      - 'platformio.ini'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
permissions:
 | 
					 | 
				
			||||||
  contents: read
 | 
					 | 
				
			||||||
  packages: read
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
jobs:
 | 
					jobs:
 | 
				
			||||||
  check-docker:
 | 
					  check-docker:
 | 
				
			||||||
    name: Build docker containers
 | 
					    name: Build docker containers
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										30
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										30
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +1,5 @@
 | 
				
			|||||||
 | 
					# THESE JOBS ARE COPIED IN release.yml and release-dev.yml
 | 
				
			||||||
 | 
					# PLEASE ALSO UPDATE THOSE FILES WHEN CHANGING LINES HERE
 | 
				
			||||||
name: CI
 | 
					name: CI
 | 
				
			||||||
 | 
					
 | 
				
			||||||
on:
 | 
					on:
 | 
				
			||||||
@@ -6,13 +8,6 @@ on:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  pull_request:
 | 
					  pull_request:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
permissions:
 | 
					 | 
				
			||||||
  contents: read
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
concurrency:
 | 
					 | 
				
			||||||
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
 | 
					 | 
				
			||||||
  cancel-in-progress: true
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
jobs:
 | 
					jobs:
 | 
				
			||||||
  ci:
 | 
					  ci:
 | 
				
			||||||
    name: ${{ matrix.name }}
 | 
					    name: ${{ matrix.name }}
 | 
				
			||||||
@@ -36,7 +31,7 @@ jobs:
 | 
				
			|||||||
          - id: test
 | 
					          - id: test
 | 
				
			||||||
            file: tests/test3.yaml
 | 
					            file: tests/test3.yaml
 | 
				
			||||||
            name: Test tests/test3.yaml
 | 
					            name: Test tests/test3.yaml
 | 
				
			||||||
            pio_cache_key: test3
 | 
					            pio_cache_key: test1
 | 
				
			||||||
          - id: test
 | 
					          - id: test
 | 
				
			||||||
            file: tests/test4.yaml
 | 
					            file: tests/test4.yaml
 | 
				
			||||||
            name: Test tests/test4.yaml
 | 
					            name: Test tests/test4.yaml
 | 
				
			||||||
@@ -82,23 +77,18 @@ jobs:
 | 
				
			|||||||
        with:
 | 
					        with:
 | 
				
			||||||
          python-version: '3.7'
 | 
					          python-version: '3.7'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: Cache virtualenv
 | 
					      - name: Cache pip modules
 | 
				
			||||||
        uses: actions/cache@v2
 | 
					        uses: actions/cache@v2
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          path: .venv
 | 
					          path: ~/.cache/pip
 | 
				
			||||||
          key: venv-${{ steps.python.outputs.python-version }}-${{ hashFiles('requirements*.txt') }}
 | 
					          key: pip-${{ steps.python.outputs.python-version }}-${{ hashFiles('requirements*.txt') }}
 | 
				
			||||||
          restore-keys: |
 | 
					          restore-keys: |
 | 
				
			||||||
            venv-${{ steps.python.outputs.python-version }}-
 | 
					            pip-${{ steps.python.outputs.python-version }}-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: Set up virtualenv
 | 
					      - name: Set up python environment
 | 
				
			||||||
        run: |
 | 
					        run: |
 | 
				
			||||||
          python -m venv .venv
 | 
					          pip3 install -r requirements.txt -r requirements_optional.txt -r requirements_test.txt
 | 
				
			||||||
          source .venv/bin/activate
 | 
					          pip3 install -e .
 | 
				
			||||||
          pip install -U pip
 | 
					 | 
				
			||||||
          pip install -r requirements.txt -r requirements_optional.txt -r requirements_test.txt
 | 
					 | 
				
			||||||
          pip install -e .
 | 
					 | 
				
			||||||
          echo "$GITHUB_WORKSPACE/.venv/bin" >> $GITHUB_PATH
 | 
					 | 
				
			||||||
          echo "VIRTUAL_ENV=$GITHUB_WORKSPACE/.venv" >> $GITHUB_ENV
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      # Use per check platformio cache because checks use different parts
 | 
					      # Use per check platformio cache because checks use different parts
 | 
				
			||||||
      - name: Cache platformio
 | 
					      - name: Cache platformio
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										14
									
								
								.github/workflows/lock.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								.github/workflows/lock.yml
									
									
									
									
										vendored
									
									
								
							@@ -9,19 +9,13 @@ permissions:
 | 
				
			|||||||
  issues: write
 | 
					  issues: write
 | 
				
			||||||
  pull-requests: write
 | 
					  pull-requests: write
 | 
				
			||||||
 | 
					
 | 
				
			||||||
concurrency:
 | 
					 | 
				
			||||||
  group: lock
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
jobs:
 | 
					jobs:
 | 
				
			||||||
  lock:
 | 
					  lock:
 | 
				
			||||||
    runs-on: ubuntu-latest
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
      - uses: dessant/lock-threads@v3
 | 
					      - uses: dessant/lock-threads@v2
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          pr-inactive-days: "1"
 | 
					          github-token: ${{ github.token }}
 | 
				
			||||||
 | 
					          pr-lock-inactive-days: "1"
 | 
				
			||||||
          pr-lock-reason: ""
 | 
					          pr-lock-reason: ""
 | 
				
			||||||
          exclude-any-pr-labels: keep-open
 | 
					          process-only: prs
 | 
				
			||||||
 | 
					 | 
				
			||||||
          issue-inactive-days: "7"
 | 
					 | 
				
			||||||
          issue-lock-reason: ""
 | 
					 | 
				
			||||||
          exclude-any-issue-labels: keep-open
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								.github/workflows/matchers/ci-custom.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/matchers/ci-custom.json
									
									
									
									
										vendored
									
									
								
							@@ -4,7 +4,7 @@
 | 
				
			|||||||
            "owner": "ci-custom",
 | 
					            "owner": "ci-custom",
 | 
				
			||||||
            "pattern": [
 | 
					            "pattern": [
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    "regexp": "^(.*):(\\d+):(\\d+):\\s+lint:\\s+(.*)$",
 | 
					                    "regexp": "^ERROR (.*):(\\d+):(\\d+) - (.*)$",
 | 
				
			||||||
                    "file": 1,
 | 
					                    "file": 1,
 | 
				
			||||||
                    "line": 2,
 | 
					                    "line": 2,
 | 
				
			||||||
                    "column": 3,
 | 
					                    "column": 3,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								.github/workflows/matchers/gcc.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/matchers/gcc.json
									
									
									
									
										vendored
									
									
								
							@@ -5,7 +5,7 @@
 | 
				
			|||||||
      "severity": "error",
 | 
					      "severity": "error",
 | 
				
			||||||
      "pattern": [
 | 
					      "pattern": [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          "regexp": "^src/(.*):(\\d+):(\\d+):\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$",
 | 
					          "regexp": "^(.*):(\\d+):(\\d+):\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$",
 | 
				
			||||||
          "file": 1,
 | 
					          "file": 1,
 | 
				
			||||||
          "line": 2,
 | 
					          "line": 2,
 | 
				
			||||||
          "column": 3,
 | 
					          "column": 3,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										15
									
								
								.github/workflows/matchers/lint-python.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								.github/workflows/matchers/lint-python.json
									
									
									
									
										vendored
									
									
								
							@@ -1,22 +1,11 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "problemMatcher": [
 | 
					  "problemMatcher": [
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "owner": "black",
 | 
					 | 
				
			||||||
      "severity": "error",
 | 
					 | 
				
			||||||
      "pattern": [
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          "regexp": "^(.*): (Please format this file with the black formatter)",
 | 
					 | 
				
			||||||
          "file": 1,
 | 
					 | 
				
			||||||
          "message": 2
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      ]
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "owner": "flake8",
 | 
					      "owner": "flake8",
 | 
				
			||||||
      "severity": "error",
 | 
					      "severity": "error",
 | 
				
			||||||
      "pattern": [
 | 
					      "pattern": [
 | 
				
			||||||
          {
 | 
					          {
 | 
				
			||||||
          "regexp": "^(.*):(\\d+): ([EFCDNW]\\d{3}.*)$",
 | 
					          "regexp": "^(.*):(\\d+) - ([EFCDNW]\\d{3}.*)$",
 | 
				
			||||||
          "file": 1,
 | 
					          "file": 1,
 | 
				
			||||||
          "line": 2,
 | 
					          "line": 2,
 | 
				
			||||||
          "message": 3
 | 
					          "message": 3
 | 
				
			||||||
@@ -28,7 +17,7 @@
 | 
				
			|||||||
      "severity": "error",
 | 
					      "severity": "error",
 | 
				
			||||||
      "pattern": [
 | 
					      "pattern": [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          "regexp": "^(.*):(\\d+): (\\[[EFCRW]\\d{4}\\(.*\\),.*\\].*)$",
 | 
					          "regexp": "^(.*):(\\d+) - (\\[[EFCRW]\\d{4}\\(.*\\),.*\\].*)$",
 | 
				
			||||||
          "file": 1,
 | 
					          "file": 1,
 | 
				
			||||||
          "line": 2,
 | 
					          "line": 2,
 | 
				
			||||||
          "message": 3
 | 
					          "message": 3
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										9
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							@@ -7,9 +7,6 @@ on:
 | 
				
			|||||||
  schedule:
 | 
					  schedule:
 | 
				
			||||||
    - cron: "0 2 * * *"
 | 
					    - cron: "0 2 * * *"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
permissions:
 | 
					 | 
				
			||||||
  contents: read
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
jobs:
 | 
					jobs:
 | 
				
			||||||
  init:
 | 
					  init:
 | 
				
			||||||
    name: Initialize build
 | 
					    name: Initialize build
 | 
				
			||||||
@@ -55,9 +52,6 @@ jobs:
 | 
				
			|||||||
  deploy-docker:
 | 
					  deploy-docker:
 | 
				
			||||||
    name: Build and publish docker containers
 | 
					    name: Build and publish docker containers
 | 
				
			||||||
    if: github.repository == 'esphome/esphome'
 | 
					    if: github.repository == 'esphome/esphome'
 | 
				
			||||||
    permissions:
 | 
					 | 
				
			||||||
      contents: read
 | 
					 | 
				
			||||||
      packages: write
 | 
					 | 
				
			||||||
    runs-on: ubuntu-latest
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
    needs: [init]
 | 
					    needs: [init]
 | 
				
			||||||
    strategy:
 | 
					    strategy:
 | 
				
			||||||
@@ -99,9 +93,6 @@ jobs:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  deploy-docker-manifest:
 | 
					  deploy-docker-manifest:
 | 
				
			||||||
    if: github.repository == 'esphome/esphome'
 | 
					    if: github.repository == 'esphome/esphome'
 | 
				
			||||||
    permissions:
 | 
					 | 
				
			||||||
      contents: read
 | 
					 | 
				
			||||||
      packages: write
 | 
					 | 
				
			||||||
    runs-on: ubuntu-latest
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
    needs: [init, deploy-docker]
 | 
					    needs: [init, deploy-docker]
 | 
				
			||||||
    strategy:
 | 
					    strategy:
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										20
									
								
								.github/workflows/stale.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										20
									
								
								.github/workflows/stale.yml
									
									
									
									
										vendored
									
									
								
							@@ -9,15 +9,13 @@ permissions:
 | 
				
			|||||||
  issues: write
 | 
					  issues: write
 | 
				
			||||||
  pull-requests: write
 | 
					  pull-requests: write
 | 
				
			||||||
 | 
					
 | 
				
			||||||
concurrency:
 | 
					 | 
				
			||||||
  group: lock
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
jobs:
 | 
					jobs:
 | 
				
			||||||
  stale:
 | 
					  stale:
 | 
				
			||||||
    runs-on: ubuntu-latest
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
      - uses: actions/stale@v4
 | 
					      - uses: actions/stale@v4
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
 | 
					          repo-token: ${{ github.token }}
 | 
				
			||||||
          days-before-pr-stale: 90
 | 
					          days-before-pr-stale: 90
 | 
				
			||||||
          days-before-pr-close: 7
 | 
					          days-before-pr-close: 7
 | 
				
			||||||
          days-before-issue-stale: -1
 | 
					          days-before-issue-stale: -1
 | 
				
			||||||
@@ -30,19 +28,3 @@ jobs:
 | 
				
			|||||||
            pull request has been automatically marked as stale because of that
 | 
					            pull request has been automatically marked as stale because of that
 | 
				
			||||||
            and will be closed if no further activity occurs within 7 days.
 | 
					            and will be closed if no further activity occurs within 7 days.
 | 
				
			||||||
            Thank you for your contributions.
 | 
					            Thank you for your contributions.
 | 
				
			||||||
 | 
					 | 
				
			||||||
  # Use stale to automatically close issues with a reference to the issue tracker
 | 
					 | 
				
			||||||
  close-issues:
 | 
					 | 
				
			||||||
    runs-on: ubuntu-latest
 | 
					 | 
				
			||||||
    steps:
 | 
					 | 
				
			||||||
      - uses: actions/stale@v4
 | 
					 | 
				
			||||||
        with:
 | 
					 | 
				
			||||||
          days-before-pr-stale: -1
 | 
					 | 
				
			||||||
          days-before-pr-close: -1
 | 
					 | 
				
			||||||
          days-before-issue-stale: 1
 | 
					 | 
				
			||||||
          days-before-issue-close: 1
 | 
					 | 
				
			||||||
          remove-stale-when-updated: true
 | 
					 | 
				
			||||||
          stale-issue-label: "stale"
 | 
					 | 
				
			||||||
          exempt-issue-labels: "not-stale"
 | 
					 | 
				
			||||||
          stale-issue-message: >
 | 
					 | 
				
			||||||
            https://github.com/esphome/esphome/issues/430
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										13
									
								
								CODEOWNERS
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								CODEOWNERS
									
									
									
									
									
								
							@@ -30,9 +30,7 @@ esphome/components/bang_bang/* @OttoWinter
 | 
				
			|||||||
esphome/components/binary_sensor/* @esphome/core
 | 
					esphome/components/binary_sensor/* @esphome/core
 | 
				
			||||||
esphome/components/ble_client/* @buxtronix
 | 
					esphome/components/ble_client/* @buxtronix
 | 
				
			||||||
esphome/components/bme680_bsec/* @trvrnrth
 | 
					esphome/components/bme680_bsec/* @trvrnrth
 | 
				
			||||||
esphome/components/button/* @esphome/core
 | 
					 | 
				
			||||||
esphome/components/canbus/* @danielschramm @mvturnho
 | 
					esphome/components/canbus/* @danielschramm @mvturnho
 | 
				
			||||||
esphome/components/cap1188/* @MrEditor97
 | 
					 | 
				
			||||||
esphome/components/captive_portal/* @OttoWinter
 | 
					esphome/components/captive_portal/* @OttoWinter
 | 
				
			||||||
esphome/components/ccs811/* @habbie
 | 
					esphome/components/ccs811/* @habbie
 | 
				
			||||||
esphome/components/climate/* @esphome/core
 | 
					esphome/components/climate/* @esphome/core
 | 
				
			||||||
@@ -41,7 +39,6 @@ esphome/components/color_temperature/* @jesserockz
 | 
				
			|||||||
esphome/components/coolix/* @glmnet
 | 
					esphome/components/coolix/* @glmnet
 | 
				
			||||||
esphome/components/cover/* @esphome/core
 | 
					esphome/components/cover/* @esphome/core
 | 
				
			||||||
esphome/components/cs5460a/* @balrog-kun
 | 
					esphome/components/cs5460a/* @balrog-kun
 | 
				
			||||||
esphome/components/cse7761/* @berfenger
 | 
					 | 
				
			||||||
esphome/components/ct_clamp/* @jesserockz
 | 
					esphome/components/ct_clamp/* @jesserockz
 | 
				
			||||||
esphome/components/current_based/* @djwmarcx
 | 
					esphome/components/current_based/* @djwmarcx
 | 
				
			||||||
esphome/components/daly_bms/* @s1lvi0
 | 
					esphome/components/daly_bms/* @s1lvi0
 | 
				
			||||||
@@ -54,7 +51,6 @@ esphome/components/dsmr/* @glmnet @zuidwijk
 | 
				
			|||||||
esphome/components/esp32/* @esphome/core
 | 
					esphome/components/esp32/* @esphome/core
 | 
				
			||||||
esphome/components/esp32_ble/* @jesserockz
 | 
					esphome/components/esp32_ble/* @jesserockz
 | 
				
			||||||
esphome/components/esp32_ble_server/* @jesserockz
 | 
					esphome/components/esp32_ble_server/* @jesserockz
 | 
				
			||||||
esphome/components/esp32_camera_web_server/* @ayufan
 | 
					 | 
				
			||||||
esphome/components/esp32_improv/* @jesserockz
 | 
					esphome/components/esp32_improv/* @jesserockz
 | 
				
			||||||
esphome/components/esp8266/* @esphome/core
 | 
					esphome/components/esp8266/* @esphome/core
 | 
				
			||||||
esphome/components/exposure_notifications/* @OttoWinter
 | 
					esphome/components/exposure_notifications/* @OttoWinter
 | 
				
			||||||
@@ -65,7 +61,6 @@ esphome/components/globals/* @esphome/core
 | 
				
			|||||||
esphome/components/gpio/* @esphome/core
 | 
					esphome/components/gpio/* @esphome/core
 | 
				
			||||||
esphome/components/gps/* @coogle
 | 
					esphome/components/gps/* @coogle
 | 
				
			||||||
esphome/components/graph/* @synco
 | 
					esphome/components/graph/* @synco
 | 
				
			||||||
esphome/components/growatt_solar/* @leeuwte
 | 
					 | 
				
			||||||
esphome/components/havells_solar/* @sourabhjaiswal
 | 
					esphome/components/havells_solar/* @sourabhjaiswal
 | 
				
			||||||
esphome/components/hbridge/fan/* @WeekendWarrior
 | 
					esphome/components/hbridge/fan/* @WeekendWarrior
 | 
				
			||||||
esphome/components/hbridge/light/* @DotNetDann
 | 
					esphome/components/hbridge/light/* @DotNetDann
 | 
				
			||||||
@@ -74,7 +69,7 @@ esphome/components/hitachi_ac424/* @sourabhjaiswal
 | 
				
			|||||||
esphome/components/homeassistant/* @OttoWinter
 | 
					esphome/components/homeassistant/* @OttoWinter
 | 
				
			||||||
esphome/components/hrxl_maxsonar_wr/* @netmikey
 | 
					esphome/components/hrxl_maxsonar_wr/* @netmikey
 | 
				
			||||||
esphome/components/i2c/* @esphome/core
 | 
					esphome/components/i2c/* @esphome/core
 | 
				
			||||||
esphome/components/improv_serial/* @esphome/core
 | 
					esphome/components/improv/* @jesserockz
 | 
				
			||||||
esphome/components/inkbird_ibsth1_mini/* @fkirill
 | 
					esphome/components/inkbird_ibsth1_mini/* @fkirill
 | 
				
			||||||
esphome/components/inkplate6/* @jesserockz
 | 
					esphome/components/inkplate6/* @jesserockz
 | 
				
			||||||
esphome/components/integration/* @OttoWinter
 | 
					esphome/components/integration/* @OttoWinter
 | 
				
			||||||
@@ -133,7 +128,7 @@ esphome/components/restart/* @esphome/core
 | 
				
			|||||||
esphome/components/rf_bridge/* @jesserockz
 | 
					esphome/components/rf_bridge/* @jesserockz
 | 
				
			||||||
esphome/components/rgbct/* @jesserockz
 | 
					esphome/components/rgbct/* @jesserockz
 | 
				
			||||||
esphome/components/rtttl/* @glmnet
 | 
					esphome/components/rtttl/* @glmnet
 | 
				
			||||||
esphome/components/safe_mode/* @jsuanet @paulmonigatti
 | 
					esphome/components/safe_mode/* @paulmonigatti
 | 
				
			||||||
esphome/components/scd4x/* @sjtrny
 | 
					esphome/components/scd4x/* @sjtrny
 | 
				
			||||||
esphome/components/script/* @esphome/core
 | 
					esphome/components/script/* @esphome/core
 | 
				
			||||||
esphome/components/sdm_meter/* @jesserockz @polyfaces
 | 
					esphome/components/sdm_meter/* @jesserockz @polyfaces
 | 
				
			||||||
@@ -143,7 +138,7 @@ esphome/components/select/* @esphome/core
 | 
				
			|||||||
esphome/components/sensor/* @esphome/core
 | 
					esphome/components/sensor/* @esphome/core
 | 
				
			||||||
esphome/components/sgp40/* @SenexCrenshaw
 | 
					esphome/components/sgp40/* @SenexCrenshaw
 | 
				
			||||||
esphome/components/sht4x/* @sjtrny
 | 
					esphome/components/sht4x/* @sjtrny
 | 
				
			||||||
esphome/components/shutdown/* @esphome/core @jsuanet
 | 
					esphome/components/shutdown/* @esphome/core
 | 
				
			||||||
esphome/components/sim800l/* @glmnet
 | 
					esphome/components/sim800l/* @glmnet
 | 
				
			||||||
esphome/components/sm2135/* @BoukeHaarsma23
 | 
					esphome/components/sm2135/* @BoukeHaarsma23
 | 
				
			||||||
esphome/components/socket/* @esphome/core
 | 
					esphome/components/socket/* @esphome/core
 | 
				
			||||||
@@ -180,10 +175,8 @@ esphome/components/toshiba/* @kbx81
 | 
				
			|||||||
esphome/components/tsl2591/* @wjcarpenter
 | 
					esphome/components/tsl2591/* @wjcarpenter
 | 
				
			||||||
esphome/components/tuya/binary_sensor/* @jesserockz
 | 
					esphome/components/tuya/binary_sensor/* @jesserockz
 | 
				
			||||||
esphome/components/tuya/climate/* @jesserockz
 | 
					esphome/components/tuya/climate/* @jesserockz
 | 
				
			||||||
esphome/components/tuya/number/* @frankiboy1
 | 
					 | 
				
			||||||
esphome/components/tuya/sensor/* @jesserockz
 | 
					esphome/components/tuya/sensor/* @jesserockz
 | 
				
			||||||
esphome/components/tuya/switch/* @jesserockz
 | 
					esphome/components/tuya/switch/* @jesserockz
 | 
				
			||||||
esphome/components/tuya/text_sensor/* @dentra
 | 
					 | 
				
			||||||
esphome/components/uart/* @esphome/core
 | 
					esphome/components/uart/* @esphome/core
 | 
				
			||||||
esphome/components/ultrasonic/* @OttoWinter
 | 
					esphome/components/ultrasonic/* @OttoWinter
 | 
				
			||||||
esphome/components/version/* @esphome/core
 | 
					esphome/components/version/* @esphome/core
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,12 +5,12 @@
 | 
				
			|||||||
# One of "docker", "hassio"
 | 
					# One of "docker", "hassio"
 | 
				
			||||||
ARG BASEIMGTYPE=docker
 | 
					ARG BASEIMGTYPE=docker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FROM ghcr.io/hassio-addons/debian-base/amd64:5.1.1 AS base-hassio-amd64
 | 
					FROM ghcr.io/hassio-addons/debian-base/amd64:5.1.0 AS base-hassio-amd64
 | 
				
			||||||
FROM ghcr.io/hassio-addons/debian-base/aarch64:5.1.1 AS base-hassio-arm64
 | 
					FROM ghcr.io/hassio-addons/debian-base/aarch64:5.1.0 AS base-hassio-arm64
 | 
				
			||||||
FROM ghcr.io/hassio-addons/debian-base/armv7:5.1.1 AS base-hassio-armv7
 | 
					FROM ghcr.io/hassio-addons/debian-base/armv7:5.1.0 AS base-hassio-armv7
 | 
				
			||||||
FROM debian:bullseye-20211011-slim AS base-docker-amd64
 | 
					FROM debian:bullseye-20210902-slim AS base-docker-amd64
 | 
				
			||||||
FROM debian:bullseye-20211011-slim AS base-docker-arm64
 | 
					FROM debian:bullseye-20210902-slim AS base-docker-arm64
 | 
				
			||||||
FROM debian:bullseye-20211011-slim AS base-docker-armv7
 | 
					FROM debian:bullseye-20210902-slim AS base-docker-armv7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Use TARGETARCH/TARGETVARIANT defined by docker
 | 
					# Use TARGETARCH/TARGETVARIANT defined by docker
 | 
				
			||||||
# https://docs.docker.com/engine/reference/builder/#automatic-platform-args-in-the-global-scope
 | 
					# https://docs.docker.com/engine/reference/builder/#automatic-platform-args-in-the-global-scope
 | 
				
			||||||
@@ -43,7 +43,7 @@ RUN \
 | 
				
			|||||||
    # Ubuntu python3-pip is missing wheel
 | 
					    # Ubuntu python3-pip is missing wheel
 | 
				
			||||||
    pip3 install --no-cache-dir \
 | 
					    pip3 install --no-cache-dir \
 | 
				
			||||||
        wheel==0.36.2 \
 | 
					        wheel==0.36.2 \
 | 
				
			||||||
        platformio==5.2.2 \
 | 
					        platformio==5.2.1 \
 | 
				
			||||||
    # Change some platformio settings
 | 
					    # Change some platformio settings
 | 
				
			||||||
    && platformio settings set enable_telemetry No \
 | 
					    && platformio settings set enable_telemetry No \
 | 
				
			||||||
    && platformio settings set check_libraries_interval 1000000 \
 | 
					    && platformio settings set check_libraries_interval 1000000 \
 | 
				
			||||||
@@ -147,9 +147,9 @@ RUN \
 | 
				
			|||||||
        /var/{cache,log}/* \
 | 
					        /var/{cache,log}/* \
 | 
				
			||||||
        /var/lib/apt/lists/*
 | 
					        /var/lib/apt/lists/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
COPY requirements.txt requirements_optional.txt requirements_test.txt docker/platformio_install_deps.py platformio.ini /
 | 
					COPY requirements.txt requirements_optional.txt docker/platformio_install_deps.py platformio.ini /
 | 
				
			||||||
RUN \
 | 
					RUN \
 | 
				
			||||||
    pip3 install --no-cache-dir -r /requirements.txt -r /requirements_optional.txt -r /requirements_test.txt \
 | 
					    pip3 install --no-cache-dir -r /requirements.txt -r /requirements_optional.txt \
 | 
				
			||||||
    && /platformio_install_deps.py /platformio.ini
 | 
					    && /platformio_install_deps.py /platformio.ini
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VOLUME ["/esphome"]
 | 
					VOLUME ["/esphome"]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,7 +18,6 @@ from esphome.const import (
 | 
				
			|||||||
    CONF_PORT,
 | 
					    CONF_PORT,
 | 
				
			||||||
    CONF_ESPHOME,
 | 
					    CONF_ESPHOME,
 | 
				
			||||||
    CONF_PLATFORMIO_OPTIONS,
 | 
					    CONF_PLATFORMIO_OPTIONS,
 | 
				
			||||||
    SECRETS_FILES,
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
from esphome.core import CORE, EsphomeError, coroutine
 | 
					from esphome.core import CORE, EsphomeError, coroutine
 | 
				
			||||||
from esphome.helpers import indent
 | 
					from esphome.helpers import indent
 | 
				
			||||||
@@ -145,8 +144,6 @@ def wrap_to_code(name, comp):
 | 
				
			|||||||
        if comp.config_schema is not None:
 | 
					        if comp.config_schema is not None:
 | 
				
			||||||
            conf_str = yaml_util.dump(conf)
 | 
					            conf_str = yaml_util.dump(conf)
 | 
				
			||||||
            conf_str = conf_str.replace("//", "")
 | 
					            conf_str = conf_str.replace("//", "")
 | 
				
			||||||
            # remove tailing \ to avoid multi-line comment warning
 | 
					 | 
				
			||||||
            conf_str = conf_str.replace("\\\n", "\n")
 | 
					 | 
				
			||||||
            cg.add(cg.LineComment(indent(conf_str)))
 | 
					            cg.add(cg.LineComment(indent(conf_str)))
 | 
				
			||||||
        await coro(conf)
 | 
					        await coro(conf)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -203,7 +200,8 @@ def upload_using_esptool(config, port):
 | 
				
			|||||||
        firmware_offset = "0x10000" if CORE.is_esp32 else "0x0"
 | 
					        firmware_offset = "0x10000" if CORE.is_esp32 else "0x0"
 | 
				
			||||||
        flash_images = [
 | 
					        flash_images = [
 | 
				
			||||||
            platformio_api.FlashImage(
 | 
					            platformio_api.FlashImage(
 | 
				
			||||||
                path=idedata.firmware_bin_path, offset=firmware_offset
 | 
					                path=idedata.firmware_bin_path,
 | 
				
			||||||
 | 
					                offset=firmware_offset,
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            *idedata.extra_flash_images,
 | 
					            *idedata.extra_flash_images,
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
@@ -609,7 +607,10 @@ def parse_args(argv):
 | 
				
			|||||||
        "wizard",
 | 
					        "wizard",
 | 
				
			||||||
        help="A helpful setup wizard that will guide you through setting up ESPHome.",
 | 
					        help="A helpful setup wizard that will guide you through setting up ESPHome.",
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    parser_wizard.add_argument("configuration", help="Your YAML configuration file.")
 | 
					    parser_wizard.add_argument(
 | 
				
			||||||
 | 
					        "configuration",
 | 
				
			||||||
 | 
					        help="Your YAML configuration file.",
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    parser_fingerprint = subparsers.add_parser(
 | 
					    parser_fingerprint = subparsers.add_parser(
 | 
				
			||||||
        "mqtt-fingerprint", help="Get the SSL fingerprint from a MQTT broker."
 | 
					        "mqtt-fingerprint", help="Get the SSL fingerprint from a MQTT broker."
 | 
				
			||||||
@@ -631,7 +632,8 @@ def parse_args(argv):
 | 
				
			|||||||
        "dashboard", help="Create a simple web server for a dashboard."
 | 
					        "dashboard", help="Create a simple web server for a dashboard."
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    parser_dashboard.add_argument(
 | 
					    parser_dashboard.add_argument(
 | 
				
			||||||
        "configuration", help="Your YAML configuration file directory."
 | 
					        "configuration",
 | 
				
			||||||
 | 
					        help="Your YAML configuration file directory.",
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    parser_dashboard.add_argument(
 | 
					    parser_dashboard.add_argument(
 | 
				
			||||||
        "--port",
 | 
					        "--port",
 | 
				
			||||||
@@ -639,12 +641,6 @@ def parse_args(argv):
 | 
				
			|||||||
        type=int,
 | 
					        type=int,
 | 
				
			||||||
        default=6052,
 | 
					        default=6052,
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    parser_dashboard.add_argument(
 | 
					 | 
				
			||||||
        "--address",
 | 
					 | 
				
			||||||
        help="The address to bind to.",
 | 
					 | 
				
			||||||
        type=str,
 | 
					 | 
				
			||||||
        default="0.0.0.0",
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    parser_dashboard.add_argument(
 | 
					    parser_dashboard.add_argument(
 | 
				
			||||||
        "--username",
 | 
					        "--username",
 | 
				
			||||||
        help="The optional username to require for authentication.",
 | 
					        help="The optional username to require for authentication.",
 | 
				
			||||||
@@ -793,10 +789,6 @@ def run_esphome(argv):
 | 
				
			|||||||
            return 1
 | 
					            return 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for conf_path in args.configuration:
 | 
					    for conf_path in args.configuration:
 | 
				
			||||||
        if any(os.path.basename(conf_path) == x for x in SECRETS_FILES):
 | 
					 | 
				
			||||||
            _LOGGER.warning("Skipping secrets file %s", conf_path)
 | 
					 | 
				
			||||||
            continue
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        CORE.config_path = conf_path
 | 
					        CORE.config_path = conf_path
 | 
				
			||||||
        CORE.dashboard = args.dashboard
 | 
					        CORE.dashboard = args.dashboard
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,6 @@ import esphome.config_validation as cv
 | 
				
			|||||||
from esphome.const import (
 | 
					from esphome.const import (
 | 
				
			||||||
    CONF_AUTOMATION_ID,
 | 
					    CONF_AUTOMATION_ID,
 | 
				
			||||||
    CONF_CONDITION,
 | 
					    CONF_CONDITION,
 | 
				
			||||||
    CONF_COUNT,
 | 
					 | 
				
			||||||
    CONF_ELSE,
 | 
					    CONF_ELSE,
 | 
				
			||||||
    CONF_ID,
 | 
					    CONF_ID,
 | 
				
			||||||
    CONF_THEN,
 | 
					    CONF_THEN,
 | 
				
			||||||
@@ -67,7 +66,6 @@ DelayAction = cg.esphome_ns.class_("DelayAction", Action, cg.Component)
 | 
				
			|||||||
LambdaAction = cg.esphome_ns.class_("LambdaAction", Action)
 | 
					LambdaAction = cg.esphome_ns.class_("LambdaAction", Action)
 | 
				
			||||||
IfAction = cg.esphome_ns.class_("IfAction", Action)
 | 
					IfAction = cg.esphome_ns.class_("IfAction", Action)
 | 
				
			||||||
WhileAction = cg.esphome_ns.class_("WhileAction", Action)
 | 
					WhileAction = cg.esphome_ns.class_("WhileAction", Action)
 | 
				
			||||||
RepeatAction = cg.esphome_ns.class_("RepeatAction", Action)
 | 
					 | 
				
			||||||
WaitUntilAction = cg.esphome_ns.class_("WaitUntilAction", Action, cg.Component)
 | 
					WaitUntilAction = cg.esphome_ns.class_("WaitUntilAction", Action, cg.Component)
 | 
				
			||||||
UpdateComponentAction = cg.esphome_ns.class_("UpdateComponentAction", Action)
 | 
					UpdateComponentAction = cg.esphome_ns.class_("UpdateComponentAction", Action)
 | 
				
			||||||
Automation = cg.esphome_ns.class_("Automation")
 | 
					Automation = cg.esphome_ns.class_("Automation")
 | 
				
			||||||
@@ -243,25 +241,6 @@ async def while_action_to_code(config, action_id, template_arg, args):
 | 
				
			|||||||
    return var
 | 
					    return var
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@register_action(
 | 
					 | 
				
			||||||
    "repeat",
 | 
					 | 
				
			||||||
    RepeatAction,
 | 
					 | 
				
			||||||
    cv.Schema(
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            cv.Required(CONF_COUNT): cv.templatable(cv.positive_not_null_int),
 | 
					 | 
				
			||||||
            cv.Required(CONF_THEN): validate_action_list,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    ),
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
async def repeat_action_to_code(config, action_id, template_arg, args):
 | 
					 | 
				
			||||||
    var = cg.new_Pvariable(action_id, template_arg)
 | 
					 | 
				
			||||||
    count_template = await cg.templatable(config[CONF_COUNT], args, cg.uint32)
 | 
					 | 
				
			||||||
    cg.add(var.set_count(count_template))
 | 
					 | 
				
			||||||
    actions = await build_action_list(config[CONF_THEN], template_arg, args)
 | 
					 | 
				
			||||||
    cg.add(var.add_then(actions))
 | 
					 | 
				
			||||||
    return var
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def validate_wait_until(value):
 | 
					def validate_wait_until(value):
 | 
				
			||||||
    schema = cv.Schema(
 | 
					    schema = cv.Schema(
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -81,5 +81,4 @@ from esphome.cpp_types import (  # noqa
 | 
				
			|||||||
    GPIOPin,
 | 
					    GPIOPin,
 | 
				
			||||||
    InternalGPIOPin,
 | 
					    InternalGPIOPin,
 | 
				
			||||||
    gpio_Flags,
 | 
					    gpio_Flags,
 | 
				
			||||||
    EntityCategory,
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,7 +25,7 @@ void AdalightLightEffect::stop() {
 | 
				
			|||||||
  AddressableLightEffect::stop();
 | 
					  AddressableLightEffect::stop();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
unsigned int AdalightLightEffect::get_frame_size_(int led_count) const {
 | 
					int AdalightLightEffect::get_frame_size_(int led_count) const {
 | 
				
			||||||
  // 3 bytes: Ada
 | 
					  // 3 bytes: Ada
 | 
				
			||||||
  // 2 bytes: LED count
 | 
					  // 2 bytes: LED count
 | 
				
			||||||
  // 1 byte: checksum
 | 
					  // 1 byte: checksum
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,7 +25,7 @@ class AdalightLightEffect : public light::AddressableLightEffect, public uart::U
 | 
				
			|||||||
    CONSUMED,
 | 
					    CONSUMED,
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  unsigned int get_frame_size_(int led_count) const;
 | 
					  int get_frame_size_(int led_count) const;
 | 
				
			||||||
  void reset_frame_(light::AddressableLight &it);
 | 
					  void reset_frame_(light::AddressableLight &it);
 | 
				
			||||||
  void blank_all_leds_(light::AddressableLight &it);
 | 
					  void blank_all_leds_(light::AddressableLight &it);
 | 
				
			||||||
  Frame parse_frame_(light::AddressableLight &it);
 | 
					  Frame parse_frame_(light::AddressableLight &it);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,5 @@
 | 
				
			|||||||
#include "adc_sensor.h"
 | 
					#include "adc_sensor.h"
 | 
				
			||||||
#include "esphome/core/log.h"
 | 
					#include "esphome/core/log.h"
 | 
				
			||||||
#include "esphome/core/helpers.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef USE_ESP8266
 | 
					#ifdef USE_ESP8266
 | 
				
			||||||
#ifdef USE_ADC_SENSOR_VCC
 | 
					#ifdef USE_ADC_SENSOR_VCC
 | 
				
			||||||
@@ -16,6 +15,50 @@ namespace adc {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static const char *const TAG = "adc";
 | 
					static const char *const TAG = "adc";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef USE_ESP32
 | 
				
			||||||
 | 
					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;
 | 
				
			||||||
 | 
					    case 37:
 | 
				
			||||||
 | 
					      return ADC1_CHANNEL_1;
 | 
				
			||||||
 | 
					    case 38:
 | 
				
			||||||
 | 
					      return ADC1_CHANNEL_2;
 | 
				
			||||||
 | 
					    case 39:
 | 
				
			||||||
 | 
					      return ADC1_CHANNEL_3;
 | 
				
			||||||
 | 
					    case 32:
 | 
				
			||||||
 | 
					      return ADC1_CHANNEL_4;
 | 
				
			||||||
 | 
					    case 33:
 | 
				
			||||||
 | 
					      return ADC1_CHANNEL_5;
 | 
				
			||||||
 | 
					    case 34:
 | 
				
			||||||
 | 
					      return ADC1_CHANNEL_6;
 | 
				
			||||||
 | 
					    case 35:
 | 
				
			||||||
 | 
					      return ADC1_CHANNEL_7;
 | 
				
			||||||
 | 
					    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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ADCSensor::setup() {
 | 
					void ADCSensor::setup() {
 | 
				
			||||||
  ESP_LOGCONFIG(TAG, "Setting up ADC '%s'...", this->get_name().c_str());
 | 
					  ESP_LOGCONFIG(TAG, "Setting up ADC '%s'...", this->get_name().c_str());
 | 
				
			||||||
#ifndef USE_ADC_SENSOR_VCC
 | 
					#ifndef USE_ADC_SENSOR_VCC
 | 
				
			||||||
@@ -23,36 +66,13 @@ void ADCSensor::setup() {
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef USE_ESP32
 | 
					#ifdef USE_ESP32
 | 
				
			||||||
 | 
					  adc1_config_channel_atten(gpio_to_adc1(pin_->get_pin()), attenuation_);
 | 
				
			||||||
  adc1_config_width(ADC_WIDTH_BIT_12);
 | 
					  adc1_config_width(ADC_WIDTH_BIT_12);
 | 
				
			||||||
  if (!autorange_) {
 | 
					#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2
 | 
				
			||||||
    adc1_config_channel_atten(channel_, attenuation_);
 | 
					  adc_gpio_init(ADC_UNIT_1, (adc_channel_t) gpio_to_adc1(pin_->get_pin()));
 | 
				
			||||||
  }
 | 
					#endif
 | 
				
			||||||
 | 
					 | 
				
			||||||
  // load characteristics for each attenuation
 | 
					 | 
				
			||||||
  for (int i = 0; i < (int) ADC_ATTEN_MAX; i++) {
 | 
					 | 
				
			||||||
    auto cal_value = esp_adc_cal_characterize(ADC_UNIT_1, (adc_atten_t) i, ADC_WIDTH_BIT_12,
 | 
					 | 
				
			||||||
                                              1100,  // default vref
 | 
					 | 
				
			||||||
                                              &cal_characteristics_[i]);
 | 
					 | 
				
			||||||
    switch (cal_value) {
 | 
					 | 
				
			||||||
      case ESP_ADC_CAL_VAL_EFUSE_VREF:
 | 
					 | 
				
			||||||
        ESP_LOGV(TAG, "Using eFuse Vref for calibration");
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
      case ESP_ADC_CAL_VAL_EFUSE_TP:
 | 
					 | 
				
			||||||
        ESP_LOGV(TAG, "Using two-point eFuse Vref for calibration");
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
      case ESP_ADC_CAL_VAL_DEFAULT_VREF:
 | 
					 | 
				
			||||||
      default:
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // adc_gpio_init doesn't exist on ESP32-C3 or ESP32-H2
 | 
					 | 
				
			||||||
#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32H2)
 | 
					 | 
				
			||||||
  adc_gpio_init(ADC_UNIT_1, (adc_channel_t) channel_);
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#endif  // USE_ESP32
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
void ADCSensor::dump_config() {
 | 
					void ADCSensor::dump_config() {
 | 
				
			||||||
  LOG_SENSOR("", "ADC Sensor", this);
 | 
					  LOG_SENSOR("", "ADC Sensor", this);
 | 
				
			||||||
#ifdef USE_ESP8266
 | 
					#ifdef USE_ESP8266
 | 
				
			||||||
@@ -61,107 +81,84 @@ void ADCSensor::dump_config() {
 | 
				
			|||||||
#else
 | 
					#else
 | 
				
			||||||
  LOG_PIN("  Pin: ", pin_);
 | 
					  LOG_PIN("  Pin: ", pin_);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#endif  // USE_ESP8266
 | 
					#endif
 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef USE_ESP32
 | 
					#ifdef USE_ESP32
 | 
				
			||||||
  LOG_PIN("  Pin: ", pin_);
 | 
					  LOG_PIN("  Pin: ", pin_);
 | 
				
			||||||
  if (autorange_)
 | 
					  switch (this->attenuation_) {
 | 
				
			||||||
    ESP_LOGCONFIG(TAG, " Attenuation: auto");
 | 
					    case ADC_ATTEN_DB_0:
 | 
				
			||||||
  else
 | 
					      ESP_LOGCONFIG(TAG, " Attenuation: 0db (max 1.1V)");
 | 
				
			||||||
    switch (this->attenuation_) {
 | 
					      break;
 | 
				
			||||||
      case ADC_ATTEN_DB_0:
 | 
					    case ADC_ATTEN_DB_2_5:
 | 
				
			||||||
        ESP_LOGCONFIG(TAG, " Attenuation: 0db (max 1.1V)");
 | 
					      ESP_LOGCONFIG(TAG, " Attenuation: 2.5db (max 1.5V)");
 | 
				
			||||||
        break;
 | 
					      break;
 | 
				
			||||||
      case ADC_ATTEN_DB_2_5:
 | 
					    case ADC_ATTEN_DB_6:
 | 
				
			||||||
        ESP_LOGCONFIG(TAG, " Attenuation: 2.5db (max 1.5V)");
 | 
					      ESP_LOGCONFIG(TAG, " Attenuation: 6db (max 2.2V)");
 | 
				
			||||||
        break;
 | 
					      break;
 | 
				
			||||||
      case ADC_ATTEN_DB_6:
 | 
					    case ADC_ATTEN_DB_11:
 | 
				
			||||||
        ESP_LOGCONFIG(TAG, " Attenuation: 6db (max 2.2V)");
 | 
					      ESP_LOGCONFIG(TAG, " Attenuation: 11db (max 3.9V)");
 | 
				
			||||||
        break;
 | 
					      break;
 | 
				
			||||||
      case ADC_ATTEN_DB_11:
 | 
					    default:  // This is to satisfy the unused ADC_ATTEN_MAX
 | 
				
			||||||
        ESP_LOGCONFIG(TAG, " Attenuation: 11db (max 3.9V)");
 | 
					      break;
 | 
				
			||||||
        break;
 | 
					  }
 | 
				
			||||||
      default:  // This is to satisfy the unused ADC_ATTEN_MAX
 | 
					#endif
 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
#endif  // USE_ESP32
 | 
					 | 
				
			||||||
  LOG_UPDATE_INTERVAL(this);
 | 
					  LOG_UPDATE_INTERVAL(this);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
float ADCSensor::get_setup_priority() const { return setup_priority::DATA; }
 | 
					float ADCSensor::get_setup_priority() const { return setup_priority::DATA; }
 | 
				
			||||||
void ADCSensor::update() {
 | 
					void ADCSensor::update() {
 | 
				
			||||||
  float value_v = this->sample();
 | 
					  float value_v = this->sample();
 | 
				
			||||||
  ESP_LOGV(TAG, "'%s': Got voltage=%.4fV", this->get_name().c_str(), value_v);
 | 
					  ESP_LOGD(TAG, "'%s': Got voltage=%.2fV", this->get_name().c_str(), value_v);
 | 
				
			||||||
  this->publish_state(value_v);
 | 
					  this->publish_state(value_v);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					float ADCSensor::sample() {
 | 
				
			||||||
 | 
					#ifdef USE_ESP32
 | 
				
			||||||
 | 
					  int raw = adc1_get_raw(gpio_to_adc1(pin_->get_pin()));
 | 
				
			||||||
 | 
					  float value_v = raw / 4095.0f;
 | 
				
			||||||
 | 
					#if CONFIG_IDF_TARGET_ESP32
 | 
				
			||||||
 | 
					  switch (this->attenuation_) {
 | 
				
			||||||
 | 
					    case ADC_ATTEN_DB_0:
 | 
				
			||||||
 | 
					      value_v *= 1.1;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case ADC_ATTEN_DB_2_5:
 | 
				
			||||||
 | 
					      value_v *= 1.5;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case ADC_ATTEN_DB_6:
 | 
				
			||||||
 | 
					      value_v *= 2.2;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case ADC_ATTEN_DB_11:
 | 
				
			||||||
 | 
					      value_v *= 3.9;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef USE_ESP8266
 | 
					#ifdef USE_ESP8266
 | 
				
			||||||
float ADCSensor::sample() {
 | 
					 | 
				
			||||||
#ifdef USE_ADC_SENSOR_VCC
 | 
					#ifdef USE_ADC_SENSOR_VCC
 | 
				
			||||||
  int raw = ESP.getVcc();  // NOLINT(readability-static-accessed-through-instance)
 | 
					  return ESP.getVcc() / 1024.0f;  // NOLINT(readability-static-accessed-through-instance)
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
  int raw = analogRead(this->pin_->get_pin());  // NOLINT
 | 
					  return analogRead(this->pin_->get_pin()) / 1024.0f;  // NOLINT
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
  if (output_raw_) {
 | 
					 | 
				
			||||||
    return raw;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return raw / 1024.0f;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef USE_ESP32
 | 
					 | 
				
			||||||
float ADCSensor::sample() {
 | 
					 | 
				
			||||||
  if (!autorange_) {
 | 
					 | 
				
			||||||
    int raw = adc1_get_raw(channel_);
 | 
					 | 
				
			||||||
    if (raw == -1) {
 | 
					 | 
				
			||||||
      return NAN;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (output_raw_) {
 | 
					 | 
				
			||||||
      return raw;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    uint32_t mv = esp_adc_cal_raw_to_voltage(raw, &cal_characteristics_[(int) attenuation_]);
 | 
					 | 
				
			||||||
    return mv / 1000.0f;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  int raw11, raw6 = 4095, raw2 = 4095, raw0 = 4095;
 | 
					 | 
				
			||||||
  adc1_config_channel_atten(channel_, ADC_ATTEN_DB_11);
 | 
					 | 
				
			||||||
  raw11 = adc1_get_raw(channel_);
 | 
					 | 
				
			||||||
  if (raw11 < 4095) {
 | 
					 | 
				
			||||||
    adc1_config_channel_atten(channel_, ADC_ATTEN_DB_6);
 | 
					 | 
				
			||||||
    raw6 = adc1_get_raw(channel_);
 | 
					 | 
				
			||||||
    if (raw6 < 4095) {
 | 
					 | 
				
			||||||
      adc1_config_channel_atten(channel_, ADC_ATTEN_DB_2_5);
 | 
					 | 
				
			||||||
      raw2 = adc1_get_raw(channel_);
 | 
					 | 
				
			||||||
      if (raw2 < 4095) {
 | 
					 | 
				
			||||||
        adc1_config_channel_atten(channel_, ADC_ATTEN_DB_0);
 | 
					 | 
				
			||||||
        raw0 = adc1_get_raw(channel_);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (raw0 == -1 || raw2 == -1 || raw6 == -1 || raw11 == -1) {
 | 
					 | 
				
			||||||
    return NAN;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  uint32_t mv11 = esp_adc_cal_raw_to_voltage(raw11, &cal_characteristics_[(int) ADC_ATTEN_DB_11]);
 | 
					 | 
				
			||||||
  uint32_t mv6 = esp_adc_cal_raw_to_voltage(raw6, &cal_characteristics_[(int) ADC_ATTEN_DB_6]);
 | 
					 | 
				
			||||||
  uint32_t mv2 = esp_adc_cal_raw_to_voltage(raw2, &cal_characteristics_[(int) ADC_ATTEN_DB_2_5]);
 | 
					 | 
				
			||||||
  uint32_t mv0 = esp_adc_cal_raw_to_voltage(raw0, &cal_characteristics_[(int) ADC_ATTEN_DB_0]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Contribution of each value, in range 0-2048
 | 
					 | 
				
			||||||
  uint32_t c11 = std::min(raw11, 2048);
 | 
					 | 
				
			||||||
  uint32_t c6 = 2048 - std::abs(raw6 - 2048);
 | 
					 | 
				
			||||||
  uint32_t c2 = 2048 - std::abs(raw2 - 2048);
 | 
					 | 
				
			||||||
  uint32_t c0 = std::min(4095 - raw0, 2048);
 | 
					 | 
				
			||||||
  // max theoretical csum value is 2048*4 = 8192
 | 
					 | 
				
			||||||
  uint32_t csum = c11 + c6 + c2 + c0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // each mv is max 3900; so max value is 3900*2048*4, fits in unsigned
 | 
					 | 
				
			||||||
  uint32_t mv_scaled = (mv11 * c11) + (mv6 * c6) + (mv2 * c2) + (mv0 * c0);
 | 
					 | 
				
			||||||
  return mv_scaled / (float) (csum * 1000U);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif  // USE_ESP32
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef USE_ESP8266
 | 
					#ifdef USE_ESP8266
 | 
				
			||||||
std::string ADCSensor::unique_id() { return get_mac_address() + "-adc"; }
 | 
					std::string ADCSensor::unique_id() { return get_mac_address() + "-adc"; }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#ifdef USE_ESP32
 | 
					#ifdef USE_ESP32
 | 
				
			||||||
#include "driver/adc.h"
 | 
					#include "driver/adc.h"
 | 
				
			||||||
#include <esp_adc_cal.h>
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace esphome {
 | 
					namespace esphome {
 | 
				
			||||||
@@ -18,9 +17,7 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage
 | 
				
			|||||||
 public:
 | 
					 public:
 | 
				
			||||||
#ifdef USE_ESP32
 | 
					#ifdef USE_ESP32
 | 
				
			||||||
  /// Set the attenuation for this pin. Only available on the ESP32.
 | 
					  /// Set the attenuation for this pin. Only available on the ESP32.
 | 
				
			||||||
  void set_attenuation(adc_atten_t attenuation) { attenuation_ = attenuation; }
 | 
					  void set_attenuation(adc_atten_t attenuation);
 | 
				
			||||||
  void set_channel(adc1_channel_t channel) { channel_ = channel; }
 | 
					 | 
				
			||||||
  void set_autorange(bool autorange) { autorange_ = autorange; }
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Update adc values.
 | 
					  /// Update adc values.
 | 
				
			||||||
@@ -31,7 +28,6 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage
 | 
				
			|||||||
  /// `HARDWARE_LATE` setup priority.
 | 
					  /// `HARDWARE_LATE` setup priority.
 | 
				
			||||||
  float get_setup_priority() const override;
 | 
					  float get_setup_priority() const override;
 | 
				
			||||||
  void set_pin(InternalGPIOPin *pin) { this->pin_ = pin; }
 | 
					  void set_pin(InternalGPIOPin *pin) { this->pin_ = pin; }
 | 
				
			||||||
  void set_output_raw(bool output_raw) { output_raw_ = output_raw; }
 | 
					 | 
				
			||||||
  float sample() override;
 | 
					  float sample() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef USE_ESP8266
 | 
					#ifdef USE_ESP8266
 | 
				
			||||||
@@ -40,13 +36,9 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 protected:
 | 
					 protected:
 | 
				
			||||||
  InternalGPIOPin *pin_;
 | 
					  InternalGPIOPin *pin_;
 | 
				
			||||||
  bool output_raw_{false};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef USE_ESP32
 | 
					#ifdef USE_ESP32
 | 
				
			||||||
  adc_atten_t attenuation_{ADC_ATTEN_DB_0};
 | 
					  adc_atten_t attenuation_{ADC_ATTEN_DB_0};
 | 
				
			||||||
  adc1_channel_t channel_{};
 | 
					 | 
				
			||||||
  bool autorange_{false};
 | 
					 | 
				
			||||||
  esp_adc_cal_characteristics_t cal_characteristics_[(int) ADC_ATTEN_MAX] = {};
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,24 +4,14 @@ from esphome import pins
 | 
				
			|||||||
from esphome.components import sensor, voltage_sampler
 | 
					from esphome.components import sensor, voltage_sampler
 | 
				
			||||||
from esphome.const import (
 | 
					from esphome.const import (
 | 
				
			||||||
    CONF_ATTENUATION,
 | 
					    CONF_ATTENUATION,
 | 
				
			||||||
    CONF_RAW,
 | 
					 | 
				
			||||||
    CONF_ID,
 | 
					    CONF_ID,
 | 
				
			||||||
    CONF_INPUT,
 | 
					    CONF_INPUT,
 | 
				
			||||||
    CONF_NUMBER,
 | 
					 | 
				
			||||||
    CONF_PIN,
 | 
					    CONF_PIN,
 | 
				
			||||||
    DEVICE_CLASS_VOLTAGE,
 | 
					    DEVICE_CLASS_VOLTAGE,
 | 
				
			||||||
    STATE_CLASS_MEASUREMENT,
 | 
					    STATE_CLASS_MEASUREMENT,
 | 
				
			||||||
    UNIT_VOLT,
 | 
					    UNIT_VOLT,
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
from esphome.core import CORE
 | 
					from esphome.core import CORE
 | 
				
			||||||
from esphome.components.esp32 import get_esp32_variant
 | 
					 | 
				
			||||||
from esphome.components.esp32.const import (
 | 
					 | 
				
			||||||
    VARIANT_ESP32,
 | 
					 | 
				
			||||||
    VARIANT_ESP32C3,
 | 
					 | 
				
			||||||
    VARIANT_ESP32H2,
 | 
					 | 
				
			||||||
    VARIANT_ESP32S2,
 | 
					 | 
				
			||||||
    VARIANT_ESP32S3,
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AUTO_LOAD = ["voltage_sampler"]
 | 
					AUTO_LOAD = ["voltage_sampler"]
 | 
				
			||||||
@@ -31,62 +21,6 @@ ATTENUATION_MODES = {
 | 
				
			|||||||
    "2.5db": cg.global_ns.ADC_ATTEN_DB_2_5,
 | 
					    "2.5db": cg.global_ns.ADC_ATTEN_DB_2_5,
 | 
				
			||||||
    "6db": cg.global_ns.ADC_ATTEN_DB_6,
 | 
					    "6db": cg.global_ns.ADC_ATTEN_DB_6,
 | 
				
			||||||
    "11db": cg.global_ns.ADC_ATTEN_DB_11,
 | 
					    "11db": cg.global_ns.ADC_ATTEN_DB_11,
 | 
				
			||||||
    "auto": "auto",
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
adc1_channel_t = cg.global_ns.enum("adc1_channel_t")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# From https://github.com/espressif/esp-idf/blob/master/components/driver/include/driver/adc_common.h
 | 
					 | 
				
			||||||
# pin to adc1 channel mapping
 | 
					 | 
				
			||||||
ESP32_VARIANT_ADC1_PIN_TO_CHANNEL = {
 | 
					 | 
				
			||||||
    VARIANT_ESP32: {
 | 
					 | 
				
			||||||
        36: adc1_channel_t.ADC1_CHANNEL_0,
 | 
					 | 
				
			||||||
        37: adc1_channel_t.ADC1_CHANNEL_1,
 | 
					 | 
				
			||||||
        38: adc1_channel_t.ADC1_CHANNEL_2,
 | 
					 | 
				
			||||||
        39: adc1_channel_t.ADC1_CHANNEL_3,
 | 
					 | 
				
			||||||
        32: adc1_channel_t.ADC1_CHANNEL_4,
 | 
					 | 
				
			||||||
        33: adc1_channel_t.ADC1_CHANNEL_5,
 | 
					 | 
				
			||||||
        34: adc1_channel_t.ADC1_CHANNEL_6,
 | 
					 | 
				
			||||||
        35: adc1_channel_t.ADC1_CHANNEL_7,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    VARIANT_ESP32S2: {
 | 
					 | 
				
			||||||
        1: adc1_channel_t.ADC1_CHANNEL_0,
 | 
					 | 
				
			||||||
        2: adc1_channel_t.ADC1_CHANNEL_1,
 | 
					 | 
				
			||||||
        3: adc1_channel_t.ADC1_CHANNEL_2,
 | 
					 | 
				
			||||||
        4: adc1_channel_t.ADC1_CHANNEL_3,
 | 
					 | 
				
			||||||
        5: adc1_channel_t.ADC1_CHANNEL_4,
 | 
					 | 
				
			||||||
        6: adc1_channel_t.ADC1_CHANNEL_5,
 | 
					 | 
				
			||||||
        7: adc1_channel_t.ADC1_CHANNEL_6,
 | 
					 | 
				
			||||||
        8: adc1_channel_t.ADC1_CHANNEL_7,
 | 
					 | 
				
			||||||
        9: adc1_channel_t.ADC1_CHANNEL_8,
 | 
					 | 
				
			||||||
        10: adc1_channel_t.ADC1_CHANNEL_9,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    VARIANT_ESP32S3: {
 | 
					 | 
				
			||||||
        1: adc1_channel_t.ADC1_CHANNEL_0,
 | 
					 | 
				
			||||||
        2: adc1_channel_t.ADC1_CHANNEL_1,
 | 
					 | 
				
			||||||
        3: adc1_channel_t.ADC1_CHANNEL_2,
 | 
					 | 
				
			||||||
        4: adc1_channel_t.ADC1_CHANNEL_3,
 | 
					 | 
				
			||||||
        5: adc1_channel_t.ADC1_CHANNEL_4,
 | 
					 | 
				
			||||||
        6: adc1_channel_t.ADC1_CHANNEL_5,
 | 
					 | 
				
			||||||
        7: adc1_channel_t.ADC1_CHANNEL_6,
 | 
					 | 
				
			||||||
        8: adc1_channel_t.ADC1_CHANNEL_7,
 | 
					 | 
				
			||||||
        9: adc1_channel_t.ADC1_CHANNEL_8,
 | 
					 | 
				
			||||||
        10: adc1_channel_t.ADC1_CHANNEL_9,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    VARIANT_ESP32C3: {
 | 
					 | 
				
			||||||
        0: adc1_channel_t.ADC1_CHANNEL_0,
 | 
					 | 
				
			||||||
        1: adc1_channel_t.ADC1_CHANNEL_1,
 | 
					 | 
				
			||||||
        2: adc1_channel_t.ADC1_CHANNEL_2,
 | 
					 | 
				
			||||||
        3: adc1_channel_t.ADC1_CHANNEL_3,
 | 
					 | 
				
			||||||
        4: adc1_channel_t.ADC1_CHANNEL_4,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    VARIANT_ESP32H2: {
 | 
					 | 
				
			||||||
        0: adc1_channel_t.ADC1_CHANNEL_0,
 | 
					 | 
				
			||||||
        1: adc1_channel_t.ADC1_CHANNEL_1,
 | 
					 | 
				
			||||||
        2: adc1_channel_t.ADC1_CHANNEL_2,
 | 
					 | 
				
			||||||
        3: adc1_channel_t.ADC1_CHANNEL_3,
 | 
					 | 
				
			||||||
        4: adc1_channel_t.ADC1_CHANNEL_4,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -95,16 +29,15 @@ def validate_adc_pin(value):
 | 
				
			|||||||
        return cv.only_on_esp8266("VCC")
 | 
					        return cv.only_on_esp8266("VCC")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if CORE.is_esp32:
 | 
					    if CORE.is_esp32:
 | 
				
			||||||
 | 
					        from esphome.components.esp32 import is_esp32c3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        value = pins.internal_gpio_input_pin_number(value)
 | 
					        value = pins.internal_gpio_input_pin_number(value)
 | 
				
			||||||
        variant = get_esp32_variant()
 | 
					        if is_esp32c3():
 | 
				
			||||||
        if variant not in ESP32_VARIANT_ADC1_PIN_TO_CHANNEL:
 | 
					            if not (0 <= value <= 4):  # ADC1
 | 
				
			||||||
            raise cv.Invalid(f"This ESP32 variant ({variant}) is not supported")
 | 
					                raise cv.Invalid("ESP32-C3: Only pins 0 though 4 support ADC.")
 | 
				
			||||||
 | 
					        elif not (32 <= value <= 39):  # ADC1
 | 
				
			||||||
        if value not in ESP32_VARIANT_ADC1_PIN_TO_CHANNEL[variant]:
 | 
					            raise cv.Invalid("ESP32: Only pins 32 though 39 support ADC.")
 | 
				
			||||||
            raise cv.Invalid(f"{variant} doesn't support ADC on this pin")
 | 
					    elif CORE.is_esp8266:
 | 
				
			||||||
        return pins.internal_gpio_input_pin_schema(value)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if CORE.is_esp8266:
 | 
					 | 
				
			||||||
        from esphome.components.esp8266.gpio import CONF_ANALOG
 | 
					        from esphome.components.esp8266.gpio import CONF_ANALOG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        value = pins.internal_gpio_pin_number({CONF_ANALOG: True, CONF_INPUT: True})(
 | 
					        value = pins.internal_gpio_pin_number({CONF_ANALOG: True, CONF_INPUT: True})(
 | 
				
			||||||
@@ -116,14 +49,10 @@ def validate_adc_pin(value):
 | 
				
			|||||||
        return pins.gpio_pin_schema(
 | 
					        return pins.gpio_pin_schema(
 | 
				
			||||||
            {CONF_ANALOG: True, CONF_INPUT: True}, internal=True
 | 
					            {CONF_ANALOG: True, CONF_INPUT: True}, internal=True
 | 
				
			||||||
        )(value)
 | 
					        )(value)
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        raise NotImplementedError
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    raise NotImplementedError
 | 
					    return pins.internal_gpio_input_pin_schema(value)
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def validate_config(config):
 | 
					 | 
				
			||||||
    if config[CONF_RAW] and config.get(CONF_ATTENUATION, None) == "auto":
 | 
					 | 
				
			||||||
        raise cv.Invalid("Automatic attenuation cannot be used when raw output is set.")
 | 
					 | 
				
			||||||
    return config
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
adc_ns = cg.esphome_ns.namespace("adc")
 | 
					adc_ns = cg.esphome_ns.namespace("adc")
 | 
				
			||||||
@@ -131,7 +60,7 @@ ADCSensor = adc_ns.class_(
 | 
				
			|||||||
    "ADCSensor", sensor.Sensor, cg.PollingComponent, voltage_sampler.VoltageSampler
 | 
					    "ADCSensor", sensor.Sensor, cg.PollingComponent, voltage_sampler.VoltageSampler
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CONFIG_SCHEMA = cv.All(
 | 
					CONFIG_SCHEMA = (
 | 
				
			||||||
    sensor.sensor_schema(
 | 
					    sensor.sensor_schema(
 | 
				
			||||||
        unit_of_measurement=UNIT_VOLT,
 | 
					        unit_of_measurement=UNIT_VOLT,
 | 
				
			||||||
        accuracy_decimals=2,
 | 
					        accuracy_decimals=2,
 | 
				
			||||||
@@ -142,14 +71,12 @@ CONFIG_SCHEMA = cv.All(
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            cv.GenerateID(): cv.declare_id(ADCSensor),
 | 
					            cv.GenerateID(): cv.declare_id(ADCSensor),
 | 
				
			||||||
            cv.Required(CONF_PIN): validate_adc_pin,
 | 
					            cv.Required(CONF_PIN): validate_adc_pin,
 | 
				
			||||||
            cv.Optional(CONF_RAW, default=False): cv.boolean,
 | 
					 | 
				
			||||||
            cv.SplitDefault(CONF_ATTENUATION, esp32="0db"): cv.All(
 | 
					            cv.SplitDefault(CONF_ATTENUATION, esp32="0db"): cv.All(
 | 
				
			||||||
                cv.only_on_esp32, cv.enum(ATTENUATION_MODES, lower=True)
 | 
					                cv.only_on_esp32, cv.enum(ATTENUATION_MODES, lower=True)
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    .extend(cv.polling_component_schema("60s")),
 | 
					    .extend(cv.polling_component_schema("60s"))
 | 
				
			||||||
    validate_config,
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -164,17 +91,5 @@ async def to_code(config):
 | 
				
			|||||||
        pin = await cg.gpio_pin_expression(config[CONF_PIN])
 | 
					        pin = await cg.gpio_pin_expression(config[CONF_PIN])
 | 
				
			||||||
        cg.add(var.set_pin(pin))
 | 
					        cg.add(var.set_pin(pin))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if CONF_RAW in config:
 | 
					 | 
				
			||||||
        cg.add(var.set_output_raw(config[CONF_RAW]))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if CONF_ATTENUATION in config:
 | 
					    if CONF_ATTENUATION in config:
 | 
				
			||||||
        if config[CONF_ATTENUATION] == "auto":
 | 
					        cg.add(var.set_attenuation(config[CONF_ATTENUATION]))
 | 
				
			||||||
            cg.add(var.set_autorange(cg.global_ns.true))
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            cg.add(var.set_attenuation(config[CONF_ATTENUATION]))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if CORE.is_esp32:
 | 
					 | 
				
			||||||
        variant = get_esp32_variant()
 | 
					 | 
				
			||||||
        pin_num = config[CONF_PIN][CONF_NUMBER]
 | 
					 | 
				
			||||||
        chan = ESP32_VARIANT_ADC1_PIN_TO_CHANNEL[variant][pin_num]
 | 
					 | 
				
			||||||
        cg.add(var.set_channel(chan))
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -73,6 +73,13 @@ void AHT10Component::update() {
 | 
				
			|||||||
  bool success = false;
 | 
					  bool success = false;
 | 
				
			||||||
  for (int i = 0; i < AHT10_ATTEMPTS; ++i) {
 | 
					  for (int i = 0; i < AHT10_ATTEMPTS; ++i) {
 | 
				
			||||||
    ESP_LOGVV(TAG, "Attempt %d at %6u", i, millis());
 | 
					    ESP_LOGVV(TAG, "Attempt %d at %6u", i, millis());
 | 
				
			||||||
 | 
					    delay_microseconds_accurate(4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint8_t reg = 0;
 | 
				
			||||||
 | 
					    if (this->write(®, 1) != i2c::ERROR_OK) {
 | 
				
			||||||
 | 
					      ESP_LOGD(TAG, "Communication with AHT10 failed, waiting...");
 | 
				
			||||||
 | 
					      continue;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    delay(delay_ms);
 | 
					    delay(delay_ms);
 | 
				
			||||||
    if (this->read(data, 6) != i2c::ERROR_OK) {
 | 
					    if (this->read(data, 6) != i2c::ERROR_OK) {
 | 
				
			||||||
      ESP_LOGD(TAG, "Communication with AHT10 failed, waiting...");
 | 
					      ESP_LOGD(TAG, "Communication with AHT10 failed, waiting...");
 | 
				
			||||||
@@ -110,12 +117,12 @@ void AHT10Component::update() {
 | 
				
			|||||||
  uint32_t raw_temperature = ((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5];
 | 
					  uint32_t raw_temperature = ((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5];
 | 
				
			||||||
  uint32_t raw_humidity = ((data[1] << 16) | (data[2] << 8) | data[3]) >> 4;
 | 
					  uint32_t raw_humidity = ((data[1] << 16) | (data[2] << 8) | data[3]) >> 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  float temperature = ((200.0f * (float) raw_temperature) / 1048576.0f) - 50.0f;
 | 
					  float temperature = ((200.0 * (float) raw_temperature) / 1048576.0) - 50.0;
 | 
				
			||||||
  float humidity;
 | 
					  float humidity;
 | 
				
			||||||
  if (raw_humidity == 0) {  // unrealistic value
 | 
					  if (raw_humidity == 0) {  // unrealistic value
 | 
				
			||||||
    humidity = NAN;
 | 
					    humidity = NAN;
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    humidity = (float) raw_humidity * 100.0f / 1048576.0f;
 | 
					    humidity = (float) raw_humidity * 100.0 / 1048576.0;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (this->temperature_sensor_ != nullptr) {
 | 
					  if (this->temperature_sensor_ != nullptr) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,9 +38,9 @@ void AM2320Component::update() {
 | 
				
			|||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  float temperature = (((data[4] & 0x7F) << 8) + data[5]) / 10.0f;
 | 
					  float temperature = (((data[4] & 0x7F) << 8) + data[5]) / 10.0;
 | 
				
			||||||
  temperature = (data[4] & 0x80) ? -temperature : temperature;
 | 
					  temperature = (data[4] & 0x80) ? -temperature : temperature;
 | 
				
			||||||
  float humidity = ((data[2] << 8) + data[3]) / 10.0f;
 | 
					  float humidity = ((data[2] << 8) + data[3]) / 10.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ESP_LOGD(TAG, "Got temperature=%.1f°C humidity=%.1f%%", temperature, humidity);
 | 
					  ESP_LOGD(TAG, "Got temperature=%.1f°C humidity=%.1f%%", temperature, humidity);
 | 
				
			||||||
  if (this->temperature_sensor_ != nullptr)
 | 
					  if (this->temperature_sensor_ != nullptr)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,8 +4,7 @@ from esphome.components import sensor, ble_client
 | 
				
			|||||||
from esphome.const import (
 | 
					from esphome.const import (
 | 
				
			||||||
    CONF_ID,
 | 
					    CONF_ID,
 | 
				
			||||||
    CONF_BATTERY_LEVEL,
 | 
					    CONF_BATTERY_LEVEL,
 | 
				
			||||||
    DEVICE_CLASS_BATTERY,
 | 
					    ICON_BATTERY,
 | 
				
			||||||
    ENTITY_CATEGORY_DIAGNOSTIC,
 | 
					 | 
				
			||||||
    CONF_ILLUMINANCE,
 | 
					    CONF_ILLUMINANCE,
 | 
				
			||||||
    ICON_BRIGHTNESS_5,
 | 
					    ICON_BRIGHTNESS_5,
 | 
				
			||||||
    UNIT_PERCENT,
 | 
					    UNIT_PERCENT,
 | 
				
			||||||
@@ -21,15 +20,10 @@ CONFIG_SCHEMA = (
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            cv.GenerateID(): cv.declare_id(Am43),
 | 
					            cv.GenerateID(): cv.declare_id(Am43),
 | 
				
			||||||
            cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema(
 | 
					            cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema(
 | 
				
			||||||
                unit_of_measurement=UNIT_PERCENT,
 | 
					                UNIT_PERCENT, ICON_BATTERY, 0
 | 
				
			||||||
                device_class=DEVICE_CLASS_BATTERY,
 | 
					 | 
				
			||||||
                accuracy_decimals=0,
 | 
					 | 
				
			||||||
                entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
 | 
					 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            cv.Optional(CONF_ILLUMINANCE): sensor.sensor_schema(
 | 
					            cv.Optional(CONF_ILLUMINANCE): sensor.sensor_schema(
 | 
				
			||||||
                unit_of_measurement=UNIT_PERCENT,
 | 
					                UNIT_PERCENT, ICON_BRIGHTNESS_5, 0
 | 
				
			||||||
                icon=ICON_BRIGHTNESS_5,
 | 
					 | 
				
			||||||
                accuracy_decimals=0,
 | 
					 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -44,9 +44,8 @@ async def to_code(config):
 | 
				
			|||||||
    width, height = image.size
 | 
					    width, height = image.size
 | 
				
			||||||
    frames = image.n_frames
 | 
					    frames = image.n_frames
 | 
				
			||||||
    if CONF_RESIZE in config:
 | 
					    if CONF_RESIZE in config:
 | 
				
			||||||
        new_width_max, new_height_max = config[CONF_RESIZE]
 | 
					        image.thumbnail(config[CONF_RESIZE])
 | 
				
			||||||
        ratio = min(new_width_max / width, new_height_max / height)
 | 
					        width, height = image.size
 | 
				
			||||||
        width, height = int(width * ratio), int(height * ratio)
 | 
					 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        if width > 500 or height > 500:
 | 
					        if width > 500 or height > 500:
 | 
				
			||||||
            _LOGGER.warning(
 | 
					            _LOGGER.warning(
 | 
				
			||||||
@@ -60,13 +59,7 @@ async def to_code(config):
 | 
				
			|||||||
        for frameIndex in range(frames):
 | 
					        for frameIndex in range(frames):
 | 
				
			||||||
            image.seek(frameIndex)
 | 
					            image.seek(frameIndex)
 | 
				
			||||||
            frame = image.convert("L", dither=Image.NONE)
 | 
					            frame = image.convert("L", dither=Image.NONE)
 | 
				
			||||||
            if CONF_RESIZE in config:
 | 
					 | 
				
			||||||
                frame = frame.resize([width, height])
 | 
					 | 
				
			||||||
            pixels = list(frame.getdata())
 | 
					            pixels = list(frame.getdata())
 | 
				
			||||||
            if len(pixels) != height * width:
 | 
					 | 
				
			||||||
                raise core.EsphomeError(
 | 
					 | 
				
			||||||
                    f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height*width})"
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
            for pix in pixels:
 | 
					            for pix in pixels:
 | 
				
			||||||
                data[pos] = pix
 | 
					                data[pos] = pix
 | 
				
			||||||
                pos += 1
 | 
					                pos += 1
 | 
				
			||||||
@@ -77,13 +70,7 @@ async def to_code(config):
 | 
				
			|||||||
        for frameIndex in range(frames):
 | 
					        for frameIndex in range(frames):
 | 
				
			||||||
            image.seek(frameIndex)
 | 
					            image.seek(frameIndex)
 | 
				
			||||||
            frame = image.convert("RGB")
 | 
					            frame = image.convert("RGB")
 | 
				
			||||||
            if CONF_RESIZE in config:
 | 
					 | 
				
			||||||
                frame = frame.resize([width, height])
 | 
					 | 
				
			||||||
            pixels = list(frame.getdata())
 | 
					            pixels = list(frame.getdata())
 | 
				
			||||||
            if len(pixels) != height * width:
 | 
					 | 
				
			||||||
                raise core.EsphomeError(
 | 
					 | 
				
			||||||
                    f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height*width})"
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
            for pix in pixels:
 | 
					            for pix in pixels:
 | 
				
			||||||
                data[pos] = pix[0]
 | 
					                data[pos] = pix[0]
 | 
				
			||||||
                pos += 1
 | 
					                pos += 1
 | 
				
			||||||
@@ -98,8 +85,6 @@ async def to_code(config):
 | 
				
			|||||||
        for frameIndex in range(frames):
 | 
					        for frameIndex in range(frames):
 | 
				
			||||||
            image.seek(frameIndex)
 | 
					            image.seek(frameIndex)
 | 
				
			||||||
            frame = image.convert("1", dither=Image.NONE)
 | 
					            frame = image.convert("1", dither=Image.NONE)
 | 
				
			||||||
            if CONF_RESIZE in config:
 | 
					 | 
				
			||||||
                frame = frame.resize([width, height])
 | 
					 | 
				
			||||||
            for y in range(height):
 | 
					            for y in range(height):
 | 
				
			||||||
                for x in range(width):
 | 
					                for x in range(width):
 | 
				
			||||||
                    if frame.getpixel((x, y)):
 | 
					                    if frame.getpixel((x, y)):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,7 +30,7 @@ class Anova : public climate::Climate, public esphome::ble_client::BLEClientNode
 | 
				
			|||||||
  climate::ClimateTraits traits() override {
 | 
					  climate::ClimateTraits traits() override {
 | 
				
			||||||
    auto traits = climate::ClimateTraits();
 | 
					    auto traits = climate::ClimateTraits();
 | 
				
			||||||
    traits.set_supports_current_temperature(true);
 | 
					    traits.set_supports_current_temperature(true);
 | 
				
			||||||
    traits.set_supported_modes({climate::CLIMATE_MODE_OFF, climate::ClimateMode::CLIMATE_MODE_HEAT});
 | 
					    traits.set_supports_heat_mode(true);
 | 
				
			||||||
    traits.set_visual_min_temperature(25.0);
 | 
					    traits.set_visual_min_temperature(25.0);
 | 
				
			||||||
    traits.set_visual_max_temperature(100.0);
 | 
					    traits.set_visual_max_temperature(100.0);
 | 
				
			||||||
    traits.set_visual_temperature_step(0.1);
 | 
					    traits.set_visual_temperature_step(0.1);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -73,46 +73,51 @@ AnovaPacket *AnovaCodec::get_stop_request() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void AnovaCodec::decode(const uint8_t *data, uint16_t length) {
 | 
					void AnovaCodec::decode(const uint8_t *data, uint16_t length) {
 | 
				
			||||||
  char buf[32];
 | 
					  memset(this->buf_, 0, 32);
 | 
				
			||||||
  memset(buf, 0, sizeof(buf));
 | 
					  strncpy(this->buf_, (char *) data, length);
 | 
				
			||||||
  strncpy(buf, (char *) data, std::min<uint16_t>(length, sizeof(buf) - 1));
 | 
					 | 
				
			||||||
  this->has_target_temp_ = this->has_current_temp_ = this->has_unit_ = this->has_running_ = false;
 | 
					  this->has_target_temp_ = this->has_current_temp_ = this->has_unit_ = this->has_running_ = false;
 | 
				
			||||||
  switch (this->current_query_) {
 | 
					  switch (this->current_query_) {
 | 
				
			||||||
    case READ_DEVICE_STATUS: {
 | 
					    case READ_DEVICE_STATUS: {
 | 
				
			||||||
      if (!strncmp(buf, "stopped", 7)) {
 | 
					      if (!strncmp(this->buf_, "stopped", 7)) {
 | 
				
			||||||
        this->has_running_ = true;
 | 
					        this->has_running_ = true;
 | 
				
			||||||
        this->running_ = false;
 | 
					        this->running_ = false;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      if (!strncmp(buf, "running", 7)) {
 | 
					      if (!strncmp(this->buf_, "running", 7)) {
 | 
				
			||||||
        this->has_running_ = true;
 | 
					        this->has_running_ = true;
 | 
				
			||||||
        this->running_ = true;
 | 
					        this->running_ = true;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case START: {
 | 
					    case START: {
 | 
				
			||||||
      if (!strncmp(buf, "start", 5)) {
 | 
					      if (!strncmp(this->buf_, "start", 5)) {
 | 
				
			||||||
        this->has_running_ = true;
 | 
					        this->has_running_ = true;
 | 
				
			||||||
        this->running_ = true;
 | 
					        this->running_ = true;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case STOP: {
 | 
					    case STOP: {
 | 
				
			||||||
      if (!strncmp(buf, "stop", 4)) {
 | 
					      if (!strncmp(this->buf_, "stop", 4)) {
 | 
				
			||||||
        this->has_running_ = true;
 | 
					        this->has_running_ = true;
 | 
				
			||||||
        this->running_ = false;
 | 
					        this->running_ = false;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case READ_TARGET_TEMPERATURE:
 | 
					    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: {
 | 
					    case SET_TARGET_TEMPERATURE: {
 | 
				
			||||||
      this->target_temp_ = parse_number<float>(str_until(buf, '\r')).value_or(0.0f);
 | 
					      this->target_temp_ = strtof(this->buf_, nullptr);
 | 
				
			||||||
      if (this->fahrenheit_)
 | 
					      if (this->fahrenheit_)
 | 
				
			||||||
        this->target_temp_ = ftoc(this->target_temp_);
 | 
					        this->target_temp_ = ftoc(this->target_temp_);
 | 
				
			||||||
      this->has_target_temp_ = true;
 | 
					      this->has_target_temp_ = true;
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case READ_CURRENT_TEMPERATURE: {
 | 
					    case READ_CURRENT_TEMPERATURE: {
 | 
				
			||||||
      this->current_temp_ = parse_number<float>(str_until(buf, '\r')).value_or(0.0f);
 | 
					      this->current_temp_ = strtof(this->buf_, nullptr);
 | 
				
			||||||
      if (this->fahrenheit_)
 | 
					      if (this->fahrenheit_)
 | 
				
			||||||
        this->current_temp_ = ftoc(this->current_temp_);
 | 
					        this->current_temp_ = ftoc(this->current_temp_);
 | 
				
			||||||
      this->has_current_temp_ = true;
 | 
					      this->has_current_temp_ = true;
 | 
				
			||||||
@@ -120,8 +125,8 @@ void AnovaCodec::decode(const uint8_t *data, uint16_t length) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    case SET_UNIT:
 | 
					    case SET_UNIT:
 | 
				
			||||||
    case READ_UNIT: {
 | 
					    case READ_UNIT: {
 | 
				
			||||||
      this->unit_ = buf[0];
 | 
					      this->unit_ = this->buf_[0];
 | 
				
			||||||
      this->fahrenheit_ = buf[0] == 'f';
 | 
					      this->fahrenheit_ = this->buf_[0] == 'f';
 | 
				
			||||||
      this->has_unit_ = true;
 | 
					      this->has_unit_ = true;
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -70,6 +70,7 @@ class AnovaCodec {
 | 
				
			|||||||
  bool has_current_temp_;
 | 
					  bool has_current_temp_;
 | 
				
			||||||
  bool has_unit_;
 | 
					  bool has_unit_;
 | 
				
			||||||
  bool has_running_;
 | 
					  bool has_running_;
 | 
				
			||||||
 | 
					  char buf_[32];
 | 
				
			||||||
  bool fahrenheit_;
 | 
					  bool fahrenheit_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  CurrentQuery current_query_;
 | 
					  CurrentQuery current_query_;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,7 +40,6 @@ service APIConnection {
 | 
				
			|||||||
  rpc climate_command (ClimateCommandRequest) returns (void) {}
 | 
					  rpc climate_command (ClimateCommandRequest) returns (void) {}
 | 
				
			||||||
  rpc number_command (NumberCommandRequest) returns (void) {}
 | 
					  rpc number_command (NumberCommandRequest) returns (void) {}
 | 
				
			||||||
  rpc select_command (SelectCommandRequest) returns (void) {}
 | 
					  rpc select_command (SelectCommandRequest) returns (void) {}
 | 
				
			||||||
  rpc button_command (ButtonCommandRequest) returns (void) {}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -183,8 +182,6 @@ message DeviceInfoResponse {
 | 
				
			|||||||
  // The esphome project details if set
 | 
					  // The esphome project details if set
 | 
				
			||||||
  string project_name = 8;
 | 
					  string project_name = 8;
 | 
				
			||||||
  string project_version = 9;
 | 
					  string project_version = 9;
 | 
				
			||||||
 | 
					 | 
				
			||||||
  uint32 webserver_port = 10;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
message ListEntitiesRequest {
 | 
					message ListEntitiesRequest {
 | 
				
			||||||
@@ -204,14 +201,6 @@ message SubscribeStatesRequest {
 | 
				
			|||||||
  // Empty
 | 
					  // Empty
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ==================== COMMON =====================
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum EntityCategory {
 | 
					 | 
				
			||||||
  ENTITY_CATEGORY_NONE = 0;
 | 
					 | 
				
			||||||
  ENTITY_CATEGORY_CONFIG = 1;
 | 
					 | 
				
			||||||
  ENTITY_CATEGORY_DIAGNOSTIC = 2;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ==================== BINARY SENSOR ====================
 | 
					// ==================== BINARY SENSOR ====================
 | 
				
			||||||
message ListEntitiesBinarySensorResponse {
 | 
					message ListEntitiesBinarySensorResponse {
 | 
				
			||||||
  option (id) = 12;
 | 
					  option (id) = 12;
 | 
				
			||||||
@@ -227,7 +216,6 @@ message ListEntitiesBinarySensorResponse {
 | 
				
			|||||||
  bool is_status_binary_sensor = 6;
 | 
					  bool is_status_binary_sensor = 6;
 | 
				
			||||||
  bool disabled_by_default = 7;
 | 
					  bool disabled_by_default = 7;
 | 
				
			||||||
  string icon = 8;
 | 
					  string icon = 8;
 | 
				
			||||||
  EntityCategory entity_category = 9;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
message BinarySensorStateResponse {
 | 
					message BinarySensorStateResponse {
 | 
				
			||||||
  option (id) = 21;
 | 
					  option (id) = 21;
 | 
				
			||||||
@@ -259,7 +247,6 @@ message ListEntitiesCoverResponse {
 | 
				
			|||||||
  string device_class = 8;
 | 
					  string device_class = 8;
 | 
				
			||||||
  bool disabled_by_default = 9;
 | 
					  bool disabled_by_default = 9;
 | 
				
			||||||
  string icon = 10;
 | 
					  string icon = 10;
 | 
				
			||||||
  EntityCategory entity_category = 11;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum LegacyCoverState {
 | 
					enum LegacyCoverState {
 | 
				
			||||||
@@ -329,7 +316,6 @@ message ListEntitiesFanResponse {
 | 
				
			|||||||
  int32 supported_speed_count = 8;
 | 
					  int32 supported_speed_count = 8;
 | 
				
			||||||
  bool disabled_by_default = 9;
 | 
					  bool disabled_by_default = 9;
 | 
				
			||||||
  string icon = 10;
 | 
					  string icon = 10;
 | 
				
			||||||
  EntityCategory entity_category = 11;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
enum FanSpeed {
 | 
					enum FanSpeed {
 | 
				
			||||||
  FAN_SPEED_LOW = 0;
 | 
					  FAN_SPEED_LOW = 0;
 | 
				
			||||||
@@ -406,7 +392,6 @@ message ListEntitiesLightResponse {
 | 
				
			|||||||
  repeated string effects = 11;
 | 
					  repeated string effects = 11;
 | 
				
			||||||
  bool disabled_by_default = 13;
 | 
					  bool disabled_by_default = 13;
 | 
				
			||||||
  string icon = 14;
 | 
					  string icon = 14;
 | 
				
			||||||
  EntityCategory entity_category = 15;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
message LightStateResponse {
 | 
					message LightStateResponse {
 | 
				
			||||||
  option (id) = 24;
 | 
					  option (id) = 24;
 | 
				
			||||||
@@ -495,7 +480,6 @@ message ListEntitiesSensorResponse {
 | 
				
			|||||||
  // Last reset type removed in 2021.9.0
 | 
					  // Last reset type removed in 2021.9.0
 | 
				
			||||||
  SensorLastResetType legacy_last_reset_type = 11;
 | 
					  SensorLastResetType legacy_last_reset_type = 11;
 | 
				
			||||||
  bool disabled_by_default = 12;
 | 
					  bool disabled_by_default = 12;
 | 
				
			||||||
  EntityCategory entity_category = 13;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
message SensorStateResponse {
 | 
					message SensorStateResponse {
 | 
				
			||||||
  option (id) = 25;
 | 
					  option (id) = 25;
 | 
				
			||||||
@@ -524,7 +508,6 @@ message ListEntitiesSwitchResponse {
 | 
				
			|||||||
  string icon = 5;
 | 
					  string icon = 5;
 | 
				
			||||||
  bool assumed_state = 6;
 | 
					  bool assumed_state = 6;
 | 
				
			||||||
  bool disabled_by_default = 7;
 | 
					  bool disabled_by_default = 7;
 | 
				
			||||||
  EntityCategory entity_category = 8;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
message SwitchStateResponse {
 | 
					message SwitchStateResponse {
 | 
				
			||||||
  option (id) = 26;
 | 
					  option (id) = 26;
 | 
				
			||||||
@@ -558,7 +541,6 @@ message ListEntitiesTextSensorResponse {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  string icon = 5;
 | 
					  string icon = 5;
 | 
				
			||||||
  bool disabled_by_default = 6;
 | 
					  bool disabled_by_default = 6;
 | 
				
			||||||
  EntityCategory entity_category = 7;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
message TextSensorStateResponse {
 | 
					message TextSensorStateResponse {
 | 
				
			||||||
  option (id) = 27;
 | 
					  option (id) = 27;
 | 
				
			||||||
@@ -719,8 +701,6 @@ message ListEntitiesCameraResponse {
 | 
				
			|||||||
  string name = 3;
 | 
					  string name = 3;
 | 
				
			||||||
  string unique_id = 4;
 | 
					  string unique_id = 4;
 | 
				
			||||||
  bool disabled_by_default = 5;
 | 
					  bool disabled_by_default = 5;
 | 
				
			||||||
  string icon = 6;
 | 
					 | 
				
			||||||
  EntityCategory entity_category = 7;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
message CameraImageResponse {
 | 
					message CameraImageResponse {
 | 
				
			||||||
@@ -815,7 +795,6 @@ message ListEntitiesClimateResponse {
 | 
				
			|||||||
  repeated string supported_custom_presets = 17;
 | 
					  repeated string supported_custom_presets = 17;
 | 
				
			||||||
  bool disabled_by_default = 18;
 | 
					  bool disabled_by_default = 18;
 | 
				
			||||||
  string icon = 19;
 | 
					  string icon = 19;
 | 
				
			||||||
  EntityCategory entity_category = 20;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
message ClimateStateResponse {
 | 
					message ClimateStateResponse {
 | 
				
			||||||
  option (id) = 47;
 | 
					  option (id) = 47;
 | 
				
			||||||
@@ -869,11 +848,6 @@ message ClimateCommandRequest {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ==================== NUMBER ====================
 | 
					// ==================== NUMBER ====================
 | 
				
			||||||
enum NumberMode {
 | 
					 | 
				
			||||||
  NUMBER_MODE_AUTO = 0;
 | 
					 | 
				
			||||||
  NUMBER_MODE_BOX = 1;
 | 
					 | 
				
			||||||
  NUMBER_MODE_SLIDER = 2;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
message ListEntitiesNumberResponse {
 | 
					message ListEntitiesNumberResponse {
 | 
				
			||||||
  option (id) = 49;
 | 
					  option (id) = 49;
 | 
				
			||||||
  option (source) = SOURCE_SERVER;
 | 
					  option (source) = SOURCE_SERVER;
 | 
				
			||||||
@@ -889,9 +863,6 @@ message ListEntitiesNumberResponse {
 | 
				
			|||||||
  float max_value = 7;
 | 
					  float max_value = 7;
 | 
				
			||||||
  float step = 8;
 | 
					  float step = 8;
 | 
				
			||||||
  bool disabled_by_default = 9;
 | 
					  bool disabled_by_default = 9;
 | 
				
			||||||
  EntityCategory entity_category = 10;
 | 
					 | 
				
			||||||
  string unit_of_measurement = 11;
 | 
					 | 
				
			||||||
  NumberMode mode = 12;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
message NumberStateResponse {
 | 
					message NumberStateResponse {
 | 
				
			||||||
  option (id) = 50;
 | 
					  option (id) = 50;
 | 
				
			||||||
@@ -929,7 +900,6 @@ message ListEntitiesSelectResponse {
 | 
				
			|||||||
  string icon = 5;
 | 
					  string icon = 5;
 | 
				
			||||||
  repeated string options = 6;
 | 
					  repeated string options = 6;
 | 
				
			||||||
  bool disabled_by_default = 7;
 | 
					  bool disabled_by_default = 7;
 | 
				
			||||||
  EntityCategory entity_category = 8;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
message SelectStateResponse {
 | 
					message SelectStateResponse {
 | 
				
			||||||
  option (id) = 53;
 | 
					  option (id) = 53;
 | 
				
			||||||
@@ -952,28 +922,3 @@ message SelectCommandRequest {
 | 
				
			|||||||
  fixed32 key = 1;
 | 
					  fixed32 key = 1;
 | 
				
			||||||
  string state = 2;
 | 
					  string state = 2;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
// ==================== BUTTON ====================
 | 
					 | 
				
			||||||
message ListEntitiesButtonResponse {
 | 
					 | 
				
			||||||
  option (id) = 61;
 | 
					 | 
				
			||||||
  option (source) = SOURCE_SERVER;
 | 
					 | 
				
			||||||
  option (ifdef) = "USE_BUTTON";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  string object_id = 1;
 | 
					 | 
				
			||||||
  fixed32 key = 2;
 | 
					 | 
				
			||||||
  string name = 3;
 | 
					 | 
				
			||||||
  string unique_id = 4;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  string icon = 5;
 | 
					 | 
				
			||||||
  bool disabled_by_default = 6;
 | 
					 | 
				
			||||||
  EntityCategory entity_category = 7;
 | 
					 | 
				
			||||||
  string device_class = 8;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
message ButtonCommandRequest {
 | 
					 | 
				
			||||||
  option (id) = 62;
 | 
					 | 
				
			||||||
  option (source) = SOURCE_CLIENT;
 | 
					 | 
				
			||||||
  option (ifdef) = "USE_BUTTON";
 | 
					 | 
				
			||||||
  option (no_delay) = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  fixed32 key = 1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -132,7 +132,7 @@ void APIConnection::loop() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  if (state_subs_at_ != -1) {
 | 
					  if (state_subs_at_ != -1) {
 | 
				
			||||||
    const auto &subs = this->parent_->get_state_subs();
 | 
					    const auto &subs = this->parent_->get_state_subs();
 | 
				
			||||||
    if (state_subs_at_ >= (int) subs.size()) {
 | 
					    if (state_subs_at_ >= subs.size()) {
 | 
				
			||||||
      state_subs_at_ = -1;
 | 
					      state_subs_at_ = -1;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      auto &it = subs[state_subs_at_];
 | 
					      auto &it = subs[state_subs_at_];
 | 
				
			||||||
@@ -184,7 +184,6 @@ bool APIConnection::send_binary_sensor_info(binary_sensor::BinarySensor *binary_
 | 
				
			|||||||
  msg.is_status_binary_sensor = binary_sensor->is_status_binary_sensor();
 | 
					  msg.is_status_binary_sensor = binary_sensor->is_status_binary_sensor();
 | 
				
			||||||
  msg.disabled_by_default = binary_sensor->is_disabled_by_default();
 | 
					  msg.disabled_by_default = binary_sensor->is_disabled_by_default();
 | 
				
			||||||
  msg.icon = binary_sensor->get_icon();
 | 
					  msg.icon = binary_sensor->get_icon();
 | 
				
			||||||
  msg.entity_category = static_cast<enums::EntityCategory>(binary_sensor->get_entity_category());
 | 
					 | 
				
			||||||
  return this->send_list_entities_binary_sensor_response(msg);
 | 
					  return this->send_list_entities_binary_sensor_response(msg);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -218,7 +217,6 @@ bool APIConnection::send_cover_info(cover::Cover *cover) {
 | 
				
			|||||||
  msg.device_class = cover->get_device_class();
 | 
					  msg.device_class = cover->get_device_class();
 | 
				
			||||||
  msg.disabled_by_default = cover->is_disabled_by_default();
 | 
					  msg.disabled_by_default = cover->is_disabled_by_default();
 | 
				
			||||||
  msg.icon = cover->get_icon();
 | 
					  msg.icon = cover->get_icon();
 | 
				
			||||||
  msg.entity_category = static_cast<enums::EntityCategory>(cover->get_entity_category());
 | 
					 | 
				
			||||||
  return this->send_list_entities_cover_response(msg);
 | 
					  return this->send_list_entities_cover_response(msg);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void APIConnection::cover_command(const CoverCommandRequest &msg) {
 | 
					void APIConnection::cover_command(const CoverCommandRequest &msg) {
 | 
				
			||||||
@@ -285,7 +283,6 @@ bool APIConnection::send_fan_info(fan::FanState *fan) {
 | 
				
			|||||||
  msg.supported_speed_count = traits.supported_speed_count();
 | 
					  msg.supported_speed_count = traits.supported_speed_count();
 | 
				
			||||||
  msg.disabled_by_default = fan->is_disabled_by_default();
 | 
					  msg.disabled_by_default = fan->is_disabled_by_default();
 | 
				
			||||||
  msg.icon = fan->get_icon();
 | 
					  msg.icon = fan->get_icon();
 | 
				
			||||||
  msg.entity_category = static_cast<enums::EntityCategory>(fan->get_entity_category());
 | 
					 | 
				
			||||||
  return this->send_list_entities_fan_response(msg);
 | 
					  return this->send_list_entities_fan_response(msg);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void APIConnection::fan_command(const FanCommandRequest &msg) {
 | 
					void APIConnection::fan_command(const FanCommandRequest &msg) {
 | 
				
			||||||
@@ -349,7 +346,6 @@ bool APIConnection::send_light_info(light::LightState *light) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  msg.disabled_by_default = light->is_disabled_by_default();
 | 
					  msg.disabled_by_default = light->is_disabled_by_default();
 | 
				
			||||||
  msg.icon = light->get_icon();
 | 
					  msg.icon = light->get_icon();
 | 
				
			||||||
  msg.entity_category = static_cast<enums::EntityCategory>(light->get_entity_category());
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (auto mode : traits.get_supported_color_modes())
 | 
					  for (auto mode : traits.get_supported_color_modes())
 | 
				
			||||||
    msg.supported_color_modes.push_back(static_cast<enums::ColorMode>(mode));
 | 
					    msg.supported_color_modes.push_back(static_cast<enums::ColorMode>(mode));
 | 
				
			||||||
@@ -436,7 +432,7 @@ bool APIConnection::send_sensor_info(sensor::Sensor *sensor) {
 | 
				
			|||||||
  msg.device_class = sensor->get_device_class();
 | 
					  msg.device_class = sensor->get_device_class();
 | 
				
			||||||
  msg.state_class = static_cast<enums::SensorStateClass>(sensor->get_state_class());
 | 
					  msg.state_class = static_cast<enums::SensorStateClass>(sensor->get_state_class());
 | 
				
			||||||
  msg.disabled_by_default = sensor->is_disabled_by_default();
 | 
					  msg.disabled_by_default = sensor->is_disabled_by_default();
 | 
				
			||||||
  msg.entity_category = static_cast<enums::EntityCategory>(sensor->get_entity_category());
 | 
					
 | 
				
			||||||
  return this->send_list_entities_sensor_response(msg);
 | 
					  return this->send_list_entities_sensor_response(msg);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -460,7 +456,6 @@ bool APIConnection::send_switch_info(switch_::Switch *a_switch) {
 | 
				
			|||||||
  msg.icon = a_switch->get_icon();
 | 
					  msg.icon = a_switch->get_icon();
 | 
				
			||||||
  msg.assumed_state = a_switch->assumed_state();
 | 
					  msg.assumed_state = a_switch->assumed_state();
 | 
				
			||||||
  msg.disabled_by_default = a_switch->is_disabled_by_default();
 | 
					  msg.disabled_by_default = a_switch->is_disabled_by_default();
 | 
				
			||||||
  msg.entity_category = static_cast<enums::EntityCategory>(a_switch->get_entity_category());
 | 
					 | 
				
			||||||
  return this->send_list_entities_switch_response(msg);
 | 
					  return this->send_list_entities_switch_response(msg);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void APIConnection::switch_command(const SwitchCommandRequest &msg) {
 | 
					void APIConnection::switch_command(const SwitchCommandRequest &msg) {
 | 
				
			||||||
@@ -496,7 +491,6 @@ bool APIConnection::send_text_sensor_info(text_sensor::TextSensor *text_sensor)
 | 
				
			|||||||
    msg.unique_id = get_default_unique_id("text_sensor", text_sensor);
 | 
					    msg.unique_id = get_default_unique_id("text_sensor", text_sensor);
 | 
				
			||||||
  msg.icon = text_sensor->get_icon();
 | 
					  msg.icon = text_sensor->get_icon();
 | 
				
			||||||
  msg.disabled_by_default = text_sensor->is_disabled_by_default();
 | 
					  msg.disabled_by_default = text_sensor->is_disabled_by_default();
 | 
				
			||||||
  msg.entity_category = static_cast<enums::EntityCategory>(text_sensor->get_entity_category());
 | 
					 | 
				
			||||||
  return this->send_list_entities_text_sensor_response(msg);
 | 
					  return this->send_list_entities_text_sensor_response(msg);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -543,7 +537,6 @@ bool APIConnection::send_climate_info(climate::Climate *climate) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  msg.disabled_by_default = climate->is_disabled_by_default();
 | 
					  msg.disabled_by_default = climate->is_disabled_by_default();
 | 
				
			||||||
  msg.icon = climate->get_icon();
 | 
					  msg.icon = climate->get_icon();
 | 
				
			||||||
  msg.entity_category = static_cast<enums::EntityCategory>(climate->get_entity_category());
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  msg.supports_current_temperature = traits.get_supports_current_temperature();
 | 
					  msg.supports_current_temperature = traits.get_supports_current_temperature();
 | 
				
			||||||
  msg.supports_two_point_target_temperature = traits.get_supports_two_point_target_temperature();
 | 
					  msg.supports_two_point_target_temperature = traits.get_supports_two_point_target_temperature();
 | 
				
			||||||
@@ -618,9 +611,6 @@ bool APIConnection::send_number_info(number::Number *number) {
 | 
				
			|||||||
  msg.unique_id = get_default_unique_id("number", number);
 | 
					  msg.unique_id = get_default_unique_id("number", number);
 | 
				
			||||||
  msg.icon = number->get_icon();
 | 
					  msg.icon = number->get_icon();
 | 
				
			||||||
  msg.disabled_by_default = number->is_disabled_by_default();
 | 
					  msg.disabled_by_default = number->is_disabled_by_default();
 | 
				
			||||||
  msg.entity_category = static_cast<enums::EntityCategory>(number->get_entity_category());
 | 
					 | 
				
			||||||
  msg.unit_of_measurement = number->traits.get_unit_of_measurement();
 | 
					 | 
				
			||||||
  msg.mode = static_cast<enums::NumberMode>(number->traits.get_mode());
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  msg.min_value = number->traits.get_min_value();
 | 
					  msg.min_value = number->traits.get_min_value();
 | 
				
			||||||
  msg.max_value = number->traits.get_max_value();
 | 
					  msg.max_value = number->traits.get_max_value();
 | 
				
			||||||
@@ -658,7 +648,6 @@ bool APIConnection::send_select_info(select::Select *select) {
 | 
				
			|||||||
  msg.unique_id = get_default_unique_id("select", select);
 | 
					  msg.unique_id = get_default_unique_id("select", select);
 | 
				
			||||||
  msg.icon = select->get_icon();
 | 
					  msg.icon = select->get_icon();
 | 
				
			||||||
  msg.disabled_by_default = select->is_disabled_by_default();
 | 
					  msg.disabled_by_default = select->is_disabled_by_default();
 | 
				
			||||||
  msg.entity_category = static_cast<enums::EntityCategory>(select->get_entity_category());
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (const auto &option : select->traits.get_options())
 | 
					  for (const auto &option : select->traits.get_options())
 | 
				
			||||||
    msg.options.push_back(option);
 | 
					    msg.options.push_back(option);
 | 
				
			||||||
@@ -676,28 +665,6 @@ void APIConnection::select_command(const SelectCommandRequest &msg) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef USE_BUTTON
 | 
					 | 
				
			||||||
bool APIConnection::send_button_info(button::Button *button) {
 | 
					 | 
				
			||||||
  ListEntitiesButtonResponse msg;
 | 
					 | 
				
			||||||
  msg.key = button->get_object_id_hash();
 | 
					 | 
				
			||||||
  msg.object_id = button->get_object_id();
 | 
					 | 
				
			||||||
  msg.name = button->get_name();
 | 
					 | 
				
			||||||
  msg.unique_id = get_default_unique_id("button", button);
 | 
					 | 
				
			||||||
  msg.icon = button->get_icon();
 | 
					 | 
				
			||||||
  msg.disabled_by_default = button->is_disabled_by_default();
 | 
					 | 
				
			||||||
  msg.entity_category = static_cast<enums::EntityCategory>(button->get_entity_category());
 | 
					 | 
				
			||||||
  msg.device_class = button->get_device_class();
 | 
					 | 
				
			||||||
  return this->send_list_entities_button_response(msg);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
void APIConnection::button_command(const ButtonCommandRequest &msg) {
 | 
					 | 
				
			||||||
  button::Button *button = App.get_button_by_key(msg.key);
 | 
					 | 
				
			||||||
  if (button == nullptr)
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  button->press();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef USE_ESP32_CAMERA
 | 
					#ifdef USE_ESP32_CAMERA
 | 
				
			||||||
void APIConnection::send_camera_state(std::shared_ptr<esp32_camera::CameraImage> image) {
 | 
					void APIConnection::send_camera_state(std::shared_ptr<esp32_camera::CameraImage> image) {
 | 
				
			||||||
  if (!this->state_subscription_)
 | 
					  if (!this->state_subscription_)
 | 
				
			||||||
@@ -713,8 +680,6 @@ bool APIConnection::send_camera_info(esp32_camera::ESP32Camera *camera) {
 | 
				
			|||||||
  msg.name = camera->get_name();
 | 
					  msg.name = camera->get_name();
 | 
				
			||||||
  msg.unique_id = get_default_unique_id("camera", camera);
 | 
					  msg.unique_id = get_default_unique_id("camera", camera);
 | 
				
			||||||
  msg.disabled_by_default = camera->is_disabled_by_default();
 | 
					  msg.disabled_by_default = camera->is_disabled_by_default();
 | 
				
			||||||
  msg.icon = camera->get_icon();
 | 
					 | 
				
			||||||
  msg.entity_category = static_cast<enums::EntityCategory>(camera->get_entity_category());
 | 
					 | 
				
			||||||
  return this->send_list_entities_camera_response(msg);
 | 
					  return this->send_list_entities_camera_response(msg);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void APIConnection::camera_image(const CameraImageRequest &msg) {
 | 
					void APIConnection::camera_image(const CameraImageRequest &msg) {
 | 
				
			||||||
@@ -793,9 +758,6 @@ DeviceInfoResponse APIConnection::device_info(const DeviceInfoRequest &msg) {
 | 
				
			|||||||
#ifdef ESPHOME_PROJECT_NAME
 | 
					#ifdef ESPHOME_PROJECT_NAME
 | 
				
			||||||
  resp.project_name = ESPHOME_PROJECT_NAME;
 | 
					  resp.project_name = ESPHOME_PROJECT_NAME;
 | 
				
			||||||
  resp.project_version = ESPHOME_PROJECT_VERSION;
 | 
					  resp.project_version = ESPHOME_PROJECT_VERSION;
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#ifdef USE_WEBSERVER
 | 
					 | 
				
			||||||
  resp.webserver_port = WEBSERVER_PORT;
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
  return resp;
 | 
					  return resp;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -73,10 +73,6 @@ class APIConnection : public APIServerConnection {
 | 
				
			|||||||
  bool send_select_state(select::Select *select, std::string state);
 | 
					  bool send_select_state(select::Select *select, std::string state);
 | 
				
			||||||
  bool send_select_info(select::Select *select);
 | 
					  bool send_select_info(select::Select *select);
 | 
				
			||||||
  void select_command(const SelectCommandRequest &msg) override;
 | 
					  void select_command(const SelectCommandRequest &msg) override;
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#ifdef USE_BUTTON
 | 
					 | 
				
			||||||
  bool send_button_info(button::Button *button);
 | 
					 | 
				
			||||||
  void button_command(const ButtonCommandRequest &msg) override;
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
  bool send_log_message(int level, const char *tag, const char *line);
 | 
					  bool send_log_message(int level, const char *tag, const char *line);
 | 
				
			||||||
  void send_homeassistant_service_call(const HomeassistantServiceResponse &call) {
 | 
					  void send_homeassistant_service_call(const HomeassistantServiceResponse &call) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -174,6 +174,9 @@ APIError APINoiseFrameHelper::loop() {
 | 
				
			|||||||
 * errno API_ERROR_HANDSHAKE_PACKET_LEN: Packet too big for this phase.
 | 
					 * errno API_ERROR_HANDSHAKE_PACKET_LEN: Packet too big for this phase.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
APIError APINoiseFrameHelper::try_read_frame_(ParsedFrame *frame) {
 | 
					APIError APINoiseFrameHelper::try_read_frame_(ParsedFrame *frame) {
 | 
				
			||||||
 | 
					  int err;
 | 
				
			||||||
 | 
					  APIError aerr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (frame == nullptr) {
 | 
					  if (frame == nullptr) {
 | 
				
			||||||
    HELPER_LOG("Bad argument for try_read_frame_");
 | 
					    HELPER_LOG("Bad argument for try_read_frame_");
 | 
				
			||||||
    return APIError::BAD_ARG;
 | 
					    return APIError::BAD_ARG;
 | 
				
			||||||
@@ -197,7 +200,7 @@ APIError APINoiseFrameHelper::try_read_frame_(ParsedFrame *frame) {
 | 
				
			|||||||
      return APIError::CONNECTION_CLOSED;
 | 
					      return APIError::CONNECTION_CLOSED;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    rx_header_buf_len_ += received;
 | 
					    rx_header_buf_len_ += received;
 | 
				
			||||||
    if ((size_t) received != to_read) {
 | 
					    if (received != to_read) {
 | 
				
			||||||
      // not a full read
 | 
					      // not a full read
 | 
				
			||||||
      return APIError::WOULD_BLOCK;
 | 
					      return APIError::WOULD_BLOCK;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -244,7 +247,7 @@ APIError APINoiseFrameHelper::try_read_frame_(ParsedFrame *frame) {
 | 
				
			|||||||
      return APIError::CONNECTION_CLOSED;
 | 
					      return APIError::CONNECTION_CLOSED;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    rx_buf_len_ += received;
 | 
					    rx_buf_len_ += received;
 | 
				
			||||||
    if ((size_t) received != to_read) {
 | 
					    if (received != to_read) {
 | 
				
			||||||
      // not all read
 | 
					      // not all read
 | 
				
			||||||
      return APIError::WOULD_BLOCK;
 | 
					      return APIError::WOULD_BLOCK;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -252,7 +255,7 @@ APIError APINoiseFrameHelper::try_read_frame_(ParsedFrame *frame) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // uncomment for even more debugging
 | 
					  // uncomment for even more debugging
 | 
				
			||||||
#ifdef HELPER_LOG_PACKETS
 | 
					#ifdef HELPER_LOG_PACKETS
 | 
				
			||||||
  ESP_LOGVV(TAG, "Received frame: %s", format_hex_pretty(rx_buf_).c_str());
 | 
					  ESP_LOGVV(TAG, "Received frame: %s", hexencode(rx_buf_).c_str());
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
  frame->msg = std::move(rx_buf_);
 | 
					  frame->msg = std::move(rx_buf_);
 | 
				
			||||||
  // consume msg
 | 
					  // consume msg
 | 
				
			||||||
@@ -541,13 +544,13 @@ APIError APINoiseFrameHelper::try_send_tx_buf_() {
 | 
				
			|||||||
APIError APINoiseFrameHelper::write_raw_(const struct iovec *iov, int iovcnt) {
 | 
					APIError APINoiseFrameHelper::write_raw_(const struct iovec *iov, int iovcnt) {
 | 
				
			||||||
  if (iovcnt == 0)
 | 
					  if (iovcnt == 0)
 | 
				
			||||||
    return APIError::OK;
 | 
					    return APIError::OK;
 | 
				
			||||||
 | 
					  int err;
 | 
				
			||||||
  APIError aerr;
 | 
					  APIError aerr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  size_t total_write_len = 0;
 | 
					  size_t total_write_len = 0;
 | 
				
			||||||
  for (int i = 0; i < iovcnt; i++) {
 | 
					  for (int i = 0; i < iovcnt; i++) {
 | 
				
			||||||
#ifdef HELPER_LOG_PACKETS
 | 
					#ifdef HELPER_LOG_PACKETS
 | 
				
			||||||
    ESP_LOGVV(TAG, "Sending raw: %s",
 | 
					    ESP_LOGVV(TAG, "Sending raw: %s", hexencode(reinterpret_cast<uint8_t *>(iov[i].iov_base), iov[i].iov_len).c_str());
 | 
				
			||||||
              format_hex_pretty(reinterpret_cast<uint8_t *>(iov[i].iov_base), iov[i].iov_len).c_str());
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    total_write_len += iov[i].iov_len;
 | 
					    total_write_len += iov[i].iov_len;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -581,7 +584,7 @@ APIError APINoiseFrameHelper::write_raw_(const struct iovec *iov, int iovcnt) {
 | 
				
			|||||||
    state_ = State::FAILED;
 | 
					    state_ = State::FAILED;
 | 
				
			||||||
    HELPER_LOG("Socket write failed with errno %d", errno);
 | 
					    HELPER_LOG("Socket write failed with errno %d", errno);
 | 
				
			||||||
    return APIError::SOCKET_WRITE_FAILED;
 | 
					    return APIError::SOCKET_WRITE_FAILED;
 | 
				
			||||||
  } else if ((size_t) sent != total_write_len) {
 | 
					  } else if (sent != total_write_len) {
 | 
				
			||||||
    // partially sent, add end to tx_buf
 | 
					    // partially sent, add end to tx_buf
 | 
				
			||||||
    size_t to_consume = sent;
 | 
					    size_t to_consume = sent;
 | 
				
			||||||
    for (int i = 0; i < iovcnt; i++) {
 | 
					    for (int i = 0; i < iovcnt; i++) {
 | 
				
			||||||
@@ -775,6 +778,9 @@ APIError APIPlaintextFrameHelper::loop() {
 | 
				
			|||||||
 * error API_ERROR_BAD_INDICATOR: Bad indicator byte at start of frame.
 | 
					 * error API_ERROR_BAD_INDICATOR: Bad indicator byte at start of frame.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
APIError APIPlaintextFrameHelper::try_read_frame_(ParsedFrame *frame) {
 | 
					APIError APIPlaintextFrameHelper::try_read_frame_(ParsedFrame *frame) {
 | 
				
			||||||
 | 
					  int err;
 | 
				
			||||||
 | 
					  APIError aerr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (frame == nullptr) {
 | 
					  if (frame == nullptr) {
 | 
				
			||||||
    HELPER_LOG("Bad argument for try_read_frame_");
 | 
					    HELPER_LOG("Bad argument for try_read_frame_");
 | 
				
			||||||
    return APIError::BAD_ARG;
 | 
					    return APIError::BAD_ARG;
 | 
				
			||||||
@@ -848,7 +854,7 @@ APIError APIPlaintextFrameHelper::try_read_frame_(ParsedFrame *frame) {
 | 
				
			|||||||
      return APIError::CONNECTION_CLOSED;
 | 
					      return APIError::CONNECTION_CLOSED;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    rx_buf_len_ += received;
 | 
					    rx_buf_len_ += received;
 | 
				
			||||||
    if ((size_t) received != to_read) {
 | 
					    if (received != to_read) {
 | 
				
			||||||
      // not all read
 | 
					      // not all read
 | 
				
			||||||
      return APIError::WOULD_BLOCK;
 | 
					      return APIError::WOULD_BLOCK;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -856,7 +862,7 @@ APIError APIPlaintextFrameHelper::try_read_frame_(ParsedFrame *frame) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // uncomment for even more debugging
 | 
					  // uncomment for even more debugging
 | 
				
			||||||
#ifdef HELPER_LOG_PACKETS
 | 
					#ifdef HELPER_LOG_PACKETS
 | 
				
			||||||
  ESP_LOGVV(TAG, "Received frame: %s", format_hex_pretty(rx_buf_).c_str());
 | 
					  ESP_LOGVV(TAG, "Received frame: %s", hexencode(rx_buf_).c_str());
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
  frame->msg = std::move(rx_buf_);
 | 
					  frame->msg = std::move(rx_buf_);
 | 
				
			||||||
  // consume msg
 | 
					  // consume msg
 | 
				
			||||||
@@ -868,6 +874,7 @@ APIError APIPlaintextFrameHelper::try_read_frame_(ParsedFrame *frame) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
APIError APIPlaintextFrameHelper::read_packet(ReadPacketBuffer *buffer) {
 | 
					APIError APIPlaintextFrameHelper::read_packet(ReadPacketBuffer *buffer) {
 | 
				
			||||||
 | 
					  int err;
 | 
				
			||||||
  APIError aerr;
 | 
					  APIError aerr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (state_ != State::DATA) {
 | 
					  if (state_ != State::DATA) {
 | 
				
			||||||
@@ -887,6 +894,9 @@ APIError APIPlaintextFrameHelper::read_packet(ReadPacketBuffer *buffer) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
bool APIPlaintextFrameHelper::can_write_without_blocking() { return state_ == State::DATA && tx_buf_.empty(); }
 | 
					bool APIPlaintextFrameHelper::can_write_without_blocking() { return state_ == State::DATA && tx_buf_.empty(); }
 | 
				
			||||||
APIError APIPlaintextFrameHelper::write_packet(uint16_t type, const uint8_t *payload, size_t payload_len) {
 | 
					APIError APIPlaintextFrameHelper::write_packet(uint16_t type, const uint8_t *payload, size_t payload_len) {
 | 
				
			||||||
 | 
					  int err;
 | 
				
			||||||
 | 
					  APIError aerr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (state_ != State::DATA) {
 | 
					  if (state_ != State::DATA) {
 | 
				
			||||||
    return APIError::BAD_STATE;
 | 
					    return APIError::BAD_STATE;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -930,13 +940,13 @@ APIError APIPlaintextFrameHelper::try_send_tx_buf_() {
 | 
				
			|||||||
APIError APIPlaintextFrameHelper::write_raw_(const struct iovec *iov, int iovcnt) {
 | 
					APIError APIPlaintextFrameHelper::write_raw_(const struct iovec *iov, int iovcnt) {
 | 
				
			||||||
  if (iovcnt == 0)
 | 
					  if (iovcnt == 0)
 | 
				
			||||||
    return APIError::OK;
 | 
					    return APIError::OK;
 | 
				
			||||||
 | 
					  int err;
 | 
				
			||||||
  APIError aerr;
 | 
					  APIError aerr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  size_t total_write_len = 0;
 | 
					  size_t total_write_len = 0;
 | 
				
			||||||
  for (int i = 0; i < iovcnt; i++) {
 | 
					  for (int i = 0; i < iovcnt; i++) {
 | 
				
			||||||
#ifdef HELPER_LOG_PACKETS
 | 
					#ifdef HELPER_LOG_PACKETS
 | 
				
			||||||
    ESP_LOGVV(TAG, "Sending raw: %s",
 | 
					    ESP_LOGVV(TAG, "Sending raw: %s", hexencode(reinterpret_cast<uint8_t *>(iov[i].iov_base), iov[i].iov_len).c_str());
 | 
				
			||||||
              format_hex_pretty(reinterpret_cast<uint8_t *>(iov[i].iov_base), iov[i].iov_len).c_str());
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    total_write_len += iov[i].iov_len;
 | 
					    total_write_len += iov[i].iov_len;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -970,7 +980,7 @@ APIError APIPlaintextFrameHelper::write_raw_(const struct iovec *iov, int iovcnt
 | 
				
			|||||||
    state_ = State::FAILED;
 | 
					    state_ = State::FAILED;
 | 
				
			||||||
    HELPER_LOG("Socket write failed with errno %d", errno);
 | 
					    HELPER_LOG("Socket write failed with errno %d", errno);
 | 
				
			||||||
    return APIError::SOCKET_WRITE_FAILED;
 | 
					    return APIError::SOCKET_WRITE_FAILED;
 | 
				
			||||||
  } else if ((size_t) sent != total_write_len) {
 | 
					  } else if (sent != total_write_len) {
 | 
				
			||||||
    // partially sent, add end to tx_buf
 | 
					    // partially sent, add end to tx_buf
 | 
				
			||||||
    size_t to_consume = sent;
 | 
					    size_t to_consume = sent;
 | 
				
			||||||
    for (int i = 0; i < iovcnt; i++) {
 | 
					    for (int i = 0; i < iovcnt; i++) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,18 +6,6 @@
 | 
				
			|||||||
namespace esphome {
 | 
					namespace esphome {
 | 
				
			||||||
namespace api {
 | 
					namespace api {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template<> const char *proto_enum_to_string<enums::EntityCategory>(enums::EntityCategory value) {
 | 
					 | 
				
			||||||
  switch (value) {
 | 
					 | 
				
			||||||
    case enums::ENTITY_CATEGORY_NONE:
 | 
					 | 
				
			||||||
      return "ENTITY_CATEGORY_NONE";
 | 
					 | 
				
			||||||
    case enums::ENTITY_CATEGORY_CONFIG:
 | 
					 | 
				
			||||||
      return "ENTITY_CATEGORY_CONFIG";
 | 
					 | 
				
			||||||
    case enums::ENTITY_CATEGORY_DIAGNOSTIC:
 | 
					 | 
				
			||||||
      return "ENTITY_CATEGORY_DIAGNOSTIC";
 | 
					 | 
				
			||||||
    default:
 | 
					 | 
				
			||||||
      return "UNKNOWN";
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
template<> const char *proto_enum_to_string<enums::LegacyCoverState>(enums::LegacyCoverState value) {
 | 
					template<> const char *proto_enum_to_string<enums::LegacyCoverState>(enums::LegacyCoverState value) {
 | 
				
			||||||
  switch (value) {
 | 
					  switch (value) {
 | 
				
			||||||
    case enums::LEGACY_COVER_STATE_OPEN:
 | 
					    case enums::LEGACY_COVER_STATE_OPEN:
 | 
				
			||||||
@@ -266,18 +254,6 @@ template<> const char *proto_enum_to_string<enums::ClimatePreset>(enums::Climate
 | 
				
			|||||||
      return "UNKNOWN";
 | 
					      return "UNKNOWN";
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
template<> const char *proto_enum_to_string<enums::NumberMode>(enums::NumberMode value) {
 | 
					 | 
				
			||||||
  switch (value) {
 | 
					 | 
				
			||||||
    case enums::NUMBER_MODE_AUTO:
 | 
					 | 
				
			||||||
      return "NUMBER_MODE_AUTO";
 | 
					 | 
				
			||||||
    case enums::NUMBER_MODE_BOX:
 | 
					 | 
				
			||||||
      return "NUMBER_MODE_BOX";
 | 
					 | 
				
			||||||
    case enums::NUMBER_MODE_SLIDER:
 | 
					 | 
				
			||||||
      return "NUMBER_MODE_SLIDER";
 | 
					 | 
				
			||||||
    default:
 | 
					 | 
				
			||||||
      return "UNKNOWN";
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
bool HelloRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) {
 | 
					bool HelloRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) {
 | 
				
			||||||
  switch (field_id) {
 | 
					  switch (field_id) {
 | 
				
			||||||
    case 1: {
 | 
					    case 1: {
 | 
				
			||||||
@@ -291,7 +267,7 @@ bool HelloRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value)
 | 
				
			|||||||
void HelloRequest::encode(ProtoWriteBuffer buffer) const { buffer.encode_string(1, this->client_info); }
 | 
					void HelloRequest::encode(ProtoWriteBuffer buffer) const { buffer.encode_string(1, this->client_info); }
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void HelloRequest::dump_to(std::string &out) const {
 | 
					void HelloRequest::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("HelloRequest {\n");
 | 
					  out.append("HelloRequest {\n");
 | 
				
			||||||
  out.append("  client_info: ");
 | 
					  out.append("  client_info: ");
 | 
				
			||||||
  out.append("'").append(this->client_info).append("'");
 | 
					  out.append("'").append(this->client_info).append("'");
 | 
				
			||||||
@@ -330,7 +306,7 @@ void HelloResponse::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void HelloResponse::dump_to(std::string &out) const {
 | 
					void HelloResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("HelloResponse {\n");
 | 
					  out.append("HelloResponse {\n");
 | 
				
			||||||
  out.append("  api_version_major: ");
 | 
					  out.append("  api_version_major: ");
 | 
				
			||||||
  sprintf(buffer, "%u", this->api_version_major);
 | 
					  sprintf(buffer, "%u", this->api_version_major);
 | 
				
			||||||
@@ -361,7 +337,7 @@ bool ConnectRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value
 | 
				
			|||||||
void ConnectRequest::encode(ProtoWriteBuffer buffer) const { buffer.encode_string(1, this->password); }
 | 
					void ConnectRequest::encode(ProtoWriteBuffer buffer) const { buffer.encode_string(1, this->password); }
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void ConnectRequest::dump_to(std::string &out) const {
 | 
					void ConnectRequest::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("ConnectRequest {\n");
 | 
					  out.append("ConnectRequest {\n");
 | 
				
			||||||
  out.append("  password: ");
 | 
					  out.append("  password: ");
 | 
				
			||||||
  out.append("'").append(this->password).append("'");
 | 
					  out.append("'").append(this->password).append("'");
 | 
				
			||||||
@@ -382,7 +358,7 @@ bool ConnectResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
 | 
				
			|||||||
void ConnectResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_bool(1, this->invalid_password); }
 | 
					void ConnectResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_bool(1, this->invalid_password); }
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void ConnectResponse::dump_to(std::string &out) const {
 | 
					void ConnectResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("ConnectResponse {\n");
 | 
					  out.append("ConnectResponse {\n");
 | 
				
			||||||
  out.append("  invalid_password: ");
 | 
					  out.append("  invalid_password: ");
 | 
				
			||||||
  out.append(YESNO(this->invalid_password));
 | 
					  out.append(YESNO(this->invalid_password));
 | 
				
			||||||
@@ -420,10 +396,6 @@ bool DeviceInfoResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
 | 
				
			|||||||
      this->has_deep_sleep = value.as_bool();
 | 
					      this->has_deep_sleep = value.as_bool();
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case 10: {
 | 
					 | 
				
			||||||
      this->webserver_port = value.as_uint32();
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -472,11 +444,10 @@ void DeviceInfoResponse::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
  buffer.encode_bool(7, this->has_deep_sleep);
 | 
					  buffer.encode_bool(7, this->has_deep_sleep);
 | 
				
			||||||
  buffer.encode_string(8, this->project_name);
 | 
					  buffer.encode_string(8, this->project_name);
 | 
				
			||||||
  buffer.encode_string(9, this->project_version);
 | 
					  buffer.encode_string(9, this->project_version);
 | 
				
			||||||
  buffer.encode_uint32(10, this->webserver_port);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void DeviceInfoResponse::dump_to(std::string &out) const {
 | 
					void DeviceInfoResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("DeviceInfoResponse {\n");
 | 
					  out.append("DeviceInfoResponse {\n");
 | 
				
			||||||
  out.append("  uses_password: ");
 | 
					  out.append("  uses_password: ");
 | 
				
			||||||
  out.append(YESNO(this->uses_password));
 | 
					  out.append(YESNO(this->uses_password));
 | 
				
			||||||
@@ -513,11 +484,6 @@ void DeviceInfoResponse::dump_to(std::string &out) const {
 | 
				
			|||||||
  out.append("  project_version: ");
 | 
					  out.append("  project_version: ");
 | 
				
			||||||
  out.append("'").append(this->project_version).append("'");
 | 
					  out.append("'").append(this->project_version).append("'");
 | 
				
			||||||
  out.append("\n");
 | 
					  out.append("\n");
 | 
				
			||||||
 | 
					 | 
				
			||||||
  out.append("  webserver_port: ");
 | 
					 | 
				
			||||||
  sprintf(buffer, "%u", this->webserver_port);
 | 
					 | 
				
			||||||
  out.append(buffer);
 | 
					 | 
				
			||||||
  out.append("\n");
 | 
					 | 
				
			||||||
  out.append("}");
 | 
					  out.append("}");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -543,10 +509,6 @@ bool ListEntitiesBinarySensorResponse::decode_varint(uint32_t field_id, ProtoVar
 | 
				
			|||||||
      this->disabled_by_default = value.as_bool();
 | 
					      this->disabled_by_default = value.as_bool();
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case 9: {
 | 
					 | 
				
			||||||
      this->entity_category = value.as_enum<enums::EntityCategory>();
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -596,11 +558,10 @@ void ListEntitiesBinarySensorResponse::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
  buffer.encode_bool(6, this->is_status_binary_sensor);
 | 
					  buffer.encode_bool(6, this->is_status_binary_sensor);
 | 
				
			||||||
  buffer.encode_bool(7, this->disabled_by_default);
 | 
					  buffer.encode_bool(7, this->disabled_by_default);
 | 
				
			||||||
  buffer.encode_string(8, this->icon);
 | 
					  buffer.encode_string(8, this->icon);
 | 
				
			||||||
  buffer.encode_enum<enums::EntityCategory>(9, this->entity_category);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void ListEntitiesBinarySensorResponse::dump_to(std::string &out) const {
 | 
					void ListEntitiesBinarySensorResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("ListEntitiesBinarySensorResponse {\n");
 | 
					  out.append("ListEntitiesBinarySensorResponse {\n");
 | 
				
			||||||
  out.append("  object_id: ");
 | 
					  out.append("  object_id: ");
 | 
				
			||||||
  out.append("'").append(this->object_id).append("'");
 | 
					  out.append("'").append(this->object_id).append("'");
 | 
				
			||||||
@@ -634,10 +595,6 @@ void ListEntitiesBinarySensorResponse::dump_to(std::string &out) const {
 | 
				
			|||||||
  out.append("  icon: ");
 | 
					  out.append("  icon: ");
 | 
				
			||||||
  out.append("'").append(this->icon).append("'");
 | 
					  out.append("'").append(this->icon).append("'");
 | 
				
			||||||
  out.append("\n");
 | 
					  out.append("\n");
 | 
				
			||||||
 | 
					 | 
				
			||||||
  out.append("  entity_category: ");
 | 
					 | 
				
			||||||
  out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
 | 
					 | 
				
			||||||
  out.append("\n");
 | 
					 | 
				
			||||||
  out.append("}");
 | 
					  out.append("}");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -672,7 +629,7 @@ void BinarySensorStateResponse::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void BinarySensorStateResponse::dump_to(std::string &out) const {
 | 
					void BinarySensorStateResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("BinarySensorStateResponse {\n");
 | 
					  out.append("BinarySensorStateResponse {\n");
 | 
				
			||||||
  out.append("  key: ");
 | 
					  out.append("  key: ");
 | 
				
			||||||
  sprintf(buffer, "%u", this->key);
 | 
					  sprintf(buffer, "%u", this->key);
 | 
				
			||||||
@@ -707,10 +664,6 @@ bool ListEntitiesCoverResponse::decode_varint(uint32_t field_id, ProtoVarInt val
 | 
				
			|||||||
      this->disabled_by_default = value.as_bool();
 | 
					      this->disabled_by_default = value.as_bool();
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case 11: {
 | 
					 | 
				
			||||||
      this->entity_category = value.as_enum<enums::EntityCategory>();
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -762,11 +715,10 @@ void ListEntitiesCoverResponse::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
  buffer.encode_string(8, this->device_class);
 | 
					  buffer.encode_string(8, this->device_class);
 | 
				
			||||||
  buffer.encode_bool(9, this->disabled_by_default);
 | 
					  buffer.encode_bool(9, this->disabled_by_default);
 | 
				
			||||||
  buffer.encode_string(10, this->icon);
 | 
					  buffer.encode_string(10, this->icon);
 | 
				
			||||||
  buffer.encode_enum<enums::EntityCategory>(11, this->entity_category);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void ListEntitiesCoverResponse::dump_to(std::string &out) const {
 | 
					void ListEntitiesCoverResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("ListEntitiesCoverResponse {\n");
 | 
					  out.append("ListEntitiesCoverResponse {\n");
 | 
				
			||||||
  out.append("  object_id: ");
 | 
					  out.append("  object_id: ");
 | 
				
			||||||
  out.append("'").append(this->object_id).append("'");
 | 
					  out.append("'").append(this->object_id).append("'");
 | 
				
			||||||
@@ -808,10 +760,6 @@ void ListEntitiesCoverResponse::dump_to(std::string &out) const {
 | 
				
			|||||||
  out.append("  icon: ");
 | 
					  out.append("  icon: ");
 | 
				
			||||||
  out.append("'").append(this->icon).append("'");
 | 
					  out.append("'").append(this->icon).append("'");
 | 
				
			||||||
  out.append("\n");
 | 
					  out.append("\n");
 | 
				
			||||||
 | 
					 | 
				
			||||||
  out.append("  entity_category: ");
 | 
					 | 
				
			||||||
  out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
 | 
					 | 
				
			||||||
  out.append("\n");
 | 
					 | 
				
			||||||
  out.append("}");
 | 
					  out.append("}");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -856,7 +804,7 @@ void CoverStateResponse::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void CoverStateResponse::dump_to(std::string &out) const {
 | 
					void CoverStateResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("CoverStateResponse {\n");
 | 
					  out.append("CoverStateResponse {\n");
 | 
				
			||||||
  out.append("  key: ");
 | 
					  out.append("  key: ");
 | 
				
			||||||
  sprintf(buffer, "%u", this->key);
 | 
					  sprintf(buffer, "%u", this->key);
 | 
				
			||||||
@@ -939,7 +887,7 @@ void CoverCommandRequest::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void CoverCommandRequest::dump_to(std::string &out) const {
 | 
					void CoverCommandRequest::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("CoverCommandRequest {\n");
 | 
					  out.append("CoverCommandRequest {\n");
 | 
				
			||||||
  out.append("  key: ");
 | 
					  out.append("  key: ");
 | 
				
			||||||
  sprintf(buffer, "%u", this->key);
 | 
					  sprintf(buffer, "%u", this->key);
 | 
				
			||||||
@@ -1000,10 +948,6 @@ bool ListEntitiesFanResponse::decode_varint(uint32_t field_id, ProtoVarInt value
 | 
				
			|||||||
      this->disabled_by_default = value.as_bool();
 | 
					      this->disabled_by_default = value.as_bool();
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case 11: {
 | 
					 | 
				
			||||||
      this->entity_category = value.as_enum<enums::EntityCategory>();
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -1051,11 +995,10 @@ void ListEntitiesFanResponse::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
  buffer.encode_int32(8, this->supported_speed_count);
 | 
					  buffer.encode_int32(8, this->supported_speed_count);
 | 
				
			||||||
  buffer.encode_bool(9, this->disabled_by_default);
 | 
					  buffer.encode_bool(9, this->disabled_by_default);
 | 
				
			||||||
  buffer.encode_string(10, this->icon);
 | 
					  buffer.encode_string(10, this->icon);
 | 
				
			||||||
  buffer.encode_enum<enums::EntityCategory>(11, this->entity_category);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void ListEntitiesFanResponse::dump_to(std::string &out) const {
 | 
					void ListEntitiesFanResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("ListEntitiesFanResponse {\n");
 | 
					  out.append("ListEntitiesFanResponse {\n");
 | 
				
			||||||
  out.append("  object_id: ");
 | 
					  out.append("  object_id: ");
 | 
				
			||||||
  out.append("'").append(this->object_id).append("'");
 | 
					  out.append("'").append(this->object_id).append("'");
 | 
				
			||||||
@@ -1098,10 +1041,6 @@ void ListEntitiesFanResponse::dump_to(std::string &out) const {
 | 
				
			|||||||
  out.append("  icon: ");
 | 
					  out.append("  icon: ");
 | 
				
			||||||
  out.append("'").append(this->icon).append("'");
 | 
					  out.append("'").append(this->icon).append("'");
 | 
				
			||||||
  out.append("\n");
 | 
					  out.append("\n");
 | 
				
			||||||
 | 
					 | 
				
			||||||
  out.append("  entity_category: ");
 | 
					 | 
				
			||||||
  out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
 | 
					 | 
				
			||||||
  out.append("\n");
 | 
					 | 
				
			||||||
  out.append("}");
 | 
					  out.append("}");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -1151,7 +1090,7 @@ void FanStateResponse::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void FanStateResponse::dump_to(std::string &out) const {
 | 
					void FanStateResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("FanStateResponse {\n");
 | 
					  out.append("FanStateResponse {\n");
 | 
				
			||||||
  out.append("  key: ");
 | 
					  out.append("  key: ");
 | 
				
			||||||
  sprintf(buffer, "%u", this->key);
 | 
					  sprintf(buffer, "%u", this->key);
 | 
				
			||||||
@@ -1252,7 +1191,7 @@ void FanCommandRequest::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void FanCommandRequest::dump_to(std::string &out) const {
 | 
					void FanCommandRequest::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("FanCommandRequest {\n");
 | 
					  out.append("FanCommandRequest {\n");
 | 
				
			||||||
  out.append("  key: ");
 | 
					  out.append("  key: ");
 | 
				
			||||||
  sprintf(buffer, "%u", this->key);
 | 
					  sprintf(buffer, "%u", this->key);
 | 
				
			||||||
@@ -1328,10 +1267,6 @@ bool ListEntitiesLightResponse::decode_varint(uint32_t field_id, ProtoVarInt val
 | 
				
			|||||||
      this->disabled_by_default = value.as_bool();
 | 
					      this->disabled_by_default = value.as_bool();
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case 15: {
 | 
					 | 
				
			||||||
      this->entity_category = value.as_enum<enums::EntityCategory>();
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -1399,11 +1334,10 @@ void ListEntitiesLightResponse::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  buffer.encode_bool(13, this->disabled_by_default);
 | 
					  buffer.encode_bool(13, this->disabled_by_default);
 | 
				
			||||||
  buffer.encode_string(14, this->icon);
 | 
					  buffer.encode_string(14, this->icon);
 | 
				
			||||||
  buffer.encode_enum<enums::EntityCategory>(15, this->entity_category);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void ListEntitiesLightResponse::dump_to(std::string &out) const {
 | 
					void ListEntitiesLightResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("ListEntitiesLightResponse {\n");
 | 
					  out.append("ListEntitiesLightResponse {\n");
 | 
				
			||||||
  out.append("  object_id: ");
 | 
					  out.append("  object_id: ");
 | 
				
			||||||
  out.append("'").append(this->object_id).append("'");
 | 
					  out.append("'").append(this->object_id).append("'");
 | 
				
			||||||
@@ -1467,10 +1401,6 @@ void ListEntitiesLightResponse::dump_to(std::string &out) const {
 | 
				
			|||||||
  out.append("  icon: ");
 | 
					  out.append("  icon: ");
 | 
				
			||||||
  out.append("'").append(this->icon).append("'");
 | 
					  out.append("'").append(this->icon).append("'");
 | 
				
			||||||
  out.append("\n");
 | 
					  out.append("\n");
 | 
				
			||||||
 | 
					 | 
				
			||||||
  out.append("  entity_category: ");
 | 
					 | 
				
			||||||
  out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
 | 
					 | 
				
			||||||
  out.append("\n");
 | 
					 | 
				
			||||||
  out.append("}");
 | 
					  out.append("}");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -1561,7 +1491,7 @@ void LightStateResponse::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void LightStateResponse::dump_to(std::string &out) const {
 | 
					void LightStateResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("LightStateResponse {\n");
 | 
					  out.append("LightStateResponse {\n");
 | 
				
			||||||
  out.append("  key: ");
 | 
					  out.append("  key: ");
 | 
				
			||||||
  sprintf(buffer, "%u", this->key);
 | 
					  sprintf(buffer, "%u", this->key);
 | 
				
			||||||
@@ -1784,7 +1714,7 @@ void LightCommandRequest::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void LightCommandRequest::dump_to(std::string &out) const {
 | 
					void LightCommandRequest::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("LightCommandRequest {\n");
 | 
					  out.append("LightCommandRequest {\n");
 | 
				
			||||||
  out.append("  key: ");
 | 
					  out.append("  key: ");
 | 
				
			||||||
  sprintf(buffer, "%u", this->key);
 | 
					  sprintf(buffer, "%u", this->key);
 | 
				
			||||||
@@ -1930,10 +1860,6 @@ bool ListEntitiesSensorResponse::decode_varint(uint32_t field_id, ProtoVarInt va
 | 
				
			|||||||
      this->disabled_by_default = value.as_bool();
 | 
					      this->disabled_by_default = value.as_bool();
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case 13: {
 | 
					 | 
				
			||||||
      this->entity_category = value.as_enum<enums::EntityCategory>();
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -1991,11 +1917,10 @@ void ListEntitiesSensorResponse::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
  buffer.encode_enum<enums::SensorStateClass>(10, this->state_class);
 | 
					  buffer.encode_enum<enums::SensorStateClass>(10, this->state_class);
 | 
				
			||||||
  buffer.encode_enum<enums::SensorLastResetType>(11, this->legacy_last_reset_type);
 | 
					  buffer.encode_enum<enums::SensorLastResetType>(11, this->legacy_last_reset_type);
 | 
				
			||||||
  buffer.encode_bool(12, this->disabled_by_default);
 | 
					  buffer.encode_bool(12, this->disabled_by_default);
 | 
				
			||||||
  buffer.encode_enum<enums::EntityCategory>(13, this->entity_category);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void ListEntitiesSensorResponse::dump_to(std::string &out) const {
 | 
					void ListEntitiesSensorResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("ListEntitiesSensorResponse {\n");
 | 
					  out.append("ListEntitiesSensorResponse {\n");
 | 
				
			||||||
  out.append("  object_id: ");
 | 
					  out.append("  object_id: ");
 | 
				
			||||||
  out.append("'").append(this->object_id).append("'");
 | 
					  out.append("'").append(this->object_id).append("'");
 | 
				
			||||||
@@ -2046,10 +1971,6 @@ void ListEntitiesSensorResponse::dump_to(std::string &out) const {
 | 
				
			|||||||
  out.append("  disabled_by_default: ");
 | 
					  out.append("  disabled_by_default: ");
 | 
				
			||||||
  out.append(YESNO(this->disabled_by_default));
 | 
					  out.append(YESNO(this->disabled_by_default));
 | 
				
			||||||
  out.append("\n");
 | 
					  out.append("\n");
 | 
				
			||||||
 | 
					 | 
				
			||||||
  out.append("  entity_category: ");
 | 
					 | 
				
			||||||
  out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
 | 
					 | 
				
			||||||
  out.append("\n");
 | 
					 | 
				
			||||||
  out.append("}");
 | 
					  out.append("}");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -2084,7 +2005,7 @@ void SensorStateResponse::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void SensorStateResponse::dump_to(std::string &out) const {
 | 
					void SensorStateResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("SensorStateResponse {\n");
 | 
					  out.append("SensorStateResponse {\n");
 | 
				
			||||||
  out.append("  key: ");
 | 
					  out.append("  key: ");
 | 
				
			||||||
  sprintf(buffer, "%u", this->key);
 | 
					  sprintf(buffer, "%u", this->key);
 | 
				
			||||||
@@ -2112,10 +2033,6 @@ bool ListEntitiesSwitchResponse::decode_varint(uint32_t field_id, ProtoVarInt va
 | 
				
			|||||||
      this->disabled_by_default = value.as_bool();
 | 
					      this->disabled_by_default = value.as_bool();
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case 8: {
 | 
					 | 
				
			||||||
      this->entity_category = value.as_enum<enums::EntityCategory>();
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -2160,11 +2077,10 @@ void ListEntitiesSwitchResponse::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
  buffer.encode_string(5, this->icon);
 | 
					  buffer.encode_string(5, this->icon);
 | 
				
			||||||
  buffer.encode_bool(6, this->assumed_state);
 | 
					  buffer.encode_bool(6, this->assumed_state);
 | 
				
			||||||
  buffer.encode_bool(7, this->disabled_by_default);
 | 
					  buffer.encode_bool(7, this->disabled_by_default);
 | 
				
			||||||
  buffer.encode_enum<enums::EntityCategory>(8, this->entity_category);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void ListEntitiesSwitchResponse::dump_to(std::string &out) const {
 | 
					void ListEntitiesSwitchResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("ListEntitiesSwitchResponse {\n");
 | 
					  out.append("ListEntitiesSwitchResponse {\n");
 | 
				
			||||||
  out.append("  object_id: ");
 | 
					  out.append("  object_id: ");
 | 
				
			||||||
  out.append("'").append(this->object_id).append("'");
 | 
					  out.append("'").append(this->object_id).append("'");
 | 
				
			||||||
@@ -2194,10 +2110,6 @@ void ListEntitiesSwitchResponse::dump_to(std::string &out) const {
 | 
				
			|||||||
  out.append("  disabled_by_default: ");
 | 
					  out.append("  disabled_by_default: ");
 | 
				
			||||||
  out.append(YESNO(this->disabled_by_default));
 | 
					  out.append(YESNO(this->disabled_by_default));
 | 
				
			||||||
  out.append("\n");
 | 
					  out.append("\n");
 | 
				
			||||||
 | 
					 | 
				
			||||||
  out.append("  entity_category: ");
 | 
					 | 
				
			||||||
  out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
 | 
					 | 
				
			||||||
  out.append("\n");
 | 
					 | 
				
			||||||
  out.append("}");
 | 
					  out.append("}");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -2227,7 +2139,7 @@ void SwitchStateResponse::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void SwitchStateResponse::dump_to(std::string &out) const {
 | 
					void SwitchStateResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("SwitchStateResponse {\n");
 | 
					  out.append("SwitchStateResponse {\n");
 | 
				
			||||||
  out.append("  key: ");
 | 
					  out.append("  key: ");
 | 
				
			||||||
  sprintf(buffer, "%u", this->key);
 | 
					  sprintf(buffer, "%u", this->key);
 | 
				
			||||||
@@ -2266,7 +2178,7 @@ void SwitchCommandRequest::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void SwitchCommandRequest::dump_to(std::string &out) const {
 | 
					void SwitchCommandRequest::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("SwitchCommandRequest {\n");
 | 
					  out.append("SwitchCommandRequest {\n");
 | 
				
			||||||
  out.append("  key: ");
 | 
					  out.append("  key: ");
 | 
				
			||||||
  sprintf(buffer, "%u", this->key);
 | 
					  sprintf(buffer, "%u", this->key);
 | 
				
			||||||
@@ -2285,10 +2197,6 @@ bool ListEntitiesTextSensorResponse::decode_varint(uint32_t field_id, ProtoVarIn
 | 
				
			|||||||
      this->disabled_by_default = value.as_bool();
 | 
					      this->disabled_by_default = value.as_bool();
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case 7: {
 | 
					 | 
				
			||||||
      this->entity_category = value.as_enum<enums::EntityCategory>();
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -2332,11 +2240,10 @@ void ListEntitiesTextSensorResponse::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
  buffer.encode_string(4, this->unique_id);
 | 
					  buffer.encode_string(4, this->unique_id);
 | 
				
			||||||
  buffer.encode_string(5, this->icon);
 | 
					  buffer.encode_string(5, this->icon);
 | 
				
			||||||
  buffer.encode_bool(6, this->disabled_by_default);
 | 
					  buffer.encode_bool(6, this->disabled_by_default);
 | 
				
			||||||
  buffer.encode_enum<enums::EntityCategory>(7, this->entity_category);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void ListEntitiesTextSensorResponse::dump_to(std::string &out) const {
 | 
					void ListEntitiesTextSensorResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("ListEntitiesTextSensorResponse {\n");
 | 
					  out.append("ListEntitiesTextSensorResponse {\n");
 | 
				
			||||||
  out.append("  object_id: ");
 | 
					  out.append("  object_id: ");
 | 
				
			||||||
  out.append("'").append(this->object_id).append("'");
 | 
					  out.append("'").append(this->object_id).append("'");
 | 
				
			||||||
@@ -2362,10 +2269,6 @@ void ListEntitiesTextSensorResponse::dump_to(std::string &out) const {
 | 
				
			|||||||
  out.append("  disabled_by_default: ");
 | 
					  out.append("  disabled_by_default: ");
 | 
				
			||||||
  out.append(YESNO(this->disabled_by_default));
 | 
					  out.append(YESNO(this->disabled_by_default));
 | 
				
			||||||
  out.append("\n");
 | 
					  out.append("\n");
 | 
				
			||||||
 | 
					 | 
				
			||||||
  out.append("  entity_category: ");
 | 
					 | 
				
			||||||
  out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
 | 
					 | 
				
			||||||
  out.append("\n");
 | 
					 | 
				
			||||||
  out.append("}");
 | 
					  out.append("}");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -2406,7 +2309,7 @@ void TextSensorStateResponse::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void TextSensorStateResponse::dump_to(std::string &out) const {
 | 
					void TextSensorStateResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("TextSensorStateResponse {\n");
 | 
					  out.append("TextSensorStateResponse {\n");
 | 
				
			||||||
  out.append("  key: ");
 | 
					  out.append("  key: ");
 | 
				
			||||||
  sprintf(buffer, "%u", this->key);
 | 
					  sprintf(buffer, "%u", this->key);
 | 
				
			||||||
@@ -2443,7 +2346,7 @@ void SubscribeLogsRequest::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void SubscribeLogsRequest::dump_to(std::string &out) const {
 | 
					void SubscribeLogsRequest::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("SubscribeLogsRequest {\n");
 | 
					  out.append("SubscribeLogsRequest {\n");
 | 
				
			||||||
  out.append("  level: ");
 | 
					  out.append("  level: ");
 | 
				
			||||||
  out.append(proto_enum_to_string<enums::LogLevel>(this->level));
 | 
					  out.append(proto_enum_to_string<enums::LogLevel>(this->level));
 | 
				
			||||||
@@ -2486,7 +2389,7 @@ void SubscribeLogsResponse::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void SubscribeLogsResponse::dump_to(std::string &out) const {
 | 
					void SubscribeLogsResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("SubscribeLogsResponse {\n");
 | 
					  out.append("SubscribeLogsResponse {\n");
 | 
				
			||||||
  out.append("  level: ");
 | 
					  out.append("  level: ");
 | 
				
			||||||
  out.append(proto_enum_to_string<enums::LogLevel>(this->level));
 | 
					  out.append(proto_enum_to_string<enums::LogLevel>(this->level));
 | 
				
			||||||
@@ -2528,7 +2431,7 @@ void HomeassistantServiceMap::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void HomeassistantServiceMap::dump_to(std::string &out) const {
 | 
					void HomeassistantServiceMap::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("HomeassistantServiceMap {\n");
 | 
					  out.append("HomeassistantServiceMap {\n");
 | 
				
			||||||
  out.append("  key: ");
 | 
					  out.append("  key: ");
 | 
				
			||||||
  out.append("'").append(this->key).append("'");
 | 
					  out.append("'").append(this->key).append("'");
 | 
				
			||||||
@@ -2587,7 +2490,7 @@ void HomeassistantServiceResponse::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void HomeassistantServiceResponse::dump_to(std::string &out) const {
 | 
					void HomeassistantServiceResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("HomeassistantServiceResponse {\n");
 | 
					  out.append("HomeassistantServiceResponse {\n");
 | 
				
			||||||
  out.append("  service: ");
 | 
					  out.append("  service: ");
 | 
				
			||||||
  out.append("'").append(this->service).append("'");
 | 
					  out.append("'").append(this->service).append("'");
 | 
				
			||||||
@@ -2643,7 +2546,7 @@ void SubscribeHomeAssistantStateResponse::encode(ProtoWriteBuffer buffer) const
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void SubscribeHomeAssistantStateResponse::dump_to(std::string &out) const {
 | 
					void SubscribeHomeAssistantStateResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("SubscribeHomeAssistantStateResponse {\n");
 | 
					  out.append("SubscribeHomeAssistantStateResponse {\n");
 | 
				
			||||||
  out.append("  entity_id: ");
 | 
					  out.append("  entity_id: ");
 | 
				
			||||||
  out.append("'").append(this->entity_id).append("'");
 | 
					  out.append("'").append(this->entity_id).append("'");
 | 
				
			||||||
@@ -2680,7 +2583,7 @@ void HomeAssistantStateResponse::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void HomeAssistantStateResponse::dump_to(std::string &out) const {
 | 
					void HomeAssistantStateResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("HomeAssistantStateResponse {\n");
 | 
					  out.append("HomeAssistantStateResponse {\n");
 | 
				
			||||||
  out.append("  entity_id: ");
 | 
					  out.append("  entity_id: ");
 | 
				
			||||||
  out.append("'").append(this->entity_id).append("'");
 | 
					  out.append("'").append(this->entity_id).append("'");
 | 
				
			||||||
@@ -2713,7 +2616,7 @@ bool GetTimeResponse::decode_32bit(uint32_t field_id, Proto32Bit value) {
 | 
				
			|||||||
void GetTimeResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_fixed32(1, this->epoch_seconds); }
 | 
					void GetTimeResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_fixed32(1, this->epoch_seconds); }
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void GetTimeResponse::dump_to(std::string &out) const {
 | 
					void GetTimeResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("GetTimeResponse {\n");
 | 
					  out.append("GetTimeResponse {\n");
 | 
				
			||||||
  out.append("  epoch_seconds: ");
 | 
					  out.append("  epoch_seconds: ");
 | 
				
			||||||
  sprintf(buffer, "%u", this->epoch_seconds);
 | 
					  sprintf(buffer, "%u", this->epoch_seconds);
 | 
				
			||||||
@@ -2748,7 +2651,7 @@ void ListEntitiesServicesArgument::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void ListEntitiesServicesArgument::dump_to(std::string &out) const {
 | 
					void ListEntitiesServicesArgument::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("ListEntitiesServicesArgument {\n");
 | 
					  out.append("ListEntitiesServicesArgument {\n");
 | 
				
			||||||
  out.append("  name: ");
 | 
					  out.append("  name: ");
 | 
				
			||||||
  out.append("'").append(this->name).append("'");
 | 
					  out.append("'").append(this->name).append("'");
 | 
				
			||||||
@@ -2793,7 +2696,7 @@ void ListEntitiesServicesResponse::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void ListEntitiesServicesResponse::dump_to(std::string &out) const {
 | 
					void ListEntitiesServicesResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("ListEntitiesServicesResponse {\n");
 | 
					  out.append("ListEntitiesServicesResponse {\n");
 | 
				
			||||||
  out.append("  name: ");
 | 
					  out.append("  name: ");
 | 
				
			||||||
  out.append("'").append(this->name).append("'");
 | 
					  out.append("'").append(this->name).append("'");
 | 
				
			||||||
@@ -2887,7 +2790,7 @@ void ExecuteServiceArgument::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void ExecuteServiceArgument::dump_to(std::string &out) const {
 | 
					void ExecuteServiceArgument::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("ExecuteServiceArgument {\n");
 | 
					  out.append("ExecuteServiceArgument {\n");
 | 
				
			||||||
  out.append("  bool_: ");
 | 
					  out.append("  bool_: ");
 | 
				
			||||||
  out.append(YESNO(this->bool_));
 | 
					  out.append(YESNO(this->bool_));
 | 
				
			||||||
@@ -2968,7 +2871,7 @@ void ExecuteServiceRequest::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void ExecuteServiceRequest::dump_to(std::string &out) const {
 | 
					void ExecuteServiceRequest::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("ExecuteServiceRequest {\n");
 | 
					  out.append("ExecuteServiceRequest {\n");
 | 
				
			||||||
  out.append("  key: ");
 | 
					  out.append("  key: ");
 | 
				
			||||||
  sprintf(buffer, "%u", this->key);
 | 
					  sprintf(buffer, "%u", this->key);
 | 
				
			||||||
@@ -2989,10 +2892,6 @@ bool ListEntitiesCameraResponse::decode_varint(uint32_t field_id, ProtoVarInt va
 | 
				
			|||||||
      this->disabled_by_default = value.as_bool();
 | 
					      this->disabled_by_default = value.as_bool();
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case 7: {
 | 
					 | 
				
			||||||
      this->entity_category = value.as_enum<enums::EntityCategory>();
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -3011,10 +2910,6 @@ bool ListEntitiesCameraResponse::decode_length(uint32_t field_id, ProtoLengthDel
 | 
				
			|||||||
      this->unique_id = value.as_string();
 | 
					      this->unique_id = value.as_string();
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case 6: {
 | 
					 | 
				
			||||||
      this->icon = value.as_string();
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -3035,12 +2930,10 @@ void ListEntitiesCameraResponse::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
  buffer.encode_string(3, this->name);
 | 
					  buffer.encode_string(3, this->name);
 | 
				
			||||||
  buffer.encode_string(4, this->unique_id);
 | 
					  buffer.encode_string(4, this->unique_id);
 | 
				
			||||||
  buffer.encode_bool(5, this->disabled_by_default);
 | 
					  buffer.encode_bool(5, this->disabled_by_default);
 | 
				
			||||||
  buffer.encode_string(6, this->icon);
 | 
					 | 
				
			||||||
  buffer.encode_enum<enums::EntityCategory>(7, this->entity_category);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void ListEntitiesCameraResponse::dump_to(std::string &out) const {
 | 
					void ListEntitiesCameraResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("ListEntitiesCameraResponse {\n");
 | 
					  out.append("ListEntitiesCameraResponse {\n");
 | 
				
			||||||
  out.append("  object_id: ");
 | 
					  out.append("  object_id: ");
 | 
				
			||||||
  out.append("'").append(this->object_id).append("'");
 | 
					  out.append("'").append(this->object_id).append("'");
 | 
				
			||||||
@@ -3062,14 +2955,6 @@ void ListEntitiesCameraResponse::dump_to(std::string &out) const {
 | 
				
			|||||||
  out.append("  disabled_by_default: ");
 | 
					  out.append("  disabled_by_default: ");
 | 
				
			||||||
  out.append(YESNO(this->disabled_by_default));
 | 
					  out.append(YESNO(this->disabled_by_default));
 | 
				
			||||||
  out.append("\n");
 | 
					  out.append("\n");
 | 
				
			||||||
 | 
					 | 
				
			||||||
  out.append("  icon: ");
 | 
					 | 
				
			||||||
  out.append("'").append(this->icon).append("'");
 | 
					 | 
				
			||||||
  out.append("\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  out.append("  entity_category: ");
 | 
					 | 
				
			||||||
  out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
 | 
					 | 
				
			||||||
  out.append("\n");
 | 
					 | 
				
			||||||
  out.append("}");
 | 
					  out.append("}");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -3110,7 +2995,7 @@ void CameraImageResponse::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void CameraImageResponse::dump_to(std::string &out) const {
 | 
					void CameraImageResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("CameraImageResponse {\n");
 | 
					  out.append("CameraImageResponse {\n");
 | 
				
			||||||
  out.append("  key: ");
 | 
					  out.append("  key: ");
 | 
				
			||||||
  sprintf(buffer, "%u", this->key);
 | 
					  sprintf(buffer, "%u", this->key);
 | 
				
			||||||
@@ -3147,7 +3032,7 @@ void CameraImageRequest::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void CameraImageRequest::dump_to(std::string &out) const {
 | 
					void CameraImageRequest::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("CameraImageRequest {\n");
 | 
					  out.append("CameraImageRequest {\n");
 | 
				
			||||||
  out.append("  single: ");
 | 
					  out.append("  single: ");
 | 
				
			||||||
  out.append(YESNO(this->single));
 | 
					  out.append(YESNO(this->single));
 | 
				
			||||||
@@ -3197,10 +3082,6 @@ bool ListEntitiesClimateResponse::decode_varint(uint32_t field_id, ProtoVarInt v
 | 
				
			|||||||
      this->disabled_by_default = value.as_bool();
 | 
					      this->disabled_by_default = value.as_bool();
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case 20: {
 | 
					 | 
				
			||||||
      this->entity_category = value.as_enum<enums::EntityCategory>();
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -3289,11 +3170,10 @@ void ListEntitiesClimateResponse::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  buffer.encode_bool(18, this->disabled_by_default);
 | 
					  buffer.encode_bool(18, this->disabled_by_default);
 | 
				
			||||||
  buffer.encode_string(19, this->icon);
 | 
					  buffer.encode_string(19, this->icon);
 | 
				
			||||||
  buffer.encode_enum<enums::EntityCategory>(20, this->entity_category);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void ListEntitiesClimateResponse::dump_to(std::string &out) const {
 | 
					void ListEntitiesClimateResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("ListEntitiesClimateResponse {\n");
 | 
					  out.append("ListEntitiesClimateResponse {\n");
 | 
				
			||||||
  out.append("  object_id: ");
 | 
					  out.append("  object_id: ");
 | 
				
			||||||
  out.append("'").append(this->object_id).append("'");
 | 
					  out.append("'").append(this->object_id).append("'");
 | 
				
			||||||
@@ -3386,10 +3266,6 @@ void ListEntitiesClimateResponse::dump_to(std::string &out) const {
 | 
				
			|||||||
  out.append("  icon: ");
 | 
					  out.append("  icon: ");
 | 
				
			||||||
  out.append("'").append(this->icon).append("'");
 | 
					  out.append("'").append(this->icon).append("'");
 | 
				
			||||||
  out.append("\n");
 | 
					  out.append("\n");
 | 
				
			||||||
 | 
					 | 
				
			||||||
  out.append("  entity_category: ");
 | 
					 | 
				
			||||||
  out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
 | 
					 | 
				
			||||||
  out.append("\n");
 | 
					 | 
				
			||||||
  out.append("}");
 | 
					  out.append("}");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -3480,7 +3356,7 @@ void ClimateStateResponse::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void ClimateStateResponse::dump_to(std::string &out) const {
 | 
					void ClimateStateResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("ClimateStateResponse {\n");
 | 
					  out.append("ClimateStateResponse {\n");
 | 
				
			||||||
  out.append("  key: ");
 | 
					  out.append("  key: ");
 | 
				
			||||||
  sprintf(buffer, "%u", this->key);
 | 
					  sprintf(buffer, "%u", this->key);
 | 
				
			||||||
@@ -3668,7 +3544,7 @@ void ClimateCommandRequest::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void ClimateCommandRequest::dump_to(std::string &out) const {
 | 
					void ClimateCommandRequest::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("ClimateCommandRequest {\n");
 | 
					  out.append("ClimateCommandRequest {\n");
 | 
				
			||||||
  out.append("  key: ");
 | 
					  out.append("  key: ");
 | 
				
			||||||
  sprintf(buffer, "%u", this->key);
 | 
					  sprintf(buffer, "%u", this->key);
 | 
				
			||||||
@@ -3766,14 +3642,6 @@ bool ListEntitiesNumberResponse::decode_varint(uint32_t field_id, ProtoVarInt va
 | 
				
			|||||||
      this->disabled_by_default = value.as_bool();
 | 
					      this->disabled_by_default = value.as_bool();
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case 10: {
 | 
					 | 
				
			||||||
      this->entity_category = value.as_enum<enums::EntityCategory>();
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    case 12: {
 | 
					 | 
				
			||||||
      this->mode = value.as_enum<enums::NumberMode>();
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -3796,10 +3664,6 @@ bool ListEntitiesNumberResponse::decode_length(uint32_t field_id, ProtoLengthDel
 | 
				
			|||||||
      this->icon = value.as_string();
 | 
					      this->icon = value.as_string();
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case 11: {
 | 
					 | 
				
			||||||
      this->unit_of_measurement = value.as_string();
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -3836,13 +3700,10 @@ void ListEntitiesNumberResponse::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
  buffer.encode_float(7, this->max_value);
 | 
					  buffer.encode_float(7, this->max_value);
 | 
				
			||||||
  buffer.encode_float(8, this->step);
 | 
					  buffer.encode_float(8, this->step);
 | 
				
			||||||
  buffer.encode_bool(9, this->disabled_by_default);
 | 
					  buffer.encode_bool(9, this->disabled_by_default);
 | 
				
			||||||
  buffer.encode_enum<enums::EntityCategory>(10, this->entity_category);
 | 
					 | 
				
			||||||
  buffer.encode_string(11, this->unit_of_measurement);
 | 
					 | 
				
			||||||
  buffer.encode_enum<enums::NumberMode>(12, this->mode);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void ListEntitiesNumberResponse::dump_to(std::string &out) const {
 | 
					void ListEntitiesNumberResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("ListEntitiesNumberResponse {\n");
 | 
					  out.append("ListEntitiesNumberResponse {\n");
 | 
				
			||||||
  out.append("  object_id: ");
 | 
					  out.append("  object_id: ");
 | 
				
			||||||
  out.append("'").append(this->object_id).append("'");
 | 
					  out.append("'").append(this->object_id).append("'");
 | 
				
			||||||
@@ -3883,18 +3744,6 @@ void ListEntitiesNumberResponse::dump_to(std::string &out) const {
 | 
				
			|||||||
  out.append("  disabled_by_default: ");
 | 
					  out.append("  disabled_by_default: ");
 | 
				
			||||||
  out.append(YESNO(this->disabled_by_default));
 | 
					  out.append(YESNO(this->disabled_by_default));
 | 
				
			||||||
  out.append("\n");
 | 
					  out.append("\n");
 | 
				
			||||||
 | 
					 | 
				
			||||||
  out.append("  entity_category: ");
 | 
					 | 
				
			||||||
  out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
 | 
					 | 
				
			||||||
  out.append("\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  out.append("  unit_of_measurement: ");
 | 
					 | 
				
			||||||
  out.append("'").append(this->unit_of_measurement).append("'");
 | 
					 | 
				
			||||||
  out.append("\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  out.append("  mode: ");
 | 
					 | 
				
			||||||
  out.append(proto_enum_to_string<enums::NumberMode>(this->mode));
 | 
					 | 
				
			||||||
  out.append("\n");
 | 
					 | 
				
			||||||
  out.append("}");
 | 
					  out.append("}");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -3929,7 +3778,7 @@ void NumberStateResponse::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void NumberStateResponse::dump_to(std::string &out) const {
 | 
					void NumberStateResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("NumberStateResponse {\n");
 | 
					  out.append("NumberStateResponse {\n");
 | 
				
			||||||
  out.append("  key: ");
 | 
					  out.append("  key: ");
 | 
				
			||||||
  sprintf(buffer, "%u", this->key);
 | 
					  sprintf(buffer, "%u", this->key);
 | 
				
			||||||
@@ -3967,7 +3816,7 @@ void NumberCommandRequest::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void NumberCommandRequest::dump_to(std::string &out) const {
 | 
					void NumberCommandRequest::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("NumberCommandRequest {\n");
 | 
					  out.append("NumberCommandRequest {\n");
 | 
				
			||||||
  out.append("  key: ");
 | 
					  out.append("  key: ");
 | 
				
			||||||
  sprintf(buffer, "%u", this->key);
 | 
					  sprintf(buffer, "%u", this->key);
 | 
				
			||||||
@@ -3987,10 +3836,6 @@ bool ListEntitiesSelectResponse::decode_varint(uint32_t field_id, ProtoVarInt va
 | 
				
			|||||||
      this->disabled_by_default = value.as_bool();
 | 
					      this->disabled_by_default = value.as_bool();
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case 8: {
 | 
					 | 
				
			||||||
      this->entity_category = value.as_enum<enums::EntityCategory>();
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -4041,11 +3886,10 @@ void ListEntitiesSelectResponse::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
    buffer.encode_string(6, it, true);
 | 
					    buffer.encode_string(6, it, true);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  buffer.encode_bool(7, this->disabled_by_default);
 | 
					  buffer.encode_bool(7, this->disabled_by_default);
 | 
				
			||||||
  buffer.encode_enum<enums::EntityCategory>(8, this->entity_category);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void ListEntitiesSelectResponse::dump_to(std::string &out) const {
 | 
					void ListEntitiesSelectResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("ListEntitiesSelectResponse {\n");
 | 
					  out.append("ListEntitiesSelectResponse {\n");
 | 
				
			||||||
  out.append("  object_id: ");
 | 
					  out.append("  object_id: ");
 | 
				
			||||||
  out.append("'").append(this->object_id).append("'");
 | 
					  out.append("'").append(this->object_id).append("'");
 | 
				
			||||||
@@ -4077,10 +3921,6 @@ void ListEntitiesSelectResponse::dump_to(std::string &out) const {
 | 
				
			|||||||
  out.append("  disabled_by_default: ");
 | 
					  out.append("  disabled_by_default: ");
 | 
				
			||||||
  out.append(YESNO(this->disabled_by_default));
 | 
					  out.append(YESNO(this->disabled_by_default));
 | 
				
			||||||
  out.append("\n");
 | 
					  out.append("\n");
 | 
				
			||||||
 | 
					 | 
				
			||||||
  out.append("  entity_category: ");
 | 
					 | 
				
			||||||
  out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
 | 
					 | 
				
			||||||
  out.append("\n");
 | 
					 | 
				
			||||||
  out.append("}");
 | 
					  out.append("}");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -4121,7 +3961,7 @@ void SelectStateResponse::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void SelectStateResponse::dump_to(std::string &out) const {
 | 
					void SelectStateResponse::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("SelectStateResponse {\n");
 | 
					  out.append("SelectStateResponse {\n");
 | 
				
			||||||
  out.append("  key: ");
 | 
					  out.append("  key: ");
 | 
				
			||||||
  sprintf(buffer, "%u", this->key);
 | 
					  sprintf(buffer, "%u", this->key);
 | 
				
			||||||
@@ -4164,7 +4004,7 @@ void SelectCommandRequest::encode(ProtoWriteBuffer buffer) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
void SelectCommandRequest::dump_to(std::string &out) const {
 | 
					void SelectCommandRequest::dump_to(std::string &out) const {
 | 
				
			||||||
  __attribute__((unused)) char buffer[64];
 | 
					  char buffer[64];
 | 
				
			||||||
  out.append("SelectCommandRequest {\n");
 | 
					  out.append("SelectCommandRequest {\n");
 | 
				
			||||||
  out.append("  key: ");
 | 
					  out.append("  key: ");
 | 
				
			||||||
  sprintf(buffer, "%u", this->key);
 | 
					  sprintf(buffer, "%u", this->key);
 | 
				
			||||||
@@ -4177,127 +4017,6 @@ void SelectCommandRequest::dump_to(std::string &out) const {
 | 
				
			|||||||
  out.append("}");
 | 
					  out.append("}");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
bool ListEntitiesButtonResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
 | 
					 | 
				
			||||||
  switch (field_id) {
 | 
					 | 
				
			||||||
    case 6: {
 | 
					 | 
				
			||||||
      this->disabled_by_default = value.as_bool();
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    case 7: {
 | 
					 | 
				
			||||||
      this->entity_category = value.as_enum<enums::EntityCategory>();
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    default:
 | 
					 | 
				
			||||||
      return false;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
bool ListEntitiesButtonResponse::decode_length(uint32_t field_id, ProtoLengthDelimited value) {
 | 
					 | 
				
			||||||
  switch (field_id) {
 | 
					 | 
				
			||||||
    case 1: {
 | 
					 | 
				
			||||||
      this->object_id = value.as_string();
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    case 3: {
 | 
					 | 
				
			||||||
      this->name = value.as_string();
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    case 4: {
 | 
					 | 
				
			||||||
      this->unique_id = value.as_string();
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    case 5: {
 | 
					 | 
				
			||||||
      this->icon = value.as_string();
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    case 8: {
 | 
					 | 
				
			||||||
      this->device_class = value.as_string();
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    default:
 | 
					 | 
				
			||||||
      return false;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
bool ListEntitiesButtonResponse::decode_32bit(uint32_t field_id, Proto32Bit value) {
 | 
					 | 
				
			||||||
  switch (field_id) {
 | 
					 | 
				
			||||||
    case 2: {
 | 
					 | 
				
			||||||
      this->key = value.as_fixed32();
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    default:
 | 
					 | 
				
			||||||
      return false;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
void ListEntitiesButtonResponse::encode(ProtoWriteBuffer buffer) const {
 | 
					 | 
				
			||||||
  buffer.encode_string(1, this->object_id);
 | 
					 | 
				
			||||||
  buffer.encode_fixed32(2, this->key);
 | 
					 | 
				
			||||||
  buffer.encode_string(3, this->name);
 | 
					 | 
				
			||||||
  buffer.encode_string(4, this->unique_id);
 | 
					 | 
				
			||||||
  buffer.encode_string(5, this->icon);
 | 
					 | 
				
			||||||
  buffer.encode_bool(6, this->disabled_by_default);
 | 
					 | 
				
			||||||
  buffer.encode_enum<enums::EntityCategory>(7, this->entity_category);
 | 
					 | 
				
			||||||
  buffer.encode_string(8, this->device_class);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					 | 
				
			||||||
void ListEntitiesButtonResponse::dump_to(std::string &out) const {
 | 
					 | 
				
			||||||
  char buffer[64];
 | 
					 | 
				
			||||||
  out.append("ListEntitiesButtonResponse {\n");
 | 
					 | 
				
			||||||
  out.append("  object_id: ");
 | 
					 | 
				
			||||||
  out.append("'").append(this->object_id).append("'");
 | 
					 | 
				
			||||||
  out.append("\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  out.append("  key: ");
 | 
					 | 
				
			||||||
  sprintf(buffer, "%u", this->key);
 | 
					 | 
				
			||||||
  out.append(buffer);
 | 
					 | 
				
			||||||
  out.append("\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  out.append("  name: ");
 | 
					 | 
				
			||||||
  out.append("'").append(this->name).append("'");
 | 
					 | 
				
			||||||
  out.append("\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  out.append("  unique_id: ");
 | 
					 | 
				
			||||||
  out.append("'").append(this->unique_id).append("'");
 | 
					 | 
				
			||||||
  out.append("\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  out.append("  icon: ");
 | 
					 | 
				
			||||||
  out.append("'").append(this->icon).append("'");
 | 
					 | 
				
			||||||
  out.append("\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  out.append("  disabled_by_default: ");
 | 
					 | 
				
			||||||
  out.append(YESNO(this->disabled_by_default));
 | 
					 | 
				
			||||||
  out.append("\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  out.append("  entity_category: ");
 | 
					 | 
				
			||||||
  out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
 | 
					 | 
				
			||||||
  out.append("\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  out.append("  device_class: ");
 | 
					 | 
				
			||||||
  out.append("'").append(this->device_class).append("'");
 | 
					 | 
				
			||||||
  out.append("\n");
 | 
					 | 
				
			||||||
  out.append("}");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
bool ButtonCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) {
 | 
					 | 
				
			||||||
  switch (field_id) {
 | 
					 | 
				
			||||||
    case 1: {
 | 
					 | 
				
			||||||
      this->key = value.as_fixed32();
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    default:
 | 
					 | 
				
			||||||
      return false;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
void ButtonCommandRequest::encode(ProtoWriteBuffer buffer) const { buffer.encode_fixed32(1, this->key); }
 | 
					 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					 | 
				
			||||||
void ButtonCommandRequest::dump_to(std::string &out) const {
 | 
					 | 
				
			||||||
  char buffer[64];
 | 
					 | 
				
			||||||
  out.append("ButtonCommandRequest {\n");
 | 
					 | 
				
			||||||
  out.append("  key: ");
 | 
					 | 
				
			||||||
  sprintf(buffer, "%u", this->key);
 | 
					 | 
				
			||||||
  out.append(buffer);
 | 
					 | 
				
			||||||
  out.append("\n");
 | 
					 | 
				
			||||||
  out.append("}");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
}  // namespace api
 | 
					}  // namespace api
 | 
				
			||||||
}  // namespace esphome
 | 
					}  // namespace esphome
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,11 +9,6 @@ namespace api {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace enums {
 | 
					namespace enums {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum EntityCategory : uint32_t {
 | 
					 | 
				
			||||||
  ENTITY_CATEGORY_NONE = 0,
 | 
					 | 
				
			||||||
  ENTITY_CATEGORY_CONFIG = 1,
 | 
					 | 
				
			||||||
  ENTITY_CATEGORY_DIAGNOSTIC = 2,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
enum LegacyCoverState : uint32_t {
 | 
					enum LegacyCoverState : uint32_t {
 | 
				
			||||||
  LEGACY_COVER_STATE_OPEN = 0,
 | 
					  LEGACY_COVER_STATE_OPEN = 0,
 | 
				
			||||||
  LEGACY_COVER_STATE_CLOSED = 1,
 | 
					  LEGACY_COVER_STATE_CLOSED = 1,
 | 
				
			||||||
@@ -123,11 +118,6 @@ enum ClimatePreset : uint32_t {
 | 
				
			|||||||
  CLIMATE_PRESET_SLEEP = 6,
 | 
					  CLIMATE_PRESET_SLEEP = 6,
 | 
				
			||||||
  CLIMATE_PRESET_ACTIVITY = 7,
 | 
					  CLIMATE_PRESET_ACTIVITY = 7,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
enum NumberMode : uint32_t {
 | 
					 | 
				
			||||||
  NUMBER_MODE_AUTO = 0,
 | 
					 | 
				
			||||||
  NUMBER_MODE_BOX = 1,
 | 
					 | 
				
			||||||
  NUMBER_MODE_SLIDER = 2,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
}  // namespace enums
 | 
					}  // namespace enums
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -234,7 +224,6 @@ class DeviceInfoResponse : public ProtoMessage {
 | 
				
			|||||||
  bool has_deep_sleep{false};
 | 
					  bool has_deep_sleep{false};
 | 
				
			||||||
  std::string project_name{};
 | 
					  std::string project_name{};
 | 
				
			||||||
  std::string project_version{};
 | 
					  std::string project_version{};
 | 
				
			||||||
  uint32_t webserver_port{0};
 | 
					 | 
				
			||||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
  void dump_to(std::string &out) const override;
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
@@ -281,7 +270,6 @@ class ListEntitiesBinarySensorResponse : public ProtoMessage {
 | 
				
			|||||||
  bool is_status_binary_sensor{false};
 | 
					  bool is_status_binary_sensor{false};
 | 
				
			||||||
  bool disabled_by_default{false};
 | 
					  bool disabled_by_default{false};
 | 
				
			||||||
  std::string icon{};
 | 
					  std::string icon{};
 | 
				
			||||||
  enums::EntityCategory entity_category{};
 | 
					 | 
				
			||||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
  void dump_to(std::string &out) const override;
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
@@ -318,7 +306,6 @@ class ListEntitiesCoverResponse : public ProtoMessage {
 | 
				
			|||||||
  std::string device_class{};
 | 
					  std::string device_class{};
 | 
				
			||||||
  bool disabled_by_default{false};
 | 
					  bool disabled_by_default{false};
 | 
				
			||||||
  std::string icon{};
 | 
					  std::string icon{};
 | 
				
			||||||
  enums::EntityCategory entity_category{};
 | 
					 | 
				
			||||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
  void dump_to(std::string &out) const override;
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
@@ -376,7 +363,6 @@ class ListEntitiesFanResponse : public ProtoMessage {
 | 
				
			|||||||
  int32_t supported_speed_count{0};
 | 
					  int32_t supported_speed_count{0};
 | 
				
			||||||
  bool disabled_by_default{false};
 | 
					  bool disabled_by_default{false};
 | 
				
			||||||
  std::string icon{};
 | 
					  std::string icon{};
 | 
				
			||||||
  enums::EntityCategory entity_category{};
 | 
					 | 
				
			||||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
  void dump_to(std::string &out) const override;
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
@@ -442,7 +428,6 @@ class ListEntitiesLightResponse : public ProtoMessage {
 | 
				
			|||||||
  std::vector<std::string> effects{};
 | 
					  std::vector<std::string> effects{};
 | 
				
			||||||
  bool disabled_by_default{false};
 | 
					  bool disabled_by_default{false};
 | 
				
			||||||
  std::string icon{};
 | 
					  std::string icon{};
 | 
				
			||||||
  enums::EntityCategory entity_category{};
 | 
					 | 
				
			||||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
  void dump_to(std::string &out) const override;
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
@@ -531,7 +516,6 @@ class ListEntitiesSensorResponse : public ProtoMessage {
 | 
				
			|||||||
  enums::SensorStateClass state_class{};
 | 
					  enums::SensorStateClass state_class{};
 | 
				
			||||||
  enums::SensorLastResetType legacy_last_reset_type{};
 | 
					  enums::SensorLastResetType legacy_last_reset_type{};
 | 
				
			||||||
  bool disabled_by_default{false};
 | 
					  bool disabled_by_default{false};
 | 
				
			||||||
  enums::EntityCategory entity_category{};
 | 
					 | 
				
			||||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
  void dump_to(std::string &out) const override;
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
@@ -565,7 +549,6 @@ class ListEntitiesSwitchResponse : public ProtoMessage {
 | 
				
			|||||||
  std::string icon{};
 | 
					  std::string icon{};
 | 
				
			||||||
  bool assumed_state{false};
 | 
					  bool assumed_state{false};
 | 
				
			||||||
  bool disabled_by_default{false};
 | 
					  bool disabled_by_default{false};
 | 
				
			||||||
  enums::EntityCategory entity_category{};
 | 
					 | 
				
			||||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
  void dump_to(std::string &out) const override;
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
@@ -610,7 +593,6 @@ class ListEntitiesTextSensorResponse : public ProtoMessage {
 | 
				
			|||||||
  std::string unique_id{};
 | 
					  std::string unique_id{};
 | 
				
			||||||
  std::string icon{};
 | 
					  std::string icon{};
 | 
				
			||||||
  bool disabled_by_default{false};
 | 
					  bool disabled_by_default{false};
 | 
				
			||||||
  enums::EntityCategory entity_category{};
 | 
					 | 
				
			||||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
  void dump_to(std::string &out) const override;
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
@@ -821,8 +803,6 @@ class ListEntitiesCameraResponse : public ProtoMessage {
 | 
				
			|||||||
  std::string name{};
 | 
					  std::string name{};
 | 
				
			||||||
  std::string unique_id{};
 | 
					  std::string unique_id{};
 | 
				
			||||||
  bool disabled_by_default{false};
 | 
					  bool disabled_by_default{false};
 | 
				
			||||||
  std::string icon{};
 | 
					 | 
				
			||||||
  enums::EntityCategory entity_category{};
 | 
					 | 
				
			||||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
  void dump_to(std::string &out) const override;
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
@@ -881,7 +861,6 @@ class ListEntitiesClimateResponse : public ProtoMessage {
 | 
				
			|||||||
  std::vector<std::string> supported_custom_presets{};
 | 
					  std::vector<std::string> supported_custom_presets{};
 | 
				
			||||||
  bool disabled_by_default{false};
 | 
					  bool disabled_by_default{false};
 | 
				
			||||||
  std::string icon{};
 | 
					  std::string icon{};
 | 
				
			||||||
  enums::EntityCategory entity_category{};
 | 
					 | 
				
			||||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
  void dump_to(std::string &out) const override;
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
@@ -961,9 +940,6 @@ class ListEntitiesNumberResponse : public ProtoMessage {
 | 
				
			|||||||
  float max_value{0.0f};
 | 
					  float max_value{0.0f};
 | 
				
			||||||
  float step{0.0f};
 | 
					  float step{0.0f};
 | 
				
			||||||
  bool disabled_by_default{false};
 | 
					  bool disabled_by_default{false};
 | 
				
			||||||
  enums::EntityCategory entity_category{};
 | 
					 | 
				
			||||||
  std::string unit_of_measurement{};
 | 
					 | 
				
			||||||
  enums::NumberMode mode{};
 | 
					 | 
				
			||||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
  void dump_to(std::string &out) const override;
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
@@ -1009,7 +985,6 @@ class ListEntitiesSelectResponse : public ProtoMessage {
 | 
				
			|||||||
  std::string icon{};
 | 
					  std::string icon{};
 | 
				
			||||||
  std::vector<std::string> options{};
 | 
					  std::vector<std::string> options{};
 | 
				
			||||||
  bool disabled_by_default{false};
 | 
					  bool disabled_by_default{false};
 | 
				
			||||||
  enums::EntityCategory entity_category{};
 | 
					 | 
				
			||||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
  void dump_to(std::string &out) const override;
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
@@ -1048,37 +1023,6 @@ class SelectCommandRequest : public ProtoMessage {
 | 
				
			|||||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
					  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
				
			||||||
  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
					  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
class ListEntitiesButtonResponse : public ProtoMessage {
 | 
					 | 
				
			||||||
 public:
 | 
					 | 
				
			||||||
  std::string object_id{};
 | 
					 | 
				
			||||||
  uint32_t key{0};
 | 
					 | 
				
			||||||
  std::string name{};
 | 
					 | 
				
			||||||
  std::string unique_id{};
 | 
					 | 
				
			||||||
  std::string icon{};
 | 
					 | 
				
			||||||
  bool disabled_by_default{false};
 | 
					 | 
				
			||||||
  enums::EntityCategory entity_category{};
 | 
					 | 
				
			||||||
  std::string device_class{};
 | 
					 | 
				
			||||||
  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 ButtonCommandRequest : public ProtoMessage {
 | 
					 | 
				
			||||||
 public:
 | 
					 | 
				
			||||||
  uint32_t key{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;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
}  // namespace api
 | 
					}  // namespace api
 | 
				
			||||||
}  // namespace esphome
 | 
					}  // namespace esphome
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -282,16 +282,6 @@ bool APIServerConnectionBase::send_select_state_response(const SelectStateRespon
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_SELECT
 | 
					#ifdef USE_SELECT
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_BUTTON
 | 
					 | 
				
			||||||
bool APIServerConnectionBase::send_list_entities_button_response(const ListEntitiesButtonResponse &msg) {
 | 
					 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					 | 
				
			||||||
  ESP_LOGVV(TAG, "send_list_entities_button_response: %s", msg.dump().c_str());
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
  return this->send_message_<ListEntitiesButtonResponse>(msg, 61);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#ifdef USE_BUTTON
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) {
 | 
					bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) {
 | 
				
			||||||
  switch (msg_type) {
 | 
					  switch (msg_type) {
 | 
				
			||||||
    case 1: {
 | 
					    case 1: {
 | 
				
			||||||
@@ -523,17 +513,6 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
 | 
				
			|||||||
      ESP_LOGVV(TAG, "on_select_command_request: %s", msg.dump().c_str());
 | 
					      ESP_LOGVV(TAG, "on_select_command_request: %s", msg.dump().c_str());
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
      this->on_select_command_request(msg);
 | 
					      this->on_select_command_request(msg);
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    case 62: {
 | 
					 | 
				
			||||||
#ifdef USE_BUTTON
 | 
					 | 
				
			||||||
      ButtonCommandRequest msg;
 | 
					 | 
				
			||||||
      msg.decode(msg_data, msg_size);
 | 
					 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					 | 
				
			||||||
      ESP_LOGVV(TAG, "on_button_command_request: %s", msg.dump().c_str());
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
      this->on_button_command_request(msg);
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -758,19 +737,6 @@ void APIServerConnection::on_select_command_request(const SelectCommandRequest &
 | 
				
			|||||||
  this->select_command(msg);
 | 
					  this->select_command(msg);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_BUTTON
 | 
					 | 
				
			||||||
void APIServerConnection::on_button_command_request(const ButtonCommandRequest &msg) {
 | 
					 | 
				
			||||||
  if (!this->is_connection_setup()) {
 | 
					 | 
				
			||||||
    this->on_no_setup_connection();
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (!this->is_authenticated()) {
 | 
					 | 
				
			||||||
    this->on_unauthenticated_access();
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  this->button_command(msg);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
}  // namespace api
 | 
					}  // namespace api
 | 
				
			||||||
}  // namespace esphome
 | 
					}  // namespace esphome
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -129,12 +129,6 @@ class APIServerConnectionBase : public ProtoService {
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_SELECT
 | 
					#ifdef USE_SELECT
 | 
				
			||||||
  virtual void on_select_command_request(const SelectCommandRequest &value){};
 | 
					  virtual void on_select_command_request(const SelectCommandRequest &value){};
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#ifdef USE_BUTTON
 | 
					 | 
				
			||||||
  bool send_list_entities_button_response(const ListEntitiesButtonResponse &msg);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#ifdef USE_BUTTON
 | 
					 | 
				
			||||||
  virtual void on_button_command_request(const ButtonCommandRequest &value){};
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 protected:
 | 
					 protected:
 | 
				
			||||||
  bool read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) override;
 | 
					  bool read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) override;
 | 
				
			||||||
@@ -177,9 +171,6 @@ class APIServerConnection : public APIServerConnectionBase {
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_SELECT
 | 
					#ifdef USE_SELECT
 | 
				
			||||||
  virtual void select_command(const SelectCommandRequest &msg) = 0;
 | 
					  virtual void select_command(const SelectCommandRequest &msg) = 0;
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#ifdef USE_BUTTON
 | 
					 | 
				
			||||||
  virtual void button_command(const ButtonCommandRequest &msg) = 0;
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 protected:
 | 
					 protected:
 | 
				
			||||||
  void on_hello_request(const HelloRequest &msg) override;
 | 
					  void on_hello_request(const HelloRequest &msg) override;
 | 
				
			||||||
@@ -218,9 +209,6 @@ class APIServerConnection : public APIServerConnectionBase {
 | 
				
			|||||||
#ifdef USE_SELECT
 | 
					#ifdef USE_SELECT
 | 
				
			||||||
  void on_select_command_request(const SelectCommandRequest &msg) override;
 | 
					  void on_select_command_request(const SelectCommandRequest &msg) override;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_BUTTON
 | 
					 | 
				
			||||||
  void on_button_command_request(const ButtonCommandRequest &msg) override;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}  // namespace api
 | 
					}  // namespace api
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -77,7 +77,7 @@ void APIServer::setup() {
 | 
				
			|||||||
  this->last_connected_ = millis();
 | 
					  this->last_connected_ = millis();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef USE_ESP32_CAMERA
 | 
					#ifdef USE_ESP32_CAMERA
 | 
				
			||||||
  if (esp32_camera::global_esp32_camera != nullptr && !esp32_camera::global_esp32_camera->is_internal()) {
 | 
					  if (esp32_camera::global_esp32_camera != nullptr) {
 | 
				
			||||||
    esp32_camera::global_esp32_camera->add_image_callback(
 | 
					    esp32_camera::global_esp32_camera->add_image_callback(
 | 
				
			||||||
        [this](const std::shared_ptr<esp32_camera::CameraImage> &image) {
 | 
					        [this](const std::shared_ptr<esp32_camera::CameraImage> &image) {
 | 
				
			||||||
          for (auto &c : this->clients_)
 | 
					          for (auto &c : this->clients_)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,6 +23,7 @@ async def async_run_logs(config, address):
 | 
				
			|||||||
    _LOGGER.info("Starting log output from %s using esphome API", address)
 | 
					    _LOGGER.info("Starting log output from %s using esphome API", address)
 | 
				
			||||||
    zc = zeroconf.Zeroconf()
 | 
					    zc = zeroconf.Zeroconf()
 | 
				
			||||||
    cli = APIClient(
 | 
					    cli = APIClient(
 | 
				
			||||||
 | 
					        asyncio.get_event_loop(),
 | 
				
			||||||
        address,
 | 
					        address,
 | 
				
			||||||
        port,
 | 
					        port,
 | 
				
			||||||
        password,
 | 
					        password,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,18 +8,6 @@
 | 
				
			|||||||
namespace esphome {
 | 
					namespace esphome {
 | 
				
			||||||
namespace api {
 | 
					namespace api {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template<typename... X> class TemplatableStringValue : public TemplatableValue<std::string, X...> {
 | 
					 | 
				
			||||||
 public:
 | 
					 | 
				
			||||||
  TemplatableStringValue() : TemplatableValue<std::string, X...>() {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  template<typename F, enable_if_t<!is_callable<F, X...>::value, int> = 0>
 | 
					 | 
				
			||||||
  TemplatableStringValue(F value) : TemplatableValue<std::string, X...>(value) {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  template<typename F, enable_if_t<is_callable<F, X...>::value, int> = 0>
 | 
					 | 
				
			||||||
  TemplatableStringValue(F f)
 | 
					 | 
				
			||||||
      : TemplatableValue<std::string, X...>([f](X... x) -> std::string { return to_string(f(x...)); }) {}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
template<typename... Ts> class TemplatableKeyValuePair {
 | 
					template<typename... Ts> class TemplatableKeyValuePair {
 | 
				
			||||||
 public:
 | 
					 public:
 | 
				
			||||||
  template<typename T> TemplatableKeyValuePair(std::string key, T value) : key(std::move(key)), value(value) {}
 | 
					  template<typename T> TemplatableKeyValuePair(std::string key, T value) : key(std::move(key)), value(value) {}
 | 
				
			||||||
@@ -31,8 +19,7 @@ template<typename... Ts> class HomeAssistantServiceCallAction : public Action<Ts
 | 
				
			|||||||
 public:
 | 
					 public:
 | 
				
			||||||
  explicit HomeAssistantServiceCallAction(APIServer *parent, bool is_event) : parent_(parent), is_event_(is_event) {}
 | 
					  explicit HomeAssistantServiceCallAction(APIServer *parent, bool is_event) : parent_(parent), is_event_(is_event) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  template<typename T> void set_service(T service) { this->service_ = service; }
 | 
					  TEMPLATABLE_STRING_VALUE(service);
 | 
				
			||||||
 | 
					 | 
				
			||||||
  template<typename T> void add_data(std::string key, T value) {
 | 
					  template<typename T> void add_data(std::string key, T value) {
 | 
				
			||||||
    this->data_.push_back(TemplatableKeyValuePair<Ts...>(key, value));
 | 
					    this->data_.push_back(TemplatableKeyValuePair<Ts...>(key, value));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -71,7 +58,6 @@ template<typename... Ts> class HomeAssistantServiceCallAction : public Action<Ts
 | 
				
			|||||||
 protected:
 | 
					 protected:
 | 
				
			||||||
  APIServer *parent_;
 | 
					  APIServer *parent_;
 | 
				
			||||||
  bool is_event_;
 | 
					  bool is_event_;
 | 
				
			||||||
  TemplatableStringValue<Ts...> service_{};
 | 
					 | 
				
			||||||
  std::vector<TemplatableKeyValuePair<Ts...>> data_;
 | 
					  std::vector<TemplatableKeyValuePair<Ts...>> data_;
 | 
				
			||||||
  std::vector<TemplatableKeyValuePair<Ts...>> data_template_;
 | 
					  std::vector<TemplatableKeyValuePair<Ts...>> data_template_;
 | 
				
			||||||
  std::vector<TemplatableKeyValuePair<Ts...>> variables_;
 | 
					  std::vector<TemplatableKeyValuePair<Ts...>> variables_;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,9 +27,6 @@ bool ListEntitiesIterator::on_sensor(sensor::Sensor *sensor) { return this->clie
 | 
				
			|||||||
#ifdef USE_SWITCH
 | 
					#ifdef USE_SWITCH
 | 
				
			||||||
bool ListEntitiesIterator::on_switch(switch_::Switch *a_switch) { return this->client_->send_switch_info(a_switch); }
 | 
					bool ListEntitiesIterator::on_switch(switch_::Switch *a_switch) { return this->client_->send_switch_info(a_switch); }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_BUTTON
 | 
					 | 
				
			||||||
bool ListEntitiesIterator::on_button(button::Button *button) { return this->client_->send_button_info(button); }
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#ifdef USE_TEXT_SENSOR
 | 
					#ifdef USE_TEXT_SENSOR
 | 
				
			||||||
bool ListEntitiesIterator::on_text_sensor(text_sensor::TextSensor *text_sensor) {
 | 
					bool ListEntitiesIterator::on_text_sensor(text_sensor::TextSensor *text_sensor) {
 | 
				
			||||||
  return this->client_->send_text_sensor_info(text_sensor);
 | 
					  return this->client_->send_text_sensor_info(text_sensor);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,9 +30,6 @@ class ListEntitiesIterator : public ComponentIterator {
 | 
				
			|||||||
#ifdef USE_SWITCH
 | 
					#ifdef USE_SWITCH
 | 
				
			||||||
  bool on_switch(switch_::Switch *a_switch) override;
 | 
					  bool on_switch(switch_::Switch *a_switch) override;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_BUTTON
 | 
					 | 
				
			||||||
  bool on_button(button::Button *button) override;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#ifdef USE_TEXT_SENSOR
 | 
					#ifdef USE_TEXT_SENSOR
 | 
				
			||||||
  bool on_text_sensor(text_sensor::TextSensor *text_sensor) override;
 | 
					  bool on_text_sensor(text_sensor::TextSensor *text_sensor) override;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,9 +31,6 @@ class InitialStateIterator : public ComponentIterator {
 | 
				
			|||||||
#ifdef USE_SWITCH
 | 
					#ifdef USE_SWITCH
 | 
				
			||||||
  bool on_switch(switch_::Switch *a_switch) override;
 | 
					  bool on_switch(switch_::Switch *a_switch) override;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_BUTTON
 | 
					 | 
				
			||||||
  bool on_button(button::Button *button) override { return true; };
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#ifdef USE_TEXT_SENSOR
 | 
					#ifdef USE_TEXT_SENSOR
 | 
				
			||||||
  bool on_text_sensor(text_sensor::TextSensor *text_sensor) override;
 | 
					  bool on_text_sensor(text_sensor::TextSensor *text_sensor) override;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -116,21 +116,6 @@ void ComponentIterator::advance() {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_BUTTON
 | 
					 | 
				
			||||||
    case IteratorState::BUTTON:
 | 
					 | 
				
			||||||
      if (this->at_ >= App.get_buttons().size()) {
 | 
					 | 
				
			||||||
        advance_platform = true;
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        auto *button = App.get_buttons()[this->at_];
 | 
					 | 
				
			||||||
        if (button->is_internal()) {
 | 
					 | 
				
			||||||
          success = true;
 | 
					 | 
				
			||||||
          break;
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
          success = this->on_button(button);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#ifdef USE_TEXT_SENSOR
 | 
					#ifdef USE_TEXT_SENSOR
 | 
				
			||||||
    case IteratorState::TEXT_SENSOR:
 | 
					    case IteratorState::TEXT_SENSOR:
 | 
				
			||||||
      if (this->at_ >= App.get_text_sensors().size()) {
 | 
					      if (this->at_ >= App.get_text_sensors().size()) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,9 +38,6 @@ class ComponentIterator {
 | 
				
			|||||||
#ifdef USE_SWITCH
 | 
					#ifdef USE_SWITCH
 | 
				
			||||||
  virtual bool on_switch(switch_::Switch *a_switch) = 0;
 | 
					  virtual bool on_switch(switch_::Switch *a_switch) = 0;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_BUTTON
 | 
					 | 
				
			||||||
  virtual bool on_button(button::Button *button) = 0;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#ifdef USE_TEXT_SENSOR
 | 
					#ifdef USE_TEXT_SENSOR
 | 
				
			||||||
  virtual bool on_text_sensor(text_sensor::TextSensor *text_sensor) = 0;
 | 
					  virtual bool on_text_sensor(text_sensor::TextSensor *text_sensor) = 0;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -81,9 +78,6 @@ class ComponentIterator {
 | 
				
			|||||||
#ifdef USE_SWITCH
 | 
					#ifdef USE_SWITCH
 | 
				
			||||||
    SWITCH,
 | 
					    SWITCH,
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_BUTTON
 | 
					 | 
				
			||||||
    BUTTON,
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#ifdef USE_TEXT_SENSOR
 | 
					#ifdef USE_TEXT_SENSOR
 | 
				
			||||||
    TEXT_SENSOR,
 | 
					    TEXT_SENSOR,
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,6 @@ from esphome.const import (
 | 
				
			|||||||
    DEVICE_CLASS_HUMIDITY,
 | 
					    DEVICE_CLASS_HUMIDITY,
 | 
				
			||||||
    DEVICE_CLASS_TEMPERATURE,
 | 
					    DEVICE_CLASS_TEMPERATURE,
 | 
				
			||||||
    DEVICE_CLASS_VOLTAGE,
 | 
					    DEVICE_CLASS_VOLTAGE,
 | 
				
			||||||
    ENTITY_CATEGORY_DIAGNOSTIC,
 | 
					 | 
				
			||||||
    STATE_CLASS_MEASUREMENT,
 | 
					    STATE_CLASS_MEASUREMENT,
 | 
				
			||||||
    UNIT_CELSIUS,
 | 
					    UNIT_CELSIUS,
 | 
				
			||||||
    UNIT_PERCENT,
 | 
					    UNIT_PERCENT,
 | 
				
			||||||
@@ -50,14 +49,12 @@ CONFIG_SCHEMA = (
 | 
				
			|||||||
                accuracy_decimals=0,
 | 
					                accuracy_decimals=0,
 | 
				
			||||||
                device_class=DEVICE_CLASS_BATTERY,
 | 
					                device_class=DEVICE_CLASS_BATTERY,
 | 
				
			||||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
					                state_class=STATE_CLASS_MEASUREMENT,
 | 
				
			||||||
                entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
 | 
					 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            cv.Optional(CONF_BATTERY_VOLTAGE): sensor.sensor_schema(
 | 
					            cv.Optional(CONF_BATTERY_VOLTAGE): sensor.sensor_schema(
 | 
				
			||||||
                unit_of_measurement=UNIT_VOLT,
 | 
					                unit_of_measurement=UNIT_VOLT,
 | 
				
			||||||
                accuracy_decimals=3,
 | 
					                accuracy_decimals=3,
 | 
				
			||||||
                device_class=DEVICE_CLASS_VOLTAGE,
 | 
					                device_class=DEVICE_CLASS_VOLTAGE,
 | 
				
			||||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
					                state_class=STATE_CLASS_MEASUREMENT,
 | 
				
			||||||
                entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
 | 
					 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,7 +17,6 @@ from esphome.const import (
 | 
				
			|||||||
    DEVICE_CLASS_POWER_FACTOR,
 | 
					    DEVICE_CLASS_POWER_FACTOR,
 | 
				
			||||||
    DEVICE_CLASS_TEMPERATURE,
 | 
					    DEVICE_CLASS_TEMPERATURE,
 | 
				
			||||||
    DEVICE_CLASS_VOLTAGE,
 | 
					    DEVICE_CLASS_VOLTAGE,
 | 
				
			||||||
    ENTITY_CATEGORY_DIAGNOSTIC,
 | 
					 | 
				
			||||||
    ICON_LIGHTBULB,
 | 
					    ICON_LIGHTBULB,
 | 
				
			||||||
    ICON_CURRENT_AC,
 | 
					    ICON_CURRENT_AC,
 | 
				
			||||||
    STATE_CLASS_MEASUREMENT,
 | 
					    STATE_CLASS_MEASUREMENT,
 | 
				
			||||||
@@ -126,7 +125,6 @@ CONFIG_SCHEMA = (
 | 
				
			|||||||
                accuracy_decimals=1,
 | 
					                accuracy_decimals=1,
 | 
				
			||||||
                device_class=DEVICE_CLASS_TEMPERATURE,
 | 
					                device_class=DEVICE_CLASS_TEMPERATURE,
 | 
				
			||||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
					                state_class=STATE_CLASS_MEASUREMENT,
 | 
				
			||||||
                entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
 | 
					 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            cv.Required(CONF_LINE_FREQUENCY): cv.enum(LINE_FREQS, upper=True),
 | 
					            cv.Required(CONF_LINE_FREQUENCY): cv.enum(LINE_FREQS, upper=True),
 | 
				
			||||||
            cv.Optional(CONF_CURRENT_PHASES, default="3"): cv.enum(
 | 
					            cv.Optional(CONF_CURRENT_PHASES, default="3"): cv.enum(
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,7 +13,6 @@ from esphome.const import (
 | 
				
			|||||||
    DEVICE_CLASS_ILLUMINANCE,
 | 
					    DEVICE_CLASS_ILLUMINANCE,
 | 
				
			||||||
    DEVICE_CLASS_TEMPERATURE,
 | 
					    DEVICE_CLASS_TEMPERATURE,
 | 
				
			||||||
    DEVICE_CLASS_VOLTAGE,
 | 
					    DEVICE_CLASS_VOLTAGE,
 | 
				
			||||||
    ENTITY_CATEGORY_DIAGNOSTIC,
 | 
					 | 
				
			||||||
    STATE_CLASS_MEASUREMENT,
 | 
					    STATE_CLASS_MEASUREMENT,
 | 
				
			||||||
    UNIT_CELSIUS,
 | 
					    UNIT_CELSIUS,
 | 
				
			||||||
    UNIT_LUX,
 | 
					    UNIT_LUX,
 | 
				
			||||||
@@ -52,7 +51,6 @@ CONFIG_SCHEMA = (
 | 
				
			|||||||
                accuracy_decimals=3,
 | 
					                accuracy_decimals=3,
 | 
				
			||||||
                device_class=DEVICE_CLASS_VOLTAGE,
 | 
					                device_class=DEVICE_CLASS_VOLTAGE,
 | 
				
			||||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
					                state_class=STATE_CLASS_MEASUREMENT,
 | 
				
			||||||
                entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
 | 
					 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            cv.Optional(CONF_MOISTURE): sensor.sensor_schema(
 | 
					            cv.Optional(CONF_MOISTURE): sensor.sensor_schema(
 | 
				
			||||||
                unit_of_measurement=UNIT_PERCENT,
 | 
					                unit_of_measurement=UNIT_PERCENT,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -79,9 +79,6 @@ void BH1750Sensor::read_data_() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  float lx = float(raw_value) / 1.2f;
 | 
					  float lx = float(raw_value) / 1.2f;
 | 
				
			||||||
  lx *= 69.0f / this->measurement_duration_;
 | 
					  lx *= 69.0f / this->measurement_duration_;
 | 
				
			||||||
  if (this->resolution_ == BH1750_RESOLUTION_0P5_LX) {
 | 
					 | 
				
			||||||
    lx /= 2.0f;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  ESP_LOGD(TAG, "'%s': Got illuminance=%.1flx", this->get_name().c_str(), lx);
 | 
					  ESP_LOGD(TAG, "'%s': Got illuminance=%.1flx", this->get_name().c_str(), lx);
 | 
				
			||||||
  this->publish_state(lx);
 | 
					  this->publish_state(lx);
 | 
				
			||||||
  this->status_clear_warning();
 | 
					  this->status_clear_warning();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -44,11 +44,9 @@ from esphome.const import (
 | 
				
			|||||||
    DEVICE_CLASS_POWER,
 | 
					    DEVICE_CLASS_POWER,
 | 
				
			||||||
    DEVICE_CLASS_PRESENCE,
 | 
					    DEVICE_CLASS_PRESENCE,
 | 
				
			||||||
    DEVICE_CLASS_PROBLEM,
 | 
					    DEVICE_CLASS_PROBLEM,
 | 
				
			||||||
    DEVICE_CLASS_RUNNING,
 | 
					 | 
				
			||||||
    DEVICE_CLASS_SAFETY,
 | 
					    DEVICE_CLASS_SAFETY,
 | 
				
			||||||
    DEVICE_CLASS_SMOKE,
 | 
					    DEVICE_CLASS_SMOKE,
 | 
				
			||||||
    DEVICE_CLASS_SOUND,
 | 
					    DEVICE_CLASS_SOUND,
 | 
				
			||||||
    DEVICE_CLASS_TAMPER,
 | 
					 | 
				
			||||||
    DEVICE_CLASS_UPDATE,
 | 
					    DEVICE_CLASS_UPDATE,
 | 
				
			||||||
    DEVICE_CLASS_VIBRATION,
 | 
					    DEVICE_CLASS_VIBRATION,
 | 
				
			||||||
    DEVICE_CLASS_WINDOW,
 | 
					    DEVICE_CLASS_WINDOW,
 | 
				
			||||||
@@ -78,11 +76,9 @@ DEVICE_CLASSES = [
 | 
				
			|||||||
    DEVICE_CLASS_POWER,
 | 
					    DEVICE_CLASS_POWER,
 | 
				
			||||||
    DEVICE_CLASS_PRESENCE,
 | 
					    DEVICE_CLASS_PRESENCE,
 | 
				
			||||||
    DEVICE_CLASS_PROBLEM,
 | 
					    DEVICE_CLASS_PROBLEM,
 | 
				
			||||||
    DEVICE_CLASS_RUNNING,
 | 
					 | 
				
			||||||
    DEVICE_CLASS_SAFETY,
 | 
					    DEVICE_CLASS_SAFETY,
 | 
				
			||||||
    DEVICE_CLASS_SMOKE,
 | 
					    DEVICE_CLASS_SMOKE,
 | 
				
			||||||
    DEVICE_CLASS_SOUND,
 | 
					    DEVICE_CLASS_SOUND,
 | 
				
			||||||
    DEVICE_CLASS_TAMPER,
 | 
					 | 
				
			||||||
    DEVICE_CLASS_UPDATE,
 | 
					    DEVICE_CLASS_UPDATE,
 | 
				
			||||||
    DEVICE_CLASS_VIBRATION,
 | 
					    DEVICE_CLASS_VIBRATION,
 | 
				
			||||||
    DEVICE_CLASS_WINDOW,
 | 
					    DEVICE_CLASS_WINDOW,
 | 
				
			||||||
@@ -317,7 +313,6 @@ def validate_multi_click_timing(value):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space="_")
 | 
					device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space="_")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
BINARY_SENSOR_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMPONENT_SCHEMA).extend(
 | 
					BINARY_SENSOR_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMPONENT_SCHEMA).extend(
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        cv.GenerateID(): cv.declare_id(BinarySensor),
 | 
					        cv.GenerateID(): cv.declare_id(BinarySensor),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -388,15 +388,6 @@ BLEDescriptor *BLECharacteristic::get_descriptor(uint16_t uuid) {
 | 
				
			|||||||
  return this->get_descriptor(espbt::ESPBTUUID::from_uint16(uuid));
 | 
					  return this->get_descriptor(espbt::ESPBTUUID::from_uint16(uuid));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void BLECharacteristic::write_value(uint8_t *new_val, int16_t new_val_size) {
 | 
					 | 
				
			||||||
  auto client = this->service->client;
 | 
					 | 
				
			||||||
  auto status = esp_ble_gattc_write_char(client->gattc_if, client->conn_id, this->handle, new_val_size, new_val,
 | 
					 | 
				
			||||||
                                         ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
 | 
					 | 
				
			||||||
  if (status) {
 | 
					 | 
				
			||||||
    ESP_LOGW(TAG, "Error sending write value to BLE gattc server, status=%d", status);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}  // namespace ble_client
 | 
					}  // namespace ble_client
 | 
				
			||||||
}  // namespace esphome
 | 
					}  // namespace esphome
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -59,7 +59,7 @@ class BLECharacteristic {
 | 
				
			|||||||
  void parse_descriptors();
 | 
					  void parse_descriptors();
 | 
				
			||||||
  BLEDescriptor *get_descriptor(espbt::ESPBTUUID uuid);
 | 
					  BLEDescriptor *get_descriptor(espbt::ESPBTUUID uuid);
 | 
				
			||||||
  BLEDescriptor *get_descriptor(uint16_t uuid);
 | 
					  BLEDescriptor *get_descriptor(uint16_t uuid);
 | 
				
			||||||
  void write_value(uint8_t *new_val, int16_t new_val_size);
 | 
					
 | 
				
			||||||
  BLEService *service;
 | 
					  BLEService *service;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,67 +0,0 @@
 | 
				
			|||||||
import esphome.codegen as cg
 | 
					 | 
				
			||||||
import esphome.config_validation as cv
 | 
					 | 
				
			||||||
from esphome.components import output, ble_client, esp32_ble_tracker
 | 
					 | 
				
			||||||
from esphome.const import CONF_ID, CONF_SERVICE_UUID
 | 
					 | 
				
			||||||
from .. import ble_client_ns
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
DEPENDENCIES = ["ble_client"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CONF_CHARACTERISTIC_UUID = "characteristic_uuid"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BLEBinaryOutput = ble_client_ns.class_(
 | 
					 | 
				
			||||||
    "BLEBinaryOutput", output.BinaryOutput, ble_client.BLEClientNode, cg.Component
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CONFIG_SCHEMA = cv.All(
 | 
					 | 
				
			||||||
    output.BINARY_OUTPUT_SCHEMA.extend(
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            cv.Required(CONF_ID): cv.declare_id(BLEBinaryOutput),
 | 
					 | 
				
			||||||
            cv.Required(CONF_SERVICE_UUID): esp32_ble_tracker.bt_uuid,
 | 
					 | 
				
			||||||
            cv.Required(CONF_CHARACTERISTIC_UUID): esp32_ble_tracker.bt_uuid,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    .extend(cv.COMPONENT_SCHEMA)
 | 
					 | 
				
			||||||
    .extend(ble_client.BLE_CLIENT_SCHEMA)
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def to_code(config):
 | 
					 | 
				
			||||||
    var = cg.new_Pvariable(config[CONF_ID])
 | 
					 | 
				
			||||||
    if len(config[CONF_SERVICE_UUID]) == len(esp32_ble_tracker.bt_uuid16_format):
 | 
					 | 
				
			||||||
        cg.add(
 | 
					 | 
				
			||||||
            var.set_service_uuid16(esp32_ble_tracker.as_hex(config[CONF_SERVICE_UUID]))
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
    elif len(config[CONF_SERVICE_UUID]) == len(esp32_ble_tracker.bt_uuid32_format):
 | 
					 | 
				
			||||||
        cg.add(
 | 
					 | 
				
			||||||
            var.set_service_uuid32(esp32_ble_tracker.as_hex(config[CONF_SERVICE_UUID]))
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
    elif len(config[CONF_SERVICE_UUID]) == len(esp32_ble_tracker.bt_uuid128_format):
 | 
					 | 
				
			||||||
        uuid128 = esp32_ble_tracker.as_reversed_hex_array(config[CONF_SERVICE_UUID])
 | 
					 | 
				
			||||||
        cg.add(var.set_service_uuid128(uuid128))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if len(config[CONF_CHARACTERISTIC_UUID]) == len(esp32_ble_tracker.bt_uuid16_format):
 | 
					 | 
				
			||||||
        cg.add(
 | 
					 | 
				
			||||||
            var.set_char_uuid16(
 | 
					 | 
				
			||||||
                esp32_ble_tracker.as_hex(config[CONF_CHARACTERISTIC_UUID])
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
    elif len(config[CONF_CHARACTERISTIC_UUID]) == len(
 | 
					 | 
				
			||||||
        esp32_ble_tracker.bt_uuid32_format
 | 
					 | 
				
			||||||
    ):
 | 
					 | 
				
			||||||
        cg.add(
 | 
					 | 
				
			||||||
            var.set_char_uuid32(
 | 
					 | 
				
			||||||
                esp32_ble_tracker.as_hex(config[CONF_CHARACTERISTIC_UUID])
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
    elif len(config[CONF_CHARACTERISTIC_UUID]) == len(
 | 
					 | 
				
			||||||
        esp32_ble_tracker.bt_uuid128_format
 | 
					 | 
				
			||||||
    ):
 | 
					 | 
				
			||||||
        uuid128 = esp32_ble_tracker.as_reversed_hex_array(
 | 
					 | 
				
			||||||
            config[CONF_CHARACTERISTIC_UUID]
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        cg.add(var.set_char_uuid128(uuid128))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    yield output.register_output(var, config)
 | 
					 | 
				
			||||||
    yield ble_client.register_ble_node(var, config)
 | 
					 | 
				
			||||||
    yield cg.register_component(var, config)
 | 
					 | 
				
			||||||
@@ -1,71 +0,0 @@
 | 
				
			|||||||
#include "ble_binary_output.h"
 | 
					 | 
				
			||||||
#include "esphome/core/log.h"
 | 
					 | 
				
			||||||
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef USE_ESP32
 | 
					 | 
				
			||||||
namespace esphome {
 | 
					 | 
				
			||||||
namespace ble_client {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const char *const TAG = "ble_binary_output";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void BLEBinaryOutput::dump_config() {
 | 
					 | 
				
			||||||
  ESP_LOGCONFIG(TAG, "BLE Binary Output:");
 | 
					 | 
				
			||||||
  ESP_LOGCONFIG(TAG, "  MAC address        : %s", this->parent_->address_str().c_str());
 | 
					 | 
				
			||||||
  ESP_LOGCONFIG(TAG, "  Service UUID       : %s", this->service_uuid_.to_string().c_str());
 | 
					 | 
				
			||||||
  ESP_LOGCONFIG(TAG, "  Characteristic UUID: %s", this->char_uuid_.to_string().c_str());
 | 
					 | 
				
			||||||
  LOG_BINARY_OUTPUT(this);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void BLEBinaryOutput::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->client_state_ = espbt::ClientState::ESTABLISHED;
 | 
					 | 
				
			||||||
      ESP_LOGW(TAG, "[%s] Connected successfully!", this->char_uuid_.to_string().c_str());
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
    case ESP_GATTC_DISCONNECT_EVT:
 | 
					 | 
				
			||||||
      ESP_LOGW(TAG, "[%s] Disconnected", this->char_uuid_.to_string().c_str());
 | 
					 | 
				
			||||||
      this->client_state_ = espbt::ClientState::IDLE;
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
    case ESP_GATTC_WRITE_CHAR_EVT: {
 | 
					 | 
				
			||||||
      if (param->write.status == 0) {
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      auto chr = this->parent()->get_characteristic(this->service_uuid_, this->char_uuid_);
 | 
					 | 
				
			||||||
      if (chr == nullptr) {
 | 
					 | 
				
			||||||
        ESP_LOGW(TAG, "[%s] Characteristic not found.", this->char_uuid_.to_string().c_str());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      if (param->write.handle == chr->handle) {
 | 
					 | 
				
			||||||
        ESP_LOGW(TAG, "[%s] Write error, status=%d", this->char_uuid_.to_string().c_str(), param->write.status);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    default:
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void BLEBinaryOutput::write_state(bool state) {
 | 
					 | 
				
			||||||
  if (this->client_state_ != espbt::ClientState::ESTABLISHED) {
 | 
					 | 
				
			||||||
    ESP_LOGW(TAG, "[%s] Not connected to BLE client.  State update can not be written.",
 | 
					 | 
				
			||||||
             this->char_uuid_.to_string().c_str());
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  auto chr = this->parent()->get_characteristic(this->service_uuid_, this->char_uuid_);
 | 
					 | 
				
			||||||
  if (chr == nullptr) {
 | 
					 | 
				
			||||||
    ESP_LOGW(TAG, "[%s] Characteristic not found.  State update can not be written.",
 | 
					 | 
				
			||||||
             this->char_uuid_.to_string().c_str());
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  uint8_t state_as_uint = (uint8_t) state;
 | 
					 | 
				
			||||||
  ESP_LOGV(TAG, "[%s] Write State: %d", this->char_uuid_.to_string().c_str(), state_as_uint);
 | 
					 | 
				
			||||||
  chr->write_value(&state_as_uint, sizeof(state_as_uint));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}  // namespace ble_client
 | 
					 | 
				
			||||||
}  // namespace esphome
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
@@ -1,39 +0,0 @@
 | 
				
			|||||||
#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/output/binary_output.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef USE_ESP32
 | 
					 | 
				
			||||||
#include <esp_gattc_api.h>
 | 
					 | 
				
			||||||
namespace esphome {
 | 
					 | 
				
			||||||
namespace ble_client {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace espbt = esphome::esp32_ble_tracker;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class BLEBinaryOutput : public output::BinaryOutput, public BLEClientNode, public Component {
 | 
					 | 
				
			||||||
 public:
 | 
					 | 
				
			||||||
  void dump_config() override;
 | 
					 | 
				
			||||||
  void loop() override {}
 | 
					 | 
				
			||||||
  float get_setup_priority() const override { return setup_priority::DATA; }
 | 
					 | 
				
			||||||
  void set_service_uuid16(uint16_t uuid) { this->service_uuid_ = espbt::ESPBTUUID::from_uint16(uuid); }
 | 
					 | 
				
			||||||
  void set_service_uuid32(uint32_t uuid) { this->service_uuid_ = espbt::ESPBTUUID::from_uint32(uuid); }
 | 
					 | 
				
			||||||
  void set_service_uuid128(uint8_t *uuid) { this->service_uuid_ = espbt::ESPBTUUID::from_raw(uuid); }
 | 
					 | 
				
			||||||
  void set_char_uuid16(uint16_t uuid) { this->char_uuid_ = espbt::ESPBTUUID::from_uint16(uuid); }
 | 
					 | 
				
			||||||
  void set_char_uuid32(uint32_t uuid) { this->char_uuid_ = espbt::ESPBTUUID::from_uint32(uuid); }
 | 
					 | 
				
			||||||
  void set_char_uuid128(uint8_t *uuid) { this->char_uuid_ = espbt::ESPBTUUID::from_raw(uuid); }
 | 
					 | 
				
			||||||
  void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
 | 
					 | 
				
			||||||
                           esp_ble_gattc_cb_param_t *param) override;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 protected:
 | 
					 | 
				
			||||||
  void write_state(bool state) override;
 | 
					 | 
				
			||||||
  espbt::ESPBTUUID service_uuid_;
 | 
					 | 
				
			||||||
  espbt::ESPBTUUID char_uuid_;
 | 
					 | 
				
			||||||
  espbt::ClientState client_state_;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}  // namespace ble_client
 | 
					 | 
				
			||||||
}  // namespace esphome
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
@@ -67,7 +67,7 @@ async def to_code(config):
 | 
				
			|||||||
            var.set_service_uuid32(esp32_ble_tracker.as_hex(config[CONF_SERVICE_UUID]))
 | 
					            var.set_service_uuid32(esp32_ble_tracker.as_hex(config[CONF_SERVICE_UUID]))
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
    elif len(config[CONF_SERVICE_UUID]) == len(esp32_ble_tracker.bt_uuid128_format):
 | 
					    elif len(config[CONF_SERVICE_UUID]) == len(esp32_ble_tracker.bt_uuid128_format):
 | 
				
			||||||
        uuid128 = esp32_ble_tracker.as_reversed_hex_array(config[CONF_SERVICE_UUID])
 | 
					        uuid128 = esp32_ble_tracker.as_hex_array(config[CONF_SERVICE_UUID])
 | 
				
			||||||
        cg.add(var.set_service_uuid128(uuid128))
 | 
					        cg.add(var.set_service_uuid128(uuid128))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if len(config[CONF_CHARACTERISTIC_UUID]) == len(esp32_ble_tracker.bt_uuid16_format):
 | 
					    if len(config[CONF_CHARACTERISTIC_UUID]) == len(esp32_ble_tracker.bt_uuid16_format):
 | 
				
			||||||
@@ -87,9 +87,7 @@ async def to_code(config):
 | 
				
			|||||||
    elif len(config[CONF_CHARACTERISTIC_UUID]) == len(
 | 
					    elif len(config[CONF_CHARACTERISTIC_UUID]) == len(
 | 
				
			||||||
        esp32_ble_tracker.bt_uuid128_format
 | 
					        esp32_ble_tracker.bt_uuid128_format
 | 
				
			||||||
    ):
 | 
					    ):
 | 
				
			||||||
        uuid128 = esp32_ble_tracker.as_reversed_hex_array(
 | 
					        uuid128 = esp32_ble_tracker.as_hex_array(config[CONF_CHARACTERISTIC_UUID])
 | 
				
			||||||
            config[CONF_CHARACTERISTIC_UUID]
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        cg.add(var.set_char_uuid128(uuid128))
 | 
					        cg.add(var.set_char_uuid128(uuid128))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if CONF_DESCRIPTOR_UUID in config:
 | 
					    if CONF_DESCRIPTOR_UUID in config:
 | 
				
			||||||
@@ -110,9 +108,7 @@ async def to_code(config):
 | 
				
			|||||||
        elif len(config[CONF_DESCRIPTOR_UUID]) == len(
 | 
					        elif len(config[CONF_DESCRIPTOR_UUID]) == len(
 | 
				
			||||||
            esp32_ble_tracker.bt_uuid128_format
 | 
					            esp32_ble_tracker.bt_uuid128_format
 | 
				
			||||||
        ):
 | 
					        ):
 | 
				
			||||||
            uuid128 = esp32_ble_tracker.as_reversed_hex_array(
 | 
					            uuid128 = esp32_ble_tracker.as_hex_array(config[CONF_DESCRIPTOR_UUID])
 | 
				
			||||||
                config[CONF_DESCRIPTOR_UUID]
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
            cg.add(var.set_descr_uuid128(uuid128))
 | 
					            cg.add(var.set_descr_uuid128(uuid128))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if CONF_LAMBDA in config:
 | 
					    if CONF_LAMBDA in config:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,7 +33,6 @@ static const uint8_t BME280_REGISTER_CONTROLHUMID = 0xF2;
 | 
				
			|||||||
static const uint8_t BME280_REGISTER_STATUS = 0xF3;
 | 
					static const uint8_t BME280_REGISTER_STATUS = 0xF3;
 | 
				
			||||||
static const uint8_t BME280_REGISTER_CONTROL = 0xF4;
 | 
					static const uint8_t BME280_REGISTER_CONTROL = 0xF4;
 | 
				
			||||||
static const uint8_t BME280_REGISTER_CONFIG = 0xF5;
 | 
					static const uint8_t BME280_REGISTER_CONFIG = 0xF5;
 | 
				
			||||||
static const uint8_t BME280_REGISTER_MEASUREMENTS = 0xF7;
 | 
					 | 
				
			||||||
static const uint8_t BME280_REGISTER_PRESSUREDATA = 0xF7;
 | 
					static const uint8_t BME280_REGISTER_PRESSUREDATA = 0xF7;
 | 
				
			||||||
static const uint8_t BME280_REGISTER_TEMPDATA = 0xFA;
 | 
					static const uint8_t BME280_REGISTER_TEMPDATA = 0xFA;
 | 
				
			||||||
static const uint8_t BME280_REGISTER_HUMIDDATA = 0xFD;
 | 
					static const uint8_t BME280_REGISTER_HUMIDDATA = 0xFD;
 | 
				
			||||||
@@ -179,29 +178,23 @@ void BME280Component::update() {
 | 
				
			|||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  float meas_time = 1.5f;
 | 
					  float meas_time = 1.5;
 | 
				
			||||||
  meas_time += 2.3f * oversampling_to_time(this->temperature_oversampling_);
 | 
					  meas_time += 2.3f * oversampling_to_time(this->temperature_oversampling_);
 | 
				
			||||||
  meas_time += 2.3f * oversampling_to_time(this->pressure_oversampling_) + 0.575f;
 | 
					  meas_time += 2.3f * oversampling_to_time(this->pressure_oversampling_) + 0.575f;
 | 
				
			||||||
  meas_time += 2.3f * oversampling_to_time(this->humidity_oversampling_) + 0.575f;
 | 
					  meas_time += 2.3f * oversampling_to_time(this->humidity_oversampling_) + 0.575f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  this->set_timeout("data", uint32_t(ceilf(meas_time)), [this]() {
 | 
					  this->set_timeout("data", uint32_t(ceilf(meas_time)), [this]() {
 | 
				
			||||||
    uint8_t data[8];
 | 
					 | 
				
			||||||
    if (!this->read_bytes(BME280_REGISTER_MEASUREMENTS, data, 8)) {
 | 
					 | 
				
			||||||
      ESP_LOGW(TAG, "Error reading registers.");
 | 
					 | 
				
			||||||
      this->status_set_warning();
 | 
					 | 
				
			||||||
      return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    int32_t t_fine = 0;
 | 
					    int32_t t_fine = 0;
 | 
				
			||||||
    float temperature = this->read_temperature_(data, &t_fine);
 | 
					    float temperature = this->read_temperature_(&t_fine);
 | 
				
			||||||
    if (std::isnan(temperature)) {
 | 
					    if (std::isnan(temperature)) {
 | 
				
			||||||
      ESP_LOGW(TAG, "Invalid temperature, cannot read pressure & humidity values.");
 | 
					      ESP_LOGW(TAG, "Invalid temperature, cannot read pressure & humidity values.");
 | 
				
			||||||
      this->status_set_warning();
 | 
					      this->status_set_warning();
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    float pressure = this->read_pressure_(data, t_fine);
 | 
					    float pressure = this->read_pressure_(t_fine);
 | 
				
			||||||
    float humidity = this->read_humidity_(data, t_fine);
 | 
					    float humidity = this->read_humidity_(t_fine);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ESP_LOGV(TAG, "Got temperature=%.1f°C pressure=%.1fhPa humidity=%.1f%%", temperature, pressure, humidity);
 | 
					    ESP_LOGD(TAG, "Got temperature=%.1f°C pressure=%.1fhPa humidity=%.1f%%", temperature, pressure, humidity);
 | 
				
			||||||
    if (this->temperature_sensor_ != nullptr)
 | 
					    if (this->temperature_sensor_ != nullptr)
 | 
				
			||||||
      this->temperature_sensor_->publish_state(temperature);
 | 
					      this->temperature_sensor_->publish_state(temperature);
 | 
				
			||||||
    if (this->pressure_sensor_ != nullptr)
 | 
					    if (this->pressure_sensor_ != nullptr)
 | 
				
			||||||
@@ -211,8 +204,11 @@ void BME280Component::update() {
 | 
				
			|||||||
    this->status_clear_warning();
 | 
					    this->status_clear_warning();
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
float BME280Component::read_temperature_(const uint8_t *data, int32_t *t_fine) {
 | 
					float BME280Component::read_temperature_(int32_t *t_fine) {
 | 
				
			||||||
  int32_t adc = ((data[3] & 0xFF) << 16) | ((data[4] & 0xFF) << 8) | (data[5] & 0xFF);
 | 
					  uint8_t data[3];
 | 
				
			||||||
 | 
					  if (!this->read_bytes(BME280_REGISTER_TEMPDATA, data, 3))
 | 
				
			||||||
 | 
					    return NAN;
 | 
				
			||||||
 | 
					  int32_t adc = ((data[0] & 0xFF) << 16) | ((data[1] & 0xFF) << 8) | (data[2] & 0xFF);
 | 
				
			||||||
  adc >>= 4;
 | 
					  adc >>= 4;
 | 
				
			||||||
  if (adc == 0x80000)
 | 
					  if (adc == 0x80000)
 | 
				
			||||||
    // temperature was disabled
 | 
					    // temperature was disabled
 | 
				
			||||||
@@ -230,7 +226,10 @@ float BME280Component::read_temperature_(const uint8_t *data, int32_t *t_fine) {
 | 
				
			|||||||
  return temperature / 100.0f;
 | 
					  return temperature / 100.0f;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
float BME280Component::read_pressure_(const uint8_t *data, int32_t t_fine) {
 | 
					float BME280Component::read_pressure_(int32_t t_fine) {
 | 
				
			||||||
 | 
					  uint8_t data[3];
 | 
				
			||||||
 | 
					  if (!this->read_bytes(BME280_REGISTER_PRESSUREDATA, data, 3))
 | 
				
			||||||
 | 
					    return NAN;
 | 
				
			||||||
  int32_t adc = ((data[0] & 0xFF) << 16) | ((data[1] & 0xFF) << 8) | (data[2] & 0xFF);
 | 
					  int32_t adc = ((data[0] & 0xFF) << 16) | ((data[1] & 0xFF) << 8) | (data[2] & 0xFF);
 | 
				
			||||||
  adc >>= 4;
 | 
					  adc >>= 4;
 | 
				
			||||||
  if (adc == 0x80000)
 | 
					  if (adc == 0x80000)
 | 
				
			||||||
@@ -266,9 +265,9 @@ float BME280Component::read_pressure_(const uint8_t *data, int32_t t_fine) {
 | 
				
			|||||||
  return (p / 256.0f) / 100.0f;
 | 
					  return (p / 256.0f) / 100.0f;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
float BME280Component::read_humidity_(const uint8_t *data, int32_t t_fine) {
 | 
					float BME280Component::read_humidity_(int32_t t_fine) {
 | 
				
			||||||
  uint16_t raw_adc = ((data[6] & 0xFF) << 8) | (data[7] & 0xFF);
 | 
					  uint16_t raw_adc;
 | 
				
			||||||
  if (raw_adc == 0x8000)
 | 
					  if (!this->read_byte_16(BME280_REGISTER_HUMIDDATA, &raw_adc) || raw_adc == 0x8000)
 | 
				
			||||||
    return NAN;
 | 
					    return NAN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  int32_t adc = raw_adc;
 | 
					  int32_t adc = raw_adc;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -82,11 +82,11 @@ class BME280Component : public PollingComponent, public i2c::I2CDevice {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 protected:
 | 
					 protected:
 | 
				
			||||||
  /// Read the temperature value and store the calculated ambient temperature in t_fine.
 | 
					  /// Read the temperature value and store the calculated ambient temperature in t_fine.
 | 
				
			||||||
  float read_temperature_(const uint8_t *data, int32_t *t_fine);
 | 
					  float read_temperature_(int32_t *t_fine);
 | 
				
			||||||
  /// Read the pressure value in hPa using the provided t_fine value.
 | 
					  /// Read the pressure value in hPa using the provided t_fine value.
 | 
				
			||||||
  float read_pressure_(const uint8_t *data, int32_t t_fine);
 | 
					  float read_pressure_(int32_t t_fine);
 | 
				
			||||||
  /// Read the humidity value in % using the provided t_fine value.
 | 
					  /// Read the humidity value in % using the provided t_fine value.
 | 
				
			||||||
  float read_humidity_(const uint8_t *data, int32_t t_fine);
 | 
					  float read_humidity_(int32_t t_fine);
 | 
				
			||||||
  uint8_t read_u8_(uint8_t a_register);
 | 
					  uint8_t read_u8_(uint8_t a_register);
 | 
				
			||||||
  uint16_t read_u16_le_(uint8_t a_register);
 | 
					  uint16_t read_u16_le_(uint8_t a_register);
 | 
				
			||||||
  int16_t read_s16_le_(uint8_t a_register);
 | 
					  int16_t read_s16_le_(uint8_t a_register);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@ import esphome.codegen as cg
 | 
				
			|||||||
import esphome.config_validation as cv
 | 
					import esphome.config_validation as cv
 | 
				
			||||||
from esphome.components import i2c
 | 
					from esphome.components import i2c
 | 
				
			||||||
from esphome.const import CONF_ID
 | 
					from esphome.const import CONF_ID
 | 
				
			||||||
 | 
					from esphome.core import CORE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CODEOWNERS = ["@trvrnrth"]
 | 
					CODEOWNERS = ["@trvrnrth"]
 | 
				
			||||||
DEPENDENCIES = ["i2c"]
 | 
					DEPENDENCIES = ["i2c"]
 | 
				
			||||||
@@ -61,8 +62,9 @@ async def to_code(config):
 | 
				
			|||||||
        var.set_state_save_interval(config[CONF_STATE_SAVE_INTERVAL].total_milliseconds)
 | 
					        var.set_state_save_interval(config[CONF_STATE_SAVE_INTERVAL].total_milliseconds)
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Although this component does not use SPI, the BSEC library requires the SPI library
 | 
					    if CORE.is_esp32:
 | 
				
			||||||
    cg.add_library("SPI", None)
 | 
					        # Although this component does not use SPI, the BSEC library requires the SPI library
 | 
				
			||||||
 | 
					        cg.add_library("SPI", None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cg.add_define("USE_BSEC")
 | 
					    cg.add_define("USE_BSEC")
 | 
				
			||||||
    cg.add_library("boschsensortec/BSEC Software Library", "1.6.1480")
 | 
					    cg.add_library("boschsensortec/BSEC Software Library", "1.6.1480")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,127 +0,0 @@
 | 
				
			|||||||
import esphome.codegen as cg
 | 
					 | 
				
			||||||
import esphome.config_validation as cv
 | 
					 | 
				
			||||||
from esphome import automation
 | 
					 | 
				
			||||||
from esphome.automation import maybe_simple_id
 | 
					 | 
				
			||||||
from esphome.components import mqtt
 | 
					 | 
				
			||||||
from esphome.const import (
 | 
					 | 
				
			||||||
    CONF_DEVICE_CLASS,
 | 
					 | 
				
			||||||
    CONF_ENTITY_CATEGORY,
 | 
					 | 
				
			||||||
    CONF_ICON,
 | 
					 | 
				
			||||||
    CONF_ID,
 | 
					 | 
				
			||||||
    CONF_ON_PRESS,
 | 
					 | 
				
			||||||
    CONF_TRIGGER_ID,
 | 
					 | 
				
			||||||
    CONF_MQTT_ID,
 | 
					 | 
				
			||||||
    DEVICE_CLASS_RESTART,
 | 
					 | 
				
			||||||
    DEVICE_CLASS_UPDATE,
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
from esphome.core import CORE, coroutine_with_priority
 | 
					 | 
				
			||||||
from esphome.cpp_helpers import setup_entity
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CODEOWNERS = ["@esphome/core"]
 | 
					 | 
				
			||||||
IS_PLATFORM_COMPONENT = True
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
DEVICE_CLASSES = [
 | 
					 | 
				
			||||||
    DEVICE_CLASS_RESTART,
 | 
					 | 
				
			||||||
    DEVICE_CLASS_UPDATE,
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
button_ns = cg.esphome_ns.namespace("button")
 | 
					 | 
				
			||||||
Button = button_ns.class_("Button", cg.EntityBase)
 | 
					 | 
				
			||||||
ButtonPtr = Button.operator("ptr")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
PressAction = button_ns.class_("PressAction", automation.Action)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ButtonPressTrigger = button_ns.class_(
 | 
					 | 
				
			||||||
    "ButtonPressTrigger", automation.Trigger.template()
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
validate_device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space="_")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BUTTON_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).extend(
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTButtonComponent),
 | 
					 | 
				
			||||||
        cv.Optional(CONF_DEVICE_CLASS): validate_device_class,
 | 
					 | 
				
			||||||
        cv.Optional(CONF_ON_PRESS): automation.validate_automation(
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ButtonPressTrigger),
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
_UNDEF = object()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def button_schema(
 | 
					 | 
				
			||||||
    icon: str = _UNDEF,
 | 
					 | 
				
			||||||
    entity_category: str = _UNDEF,
 | 
					 | 
				
			||||||
    device_class: str = _UNDEF,
 | 
					 | 
				
			||||||
) -> cv.Schema:
 | 
					 | 
				
			||||||
    schema = BUTTON_SCHEMA
 | 
					 | 
				
			||||||
    if icon is not _UNDEF:
 | 
					 | 
				
			||||||
        schema = schema.extend({cv.Optional(CONF_ICON, default=icon): cv.icon})
 | 
					 | 
				
			||||||
    if entity_category is not _UNDEF:
 | 
					 | 
				
			||||||
        schema = schema.extend(
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                cv.Optional(
 | 
					 | 
				
			||||||
                    CONF_ENTITY_CATEGORY, default=entity_category
 | 
					 | 
				
			||||||
                ): cv.entity_category
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
    if device_class is not _UNDEF:
 | 
					 | 
				
			||||||
        schema = schema.extend(
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                cv.Optional(
 | 
					 | 
				
			||||||
                    CONF_DEVICE_CLASS, default=device_class
 | 
					 | 
				
			||||||
                ): validate_device_class
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
    return schema
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
async def setup_button_core_(var, config):
 | 
					 | 
				
			||||||
    await setup_entity(var, config)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for conf in config.get(CONF_ON_PRESS, []):
 | 
					 | 
				
			||||||
        trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
 | 
					 | 
				
			||||||
        await automation.build_automation(trigger, [], conf)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if CONF_DEVICE_CLASS in config:
 | 
					 | 
				
			||||||
        cg.add(var.set_device_class(config[CONF_DEVICE_CLASS]))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if CONF_MQTT_ID in config:
 | 
					 | 
				
			||||||
        mqtt_ = cg.new_Pvariable(config[CONF_MQTT_ID], var)
 | 
					 | 
				
			||||||
        await mqtt.register_mqtt_component(mqtt_, config)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
async def register_button(var, config):
 | 
					 | 
				
			||||||
    if not CORE.has_id(config[CONF_ID]):
 | 
					 | 
				
			||||||
        var = cg.Pvariable(config[CONF_ID], var)
 | 
					 | 
				
			||||||
    cg.add(cg.App.register_button(var))
 | 
					 | 
				
			||||||
    await setup_button_core_(var, config)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
async def new_button(config):
 | 
					 | 
				
			||||||
    var = cg.new_Pvariable(config[CONF_ID])
 | 
					 | 
				
			||||||
    await register_button(var, config)
 | 
					 | 
				
			||||||
    return var
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BUTTON_PRESS_SCHEMA = maybe_simple_id(
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        cv.Required(CONF_ID): cv.use_id(Button),
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@automation.register_action("button.press", PressAction, BUTTON_PRESS_SCHEMA)
 | 
					 | 
				
			||||||
async def button_press_to_code(config, action_id, template_arg, args):
 | 
					 | 
				
			||||||
    paren = await cg.get_variable(config[CONF_ID])
 | 
					 | 
				
			||||||
    return cg.new_Pvariable(action_id, template_arg, paren)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@coroutine_with_priority(100.0)
 | 
					 | 
				
			||||||
async def to_code(config):
 | 
					 | 
				
			||||||
    cg.add_global(button_ns.using)
 | 
					 | 
				
			||||||
    cg.add_define("USE_BUTTON")
 | 
					 | 
				
			||||||
@@ -1,28 +0,0 @@
 | 
				
			|||||||
#pragma once
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "esphome/components/button/button.h"
 | 
					 | 
				
			||||||
#include "esphome/core/automation.h"
 | 
					 | 
				
			||||||
#include "esphome/core/component.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace esphome {
 | 
					 | 
				
			||||||
namespace button {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
template<typename... Ts> class PressAction : public Action<Ts...> {
 | 
					 | 
				
			||||||
 public:
 | 
					 | 
				
			||||||
  explicit PressAction(Button *button) : button_(button) {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  void play(Ts... x) override { this->button_->press(); }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 protected:
 | 
					 | 
				
			||||||
  Button *button_;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class ButtonPressTrigger : public Trigger<> {
 | 
					 | 
				
			||||||
 public:
 | 
					 | 
				
			||||||
  ButtonPressTrigger(Button *button) {
 | 
					 | 
				
			||||||
    button->add_on_press_callback([this]() { this->trigger(); });
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}  // namespace button
 | 
					 | 
				
			||||||
}  // namespace esphome
 | 
					 | 
				
			||||||
@@ -1,28 +0,0 @@
 | 
				
			|||||||
#include "button.h"
 | 
					 | 
				
			||||||
#include "esphome/core/log.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace esphome {
 | 
					 | 
				
			||||||
namespace button {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const char *const TAG = "button";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Button::Button(const std::string &name) : EntityBase(name) {}
 | 
					 | 
				
			||||||
Button::Button() : Button("") {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void Button::press() {
 | 
					 | 
				
			||||||
  ESP_LOGD(TAG, "'%s' Pressed.", this->get_name().c_str());
 | 
					 | 
				
			||||||
  this->press_action();
 | 
					 | 
				
			||||||
  this->press_callback_.call();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
void Button::add_on_press_callback(std::function<void()> &&callback) { this->press_callback_.add(std::move(callback)); }
 | 
					 | 
				
			||||||
uint32_t Button::hash_base() { return 1495763804UL; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void Button::set_device_class(const std::string &device_class) { this->device_class_ = device_class; }
 | 
					 | 
				
			||||||
std::string Button::get_device_class() {
 | 
					 | 
				
			||||||
  if (this->device_class_.has_value())
 | 
					 | 
				
			||||||
    return *this->device_class_;
 | 
					 | 
				
			||||||
  return "";
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}  // namespace button
 | 
					 | 
				
			||||||
}  // namespace esphome
 | 
					 | 
				
			||||||
@@ -1,57 +0,0 @@
 | 
				
			|||||||
#pragma once
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "esphome/core/component.h"
 | 
					 | 
				
			||||||
#include "esphome/core/entity_base.h"
 | 
					 | 
				
			||||||
#include "esphome/core/helpers.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace esphome {
 | 
					 | 
				
			||||||
namespace button {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define LOG_BUTTON(prefix, type, obj) \
 | 
					 | 
				
			||||||
  if ((obj) != nullptr) { \
 | 
					 | 
				
			||||||
    ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \
 | 
					 | 
				
			||||||
    if (!(obj)->get_icon().empty()) { \
 | 
					 | 
				
			||||||
      ESP_LOGCONFIG(TAG, "%s  Icon: '%s'", prefix, (obj)->get_icon().c_str()); \
 | 
					 | 
				
			||||||
    } \
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** Base class for all buttons.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * A button is just a momentary switch that does not have a state, only a trigger.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
class Button : public EntityBase {
 | 
					 | 
				
			||||||
 public:
 | 
					 | 
				
			||||||
  explicit Button();
 | 
					 | 
				
			||||||
  explicit Button(const std::string &name);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /** Press this button. This is called by the front-end.
 | 
					 | 
				
			||||||
   *
 | 
					 | 
				
			||||||
   * For implementing buttons, please override press_action.
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  void press();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /** Set callback for state changes.
 | 
					 | 
				
			||||||
   *
 | 
					 | 
				
			||||||
   * @param callback The void() callback.
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  void add_on_press_callback(std::function<void()> &&callback);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /// Set the Home Assistant device class (see button::device_class).
 | 
					 | 
				
			||||||
  void set_device_class(const std::string &device_class);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /// Get the device class for this button.
 | 
					 | 
				
			||||||
  std::string get_device_class();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 protected:
 | 
					 | 
				
			||||||
  /** You should implement this virtual method if you want to create your own button.
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  virtual void press_action(){};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  uint32_t hash_base() override;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  CallbackManager<void()> press_callback_{};
 | 
					 | 
				
			||||||
  optional<std::string> device_class_{};
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}  // namespace button
 | 
					 | 
				
			||||||
}  // namespace esphome
 | 
					 | 
				
			||||||
@@ -1,45 +0,0 @@
 | 
				
			|||||||
import esphome.codegen as cg
 | 
					 | 
				
			||||||
import esphome.config_validation as cv
 | 
					 | 
				
			||||||
from esphome.components import i2c
 | 
					 | 
				
			||||||
from esphome.const import CONF_ID, CONF_RESET_PIN
 | 
					 | 
				
			||||||
from esphome import pins
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CONF_TOUCH_THRESHOLD = "touch_threshold"
 | 
					 | 
				
			||||||
CONF_ALLOW_MULTIPLE_TOUCHES = "allow_multiple_touches"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
DEPENDENCIES = ["i2c"]
 | 
					 | 
				
			||||||
AUTO_LOAD = ["binary_sensor", "output"]
 | 
					 | 
				
			||||||
CODEOWNERS = ["@MrEditor97"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
cap1188_ns = cg.esphome_ns.namespace("cap1188")
 | 
					 | 
				
			||||||
CONF_CAP1188_ID = "cap1188_id"
 | 
					 | 
				
			||||||
CAP1188Component = cap1188_ns.class_("CAP1188Component", cg.Component, i2c.I2CDevice)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MULTI_CONF = True
 | 
					 | 
				
			||||||
CONFIG_SCHEMA = (
 | 
					 | 
				
			||||||
    cv.Schema(
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            cv.GenerateID(): cv.declare_id(CAP1188Component),
 | 
					 | 
				
			||||||
            cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema,
 | 
					 | 
				
			||||||
            cv.Optional(CONF_TOUCH_THRESHOLD, default=0x20): cv.int_range(
 | 
					 | 
				
			||||||
                min=0x01, max=0x80
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
            cv.Optional(CONF_ALLOW_MULTIPLE_TOUCHES, default=False): cv.boolean,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    .extend(cv.COMPONENT_SCHEMA)
 | 
					 | 
				
			||||||
    .extend(i2c.i2c_device_schema(0x29))
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
async def to_code(config):
 | 
					 | 
				
			||||||
    var = cg.new_Pvariable(config[CONF_ID])
 | 
					 | 
				
			||||||
    cg.add(var.set_touch_threshold(config[CONF_TOUCH_THRESHOLD]))
 | 
					 | 
				
			||||||
    cg.add(var.set_allow_multiple_touches(config[CONF_ALLOW_MULTIPLE_TOUCHES]))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if CONF_RESET_PIN in config:
 | 
					 | 
				
			||||||
        pin = await cg.gpio_pin_expression(config[CONF_RESET_PIN])
 | 
					 | 
				
			||||||
        cg.add(var.set_reset_pin(pin))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    await cg.register_component(var, config)
 | 
					 | 
				
			||||||
    await i2c.register_i2c_device(var, config)
 | 
					 | 
				
			||||||
@@ -1,25 +0,0 @@
 | 
				
			|||||||
import esphome.codegen as cg
 | 
					 | 
				
			||||||
import esphome.config_validation as cv
 | 
					 | 
				
			||||||
from esphome.components import binary_sensor
 | 
					 | 
				
			||||||
from esphome.const import CONF_CHANNEL, CONF_ID
 | 
					 | 
				
			||||||
from . import cap1188_ns, CAP1188Component, CONF_CAP1188_ID
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
DEPENDENCIES = ["cap1188"]
 | 
					 | 
				
			||||||
CAP1188Channel = cap1188_ns.class_("CAP1188Channel", binary_sensor.BinarySensor)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend(
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        cv.GenerateID(): cv.declare_id(CAP1188Channel),
 | 
					 | 
				
			||||||
        cv.GenerateID(CONF_CAP1188_ID): cv.use_id(CAP1188Component),
 | 
					 | 
				
			||||||
        cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=7),
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
async def to_code(config):
 | 
					 | 
				
			||||||
    var = cg.new_Pvariable(config[CONF_ID])
 | 
					 | 
				
			||||||
    await binary_sensor.register_binary_sensor(var, config)
 | 
					 | 
				
			||||||
    hub = await cg.get_variable(config[CONF_CAP1188_ID])
 | 
					 | 
				
			||||||
    cg.add(var.set_channel(config[CONF_CHANNEL]))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    cg.add(hub.register_channel(var))
 | 
					 | 
				
			||||||
@@ -1,88 +0,0 @@
 | 
				
			|||||||
#include "cap1188.h"
 | 
					 | 
				
			||||||
#include "esphome/core/log.h"
 | 
					 | 
				
			||||||
#include "esphome/core/hal.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace esphome {
 | 
					 | 
				
			||||||
namespace cap1188 {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const char *const TAG = "cap1188";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void CAP1188Component::setup() {
 | 
					 | 
				
			||||||
  ESP_LOGCONFIG(TAG, "Setting up CAP1188...");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Reset device using the reset pin
 | 
					 | 
				
			||||||
  if (this->reset_pin_ != nullptr) {
 | 
					 | 
				
			||||||
    this->reset_pin_->setup();
 | 
					 | 
				
			||||||
    this->reset_pin_->digital_write(false);
 | 
					 | 
				
			||||||
    delay(100);  // NOLINT
 | 
					 | 
				
			||||||
    this->reset_pin_->digital_write(true);
 | 
					 | 
				
			||||||
    delay(100);  // NOLINT
 | 
					 | 
				
			||||||
    this->reset_pin_->digital_write(false);
 | 
					 | 
				
			||||||
    delay(100);  // NOLINT
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Check if CAP1188 is actually connected
 | 
					 | 
				
			||||||
  this->read_byte(CAP1188_PRODUCT_ID, &this->cap1188_product_id_);
 | 
					 | 
				
			||||||
  this->read_byte(CAP1188_MANUFACTURE_ID, &this->cap1188_manufacture_id_);
 | 
					 | 
				
			||||||
  this->read_byte(CAP1188_REVISION, &this->cap1188_revision_);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if ((this->cap1188_product_id_ != 0x50) || (this->cap1188_manufacture_id_ != 0x5D)) {
 | 
					 | 
				
			||||||
    this->error_code_ = COMMUNICATION_FAILED;
 | 
					 | 
				
			||||||
    this->mark_failed();
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Set sensitivity
 | 
					 | 
				
			||||||
  uint8_t sensitivity = 0;
 | 
					 | 
				
			||||||
  this->read_byte(CAP1188_SENSITVITY, &sensitivity);
 | 
					 | 
				
			||||||
  sensitivity = sensitivity & 0x0f;
 | 
					 | 
				
			||||||
  this->write_byte(CAP1188_SENSITVITY, sensitivity | this->touch_threshold_);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Allow multiple touches
 | 
					 | 
				
			||||||
  this->write_byte(CAP1188_MULTI_TOUCH, this->allow_multiple_touches_);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Have LEDs follow touches
 | 
					 | 
				
			||||||
  this->write_byte(CAP1188_LED_LINK, 0xFF);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Speed up a bit
 | 
					 | 
				
			||||||
  this->write_byte(CAP1188_STAND_BY_CONFIGURATION, 0x30);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void CAP1188Component::dump_config() {
 | 
					 | 
				
			||||||
  ESP_LOGCONFIG(TAG, "CAP1188:");
 | 
					 | 
				
			||||||
  LOG_I2C_DEVICE(this);
 | 
					 | 
				
			||||||
  LOG_PIN("  Reset Pin: ", this->reset_pin_);
 | 
					 | 
				
			||||||
  ESP_LOGCONFIG(TAG, "  Product ID: 0x%x", this->cap1188_product_id_);
 | 
					 | 
				
			||||||
  ESP_LOGCONFIG(TAG, "  Manufacture ID: 0x%x", this->cap1188_manufacture_id_);
 | 
					 | 
				
			||||||
  ESP_LOGCONFIG(TAG, "  Revision ID: 0x%x", this->cap1188_revision_);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  switch (this->error_code_) {
 | 
					 | 
				
			||||||
    case COMMUNICATION_FAILED:
 | 
					 | 
				
			||||||
      ESP_LOGE(TAG, "Product ID or Manufacture ID of the connected device does not match a known CAP1188.");
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
    case NONE:
 | 
					 | 
				
			||||||
    default:
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void CAP1188Component::loop() {
 | 
					 | 
				
			||||||
  uint8_t touched = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  this->read_register(CAP1188_SENSOR_INPUT_STATUS, &touched, 1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (touched) {
 | 
					 | 
				
			||||||
    uint8_t data = 0;
 | 
					 | 
				
			||||||
    this->read_register(CAP1188_MAIN, &data, 1);
 | 
					 | 
				
			||||||
    data = data & ~CAP1188_MAIN_INT;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    this->write_register(CAP1188_MAIN, &data, 2);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  for (auto *channel : this->channels_) {
 | 
					 | 
				
			||||||
    channel->process(touched);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}  // namespace cap1188
 | 
					 | 
				
			||||||
}  // namespace esphome
 | 
					 | 
				
			||||||
@@ -1,68 +0,0 @@
 | 
				
			|||||||
#pragma once
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "esphome/core/component.h"
 | 
					 | 
				
			||||||
#include "esphome/core/hal.h"
 | 
					 | 
				
			||||||
#include "esphome/components/i2c/i2c.h"
 | 
					 | 
				
			||||||
#include "esphome/components/output/binary_output.h"
 | 
					 | 
				
			||||||
#include "esphome/components/binary_sensor/binary_sensor.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace esphome {
 | 
					 | 
				
			||||||
namespace cap1188 {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum {
 | 
					 | 
				
			||||||
  CAP1188_I2CADDR = 0x29,
 | 
					 | 
				
			||||||
  CAP1188_SENSOR_INPUT_STATUS = 0x3,
 | 
					 | 
				
			||||||
  CAP1188_MULTI_TOUCH = 0x2A,
 | 
					 | 
				
			||||||
  CAP1188_LED_LINK = 0x72,
 | 
					 | 
				
			||||||
  CAP1188_PRODUCT_ID = 0xFD,
 | 
					 | 
				
			||||||
  CAP1188_MANUFACTURE_ID = 0xFE,
 | 
					 | 
				
			||||||
  CAP1188_STAND_BY_CONFIGURATION = 0x41,
 | 
					 | 
				
			||||||
  CAP1188_REVISION = 0xFF,
 | 
					 | 
				
			||||||
  CAP1188_MAIN = 0x00,
 | 
					 | 
				
			||||||
  CAP1188_MAIN_INT = 0x01,
 | 
					 | 
				
			||||||
  CAP1188_LEDPOL = 0x73,
 | 
					 | 
				
			||||||
  CAP1188_INTERUPT_REPEAT = 0x28,
 | 
					 | 
				
			||||||
  CAP1188_SENSITVITY = 0x1f,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class CAP1188Channel : public binary_sensor::BinarySensor {
 | 
					 | 
				
			||||||
 public:
 | 
					 | 
				
			||||||
  void set_channel(uint8_t channel) { channel_ = channel; }
 | 
					 | 
				
			||||||
  void process(uint8_t data) { this->publish_state(static_cast<bool>(data & (1 << this->channel_))); }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 protected:
 | 
					 | 
				
			||||||
  uint8_t channel_{0};
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class CAP1188Component : public Component, public i2c::I2CDevice {
 | 
					 | 
				
			||||||
 public:
 | 
					 | 
				
			||||||
  void register_channel(CAP1188Channel *channel) { this->channels_.push_back(channel); }
 | 
					 | 
				
			||||||
  void set_touch_threshold(uint8_t touch_threshold) { this->touch_threshold_ = touch_threshold; };
 | 
					 | 
				
			||||||
  void set_allow_multiple_touches(bool allow_multiple_touches) {
 | 
					 | 
				
			||||||
    this->allow_multiple_touches_ = allow_multiple_touches ? 0x41 : 0x80;
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
  void set_reset_pin(GPIOPin *reset_pin) { this->reset_pin_ = reset_pin; }
 | 
					 | 
				
			||||||
  void setup() override;
 | 
					 | 
				
			||||||
  void dump_config() override;
 | 
					 | 
				
			||||||
  float get_setup_priority() const override { return setup_priority::DATA; }
 | 
					 | 
				
			||||||
  void loop() override;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 protected:
 | 
					 | 
				
			||||||
  std::vector<CAP1188Channel *> channels_{};
 | 
					 | 
				
			||||||
  uint8_t touch_threshold_{0x20};
 | 
					 | 
				
			||||||
  uint8_t allow_multiple_touches_{0x80};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  GPIOPin *reset_pin_{nullptr};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  uint8_t cap1188_product_id_{0};
 | 
					 | 
				
			||||||
  uint8_t cap1188_manufacture_id_{0};
 | 
					 | 
				
			||||||
  uint8_t cap1188_revision_{0};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  enum ErrorCode {
 | 
					 | 
				
			||||||
    NONE = 0,
 | 
					 | 
				
			||||||
    COMMUNICATION_FAILED,
 | 
					 | 
				
			||||||
  } error_code_{NONE};
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}  // namespace cap1188
 | 
					 | 
				
			||||||
}  // namespace esphome
 | 
					 | 
				
			||||||
@@ -36,5 +36,3 @@ async def to_code(config):
 | 
				
			|||||||
    if CORE.is_esp32:
 | 
					    if CORE.is_esp32:
 | 
				
			||||||
        cg.add_library("DNSServer", None)
 | 
					        cg.add_library("DNSServer", None)
 | 
				
			||||||
        cg.add_library("WiFi", None)
 | 
					        cg.add_library("WiFi", None)
 | 
				
			||||||
    if CORE.is_esp8266:
 | 
					 | 
				
			||||||
        cg.add_library("DNSServer", None)
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -67,7 +67,6 @@ void CaptivePortal::handle_wifisave(AsyncWebServerRequest *request) {
 | 
				
			|||||||
  ESP_LOGI(TAG, "  SSID='%s'", ssid.c_str());
 | 
					  ESP_LOGI(TAG, "  SSID='%s'", ssid.c_str());
 | 
				
			||||||
  ESP_LOGI(TAG, "  Password=" LOG_SECRET("'%s'"), psk.c_str());
 | 
					  ESP_LOGI(TAG, "  Password=" LOG_SECRET("'%s'"), psk.c_str());
 | 
				
			||||||
  wifi::global_wifi_component->save_wifi_sta(ssid, psk);
 | 
					  wifi::global_wifi_component->save_wifi_sta(ssid, psk);
 | 
				
			||||||
  wifi::global_wifi_component->start_scanning();
 | 
					 | 
				
			||||||
  request->redirect("/?save=true");
 | 
					  request->redirect("/?save=true");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -85,7 +84,14 @@ void CaptivePortal::start() {
 | 
				
			|||||||
  this->dns_server_->start(53, "*", (uint32_t) ip);
 | 
					  this->dns_server_->start(53, "*", (uint32_t) ip);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  this->base_->get_server()->onNotFound([this](AsyncWebServerRequest *req) {
 | 
					  this->base_->get_server()->onNotFound([this](AsyncWebServerRequest *req) {
 | 
				
			||||||
    if (!this->active_ || req->host().c_str() == wifi::global_wifi_component->wifi_soft_ap_ip().str()) {
 | 
					    bool not_found = false;
 | 
				
			||||||
 | 
					    if (!this->active_) {
 | 
				
			||||||
 | 
					      not_found = true;
 | 
				
			||||||
 | 
					    } else if (req->host().c_str() == wifi::global_wifi_component->wifi_soft_ap_ip().str()) {
 | 
				
			||||||
 | 
					      not_found = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (not_found) {
 | 
				
			||||||
      req->send(404, "text/html", "File not found");
 | 
					      req->send(404, "text/html", "File not found");
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -52,7 +52,7 @@ void CCS811Component::setup() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  if (this->baseline_.has_value()) {
 | 
					  if (this->baseline_.has_value()) {
 | 
				
			||||||
    // baseline available, write to sensor
 | 
					    // baseline available, write to sensor
 | 
				
			||||||
    this->write_bytes(0x11, decode_value(*this->baseline_));
 | 
					    this->write_bytes(0x11, decode_uint16(*this->baseline_));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  auto hardware_version_data = this->read_bytes<1>(0x21);
 | 
					  auto hardware_version_data = this->read_bytes<1>(0x21);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,7 +20,6 @@ from esphome.const import (
 | 
				
			|||||||
    CONF_MODE,
 | 
					    CONF_MODE,
 | 
				
			||||||
    CONF_MODE_COMMAND_TOPIC,
 | 
					    CONF_MODE_COMMAND_TOPIC,
 | 
				
			||||||
    CONF_MODE_STATE_TOPIC,
 | 
					    CONF_MODE_STATE_TOPIC,
 | 
				
			||||||
    CONF_ON_STATE,
 | 
					 | 
				
			||||||
    CONF_PRESET,
 | 
					    CONF_PRESET,
 | 
				
			||||||
    CONF_SWING_MODE,
 | 
					    CONF_SWING_MODE,
 | 
				
			||||||
    CONF_SWING_MODE_COMMAND_TOPIC,
 | 
					    CONF_SWING_MODE_COMMAND_TOPIC,
 | 
				
			||||||
@@ -35,7 +34,6 @@ from esphome.const import (
 | 
				
			|||||||
    CONF_TARGET_TEMPERATURE_LOW_COMMAND_TOPIC,
 | 
					    CONF_TARGET_TEMPERATURE_LOW_COMMAND_TOPIC,
 | 
				
			||||||
    CONF_TARGET_TEMPERATURE_LOW_STATE_TOPIC,
 | 
					    CONF_TARGET_TEMPERATURE_LOW_STATE_TOPIC,
 | 
				
			||||||
    CONF_TEMPERATURE_STEP,
 | 
					    CONF_TEMPERATURE_STEP,
 | 
				
			||||||
    CONF_TRIGGER_ID,
 | 
					 | 
				
			||||||
    CONF_VISUAL,
 | 
					    CONF_VISUAL,
 | 
				
			||||||
    CONF_MQTT_ID,
 | 
					    CONF_MQTT_ID,
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -103,7 +101,6 @@ validate_climate_swing_mode = cv.enum(CLIMATE_SWING_MODES, upper=True)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# Actions
 | 
					# Actions
 | 
				
			||||||
ControlAction = climate_ns.class_("ControlAction", automation.Action)
 | 
					ControlAction = climate_ns.class_("ControlAction", automation.Action)
 | 
				
			||||||
StateTrigger = climate_ns.class_("StateTrigger", automation.Trigger.template())
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
CLIMATE_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).extend(
 | 
					CLIMATE_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).extend(
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -164,11 +161,6 @@ CLIMATE_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).
 | 
				
			|||||||
        cv.Optional(CONF_TARGET_TEMPERATURE_LOW_STATE_TOPIC): cv.All(
 | 
					        cv.Optional(CONF_TARGET_TEMPERATURE_LOW_STATE_TOPIC): cv.All(
 | 
				
			||||||
            cv.requires_component("mqtt"), cv.publish_topic
 | 
					            cv.requires_component("mqtt"), cv.publish_topic
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        cv.Optional(CONF_ON_STATE): automation.validate_automation(
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StateTrigger),
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -213,7 +205,7 @@ async def setup_climate_core_(var, config):
 | 
				
			|||||||
        if CONF_MODE_COMMAND_TOPIC in config:
 | 
					        if CONF_MODE_COMMAND_TOPIC in config:
 | 
				
			||||||
            cg.add(mqtt_.set_custom_mode_command_topic(config[CONF_MODE_COMMAND_TOPIC]))
 | 
					            cg.add(mqtt_.set_custom_mode_command_topic(config[CONF_MODE_COMMAND_TOPIC]))
 | 
				
			||||||
        if CONF_MODE_STATE_TOPIC in config:
 | 
					        if CONF_MODE_STATE_TOPIC in config:
 | 
				
			||||||
            cg.add(mqtt_.set_custom_mode_state_topic(config[CONF_MODE_STATE_TOPIC]))
 | 
					            cg.add(mqtt_.set_custom_state_topic(config[CONF_MODE_STATE_TOPIC]))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if CONF_SWING_MODE_COMMAND_TOPIC in config:
 | 
					        if CONF_SWING_MODE_COMMAND_TOPIC in config:
 | 
				
			||||||
            cg.add(
 | 
					            cg.add(
 | 
				
			||||||
@@ -264,10 +256,6 @@ async def setup_climate_core_(var, config):
 | 
				
			|||||||
                )
 | 
					                )
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for conf in config.get(CONF_ON_STATE, []):
 | 
					 | 
				
			||||||
        trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
 | 
					 | 
				
			||||||
        await automation.build_automation(trigger, [], conf)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
async def register_climate(var, config):
 | 
					async def register_climate(var, config):
 | 
				
			||||||
    if not CORE.has_id(config[CONF_ID]):
 | 
					    if not CORE.has_id(config[CONF_ID]):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,12 +42,5 @@ template<typename... Ts> class ControlAction : public Action<Ts...> {
 | 
				
			|||||||
  Climate *climate_;
 | 
					  Climate *climate_;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class StateTrigger : public Trigger<> {
 | 
					 | 
				
			||||||
 public:
 | 
					 | 
				
			||||||
  StateTrigger(Climate *climate) {
 | 
					 | 
				
			||||||
    climate->add_on_state_callback([this]() { this->trigger(); });
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}  // namespace climate
 | 
					}  // namespace climate
 | 
				
			||||||
}  // namespace esphome
 | 
					}  // namespace esphome
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -102,6 +102,8 @@ void CS5460AComponent::hw_init_() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* Doesn't reset the register values etc., just restarts the "computation cycle" */
 | 
					/* Doesn't reset the register values etc., just restarts the "computation cycle" */
 | 
				
			||||||
void CS5460AComponent::restart_() {
 | 
					void CS5460AComponent::restart_() {
 | 
				
			||||||
 | 
					  int cnt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  this->enable();
 | 
					  this->enable();
 | 
				
			||||||
  /* Stop running conversion, wake up if needed */
 | 
					  /* Stop running conversion, wake up if needed */
 | 
				
			||||||
  this->write_byte(CMD_POWER_UP);
 | 
					  this->write_byte(CMD_POWER_UP);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,244 +0,0 @@
 | 
				
			|||||||
#include "cse7761.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "esphome/core/log.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace esphome {
 | 
					 | 
				
			||||||
namespace cse7761 {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const char *const TAG = "cse7761";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*********************************************************************************************\
 | 
					 | 
				
			||||||
 * CSE7761 - Energy  (Sonoff Dual R3 Pow v1.x)
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Based on Tasmota source code
 | 
					 | 
				
			||||||
 * See https://github.com/arendst/Tasmota/discussions/10793
 | 
					 | 
				
			||||||
 * https://github.com/arendst/Tasmota/blob/development/tasmota/xnrg_19_cse7761.ino
 | 
					 | 
				
			||||||
\*********************************************************************************************/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const int CSE7761_UREF = 42563;  // RmsUc
 | 
					 | 
				
			||||||
static const int CSE7761_IREF = 52241;  // RmsIAC
 | 
					 | 
				
			||||||
static const int CSE7761_PREF = 44513;  // PowerPAC
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const uint8_t CSE7761_REG_SYSCON = 0x00;     // (2) System Control Register (0x0A04)
 | 
					 | 
				
			||||||
static const uint8_t CSE7761_REG_EMUCON = 0x01;     // (2) Metering control register (0x0000)
 | 
					 | 
				
			||||||
static const uint8_t CSE7761_REG_EMUCON2 = 0x13;    // (2) Metering control register 2 (0x0001)
 | 
					 | 
				
			||||||
static const uint8_t CSE7761_REG_PULSE1SEL = 0x1D;  // (2) Pin function output select register (0x3210)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const uint8_t CSE7761_REG_RMSIA = 0x24;      // (3) The effective value of channel A current (0x000000)
 | 
					 | 
				
			||||||
static const uint8_t CSE7761_REG_RMSIB = 0x25;      // (3) The effective value of channel B current (0x000000)
 | 
					 | 
				
			||||||
static const uint8_t CSE7761_REG_RMSU = 0x26;       // (3) Voltage RMS (0x000000)
 | 
					 | 
				
			||||||
static const uint8_t CSE7761_REG_POWERPA = 0x2C;    // (4) Channel A active power, update rate 27.2Hz (0x00000000)
 | 
					 | 
				
			||||||
static const uint8_t CSE7761_REG_POWERPB = 0x2D;    // (4) Channel B active power, update rate 27.2Hz (0x00000000)
 | 
					 | 
				
			||||||
static const uint8_t CSE7761_REG_SYSSTATUS = 0x43;  // (1) System status register
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const uint8_t CSE7761_REG_COEFFCHKSUM = 0x6F;  // (2) Coefficient checksum
 | 
					 | 
				
			||||||
static const uint8_t CSE7761_REG_RMSIAC = 0x70;       // (2) Channel A effective current conversion coefficient
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const uint8_t CSE7761_SPECIAL_COMMAND = 0xEA;   // Start special command
 | 
					 | 
				
			||||||
static const uint8_t CSE7761_CMD_RESET = 0x96;         // Reset command, after receiving the command, the chip resets
 | 
					 | 
				
			||||||
static const uint8_t CSE7761_CMD_CLOSE_WRITE = 0xDC;   // Close write operation
 | 
					 | 
				
			||||||
static const uint8_t CSE7761_CMD_ENABLE_WRITE = 0xE5;  // Enable write operation
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum CSE7761 { RMS_IAC, RMS_IBC, RMS_UC, POWER_PAC, POWER_PBC, POWER_SC, ENERGY_AC, ENERGY_BC };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void CSE7761Component::setup() {
 | 
					 | 
				
			||||||
  ESP_LOGCONFIG(TAG, "Setting up CSE7761...");
 | 
					 | 
				
			||||||
  this->write_(CSE7761_SPECIAL_COMMAND, CSE7761_CMD_RESET);
 | 
					 | 
				
			||||||
  uint16_t syscon = this->read_(0x00, 2);  // Default 0x0A04
 | 
					 | 
				
			||||||
  if ((0x0A04 == syscon) && this->chip_init_()) {
 | 
					 | 
				
			||||||
    this->write_(CSE7761_SPECIAL_COMMAND, CSE7761_CMD_CLOSE_WRITE);
 | 
					 | 
				
			||||||
    ESP_LOGD(TAG, "CSE7761 found");
 | 
					 | 
				
			||||||
    this->data_.ready = true;
 | 
					 | 
				
			||||||
  } else {
 | 
					 | 
				
			||||||
    this->mark_failed();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void CSE7761Component::dump_config() {
 | 
					 | 
				
			||||||
  ESP_LOGCONFIG(TAG, "CSE7761:");
 | 
					 | 
				
			||||||
  if (this->is_failed()) {
 | 
					 | 
				
			||||||
    ESP_LOGE(TAG, "Communication with CSE7761 failed!");
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  LOG_UPDATE_INTERVAL(this);
 | 
					 | 
				
			||||||
  this->check_uart_settings(38400, 1, uart::UART_CONFIG_PARITY_EVEN, 8);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
float CSE7761Component::get_setup_priority() const { return setup_priority::DATA; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void CSE7761Component::update() {
 | 
					 | 
				
			||||||
  if (this->data_.ready) {
 | 
					 | 
				
			||||||
    this->get_data_();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void CSE7761Component::write_(uint8_t reg, uint16_t data) {
 | 
					 | 
				
			||||||
  uint8_t buffer[5];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  buffer[0] = 0xA5;
 | 
					 | 
				
			||||||
  buffer[1] = reg;
 | 
					 | 
				
			||||||
  uint32_t len = 2;
 | 
					 | 
				
			||||||
  if (data) {
 | 
					 | 
				
			||||||
    if (data < 0xFF) {
 | 
					 | 
				
			||||||
      buffer[2] = data & 0xFF;
 | 
					 | 
				
			||||||
      len = 3;
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      buffer[2] = (data >> 8) & 0xFF;
 | 
					 | 
				
			||||||
      buffer[3] = data & 0xFF;
 | 
					 | 
				
			||||||
      len = 4;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    uint8_t crc = 0;
 | 
					 | 
				
			||||||
    for (uint32_t i = 0; i < len; i++) {
 | 
					 | 
				
			||||||
      crc += buffer[i];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    buffer[len] = ~crc;
 | 
					 | 
				
			||||||
    len++;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  this->write_array(buffer, len);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool CSE7761Component::read_once_(uint8_t reg, uint8_t size, uint32_t *value) {
 | 
					 | 
				
			||||||
  while (this->available()) {
 | 
					 | 
				
			||||||
    this->read();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  this->write_(reg, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  uint8_t buffer[8] = {0};
 | 
					 | 
				
			||||||
  uint32_t rcvd = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  for (uint32_t i = 0; i <= size; i++) {
 | 
					 | 
				
			||||||
    int value = this->read();
 | 
					 | 
				
			||||||
    if (value > -1 && rcvd < sizeof(buffer) - 1) {
 | 
					 | 
				
			||||||
      buffer[rcvd++] = value;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (!rcvd) {
 | 
					 | 
				
			||||||
    ESP_LOGD(TAG, "Received 0 bytes for register %hhu", reg);
 | 
					 | 
				
			||||||
    return false;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  rcvd--;
 | 
					 | 
				
			||||||
  uint32_t result = 0;
 | 
					 | 
				
			||||||
  // CRC check
 | 
					 | 
				
			||||||
  uint8_t crc = 0xA5 + reg;
 | 
					 | 
				
			||||||
  for (uint32_t i = 0; i < rcvd; i++) {
 | 
					 | 
				
			||||||
    result = (result << 8) | buffer[i];
 | 
					 | 
				
			||||||
    crc += buffer[i];
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  crc = ~crc;
 | 
					 | 
				
			||||||
  if (crc != buffer[rcvd]) {
 | 
					 | 
				
			||||||
    return false;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  *value = result;
 | 
					 | 
				
			||||||
  return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
uint32_t CSE7761Component::read_(uint8_t reg, uint8_t size) {
 | 
					 | 
				
			||||||
  bool result = false;  // Start loop
 | 
					 | 
				
			||||||
  uint8_t retry = 3;    // Retry up to three times
 | 
					 | 
				
			||||||
  uint32_t value = 0;   // Default no value
 | 
					 | 
				
			||||||
  while (!result && retry > 0) {
 | 
					 | 
				
			||||||
    retry--;
 | 
					 | 
				
			||||||
    if (this->read_once_(reg, size, &value))
 | 
					 | 
				
			||||||
      return value;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  ESP_LOGE(TAG, "Reading register %hhu failed!", reg);
 | 
					 | 
				
			||||||
  return value;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
uint32_t CSE7761Component::coefficient_by_unit_(uint32_t unit) {
 | 
					 | 
				
			||||||
  switch (unit) {
 | 
					 | 
				
			||||||
    case RMS_UC:
 | 
					 | 
				
			||||||
      return 0x400000 * 100 / this->data_.coefficient[RMS_UC];
 | 
					 | 
				
			||||||
    case RMS_IAC:
 | 
					 | 
				
			||||||
      return (0x800000 * 100 / this->data_.coefficient[RMS_IAC]) * 10;  // Stay within 32 bits
 | 
					 | 
				
			||||||
    case POWER_PAC:
 | 
					 | 
				
			||||||
      return 0x80000000 / this->data_.coefficient[POWER_PAC];
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool CSE7761Component::chip_init_() {
 | 
					 | 
				
			||||||
  uint16_t calc_chksum = 0xFFFF;
 | 
					 | 
				
			||||||
  for (uint32_t i = 0; i < 8; i++) {
 | 
					 | 
				
			||||||
    this->data_.coefficient[i] = this->read_(CSE7761_REG_RMSIAC + i, 2);
 | 
					 | 
				
			||||||
    calc_chksum += this->data_.coefficient[i];
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  calc_chksum = ~calc_chksum;
 | 
					 | 
				
			||||||
  uint16_t coeff_chksum = this->read_(CSE7761_REG_COEFFCHKSUM, 2);
 | 
					 | 
				
			||||||
  if ((calc_chksum != coeff_chksum) || (!calc_chksum)) {
 | 
					 | 
				
			||||||
    ESP_LOGD(TAG, "Default calibration");
 | 
					 | 
				
			||||||
    this->data_.coefficient[RMS_IAC] = CSE7761_IREF;
 | 
					 | 
				
			||||||
    this->data_.coefficient[RMS_UC] = CSE7761_UREF;
 | 
					 | 
				
			||||||
    this->data_.coefficient[POWER_PAC] = CSE7761_PREF;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  this->write_(CSE7761_SPECIAL_COMMAND, CSE7761_CMD_ENABLE_WRITE);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  uint8_t sys_status = this->read_(CSE7761_REG_SYSSTATUS, 1);
 | 
					 | 
				
			||||||
  if (sys_status & 0x10) {  // Write enable to protected registers (WREN)
 | 
					 | 
				
			||||||
    this->write_(CSE7761_REG_SYSCON | 0x80, 0xFF04);
 | 
					 | 
				
			||||||
    this->write_(CSE7761_REG_EMUCON | 0x80, 0x1183);
 | 
					 | 
				
			||||||
    this->write_(CSE7761_REG_EMUCON2 | 0x80, 0x0FC1);
 | 
					 | 
				
			||||||
    this->write_(CSE7761_REG_PULSE1SEL | 0x80, 0x3290);
 | 
					 | 
				
			||||||
  } else {
 | 
					 | 
				
			||||||
    ESP_LOGD(TAG, "Write failed at chip_init");
 | 
					 | 
				
			||||||
    return false;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void CSE7761Component::get_data_() {
 | 
					 | 
				
			||||||
  // The effective value of current and voltage Rms is a 24-bit signed number,
 | 
					 | 
				
			||||||
  // the highest bit is 0 for valid data,
 | 
					 | 
				
			||||||
  //   and when the highest bit is 1, the reading will be processed as zero
 | 
					 | 
				
			||||||
  // The active power parameter PowerA/B is in two’s complement format, 32-bit
 | 
					 | 
				
			||||||
  // data, the highest bit is Sign bit.
 | 
					 | 
				
			||||||
  uint32_t value = this->read_(CSE7761_REG_RMSU, 3);
 | 
					 | 
				
			||||||
  this->data_.voltage_rms = (value >= 0x800000) ? 0 : value;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  value = this->read_(CSE7761_REG_RMSIA, 3);
 | 
					 | 
				
			||||||
  this->data_.current_rms[0] = ((value >= 0x800000) || (value < 1600)) ? 0 : value;  // No load threshold of 10mA
 | 
					 | 
				
			||||||
  value = this->read_(CSE7761_REG_POWERPA, 4);
 | 
					 | 
				
			||||||
  this->data_.active_power[0] = (0 == this->data_.current_rms[0]) ? 0 : ((uint32_t) abs((int) value));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  value = this->read_(CSE7761_REG_RMSIB, 3);
 | 
					 | 
				
			||||||
  this->data_.current_rms[1] = ((value >= 0x800000) || (value < 1600)) ? 0 : value;  // No load threshold of 10mA
 | 
					 | 
				
			||||||
  value = this->read_(CSE7761_REG_POWERPB, 4);
 | 
					 | 
				
			||||||
  this->data_.active_power[1] = (0 == this->data_.current_rms[1]) ? 0 : ((uint32_t) abs((int) value));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // convert values and publish to sensors
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  float voltage = (float) this->data_.voltage_rms / this->coefficient_by_unit_(RMS_UC);
 | 
					 | 
				
			||||||
  if (this->voltage_sensor_ != nullptr) {
 | 
					 | 
				
			||||||
    this->voltage_sensor_->publish_state(voltage);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  for (uint32_t channel = 0; channel < 2; channel++) {
 | 
					 | 
				
			||||||
    // Active power = PowerPA * PowerPAC * 1000 / 0x80000000
 | 
					 | 
				
			||||||
    float active_power = (float) this->data_.active_power[channel] / this->coefficient_by_unit_(POWER_PAC);  // W
 | 
					 | 
				
			||||||
    float amps = (float) this->data_.current_rms[channel] / this->coefficient_by_unit_(RMS_IAC);             // A
 | 
					 | 
				
			||||||
    ESP_LOGD(TAG, "Channel %d power %f W, current %f A", channel + 1, active_power, amps);
 | 
					 | 
				
			||||||
    if (channel == 0) {
 | 
					 | 
				
			||||||
      if (this->power_sensor_1_ != nullptr) {
 | 
					 | 
				
			||||||
        this->power_sensor_1_->publish_state(active_power);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      if (this->current_sensor_1_ != nullptr) {
 | 
					 | 
				
			||||||
        this->current_sensor_1_->publish_state(amps);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    } else if (channel == 1) {
 | 
					 | 
				
			||||||
      if (this->power_sensor_2_ != nullptr) {
 | 
					 | 
				
			||||||
        this->power_sensor_2_->publish_state(active_power);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      if (this->current_sensor_2_ != nullptr) {
 | 
					 | 
				
			||||||
        this->current_sensor_2_->publish_state(amps);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}  // namespace cse7761
 | 
					 | 
				
			||||||
}  // namespace esphome
 | 
					 | 
				
			||||||
@@ -1,52 +0,0 @@
 | 
				
			|||||||
#pragma once
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "esphome/components/sensor/sensor.h"
 | 
					 | 
				
			||||||
#include "esphome/components/uart/uart.h"
 | 
					 | 
				
			||||||
#include "esphome/core/component.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace esphome {
 | 
					 | 
				
			||||||
namespace cse7761 {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct CSE7761DataStruct {
 | 
					 | 
				
			||||||
  uint32_t frequency = 0;
 | 
					 | 
				
			||||||
  uint32_t voltage_rms = 0;
 | 
					 | 
				
			||||||
  uint32_t current_rms[2] = {0};
 | 
					 | 
				
			||||||
  uint32_t energy[2] = {0};
 | 
					 | 
				
			||||||
  uint32_t active_power[2] = {0};
 | 
					 | 
				
			||||||
  uint16_t coefficient[8] = {0};
 | 
					 | 
				
			||||||
  uint8_t energy_update = 0;
 | 
					 | 
				
			||||||
  bool ready = false;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// This class implements support for the CSE7761 UART power sensor.
 | 
					 | 
				
			||||||
class CSE7761Component : public PollingComponent, public uart::UARTDevice {
 | 
					 | 
				
			||||||
 public:
 | 
					 | 
				
			||||||
  void set_voltage_sensor(sensor::Sensor *voltage_sensor) { voltage_sensor_ = voltage_sensor; }
 | 
					 | 
				
			||||||
  void set_active_power_1_sensor(sensor::Sensor *power_sensor_1) { power_sensor_1_ = power_sensor_1; }
 | 
					 | 
				
			||||||
  void set_current_1_sensor(sensor::Sensor *current_sensor_1) { current_sensor_1_ = current_sensor_1; }
 | 
					 | 
				
			||||||
  void set_active_power_2_sensor(sensor::Sensor *power_sensor_2) { power_sensor_2_ = power_sensor_2; }
 | 
					 | 
				
			||||||
  void set_current_2_sensor(sensor::Sensor *current_sensor_2) { current_sensor_2_ = current_sensor_2; }
 | 
					 | 
				
			||||||
  void setup() override;
 | 
					 | 
				
			||||||
  void dump_config() override;
 | 
					 | 
				
			||||||
  float get_setup_priority() const override;
 | 
					 | 
				
			||||||
  void update() override;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 protected:
 | 
					 | 
				
			||||||
  // Sensors
 | 
					 | 
				
			||||||
  sensor::Sensor *voltage_sensor_{nullptr};
 | 
					 | 
				
			||||||
  sensor::Sensor *power_sensor_1_{nullptr};
 | 
					 | 
				
			||||||
  sensor::Sensor *current_sensor_1_{nullptr};
 | 
					 | 
				
			||||||
  sensor::Sensor *power_sensor_2_{nullptr};
 | 
					 | 
				
			||||||
  sensor::Sensor *current_sensor_2_{nullptr};
 | 
					 | 
				
			||||||
  CSE7761DataStruct data_;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  void write_(uint8_t reg, uint16_t data);
 | 
					 | 
				
			||||||
  bool read_once_(uint8_t reg, uint8_t size, uint32_t *value);
 | 
					 | 
				
			||||||
  uint32_t read_(uint8_t reg, uint8_t size);
 | 
					 | 
				
			||||||
  uint32_t coefficient_by_unit_(uint32_t unit);
 | 
					 | 
				
			||||||
  bool chip_init_();
 | 
					 | 
				
			||||||
  void get_data_();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}  // namespace cse7761
 | 
					 | 
				
			||||||
}  // namespace esphome
 | 
					 | 
				
			||||||
@@ -1,90 +0,0 @@
 | 
				
			|||||||
import esphome.codegen as cg
 | 
					 | 
				
			||||||
import esphome.config_validation as cv
 | 
					 | 
				
			||||||
from esphome.components import sensor, uart
 | 
					 | 
				
			||||||
from esphome.const import (
 | 
					 | 
				
			||||||
    CONF_ID,
 | 
					 | 
				
			||||||
    CONF_VOLTAGE,
 | 
					 | 
				
			||||||
    DEVICE_CLASS_CURRENT,
 | 
					 | 
				
			||||||
    DEVICE_CLASS_POWER,
 | 
					 | 
				
			||||||
    DEVICE_CLASS_VOLTAGE,
 | 
					 | 
				
			||||||
    STATE_CLASS_MEASUREMENT,
 | 
					 | 
				
			||||||
    UNIT_VOLT,
 | 
					 | 
				
			||||||
    UNIT_AMPERE,
 | 
					 | 
				
			||||||
    UNIT_WATT,
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CODEOWNERS = ["@berfenger"]
 | 
					 | 
				
			||||||
DEPENDENCIES = ["uart"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
cse7761_ns = cg.esphome_ns.namespace("cse7761")
 | 
					 | 
				
			||||||
CSE7761Component = cse7761_ns.class_(
 | 
					 | 
				
			||||||
    "CSE7761Component", cg.PollingComponent, uart.UARTDevice
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CONF_CURRENT_1 = "current_1"
 | 
					 | 
				
			||||||
CONF_CURRENT_2 = "current_2"
 | 
					 | 
				
			||||||
CONF_ACTIVE_POWER_1 = "active_power_1"
 | 
					 | 
				
			||||||
CONF_ACTIVE_POWER_2 = "active_power_2"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CONFIG_SCHEMA = (
 | 
					 | 
				
			||||||
    cv.Schema(
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            cv.GenerateID(): cv.declare_id(CSE7761Component),
 | 
					 | 
				
			||||||
            cv.Optional(CONF_VOLTAGE): sensor.sensor_schema(
 | 
					 | 
				
			||||||
                unit_of_measurement=UNIT_VOLT,
 | 
					 | 
				
			||||||
                accuracy_decimals=1,
 | 
					 | 
				
			||||||
                device_class=DEVICE_CLASS_VOLTAGE,
 | 
					 | 
				
			||||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
            cv.Optional(CONF_CURRENT_1): sensor.sensor_schema(
 | 
					 | 
				
			||||||
                unit_of_measurement=UNIT_AMPERE,
 | 
					 | 
				
			||||||
                accuracy_decimals=2,
 | 
					 | 
				
			||||||
                device_class=DEVICE_CLASS_CURRENT,
 | 
					 | 
				
			||||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
            cv.Optional(CONF_CURRENT_2): sensor.sensor_schema(
 | 
					 | 
				
			||||||
                unit_of_measurement=UNIT_AMPERE,
 | 
					 | 
				
			||||||
                accuracy_decimals=2,
 | 
					 | 
				
			||||||
                device_class=DEVICE_CLASS_CURRENT,
 | 
					 | 
				
			||||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
            cv.Optional(CONF_ACTIVE_POWER_1): sensor.sensor_schema(
 | 
					 | 
				
			||||||
                unit_of_measurement=UNIT_WATT,
 | 
					 | 
				
			||||||
                accuracy_decimals=1,
 | 
					 | 
				
			||||||
                device_class=DEVICE_CLASS_POWER,
 | 
					 | 
				
			||||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
            cv.Optional(CONF_ACTIVE_POWER_2): sensor.sensor_schema(
 | 
					 | 
				
			||||||
                unit_of_measurement=UNIT_WATT,
 | 
					 | 
				
			||||||
                accuracy_decimals=1,
 | 
					 | 
				
			||||||
                device_class=DEVICE_CLASS_POWER,
 | 
					 | 
				
			||||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    .extend(cv.polling_component_schema("60s"))
 | 
					 | 
				
			||||||
    .extend(uart.UART_DEVICE_SCHEMA)
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema(
 | 
					 | 
				
			||||||
    "cse7761", baud_rate=38400, require_rx=True, require_tx=True
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
async def to_code(config):
 | 
					 | 
				
			||||||
    var = cg.new_Pvariable(config[CONF_ID])
 | 
					 | 
				
			||||||
    await cg.register_component(var, config)
 | 
					 | 
				
			||||||
    await uart.register_uart_device(var, config)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for key in [
 | 
					 | 
				
			||||||
        CONF_VOLTAGE,
 | 
					 | 
				
			||||||
        CONF_CURRENT_1,
 | 
					 | 
				
			||||||
        CONF_CURRENT_2,
 | 
					 | 
				
			||||||
        CONF_ACTIVE_POWER_1,
 | 
					 | 
				
			||||||
        CONF_ACTIVE_POWER_2,
 | 
					 | 
				
			||||||
    ]:
 | 
					 | 
				
			||||||
        if key not in config:
 | 
					 | 
				
			||||||
            continue
 | 
					 | 
				
			||||||
        conf = config[key]
 | 
					 | 
				
			||||||
        sens = await sensor.new_sensor(conf)
 | 
					 | 
				
			||||||
        cg.add(getattr(var, f"set_{key}_sensor")(sens))
 | 
					 | 
				
			||||||
@@ -90,7 +90,6 @@ void CSE7766Component::parse_data_() {
 | 
				
			|||||||
  uint32_t power_cycle = this->get_24_bit_uint_(17);
 | 
					  uint32_t power_cycle = this->get_24_bit_uint_(17);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  uint8_t adj = this->raw_data_[20];
 | 
					  uint8_t adj = this->raw_data_[20];
 | 
				
			||||||
  uint32_t cf_pulses = (this->raw_data_[21] << 8) + this->raw_data_[22];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool power_ok = true;
 | 
					  bool power_ok = true;
 | 
				
			||||||
  bool voltage_ok = true;
 | 
					  bool voltage_ok = true;
 | 
				
			||||||
@@ -128,18 +127,6 @@ void CSE7766Component::parse_data_() {
 | 
				
			|||||||
    power = power_calib / float(power_cycle);
 | 
					    power = power_calib / float(power_cycle);
 | 
				
			||||||
    this->power_acc_ += power;
 | 
					    this->power_acc_ += power;
 | 
				
			||||||
    this->power_counts_ += 1;
 | 
					    this->power_counts_ += 1;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    uint32_t difference;
 | 
					 | 
				
			||||||
    if (this->cf_pulses_last_ == 0)
 | 
					 | 
				
			||||||
      this->cf_pulses_last_ = cf_pulses;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (cf_pulses < this->cf_pulses_last_) {
 | 
					 | 
				
			||||||
      difference = cf_pulses + (0x10000 - this->cf_pulses_last_);
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      difference = cf_pulses - this->cf_pulses_last_;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    this->cf_pulses_last_ = cf_pulses;
 | 
					 | 
				
			||||||
    this->energy_total_ += difference * float(power_calib) / 1000000.0 / 3600.0;
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if ((adj & 0x20) == 0x20 && current_ok && voltage_ok && power != 0.0) {
 | 
					  if ((adj & 0x20) == 0x20 && current_ok && voltage_ok && power != 0.0) {
 | 
				
			||||||
@@ -149,9 +136,9 @@ void CSE7766Component::parse_data_() {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void CSE7766Component::update() {
 | 
					void CSE7766Component::update() {
 | 
				
			||||||
  float voltage = this->voltage_counts_ > 0 ? this->voltage_acc_ / this->voltage_counts_ : 0.0f;
 | 
					  float voltage = this->voltage_counts_ > 0 ? this->voltage_acc_ / this->voltage_counts_ : 0.0;
 | 
				
			||||||
  float current = this->current_counts_ > 0 ? this->current_acc_ / this->current_counts_ : 0.0f;
 | 
					  float current = this->current_counts_ > 0 ? this->current_acc_ / this->current_counts_ : 0.0;
 | 
				
			||||||
  float power = this->power_counts_ > 0 ? this->power_acc_ / this->power_counts_ : 0.0f;
 | 
					  float power = this->power_counts_ > 0 ? this->power_acc_ / this->power_counts_ : 0.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ESP_LOGV(TAG, "Got voltage_acc=%.2f current_acc=%.2f power_acc=%.2f", this->voltage_acc_, this->current_acc_,
 | 
					  ESP_LOGV(TAG, "Got voltage_acc=%.2f current_acc=%.2f power_acc=%.2f", this->voltage_acc_, this->current_acc_,
 | 
				
			||||||
           this->power_acc_);
 | 
					           this->power_acc_);
 | 
				
			||||||
@@ -165,8 +152,6 @@ void CSE7766Component::update() {
 | 
				
			|||||||
    this->current_sensor_->publish_state(current);
 | 
					    this->current_sensor_->publish_state(current);
 | 
				
			||||||
  if (this->power_sensor_ != nullptr)
 | 
					  if (this->power_sensor_ != nullptr)
 | 
				
			||||||
    this->power_sensor_->publish_state(power);
 | 
					    this->power_sensor_->publish_state(power);
 | 
				
			||||||
  if (this->energy_sensor_ != nullptr)
 | 
					 | 
				
			||||||
    this->energy_sensor_->publish_state(this->energy_total_);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  this->voltage_acc_ = 0.0f;
 | 
					  this->voltage_acc_ = 0.0f;
 | 
				
			||||||
  this->current_acc_ = 0.0f;
 | 
					  this->current_acc_ = 0.0f;
 | 
				
			||||||
@@ -187,7 +172,6 @@ void CSE7766Component::dump_config() {
 | 
				
			|||||||
  LOG_SENSOR("  ", "Voltage", this->voltage_sensor_);
 | 
					  LOG_SENSOR("  ", "Voltage", this->voltage_sensor_);
 | 
				
			||||||
  LOG_SENSOR("  ", "Current", this->current_sensor_);
 | 
					  LOG_SENSOR("  ", "Current", this->current_sensor_);
 | 
				
			||||||
  LOG_SENSOR("  ", "Power", this->power_sensor_);
 | 
					  LOG_SENSOR("  ", "Power", this->power_sensor_);
 | 
				
			||||||
  LOG_SENSOR("  ", "Energy", this->energy_sensor_);
 | 
					 | 
				
			||||||
  this->check_uart_settings(4800);
 | 
					  this->check_uart_settings(4800);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,6 @@ class CSE7766Component : public PollingComponent, public uart::UARTDevice {
 | 
				
			|||||||
  void set_voltage_sensor(sensor::Sensor *voltage_sensor) { voltage_sensor_ = voltage_sensor; }
 | 
					  void set_voltage_sensor(sensor::Sensor *voltage_sensor) { voltage_sensor_ = voltage_sensor; }
 | 
				
			||||||
  void set_current_sensor(sensor::Sensor *current_sensor) { current_sensor_ = current_sensor; }
 | 
					  void set_current_sensor(sensor::Sensor *current_sensor) { current_sensor_ = current_sensor; }
 | 
				
			||||||
  void set_power_sensor(sensor::Sensor *power_sensor) { power_sensor_ = power_sensor; }
 | 
					  void set_power_sensor(sensor::Sensor *power_sensor) { power_sensor_ = power_sensor; }
 | 
				
			||||||
  void set_energy_sensor(sensor::Sensor *energy_sensor) { energy_sensor_ = energy_sensor; }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void loop() override;
 | 
					  void loop() override;
 | 
				
			||||||
  float get_setup_priority() const override;
 | 
					  float get_setup_priority() const override;
 | 
				
			||||||
@@ -30,12 +29,9 @@ class CSE7766Component : public PollingComponent, public uart::UARTDevice {
 | 
				
			|||||||
  sensor::Sensor *voltage_sensor_{nullptr};
 | 
					  sensor::Sensor *voltage_sensor_{nullptr};
 | 
				
			||||||
  sensor::Sensor *current_sensor_{nullptr};
 | 
					  sensor::Sensor *current_sensor_{nullptr};
 | 
				
			||||||
  sensor::Sensor *power_sensor_{nullptr};
 | 
					  sensor::Sensor *power_sensor_{nullptr};
 | 
				
			||||||
  sensor::Sensor *energy_sensor_{nullptr};
 | 
					 | 
				
			||||||
  float voltage_acc_{0.0f};
 | 
					  float voltage_acc_{0.0f};
 | 
				
			||||||
  float current_acc_{0.0f};
 | 
					  float current_acc_{0.0f};
 | 
				
			||||||
  float power_acc_{0.0f};
 | 
					  float power_acc_{0.0f};
 | 
				
			||||||
  float energy_total_{0.0f};
 | 
					 | 
				
			||||||
  uint32_t cf_pulses_last_{0};
 | 
					 | 
				
			||||||
  uint32_t voltage_counts_{0};
 | 
					  uint32_t voltage_counts_{0};
 | 
				
			||||||
  uint32_t current_counts_{0};
 | 
					  uint32_t current_counts_{0};
 | 
				
			||||||
  uint32_t power_counts_{0};
 | 
					  uint32_t power_counts_{0};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,20 +3,16 @@ import esphome.config_validation as cv
 | 
				
			|||||||
from esphome.components import sensor, uart
 | 
					from esphome.components import sensor, uart
 | 
				
			||||||
from esphome.const import (
 | 
					from esphome.const import (
 | 
				
			||||||
    CONF_CURRENT,
 | 
					    CONF_CURRENT,
 | 
				
			||||||
    CONF_ENERGY,
 | 
					 | 
				
			||||||
    CONF_ID,
 | 
					    CONF_ID,
 | 
				
			||||||
    CONF_POWER,
 | 
					    CONF_POWER,
 | 
				
			||||||
    CONF_VOLTAGE,
 | 
					    CONF_VOLTAGE,
 | 
				
			||||||
    DEVICE_CLASS_CURRENT,
 | 
					    DEVICE_CLASS_CURRENT,
 | 
				
			||||||
    DEVICE_CLASS_ENERGY,
 | 
					 | 
				
			||||||
    DEVICE_CLASS_POWER,
 | 
					    DEVICE_CLASS_POWER,
 | 
				
			||||||
    DEVICE_CLASS_VOLTAGE,
 | 
					    DEVICE_CLASS_VOLTAGE,
 | 
				
			||||||
    STATE_CLASS_MEASUREMENT,
 | 
					    STATE_CLASS_MEASUREMENT,
 | 
				
			||||||
    STATE_CLASS_TOTAL_INCREASING,
 | 
					 | 
				
			||||||
    UNIT_VOLT,
 | 
					    UNIT_VOLT,
 | 
				
			||||||
    UNIT_AMPERE,
 | 
					    UNIT_AMPERE,
 | 
				
			||||||
    UNIT_WATT,
 | 
					    UNIT_WATT,
 | 
				
			||||||
    UNIT_WATT_HOURS,
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DEPENDENCIES = ["uart"]
 | 
					DEPENDENCIES = ["uart"]
 | 
				
			||||||
@@ -48,12 +44,6 @@ CONFIG_SCHEMA = (
 | 
				
			|||||||
                device_class=DEVICE_CLASS_POWER,
 | 
					                device_class=DEVICE_CLASS_POWER,
 | 
				
			||||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
					                state_class=STATE_CLASS_MEASUREMENT,
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            cv.Optional(CONF_ENERGY): sensor.sensor_schema(
 | 
					 | 
				
			||||||
                unit_of_measurement=UNIT_WATT_HOURS,
 | 
					 | 
				
			||||||
                accuracy_decimals=3,
 | 
					 | 
				
			||||||
                device_class=DEVICE_CLASS_ENERGY,
 | 
					 | 
				
			||||||
                state_class=STATE_CLASS_TOTAL_INCREASING,
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    .extend(cv.polling_component_schema("60s"))
 | 
					    .extend(cv.polling_component_schema("60s"))
 | 
				
			||||||
@@ -81,7 +71,3 @@ async def to_code(config):
 | 
				
			|||||||
        conf = config[CONF_POWER]
 | 
					        conf = config[CONF_POWER]
 | 
				
			||||||
        sens = await sensor.new_sensor(conf)
 | 
					        sens = await sensor.new_sensor(conf)
 | 
				
			||||||
        cg.add(var.set_power_sensor(sens))
 | 
					        cg.add(var.set_power_sensor(sens))
 | 
				
			||||||
    if CONF_ENERGY in config:
 | 
					 | 
				
			||||||
        conf = config[CONF_ENERGY]
 | 
					 | 
				
			||||||
        sens = await sensor.new_sensor(conf)
 | 
					 | 
				
			||||||
        cg.add(var.set_energy_sensor(sens))
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -231,7 +231,7 @@ bool DaikinClimate::on_receive(remote_base::RemoteReceiveData data) {
 | 
				
			|||||||
      // frame header
 | 
					      // frame header
 | 
				
			||||||
      if (byte != 0x27)
 | 
					      if (byte != 0x27)
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    } else if (pos == 3) {  // NOLINT(bugprone-branch-clone)
 | 
					    } else if (pos == 3) {
 | 
				
			||||||
      // frame header
 | 
					      // frame header
 | 
				
			||||||
      if (byte != 0x00)
 | 
					      if (byte != 0x00)
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,20 +6,26 @@ from esphome.const import CONF_ID, CONF_PIN
 | 
				
			|||||||
MULTI_CONF = True
 | 
					MULTI_CONF = True
 | 
				
			||||||
AUTO_LOAD = ["sensor"]
 | 
					AUTO_LOAD = ["sensor"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CONF_ONE_WIRE_ID = "one_wire_id"
 | 
				
			||||||
dallas_ns = cg.esphome_ns.namespace("dallas")
 | 
					dallas_ns = cg.esphome_ns.namespace("dallas")
 | 
				
			||||||
DallasComponent = dallas_ns.class_("DallasComponent", cg.PollingComponent)
 | 
					DallasComponent = dallas_ns.class_("DallasComponent", cg.PollingComponent)
 | 
				
			||||||
 | 
					ESPOneWire = dallas_ns.class_("ESPOneWire")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CONFIG_SCHEMA = cv.Schema(
 | 
					CONFIG_SCHEMA = cv.All(
 | 
				
			||||||
    {
 | 
					    cv.Schema(
 | 
				
			||||||
        cv.GenerateID(): cv.declare_id(DallasComponent),
 | 
					        {
 | 
				
			||||||
        cv.Required(CONF_PIN): pins.internal_gpio_output_pin_schema,
 | 
					            cv.GenerateID(): cv.declare_id(DallasComponent),
 | 
				
			||||||
    }
 | 
					            cv.GenerateID(CONF_ONE_WIRE_ID): cv.declare_id(ESPOneWire),
 | 
				
			||||||
).extend(cv.polling_component_schema("60s"))
 | 
					            cv.Required(CONF_PIN): pins.internal_gpio_output_pin_schema,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    ).extend(cv.polling_component_schema("60s")),
 | 
				
			||||||
 | 
					    # pin_mode call logs in esp-idf, but InterruptLock is active -> crash
 | 
				
			||||||
 | 
					    cv.only_with_arduino,
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async def to_code(config):
 | 
					async def to_code(config):
 | 
				
			||||||
    var = cg.new_Pvariable(config[CONF_ID])
 | 
					 | 
				
			||||||
    await cg.register_component(var, config)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pin = await cg.gpio_pin_expression(config[CONF_PIN])
 | 
					    pin = await cg.gpio_pin_expression(config[CONF_PIN])
 | 
				
			||||||
    cg.add(var.set_pin(pin))
 | 
					    one_wire = cg.new_Pvariable(config[CONF_ONE_WIRE_ID], pin)
 | 
				
			||||||
 | 
					    var = cg.new_Pvariable(config[CONF_ID], one_wire)
 | 
				
			||||||
 | 
					    await cg.register_component(var, config)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,11 +31,12 @@ uint16_t DallasTemperatureSensor::millis_to_wait_for_conversion() const {
 | 
				
			|||||||
void DallasComponent::setup() {
 | 
					void DallasComponent::setup() {
 | 
				
			||||||
  ESP_LOGCONFIG(TAG, "Setting up DallasComponent...");
 | 
					  ESP_LOGCONFIG(TAG, "Setting up DallasComponent...");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  pin_->setup();
 | 
					  yield();
 | 
				
			||||||
  one_wire_ = new ESPOneWire(pin_);  // NOLINT(cppcoreguidelines-owning-memory)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  std::vector<uint64_t> raw_sensors;
 | 
					  std::vector<uint64_t> raw_sensors;
 | 
				
			||||||
  raw_sensors = this->one_wire_->search_vec();
 | 
					  {
 | 
				
			||||||
 | 
					    InterruptLock lock;
 | 
				
			||||||
 | 
					    raw_sensors = this->one_wire_->search_vec();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (auto &address : raw_sensors) {
 | 
					  for (auto &address : raw_sensors) {
 | 
				
			||||||
    std::string s = uint64_to_string(address);
 | 
					    std::string s = uint64_to_string(address);
 | 
				
			||||||
@@ -69,7 +70,7 @@ void DallasComponent::setup() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
void DallasComponent::dump_config() {
 | 
					void DallasComponent::dump_config() {
 | 
				
			||||||
  ESP_LOGCONFIG(TAG, "DallasComponent:");
 | 
					  ESP_LOGCONFIG(TAG, "DallasComponent:");
 | 
				
			||||||
  LOG_PIN("  Pin: ", this->pin_);
 | 
					  LOG_PIN("  Pin: ", this->one_wire_->get_pin());
 | 
				
			||||||
  LOG_UPDATE_INTERVAL(this);
 | 
					  LOG_UPDATE_INTERVAL(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (this->found_sensors_.empty()) {
 | 
					  if (this->found_sensors_.empty()) {
 | 
				
			||||||
@@ -101,12 +102,15 @@ void DallasComponent::update() {
 | 
				
			|||||||
  this->status_clear_warning();
 | 
					  this->status_clear_warning();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool result;
 | 
					  bool result;
 | 
				
			||||||
  if (!this->one_wire_->reset()) {
 | 
					  {
 | 
				
			||||||
    result = false;
 | 
					    InterruptLock lock;
 | 
				
			||||||
  } else {
 | 
					    if (!this->one_wire_->reset()) {
 | 
				
			||||||
    result = true;
 | 
					      result = false;
 | 
				
			||||||
    this->one_wire_->skip();
 | 
					    } else {
 | 
				
			||||||
    this->one_wire_->write8(DALLAS_COMMAND_START_CONVERSION);
 | 
					      result = true;
 | 
				
			||||||
 | 
					      this->one_wire_->skip();
 | 
				
			||||||
 | 
					      this->one_wire_->write8(DALLAS_COMMAND_START_CONVERSION);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!result) {
 | 
					  if (!result) {
 | 
				
			||||||
@@ -117,7 +121,11 @@ void DallasComponent::update() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  for (auto *sensor : this->sensors_) {
 | 
					  for (auto *sensor : this->sensors_) {
 | 
				
			||||||
    this->set_timeout(sensor->get_address_name(), sensor->millis_to_wait_for_conversion(), [this, sensor] {
 | 
					    this->set_timeout(sensor->get_address_name(), sensor->millis_to_wait_for_conversion(), [this, sensor] {
 | 
				
			||||||
      bool res = sensor->read_scratch_pad();
 | 
					      bool res;
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        InterruptLock lock;
 | 
				
			||||||
 | 
					        res = sensor->read_scratch_pad();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (!res) {
 | 
					      if (!res) {
 | 
				
			||||||
        ESP_LOGW(TAG, "'%s' - Resetting bus for read failed!", sensor->get_name().c_str());
 | 
					        ESP_LOGW(TAG, "'%s' - Resetting bus for read failed!", sensor->get_name().c_str());
 | 
				
			||||||
@@ -138,6 +146,7 @@ void DallasComponent::update() {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					DallasComponent::DallasComponent(ESPOneWire *one_wire) : one_wire_(one_wire) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void DallasTemperatureSensor::set_address(uint64_t address) { this->address_ = address; }
 | 
					void DallasTemperatureSensor::set_address(uint64_t address) { this->address_ = address; }
 | 
				
			||||||
uint8_t DallasTemperatureSensor::get_resolution() const { return this->resolution_; }
 | 
					uint8_t DallasTemperatureSensor::get_resolution() const { return this->resolution_; }
 | 
				
			||||||
@@ -153,7 +162,7 @@ const std::string &DallasTemperatureSensor::get_address_name() {
 | 
				
			|||||||
  return this->address_name_;
 | 
					  return this->address_name_;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
bool IRAM_ATTR DallasTemperatureSensor::read_scratch_pad() {
 | 
					bool IRAM_ATTR DallasTemperatureSensor::read_scratch_pad() {
 | 
				
			||||||
  auto *wire = this->parent_->one_wire_;
 | 
					  ESPOneWire *wire = this->parent_->one_wire_;
 | 
				
			||||||
  if (!wire->reset()) {
 | 
					  if (!wire->reset()) {
 | 
				
			||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -167,7 +176,11 @@ bool IRAM_ATTR DallasTemperatureSensor::read_scratch_pad() {
 | 
				
			|||||||
  return true;
 | 
					  return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
bool DallasTemperatureSensor::setup_sensor() {
 | 
					bool DallasTemperatureSensor::setup_sensor() {
 | 
				
			||||||
  bool r = this->read_scratch_pad();
 | 
					  bool r;
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    InterruptLock lock;
 | 
				
			||||||
 | 
					    r = this->read_scratch_pad();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!r) {
 | 
					  if (!r) {
 | 
				
			||||||
    ESP_LOGE(TAG, "Reading scratchpad failed: reset");
 | 
					    ESP_LOGE(TAG, "Reading scratchpad failed: reset");
 | 
				
			||||||
@@ -201,18 +214,21 @@ bool DallasTemperatureSensor::setup_sensor() {
 | 
				
			|||||||
      break;
 | 
					      break;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  auto *wire = this->parent_->one_wire_;
 | 
					  ESPOneWire *wire = this->parent_->one_wire_;
 | 
				
			||||||
  if (wire->reset()) {
 | 
					  {
 | 
				
			||||||
    wire->select(this->address_);
 | 
					    InterruptLock lock;
 | 
				
			||||||
    wire->write8(DALLAS_COMMAND_WRITE_SCRATCH_PAD);
 | 
					    if (wire->reset()) {
 | 
				
			||||||
    wire->write8(this->scratch_pad_[2]);  // high alarm temp
 | 
					      wire->select(this->address_);
 | 
				
			||||||
    wire->write8(this->scratch_pad_[3]);  // low alarm temp
 | 
					      wire->write8(DALLAS_COMMAND_WRITE_SCRATCH_PAD);
 | 
				
			||||||
    wire->write8(this->scratch_pad_[4]);  // resolution
 | 
					      wire->write8(this->scratch_pad_[2]);  // high alarm temp
 | 
				
			||||||
    wire->reset();
 | 
					      wire->write8(this->scratch_pad_[3]);  // low alarm temp
 | 
				
			||||||
 | 
					      wire->write8(this->scratch_pad_[4]);  // resolution
 | 
				
			||||||
 | 
					      wire->reset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // write value to EEPROM
 | 
					      // write value to EEPROM
 | 
				
			||||||
    wire->select(this->address_);
 | 
					      wire->select(this->address_);
 | 
				
			||||||
    wire->write8(0x48);
 | 
					      wire->write8(0x48);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  delay(20);  // allow it to finish operation
 | 
					  delay(20);  // allow it to finish operation
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,8 @@ class DallasTemperatureSensor;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class DallasComponent : public PollingComponent {
 | 
					class DallasComponent : public PollingComponent {
 | 
				
			||||||
 public:
 | 
					 public:
 | 
				
			||||||
  void set_pin(InternalGPIOPin *pin) { pin_ = pin; }
 | 
					  explicit DallasComponent(ESPOneWire *one_wire);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void register_sensor(DallasTemperatureSensor *sensor);
 | 
					  void register_sensor(DallasTemperatureSensor *sensor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void setup() override;
 | 
					  void setup() override;
 | 
				
			||||||
@@ -23,7 +24,6 @@ class DallasComponent : public PollingComponent {
 | 
				
			|||||||
 protected:
 | 
					 protected:
 | 
				
			||||||
  friend DallasTemperatureSensor;
 | 
					  friend DallasTemperatureSensor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  InternalGPIOPin *pin_;
 | 
					 | 
				
			||||||
  ESPOneWire *one_wire_;
 | 
					  ESPOneWire *one_wire_;
 | 
				
			||||||
  std::vector<DallasTemperatureSensor *> sensors_;
 | 
					  std::vector<DallasTemperatureSensor *> sensors_;
 | 
				
			||||||
  std::vector<uint64_t> found_sensors_;
 | 
					  std::vector<uint64_t> found_sensors_;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,123 +10,115 @@ static const char *const TAG = "dallas.one_wire";
 | 
				
			|||||||
const uint8_t ONE_WIRE_ROM_SELECT = 0x55;
 | 
					const uint8_t ONE_WIRE_ROM_SELECT = 0x55;
 | 
				
			||||||
const int ONE_WIRE_ROM_SEARCH = 0xF0;
 | 
					const int ONE_WIRE_ROM_SEARCH = 0xF0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ESPOneWire::ESPOneWire(InternalGPIOPin *pin) { pin_ = pin->to_isr(); }
 | 
					ESPOneWire::ESPOneWire(GPIOPin *pin) : pin_(pin) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool HOT IRAM_ATTR ESPOneWire::reset() {
 | 
					bool HOT IRAM_ATTR ESPOneWire::reset() {
 | 
				
			||||||
  // See reset here:
 | 
					 | 
				
			||||||
  // https://www.maximintegrated.com/en/design/technical-documents/app-notes/1/126.html
 | 
					 | 
				
			||||||
  InterruptLock lock;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Wait for communication to clear (delay G)
 | 
					 | 
				
			||||||
  pin_.pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
 | 
					 | 
				
			||||||
  uint8_t retries = 125;
 | 
					  uint8_t retries = 125;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Wait for communication to clear
 | 
				
			||||||
 | 
					  this->pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
 | 
				
			||||||
  do {
 | 
					  do {
 | 
				
			||||||
    if (--retries == 0)
 | 
					    if (--retries == 0)
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
    delayMicroseconds(2);
 | 
					    delayMicroseconds(2);
 | 
				
			||||||
  } while (!pin_.digital_read());
 | 
					  } while (!this->pin_->digital_read());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Send 480µs LOW TX reset pulse (drive bus low, delay H)
 | 
					  // Send 480µs LOW TX reset pulse
 | 
				
			||||||
  pin_.pin_mode(gpio::FLAG_OUTPUT);
 | 
					  this->pin_->pin_mode(gpio::FLAG_OUTPUT);
 | 
				
			||||||
  pin_.digital_write(false);
 | 
					  this->pin_->digital_write(false);
 | 
				
			||||||
  delayMicroseconds(480);
 | 
					  delayMicroseconds(480);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Release the bus, delay I
 | 
					  // Switch into RX mode, letting the pin float
 | 
				
			||||||
  pin_.pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
 | 
					  this->pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
 | 
				
			||||||
 | 
					  // after 15µs-60µs wait time, responder pulls low for 60µs-240µs
 | 
				
			||||||
 | 
					  // let's have 70µs just in case
 | 
				
			||||||
  delayMicroseconds(70);
 | 
					  delayMicroseconds(70);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // sample bus, 0=device(s) present, 1=no device present
 | 
					  bool r = !this->pin_->digital_read();
 | 
				
			||||||
  bool r = !pin_.digital_read();
 | 
					 | 
				
			||||||
  // delay J
 | 
					 | 
				
			||||||
  delayMicroseconds(410);
 | 
					  delayMicroseconds(410);
 | 
				
			||||||
  return r;
 | 
					  return r;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void HOT IRAM_ATTR ESPOneWire::write_bit(bool bit) {
 | 
					void HOT IRAM_ATTR ESPOneWire::write_bit(bool bit) {
 | 
				
			||||||
  // See write 1/0 bit here:
 | 
					  // Initiate write/read by pulling low.
 | 
				
			||||||
  // https://www.maximintegrated.com/en/design/technical-documents/app-notes/1/126.html
 | 
					  this->pin_->pin_mode(gpio::FLAG_OUTPUT);
 | 
				
			||||||
  InterruptLock lock;
 | 
					  this->pin_->digital_write(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // drive bus low
 | 
					  // bus sampled within 15µs and 60µs after pulling LOW.
 | 
				
			||||||
  pin_.pin_mode(gpio::FLAG_OUTPUT);
 | 
					  if (bit) {
 | 
				
			||||||
  pin_.digital_write(false);
 | 
					    // pull high/release within 15µs
 | 
				
			||||||
 | 
					    delayMicroseconds(10);
 | 
				
			||||||
  uint32_t delay0 = bit ? 10 : 65;
 | 
					    this->pin_->digital_write(true);
 | 
				
			||||||
  uint32_t delay1 = bit ? 55 : 5;
 | 
					    // in total minimum of 60µs long
 | 
				
			||||||
 | 
					    delayMicroseconds(55);
 | 
				
			||||||
  // delay A/C
 | 
					  } else {
 | 
				
			||||||
  delayMicroseconds(delay0);
 | 
					    // continue pulling LOW for at least 60µs
 | 
				
			||||||
  // release bus
 | 
					    delayMicroseconds(65);
 | 
				
			||||||
  pin_.digital_write(true);
 | 
					    this->pin_->digital_write(true);
 | 
				
			||||||
  // delay B/D
 | 
					    // grace period, 1µs recovery time
 | 
				
			||||||
  delayMicroseconds(delay1);
 | 
					    delayMicroseconds(5);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool HOT IRAM_ATTR ESPOneWire::read_bit() {
 | 
					bool HOT IRAM_ATTR ESPOneWire::read_bit() {
 | 
				
			||||||
  // See read bit here:
 | 
					  // Initiate read slot by pulling LOW for at least 1µs
 | 
				
			||||||
  // https://www.maximintegrated.com/en/design/technical-documents/app-notes/1/126.html
 | 
					  this->pin_->pin_mode(gpio::FLAG_OUTPUT);
 | 
				
			||||||
  InterruptLock lock;
 | 
					  this->pin_->digital_write(false);
 | 
				
			||||||
 | 
					 | 
				
			||||||
  // drive bus low, delay A
 | 
					 | 
				
			||||||
  pin_.pin_mode(gpio::FLAG_OUTPUT);
 | 
					 | 
				
			||||||
  pin_.digital_write(false);
 | 
					 | 
				
			||||||
  delayMicroseconds(3);
 | 
					  delayMicroseconds(3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // release bus, delay E
 | 
					  // release bus, we have to sample within 15µs of pulling low
 | 
				
			||||||
  pin_.pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
 | 
					  this->pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
 | 
				
			||||||
  delayMicroseconds(10);
 | 
					  delayMicroseconds(10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // sample bus to read bit from peer
 | 
					  bool r = this->pin_->digital_read();
 | 
				
			||||||
  bool r = pin_.digital_read();
 | 
					  // read time slot at least 60µs long + 1µs recovery time between slots
 | 
				
			||||||
 | 
					 | 
				
			||||||
  // delay F
 | 
					 | 
				
			||||||
  delayMicroseconds(53);
 | 
					  delayMicroseconds(53);
 | 
				
			||||||
  return r;
 | 
					  return r;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ESPOneWire::write8(uint8_t val) {
 | 
					void IRAM_ATTR ESPOneWire::write8(uint8_t val) {
 | 
				
			||||||
  for (uint8_t i = 0; i < 8; i++) {
 | 
					  for (uint8_t i = 0; i < 8; i++) {
 | 
				
			||||||
    this->write_bit(bool((1u << i) & val));
 | 
					    this->write_bit(bool((1u << i) & val));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ESPOneWire::write64(uint64_t val) {
 | 
					void IRAM_ATTR ESPOneWire::write64(uint64_t val) {
 | 
				
			||||||
  for (uint8_t i = 0; i < 64; i++) {
 | 
					  for (uint8_t i = 0; i < 64; i++) {
 | 
				
			||||||
    this->write_bit(bool((1ULL << i) & val));
 | 
					    this->write_bit(bool((1ULL << i) & val));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint8_t ESPOneWire::read8() {
 | 
					uint8_t IRAM_ATTR ESPOneWire::read8() {
 | 
				
			||||||
  uint8_t ret = 0;
 | 
					  uint8_t ret = 0;
 | 
				
			||||||
  for (uint8_t i = 0; i < 8; i++) {
 | 
					  for (uint8_t i = 0; i < 8; i++) {
 | 
				
			||||||
    ret |= (uint8_t(this->read_bit()) << i);
 | 
					    ret |= (uint8_t(this->read_bit()) << i);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return ret;
 | 
					  return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
uint64_t ESPOneWire::read64() {
 | 
					uint64_t IRAM_ATTR ESPOneWire::read64() {
 | 
				
			||||||
  uint64_t ret = 0;
 | 
					  uint64_t ret = 0;
 | 
				
			||||||
  for (uint8_t i = 0; i < 8; i++) {
 | 
					  for (uint8_t i = 0; i < 8; i++) {
 | 
				
			||||||
    ret |= (uint64_t(this->read_bit()) << i);
 | 
					    ret |= (uint64_t(this->read_bit()) << i);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return ret;
 | 
					  return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void ESPOneWire::select(uint64_t address) {
 | 
					void IRAM_ATTR ESPOneWire::select(uint64_t address) {
 | 
				
			||||||
  this->write8(ONE_WIRE_ROM_SELECT);
 | 
					  this->write8(ONE_WIRE_ROM_SELECT);
 | 
				
			||||||
  this->write64(address);
 | 
					  this->write64(address);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void ESPOneWire::reset_search() {
 | 
					void IRAM_ATTR ESPOneWire::reset_search() {
 | 
				
			||||||
  this->last_discrepancy_ = 0;
 | 
					  this->last_discrepancy_ = 0;
 | 
				
			||||||
  this->last_device_flag_ = false;
 | 
					  this->last_device_flag_ = false;
 | 
				
			||||||
  this->last_family_discrepancy_ = 0;
 | 
					  this->last_family_discrepancy_ = 0;
 | 
				
			||||||
  this->rom_number_ = 0;
 | 
					  this->rom_number_ = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
uint64_t ESPOneWire::search() {
 | 
					uint64_t HOT IRAM_ATTR ESPOneWire::search() {
 | 
				
			||||||
  if (this->last_device_flag_) {
 | 
					  if (this->last_device_flag_) {
 | 
				
			||||||
    return 0u;
 | 
					    return 0u;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!this->reset()) {
 | 
					  if (!this->reset()) {
 | 
				
			||||||
    // Reset failed or no devices present
 | 
					    // Reset failed
 | 
				
			||||||
    this->reset_search();
 | 
					    this->reset_search();
 | 
				
			||||||
    return 0u;
 | 
					    return 0u;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -204,7 +196,7 @@ uint64_t ESPOneWire::search() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  return this->rom_number_;
 | 
					  return this->rom_number_;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
std::vector<uint64_t> ESPOneWire::search_vec() {
 | 
					std::vector<uint64_t> IRAM_ATTR ESPOneWire::search_vec() {
 | 
				
			||||||
  std::vector<uint64_t> res;
 | 
					  std::vector<uint64_t> res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  this->reset_search();
 | 
					  this->reset_search();
 | 
				
			||||||
@@ -214,9 +206,10 @@ std::vector<uint64_t> ESPOneWire::search_vec() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  return res;
 | 
					  return res;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void ESPOneWire::skip() {
 | 
					void IRAM_ATTR ESPOneWire::skip() {
 | 
				
			||||||
  this->write8(0xCC);  // skip ROM
 | 
					  this->write8(0xCC);  // skip ROM
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					GPIOPin *ESPOneWire::get_pin() { return this->pin_; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint8_t IRAM_ATTR *ESPOneWire::rom_number8_() { return reinterpret_cast<uint8_t *>(&this->rom_number_); }
 | 
					uint8_t IRAM_ATTR *ESPOneWire::rom_number8_() { return reinterpret_cast<uint8_t *>(&this->rom_number_); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,6 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "esphome/core/component.h"
 | 
				
			||||||
#include "esphome/core/hal.h"
 | 
					#include "esphome/core/hal.h"
 | 
				
			||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -11,7 +12,7 @@ extern const int ONE_WIRE_ROM_SEARCH;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class ESPOneWire {
 | 
					class ESPOneWire {
 | 
				
			||||||
 public:
 | 
					 public:
 | 
				
			||||||
  explicit ESPOneWire(InternalGPIOPin *pin);
 | 
					  explicit ESPOneWire(GPIOPin *pin);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** Reset the bus, should be done before all write operations.
 | 
					  /** Reset the bus, should be done before all write operations.
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
@@ -54,11 +55,13 @@ class ESPOneWire {
 | 
				
			|||||||
  /// Helper that wraps search in a std::vector.
 | 
					  /// Helper that wraps search in a std::vector.
 | 
				
			||||||
  std::vector<uint64_t> search_vec();
 | 
					  std::vector<uint64_t> search_vec();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  GPIOPin *get_pin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 protected:
 | 
					 protected:
 | 
				
			||||||
  /// Helper to get the internal 64-bit unsigned rom number as a 8-bit integer pointer.
 | 
					  /// Helper to get the internal 64-bit unsigned rom number as a 8-bit integer pointer.
 | 
				
			||||||
  inline uint8_t *rom_number8_();
 | 
					  inline uint8_t *rom_number8_();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ISRInternalGPIOPin pin_;
 | 
					  GPIOPin *pin_;
 | 
				
			||||||
  uint8_t last_discrepancy_{0};
 | 
					  uint8_t last_discrepancy_{0};
 | 
				
			||||||
  uint8_t last_family_discrepancy_{0};
 | 
					  uint8_t last_family_discrepancy_{0};
 | 
				
			||||||
  bool last_device_flag_{false};
 | 
					  bool last_device_flag_{false};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,13 +29,6 @@ CONFIG_SCHEMA = cv.Schema(
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
WIFI_CONFIG = """
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
wifi:
 | 
					 | 
				
			||||||
  ssid: !secret wifi_ssid
 | 
					 | 
				
			||||||
  password: !secret wifi_password
 | 
					 | 
				
			||||||
"""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
async def to_code(config):
 | 
					async def to_code(config):
 | 
				
			||||||
    cg.add_define("USE_DASHBOARD_IMPORT")
 | 
					    cg.add_define("USE_DASHBOARD_IMPORT")
 | 
				
			||||||
@@ -48,12 +41,5 @@ def import_config(path: str, name: str, project_name: str, import_url: str) -> N
 | 
				
			|||||||
    if p.exists():
 | 
					    if p.exists():
 | 
				
			||||||
        raise FileExistsError
 | 
					        raise FileExistsError
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    config = {
 | 
					    config = {"substitutions": {"name": name}, "packages": {project_name: import_url}}
 | 
				
			||||||
        "substitutions": {"name": name},
 | 
					    p.write_text(dump(config), encoding="utf8")
 | 
				
			||||||
        "packages": {project_name: import_url},
 | 
					 | 
				
			||||||
        "esphome": {"name_add_mac_suffix": False},
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    p.write_text(
 | 
					 | 
				
			||||||
        dump(config) + WIFI_CONFIG,
 | 
					 | 
				
			||||||
        encoding="utf8",
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,23 +4,20 @@
 | 
				
			|||||||
#include "esphome/core/defines.h"
 | 
					#include "esphome/core/defines.h"
 | 
				
			||||||
#include "esphome/core/version.h"
 | 
					#include "esphome/core/version.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef USE_ESP_IDF
 | 
					 | 
				
			||||||
#include <esp_heap_caps.h>
 | 
					 | 
				
			||||||
#include <esp_system.h>
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef USE_ESP32
 | 
					#ifdef USE_ESP32
 | 
				
			||||||
#if ESP_IDF_VERSION_MAJOR >= 4
 | 
					 | 
				
			||||||
#include <esp32/rom/rtc.h>
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
#include <rom/rtc.h>
 | 
					#include <rom/rtc.h>
 | 
				
			||||||
#endif
 | 
					#include <esp_idf_version.h>
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef USE_ARDUINO
 | 
					#ifdef USE_ARDUINO
 | 
				
			||||||
#include <Esp.h>
 | 
					#include <Esp.h>
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef USE_ESP_IDF
 | 
				
			||||||
 | 
					#include <esp_heap_caps.h>
 | 
				
			||||||
 | 
					#include <esp_system.h>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace esphome {
 | 
					namespace esphome {
 | 
				
			||||||
namespace debug {
 | 
					namespace debug {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,30 +41,15 @@ EXT1_WAKEUP_MODES = {
 | 
				
			|||||||
    "ALL_LOW": esp_sleep_ext1_wakeup_mode_t.ESP_EXT1_WAKEUP_ALL_LOW,
 | 
					    "ALL_LOW": esp_sleep_ext1_wakeup_mode_t.ESP_EXT1_WAKEUP_ALL_LOW,
 | 
				
			||||||
    "ANY_HIGH": esp_sleep_ext1_wakeup_mode_t.ESP_EXT1_WAKEUP_ANY_HIGH,
 | 
					    "ANY_HIGH": esp_sleep_ext1_wakeup_mode_t.ESP_EXT1_WAKEUP_ANY_HIGH,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
WakeupCauseToRunDuration = deep_sleep_ns.struct("WakeupCauseToRunDuration")
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
CONF_WAKEUP_PIN_MODE = "wakeup_pin_mode"
 | 
					CONF_WAKEUP_PIN_MODE = "wakeup_pin_mode"
 | 
				
			||||||
CONF_ESP32_EXT1_WAKEUP = "esp32_ext1_wakeup"
 | 
					CONF_ESP32_EXT1_WAKEUP = "esp32_ext1_wakeup"
 | 
				
			||||||
CONF_TOUCH_WAKEUP = "touch_wakeup"
 | 
					CONF_TOUCH_WAKEUP = "touch_wakeup"
 | 
				
			||||||
CONF_DEFAULT = "default"
 | 
					 | 
				
			||||||
CONF_GPIO_WAKEUP_REASON = "gpio_wakeup_reason"
 | 
					 | 
				
			||||||
CONF_TOUCH_WAKEUP_REASON = "touch_wakeup_reason"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
WAKEUP_CAUSES_SCHEMA = cv.Schema(
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        cv.Required(CONF_DEFAULT): cv.positive_time_period_milliseconds,
 | 
					 | 
				
			||||||
        cv.Optional(CONF_TOUCH_WAKEUP_REASON): cv.positive_time_period_milliseconds,
 | 
					 | 
				
			||||||
        cv.Optional(CONF_GPIO_WAKEUP_REASON): cv.positive_time_period_milliseconds,
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
CONFIG_SCHEMA = cv.Schema(
 | 
					CONFIG_SCHEMA = cv.Schema(
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        cv.GenerateID(): cv.declare_id(DeepSleepComponent),
 | 
					        cv.GenerateID(): cv.declare_id(DeepSleepComponent),
 | 
				
			||||||
        cv.Optional(CONF_RUN_DURATION): cv.Any(
 | 
					        cv.Optional(CONF_RUN_DURATION): cv.positive_time_period_milliseconds,
 | 
				
			||||||
            cv.All(cv.only_on_esp32, WAKEUP_CAUSES_SCHEMA),
 | 
					 | 
				
			||||||
            cv.positive_time_period_milliseconds,
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
        cv.Optional(CONF_SLEEP_DURATION): cv.positive_time_period_milliseconds,
 | 
					        cv.Optional(CONF_SLEEP_DURATION): cv.positive_time_period_milliseconds,
 | 
				
			||||||
        cv.Optional(CONF_WAKEUP_PIN): cv.All(
 | 
					        cv.Optional(CONF_WAKEUP_PIN): cv.All(
 | 
				
			||||||
            cv.only_on_esp32, pins.internal_gpio_input_pin_schema, validate_pin_number
 | 
					            cv.only_on_esp32, pins.internal_gpio_input_pin_schema, validate_pin_number
 | 
				
			||||||
@@ -100,28 +85,7 @@ async def to_code(config):
 | 
				
			|||||||
    if CONF_WAKEUP_PIN_MODE in config:
 | 
					    if CONF_WAKEUP_PIN_MODE in config:
 | 
				
			||||||
        cg.add(var.set_wakeup_pin_mode(config[CONF_WAKEUP_PIN_MODE]))
 | 
					        cg.add(var.set_wakeup_pin_mode(config[CONF_WAKEUP_PIN_MODE]))
 | 
				
			||||||
    if CONF_RUN_DURATION in config:
 | 
					    if CONF_RUN_DURATION in config:
 | 
				
			||||||
        run_duration_config = config[CONF_RUN_DURATION]
 | 
					        cg.add(var.set_run_duration(config[CONF_RUN_DURATION]))
 | 
				
			||||||
        if not isinstance(run_duration_config, dict):
 | 
					 | 
				
			||||||
            cg.add(var.set_run_duration(config[CONF_RUN_DURATION]))
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            default_run_duration = run_duration_config[CONF_DEFAULT]
 | 
					 | 
				
			||||||
            wakeup_cause_to_run_duration = cg.StructInitializer(
 | 
					 | 
				
			||||||
                WakeupCauseToRunDuration,
 | 
					 | 
				
			||||||
                ("default_cause", default_run_duration),
 | 
					 | 
				
			||||||
                (
 | 
					 | 
				
			||||||
                    "touch_cause",
 | 
					 | 
				
			||||||
                    run_duration_config.get(
 | 
					 | 
				
			||||||
                        CONF_TOUCH_WAKEUP_REASON, default_run_duration
 | 
					 | 
				
			||||||
                    ),
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
                (
 | 
					 | 
				
			||||||
                    "gpio_cause",
 | 
					 | 
				
			||||||
                    run_duration_config.get(
 | 
					 | 
				
			||||||
                        CONF_GPIO_WAKEUP_REASON, default_run_duration
 | 
					 | 
				
			||||||
                    ),
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
            cg.add(var.set_run_duration(wakeup_cause_to_run_duration))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if CONF_ESP32_EXT1_WAKEUP in config:
 | 
					    if CONF_ESP32_EXT1_WAKEUP in config:
 | 
				
			||||||
        conf = config[CONF_ESP32_EXT1_WAKEUP]
 | 
					        conf = config[CONF_ESP32_EXT1_WAKEUP]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,35 +13,12 @@ static const char *const TAG = "deep_sleep";
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
bool global_has_deep_sleep = false;  // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
 | 
					bool global_has_deep_sleep = false;  // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
optional<uint32_t> DeepSleepComponent::get_run_duration_() const {
 | 
					 | 
				
			||||||
#ifdef USE_ESP32
 | 
					 | 
				
			||||||
  if (this->wakeup_cause_to_run_duration_.has_value()) {
 | 
					 | 
				
			||||||
    esp_sleep_wakeup_cause_t wakeup_cause = esp_sleep_get_wakeup_cause();
 | 
					 | 
				
			||||||
    switch (wakeup_cause) {
 | 
					 | 
				
			||||||
      case ESP_SLEEP_WAKEUP_EXT0:
 | 
					 | 
				
			||||||
      case ESP_SLEEP_WAKEUP_EXT1:
 | 
					 | 
				
			||||||
        return this->wakeup_cause_to_run_duration_->gpio_cause;
 | 
					 | 
				
			||||||
      case ESP_SLEEP_WAKEUP_TOUCHPAD:
 | 
					 | 
				
			||||||
        return this->wakeup_cause_to_run_duration_->touch_cause;
 | 
					 | 
				
			||||||
      default:
 | 
					 | 
				
			||||||
        return this->wakeup_cause_to_run_duration_->default_cause;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
  return this->run_duration_;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void DeepSleepComponent::setup() {
 | 
					void DeepSleepComponent::setup() {
 | 
				
			||||||
  ESP_LOGCONFIG(TAG, "Setting up Deep Sleep...");
 | 
					  ESP_LOGCONFIG(TAG, "Setting up Deep Sleep...");
 | 
				
			||||||
  global_has_deep_sleep = true;
 | 
					  global_has_deep_sleep = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const optional<uint32_t> run_duration = get_run_duration_();
 | 
					  if (this->run_duration_.has_value())
 | 
				
			||||||
  if (run_duration.has_value()) {
 | 
					    this->set_timeout(*this->run_duration_, [this]() { this->begin_sleep(); });
 | 
				
			||||||
    ESP_LOGI(TAG, "Scheduling Deep Sleep to start in %u ms", *run_duration);
 | 
					 | 
				
			||||||
    this->set_timeout(*run_duration, [this]() { this->begin_sleep(); });
 | 
					 | 
				
			||||||
  } else {
 | 
					 | 
				
			||||||
    ESP_LOGD(TAG, "Not scheduling Deep Sleep, as no run duration is configured.");
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void DeepSleepComponent::dump_config() {
 | 
					void DeepSleepComponent::dump_config() {
 | 
				
			||||||
  ESP_LOGCONFIG(TAG, "Setting up Deep Sleep...");
 | 
					  ESP_LOGCONFIG(TAG, "Setting up Deep Sleep...");
 | 
				
			||||||
@@ -56,11 +33,6 @@ void DeepSleepComponent::dump_config() {
 | 
				
			|||||||
  if (wakeup_pin_ != nullptr) {
 | 
					  if (wakeup_pin_ != nullptr) {
 | 
				
			||||||
    LOG_PIN("  Wakeup Pin: ", this->wakeup_pin_);
 | 
					    LOG_PIN("  Wakeup Pin: ", this->wakeup_pin_);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (this->wakeup_cause_to_run_duration_.has_value()) {
 | 
					 | 
				
			||||||
    ESP_LOGCONFIG(TAG, "  Default Wakeup Run Duration: %u ms", this->wakeup_cause_to_run_duration_->default_cause);
 | 
					 | 
				
			||||||
    ESP_LOGCONFIG(TAG, "  Touch Wakeup Run Duration: %u ms", this->wakeup_cause_to_run_duration_->touch_cause);
 | 
					 | 
				
			||||||
    ESP_LOGCONFIG(TAG, "  GPIO Wakeup Run Duration: %u ms", this->wakeup_cause_to_run_duration_->gpio_cause);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void DeepSleepComponent::loop() {
 | 
					void DeepSleepComponent::loop() {
 | 
				
			||||||
@@ -77,9 +49,6 @@ void DeepSleepComponent::set_wakeup_pin_mode(WakeupPinMode wakeup_pin_mode) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
void DeepSleepComponent::set_ext1_wakeup(Ext1Wakeup ext1_wakeup) { this->ext1_wakeup_ = ext1_wakeup; }
 | 
					void DeepSleepComponent::set_ext1_wakeup(Ext1Wakeup ext1_wakeup) { this->ext1_wakeup_ = ext1_wakeup; }
 | 
				
			||||||
void DeepSleepComponent::set_touch_wakeup(bool touch_wakeup) { this->touch_wakeup_ = touch_wakeup; }
 | 
					void DeepSleepComponent::set_touch_wakeup(bool touch_wakeup) { this->touch_wakeup_ = touch_wakeup; }
 | 
				
			||||||
void DeepSleepComponent::set_run_duration(WakeupCauseToRunDuration wakeup_cause_to_run_duration) {
 | 
					 | 
				
			||||||
  wakeup_cause_to_run_duration_ = wakeup_cause_to_run_duration;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
void DeepSleepComponent::set_run_duration(uint32_t time_ms) { this->run_duration_ = time_ms; }
 | 
					void DeepSleepComponent::set_run_duration(uint32_t time_ms) { this->run_duration_ = time_ms; }
 | 
				
			||||||
void DeepSleepComponent::begin_sleep(bool manual) {
 | 
					void DeepSleepComponent::begin_sleep(bool manual) {
 | 
				
			||||||
@@ -108,10 +77,9 @@ void DeepSleepComponent::begin_sleep(bool manual) {
 | 
				
			|||||||
  if (this->sleep_duration_.has_value())
 | 
					  if (this->sleep_duration_.has_value())
 | 
				
			||||||
    esp_sleep_enable_timer_wakeup(*this->sleep_duration_);
 | 
					    esp_sleep_enable_timer_wakeup(*this->sleep_duration_);
 | 
				
			||||||
  if (this->wakeup_pin_ != nullptr) {
 | 
					  if (this->wakeup_pin_ != nullptr) {
 | 
				
			||||||
    bool level = !this->wakeup_pin_->is_inverted();
 | 
					    bool level = this->wakeup_pin_->is_inverted();
 | 
				
			||||||
    if (this->wakeup_pin_mode_ == WAKEUP_PIN_MODE_INVERT_WAKEUP && this->wakeup_pin_->digital_read()) {
 | 
					    if (this->wakeup_pin_mode_ == WAKEUP_PIN_MODE_INVERT_WAKEUP && this->wakeup_pin_->digital_read())
 | 
				
			||||||
      level = !level;
 | 
					      level = !level;
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    esp_sleep_enable_ext0_wakeup(gpio_num_t(this->wakeup_pin_->get_pin()), level);
 | 
					    esp_sleep_enable_ext0_wakeup(gpio_num_t(this->wakeup_pin_->get_pin()), level);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (this->ext1_wakeup_.has_value()) {
 | 
					  if (this->ext1_wakeup_.has_value()) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,15 +32,6 @@ struct Ext1Wakeup {
 | 
				
			|||||||
  esp_sleep_ext1_wakeup_mode_t wakeup_mode;
 | 
					  esp_sleep_ext1_wakeup_mode_t wakeup_mode;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct WakeupCauseToRunDuration {
 | 
					 | 
				
			||||||
  // Run duration if woken up by timer or any other reason besides those below.
 | 
					 | 
				
			||||||
  uint32_t default_cause;
 | 
					 | 
				
			||||||
  // Run duration if woken up by touch pads.
 | 
					 | 
				
			||||||
  uint32_t touch_cause;
 | 
					 | 
				
			||||||
  // Run duration if woken up by GPIO pins.
 | 
					 | 
				
			||||||
  uint32_t gpio_cause;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template<typename... Ts> class EnterDeepSleepAction;
 | 
					template<typename... Ts> class EnterDeepSleepAction;
 | 
				
			||||||
@@ -68,11 +59,6 @@ class DeepSleepComponent : public Component {
 | 
				
			|||||||
  void set_ext1_wakeup(Ext1Wakeup ext1_wakeup);
 | 
					  void set_ext1_wakeup(Ext1Wakeup ext1_wakeup);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void set_touch_wakeup(bool touch_wakeup);
 | 
					  void set_touch_wakeup(bool touch_wakeup);
 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Set the duration in ms for how long the code should run before entering
 | 
					 | 
				
			||||||
  // deep sleep mode, according to the cause the ESP32 has woken.
 | 
					 | 
				
			||||||
  void set_run_duration(WakeupCauseToRunDuration wakeup_cause_to_run_duration);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
  /// Set a duration in ms for how long the code should run before entering deep sleep mode.
 | 
					  /// Set a duration in ms for how long the code should run before entering deep sleep mode.
 | 
				
			||||||
  void set_run_duration(uint32_t time_ms);
 | 
					  void set_run_duration(uint32_t time_ms);
 | 
				
			||||||
@@ -89,17 +75,12 @@ class DeepSleepComponent : public Component {
 | 
				
			|||||||
  void prevent_deep_sleep();
 | 
					  void prevent_deep_sleep();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 protected:
 | 
					 protected:
 | 
				
			||||||
  // Returns nullopt if no run duration is set. Otherwise, returns the run
 | 
					 | 
				
			||||||
  // duration before entering deep sleep.
 | 
					 | 
				
			||||||
  optional<uint32_t> get_run_duration_() const;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  optional<uint64_t> sleep_duration_;
 | 
					  optional<uint64_t> sleep_duration_;
 | 
				
			||||||
#ifdef USE_ESP32
 | 
					#ifdef USE_ESP32
 | 
				
			||||||
  InternalGPIOPin *wakeup_pin_;
 | 
					  InternalGPIOPin *wakeup_pin_;
 | 
				
			||||||
  WakeupPinMode wakeup_pin_mode_{WAKEUP_PIN_MODE_IGNORE};
 | 
					  WakeupPinMode wakeup_pin_mode_{WAKEUP_PIN_MODE_IGNORE};
 | 
				
			||||||
  optional<Ext1Wakeup> ext1_wakeup_;
 | 
					  optional<Ext1Wakeup> ext1_wakeup_;
 | 
				
			||||||
  optional<bool> touch_wakeup_;
 | 
					  optional<bool> touch_wakeup_;
 | 
				
			||||||
  optional<WakeupCauseToRunDuration> wakeup_cause_to_run_duration_;
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
  optional<uint32_t> run_duration_;
 | 
					  optional<uint32_t> run_duration_;
 | 
				
			||||||
  bool next_enter_deep_sleep_{false};
 | 
					  bool next_enter_deep_sleep_{false};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,6 @@ import esphome.config_validation as cv
 | 
				
			|||||||
from esphome import core, automation
 | 
					from esphome import core, automation
 | 
				
			||||||
from esphome.automation import maybe_simple_id
 | 
					from esphome.automation import maybe_simple_id
 | 
				
			||||||
from esphome.const import (
 | 
					from esphome.const import (
 | 
				
			||||||
    CONF_AUTO_CLEAR_ENABLED,
 | 
					 | 
				
			||||||
    CONF_ID,
 | 
					    CONF_ID,
 | 
				
			||||||
    CONF_LAMBDA,
 | 
					    CONF_LAMBDA,
 | 
				
			||||||
    CONF_PAGES,
 | 
					    CONF_PAGES,
 | 
				
			||||||
@@ -80,7 +79,6 @@ FULL_DISPLAY_SCHEMA = BASIC_DISPLAY_SCHEMA.extend(
 | 
				
			|||||||
                cv.Optional(CONF_TO): cv.use_id(DisplayPage),
 | 
					                cv.Optional(CONF_TO): cv.use_id(DisplayPage),
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        cv.Optional(CONF_AUTO_CLEAR_ENABLED, default=True): cv.boolean,
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -88,10 +86,6 @@ FULL_DISPLAY_SCHEMA = BASIC_DISPLAY_SCHEMA.extend(
 | 
				
			|||||||
async def setup_display_core_(var, config):
 | 
					async def setup_display_core_(var, config):
 | 
				
			||||||
    if CONF_ROTATION in config:
 | 
					    if CONF_ROTATION in config:
 | 
				
			||||||
        cg.add(var.set_rotation(DISPLAY_ROTATIONS[config[CONF_ROTATION]]))
 | 
					        cg.add(var.set_rotation(DISPLAY_ROTATIONS[config[CONF_ROTATION]]))
 | 
				
			||||||
 | 
					 | 
				
			||||||
    if CONF_AUTO_CLEAR_ENABLED in config:
 | 
					 | 
				
			||||||
        cg.add(var.set_auto_clear(config[CONF_AUTO_CLEAR_ENABLED]))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if CONF_PAGES in config:
 | 
					    if CONF_PAGES in config:
 | 
				
			||||||
        pages = []
 | 
					        pages = []
 | 
				
			||||||
        for conf in config[CONF_PAGES]:
 | 
					        for conf in config[CONF_PAGES]:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -336,9 +336,7 @@ void DisplayBuffer::show_page(DisplayPage *page) {
 | 
				
			|||||||
void DisplayBuffer::show_next_page() { this->page_->show_next(); }
 | 
					void DisplayBuffer::show_next_page() { this->page_->show_next(); }
 | 
				
			||||||
void DisplayBuffer::show_prev_page() { this->page_->show_prev(); }
 | 
					void DisplayBuffer::show_prev_page() { this->page_->show_prev(); }
 | 
				
			||||||
void DisplayBuffer::do_update_() {
 | 
					void DisplayBuffer::do_update_() {
 | 
				
			||||||
  if (this->auto_clear_enabled_) {
 | 
					  this->clear();
 | 
				
			||||||
    this->clear();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (this->page_ != nullptr) {
 | 
					  if (this->page_ != nullptr) {
 | 
				
			||||||
    this->page_->get_writer()(*this);
 | 
					    this->page_->get_writer()(*this);
 | 
				
			||||||
  } else if (this->writer_.has_value()) {
 | 
					  } else if (this->writer_.has_value()) {
 | 
				
			||||||
@@ -496,7 +494,7 @@ bool Animation::get_pixel(int x, int y) const {
 | 
				
			|||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
  const uint32_t width_8 = ((this->width_ + 7u) / 8u) * 8u;
 | 
					  const uint32_t width_8 = ((this->width_ + 7u) / 8u) * 8u;
 | 
				
			||||||
  const uint32_t frame_index = this->height_ * width_8 * this->current_frame_;
 | 
					  const uint32_t frame_index = this->height_ * width_8 * this->current_frame_;
 | 
				
			||||||
  if (frame_index >= (uint32_t)(this->width_ * this->height_ * this->animation_frame_count_))
 | 
					  if (frame_index >= this->width_ * this->height_ * this->animation_frame_count_)
 | 
				
			||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
  const uint32_t pos = x + y * width_8 + frame_index;
 | 
					  const uint32_t pos = x + y * width_8 + frame_index;
 | 
				
			||||||
  return progmem_read_byte(this->data_start_ + (pos / 8u)) & (0x80 >> (pos % 8u));
 | 
					  return progmem_read_byte(this->data_start_ + (pos / 8u)) & (0x80 >> (pos % 8u));
 | 
				
			||||||
@@ -505,7 +503,7 @@ Color Animation::get_color_pixel(int x, int y) const {
 | 
				
			|||||||
  if (x < 0 || x >= this->width_ || y < 0 || y >= this->height_)
 | 
					  if (x < 0 || x >= this->width_ || y < 0 || y >= this->height_)
 | 
				
			||||||
    return Color::BLACK;
 | 
					    return Color::BLACK;
 | 
				
			||||||
  const uint32_t frame_index = this->width_ * this->height_ * this->current_frame_;
 | 
					  const uint32_t frame_index = this->width_ * this->height_ * this->current_frame_;
 | 
				
			||||||
  if (frame_index >= (uint32_t)(this->width_ * this->height_ * this->animation_frame_count_))
 | 
					  if (frame_index >= this->width_ * this->height_ * this->animation_frame_count_)
 | 
				
			||||||
    return Color::BLACK;
 | 
					    return Color::BLACK;
 | 
				
			||||||
  const uint32_t pos = (x + y * this->width_ + frame_index) * 3;
 | 
					  const uint32_t pos = (x + y * this->width_ + frame_index) * 3;
 | 
				
			||||||
  const uint32_t color32 = (progmem_read_byte(this->data_start_ + pos + 2) << 0) |
 | 
					  const uint32_t color32 = (progmem_read_byte(this->data_start_ + pos + 2) << 0) |
 | 
				
			||||||
@@ -517,7 +515,7 @@ Color Animation::get_grayscale_pixel(int x, int y) const {
 | 
				
			|||||||
  if (x < 0 || x >= this->width_ || y < 0 || y >= this->height_)
 | 
					  if (x < 0 || x >= this->width_ || y < 0 || y >= this->height_)
 | 
				
			||||||
    return Color::BLACK;
 | 
					    return Color::BLACK;
 | 
				
			||||||
  const uint32_t frame_index = this->width_ * this->height_ * this->current_frame_;
 | 
					  const uint32_t frame_index = this->width_ * this->height_ * this->current_frame_;
 | 
				
			||||||
  if (frame_index >= (uint32_t)(this->width_ * this->height_ * this->animation_frame_count_))
 | 
					  if (frame_index >= this->width_ * this->height_ * this->animation_frame_count_)
 | 
				
			||||||
    return Color::BLACK;
 | 
					    return Color::BLACK;
 | 
				
			||||||
  const uint32_t pos = (x + y * this->width_ + frame_index);
 | 
					  const uint32_t pos = (x + y * this->width_ + frame_index);
 | 
				
			||||||
  const uint8_t gray = progmem_read_byte(this->data_start_ + pos);
 | 
					  const uint8_t gray = progmem_read_byte(this->data_start_ + pos);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -333,9 +333,6 @@ class DisplayBuffer {
 | 
				
			|||||||
  /// Internal method to set the display rotation with.
 | 
					  /// Internal method to set the display rotation with.
 | 
				
			||||||
  void set_rotation(DisplayRotation rotation);
 | 
					  void set_rotation(DisplayRotation rotation);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Internal method to set display auto clearing.
 | 
					 | 
				
			||||||
  void set_auto_clear(bool auto_clear_enabled) { this->auto_clear_enabled_ = auto_clear_enabled; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 protected:
 | 
					 protected:
 | 
				
			||||||
  void vprintf_(int x, int y, Font *font, Color color, TextAlign align, const char *format, va_list arg);
 | 
					  void vprintf_(int x, int y, Font *font, Color color, TextAlign align, const char *format, va_list arg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -355,7 +352,6 @@ class DisplayBuffer {
 | 
				
			|||||||
  DisplayPage *page_{nullptr};
 | 
					  DisplayPage *page_{nullptr};
 | 
				
			||||||
  DisplayPage *previous_page_{nullptr};
 | 
					  DisplayPage *previous_page_{nullptr};
 | 
				
			||||||
  std::vector<DisplayOnPageChangeTrigger *> on_page_change_triggers_;
 | 
					  std::vector<DisplayOnPageChangeTrigger *> on_page_change_triggers_;
 | 
				
			||||||
  bool auto_clear_enabled_{true};
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DisplayPage {
 | 
					class DisplayPage {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,7 +42,7 @@ class ColorUtil {
 | 
				
			|||||||
                       ? esp_scale(((colorcode >> third_bits) & ((1 << second_bits) - 1)), ((1 << second_bits) - 1))
 | 
					                       ? esp_scale(((colorcode >> third_bits) & ((1 << second_bits) - 1)), ((1 << second_bits) - 1))
 | 
				
			||||||
                       : esp_scale(((colorcode >> 8) & 0xFF), ((1 << second_bits) - 1));
 | 
					                       : esp_scale(((colorcode >> 8) & 0xFF), ((1 << second_bits) - 1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    third_color = (right_bit_aligned ? esp_scale(((colorcode >> 0) & ((1 << third_bits) - 1)), ((1 << third_bits) - 1))
 | 
					    third_color = (right_bit_aligned ? esp_scale(((colorcode >> 0) & 0xFF), ((1 << third_bits) - 1))
 | 
				
			||||||
                                     : esp_scale(((colorcode >> 0) & 0xFF), (1 << third_bits) - 1));
 | 
					                                     : esp_scale(((colorcode >> 0) & 0xFF), (1 << third_bits) - 1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Color color_return;
 | 
					    Color color_return;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,9 @@
 | 
				
			|||||||
import esphome.codegen as cg
 | 
					import esphome.codegen as cg
 | 
				
			||||||
import esphome.config_validation as cv
 | 
					import esphome.config_validation as cv
 | 
				
			||||||
from esphome import pins
 | 
					 | 
				
			||||||
from esphome.components import uart
 | 
					from esphome.components import uart
 | 
				
			||||||
from esphome.const import (
 | 
					from esphome.const import (
 | 
				
			||||||
    CONF_ID,
 | 
					    CONF_ID,
 | 
				
			||||||
    CONF_UART_ID,
 | 
					    CONF_UART_ID,
 | 
				
			||||||
    CONF_RECEIVE_TIMEOUT,
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CODEOWNERS = ["@glmnet", "@zuidwijk"]
 | 
					CODEOWNERS = ["@glmnet", "@zuidwijk"]
 | 
				
			||||||
@@ -13,13 +11,10 @@ CODEOWNERS = ["@glmnet", "@zuidwijk"]
 | 
				
			|||||||
DEPENDENCIES = ["uart"]
 | 
					DEPENDENCIES = ["uart"]
 | 
				
			||||||
AUTO_LOAD = ["sensor", "text_sensor"]
 | 
					AUTO_LOAD = ["sensor", "text_sensor"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CONF_CRC_CHECK = "crc_check"
 | 
					 | 
				
			||||||
CONF_DECRYPTION_KEY = "decryption_key"
 | 
					 | 
				
			||||||
CONF_DSMR_ID = "dsmr_id"
 | 
					CONF_DSMR_ID = "dsmr_id"
 | 
				
			||||||
 | 
					CONF_DECRYPTION_KEY = "decryption_key"
 | 
				
			||||||
 | 
					CONF_CRC_CHECK = "crc_check"
 | 
				
			||||||
CONF_GAS_MBUS_ID = "gas_mbus_id"
 | 
					CONF_GAS_MBUS_ID = "gas_mbus_id"
 | 
				
			||||||
CONF_MAX_TELEGRAM_LENGTH = "max_telegram_length"
 | 
					 | 
				
			||||||
CONF_REQUEST_INTERVAL = "request_interval"
 | 
					 | 
				
			||||||
CONF_REQUEST_PIN = "request_pin"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Hack to prevent compile error due to ambiguity with lib namespace
 | 
					# Hack to prevent compile error due to ambiguity with lib namespace
 | 
				
			||||||
dsmr_ns = cg.esphome_ns.namespace("esphome::dsmr")
 | 
					dsmr_ns = cg.esphome_ns.namespace("esphome::dsmr")
 | 
				
			||||||
@@ -51,14 +46,6 @@ CONFIG_SCHEMA = cv.All(
 | 
				
			|||||||
            cv.Optional(CONF_DECRYPTION_KEY): _validate_key,
 | 
					            cv.Optional(CONF_DECRYPTION_KEY): _validate_key,
 | 
				
			||||||
            cv.Optional(CONF_CRC_CHECK, default=True): cv.boolean,
 | 
					            cv.Optional(CONF_CRC_CHECK, default=True): cv.boolean,
 | 
				
			||||||
            cv.Optional(CONF_GAS_MBUS_ID, default=1): cv.int_,
 | 
					            cv.Optional(CONF_GAS_MBUS_ID, default=1): cv.int_,
 | 
				
			||||||
            cv.Optional(CONF_MAX_TELEGRAM_LENGTH, default=1500): cv.int_,
 | 
					 | 
				
			||||||
            cv.Optional(CONF_REQUEST_PIN): pins.gpio_output_pin_schema,
 | 
					 | 
				
			||||||
            cv.Optional(
 | 
					 | 
				
			||||||
                CONF_REQUEST_INTERVAL, default="0ms"
 | 
					 | 
				
			||||||
            ): cv.positive_time_period_milliseconds,
 | 
					 | 
				
			||||||
            cv.Optional(
 | 
					 | 
				
			||||||
                CONF_RECEIVE_TIMEOUT, default="200ms"
 | 
					 | 
				
			||||||
            ): cv.positive_time_period_milliseconds,
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ).extend(uart.UART_DEVICE_SCHEMA),
 | 
					    ).extend(uart.UART_DEVICE_SCHEMA),
 | 
				
			||||||
    cv.only_with_arduino,
 | 
					    cv.only_with_arduino,
 | 
				
			||||||
@@ -68,17 +55,10 @@ CONFIG_SCHEMA = cv.All(
 | 
				
			|||||||
async def to_code(config):
 | 
					async def to_code(config):
 | 
				
			||||||
    uart_component = await cg.get_variable(config[CONF_UART_ID])
 | 
					    uart_component = await cg.get_variable(config[CONF_UART_ID])
 | 
				
			||||||
    var = cg.new_Pvariable(config[CONF_ID], uart_component, config[CONF_CRC_CHECK])
 | 
					    var = cg.new_Pvariable(config[CONF_ID], uart_component, config[CONF_CRC_CHECK])
 | 
				
			||||||
    cg.add(var.set_max_telegram_length(config[CONF_MAX_TELEGRAM_LENGTH]))
 | 
					 | 
				
			||||||
    if CONF_DECRYPTION_KEY in config:
 | 
					    if CONF_DECRYPTION_KEY in config:
 | 
				
			||||||
        cg.add(var.set_decryption_key(config[CONF_DECRYPTION_KEY]))
 | 
					        cg.add(var.set_decryption_key(config[CONF_DECRYPTION_KEY]))
 | 
				
			||||||
    await cg.register_component(var, config)
 | 
					    await cg.register_component(var, config)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if CONF_REQUEST_PIN in config:
 | 
					 | 
				
			||||||
        request_pin = await cg.gpio_pin_expression(config[CONF_REQUEST_PIN])
 | 
					 | 
				
			||||||
        cg.add(var.set_request_pin(request_pin))
 | 
					 | 
				
			||||||
    cg.add(var.set_request_interval(config[CONF_REQUEST_INTERVAL].total_milliseconds))
 | 
					 | 
				
			||||||
    cg.add(var.set_receive_timeout(config[CONF_RECEIVE_TIMEOUT].total_milliseconds))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    cg.add_define("DSMR_GAS_MBUS_ID", config[CONF_GAS_MBUS_ID])
 | 
					    cg.add_define("DSMR_GAS_MBUS_ID", config[CONF_GAS_MBUS_ID])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # DSMR Parser
 | 
					    # DSMR Parser
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,275 +12,156 @@ namespace dsmr {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static const char *const TAG = "dsmr";
 | 
					static const char *const TAG = "dsmr";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Dsmr::setup() {
 | 
					 | 
				
			||||||
  this->telegram_ = new char[this->max_telegram_len_];  // NOLINT
 | 
					 | 
				
			||||||
  if (this->request_pin_ != nullptr) {
 | 
					 | 
				
			||||||
    this->request_pin_->setup();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void Dsmr::loop() {
 | 
					void Dsmr::loop() {
 | 
				
			||||||
  if (this->ready_to_request_data_()) {
 | 
					  if (this->decryption_key_.empty())
 | 
				
			||||||
    if (this->decryption_key_.empty()) {
 | 
					    this->receive_telegram_();
 | 
				
			||||||
      this->receive_telegram_();
 | 
					  else
 | 
				
			||||||
    } else {
 | 
					    this->receive_encrypted_();
 | 
				
			||||||
      this->receive_encrypted_telegram_();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool Dsmr::ready_to_request_data_() {
 | 
					 | 
				
			||||||
  // When using a request pin, then wait for the next request interval.
 | 
					 | 
				
			||||||
  if (this->request_pin_ != nullptr) {
 | 
					 | 
				
			||||||
    if (!this->requesting_data_ && this->request_interval_reached_()) {
 | 
					 | 
				
			||||||
      this->start_requesting_data_();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  // Otherwise, sink serial data until next request interval.
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    if (this->request_interval_reached_()) {
 | 
					 | 
				
			||||||
      this->start_requesting_data_();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (!this->requesting_data_) {
 | 
					 | 
				
			||||||
      while (this->available()) {
 | 
					 | 
				
			||||||
        this->read();
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return this->requesting_data_;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool Dsmr::request_interval_reached_() {
 | 
					 | 
				
			||||||
  if (this->last_request_time_ == 0) {
 | 
					 | 
				
			||||||
    return true;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return millis() - this->last_request_time_ > this->request_interval_;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool Dsmr::receive_timeout_reached_() { return millis() - this->last_read_time_ > this->receive_timeout_; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool Dsmr::available_within_timeout_() {
 | 
					 | 
				
			||||||
  // Data are available for reading on the UART bus?
 | 
					 | 
				
			||||||
  // Then we can start reading right away.
 | 
					 | 
				
			||||||
  if (this->available()) {
 | 
					 | 
				
			||||||
    this->last_read_time_ = millis();
 | 
					 | 
				
			||||||
    return true;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  // When we're not in the process of reading a telegram, then there is
 | 
					 | 
				
			||||||
  // no need to actively wait for new data to come in.
 | 
					 | 
				
			||||||
  if (!header_found_) {
 | 
					 | 
				
			||||||
    return false;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  // A telegram is being read. The smart meter might not deliver a telegram
 | 
					 | 
				
			||||||
  // in one go, but instead send it in chunks with small pauses in between.
 | 
					 | 
				
			||||||
  // When the UART RX buffer cannot hold a full telegram, then make sure
 | 
					 | 
				
			||||||
  // that the UART read buffer does not overflow while other components
 | 
					 | 
				
			||||||
  // perform their work in their loop. Do this by not returning control to
 | 
					 | 
				
			||||||
  // the main loop, until the read timeout is reached.
 | 
					 | 
				
			||||||
  if (this->parent_->get_rx_buffer_size() < this->max_telegram_len_) {
 | 
					 | 
				
			||||||
    while (!this->receive_timeout_reached_()) {
 | 
					 | 
				
			||||||
      delay(5);
 | 
					 | 
				
			||||||
      if (this->available()) {
 | 
					 | 
				
			||||||
        this->last_read_time_ = millis();
 | 
					 | 
				
			||||||
        return true;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  // No new data has come in during the read timeout? Then stop reading the
 | 
					 | 
				
			||||||
  // telegram and start waiting for the next one to arrive.
 | 
					 | 
				
			||||||
  if (this->receive_timeout_reached_()) {
 | 
					 | 
				
			||||||
    ESP_LOGW(TAG, "Timeout while reading data for telegram");
 | 
					 | 
				
			||||||
    this->reset_telegram_();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return false;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void Dsmr::start_requesting_data_() {
 | 
					 | 
				
			||||||
  if (!this->requesting_data_) {
 | 
					 | 
				
			||||||
    if (this->request_pin_ != nullptr) {
 | 
					 | 
				
			||||||
      ESP_LOGV(TAG, "Start requesting data from P1 port");
 | 
					 | 
				
			||||||
      this->request_pin_->digital_write(true);
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      ESP_LOGV(TAG, "Start reading data from P1 port");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    this->requesting_data_ = true;
 | 
					 | 
				
			||||||
    this->last_request_time_ = millis();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void Dsmr::stop_requesting_data_() {
 | 
					 | 
				
			||||||
  if (this->requesting_data_) {
 | 
					 | 
				
			||||||
    if (this->request_pin_ != nullptr) {
 | 
					 | 
				
			||||||
      ESP_LOGV(TAG, "Stop requesting data from P1 port");
 | 
					 | 
				
			||||||
      this->request_pin_->digital_write(false);
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      ESP_LOGV(TAG, "Stop reading data from P1 port");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    while (this->available()) {
 | 
					 | 
				
			||||||
      this->read();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    this->requesting_data_ = false;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void Dsmr::reset_telegram_() {
 | 
					 | 
				
			||||||
  this->header_found_ = false;
 | 
					 | 
				
			||||||
  this->footer_found_ = false;
 | 
					 | 
				
			||||||
  this->bytes_read_ = 0;
 | 
					 | 
				
			||||||
  this->crypt_bytes_read_ = 0;
 | 
					 | 
				
			||||||
  this->crypt_telegram_len_ = 0;
 | 
					 | 
				
			||||||
  this->last_read_time_ = 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Dsmr::receive_telegram_() {
 | 
					void Dsmr::receive_telegram_() {
 | 
				
			||||||
  while (this->available_within_timeout_()) {
 | 
					  int count = MAX_BYTES_PER_LOOP;
 | 
				
			||||||
    const char c = this->read();
 | 
					  while (available() && count-- > 0) {
 | 
				
			||||||
 | 
					    const char c = read();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Find a new telegram header, i.e. forward slash.
 | 
					    // Find a new telegram header, i.e. forward slash.
 | 
				
			||||||
    if (c == '/') {
 | 
					    if (c == '/') {
 | 
				
			||||||
      ESP_LOGV(TAG, "Header of telegram found");
 | 
					      ESP_LOGV(TAG, "Header found");
 | 
				
			||||||
      this->reset_telegram_();
 | 
					      header_found_ = true;
 | 
				
			||||||
      this->header_found_ = true;
 | 
					      footer_found_ = false;
 | 
				
			||||||
 | 
					      telegram_len_ = 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (!this->header_found_)
 | 
					    if (!header_found_)
 | 
				
			||||||
      continue;
 | 
					      continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Check for buffer overflow.
 | 
					    // Check for buffer overflow.
 | 
				
			||||||
    if (this->bytes_read_ >= this->max_telegram_len_) {
 | 
					    if (telegram_len_ >= MAX_TELEGRAM_LENGTH) {
 | 
				
			||||||
      this->reset_telegram_();
 | 
					      header_found_ = false;
 | 
				
			||||||
      ESP_LOGE(TAG, "Error: telegram larger than buffer (%d bytes)", this->max_telegram_len_);
 | 
					      footer_found_ = false;
 | 
				
			||||||
 | 
					      ESP_LOGE(TAG, "Error: Message larger than buffer");
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Some v2.2 or v3 meters will send a new value which starts with '('
 | 
					    // Some v2.2 or v3 meters will send a new value which starts with '('
 | 
				
			||||||
    // in a new line, while the value belongs to the previous ObisId. For
 | 
					    // in a new line while the value belongs to the previous ObisId. For
 | 
				
			||||||
    // proper parsing, remove these new line characters.
 | 
					    // proper parsing remove these new line characters
 | 
				
			||||||
    if (c == '(') {
 | 
					    while (c == '(' && (telegram_[telegram_len_ - 1] == '\n' || telegram_[telegram_len_ - 1] == '\r'))
 | 
				
			||||||
      while (true) {
 | 
					      telegram_len_--;
 | 
				
			||||||
        auto previous_char = this->telegram_[this->bytes_read_ - 1];
 | 
					 | 
				
			||||||
        if (previous_char == '\n' || previous_char == '\r') {
 | 
					 | 
				
			||||||
          this->bytes_read_--;
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
          break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Store the byte in the buffer.
 | 
					    // Store the byte in the buffer.
 | 
				
			||||||
    this->telegram_[this->bytes_read_] = c;
 | 
					    telegram_[telegram_len_] = c;
 | 
				
			||||||
    this->bytes_read_++;
 | 
					    telegram_len_++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Check for a footer, i.e. exlamation mark, followed by a hex checksum.
 | 
					    // Check for a footer, i.e. exlamation mark, followed by a hex checksum.
 | 
				
			||||||
    if (c == '!') {
 | 
					    if (c == '!') {
 | 
				
			||||||
      ESP_LOGV(TAG, "Footer of telegram found");
 | 
					      ESP_LOGV(TAG, "Footer found");
 | 
				
			||||||
      this->footer_found_ = true;
 | 
					      footer_found_ = true;
 | 
				
			||||||
      continue;
 | 
					      continue;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // Check for the end of the hex checksum, i.e. a newline.
 | 
					    // Check for the end of the hex checksum, i.e. a newline.
 | 
				
			||||||
    if (this->footer_found_ && c == '\n') {
 | 
					    if (footer_found_ && c == '\n') {
 | 
				
			||||||
 | 
					      header_found_ = false;
 | 
				
			||||||
      // Parse the telegram and publish sensor values.
 | 
					      // Parse the telegram and publish sensor values.
 | 
				
			||||||
      this->parse_telegram();
 | 
					      if (parse_telegram())
 | 
				
			||||||
      this->reset_telegram_();
 | 
					        return;
 | 
				
			||||||
      return;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Dsmr::receive_encrypted_telegram_() {
 | 
					void Dsmr::receive_encrypted_() {
 | 
				
			||||||
  while (this->available_within_timeout_()) {
 | 
					  // Encrypted buffer
 | 
				
			||||||
    const char c = this->read();
 | 
					  uint8_t buffer[MAX_TELEGRAM_LENGTH];
 | 
				
			||||||
 | 
					  size_t buffer_length = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Find a new telegram start byte.
 | 
					  size_t packet_size = 0;
 | 
				
			||||||
    if (!this->header_found_) {
 | 
					  while (available()) {
 | 
				
			||||||
      if ((uint8_t) c != 0xDB) {
 | 
					    const char c = read();
 | 
				
			||||||
        continue;
 | 
					
 | 
				
			||||||
 | 
					    if (!header_found_) {
 | 
				
			||||||
 | 
					      if ((uint8_t) c == 0xdb) {
 | 
				
			||||||
 | 
					        ESP_LOGV(TAG, "Start byte 0xDB found");
 | 
				
			||||||
 | 
					        header_found_ = true;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      ESP_LOGV(TAG, "Start byte 0xDB of encrypted telegram found");
 | 
					 | 
				
			||||||
      this->reset_telegram_();
 | 
					 | 
				
			||||||
      this->header_found_ = true;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Check for buffer overflow.
 | 
					    // Sanity check
 | 
				
			||||||
    if (this->crypt_bytes_read_ >= this->max_telegram_len_) {
 | 
					    if (!header_found_ || buffer_length >= MAX_TELEGRAM_LENGTH) {
 | 
				
			||||||
      this->reset_telegram_();
 | 
					      if (buffer_length == 0) {
 | 
				
			||||||
      ESP_LOGE(TAG, "Error: encrypted telegram larger than buffer (%d bytes)", this->max_telegram_len_);
 | 
					        ESP_LOGE(TAG, "First byte of encrypted telegram should be 0xDB, aborting.");
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        ESP_LOGW(TAG, "Unexpected data");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      this->status_momentary_warning("unexpected_data");
 | 
				
			||||||
 | 
					      this->flush();
 | 
				
			||||||
 | 
					      while (available())
 | 
				
			||||||
 | 
					        read();
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Store the byte in the buffer.
 | 
					    buffer[buffer_length++] = c;
 | 
				
			||||||
    this->crypt_telegram_[this->crypt_bytes_read_] = c;
 | 
					 | 
				
			||||||
    this->crypt_bytes_read_++;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Read the length of the incoming encrypted telegram.
 | 
					    if (packet_size == 0 && buffer_length > 20) {
 | 
				
			||||||
    if (this->crypt_telegram_len_ == 0 && this->crypt_bytes_read_ > 20) {
 | 
					      // Complete header + a few bytes of data
 | 
				
			||||||
      // Complete header + data bytes
 | 
					      packet_size = buffer[11] << 8 | buffer[12];
 | 
				
			||||||
      this->crypt_telegram_len_ = 13 + (this->crypt_telegram_[11] << 8 | this->crypt_telegram_[12]);
 | 
					    }
 | 
				
			||||||
      ESP_LOGV(TAG, "Encrypted telegram length: %d bytes", this->crypt_telegram_len_);
 | 
					    if (buffer_length == packet_size + 13 && packet_size > 0) {
 | 
				
			||||||
 | 
					      ESP_LOGV(TAG, "Encrypted data: %d bytes", buffer_length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      GCM<AES128> *gcmaes128{new GCM<AES128>()};
 | 
				
			||||||
 | 
					      gcmaes128->setKey(this->decryption_key_.data(), gcmaes128->keySize());
 | 
				
			||||||
 | 
					      // the iv is 8 bytes of the system title + 4 bytes frame counter
 | 
				
			||||||
 | 
					      // system title is at byte 2 and frame counter at byte 15
 | 
				
			||||||
 | 
					      for (int i = 10; i < 14; i++)
 | 
				
			||||||
 | 
					        buffer[i] = buffer[i + 4];
 | 
				
			||||||
 | 
					      constexpr uint16_t iv_size{12};
 | 
				
			||||||
 | 
					      gcmaes128->setIV(&buffer[2], iv_size);
 | 
				
			||||||
 | 
					      gcmaes128->decrypt(reinterpret_cast<uint8_t *>(this->telegram_),
 | 
				
			||||||
 | 
					                         // the ciphertext start at byte 18
 | 
				
			||||||
 | 
					                         &buffer[18],
 | 
				
			||||||
 | 
					                         // cipher size
 | 
				
			||||||
 | 
					                         buffer_length - 17);
 | 
				
			||||||
 | 
					      delete gcmaes128;  // NOLINT(cppcoreguidelines-owning-memory)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      telegram_len_ = strnlen(this->telegram_, sizeof(this->telegram_));
 | 
				
			||||||
 | 
					      ESP_LOGV(TAG, "Decrypted data length: %d", telegram_len_);
 | 
				
			||||||
 | 
					      ESP_LOGVV(TAG, "Decrypted data %s", this->telegram_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      parse_telegram();
 | 
				
			||||||
 | 
					      telegram_len_ = 0;
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Check for the end of the encrypted telegram.
 | 
					    if (!available()) {
 | 
				
			||||||
    if (this->crypt_telegram_len_ == 0 || this->crypt_bytes_read_ != this->crypt_telegram_len_) {
 | 
					      // baud rate is 115200 for encrypted data, this means a few byte should arrive every time
 | 
				
			||||||
      continue;
 | 
					      // program runs faster than buffer loading then available() might return false in the middle
 | 
				
			||||||
 | 
					      delay(4);  // Wait for data
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    ESP_LOGV(TAG, "End of encrypted telegram found");
 | 
					  }
 | 
				
			||||||
 | 
					  if (buffer_length > 0) {
 | 
				
			||||||
    // Decrypt the encrypted telegram.
 | 
					    ESP_LOGW(TAG, "Timeout while waiting for encrypted data or invalid data received.");
 | 
				
			||||||
    GCM<AES128> *gcmaes128{new GCM<AES128>()};
 | 
					 | 
				
			||||||
    gcmaes128->setKey(this->decryption_key_.data(), gcmaes128->keySize());
 | 
					 | 
				
			||||||
    // the iv is 8 bytes of the system title + 4 bytes frame counter
 | 
					 | 
				
			||||||
    // system title is at byte 2 and frame counter at byte 15
 | 
					 | 
				
			||||||
    for (int i = 10; i < 14; i++)
 | 
					 | 
				
			||||||
      this->crypt_telegram_[i] = this->crypt_telegram_[i + 4];
 | 
					 | 
				
			||||||
    constexpr uint16_t iv_size{12};
 | 
					 | 
				
			||||||
    gcmaes128->setIV(&this->crypt_telegram_[2], iv_size);
 | 
					 | 
				
			||||||
    gcmaes128->decrypt(reinterpret_cast<uint8_t *>(this->telegram_),
 | 
					 | 
				
			||||||
                       // the ciphertext start at byte 18
 | 
					 | 
				
			||||||
                       &this->crypt_telegram_[18],
 | 
					 | 
				
			||||||
                       // cipher size
 | 
					 | 
				
			||||||
                       this->crypt_bytes_read_ - 17);
 | 
					 | 
				
			||||||
    delete gcmaes128;  // NOLINT(cppcoreguidelines-owning-memory)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    this->bytes_read_ = strnlen(this->telegram_, this->max_telegram_len_);
 | 
					 | 
				
			||||||
    ESP_LOGV(TAG, "Decrypted telegram size: %d bytes", this->bytes_read_);
 | 
					 | 
				
			||||||
    ESP_LOGVV(TAG, "Decrypted telegram: %s", this->telegram_);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Parse the decrypted telegram and publish sensor values.
 | 
					 | 
				
			||||||
    this->parse_telegram();
 | 
					 | 
				
			||||||
    this->reset_telegram_();
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool Dsmr::parse_telegram() {
 | 
					bool Dsmr::parse_telegram() {
 | 
				
			||||||
  MyData data;
 | 
					  MyData data;
 | 
				
			||||||
  ESP_LOGV(TAG, "Trying to parse telegram");
 | 
					  ESP_LOGV(TAG, "Trying to parse");
 | 
				
			||||||
  this->stop_requesting_data_();
 | 
					 | 
				
			||||||
  ::dsmr::ParseResult<void> res =
 | 
					  ::dsmr::ParseResult<void> res =
 | 
				
			||||||
      ::dsmr::P1Parser::parse(&data, this->telegram_, this->bytes_read_, false,
 | 
					      ::dsmr::P1Parser::parse(&data, telegram_, telegram_len_, false,
 | 
				
			||||||
                              this->crc_check_);  // Parse telegram according to data definition. Ignore unknown values.
 | 
					                              this->crc_check_);  // Parse telegram according to data definition. Ignore unknown values.
 | 
				
			||||||
  if (res.err) {
 | 
					  if (res.err) {
 | 
				
			||||||
    // Parsing error, show it
 | 
					    // Parsing error, show it
 | 
				
			||||||
    auto err_str = res.fullError(this->telegram_, this->telegram_ + this->bytes_read_);
 | 
					    auto err_str = res.fullError(telegram_, telegram_ + telegram_len_);
 | 
				
			||||||
    ESP_LOGE(TAG, "%s", err_str.c_str());
 | 
					    ESP_LOGE(TAG, "%s", err_str.c_str());
 | 
				
			||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    this->status_clear_warning();
 | 
					    this->status_clear_warning();
 | 
				
			||||||
    this->publish_sensors(data);
 | 
					    publish_sensors(data);
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Dsmr::dump_config() {
 | 
					void Dsmr::dump_config() {
 | 
				
			||||||
  ESP_LOGCONFIG(TAG, "DSMR:");
 | 
					  ESP_LOGCONFIG(TAG, "dsmr:");
 | 
				
			||||||
  ESP_LOGCONFIG(TAG, "  Max telegram length: %d", this->max_telegram_len_);
 | 
					 | 
				
			||||||
  ESP_LOGCONFIG(TAG, "  Receive timeout: %.1fs", this->receive_timeout_ / 1e3f);
 | 
					 | 
				
			||||||
  if (this->request_pin_ != nullptr) {
 | 
					 | 
				
			||||||
    LOG_PIN("  Request Pin: ", this->request_pin_);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (this->request_interval_ > 0) {
 | 
					 | 
				
			||||||
    ESP_LOGCONFIG(TAG, "  Request Interval: %.1fs", this->request_interval_ / 1e3f);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DSMR_LOG_SENSOR(s) LOG_SENSOR("  ", #s, this->s_##s##_);
 | 
					#define DSMR_LOG_SENSOR(s) LOG_SENSOR("  ", #s, this->s_##s##_);
 | 
				
			||||||
  DSMR_SENSOR_LIST(DSMR_LOG_SENSOR, )
 | 
					  DSMR_SENSOR_LIST(DSMR_LOG_SENSOR, )
 | 
				
			||||||
@@ -293,31 +174,23 @@ void Dsmr::set_decryption_key(const std::string &decryption_key) {
 | 
				
			|||||||
  if (decryption_key.length() == 0) {
 | 
					  if (decryption_key.length() == 0) {
 | 
				
			||||||
    ESP_LOGI(TAG, "Disabling decryption");
 | 
					    ESP_LOGI(TAG, "Disabling decryption");
 | 
				
			||||||
    this->decryption_key_.clear();
 | 
					    this->decryption_key_.clear();
 | 
				
			||||||
    if (this->crypt_telegram_ != nullptr) {
 | 
					 | 
				
			||||||
      delete[] this->crypt_telegram_;
 | 
					 | 
				
			||||||
      this->crypt_telegram_ = nullptr;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (decryption_key.length() != 32) {
 | 
					  if (decryption_key.length() != 32) {
 | 
				
			||||||
    ESP_LOGE(TAG, "Error, decryption key must be 32 character long");
 | 
					    ESP_LOGE(TAG, "Error, decryption key must be 32 character long.");
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  this->decryption_key_.clear();
 | 
					  this->decryption_key_.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ESP_LOGI(TAG, "Decryption key is set");
 | 
					  ESP_LOGI(TAG, "Decryption key is set.");
 | 
				
			||||||
  // Verbose level prints decryption key
 | 
					  // Verbose level prints decryption key
 | 
				
			||||||
  ESP_LOGV(TAG, "Using decryption key: %s", decryption_key.c_str());
 | 
					  ESP_LOGV(TAG, "Using decryption key: %s", decryption_key.c_str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  char temp[3] = {0};
 | 
					  char temp[3] = {0};
 | 
				
			||||||
  for (int i = 0; i < 16; i++) {
 | 
					  for (int i = 0; i < 16; i++) {
 | 
				
			||||||
    strncpy(temp, &(decryption_key.c_str()[i * 2]), 2);
 | 
					    strncpy(temp, &(decryption_key.c_str()[i * 2]), 2);
 | 
				
			||||||
    this->decryption_key_.push_back(std::strtoul(temp, nullptr, 16));
 | 
					    decryption_key_.push_back(std::strtoul(temp, nullptr, 16));
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (this->crypt_telegram_ == nullptr) {
 | 
					 | 
				
			||||||
    this->crypt_telegram_ = new uint8_t[this->max_telegram_len_];  // NOLINT
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,6 +16,10 @@
 | 
				
			|||||||
namespace esphome {
 | 
					namespace esphome {
 | 
				
			||||||
namespace dsmr {
 | 
					namespace dsmr {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static constexpr uint32_t MAX_TELEGRAM_LENGTH = 1500;
 | 
				
			||||||
 | 
					static constexpr uint32_t MAX_BYTES_PER_LOOP = 50;
 | 
				
			||||||
 | 
					static constexpr uint32_t POLL_TIMEOUT = 1000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using namespace ::dsmr::fields;
 | 
					using namespace ::dsmr::fields;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DSMR_**_LIST generated by ESPHome and written in esphome/core/defines
 | 
					// DSMR_**_LIST generated by ESPHome and written in esphome/core/defines
 | 
				
			||||||
@@ -49,7 +53,6 @@ class Dsmr : public Component, public uart::UARTDevice {
 | 
				
			|||||||
 public:
 | 
					 public:
 | 
				
			||||||
  Dsmr(uart::UARTComponent *uart, bool crc_check) : uart::UARTDevice(uart), crc_check_(crc_check) {}
 | 
					  Dsmr(uart::UARTComponent *uart, bool crc_check) : uart::UARTDevice(uart), crc_check_(crc_check) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void setup() override;
 | 
					 | 
				
			||||||
  void loop() override;
 | 
					  void loop() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool parse_telegram();
 | 
					  bool parse_telegram();
 | 
				
			||||||
@@ -69,10 +72,6 @@ class Dsmr : public Component, public uart::UARTDevice {
 | 
				
			|||||||
  void dump_config() override;
 | 
					  void dump_config() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void set_decryption_key(const std::string &decryption_key);
 | 
					  void set_decryption_key(const std::string &decryption_key);
 | 
				
			||||||
  void set_max_telegram_length(size_t length) { this->max_telegram_len_ = length; }
 | 
					 | 
				
			||||||
  void set_request_pin(GPIOPin *request_pin) { this->request_pin_ = request_pin; }
 | 
					 | 
				
			||||||
  void set_request_interval(uint32_t interval) { this->request_interval_ = interval; }
 | 
					 | 
				
			||||||
  void set_receive_timeout(uint32_t timeout) { this->receive_timeout_ = timeout; }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Sensor setters
 | 
					// Sensor setters
 | 
				
			||||||
#define DSMR_SET_SENSOR(s) \
 | 
					#define DSMR_SET_SENSOR(s) \
 | 
				
			||||||
@@ -85,40 +84,13 @@ class Dsmr : public Component, public uart::UARTDevice {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 protected:
 | 
					 protected:
 | 
				
			||||||
  void receive_telegram_();
 | 
					  void receive_telegram_();
 | 
				
			||||||
  void receive_encrypted_telegram_();
 | 
					  void receive_encrypted_();
 | 
				
			||||||
  void reset_telegram_();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Wait for UART data to become available within the read timeout.
 | 
					  // Telegram buffer
 | 
				
			||||||
  ///
 | 
					  char telegram_[MAX_TELEGRAM_LENGTH];
 | 
				
			||||||
  /// The smart meter might provide data in chunks, causing available() to
 | 
					  int telegram_len_{0};
 | 
				
			||||||
  /// return 0. When we're already reading a telegram, then we don't return
 | 
					 | 
				
			||||||
  /// right away (to handle further data in an upcoming loop) but wait a
 | 
					 | 
				
			||||||
  /// little while using this method to see if more data are incoming.
 | 
					 | 
				
			||||||
  /// By not returning, we prevent other components from taking so much
 | 
					 | 
				
			||||||
  /// time that the UART RX buffer overflows and bytes of the telegram get
 | 
					 | 
				
			||||||
  /// lost in the process.
 | 
					 | 
				
			||||||
  bool available_within_timeout_();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Request telegram
 | 
					  // Serial parser
 | 
				
			||||||
  uint32_t request_interval_;
 | 
					 | 
				
			||||||
  bool request_interval_reached_();
 | 
					 | 
				
			||||||
  GPIOPin *request_pin_{nullptr};
 | 
					 | 
				
			||||||
  uint32_t last_request_time_{0};
 | 
					 | 
				
			||||||
  bool requesting_data_{false};
 | 
					 | 
				
			||||||
  bool ready_to_request_data_();
 | 
					 | 
				
			||||||
  void start_requesting_data_();
 | 
					 | 
				
			||||||
  void stop_requesting_data_();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Read telegram
 | 
					 | 
				
			||||||
  uint32_t receive_timeout_;
 | 
					 | 
				
			||||||
  bool receive_timeout_reached_();
 | 
					 | 
				
			||||||
  size_t max_telegram_len_;
 | 
					 | 
				
			||||||
  char *telegram_{nullptr};
 | 
					 | 
				
			||||||
  size_t bytes_read_{0};
 | 
					 | 
				
			||||||
  uint8_t *crypt_telegram_{nullptr};
 | 
					 | 
				
			||||||
  size_t crypt_telegram_len_{0};
 | 
					 | 
				
			||||||
  size_t crypt_bytes_read_{0};
 | 
					 | 
				
			||||||
  uint32_t last_read_time_{0};
 | 
					 | 
				
			||||||
  bool header_found_{false};
 | 
					  bool header_found_{false};
 | 
				
			||||||
  bool footer_found_{false};
 | 
					  bool footer_found_{false};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,6 +12,7 @@ void DutyCycleSensor::setup() {
 | 
				
			|||||||
  this->pin_->setup();
 | 
					  this->pin_->setup();
 | 
				
			||||||
  this->store_.pin = this->pin_->to_isr();
 | 
					  this->store_.pin = this->pin_->to_isr();
 | 
				
			||||||
  this->store_.last_level = this->pin_->digital_read();
 | 
					  this->store_.last_level = this->pin_->digital_read();
 | 
				
			||||||
 | 
					  this->last_update_ = micros();
 | 
				
			||||||
  this->store_.last_interrupt = micros();
 | 
					  this->store_.last_interrupt = micros();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  this->pin_->attach_interrupt(DutyCycleSensorStore::gpio_intr, &this->store_, gpio::INTERRUPT_ANY_EDGE);
 | 
					  this->pin_->attach_interrupt(DutyCycleSensorStore::gpio_intr, &this->store_, gpio::INTERRUPT_ANY_EDGE);
 | 
				
			||||||
@@ -23,24 +24,21 @@ void DutyCycleSensor::dump_config() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
void DutyCycleSensor::update() {
 | 
					void DutyCycleSensor::update() {
 | 
				
			||||||
  const uint32_t now = micros();
 | 
					  const uint32_t now = micros();
 | 
				
			||||||
  const uint32_t last_interrupt = this->store_.last_interrupt;  // Read the measurement taken by the interrupt
 | 
					  const bool level = this->store_.last_level;
 | 
				
			||||||
 | 
					  const uint32_t last_interrupt = this->store_.last_interrupt;
 | 
				
			||||||
  uint32_t on_time = this->store_.on_time;
 | 
					  uint32_t on_time = this->store_.on_time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  this->store_.on_time = 0;  // Start new measurement, exactly aligned with the micros() reading
 | 
					  if (level)
 | 
				
			||||||
 | 
					    on_time += now - last_interrupt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const float total_time = float(now - this->last_update_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const float value = (on_time / total_time) * 100.0f;
 | 
				
			||||||
 | 
					  ESP_LOGD(TAG, "'%s' Got duty cycle=%.1f%%", this->get_name().c_str(), value);
 | 
				
			||||||
 | 
					  this->publish_state(value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  this->store_.on_time = 0;
 | 
				
			||||||
  this->store_.last_interrupt = now;
 | 
					  this->store_.last_interrupt = now;
 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (this->last_update_ != 0) {
 | 
					 | 
				
			||||||
    const bool level = this->store_.last_level;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (level)
 | 
					 | 
				
			||||||
      on_time += now - last_interrupt;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const float total_time = float(now - this->last_update_);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const float value = (on_time * 100.0f) / total_time;
 | 
					 | 
				
			||||||
    ESP_LOGD(TAG, "'%s' Got duty cycle=%.1f%%", this->get_name().c_str(), value);
 | 
					 | 
				
			||||||
    this->publish_state(value);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  this->last_update_ = now;
 | 
					  this->last_update_ = now;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,7 +30,7 @@ class DutyCycleSensor : public sensor::Sensor, public PollingComponent {
 | 
				
			|||||||
  InternalGPIOPin *pin_;
 | 
					  InternalGPIOPin *pin_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  DutyCycleSensorStore store_{};
 | 
					  DutyCycleSensorStore store_{};
 | 
				
			||||||
  uint32_t last_update_{0};
 | 
					  uint32_t last_update_;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}  // namespace duty_cycle
 | 
					}  // namespace duty_cycle
 | 
				
			||||||
 
 | 
				
			|||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user