1
0
mirror of https://github.com/esphome/esphome.git synced 2025-11-01 15:41:52 +00:00

Compare commits

...

223 Commits

Author SHA1 Message Date
Jesse Hills
0f1e186189 Merge pull request #4732 from esphome/bump-2023.4.1
2023.4.1
2023-04-24 09:47:08 +12:00
Jesse Hills
96d208e0d8 Bump version to 2023.4.1 2023-04-24 09:11:07 +12:00
Jesse Hills
38ed38864e Use proper schema for delta filter (#4723) 2023-04-24 09:11:07 +12:00
Samuel Sieb
a12ba7bd38 fix flip_x (#4727) 2023-04-24 09:11:06 +12:00
Jesse Hills
19fc1417ae Merge pull request #4715 from esphome/bump-2023.4.0
2023.4.0
2023-04-20 15:18:09 +12:00
Jesse Hills
e2fefa51f5 Bump version to 2023.4.0 2023-04-20 14:06:53 +12:00
Jesse Hills
f668d5617f Merge branch 'beta' into bump-2023.4.0 2023-04-20 14:06:52 +12:00
Jesse Hills
47c4ff15d6 Merge pull request #4714 from esphome/bump-2023.4.0b4
2023.4.0b4
2023-04-20 14:00:12 +12:00
Jesse Hills
ccf1bdc0b4 Bump version to 2023.4.0b4 2023-04-20 13:10:26 +12:00
Jesse Hills
e993fcf80c Bump arduino platform version to 5.3.0 (#4713)
* Bump arduino platform version to 5.3.0

* Update root platformio.ini
2023-04-20 13:10:25 +12:00
tracestep
1bdc30a09e Add ethernet powerdown (fixes esphome/issues#4420) (#4706)
* Add ethernet powerdown

* Add on_shutdown (fixes esphome/issues#4420

* Sync dev and clang-tidy fix

* fix typo and trainling space

* Initialize phy_ member

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>

* Use `this` pointer

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>

* Member initialized at declaration

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>

* Use `this` pointer

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>

* Use `this` pointer

---------

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-04-20 13:10:25 +12:00
Jesse Hills
f56e89597f Merge pull request #4711 from esphome/bump-2023.4.0b3
2023.4.0b3
2023-04-20 11:14:00 +12:00
Jesse Hills
9460fb28c4 Bump version to 2023.4.0b3 2023-04-20 10:15:34 +12:00
Jesse Hills
7207b9734f Call on_error if no api client connected that handles voice (#4709) 2023-04-20 10:15:34 +12:00
Jesse Hills
3be3267d06 Merge pull request #4700 from esphome/bump-2023.4.0b2
2023.4.0b2
2023-04-17 17:16:16 +12:00
Jesse Hills
98db604dba Bump version to 2023.4.0b2 2023-04-17 15:45:35 +12:00
Jesse Hills
ebf6f8c6de Add event triggers to voice_assistant (#4699)
* Add event triggers to voice_assistant

* Add triggers to test
2023-04-17 15:45:34 +12:00
Szewcson
2ebacad398 Add timeout to i2c write error logs (#4697) 2023-04-17 15:45:34 +12:00
Jimmy Hedman
53c59cf675 Fixed dns2 for ethernet (#4698) 2023-04-17 15:45:34 +12:00
Jesse Hills
9da261cb39 debug component, allow without debug logging (#4685) 2023-04-17 15:45:34 +12:00
Jesse Hills
9fbbcd6d8a Merge pull request #4683 from esphome/bump-2023.4.0b1
2023.4.0b1
2023-04-13 11:06:53 +12:00
Jesse Hills
1a86167a47 Bump version to 2023.4.0b1 2023-04-13 10:13:52 +12:00
Jesse Hills
614ed7fd0c Merge branch 'dev' into bump-2023.4.0b1 2023-04-13 10:13:52 +12:00
spacemanspiff2007
4eb69d6af5 Fix restore (#4655)
* ALWAYS_OFF for fan

* ALWAYS_OFF for light

* ALWAYS_OFF for switch
2023-04-12 21:28:02 +00:00
Fabian
0547f2a931 Add KSZ8081 support. (#4668)
Co-authored-by: Your Name <you@example.com>
2023-04-12 21:22:08 +00:00
unhold
b5fbe0b145 Fix cut-off on 2.13" waveshare/ttgo epaper displays (#4255)
The controller of the 2.13" waveshare/ttgo epaper displays operates with a 128x250 buffer,
while only 122x250 pixels are shown. While this can be ignored for rotations 0/270°,
with roations 90/180°, 6 pixels are cut-off from the top or left edge.
This change introduces a distinction between object width and controller width,
resulting in pixel-perfect rotations.
2023-04-12 21:19:52 +00:00
unhold
443c3c2a56 Fix graph limits for negative values and other corner cases (#4253)
Fix lower graph limit for negative values by rounding down instead of truncating.
Consistently handle the corner cases: empty trace, min=max (e.g. single value)
by drawing the grid lines for a single grid division.
2023-04-12 21:18:09 +00:00
X-Ryl669
d75daa9644 Add always trigger stop (#4249)
* feat: Add manual control config override 1/3

* feat: Add manual control config override 2/3

* feat: Add manual control config override 3/3

* No magical number is better

Co-authored-by: Guillermo Ruffino <glm.net@gmail.com>

---------

Co-authored-by: Guillermo Ruffino <glm.net@gmail.com>
2023-04-12 21:16:44 +00:00
Joe
7963abb27a Fix BedJet setup priority [fixes esphome/issues#3807] (#4677)
There is a race condition where a BedJet unit previously had its BLE
"notify" flag enabled, and it continues to broadcast these notify
packets even after the ESP32 (and BLEClient) goes away, such as during
a crash or unplugging power.

BLEClient::setup_priority=AFTER_BLUETOOTH, while
BedJetHub::setup_priority=AFTER_WIFI. When the ESP32 starts back up
again, BLEClient::setup() happens first and will start receiving the
BLE notify packets almost immediately. Since we register the BLEClient
child from codegen, BedJetHub is registered as a child already by this
point, so BLEClient dispatches the notify status packet (and other gatt
events) to the BedJetHub handler, even though BedJetHub::setup() has
not been called yet.

We initialize BedJetHub::codec_ in setup(), so if BLEClient starts
dispatching gatt events before setup() is called, then codec_ will not
be initialized yet. This causes BedJetHub's gatt notify handler to call
`this->codec_->decode_notify()` on an uninitialized null pointer. Since
invoking a method does not have to dereference the pointer, that method
invocation is allowed; but later trying to access memory on that
instance results in a StoreProhibited panic.

Changing the BedJetHub's setup_priority to BLUETOOTH causes it to be
setup before BLEClient, so that by the time BLEClient starts to receive
BLE packets, BedJetHub is ready to receive them.
2023-04-12 08:33:15 +00:00
Jesse Hills
0b9e8fda34 Fix pin schema for i2s microphone (#4680) 2023-04-12 08:25:19 +00:00
Dave Johnston
a3cacc0c8b Add support for SSD1306 72x40 displays (#4659)
* add SSD1306 72x40

* fix indents

* fix clang style
2023-04-12 04:02:29 +00:00
Keith Burzinski
5a4840f641 Fix some NFC/PN532 crashes (#4678)
* Add + use some constants, fix some crashes

* Fix PN532 crashes
2023-04-12 02:29:06 +00:00
Keith Burzinski
3d7d689040 Fix ESP32 SPI hardware assignment in Arduino fw (#4669) 2023-04-12 01:38:41 +00:00
Jesse Hills
b60c08dd28 Add push to talk voice assistant (#4648)
* Add push to talk voice assistant

* Refactor most code into voice_assistant

* Make voice_assistant the component and remove push_to_talk (can be done in yaml)

* Fix component setup

* Always AF_INET to match serverside

* Fix microphone and media player co-existence

* Format

* Update codeowners

* Update test file

* Fix endifs

* nullptr not NULL

* clang-tidy

* Format

* fixup: Add VA event data

* Generate proto

* Parse and log events

* Add default to switch

* Fix

* Add mic/va to test5
2023-04-11 23:45:10 +00:00
dependabot[bot]
80bc567c31 Bump pytest from 7.2.2 to 7.3.0 (#4673)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.2.2 to 7.3.0.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.2.2...7.3.0)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-10 22:29:40 +00:00
dependabot[bot]
888ac2e180 Bump zeroconf from 0.47.4 to 0.56.0 (#4674)
Bumps [zeroconf](https://github.com/python-zeroconf/python-zeroconf) from 0.47.4 to 0.56.0.
- [Release notes](https://github.com/python-zeroconf/python-zeroconf/releases)
- [Changelog](https://github.com/python-zeroconf/python-zeroconf/blob/master/CHANGELOG.md)
- [Commits](https://github.com/python-zeroconf/python-zeroconf/compare/0.47.4...0.56.0)

---
updated-dependencies:
- dependency-name: zeroconf
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-10 22:29:22 +00:00
Jörg Thalheim
421ebcc8b2 use PRIx macros for printing u32/i32 ints (#4671)
This fix compilation issues with the latest esp-idf.
2023-04-10 22:20:02 +00:00
dependabot[bot]
b56fa8c50a Bump black from 23.1.0 to 23.3.0 (#4635)
* Bump black from 23.1.0 to 23.3.0

Bumps [black](https://github.com/psf/black) from 23.1.0 to 23.3.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/23.1.0...23.3.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update black in pre-commit

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-04-04 02:34:36 +00:00
Ben Hoff
42401775e1 Added in mmc5603 code (#4175)
* added in mmc5603 code

* added in codeowner

* fix linter errors

* whitespace linter errors

* added codeowner

* clang format

* remove clang format from python code

* fix whitespace

* add tests

* fix test

* make requested edits

* remove status manipulation

---------

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-04-04 02:34:14 +00:00
dependabot[bot]
9c9bc58c16 Bump pylint from 2.16.4 to 2.17.2 (#4650)
* Bump pylint from 2.16.4 to 2.17.2

Bumps [pylint](https://github.com/PyCQA/pylint) from 2.16.4 to 2.17.2.
- [Release notes](https://github.com/PyCQA/pylint/releases)
- [Commits](https://github.com/PyCQA/pylint/compare/v2.16.4...v2.17.2)

---
updated-dependencies:
- dependency-name: pylint
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Add return 0 to run_miniterm

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-04-03 23:55:00 +00:00
tracestep
fbc129cccc Version retry (fixes esphome/issues#3823) (#4651) 2023-04-03 22:23:31 +00:00
Jesse Hills
99638190cb VSCode / devcontainer updates (#4647) 2023-04-03 19:44:46 +00:00
RoboMagus
d78e9e6aa8 Number step not optional (#4649)
* Number step not optional

* Update __init__.py

* Update __init__.py

---------

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-04-03 19:31:11 +00:00
Mikkel Jeppesen
878155a03d Log calibration results at level INFO (#4240)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-03-31 09:05:28 +00:00
Fabian
9922eb83e2 Support advanced UART customization (#4465)
* Add methods to get hardware uart details.

* Fix `setRxBufferSize` error.

---------

Co-authored-by: Your Name <you@example.com>
2023-03-31 04:30:24 +00:00
Fabian
79f861f012 Avoid sensor padding. (#4638)
Co-authored-by: Your Name <you@example.com>
2023-03-31 04:29:17 +00:00
Fabian
4faa9d109e entity_base avoid padding bytes. (#4637)
Co-authored-by: Your Name <you@example.com>
2023-03-31 04:28:49 +00:00
kahrendt
28534ecc61 Binary map bugfixes (#4636)
* limit configuration to 64 binary sensors to match code limitation

* remove superfluous debug logging

* improve state publishing logic eliminating NAN being sent on boot in certain cases

* adjust type for bitmask shift to match mask variable type
2023-03-31 04:27:24 +00:00
felixlungu
616e0a21d8 add bluetooth mac address in dump_config() (#4628)
* add bluetooth mac address in dump_config()

* Update ble.cpp

* Update ble.cpp

* Update ble.cpp

* Update ble.cpp

* Update ble.cpp

* Update ble.cpp

* Update ble.cpp
2023-03-30 01:12:06 +00:00
Jesse Hills
a546ffd490 Add ifdef to new bt proxy unsubscribe (#4634)
* Add ifdef to new bt proxy unsubscribe

* Also add to subscribe message and wrap api conneciton code

* Format file
2023-03-30 01:08:51 +00:00
Jesse Hills
b5d0aede38 Remove AUTO_LOAD from as3935 (#4630) 2023-03-30 01:08:31 +00:00
github-actions[bot]
a014d853a4 Synchronise Device Classes from Home Assistant (#4633)
* Synchronise Device Classes from Home Assistant

* Remove count do the `DEVICE_CLASSES` list is also updated

* Format file

---------

Co-authored-by: esphomebot <esphome@nabucasa.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-03-29 02:47:00 +00:00
Jesse Hills
c4ddf7697d Update sync-device-classes.yml 2023-03-29 14:02:34 +13:00
Jesse Hills
a2931b6774 Add workflow to sync device classes with HA dev (#4629) 2023-03-28 23:31:07 +00:00
Fabian
3ac7bf3761 EntityBase: Move ObjectId to Flash (#4569)
* Move EntityBase Object Id from memory to flash.

* Sprinkler use common `setup_entity` method.

* Remove `EntityBase` from Sprinkler.

* Support for entity names set to None

* change so gh PR picks up commit.

---------

Co-authored-by: Your Name <you@example.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-03-28 09:00:34 +00:00
richardhopton
922344811f feat: Add support to unsubscribe from BLE advertisements (#4620)
* feat: Add support to unsubscribe from BLE advertisements

* Fix tests & clang

---------

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-03-28 08:54:58 +00:00
Fabian
cb2fcaa9b1 EntityBase Name can stay in flash. (#4594)
* `EntityBase`can stay in flash.

* Trying to please the CI.

---------

Co-authored-by: Your Name <you@example.com>
2023-03-28 06:38:56 +00:00
Alfredo
1f50bd0649 Fix EzoCommandType enum (#4593)
* Fix EzoCommandType enum

Assign explicit value to EZO_CALIBRATION, and rescale all subsequent values.

* Remove enum values

---------

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-03-27 22:08:26 +00:00
Jesse Hills
e4b2de5c68 Merge pull request #4623 from esphome/bump-2023.3.2
2023.3.2
2023-03-27 16:45:14 +13:00
Jesse Hills
f862b479e7 Bump version to 2023.3.2 2023-03-27 15:58:29 +13:00
tracestep
358c59bd8d SX1509 minimum loop period (fixes esphome/issues#4325) (#4613)
* Minimum loop period (fixes esphome/issues#4325)

* clang-tidy suggestions

* More clang-tidy suggestions
2023-03-27 15:58:28 +13:00
guillempages
74fe135c9c Fix animation resizing (#4608)
Animation resizing in RGB24 format is causing an error "Image cannot be resized to a bigger size". Other image types do not show the issue, and the only difference is the "image.thumbnail" call.

Removed the call and tested; the animation is shown with the desired size.
2023-03-27 15:58:28 +13:00
Jesse Hills
8d3896172d Swap curly brackets for round on LockGuard (#4610) 2023-03-27 15:58:28 +13:00
Kai Gerken
9d9725144d Fix compile error on pzemdc.h (#4583) 2023-03-27 15:58:28 +13:00
Jesse Hills
dd8dc1ef1d Merge pull request #4609 from esphome/bump-2023.3.1
2023.3.1
2023-03-22 12:40:28 +13:00
Jesse Hills
bc427de16a Bump version to 2023.3.1 2023-03-22 12:03:34 +13:00
Jesse Hills
db5988bbe1 rp2040: Use fake Mutex lock (#4602) 2023-03-22 12:03:34 +13:00
Nathaniel Wesley Filardo
a3875af4b4 climate: brown paper bag fix for on_configure (#4573)
I forgot this hunk in https://github.com/esphome/esphome/pull/4511 .
I'm sorry for the noise.
2023-03-22 12:03:34 +13:00
Jesse Hills
e6737479f7 Merge pull request #4568 from esphome/bump-2023.3.0
2023.3.0
2023-03-16 10:40:18 +13:00
Jesse Hills
7f75832bf1 Bump version to 2023.3.0 2023-03-16 09:38:19 +13:00
Jesse Hills
33339e3bd8 Merge branch 'beta' into bump-2023.3.0 2023-03-16 09:38:19 +13:00
Jesse Hills
c298c1166f Merge pull request #4567 from esphome/bump-2023.3.0b6
2023.3.0b6
2023-03-16 09:34:00 +13:00
Jesse Hills
c3d9eef01f Bump version to 2023.3.0b6 2023-03-16 08:57:54 +13:00
NP v/d Spek
5ffdc66864 fixing shrink and extend functions of the displaybuffer's Rect class (#4565)
* fixing rectangle's `shrink` and `extend`

* fixed the rect::shrink and rect::inside methods
and added rect:equal() method

* fixed internal clang issue again. When would is
this going to be fixed :(

* fixed internal clang issue again. When would is
this going to be fixed :(

* remove trailing space
2023-03-16 08:57:54 +13:00
Jesse Hills
9922c1503a Merge pull request #4564 from esphome/bump-2023.3.0b5
2023.3.0b5
2023-03-15 23:46:14 +13:00
Jesse Hills
fce99d4b17 Bump version to 2023.3.0b5 2023-03-15 21:20:08 +13:00
Jesse Hills
11567085d8 Mark esp32_touch supported only on standard esp32 variant (#4562)
* Mark esp32_touch supported only on standard esp32 variant

* Add back default
2023-03-15 21:20:08 +13:00
Keith Burzinski
83f8e84247 Remove switch actions during config; bump setup priority (#4563) 2023-03-15 21:20:08 +13:00
Jesse Hills
11eb5cb0fa Merge pull request #4559 from esphome/bump-2023.3.0b4
2023.3.0b4
2023-03-14 16:17:51 +13:00
Jesse Hills
9a7af97b2d Bump version to 2023.3.0b4 2023-03-14 14:11:55 +13:00
Stroe Andrei Catalin
5e11469f50 Added response for Tuya RSSI command (#4549)
* Added wifi rssi util
Added tuya mcu response to wifi rssi command

* Cleanup

* PR Comments

* PR Comments
2023-03-14 14:11:55 +13:00
DAVe3283
0c7a3d1fff Revert "Remove state class from uptime sensor (#4345)" (#4557)
This reverts commit 36c2e770bf.
Addresses esphome/issues#4193.
2023-03-14 14:11:55 +13:00
Eduardo Roldan
8a705bf4b0 pipsolar component. Correct the sscanf format for QPIG command parsing to set pv_input_voltage as float (not int) (#4165) 2023-03-14 14:11:55 +13:00
Jesse Hills
6a89180deb Merge pull request #4553 from esphome/bump-2023.3.0b3
2023.3.0b3
2023-03-13 15:31:04 +13:00
Jesse Hills
65d2b806cc Bump version to 2023.3.0b3 2023-03-13 13:32:21 +13:00
Jesse Hills
c149a3033c Map gpio pins for touch on esp32-s2/s3 (#4552)
* Map gpio pins for touch on esp32-s2/s3

* fix value
2023-03-13 13:32:21 +13:00
NP v/d Spek
4b7c233f1a On the ILI9xxx display's enable the psram on esp32 and allow big screen (#4551)
* enable the psram on esp32 and allow big screen

* update CODEOWNERS

* small update

* update CODEOWNERS again.

* Removed the M5STACK because it is a ESP32 device.

* i removed the wrong model

* update the error message.
2023-03-13 13:32:21 +13:00
Jesse Hills
6e8e9c2aa9 Allow AUTO_LOAD to be a function (#4550) 2023-03-13 13:32:21 +13:00
Dorian Zedler
b6f628ee40 Feat: add support for hex color in color component (#4493)
* Feat: add support for hex color in color component

* Chore: move hex color validator to color component

* Chore: add test

* Chore: fix formatting

* Chore: make linter happy

* Chore: make linter happy

* Fix: parse correct offsets

Co-authored-by: Oxan van Leeuwen <oxan@oxanvanleeuwen.nl>

* Chore: use cv.Invalid

* Fix: remove # because it indicates a comment in yaml

* Fix: only allow hex if no other color value is set

* Fix: tests

* Fix: mutual exclusion of raw and hex colors

* Chore: format file

* Update __init__.py

---------

Co-authored-by: Oxan van Leeuwen <oxan@oxanvanleeuwen.nl>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-03-13 13:32:21 +13:00
Martin Murray
bf79a700b7 Add carbon dioxide device class to scd30 sensor schema. (#4547) 2023-03-13 13:32:21 +13:00
jakehdk
cdeb6e750f Add support for new clones of mpu6050 responding with 0x70 address (#4546)
Co-authored-by: jakehdk <Jake@Jakobs-MacBook-Pro.local>
2023-03-13 13:32:21 +13:00
Jesse Hills
dd226360bb Merge pull request #4542 from esphome/bump-2023.3.0b2
2023.3.0b2
2023-03-09 19:03:39 +13:00
Jesse Hills
1a9aedf152 Bump version to 2023.3.0b2 2023-03-09 15:47:57 +13:00
Carlos Garcia Saura
d82c6df57e Correct BME680 gas calculation and heater_off (#4498)
* Fix missing data array

* Fix incorrect bit offset

* Correct variable types

* Do same conversions as in original library

* Correct clang-format

* Move out float conversion for clarity

* Added check for heater stability

* Correct clang format

* Allow reporting gas resistance when heater is disabled

* Correct clang format

* Better error reporting by @DAVe3283

* Correct signed operation, range switching error was positive all the time
2023-03-09 15:47:57 +13:00
Oxan van Leeuwen
7c91b4474a Revert storing Font glyphs in manually-allocated memory (#4516)
This partially reverts commit 62459a8ae1.
2023-03-09 15:47:57 +13:00
Oxan van Leeuwen
a4f21db272 Drop broken logging macros (#4534) 2023-03-09 15:47:57 +13:00
NP v/d Spek
58a8e1859e Renaming and extending the ili9341 to the ili9xxx component (#4275)
* - Removed cleaning the screen twice.
  \Should be handled by  `DisplayBuffer::init_internal_();`
- Made ili9341::initalize() protected and renamed
  \ it to ili9341::initalize().
- ili9341::initalize() should only init the display
  \ and set the width and heigth.

* removed to much

* clang format fixes

* removing trailing underscors for
protected virtual methods

* removed the "override"  on display()

* clang fixes

* restored old changes

* Renamed the ili9341 platform to ili9xxx and added
multiple drivers as well. including PR #3848

* fixed most of the clang reported issues

* fixed reported issues

* last fixes

* Setting the right codeowners

* missing changes

* fixed naming Display() method.

* clang again

* clang fix

* fixes reported by @jesserockz & @gpambrozio

* a change to display.py removing an unneeded var

* re-introduce **backlight** option.

* update the ili9488 initialization

* update the ili9488 initialization and fix typo

* fixed typo

* add missing constants

* swap height and width back for the ili9488

* init fixes ili9488

* fixed lint issue
testing the init code

* oeps

* init fixes ili9488

* fixed wrong define

* fixed wrong define again

* removed some spaces

* revert to ili9341

* Remove parts that where used for
the switchplate

* lint fixes and removing unused function

* fix error and introducing 16bit color option

* fix error and introducing 16bit color option

* fix clang issue

* clang fix

* clang issue again

* is this what clang exprect

* clang fix

* clang fix

* try again

* let try again

* and again

* and the last clang fix

* remove the need of wifi

* update dimentions

* update ili8488 init code.

* update dimentions

* allow to change height and width

* dump color mode config

* fix

* fix

* modify logging

* referd back unrelated change

* code formatting commit and moving functions around

* add missing ;

* update code

* update code

* use the correct write_array for sending uint16_t

* fix panic loop

* fix panic loop

* - update the test file
- fixed sending display data

* clang fixes

* clang fixes

* clang fixes again

* remove .gitignore items

* remove .gitignore items

* make sure Update() can can not be called while
called

* clang correction

* adding a test yaml for the ili9341

* Update ili9341 example

* Make test ili9xxx/tests only local

* restore back old ili9341 driver code

* Add a new config for the M5Core

* fix clang request

* reverd to restore of the old ili9341
there is no proper way to say it is depricated.

* Remove the backlight/led pin from the config.
You need to use a proper light platform component

* Ili9488init changes (#88)

Fixed ILI9488 init settings, and adjusted pixel handling code to push pixels in 18 bit format.
This does not change the internal 16-bit representation.

* fixed some leftover clang issues from the merge.

* fixed the slang-tidy request.

* remove `backlight_pin` warning.

---------

Co-authored-by: JD Steffen <jdsteffen81@gmail.com>
2023-03-09 15:47:57 +13:00
Russell Cloran
2bed5b18c1 Add ESP32-S3 support in NeoPixelBus component (#4114)
* Add ESP32-S3 support in NeoPixelBus component

* Update NeoPixelBus version in platformio.ini
2023-03-09 15:47:57 +13:00
Jared Sanson
fb5eb57345 Fix ethernet clk_mode for GPIO0_OUT (#4307)
* Fix GPIO0_OUT definition for ethernet component

* Formatting

---------

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-03-09 15:47:57 +13:00
Jesse Hills
63db42a1d4 Merge pull request #4536 from esphome/bump-2023.3.0b1
2023.3.0b1
2023-03-09 10:43:40 +13:00
Jesse Hills
f58ffe41f8 Bump version to 2023.3.0b1 2023-03-09 09:09:39 +13:00
Jesse Hills
445d2e372c Merge branch 'dev' into bump-2023.3.0b1 2023-03-09 09:09:39 +13:00
Jesse Hills
c037e95861 Merge pull request #4478 from esphome/bump-2023.2.4
2023.2.4
2023-02-23 14:17:01 +13:00
Jesse Hills
2e1b35959f Bump version to 2023.2.4 2023-02-23 13:42:02 +13:00
Jesse Hills
7f46d9e0f9 Fix multiple remote_receivers with triggers (#4477) 2023-02-23 13:42:01 +13:00
Samuel Sieb
069b5f81a0 fix parity (#4476)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2023-02-23 13:42:01 +13:00
konsulten
3a36d0b13f BL0939 state_class set for energy sensors (#4463)
BL0939 was missing TOTAL_INCREASING for energy (kWh) thus it did not show as statistics in home assistant
2023-02-23 13:42:01 +13:00
Jesse Hills
f0760e99b7 Merge pull request #4466 from esphome/bump-2023.2.3
2023.2.3
2023-02-20 08:54:32 +13:00
Jesse Hills
18fecf8c09 Bump version to 2023.2.3 2023-02-20 08:16:47 +13:00
Jesse Hills
414cf1b333 Update Manifest to rmeove unused dashboard files and include .c ethernet drivers (#4459) 2023-02-20 08:16:46 +13:00
jmichiel
d10f891f51 fix preset discovery config (#4451)
Co-authored-by: Michiel, Jeroen <jeroen.michiel@teledyneflir.com>
2023-02-20 08:16:46 +13:00
Jesse Hills
b5927322e6 Merge pull request #4458 from esphome/bump-2023.2.2
2023.2.2
2023-02-17 19:38:01 +13:00
Jesse Hills
1cf4107e1c Bump version to 2023.2.2 2023-02-17 19:11:15 +13:00
Jesse Hills
c12408326c Fix adoption of variants and pico-w (#4455) 2023-02-17 19:11:14 +13:00
Jesse Hills
4434e59e5a Merge pull request #4445 from esphome/bump-2023.2.1
2023.2.1
2023-02-16 15:44:32 +13:00
Jesse Hills
45180d98f6 Bump version to 2023.2.1 2023-02-16 14:06:42 +13:00
Jesse Hills
44494ad18e Add ESPHome version to generated platformio.ini (#4443)
* Add ESPHome version to generated platformio.ini

* Move description to platformio section
2023-02-16 14:06:42 +13:00
Jesse Hills
1447536906 Merge pull request #4441 from esphome/bump-2023.2.0
2023.2.0
2023-02-15 22:33:31 +13:00
Jesse Hills
27ec517084 Remove dup line 2023-02-15 21:39:17 +13:00
Jesse Hills
ce1f034bac Bump version to 2023.2.0 2023-02-15 19:29:02 +13:00
Jesse Hills
f1f96f16e9 Merge branch 'beta' into bump-2023.2.0 2023-02-15 19:29:02 +13:00
Jesse Hills
7665e9b076 Merge pull request #4433 from esphome/bump-2023.2.0b5
2023.2.0b5
2023-02-14 14:51:00 +13:00
Jesse Hills
227d94f38d Bump version to 2023.2.0b5 2023-02-14 13:59:49 +13:00
Sergey Dudanov
b724ae9e0e Fix setting wrong traits on midea climate component (#4425)
* Fix issue3914

* Remove also default presets and modes

* Fix traits after autoconf
2023-02-14 13:59:49 +13:00
Jesse Hills
df6cc14201 Bump esphome-dashboard to 20230214.0 (#4431) 2023-02-14 13:59:49 +13:00
Jesse Hills
d981d7859d Handle uart.write in json-config endpoint (#4430) 2023-02-14 13:59:49 +13:00
Jesse Hills
0f1ec515c1 Add version api endpoint (#4429) 2023-02-14 13:59:49 +13:00
WitchKing
78e18256f7 Ledc fix (#4338) 2023-02-14 13:59:49 +13:00
Jesse Hills
4899dfe642 Merge pull request #4423 from esphome/bump-2023.2.0b4
2023.2.0b4
2023-02-13 15:17:05 +13:00
Jesse Hills
d6b6e94059 Bump version to 2023.2.0b4 2023-02-13 11:54:27 +13:00
NP v/d Spek
310355a00b Fix check for empty clipping array (#4421) 2023-02-13 11:54:26 +13:00
NP v/d Spek
8cf26d6f3c Add Clipping to displaybuffer (#4271)
* adding Clipping support to the displaybuffer
- add rect structure

* removed unused define

* add missing property for storing the clipped areas

* include log header

* Move Rect method's code to cpp file
- removed obsolete remarks

* fixed reported issues

* make Rect class methods public

* clang fix

* Remove commented code

* Renaming clipping methods

* Multiple changes:
- replaced 32766 with VALUE_NO_SET
- fixed the way *_clipping(left, top, right, bottom) is stored
- add `is_clipping();`
- make sure that all clipped region are closed after `do_update_()`
- rename de parameters for `Rect::expand();`

* remove unneeded space

* replace define with static const uint8_t

* correcting my copy paste mistake

---------

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-02-13 11:54:26 +13:00
Patrick Collins
b15a10f905 Climate PID Autotune Logging fixes (#4136)
* pid autotune logging fixes

* fixed clang-format request

* improved and clarified logging

* changed logging not to alter the TAG

* logging now does not alter TAG. fixed clang formattting

* fixed string issues

* playing with strings to please the clang gods

* playing with strings

* Delete secrets.yaml

* Delete console-fan-autotune-test.yaml

* Update esphome/components/pid/pid_autotuner.cpp

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>

* Update esphome/components/pid/pid_autotuner.cpp

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>

* Update esphome/components/pid/pid_autotuner.cpp

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>

* Update esphome/components/pid/pid_autotuner.cpp

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>

* Update esphome/components/pid/pid_autotuner.cpp

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>

---------

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2023-02-13 11:54:26 +13:00
Jesse Hills
5dcf1debd7 Merge pull request #4406 from esphome/bump-2023.2.0b3
2023.2.0b3
2023-02-09 18:04:35 +13:00
Jesse Hills
9b57e1ac1d Bump version to 2023.2.0b3 2023-02-09 17:38:54 +13:00
Jesse Hills
68683e3a50 Fix release workflow (#4405) 2023-02-09 17:38:54 +13:00
Jesse Hills
d83324c4dc Merge pull request #4404 from esphome/bump-2023.2.0b2
2023.2.0b2
2023-02-09 16:55:48 +13:00
Jesse Hills
ecde4c1d2d Bump version to 2023.2.0b2 2023-02-09 16:27:25 +13:00
Jesse Hills
bd8e470726 Bump curl version in docker (#4403) 2023-02-09 16:27:24 +13:00
Jesse Hills
d2913fe627 Merge pull request #4402 from esphome/bump-2023.2.0b1
2023.2.0b1
2023-02-09 15:59:06 +13:00
Jesse Hills
43acc7dc2c Bump version to 2023.2.0b1 2023-02-09 15:33:02 +13:00
Jesse Hills
e2a16d758b Merge branch 'dev' into bump-2023.2.0b1 2023-02-09 15:33:01 +13:00
Jesse Hills
4af4649e23 Merge pull request #4355 from esphome/bump-2022.12.8
2022.12.8
2023-01-27 10:04:29 +13:00
Jesse Hills
8bcddef39d Bump version to 2022.12.8 2023-01-27 09:44:41 +13:00
Franck Nijhof
4ac96ccea2 Add Home Assistant integration discovery (#4328) 2023-01-27 09:44:41 +13:00
Franck Nijhof
3c5de77ae9 Refactor NGINX configuration of Home Assistant Add-on (#4312) 2023-01-27 09:44:41 +13:00
Franck Nijhof
a2925b1d37 Migrate old-style S6 scripts to s6-rc.d (#4311) 2023-01-27 09:44:41 +13:00
Franck Nijhof
73748e9e20 Upgrades add-on base image to 6.2.0 (#4310) 2023-01-27 09:44:40 +13:00
Jesse Hills
75c9823899 Merge pull request #4350 from esphome/bump-2022.12.7
2022.12.7
2023-01-26 15:50:03 +13:00
Jesse Hills
c8c0bd3351 Bump version to 2022.12.7 2023-01-26 15:00:18 +13:00
melyux
e1cdeb7c8f Add a soft reset in setup() for bmp280 (#4329)
fixes https://github.com/esphome/issues/issues/3383
2023-01-26 15:00:17 +13:00
Alex
7f97f42552 Fix BME280 initialization before wifi setup (#4190)
fixes https://github.com/esphome/issues/issues/3530
2023-01-26 15:00:17 +13:00
Stephan Martin
aa7f3569ec rename esp32 CAN to TWAI, so it compiles again (#4334)
fixes https://github.com/esphome/issues/issues/4023
2023-01-26 15:00:17 +13:00
Denis Bodor (aka Lefinnois)
2d0a08442e fix stepper jump back with small steps (#4339) 2023-01-26 15:00:17 +13:00
Joakim Sørensen
d2380756b2 Add "content" to deploy-ha-addon-repo dispatch (#4349) 2023-01-26 15:00:17 +13:00
Jesse Hills
925e3cb6c9 Fix missing s 2023-01-23 20:34:31 +00:00
Jesse Hills
6757acba56 Merge pull request #4342 from esphome/bump-2022.12.6
2022.12.6
2023-01-24 08:58:45 +13:00
Jesse Hills
5cc91cdd95 Bump version to 2022.12.6 2023-01-24 08:30:42 +13:00
Jesse Hills
2b41886819 Move from docker manifest command to buildx with platforms (#4320) 2023-01-24 08:30:42 +13:00
Jesse Hills
72c6efd6a0 Merge pull request #4335 from esphome/bump-2022.12.5
2022.12.5
2023-01-23 09:27:18 +13:00
Jesse Hills
a1f1804112 Bump version to 2022.12.5 2023-01-23 09:06:20 +13:00
Jesse Hills
a8b1ceb4e9 Bump nano version in lint docker image (#4218) 2023-01-23 09:06:20 +13:00
Jesse Hills
4fb0f7f8c6 Merge pull request #4323 from esphome/bump-2022.12.4
2022.12.4
2023-01-21 16:17:57 +13:00
Jesse Hills
958cadeca8 Bump version to 2022.12.4 2023-01-20 18:33:09 +13:00
J. Nick Koston
00f2655f1a Always send the MTU request for BLE v3 cached connections (#4322)
closes https://github.com/esphome/esphome/pull/4321
fixes https://github.com/esphome/issues/issues/4041
fixes https://github.com/esphome/issues/issues/3951
2023-01-20 18:33:09 +13:00
Jesse Hills
074f5029eb Fix gpio pin mode for ISR pins (#4216) 2023-01-20 18:33:09 +13:00
Jesse Hills
1691976587 Merge pull request #4214 from esphome/bump-2022.12.3
2022.12.3
2022-12-20 23:34:01 +13:00
Jesse Hills
60e6b4d21e Bump version to 2022.12.3 2022-12-20 23:15:39 +13:00
Jesse Hills
5750591df2 Fix ESP32 GPIO when using INPUT PULLUP mode (#4213) 2022-12-20 23:15:39 +13:00
Jesse Hills
a75da54455 Merge pull request #4212 from esphome/bump-2022.12.2
2022.12.2
2022-12-20 11:06:34 +13:00
Jesse Hills
de7f6c3f5f Bump version to 2022.12.2 2022-12-20 10:49:36 +13:00
J. Nick Koston
4245480656 Handle zero padding anywhere in the combined adv data (#4208)
fixes https://github.com/esphome/issues/issues/3913
2022-12-20 10:49:35 +13:00
Jesse Hills
1824c8131e Fix import_full_config for adoption configs (#4197)
* Fix git raw url

* Fix setting full config query param

* Force dashboard import urls to have a branch or tag reference for full import
2022-12-20 10:49:35 +13:00
Jesse Hills
4e9606d2e0 Merge pull request #4196 from esphome/bump-2022.12.1
2022.12.1
2022-12-16 14:05:24 +13:00
Jesse Hills
78500fa933 Bump version to 2022.12.1 2022-12-16 13:36:11 +13:00
Jesse Hills
9c69b98a49 Fix i2s_audio media_player compiling for esp32-s2 (#4195) 2022-12-16 13:36:10 +13:00
Jesse Hills
e6d8ef98d3 Mark ESP32-S2 as not having Bluetooth (#4194) 2022-12-16 13:36:10 +13:00
Stefan Agner
3f1af1690b Support non-multiarch toolchains on 32-bit ARM (#4191)
fixes https://github.com/esphome/issues/issues/3904
2022-12-16 13:36:10 +13:00
Jesse Hills
84374b6b1e Merge pull request #4186 from esphome/bump-2022.12.0
2022.12.0
2022-12-14 17:06:24 +13:00
Jesse Hills
391316c9b5 Bump version to 2022.12.0 2022-12-14 16:37:39 +13:00
Jesse Hills
705c62ebd7 Merge branch 'beta' into bump-2022.12.0 2022-12-14 16:37:39 +13:00
Jesse Hills
cb520c00a5 Merge pull request #4185 from esphome/bump-2022.12.0b6
2022.12.0b6
2022-12-14 12:24:25 +13:00
Jesse Hills
2f24138345 Bump version to 2022.12.0b6 2022-12-14 12:03:03 +13:00
Jesse Hills
96512b80cc Revert camera config change for esp-idf (#4182) 2022-12-14 12:03:03 +13:00
Jesse Hills
fcb9b51978 Remove warnings when falling through switch cases on purpose (#4181) 2022-12-14 12:03:03 +13:00
Jesse Hills
f408f1a368 Merge pull request #4180 from esphome/bump-2022.12.0b5
2022.12.0b5
2022-12-13 19:42:18 +13:00
Jesse Hills
7d8d563c62 Bump version to 2022.12.0b5 2022-12-13 13:58:44 +13:00
J. Nick Koston
0a1f705fda Speed up bluetooth proxy connections when using esp-idf (#4171) 2022-12-13 13:58:44 +13:00
Jesse Hills
1952c1880b Remove internal pin restriction from cd74hc4067 (#4179) 2022-12-13 13:58:44 +13:00
Jesse Hills
b03967dac1 Merge pull request #4178 from esphome/bump-2022.12.0b4
2022.12.0b4
2022-12-13 10:14:08 +13:00
Jesse Hills
bcae2596a6 Bump version to 2022.12.0b4 2022-12-13 09:13:28 +13:00
Jesse Hills
fc0347c86c Bump esphome-dashboard to 20221213.0 (#4176) 2022-12-13 09:13:28 +13:00
Jesse Hills
d9563d4de1 Merge pull request #4174 from esphome/bump-2022.12.0b3
2022.12.0b3
2022-12-12 17:31:44 +13:00
Jesse Hills
cc7e2bf8db Bump version to 2022.12.0b3 2022-12-12 17:19:12 +13:00
Jesse Hills
5d98e2923b Increase watchdog timeout when starting OTA (#4172) 2022-12-12 17:19:12 +13:00
Jesse Hills
07197d12f6 Merge pull request #4163 from esphome/bump-2022.12.0b2
2022.12.0b2
2022-12-08 14:04:20 +13:00
Jesse Hills
7b0a298497 Bump version to 2022.12.0b2 2022-12-08 13:42:25 +13:00
Jesse Hills
21679cf2ba Fix ble parsing with zero padded advertisements (#4162) 2022-12-08 13:42:24 +13:00
Jesse Hills
4be7cd12a1 Merge pull request #4157 from esphome/bump-2022.12.0b1
2022.12.0b1
2022-12-07 17:25:12 +13:00
Jesse Hills
dee4d0ccb7 Bump version to 2022.12.0b1 2022-12-07 17:00:10 +13:00
Jesse Hills
7209dd8bae Merge pull request #4152 from esphome/bump-2022.11.5
2022.11.5
2022-12-06 13:12:57 +13:00
Jesse Hills
ab736c89bb Bump version to 2022.11.5 2022-12-06 12:52:48 +13:00
Jesse Hills
6911639617 Fix board pin alias lookup (#4147) 2022-12-06 12:52:48 +13:00
Jesse Hills
b9720d0715 Merge pull request #4130 from esphome/bump-2022.11.4
2022.11.4
2022-12-01 15:38:52 +13:00
Jesse Hills
47b3267ed4 Bump version to 2022.11.4 2022-12-01 13:47:50 +13:00
Jesse Hills
e16ba2adb5 Fix queuing scripts not compiling (#4077) 2022-12-01 13:47:50 +13:00
Nicolas Graziano
0a19b1e32c Dashboard, after login use relative url. (#4103) 2022-12-01 13:47:49 +13:00
Jesse Hills
bae9a950c0 current-based cover fix copy paste mistake (#4124) 2022-12-01 13:47:49 +13:00
Jesse Hills
72b2943332 Merge pull request #4083 from esphome/bump-2022.11.3
2022.11.3
2022-11-25 07:23:08 +13:00
Jesse Hills
4ec0ef7548 Bump version to 2022.11.3 2022-11-24 17:01:52 +13:00
Jesse Hills
25bc6761f6 Don't convert climate temperature step (#4082) 2022-11-24 17:01:52 +13:00
Brian Kaufman
81b6562c25 Fix units for refresh: never (#4048) 2022-11-24 17:01:52 +13:00
Samuel Sieb
ae74189fc2 fix missing library (#4051) 2022-11-24 17:01:51 +13:00
Jesse Hills
9e516efe10 Merge pull request #4074 from esphome/bump-2022.11.2
2022.11.2
2022-11-23 16:06:34 +13:00
Jesse Hills
366e29439e Bump version to 2022.11.2 2022-11-23 13:04:21 +13:00
J. Nick Koston
1c9c700d7f Avoid creating a new espbt::ESPBTUUID each loop when registering for notify (#4069) 2022-11-23 13:04:21 +13:00
J. Nick Koston
b2e6b9d31f Avoid 128bit uuid loop for 16/32 bit uuids (#4068) 2022-11-23 13:04:21 +13:00
Jesse Hills
7623f63846 rp2040_pwm frequency is per pair of pins (#4061) 2022-11-23 13:04:21 +13:00
Jesse Hills
2bfaf9dce3 Update web_server index (#4060) 2022-11-23 13:04:20 +13:00
Jesse Hills
5c2c1560bb Fix rp2040 pwm to use pico-sdk, not mbed (#4059) 2022-11-23 13:04:20 +13:00
Jesse Hills
f7096ab78e Merge pull request #4041 from esphome/bump-2022.11.1
2022.11.1
2022-11-17 15:40:51 +13:00
Jesse Hills
98f8feb625 Bump version to 2022.11.1 2022-11-17 13:52:15 +13:00
Jesse Hills
9944ca414e Support ADC on RP2040 (#4040) 2022-11-17 13:52:15 +13:00
132 changed files with 2578 additions and 345 deletions

View File

@@ -4,53 +4,60 @@
"postCreateCommand": [
"script/devcontainer-post-create"
],
"containerEnv": {
"DEVCONTAINER": "1"
},
"runArgs": [
"--privileged",
"-e",
"ESPHOME_DASHBOARD_USE_PING=1"
],
"appPort": 6052,
"extensions": [
// python
"ms-python.python",
"visualstudioexptteam.vscodeintellicode",
// yaml
"redhat.vscode-yaml",
// cpp
"ms-vscode.cpptools",
// editorconfig
"editorconfig.editorconfig",
],
"settings": {
"python.languageServer": "Pylance",
"python.pythonPath": "/usr/bin/python3",
"python.linting.pylintEnabled": true,
"python.linting.enabled": true,
"python.formatting.provider": "black",
"editor.formatOnPaste": false,
"editor.formatOnSave": true,
"editor.formatOnType": true,
"files.trimTrailingWhitespace": true,
"terminal.integrated.defaultProfile.linux": "bash",
"yaml.customTags": [
"!secret scalar",
"!lambda scalar",
"!include_dir_named scalar",
"!include_dir_list scalar",
"!include_dir_merge_list scalar",
"!include_dir_merge_named scalar"
],
"files.exclude": {
"**/.git": true,
"**/.DS_Store": true,
"**/*.pyc": {
"when": "$(basename).py"
},
"**/__pycache__": true
},
"files.associations": {
"**/.vscode/*.json": "jsonc"
},
"C_Cpp.clang_format_path": "/usr/bin/clang-format-13",
"customizations": {
"vscode": {
"extensions": [
// python
"ms-python.python",
"visualstudioexptteam.vscodeintellicode",
// yaml
"redhat.vscode-yaml",
// cpp
"ms-vscode.cpptools",
// editorconfig
"editorconfig.editorconfig",
],
"settings": {
"python.languageServer": "Pylance",
"python.pythonPath": "/usr/bin/python3",
"python.linting.pylintEnabled": true,
"python.linting.enabled": true,
"python.formatting.provider": "black",
"editor.formatOnPaste": false,
"editor.formatOnSave": true,
"editor.formatOnType": true,
"files.trimTrailingWhitespace": true,
"terminal.integrated.defaultProfile.linux": "bash",
"yaml.customTags": [
"!secret scalar",
"!lambda scalar",
"!include_dir_named scalar",
"!include_dir_list scalar",
"!include_dir_merge_list scalar",
"!include_dir_merge_named scalar"
],
"files.exclude": {
"**/.git": true,
"**/.DS_Store": true,
"**/*.pyc": {
"when": "$(basename).py"
},
"**/__pycache__": true
},
"files.associations": {
"**/.vscode/*.json": "jsonc"
},
"C_Cpp.clang_format_path": "/usr/bin/clang-format-13"
}
}
}
}

View File

@@ -0,0 +1,60 @@
---
name: Synchronise Device Classes from Home Assistant
on:
workflow_dispatch:
schedule:
- cron: '45 6 * * *'
permissions:
contents: write
pull-requests: write
jobs:
sync:
name: Sync Device Classes
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Checkout Home Assistant
uses: actions/checkout@v3
with:
repository: home-assistant/core
path: lib/home-assistant
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: 3.11
- name: Install Home Assistant
run: |
python -m pip install --upgrade pip
pip install -e lib/home-assistant
- name: Sync
run: |
python ./script/sync-device_class.py
- name: Get PR template
id: pr-template-body
run: |
body=$(cat .github/PULL_REQUEST_TEMPLATE.md)
delimiter="$(openssl rand -hex 8)"
echo "body<<$delimiter" >> $GITHUB_OUTPUT
echo "$body" >> $GITHUB_OUTPUT
echo "$delimiter" >> $GITHUB_OUTPUT
- name: Commit changes
uses: peter-evans/create-pull-request@v4
with:
commit-message: "Synchronise Device Classes from Home Assistant"
committer: esphomebot <esphome@nabucasa.com>
author: esphomebot <esphome@nabucasa.com>
branch: sync/device-classes/
branch-suffix: timestamp
delete-branch: true
title: "Synchronise Device Classes from Home Assistant"
body: ${{ steps.pr-template-body.outputs.body }}

View File

@@ -2,8 +2,8 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/ambv/black
rev: 23.1.0
- repo: https://github.com/psf/black
rev: 23.3.0
hooks:
- id: black
args:

15
.vscode/tasks.json vendored
View File

@@ -2,15 +2,24 @@
"version": "2.0.0",
"tasks": [
{
"label": "run",
"label": "Run Dashboard",
"type": "shell",
"command": "python3 -m esphome dashboard config/",
"command": "${command:python.interpreterPath}",
"args": [
"-m",
"esphome",
"dashboard",
"config/"
],
"problemMatcher": []
},
{
"label": "clang-tidy",
"type": "shell",
"command": "./script/clang-tidy",
"command": "${command:python.interpreterPath}",
"args": [
"./script/clang-tidy"
],
"problemMatcher": [
{
"owner": "clang-tidy",

View File

@@ -111,6 +111,8 @@ esphome/components/hte501/* @Stock-M
esphome/components/hydreon_rgxx/* @functionpointer
esphome/components/i2c/* @esphome/core
esphome/components/i2s_audio/* @jesserockz
esphome/components/i2s_audio/media_player/* @jesserockz
esphome/components/i2s_audio/microphone/* @jesserockz
esphome/components/ili9xxx/* @nielsnl68
esphome/components/improv_base/* @esphome/core
esphome/components/improv_serial/* @esphome/core
@@ -154,11 +156,13 @@ esphome/components/mcp9808/* @k7hpn
esphome/components/md5/* @esphome/core
esphome/components/mdns/* @esphome/core
esphome/components/media_player/* @jesserockz
esphome/components/microphone/* @jesserockz
esphome/components/mics_4514/* @jesserockz
esphome/components/midea/* @dudanov
esphome/components/midea_ir/* @dudanov
esphome/components/mitsubishi/* @RubyBailey
esphome/components/mlx90393/* @functionpointer
esphome/components/mmc5603/* @benhoff
esphome/components/modbus_controller/* @martgras
esphome/components/modbus_controller/binary_sensor/* @martgras
esphome/components/modbus_controller/number/* @martgras
@@ -286,6 +290,7 @@ esphome/components/ufire_ise/* @pvizeli
esphome/components/ultrasonic/* @OttoWinter
esphome/components/vbus/* @ssieb
esphome/components/version/* @esphome/core
esphome/components/voice_assistant/* @jesserockz
esphome/components/wake_on_lan/* @willwill2will54
esphome/components/web_server_base/* @OttoWinter
esphome/components/whirlpool/* @glmnet

View File

@@ -152,6 +152,8 @@ def run_miniterm(config, port):
_LOGGER.error("Could not connect to serial port %s", port)
return 1
return 0
def wrap_to_code(name, comp):
coro = coroutine(comp.to_code)

View File

@@ -53,6 +53,9 @@ service APIConnection {
rpc bluetooth_gatt_write_descriptor(BluetoothGATTWriteDescriptorRequest) returns (void) {}
rpc bluetooth_gatt_notify(BluetoothGATTNotifyRequest) returns (void) {}
rpc subscribe_bluetooth_connections_free(SubscribeBluetoothConnectionsFreeRequest) returns (BluetoothConnectionsFreeResponse) {}
rpc unsubscribe_bluetooth_le_advertisements(UnsubscribeBluetoothLEAdvertisementsRequest) returns (void) {}
rpc subscribe_voice_assistant(SubscribeVoiceAssistantRequest) returns (void) {}
}
@@ -208,6 +211,8 @@ message DeviceInfoResponse {
string manufacturer = 12;
string friendly_name = 13;
uint32 voice_assistant_version = 14;
}
message ListEntitiesRequest {
@@ -1125,6 +1130,7 @@ message MediaPlayerCommandRequest {
message SubscribeBluetoothLEAdvertisementsRequest {
option (id) = 66;
option (source) = SOURCE_CLIENT;
option (ifdef) = "USE_BLUETOOTH_PROXY";
}
message BluetoothServiceData {
@@ -1361,6 +1367,12 @@ message BluetoothDeviceUnpairingResponse {
int32 error = 3;
}
message UnsubscribeBluetoothLEAdvertisementsRequest {
option (id) = 87;
option (source) = SOURCE_CLIENT;
option (ifdef) = "USE_BLUETOOTH_PROXY";
}
message BluetoothDeviceClearCacheResponse {
option (id) = 88;
option (source) = SOURCE_SERVER;
@@ -1370,3 +1382,55 @@ message BluetoothDeviceClearCacheResponse {
bool success = 2;
int32 error = 3;
}
// ==================== PUSH TO TALK ====================
message SubscribeVoiceAssistantRequest {
option (id) = 89;
option (source) = SOURCE_CLIENT;
option (ifdef) = "USE_VOICE_ASSISTANT";
bool subscribe = 1;
}
message VoiceAssistantRequest {
option (id) = 90;
option (source) = SOURCE_SERVER;
option (ifdef) = "USE_VOICE_ASSISTANT";
bool start = 1;
}
message VoiceAssistantResponse {
option (id) = 91;
option (source) = SOURCE_CLIENT;
option (ifdef) = "USE_VOICE_ASSISTANT";
uint32 port = 1;
bool error = 2;
}
enum VoiceAssistantEvent {
VOICE_ASSISTANT_ERROR = 0;
VOICE_ASSISTANT_RUN_START = 1;
VOICE_ASSISTANT_RUN_END = 2;
VOICE_ASSISTANT_STT_START = 3;
VOICE_ASSISTANT_STT_END = 4;
VOICE_ASSISTANT_INTENT_START = 5;
VOICE_ASSISTANT_INTENT_END = 6;
VOICE_ASSISTANT_TTS_START = 7;
VOICE_ASSISTANT_TTS_END = 8;
}
message VoiceAssistantEventData {
string name = 1;
string value = 2;
}
message VoiceAssistantEventResponse {
option (id) = 92;
option (source) = SOURCE_CLIENT;
option (ifdef) = "USE_VOICE_ASSISTANT";
VoiceAssistantEvent event_type = 1;
repeated VoiceAssistantEventData data = 2;
}

View File

@@ -1,5 +1,6 @@
#include "api_connection.h"
#include <cerrno>
#include <cinttypes>
#include "esphome/components/network/util.h"
#include "esphome/core/entity_base.h"
#include "esphome/core/hal.h"
@@ -15,6 +16,9 @@
#ifdef USE_BLUETOOTH_PROXY
#include "esphome/components/bluetooth_proxy/bluetooth_proxy.h"
#endif
#ifdef USE_VOICE_ASSISTANT
#include "esphome/components/voice_assistant/voice_assistant.h"
#endif
namespace esphome {
namespace api {
@@ -892,6 +896,30 @@ BluetoothConnectionsFreeResponse APIConnection::subscribe_bluetooth_connections_
}
#endif
#ifdef USE_VOICE_ASSISTANT
bool APIConnection::request_voice_assistant(bool start) {
if (!this->voice_assistant_subscription_)
return false;
VoiceAssistantRequest msg;
msg.start = start;
return this->send_voice_assistant_request(msg);
}
void APIConnection::on_voice_assistant_response(const VoiceAssistantResponse &msg) {
if (voice_assistant::global_voice_assistant != nullptr) {
struct sockaddr_storage storage;
socklen_t len = sizeof(storage);
this->helper_->getpeername((struct sockaddr *) &storage, &len);
voice_assistant::global_voice_assistant->start(&storage, msg.port);
}
};
void APIConnection::on_voice_assistant_event_response(const VoiceAssistantEventResponse &msg) {
if (voice_assistant::global_voice_assistant != nullptr) {
voice_assistant::global_voice_assistant->on_event(msg);
}
}
#endif
bool APIConnection::send_log_message(int level, const char *tag, const char *line) {
if (this->log_subscription_ < level)
return false;
@@ -911,7 +939,7 @@ HelloResponse APIConnection::hello(const HelloRequest &msg) {
this->helper_->set_log_info(client_info_);
this->client_api_version_major_ = msg.api_version_major;
this->client_api_version_minor_ = msg.api_version_minor;
ESP_LOGV(TAG, "Hello from client: '%s' | API Version %d.%d", this->client_info_.c_str(),
ESP_LOGV(TAG, "Hello from client: '%s' | API Version %" PRIu32 ".%" PRIu32, this->client_info_.c_str(),
this->client_api_version_major_, this->client_api_version_minor_);
HelloResponse resp;
@@ -969,6 +997,9 @@ DeviceInfoResponse APIConnection::device_info(const DeviceInfoRequest &msg) {
resp.bluetooth_proxy_version = bluetooth_proxy::global_bluetooth_proxy->has_active()
? bluetooth_proxy::ACTIVE_CONNECTIONS_VERSION
: bluetooth_proxy::PASSIVE_ONLY_VERSION;
#endif
#ifdef USE_VOICE_ASSISTANT
resp.voice_assistant_version = 1;
#endif
return resp;
}

View File

@@ -6,6 +6,7 @@
#include "api_server.h"
#include "esphome/core/application.h"
#include "esphome/core/component.h"
#include "esphome/core/defines.h"
#include <vector>
@@ -97,6 +98,12 @@ class APIConnection : public APIServerConnection {
this->send_homeassistant_service_response(call);
}
#ifdef USE_BLUETOOTH_PROXY
void subscribe_bluetooth_le_advertisements(const SubscribeBluetoothLEAdvertisementsRequest &msg) override {
this->bluetooth_le_advertisement_subscription_ = true;
}
void unsubscribe_bluetooth_le_advertisements(const UnsubscribeBluetoothLEAdvertisementsRequest &msg) override {
this->bluetooth_le_advertisement_subscription_ = false;
}
bool send_bluetooth_le_advertisement(const BluetoothLEAdvertisementResponse &msg);
void bluetooth_device_request(const BluetoothDeviceRequest &msg) override;
@@ -117,6 +124,15 @@ class APIConnection : public APIServerConnection {
}
#endif
#ifdef USE_VOICE_ASSISTANT
void subscribe_voice_assistant(const SubscribeVoiceAssistantRequest &msg) override {
this->voice_assistant_subscription_ = msg.subscribe;
}
bool request_voice_assistant(bool start);
void on_voice_assistant_response(const VoiceAssistantResponse &msg) override;
void on_voice_assistant_event_response(const VoiceAssistantEventResponse &msg) override;
#endif
void on_disconnect_response(const DisconnectResponse &value) override;
void on_ping_response(const PingResponse &value) override {
// we initiated ping
@@ -150,9 +166,7 @@ class APIConnection : public APIServerConnection {
return {};
}
void execute_service(const ExecuteServiceRequest &msg) override;
void subscribe_bluetooth_le_advertisements(const SubscribeBluetoothLEAdvertisementsRequest &msg) override {
this->bluetooth_le_advertisement_subscription_ = true;
}
bool is_authenticated() override { return this->connection_state_ == ConnectionState::AUTHENTICATED; }
bool is_connection_setup() override {
return this->connection_state_ == ConnectionState ::CONNECTED || this->is_authenticated();
@@ -197,7 +211,12 @@ class APIConnection : public APIServerConnection {
uint32_t last_traffic_;
bool sent_ping_{false};
bool service_call_subscription_{false};
#ifdef USE_BLUETOOTH_PROXY
bool bluetooth_le_advertisement_subscription_{false};
#endif
#ifdef USE_VOICE_ASSISTANT
bool voice_assistant_subscription_{false};
#endif
bool next_close_ = false;
APIServer *parent_;
InitialStateIterator initial_state_iterator_;

View File

@@ -10,8 +10,8 @@
#include "noise/protocol.h"
#endif
#include "esphome/components/socket/socket.h"
#include "api_noise_context.h"
#include "esphome/components/socket/socket.h"
namespace esphome {
namespace api {
@@ -67,6 +67,7 @@ class APIFrameHelper {
virtual bool can_write_without_blocking() = 0;
virtual APIError write_packet(uint16_t type, const uint8_t *data, size_t len) = 0;
virtual std::string getpeername() = 0;
virtual int getpeername(struct sockaddr *addr, socklen_t *addrlen) = 0;
virtual APIError close() = 0;
virtual APIError shutdown(int how) = 0;
// Give this helper a name for logging
@@ -84,7 +85,10 @@ class APINoiseFrameHelper : public APIFrameHelper {
APIError read_packet(ReadPacketBuffer *buffer) override;
bool can_write_without_blocking() override;
APIError write_packet(uint16_t type, const uint8_t *payload, size_t len) override;
std::string getpeername() override { return socket_->getpeername(); }
std::string getpeername() override { return this->socket_->getpeername(); }
int getpeername(struct sockaddr *addr, socklen_t *addrlen) override {
return this->socket_->getpeername(addr, addrlen);
}
APIError close() override;
APIError shutdown(int how) override;
// Give this helper a name for logging
@@ -144,7 +148,10 @@ class APIPlaintextFrameHelper : public APIFrameHelper {
APIError read_packet(ReadPacketBuffer *buffer) override;
bool can_write_without_blocking() override;
APIError write_packet(uint16_t type, const uint8_t *payload, size_t len) override;
std::string getpeername() override { return socket_->getpeername(); }
std::string getpeername() override { return this->socket_->getpeername(); }
int getpeername(struct sockaddr *addr, socklen_t *addrlen) override {
return this->socket_->getpeername(addr, addrlen);
}
APIError close() override;
APIError shutdown(int how) override;
// Give this helper a name for logging

View File

@@ -407,6 +407,32 @@ const char *proto_enum_to_string<enums::BluetoothDeviceRequestType>(enums::Bluet
}
}
#endif
#ifdef HAS_PROTO_MESSAGE_DUMP
template<> const char *proto_enum_to_string<enums::VoiceAssistantEvent>(enums::VoiceAssistantEvent value) {
switch (value) {
case enums::VOICE_ASSISTANT_ERROR:
return "VOICE_ASSISTANT_ERROR";
case enums::VOICE_ASSISTANT_RUN_START:
return "VOICE_ASSISTANT_RUN_START";
case enums::VOICE_ASSISTANT_RUN_END:
return "VOICE_ASSISTANT_RUN_END";
case enums::VOICE_ASSISTANT_STT_START:
return "VOICE_ASSISTANT_STT_START";
case enums::VOICE_ASSISTANT_STT_END:
return "VOICE_ASSISTANT_STT_END";
case enums::VOICE_ASSISTANT_INTENT_START:
return "VOICE_ASSISTANT_INTENT_START";
case enums::VOICE_ASSISTANT_INTENT_END:
return "VOICE_ASSISTANT_INTENT_END";
case enums::VOICE_ASSISTANT_TTS_START:
return "VOICE_ASSISTANT_TTS_START";
case enums::VOICE_ASSISTANT_TTS_END:
return "VOICE_ASSISTANT_TTS_END";
default:
return "UNKNOWN";
}
}
#endif
bool HelloRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
switch (field_id) {
case 2: {
@@ -594,6 +620,10 @@ bool DeviceInfoResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
this->bluetooth_proxy_version = value.as_uint32();
return true;
}
case 14: {
this->voice_assistant_version = value.as_uint32();
return true;
}
default:
return false;
}
@@ -654,6 +684,7 @@ void DeviceInfoResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_uint32(11, this->bluetooth_proxy_version);
buffer.encode_string(12, this->manufacturer);
buffer.encode_string(13, this->friendly_name);
buffer.encode_uint32(14, this->voice_assistant_version);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void DeviceInfoResponse::dump_to(std::string &out) const {
@@ -712,6 +743,11 @@ void DeviceInfoResponse::dump_to(std::string &out) const {
out.append(" friendly_name: ");
out.append("'").append(this->friendly_name).append("'");
out.append("\n");
out.append(" voice_assistant_version: ");
sprintf(buffer, "%u", this->voice_assistant_version);
out.append(buffer);
out.append("\n");
out.append("}");
}
#endif
@@ -6062,6 +6098,12 @@ void BluetoothDeviceUnpairingResponse::dump_to(std::string &out) const {
out.append("}");
}
#endif
void UnsubscribeBluetoothLEAdvertisementsRequest::encode(ProtoWriteBuffer buffer) const {}
#ifdef HAS_PROTO_MESSAGE_DUMP
void UnsubscribeBluetoothLEAdvertisementsRequest::dump_to(std::string &out) const {
out.append("UnsubscribeBluetoothLEAdvertisementsRequest {}");
}
#endif
bool BluetoothDeviceClearCacheResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
switch (field_id) {
case 1: {
@@ -6105,6 +6147,155 @@ void BluetoothDeviceClearCacheResponse::dump_to(std::string &out) const {
out.append("}");
}
#endif
bool SubscribeVoiceAssistantRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
switch (field_id) {
case 1: {
this->subscribe = value.as_bool();
return true;
}
default:
return false;
}
}
void SubscribeVoiceAssistantRequest::encode(ProtoWriteBuffer buffer) const { buffer.encode_bool(1, this->subscribe); }
#ifdef HAS_PROTO_MESSAGE_DUMP
void SubscribeVoiceAssistantRequest::dump_to(std::string &out) const {
__attribute__((unused)) char buffer[64];
out.append("SubscribeVoiceAssistantRequest {\n");
out.append(" subscribe: ");
out.append(YESNO(this->subscribe));
out.append("\n");
out.append("}");
}
#endif
bool VoiceAssistantRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
switch (field_id) {
case 1: {
this->start = value.as_bool();
return true;
}
default:
return false;
}
}
void VoiceAssistantRequest::encode(ProtoWriteBuffer buffer) const { buffer.encode_bool(1, this->start); }
#ifdef HAS_PROTO_MESSAGE_DUMP
void VoiceAssistantRequest::dump_to(std::string &out) const {
__attribute__((unused)) char buffer[64];
out.append("VoiceAssistantRequest {\n");
out.append(" start: ");
out.append(YESNO(this->start));
out.append("\n");
out.append("}");
}
#endif
bool VoiceAssistantResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
switch (field_id) {
case 1: {
this->port = value.as_uint32();
return true;
}
case 2: {
this->error = value.as_bool();
return true;
}
default:
return false;
}
}
void VoiceAssistantResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_uint32(1, this->port);
buffer.encode_bool(2, this->error);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void VoiceAssistantResponse::dump_to(std::string &out) const {
__attribute__((unused)) char buffer[64];
out.append("VoiceAssistantResponse {\n");
out.append(" port: ");
sprintf(buffer, "%u", this->port);
out.append(buffer);
out.append("\n");
out.append(" error: ");
out.append(YESNO(this->error));
out.append("\n");
out.append("}");
}
#endif
bool VoiceAssistantEventData::decode_length(uint32_t field_id, ProtoLengthDelimited value) {
switch (field_id) {
case 1: {
this->name = value.as_string();
return true;
}
case 2: {
this->value = value.as_string();
return true;
}
default:
return false;
}
}
void VoiceAssistantEventData::encode(ProtoWriteBuffer buffer) const {
buffer.encode_string(1, this->name);
buffer.encode_string(2, this->value);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void VoiceAssistantEventData::dump_to(std::string &out) const {
__attribute__((unused)) char buffer[64];
out.append("VoiceAssistantEventData {\n");
out.append(" name: ");
out.append("'").append(this->name).append("'");
out.append("\n");
out.append(" value: ");
out.append("'").append(this->value).append("'");
out.append("\n");
out.append("}");
}
#endif
bool VoiceAssistantEventResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
switch (field_id) {
case 1: {
this->event_type = value.as_enum<enums::VoiceAssistantEvent>();
return true;
}
default:
return false;
}
}
bool VoiceAssistantEventResponse::decode_length(uint32_t field_id, ProtoLengthDelimited value) {
switch (field_id) {
case 2: {
this->data.push_back(value.as_message<VoiceAssistantEventData>());
return true;
}
default:
return false;
}
}
void VoiceAssistantEventResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_enum<enums::VoiceAssistantEvent>(1, this->event_type);
for (auto &it : this->data) {
buffer.encode_message<VoiceAssistantEventData>(2, it, true);
}
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void VoiceAssistantEventResponse::dump_to(std::string &out) const {
__attribute__((unused)) char buffer[64];
out.append("VoiceAssistantEventResponse {\n");
out.append(" event_type: ");
out.append(proto_enum_to_string<enums::VoiceAssistantEvent>(this->event_type));
out.append("\n");
for (const auto &it : this->data) {
out.append(" data: ");
it.dump_to(out);
out.append("\n");
}
out.append("}");
}
#endif
} // namespace api
} // namespace esphome

View File

@@ -165,6 +165,17 @@ enum BluetoothDeviceRequestType : uint32_t {
BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITHOUT_CACHE = 5,
BLUETOOTH_DEVICE_REQUEST_TYPE_CLEAR_CACHE = 6,
};
enum VoiceAssistantEvent : uint32_t {
VOICE_ASSISTANT_ERROR = 0,
VOICE_ASSISTANT_RUN_START = 1,
VOICE_ASSISTANT_RUN_END = 2,
VOICE_ASSISTANT_STT_START = 3,
VOICE_ASSISTANT_STT_END = 4,
VOICE_ASSISTANT_INTENT_START = 5,
VOICE_ASSISTANT_INTENT_END = 6,
VOICE_ASSISTANT_TTS_START = 7,
VOICE_ASSISTANT_TTS_END = 8,
};
} // namespace enums
@@ -279,6 +290,7 @@ class DeviceInfoResponse : public ProtoMessage {
uint32_t bluetooth_proxy_version{0};
std::string manufacturer{};
std::string friendly_name{};
uint32_t voice_assistant_version{0};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
@@ -1555,6 +1567,15 @@ class BluetoothDeviceUnpairingResponse : public ProtoMessage {
protected:
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
class UnsubscribeBluetoothLEAdvertisementsRequest : public ProtoMessage {
public:
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
#endif
protected:
};
class BluetoothDeviceClearCacheResponse : public ProtoMessage {
public:
uint64_t address{0};
@@ -1568,6 +1589,65 @@ class BluetoothDeviceClearCacheResponse : public ProtoMessage {
protected:
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
class SubscribeVoiceAssistantRequest : public ProtoMessage {
public:
bool subscribe{false};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
#endif
protected:
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
class VoiceAssistantRequest : public ProtoMessage {
public:
bool start{false};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
#endif
protected:
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
class VoiceAssistantResponse : public ProtoMessage {
public:
uint32_t port{0};
bool error{false};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
#endif
protected:
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
class VoiceAssistantEventData : public ProtoMessage {
public:
std::string name{};
std::string value{};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
#endif
protected:
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
};
class VoiceAssistantEventResponse : public ProtoMessage {
public:
enums::VoiceAssistantEvent event_type{};
std::vector<VoiceAssistantEventData> data{};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
#endif
protected:
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
} // namespace api
} // namespace esphome

View File

@@ -329,6 +329,8 @@ bool APIServerConnectionBase::send_media_player_state_response(const MediaPlayer
#ifdef USE_MEDIA_PLAYER
#endif
#ifdef USE_BLUETOOTH_PROXY
#endif
#ifdef USE_BLUETOOTH_PROXY
bool APIServerConnectionBase::send_bluetooth_le_advertisement_response(const BluetoothLEAdvertisementResponse &msg) {
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "send_bluetooth_le_advertisement_response: %s", msg.dump().c_str());
@@ -442,6 +444,8 @@ bool APIServerConnectionBase::send_bluetooth_device_unpairing_response(const Blu
}
#endif
#ifdef USE_BLUETOOTH_PROXY
#endif
#ifdef USE_BLUETOOTH_PROXY
bool APIServerConnectionBase::send_bluetooth_device_clear_cache_response(const BluetoothDeviceClearCacheResponse &msg) {
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "send_bluetooth_device_clear_cache_response: %s", msg.dump().c_str());
@@ -449,6 +453,20 @@ bool APIServerConnectionBase::send_bluetooth_device_clear_cache_response(const B
return this->send_message_<BluetoothDeviceClearCacheResponse>(msg, 88);
}
#endif
#ifdef USE_VOICE_ASSISTANT
#endif
#ifdef USE_VOICE_ASSISTANT
bool APIServerConnectionBase::send_voice_assistant_request(const VoiceAssistantRequest &msg) {
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "send_voice_assistant_request: %s", msg.dump().c_str());
#endif
return this->send_message_<VoiceAssistantRequest>(msg, 90);
}
#endif
#ifdef USE_VOICE_ASSISTANT
#endif
#ifdef USE_VOICE_ASSISTANT
#endif
bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) {
switch (msg_type) {
case 1: {
@@ -717,12 +735,14 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
break;
}
case 66: {
#ifdef USE_BLUETOOTH_PROXY
SubscribeBluetoothLEAdvertisementsRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_subscribe_bluetooth_le_advertisements_request: %s", msg.dump().c_str());
#endif
this->on_subscribe_bluetooth_le_advertisements_request(msg);
#endif
break;
}
case 68: {
@@ -810,6 +830,50 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
ESP_LOGVV(TAG, "on_subscribe_bluetooth_connections_free_request: %s", msg.dump().c_str());
#endif
this->on_subscribe_bluetooth_connections_free_request(msg);
#endif
break;
}
case 87: {
#ifdef USE_BLUETOOTH_PROXY
UnsubscribeBluetoothLEAdvertisementsRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_unsubscribe_bluetooth_le_advertisements_request: %s", msg.dump().c_str());
#endif
this->on_unsubscribe_bluetooth_le_advertisements_request(msg);
#endif
break;
}
case 89: {
#ifdef USE_VOICE_ASSISTANT
SubscribeVoiceAssistantRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_subscribe_voice_assistant_request: %s", msg.dump().c_str());
#endif
this->on_subscribe_voice_assistant_request(msg);
#endif
break;
}
case 91: {
#ifdef USE_VOICE_ASSISTANT
VoiceAssistantResponse msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_voice_assistant_response: %s", msg.dump().c_str());
#endif
this->on_voice_assistant_response(msg);
#endif
break;
}
case 92: {
#ifdef USE_VOICE_ASSISTANT
VoiceAssistantEventResponse msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_voice_assistant_event_response: %s", msg.dump().c_str());
#endif
this->on_voice_assistant_event_response(msg);
#endif
break;
}
@@ -1073,6 +1137,7 @@ void APIServerConnection::on_media_player_command_request(const MediaPlayerComma
this->media_player_command(msg);
}
#endif
#ifdef USE_BLUETOOTH_PROXY
void APIServerConnection::on_subscribe_bluetooth_le_advertisements_request(
const SubscribeBluetoothLEAdvertisementsRequest &msg) {
if (!this->is_connection_setup()) {
@@ -1085,6 +1150,7 @@ void APIServerConnection::on_subscribe_bluetooth_le_advertisements_request(
}
this->subscribe_bluetooth_le_advertisements(msg);
}
#endif
#ifdef USE_BLUETOOTH_PROXY
void APIServerConnection::on_bluetooth_device_request(const BluetoothDeviceRequest &msg) {
if (!this->is_connection_setup()) {
@@ -1193,6 +1259,33 @@ void APIServerConnection::on_subscribe_bluetooth_connections_free_request(
}
}
#endif
#ifdef USE_BLUETOOTH_PROXY
void APIServerConnection::on_unsubscribe_bluetooth_le_advertisements_request(
const UnsubscribeBluetoothLEAdvertisementsRequest &msg) {
if (!this->is_connection_setup()) {
this->on_no_setup_connection();
return;
}
if (!this->is_authenticated()) {
this->on_unauthenticated_access();
return;
}
this->unsubscribe_bluetooth_le_advertisements(msg);
}
#endif
#ifdef USE_VOICE_ASSISTANT
void APIServerConnection::on_subscribe_voice_assistant_request(const SubscribeVoiceAssistantRequest &msg) {
if (!this->is_connection_setup()) {
this->on_no_setup_connection();
return;
}
if (!this->is_authenticated()) {
this->on_unauthenticated_access();
return;
}
this->subscribe_voice_assistant(msg);
}
#endif
} // namespace api
} // namespace esphome

View File

@@ -154,8 +154,10 @@ class APIServerConnectionBase : public ProtoService {
#ifdef USE_MEDIA_PLAYER
virtual void on_media_player_command_request(const MediaPlayerCommandRequest &value){};
#endif
#ifdef USE_BLUETOOTH_PROXY
virtual void on_subscribe_bluetooth_le_advertisements_request(
const SubscribeBluetoothLEAdvertisementsRequest &value){};
#endif
#ifdef USE_BLUETOOTH_PROXY
bool send_bluetooth_le_advertisement_response(const BluetoothLEAdvertisementResponse &msg);
#endif
@@ -216,8 +218,24 @@ class APIServerConnectionBase : public ProtoService {
#ifdef USE_BLUETOOTH_PROXY
bool send_bluetooth_device_unpairing_response(const BluetoothDeviceUnpairingResponse &msg);
#endif
#ifdef USE_BLUETOOTH_PROXY
virtual void on_unsubscribe_bluetooth_le_advertisements_request(
const UnsubscribeBluetoothLEAdvertisementsRequest &value){};
#endif
#ifdef USE_BLUETOOTH_PROXY
bool send_bluetooth_device_clear_cache_response(const BluetoothDeviceClearCacheResponse &msg);
#endif
#ifdef USE_VOICE_ASSISTANT
virtual void on_subscribe_voice_assistant_request(const SubscribeVoiceAssistantRequest &value){};
#endif
#ifdef USE_VOICE_ASSISTANT
bool send_voice_assistant_request(const VoiceAssistantRequest &msg);
#endif
#ifdef USE_VOICE_ASSISTANT
virtual void on_voice_assistant_response(const VoiceAssistantResponse &value){};
#endif
#ifdef USE_VOICE_ASSISTANT
virtual void on_voice_assistant_event_response(const VoiceAssistantEventResponse &value){};
#endif
protected:
bool read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) override;
@@ -270,7 +288,9 @@ class APIServerConnection : public APIServerConnectionBase {
#ifdef USE_MEDIA_PLAYER
virtual void media_player_command(const MediaPlayerCommandRequest &msg) = 0;
#endif
#ifdef USE_BLUETOOTH_PROXY
virtual void subscribe_bluetooth_le_advertisements(const SubscribeBluetoothLEAdvertisementsRequest &msg) = 0;
#endif
#ifdef USE_BLUETOOTH_PROXY
virtual void bluetooth_device_request(const BluetoothDeviceRequest &msg) = 0;
#endif
@@ -295,6 +315,12 @@ class APIServerConnection : public APIServerConnectionBase {
#ifdef USE_BLUETOOTH_PROXY
virtual BluetoothConnectionsFreeResponse subscribe_bluetooth_connections_free(
const SubscribeBluetoothConnectionsFreeRequest &msg) = 0;
#endif
#ifdef USE_BLUETOOTH_PROXY
virtual void unsubscribe_bluetooth_le_advertisements(const UnsubscribeBluetoothLEAdvertisementsRequest &msg) = 0;
#endif
#ifdef USE_VOICE_ASSISTANT
virtual void subscribe_voice_assistant(const SubscribeVoiceAssistantRequest &msg) = 0;
#endif
protected:
void on_hello_request(const HelloRequest &msg) override;
@@ -342,7 +368,9 @@ class APIServerConnection : public APIServerConnectionBase {
#ifdef USE_MEDIA_PLAYER
void on_media_player_command_request(const MediaPlayerCommandRequest &msg) override;
#endif
#ifdef USE_BLUETOOTH_PROXY
void on_subscribe_bluetooth_le_advertisements_request(const SubscribeBluetoothLEAdvertisementsRequest &msg) override;
#endif
#ifdef USE_BLUETOOTH_PROXY
void on_bluetooth_device_request(const BluetoothDeviceRequest &msg) override;
#endif
@@ -367,6 +395,13 @@ class APIServerConnection : public APIServerConnectionBase {
#ifdef USE_BLUETOOTH_PROXY
void on_subscribe_bluetooth_connections_free_request(const SubscribeBluetoothConnectionsFreeRequest &msg) override;
#endif
#ifdef USE_BLUETOOTH_PROXY
void on_unsubscribe_bluetooth_le_advertisements_request(
const UnsubscribeBluetoothLEAdvertisementsRequest &msg) override;
#endif
#ifdef USE_VOICE_ASSISTANT
void on_subscribe_voice_assistant_request(const SubscribeVoiceAssistantRequest &msg) override;
#endif
};
} // namespace api

View File

@@ -427,5 +427,20 @@ void APIServer::on_shutdown() {
delay(10);
}
#ifdef USE_VOICE_ASSISTANT
bool APIServer::start_voice_assistant() {
bool result = false;
for (auto &c : this->clients_) {
result |= c->request_voice_assistant(true);
}
return result;
}
void APIServer::stop_voice_assistant() {
for (auto &c : this->clients_) {
c->request_voice_assistant(false);
}
}
#endif
} // namespace api
} // namespace esphome

View File

@@ -95,6 +95,11 @@ class APIServer : public Component, public Controller {
void request_time();
#endif
#ifdef USE_VOICE_ASSISTANT
bool start_voice_assistant();
void stop_voice_assistant();
#endif
bool is_connected() const;
struct HomeAssistantStateSubscription {

View File

@@ -1,4 +1,5 @@
#include "proto.h"
#include <cinttypes>
#include "esphome/core/log.h"
namespace esphome {
@@ -13,7 +14,7 @@ void ProtoMessage::decode(const uint8_t *buffer, size_t length) {
uint32_t consumed;
auto res = ProtoVarInt::parse(&buffer[i], length - i, &consumed);
if (!res.has_value()) {
ESP_LOGV(TAG, "Invalid field start at %u", i);
ESP_LOGV(TAG, "Invalid field start at %" PRIu32, i);
break;
}
@@ -25,12 +26,12 @@ void ProtoMessage::decode(const uint8_t *buffer, size_t length) {
case 0: { // VarInt
res = ProtoVarInt::parse(&buffer[i], length - i, &consumed);
if (!res.has_value()) {
ESP_LOGV(TAG, "Invalid VarInt at %u", i);
ESP_LOGV(TAG, "Invalid VarInt at %" PRIu32, i);
error = true;
break;
}
if (!this->decode_varint(field_id, *res)) {
ESP_LOGV(TAG, "Cannot decode VarInt field %u with value %u!", field_id, res->as_uint32());
ESP_LOGV(TAG, "Cannot decode VarInt field %" PRIu32 " with value %" PRIu32 "!", field_id, res->as_uint32());
}
i += consumed;
break;
@@ -38,38 +39,38 @@ void ProtoMessage::decode(const uint8_t *buffer, size_t length) {
case 2: { // Length-delimited
res = ProtoVarInt::parse(&buffer[i], length - i, &consumed);
if (!res.has_value()) {
ESP_LOGV(TAG, "Invalid Length Delimited at %u", i);
ESP_LOGV(TAG, "Invalid Length Delimited at %" PRIu32, i);
error = true;
break;
}
uint32_t field_length = res->as_uint32();
i += consumed;
if (field_length > length - i) {
ESP_LOGV(TAG, "Out-of-bounds Length Delimited at %u", i);
ESP_LOGV(TAG, "Out-of-bounds Length Delimited at %" PRIu32, i);
error = true;
break;
}
if (!this->decode_length(field_id, ProtoLengthDelimited(&buffer[i], field_length))) {
ESP_LOGV(TAG, "Cannot decode Length Delimited field %u!", field_id);
ESP_LOGV(TAG, "Cannot decode Length Delimited field %" PRIu32 "!", field_id);
}
i += field_length;
break;
}
case 5: { // 32-bit
if (length - i < 4) {
ESP_LOGV(TAG, "Out-of-bounds Fixed32-bit at %u", i);
ESP_LOGV(TAG, "Out-of-bounds Fixed32-bit at %" PRIu32, i);
error = true;
break;
}
uint32_t val = encode_uint32(buffer[i + 3], buffer[i + 2], buffer[i + 1], buffer[i]);
if (!this->decode_32bit(field_id, Proto32Bit(val))) {
ESP_LOGV(TAG, "Cannot decode 32-bit field %u with value %u!", field_id, val);
ESP_LOGV(TAG, "Cannot decode 32-bit field %" PRIu32 " with value %" PRIu32 "!", field_id, val);
}
i += 4;
break;
}
default:
ESP_LOGV(TAG, "Invalid field type at %u", i);
ESP_LOGV(TAG, "Invalid field type at %" PRIu32, i);
error = true;
break;
}

View File

@@ -12,7 +12,6 @@ from esphome.const import (
CONF_CAPACITANCE,
)
AUTO_LOAD = ["sensor", "binary_sensor"]
MULTI_CONF = True
CONF_AS3935_ID = "as3935_id"

View File

@@ -26,9 +26,13 @@ void AS3935Component::setup() {
void AS3935Component::dump_config() {
ESP_LOGCONFIG(TAG, "AS3935:");
LOG_PIN(" Interrupt Pin: ", this->irq_pin_);
#ifdef USE_BINARY_SENSOR
LOG_BINARY_SENSOR(" ", "Thunder alert", this->thunder_alert_binary_sensor_);
#endif
#ifdef USE_SENSOR
LOG_SENSOR(" ", "Distance", this->distance_sensor_);
LOG_SENSOR(" ", "Lightning energy", this->energy_sensor_);
#endif
}
float AS3935Component::get_setup_priority() const { return setup_priority::DATA; }
@@ -44,16 +48,22 @@ void AS3935Component::loop() {
ESP_LOGI(TAG, "Disturber was detected - try increasing the spike rejection value!");
} else if (int_value == LIGHTNING_INT) {
ESP_LOGI(TAG, "Lightning has been detected!");
if (this->thunder_alert_binary_sensor_ != nullptr)
#ifdef USE_BINARY_SENSOR
if (this->thunder_alert_binary_sensor_ != nullptr) {
this->thunder_alert_binary_sensor_->publish_state(true);
this->set_timeout(10, [this]() { this->thunder_alert_binary_sensor_->publish_state(false); });
}
#endif
#ifdef USE_SENSOR
uint8_t distance = this->get_distance_to_storm_();
if (this->distance_sensor_ != nullptr)
this->distance_sensor_->publish_state(distance);
uint32_t energy = this->get_lightning_energy_();
if (this->energy_sensor_ != nullptr)
this->energy_sensor_->publish_state(energy);
#endif
}
this->thunder_alert_binary_sensor_->publish_state(false);
}
void AS3935Component::write_indoor(bool indoor) {

View File

@@ -1,9 +1,14 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/core/defines.h"
#include "esphome/core/hal.h"
#ifdef USE_SENSOR
#include "esphome/components/sensor/sensor.h"
#endif
#ifdef USE_BINARY_SENSOR
#include "esphome/components/binary_sensor/binary_sensor.h"
#endif
namespace esphome {
namespace as3935 {
@@ -52,6 +57,15 @@ enum AS3935Values {
};
class AS3935Component : public Component {
#ifdef USE_SENSOR
SUB_SENSOR(distance)
SUB_SENSOR(energy)
#endif
#ifdef USE_BINARY_SENSOR
SUB_BINARY_SENSOR(thunder_alert)
#endif
public:
void setup() override;
void dump_config() override;
@@ -59,11 +73,7 @@ class AS3935Component : public Component {
void loop() override;
void set_irq_pin(GPIOPin *irq_pin) { irq_pin_ = irq_pin; }
void set_distance_sensor(sensor::Sensor *distance_sensor) { distance_sensor_ = distance_sensor; }
void set_energy_sensor(sensor::Sensor *energy_sensor) { energy_sensor_ = energy_sensor; }
void set_thunder_alert_binary_sensor(binary_sensor::BinarySensor *thunder_alert_binary_sensor) {
thunder_alert_binary_sensor_ = thunder_alert_binary_sensor;
}
void set_indoor(bool indoor) { indoor_ = indoor; }
void write_indoor(bool indoor);
void set_noise_level(uint8_t noise_level) { noise_level_ = noise_level; }
@@ -92,9 +102,6 @@ class AS3935Component : public Component {
virtual void write_register(uint8_t reg, uint8_t mask, uint8_t bits, uint8_t start_position) = 0;
sensor::Sensor *distance_sensor_{nullptr};
sensor::Sensor *energy_sensor_{nullptr};
binary_sensor::BinarySensor *thunder_alert_binary_sensor_{nullptr};
GPIOPin *irq_pin_;
bool indoor_;

View File

@@ -116,7 +116,7 @@ class BedJetHub : public esphome::ble_client::BLEClientNode, public PollingCompo
void update() override;
void dump_config() override;
void setup() override { this->codec_ = make_unique<BedjetCodec>(); }
float get_setup_priority() const override { return setup_priority::AFTER_WIFI; }
float get_setup_priority() const override { return setup_priority::BLUETOOTH; }
/** @return The BedJet's configured name, or the MAC address if not discovered yet. */
std::string get_name() {

View File

@@ -30,7 +30,7 @@ void BinarySensorMap::process_group_() {
if (bs.binary_sensor->state) {
num_active_sensors++;
total_current_value += bs.sensor_value;
mask |= 1 << i;
mask |= 1ULL << i;
}
}
// check if the sensor map was touched
@@ -38,12 +38,11 @@ void BinarySensorMap::process_group_() {
// did the bit_mask change or is it a new sensor touch
if (this->last_mask_ != mask) {
float publish_value = total_current_value / num_active_sensors;
ESP_LOGD(TAG, "'%s' - Publishing %.2f", this->name_.c_str(), publish_value);
this->publish_state(publish_value);
}
} else if (this->last_mask_ != 0ULL) {
// is this a new sensor release
ESP_LOGD(TAG, "'%s' - No binary sensor active, publishing NAN", this->name_.c_str());
ESP_LOGV(TAG, "'%s' - No binary sensor active, publishing NAN", this->name_.c_str());
this->publish_state(NAN);
}
this->last_mask_ = mask;
@@ -52,28 +51,22 @@ void BinarySensorMap::process_group_() {
void BinarySensorMap::process_sum_() {
float total_current_value = 0.0;
uint64_t mask = 0x00;
// check all binary_sensors for its state. when active add its value to total_current_value.
// create a bitmask for the binary_sensor status on all channels
// - check all binary_sensor states
// - if active, add its value to total_current_value
// - creates a bitmask for the binary_sensor status on all channels
for (size_t i = 0; i < this->channels_.size(); i++) {
auto bs = this->channels_[i];
if (bs.binary_sensor->state) {
total_current_value += bs.sensor_value;
mask |= 1 << i;
mask |= 1ULL << i;
}
}
// check if the sensor map was touched
if (mask != 0ULL) {
// did the bit_mask change or is it a new sensor touch
if (this->last_mask_ != mask) {
float publish_value = total_current_value;
ESP_LOGD(TAG, "'%s' - Publishing %.2f", this->name_.c_str(), publish_value);
this->publish_state(publish_value);
}
} else if (this->last_mask_ != 0ULL) {
// is this a new sensor release
ESP_LOGD(TAG, "'%s' - No binary sensor active, publishing 0", this->name_.c_str());
this->publish_state(0.0);
// update state only if the binary sensor states have changed or if no state has ever been sent on boot
if ((this->last_mask_ != mask) || (!this->has_state())) {
this->publish_state(total_current_value);
}
this->last_mask_ = mask;
}

View File

@@ -39,7 +39,7 @@ CONFIG_SCHEMA = cv.typed_schema(
).extend(
{
cv.Required(CONF_CHANNELS): cv.All(
cv.ensure_list(entry), cv.Length(min=1)
cv.ensure_list(entry), cv.Length(min=1, max=64)
),
}
),
@@ -50,7 +50,7 @@ CONFIG_SCHEMA = cv.typed_schema(
).extend(
{
cv.Required(CONF_CHANNELS): cv.All(
cv.ensure_list(entry), cv.Length(min=1)
cv.ensure_list(entry), cv.Length(min=1, max=64)
),
}
),

View File

@@ -6,9 +6,6 @@ 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();

View File

@@ -28,9 +28,6 @@ namespace button {
*/
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.

View File

@@ -453,12 +453,7 @@ void Climate::set_visual_temperature_step_override(float target, float current)
this->visual_target_temperature_step_override_ = target;
this->visual_current_temperature_step_override_ = current;
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
Climate::Climate(const std::string &name) : EntityBase(name) {}
#pragma GCC diagnostic pop
Climate::Climate() : Climate("") {}
ClimateCall Climate::make_call() { return ClimateCall(this); }
ClimateCall ClimateDeviceRestoreState::to_call(Climate *climate) {

View File

@@ -166,11 +166,6 @@ struct ClimateDeviceRestoreState {
*/
class Climate : public EntityBase {
public:
/// Construct a climate device with empty name (will be set later).
Climate();
/// Construct a climate device with a name.
Climate(const std::string &name);
/// The active mode of the climate device.
ClimateMode mode{CLIMATE_MODE_OFF};
/// The active state of the climate device.

View File

@@ -31,7 +31,7 @@ const char *cover_operation_to_str(CoverOperation op) {
}
}
Cover::Cover(const std::string &name) : EntityBase(name), position{COVER_OPEN} {}
Cover::Cover() : position{COVER_OPEN} {}
CoverCall::CoverCall(Cover *parent) : parent_(parent) {}
CoverCall &CoverCall::set_command(const char *command) {
@@ -204,7 +204,6 @@ optional<CoverRestoreState> Cover::restore_state_() {
return {};
return recovered;
}
Cover::Cover() : Cover("") {}
std::string Cover::get_device_class() {
if (this->device_class_override_.has_value())
return *this->device_class_override_;

View File

@@ -111,7 +111,6 @@ const char *cover_operation_to_str(CoverOperation op);
class Cover : public EntityBase {
public:
explicit Cover();
explicit Cover(const std::string &name);
/// The current operation of the cover (idle, opening, closing).
CoverOperation current_operation{COVER_OPERATION_IDLE};

View File

@@ -1,15 +1,11 @@
import esphome.codegen as cg
import esphome.config_validation as cv
import esphome.final_validate as fv
from esphome.components import logger
from esphome.const import (
CONF_BLOCK,
CONF_DEVICE,
CONF_FRAGMENTATION,
CONF_FREE,
CONF_ID,
CONF_LEVEL,
CONF_LOGGER,
CONF_LOOP_TIME,
)
@@ -43,18 +39,6 @@ CONFIG_SCHEMA = cv.Schema(
).extend(cv.polling_component_schema("60s"))
def _final_validate(_):
logger_conf = fv.full_config.get()[CONF_LOGGER]
severity = logger.LOG_LEVEL_SEVERITY.index(logger_conf[CONF_LEVEL])
if severity < logger.LOG_LEVEL_SEVERITY.index("DEBUG"):
raise cv.Invalid(
"The debug component requires the logger to be at least at DEBUG level"
)
FINAL_VALIDATE_SCHEMA = _final_validate
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)

View File

@@ -37,6 +37,10 @@ static uint32_t get_free_heap() {
}
void DebugComponent::dump_config() {
#ifndef ESPHOME_LOG_HAS_DEBUG
return; // Can't log below if debug logging is disabled
#endif
std::string device_info;
std::string reset_reason;
device_info.reserve(256);

View File

@@ -163,7 +163,7 @@ RECOMMENDED_ARDUINO_FRAMEWORK_VERSION = cv.Version(2, 0, 5)
# The platformio/espressif32 version to use for arduino frameworks
# - https://github.com/platformio/platform-espressif32/releases
# - https://api.registry.platformio.org/v3/packages/platformio/platform/espressif32
ARDUINO_PLATFORM_VERSION = cv.Version(5, 2, 0)
ARDUINO_PLATFORM_VERSION = cv.Version(5, 3, 0)
# The default/recommended esp-idf framework version
# - https://github.com/espressif/esp-idf/releases

View File

@@ -2,6 +2,7 @@
#include "gpio.h"
#include "esphome/core/log.h"
#include <cinttypes>
namespace esphome {
namespace esp32 {
@@ -74,7 +75,7 @@ void ESP32InternalGPIOPin::attach_interrupt(void (*func)(void *), void *arg, gpi
std::string ESP32InternalGPIOPin::dump_summary() const {
char buffer[32];
snprintf(buffer, sizeof(buffer), "GPIO%u", static_cast<uint32_t>(pin_));
snprintf(buffer, sizeof(buffer), "GPIO%" PRIu32, static_cast<uint32_t>(pin_));
return buffer;
}

View File

@@ -5,6 +5,7 @@
#include "esphome/core/log.h"
#include <nvs_flash.h>
#include <cstring>
#include <cinttypes>
#include <vector>
#include <string>
@@ -101,7 +102,7 @@ class ESP32Preferences : public ESPPreferences {
pref->nvs_handle = nvs_handle;
uint32_t keyval = type;
pref->key = str_sprintf("%u", keyval);
pref->key = str_sprintf("%" PRIu32, keyval);
return ESPPreferenceObject(pref);
}

View File

@@ -12,6 +12,8 @@ CONF_BLE_ID = "ble_id"
NO_BLUTOOTH_VARIANTS = [const.VARIANT_ESP32S2]
NO_BLUTOOTH_VARIANTS = [const.VARIANT_ESP32S2]
esp32_ble_ns = cg.esphome_ns.namespace("esp32_ble")
ESP32BLE = esp32_ble_ns.class_("ESP32BLE", cg.Component)

View File

@@ -6,6 +6,7 @@
#include <esp_bt.h>
#include <esp_bt_main.h>
#include <esp_bt_device.h>
#include <esp_gap_ble_api.h>
#include <freertos/FreeRTOS.h>
#include <freertos/FreeRTOSConfig.h>
@@ -211,7 +212,16 @@ void ESP32BLE::real_gattc_event_handler_(esp_gattc_cb_event_t event, esp_gatt_if
float ESP32BLE::get_setup_priority() const { return setup_priority::BLUETOOTH; }
void ESP32BLE::dump_config() { ESP_LOGCONFIG(TAG, "ESP32 BLE:"); }
void ESP32BLE::dump_config() {
const uint8_t *mac_address = esp_bt_dev_get_address();
if (mac_address) {
ESP_LOGCONFIG(TAG, "ESP32 BLE:");
ESP_LOGCONFIG(TAG, " MAC address: %02X:%02X:%02X:%02X:%02X:%02X", mac_address[0], mac_address[1], mac_address[2],
mac_address[3], mac_address[4], mac_address[5]);
} else {
ESP_LOGCONFIG(TAG, "ESP32 BLE: bluetooth stack is not enabled");
}
}
ESP32BLE *global_ble = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)

View File

@@ -202,7 +202,7 @@ void ESP32Camera::loop() {
float ESP32Camera::get_setup_priority() const { return setup_priority::DATA; }
/* ---------------- constructors ---------------- */
ESP32Camera::ESP32Camera(const std::string &name) : EntityBase(name) {
ESP32Camera::ESP32Camera() {
this->config_.pin_pwdn = -1;
this->config_.pin_reset = -1;
this->config_.pin_xclk = -1;
@@ -215,7 +215,6 @@ ESP32Camera::ESP32Camera(const std::string &name) : EntityBase(name) {
global_esp32_camera = this;
}
ESP32Camera::ESP32Camera() : ESP32Camera("") {}
/* ---------------- setters ---------------- */
/* set pin assignment */

View File

@@ -103,7 +103,6 @@ class CameraImageReader {
/* ---------------- ESP32Camera class ---------------- */
class ESP32Camera : public Component, public EntityBase {
public:
ESP32Camera(const std::string &name);
ESP32Camera();
/* setters */

View File

@@ -34,6 +34,7 @@ ETHERNET_TYPES = {
"DP83848": EthernetType.ETHERNET_TYPE_DP83848,
"IP101": EthernetType.ETHERNET_TYPE_IP101,
"JL1101": EthernetType.ETHERNET_TYPE_JL1101,
"KSZ8081": EthernetType.ETHERNET_TYPE_KSZ8081,
}
emac_rmii_clock_mode_t = cg.global_ns.enum("emac_rmii_clock_mode_t")

View File

@@ -26,8 +26,10 @@ EthernetComponent::EthernetComponent() { global_eth_component = this; }
void EthernetComponent::setup() {
ESP_LOGCONFIG(TAG, "Setting up Ethernet...");
// Delay here to allow power to stabilise before Ethernet is initialised.
delay(300); // NOLINT
if (esp_reset_reason() != ESP_RST_DEEPSLEEP) {
// Delay here to allow power to stabilise before Ethernet is initialized.
delay(300); // NOLINT
}
esp_err_t err;
err = esp_netif_init();
@@ -52,26 +54,29 @@ void EthernetComponent::setup() {
esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config);
esp_eth_phy_t *phy;
switch (this->type_) {
case ETHERNET_TYPE_LAN8720: {
phy = esp_eth_phy_new_lan87xx(&phy_config);
this->phy_ = esp_eth_phy_new_lan87xx(&phy_config);
break;
}
case ETHERNET_TYPE_RTL8201: {
phy = esp_eth_phy_new_rtl8201(&phy_config);
this->phy_ = esp_eth_phy_new_rtl8201(&phy_config);
break;
}
case ETHERNET_TYPE_DP83848: {
phy = esp_eth_phy_new_dp83848(&phy_config);
this->phy_ = esp_eth_phy_new_dp83848(&phy_config);
break;
}
case ETHERNET_TYPE_IP101: {
phy = esp_eth_phy_new_ip101(&phy_config);
this->phy_ = esp_eth_phy_new_ip101(&phy_config);
break;
}
case ETHERNET_TYPE_JL1101: {
phy = esp_eth_phy_new_jl1101(&phy_config);
this->phy_ = esp_eth_phy_new_jl1101(&phy_config);
break;
}
case ETHERNET_TYPE_KSZ8081: {
this->phy_ = esp_eth_phy_new_ksz8081(&phy_config);
break;
}
default: {
@@ -80,7 +85,7 @@ void EthernetComponent::setup() {
}
}
esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, phy);
esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, this->phy_);
this->eth_handle_ = nullptr;
err = esp_eth_driver_install(&eth_config, &this->eth_handle_);
ESPHL_ERROR_CHECK(err, "ETH driver install error");
@@ -140,7 +145,7 @@ void EthernetComponent::loop() {
}
void EthernetComponent::dump_config() {
std::string eth_type;
const char *eth_type;
switch (this->type_) {
case ETHERNET_TYPE_LAN8720:
eth_type = "LAN8720";
@@ -158,6 +163,14 @@ void EthernetComponent::dump_config() {
eth_type = "IP101";
break;
case ETHERNET_TYPE_JL1101:
eth_type = "JL1101";
break;
case ETHERNET_TYPE_KSZ8081:
eth_type = "KSZ8081";
break;
default:
eth_type = "Unknown";
break;
@@ -170,7 +183,8 @@ void EthernetComponent::dump_config() {
}
ESP_LOGCONFIG(TAG, " MDC Pin: %u", this->mdc_pin_);
ESP_LOGCONFIG(TAG, " MDIO Pin: %u", this->mdio_pin_);
ESP_LOGCONFIG(TAG, " Type: %s", eth_type.c_str());
ESP_LOGCONFIG(TAG, " Type: %s", eth_type);
ESP_LOGCONFIG(TAG, " PHY addr: %u", this->phy_addr_);
}
float EthernetComponent::get_setup_priority() const { return setup_priority::WIFI; }
@@ -263,7 +277,7 @@ void EthernetComponent::start_connect_() {
#endif
dns_setserver(0, &d);
}
if (uint32_t(this->manual_ip_->dns1) != 0) {
if (uint32_t(this->manual_ip_->dns2) != 0) {
ip_addr_t d;
#if LWIP_IPV6
d.type = IPADDR_TYPE_V4;
@@ -343,6 +357,21 @@ std::string EthernetComponent::get_use_address() const {
void EthernetComponent::set_use_address(const std::string &use_address) { this->use_address_ = use_address; }
bool EthernetComponent::powerdown() {
ESP_LOGI(TAG, "Powering down ethernet PHY");
if (this->phy_ == nullptr) {
ESP_LOGE(TAG, "Ethernet PHY not assigned");
return false;
}
this->connected_ = false;
this->started_ = false;
if (this->phy_->pwrctl(this->phy_, false) != ESP_OK) {
ESP_LOGE(TAG, "Error powering down ethernet PHY");
return false;
}
return true;
}
} // namespace ethernet
} // namespace esphome

View File

@@ -14,11 +14,13 @@ namespace esphome {
namespace ethernet {
enum EthernetType {
ETHERNET_TYPE_LAN8720 = 0,
ETHERNET_TYPE_UNKNOWN = 0,
ETHERNET_TYPE_LAN8720,
ETHERNET_TYPE_RTL8201,
ETHERNET_TYPE_DP83848,
ETHERNET_TYPE_IP101,
ETHERNET_TYPE_JL1101,
ETHERNET_TYPE_KSZ8081,
};
struct ManualIP {
@@ -43,6 +45,7 @@ class EthernetComponent : public Component {
void dump_config() override;
float get_setup_priority() const override;
bool can_proceed() override;
void on_shutdown() override { powerdown(); }
bool is_connected();
void set_phy_addr(uint8_t phy_addr);
@@ -56,6 +59,7 @@ class EthernetComponent : public Component {
network::IPAddress get_ip_address();
std::string get_use_address() const;
void set_use_address(const std::string &use_address);
bool powerdown();
protected:
static void eth_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data);
@@ -69,7 +73,7 @@ class EthernetComponent : public Component {
int power_pin_{-1};
uint8_t mdc_pin_{23};
uint8_t mdio_pin_{18};
EthernetType type_{ETHERNET_TYPE_LAN8720};
EthernetType type_{ETHERNET_TYPE_UNKNOWN};
emac_rmii_clock_mode_t clk_mode_{EMAC_CLK_EXT_IN};
emac_rmii_clock_gpio_t clk_gpio_{EMAC_CLK_IN_GPIO};
optional<ManualIP> manual_ip_{};
@@ -80,6 +84,7 @@ class EthernetComponent : public Component {
uint32_t connect_begin_;
esp_netif_t *eth_netif_{nullptr};
esp_eth_handle_t eth_handle_;
esp_eth_phy_t *phy_{nullptr};
};
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)

View File

@@ -12,14 +12,14 @@ static const char *const TAG = "ezo.sensor";
enum EzoCommandType : uint8_t {
EZO_READ = 0,
EZO_LED = 1,
EZO_DEVICE_INFORMATION = 2,
EZO_SLOPE = 3,
EZO_LED,
EZO_DEVICE_INFORMATION,
EZO_SLOPE,
EZO_CALIBRATION,
EZO_SLEEP = 4,
EZO_I2C = 5,
EZO_T = 6,
EZO_CUSTOM = 7
EZO_SLEEP,
EZO_I2C,
EZO_T,
EZO_CUSTOM
};
enum EzoCalibrationType : uint8_t { EZO_CAL_LOW = 0, EZO_CAL_MID = 1, EZO_CAL_HIGH = 2 };

View File

@@ -63,7 +63,7 @@ FanIsOffCondition = fan_ns.class_("FanIsOffCondition", automation.Condition.temp
FAN_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).extend(
{
cv.GenerateID(): cv.declare_id(Fan),
cv.Optional(CONF_RESTORE_MODE, default="RESTORE_DEFAULT_OFF"): cv.enum(
cv.Optional(CONF_RESTORE_MODE, default="ALWAYS_OFF"): cv.enum(
RESTORE_MODES, upper=True, space="_"
),
cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTFanComponent),

View File

@@ -80,9 +80,6 @@ void FanRestoreState::apply(Fan &fan) {
fan.publish_state();
}
Fan::Fan() : EntityBase("") {}
Fan::Fan(const std::string &name) : EntityBase(name) {}
FanCall Fan::turn_on() { return this->make_call().set_state(true); }
FanCall Fan::turn_off() { return this->make_call().set_state(false); }
FanCall Fan::toggle() { return this->make_call().set_state(!this->state); }

View File

@@ -99,10 +99,6 @@ struct FanRestoreState {
class Fan : public EntityBase {
public:
Fan();
/// Construct the fan with name.
explicit Fan(const std::string &name);
/// The current on/off state of the fan.
bool state{false};
/// The current oscillation state of the fan.

View File

@@ -15,7 +15,6 @@ enum ESPDEPRECATED("LegacyFanDirection members are deprecated, use FanDirection
class ESPDEPRECATED("FanState is deprecated, use Fan instead.", "2022.2") FanState : public Fan, public Component {
public:
FanState() = default;
explicit FanState(const std::string &name) : Fan(name) {}
/// Get the traits of this fan.
FanTraits get_traits() override { return this->traits_; }

View File

@@ -122,11 +122,18 @@ void Graph::draw(DisplayBuffer *buff, uint16_t x_offset, uint16_t y_offset, Colo
}
// Adjust limits to nice y_per_div boundaries
int yn = int(ymin / y_per_div);
int ym = int(ymax / y_per_div) + int(1 * (fmodf(ymax, y_per_div) != 0));
ymin = yn * y_per_div;
ymax = ym * y_per_div;
yrange = ymax - ymin;
int yn = 0;
int ym = 1;
if (!std::isnan(ymin) && !std::isnan(ymax)) {
yn = (int) floorf(ymin / y_per_div);
ym = (int) ceilf(ymax / y_per_div);
if (yn == ym) {
ym++;
}
ymin = yn * y_per_div;
ymax = ym * y_per_div;
yrange = ymax - ymin;
}
/// Draw grid
if (!std::isnan(this->gridspacing_y_)) {

View File

@@ -154,18 +154,25 @@ ErrorCode ArduinoI2CBus::writev(uint8_t address, WriteBuffer *buffers, size_t cn
}
}
uint8_t status = wire_->endTransmission(stop);
if (status == 0) {
return ERROR_OK;
} else if (status == 1) {
// transmit buffer not large enough
ESP_LOGVV(TAG, "TX failed: buffer not large enough");
return ERROR_UNKNOWN;
} else if (status == 2 || status == 3) {
ESP_LOGVV(TAG, "TX failed: not acknowledged");
return ERROR_NOT_ACKNOWLEDGED;
switch (status) {
case 0:
return ERROR_OK;
case 1:
// transmit buffer not large enough
ESP_LOGVV(TAG, "TX failed: buffer not large enough");
return ERROR_UNKNOWN;
case 2:
case 3:
ESP_LOGVV(TAG, "TX failed: not acknowledged");
return ERROR_NOT_ACKNOWLEDGED;
case 5:
ESP_LOGVV(TAG, "TX failed: timeout");
return ERROR_UNKNOWN;
case 4:
default:
ESP_LOGVV(TAG, "TX failed: unknown error %u", status);
return ERROR_UNKNOWN;
}
ESP_LOGVV(TAG, "TX failed: unknown error %u", status);
return ERROR_UNKNOWN;
}
/// Perform I2C bus recovery, see:

View File

@@ -5,6 +5,7 @@
#include "esphome/core/log.h"
#include "esphome/core/helpers.h"
#include <cstring>
#include <cinttypes>
namespace esphome {
namespace i2c {
@@ -47,7 +48,7 @@ void IDFI2CBus::dump_config() {
ESP_LOGCONFIG(TAG, "I2C Bus:");
ESP_LOGCONFIG(TAG, " SDA Pin: GPIO%u", this->sda_pin_);
ESP_LOGCONFIG(TAG, " SCL Pin: GPIO%u", this->scl_pin_);
ESP_LOGCONFIG(TAG, " Frequency: %u Hz", this->frequency_);
ESP_LOGCONFIG(TAG, " Frequency: %" PRIu32 " Hz", this->frequency_);
switch (this->recovery_result_) {
case RECOVERY_COMPLETED:
ESP_LOGCONFIG(TAG, " Recovery: bus successfully recovered");

View File

@@ -0,0 +1,70 @@
import esphome.config_validation as cv
import esphome.final_validate as fv
import esphome.codegen as cg
from esphome import pins
from esphome.const import CONF_ID
from esphome.components.esp32 import get_esp32_variant
from esphome.components.esp32.const import (
VARIANT_ESP32,
VARIANT_ESP32S2,
VARIANT_ESP32S3,
VARIANT_ESP32C3,
)
CODEOWNERS = ["@jesserockz"]
DEPENDENCIES = ["esp32"]
MULTI_CONF = True
CONF_I2S_DOUT_PIN = "i2s_dout_pin"
CONF_I2S_DIN_PIN = "i2s_din_pin"
CONF_I2S_BCLK_PIN = "i2s_bclk_pin"
CONF_I2S_LRCLK_PIN = "i2s_lrclk_pin"
CONF_I2S_AUDIO = "i2s_audio"
CONF_I2S_AUDIO_ID = "i2s_audio_id"
i2s_audio_ns = cg.esphome_ns.namespace("i2s_audio")
I2SAudioComponent = i2s_audio_ns.class_("I2SAudioComponent", cg.Component)
I2SAudioIn = i2s_audio_ns.class_("I2SAudioIn", cg.Parented.template(I2SAudioComponent))
I2SAudioOut = i2s_audio_ns.class_(
"I2SAudioOut", cg.Parented.template(I2SAudioComponent)
)
# https://github.com/espressif/esp-idf/blob/master/components/soc/{variant}/include/soc/soc_caps.h
I2S_PORTS = {
VARIANT_ESP32: 2,
VARIANT_ESP32S2: 1,
VARIANT_ESP32S3: 2,
VARIANT_ESP32C3: 1,
}
CONFIG_SCHEMA = cv.Schema(
{
cv.GenerateID(): cv.declare_id(I2SAudioComponent),
cv.Required(CONF_I2S_BCLK_PIN): pins.internal_gpio_output_pin_number,
cv.Required(CONF_I2S_LRCLK_PIN): pins.internal_gpio_output_pin_number,
}
)
def _final_validate(_):
i2s_audio_configs = fv.full_config.get()[CONF_I2S_AUDIO]
variant = get_esp32_variant()
if variant not in I2S_PORTS:
raise cv.Invalid(f"Unsupported variant {variant}")
if len(i2s_audio_configs) > I2S_PORTS[variant]:
raise cv.Invalid(
f"Only {I2S_PORTS[variant]} I2S audio ports are supported on {variant}"
)
FINAL_VALIDATE_SCHEMA = _final_validate
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
cg.add(var.set_bclk_pin(config[CONF_I2S_BCLK_PIN]))
cg.add(var.set_lrclk_pin(config[CONF_I2S_LRCLK_PIN]))

View File

@@ -0,0 +1,30 @@
#include "i2s_audio.h"
#ifdef USE_ESP32
#include "esphome/core/log.h"
namespace esphome {
namespace i2s_audio {
static const char *const TAG = "i2s_audio";
void I2SAudioComponent::setup() {
static i2s_port_t next_port_num = I2S_NUM_0;
if (next_port_num >= I2S_NUM_MAX) {
ESP_LOGE(TAG, "Too many I2S Audio components!");
this->mark_failed();
return;
}
this->port_ = next_port_num;
next_port_num = (i2s_port_t) (next_port_num + 1);
ESP_LOGCONFIG(TAG, "Setting up I2S Audio...");
}
} // namespace i2s_audio
} // namespace esphome
#endif // USE_ESP32

View File

@@ -0,0 +1,64 @@
#pragma once
#ifdef USE_ESP32
#include <driver/i2s.h>
#include "esphome/core/component.h"
#include "esphome/core/helpers.h"
namespace esphome {
namespace i2s_audio {
class I2SAudioComponent;
class I2SAudioIn : public Parented<I2SAudioComponent> {};
class I2SAudioOut : public Parented<I2SAudioComponent> {};
class I2SAudioComponent : public Component {
public:
void setup() override;
void register_audio_in(I2SAudioIn *in) {
this->audio_in_ = in;
in->set_parent(this);
}
void register_audio_out(I2SAudioOut *out) {
this->audio_out_ = out;
out->set_parent(this);
}
i2s_pin_config_t get_pin_config() const {
return {
.mck_io_num = I2S_PIN_NO_CHANGE,
.bck_io_num = this->bclk_pin_,
.ws_io_num = this->lrclk_pin_,
.data_out_num = I2S_PIN_NO_CHANGE,
.data_in_num = I2S_PIN_NO_CHANGE,
};
}
void set_bclk_pin(uint8_t pin) { this->bclk_pin_ = pin; }
void set_lrclk_pin(uint8_t pin) { this->lrclk_pin_ = pin; }
void lock() { this->lock_.lock(); }
bool try_lock() { return this->lock_.try_lock(); }
void unlock() { this->lock_.unlock(); }
i2s_port_t get_port() const { return this->port_; }
protected:
Mutex lock_;
I2SAudioIn *audio_in_{nullptr};
I2SAudioOut *audio_out_{nullptr};
uint8_t bclk_pin_;
uint8_t lrclk_pin_;
i2s_port_t port_{};
};
} // namespace i2s_audio
} // namespace esphome
#endif // USE_ESP32

View File

@@ -5,22 +5,25 @@ import esphome.config_validation as cv
from esphome import pins
from esphome.const import CONF_ID, CONF_MODE
from esphome.core import CORE
from .. import (
i2s_audio_ns,
I2SAudioComponent,
I2SAudioOut,
CONF_I2S_AUDIO_ID,
CONF_I2S_DOUT_PIN,
)
CODEOWNERS = ["@jesserockz"]
DEPENDENCIES = ["esp32"]
i2s_audio_ns = cg.esphome_ns.namespace("i2s_audio")
DEPENDENCIES = ["i2s_audio"]
I2SAudioMediaPlayer = i2s_audio_ns.class_(
"I2SAudioMediaPlayer", cg.Component, media_player.MediaPlayer
"I2SAudioMediaPlayer", cg.Component, media_player.MediaPlayer, I2SAudioOut
)
i2s_dac_mode_t = cg.global_ns.enum("i2s_dac_mode_t")
CONF_I2S_DOUT_PIN = "i2s_dout_pin"
CONF_I2S_BCLK_PIN = "i2s_bclk_pin"
CONF_I2S_LRCLK_PIN = "i2s_lrclk_pin"
CONF_MUTE_PIN = "mute_pin"
CONF_AUDIO_ID = "audio_id"
CONF_DAC_TYPE = "dac_type"
@@ -48,34 +51,26 @@ def validate_esp32_variant(config):
CONFIG_SCHEMA = cv.All(
cv.typed_schema(
{
"internal": cv.Schema(
"internal": media_player.MEDIA_PLAYER_SCHEMA.extend(
{
cv.GenerateID(): cv.declare_id(I2SAudioMediaPlayer),
cv.GenerateID(CONF_I2S_AUDIO_ID): cv.use_id(I2SAudioComponent),
cv.Required(CONF_MODE): cv.enum(INTERNAL_DAC_OPTIONS, lower=True),
}
)
.extend(media_player.MEDIA_PLAYER_SCHEMA)
.extend(cv.COMPONENT_SCHEMA),
"external": cv.Schema(
).extend(cv.COMPONENT_SCHEMA),
"external": media_player.MEDIA_PLAYER_SCHEMA.extend(
{
cv.GenerateID(): cv.declare_id(I2SAudioMediaPlayer),
cv.GenerateID(CONF_I2S_AUDIO_ID): cv.use_id(I2SAudioComponent),
cv.Required(
CONF_I2S_DOUT_PIN
): pins.internal_gpio_output_pin_number,
cv.Required(
CONF_I2S_BCLK_PIN
): pins.internal_gpio_output_pin_number,
cv.Required(
CONF_I2S_LRCLK_PIN
): pins.internal_gpio_output_pin_number,
cv.Optional(CONF_MUTE_PIN): pins.gpio_output_pin_schema,
cv.Optional(CONF_MODE, default="mono"): cv.one_of(
*EXTERNAL_DAC_OPTIONS, lower=True
),
}
)
.extend(media_player.MEDIA_PLAYER_SCHEMA)
.extend(cv.COMPONENT_SCHEMA),
).extend(cv.COMPONENT_SCHEMA),
},
key=CONF_DAC_TYPE,
),
@@ -89,19 +84,19 @@ async def to_code(config):
await cg.register_component(var, config)
await media_player.register_media_player(var, config)
parent = await cg.get_variable(config[CONF_I2S_AUDIO_ID])
cg.add(parent.register_audio_out(var))
if config[CONF_DAC_TYPE] == "internal":
cg.add(var.set_internal_dac_mode(config[CONF_MODE]))
else:
cg.add(var.set_dout_pin(config[CONF_I2S_DOUT_PIN]))
cg.add(var.set_bclk_pin(config[CONF_I2S_BCLK_PIN]))
cg.add(var.set_lrclk_pin(config[CONF_I2S_LRCLK_PIN]))
if CONF_MUTE_PIN in config:
pin = await cg.gpio_pin_expression(config[CONF_MUTE_PIN])
cg.add(var.set_mute_pin(pin))
cg.add(var.set_external_dac_channels(2 if config[CONF_MODE] == "stereo" else 1))
if CORE.is_esp32:
cg.add_library("WiFiClientSecure", None)
cg.add_library("HTTPClient", None)
cg.add_library("esphome/ESP32-audioI2S", "2.0.6")
cg.add_build_flag("-DAUDIO_NO_SD_FS")
cg.add_library("WiFiClientSecure", None)
cg.add_library("HTTPClient", None)
cg.add_library("esphome/ESP32-audioI2S", "2.0.6")
cg.add_build_flag("-DAUDIO_NO_SD_FS")

View File

@@ -11,11 +11,19 @@ static const char *const TAG = "audio";
void I2SAudioMediaPlayer::control(const media_player::MediaPlayerCall &call) {
if (call.get_media_url().has_value()) {
if (this->audio_->isRunning())
this->audio_->stopSong();
this->high_freq_.start();
this->audio_->connecttohost(call.get_media_url().value().c_str());
this->state = media_player::MEDIA_PLAYER_STATE_PLAYING;
this->current_url_ = call.get_media_url();
if (this->state == media_player::MEDIA_PLAYER_STATE_PLAYING && this->audio_ != nullptr) {
if (this->audio_->isRunning()) {
this->audio_->stopSong();
}
this->audio_->connecttohost(this->current_url_.value().c_str());
} else {
this->start();
}
}
if (this->i2s_state_ != I2S_STATE_RUNNING) {
return;
}
if (call.get_volume().has_value()) {
this->volume = call.get_volume().value();
@@ -35,7 +43,7 @@ void I2SAudioMediaPlayer::control(const media_player::MediaPlayerCall &call) {
this->state = media_player::MEDIA_PLAYER_STATE_PAUSED;
break;
case media_player::MEDIA_PLAYER_COMMAND_STOP:
this->stop_();
this->stop();
break;
case media_player::MEDIA_PLAYER_COMMAND_MUTE:
this->mute_();
@@ -94,22 +102,51 @@ void I2SAudioMediaPlayer::set_volume_(float volume, bool publish) {
this->volume = volume;
}
void I2SAudioMediaPlayer::stop_() {
if (this->audio_->isRunning())
this->audio_->stopSong();
this->high_freq_.stop();
void I2SAudioMediaPlayer::setup() {
ESP_LOGCONFIG(TAG, "Setting up Audio...");
this->state = media_player::MEDIA_PLAYER_STATE_IDLE;
}
void I2SAudioMediaPlayer::setup() {
ESP_LOGCONFIG(TAG, "Setting up Audio...");
void I2SAudioMediaPlayer::loop() {
switch (this->i2s_state_) {
case I2S_STATE_STARTING:
this->start_();
break;
case I2S_STATE_RUNNING:
this->play_();
break;
case I2S_STATE_STOPPING:
this->stop_();
break;
case I2S_STATE_STOPPED:
break;
}
}
void I2SAudioMediaPlayer::play_() {
this->audio_->loop();
if (this->state == media_player::MEDIA_PLAYER_STATE_PLAYING && !this->audio_->isRunning()) {
this->stop();
}
}
void I2SAudioMediaPlayer::start() { this->i2s_state_ = I2S_STATE_STARTING; }
void I2SAudioMediaPlayer::start_() {
if (this->parent_->try_lock()) {
return; // Waiting for another i2s to return lock
}
#if SOC_I2S_SUPPORTS_DAC
if (this->internal_dac_mode_ != I2S_DAC_CHANNEL_DISABLE) {
this->audio_ = make_unique<Audio>(true, this->internal_dac_mode_);
this->audio_ = make_unique<Audio>(true, this->internal_dac_mode_, this->parent_->get_port());
} else {
#endif
this->audio_ = make_unique<Audio>(false);
this->audio_->setPinout(this->bclk_pin_, this->lrclk_pin_, this->dout_pin_);
this->audio_ = make_unique<Audio>(false, I2S_DAC_CHANNEL_BOTH_EN, this->parent_->get_port());
i2s_pin_config_t pin_config = this->parent_->get_pin_config();
pin_config.data_out_num = this->dout_pin_;
i2s_set_pin(this->parent_->get_port(), &pin_config);
this->audio_->forceMono(this->external_dac_channels_ == 1);
if (this->mute_pin_ != nullptr) {
this->mute_pin_->setup();
@@ -118,16 +155,30 @@ void I2SAudioMediaPlayer::setup() {
#if SOC_I2S_SUPPORTS_DAC
}
#endif
this->state = media_player::MEDIA_PLAYER_STATE_IDLE;
}
void I2SAudioMediaPlayer::loop() {
this->audio_->loop();
if (this->state == media_player::MEDIA_PLAYER_STATE_PLAYING && !this->audio_->isRunning()) {
this->stop_();
this->i2s_state_ = I2S_STATE_RUNNING;
this->high_freq_.start();
if (this->current_url_.has_value()) {
this->audio_->connecttohost(this->current_url_.value().c_str());
this->state = media_player::MEDIA_PLAYER_STATE_PLAYING;
this->publish_state();
}
}
void I2SAudioMediaPlayer::stop() { this->i2s_state_ = I2S_STATE_STOPPING; }
void I2SAudioMediaPlayer::stop_() {
if (this->audio_->isRunning()) {
this->audio_->stopSong();
return;
}
this->audio_ = nullptr;
this->current_url_ = {};
this->parent_->unlock();
this->i2s_state_ = I2S_STATE_STOPPED;
this->high_freq_.stop();
this->state = media_player::MEDIA_PLAYER_STATE_IDLE;
this->publish_state();
}
media_player::MediaPlayerTraits I2SAudioMediaPlayer::get_traits() {
auto traits = media_player::MediaPlayerTraits();

View File

@@ -2,6 +2,10 @@
#ifdef USE_ESP32_FRAMEWORK_ARDUINO
#include "../i2s_audio.h"
#include <driver/i2s.h>
#include "esphome/components/media_player/media_player.h"
#include "esphome/core/component.h"
#include "esphome/core/gpio.h"
@@ -12,7 +16,14 @@
namespace esphome {
namespace i2s_audio {
class I2SAudioMediaPlayer : public Component, public media_player::MediaPlayer {
enum I2SState : uint8_t {
I2S_STATE_STOPPED = 0,
I2S_STATE_STARTING,
I2S_STATE_RUNNING,
I2S_STATE_STOPPING,
};
class I2SAudioMediaPlayer : public Component, public media_player::MediaPlayer, public I2SAudioOut {
public:
void setup() override;
float get_setup_priority() const override { return esphome::setup_priority::LATE; }
@@ -22,8 +33,6 @@ class I2SAudioMediaPlayer : public Component, public media_player::MediaPlayer {
void dump_config() override;
void set_dout_pin(uint8_t pin) { this->dout_pin_ = pin; }
void set_bclk_pin(uint8_t pin) { this->bclk_pin_ = pin; }
void set_lrclk_pin(uint8_t pin) { this->lrclk_pin_ = pin; }
void set_mute_pin(GPIOPin *mute_pin) { this->mute_pin_ = mute_pin; }
#if SOC_I2S_SUPPORTS_DAC
void set_internal_dac_mode(i2s_dac_mode_t mode) { this->internal_dac_mode_ = mode; }
@@ -34,20 +43,24 @@ class I2SAudioMediaPlayer : public Component, public media_player::MediaPlayer {
bool is_muted() const override { return this->muted_; }
void start();
void stop();
protected:
void control(const media_player::MediaPlayerCall &call) override;
void mute_();
void unmute_();
void set_volume_(float volume, bool publish = true);
void stop_();
void start_();
void stop_();
void play_();
I2SState i2s_state_{I2S_STATE_STOPPED};
std::unique_ptr<Audio> audio_;
uint8_t dout_pin_{0};
uint8_t din_pin_{0};
uint8_t bclk_pin_;
uint8_t lrclk_pin_;
GPIOPin *mute_pin_{nullptr};
bool muted_{false};
@@ -59,6 +72,8 @@ class I2SAudioMediaPlayer : public Component, public media_player::MediaPlayer {
uint8_t external_dac_channels_;
HighFrequencyLoopRequester high_freq_;
optional<std::string> current_url_{};
};
} // namespace i2s_audio

View File

@@ -0,0 +1,41 @@
import esphome.config_validation as cv
import esphome.codegen as cg
from esphome import pins
from esphome.const import CONF_ID
from esphome.components import microphone
from .. import (
i2s_audio_ns,
I2SAudioComponent,
I2SAudioIn,
CONF_I2S_AUDIO_ID,
CONF_I2S_DIN_PIN,
)
CODEOWNERS = ["@jesserockz"]
DEPENDENCIES = ["i2s_audio"]
I2SAudioMicrophone = i2s_audio_ns.class_(
"I2SAudioMicrophone", I2SAudioIn, microphone.Microphone, cg.Component
)
CONFIG_SCHEMA = microphone.MICROPHONE_SCHEMA.extend(
{
cv.GenerateID(): cv.declare_id(I2SAudioMicrophone),
cv.GenerateID(CONF_I2S_AUDIO_ID): cv.use_id(I2SAudioComponent),
cv.Required(CONF_I2S_DIN_PIN): pins.internal_gpio_input_pin_number,
}
).extend(cv.COMPONENT_SCHEMA)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
parent = await cg.get_variable(config[CONF_I2S_AUDIO_ID])
cg.add(parent.register_audio_in(var))
cg.add(var.set_din_pin(config[CONF_I2S_DIN_PIN]))
await microphone.register_microphone(var, config)

View File

@@ -0,0 +1,101 @@
#include "i2s_audio_microphone.h"
#ifdef USE_ESP32
#include <driver/i2s.h>
#include "esphome/core/hal.h"
#include "esphome/core/log.h"
namespace esphome {
namespace i2s_audio {
static const size_t BUFFER_SIZE = 512;
static const char *const TAG = "i2s_audio.microphone";
void I2SAudioMicrophone::setup() {
ESP_LOGCONFIG(TAG, "Setting up I2S Audio Microphone...");
this->buffer_.resize(BUFFER_SIZE);
}
void I2SAudioMicrophone::start() { this->state_ = microphone::STATE_STARTING; }
void I2SAudioMicrophone::start_() {
if (!this->parent_->try_lock()) {
return; // Waiting for another i2s to return lock
}
i2s_driver_config_t config = {
.mode = (i2s_mode_t) (I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM),
.sample_rate = 16000,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT,
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 4,
.dma_buf_len = 256,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0,
.mclk_multiple = I2S_MCLK_MULTIPLE_DEFAULT,
.bits_per_chan = I2S_BITS_PER_CHAN_DEFAULT,
};
i2s_driver_install(this->parent_->get_port(), &config, 0, nullptr);
i2s_pin_config_t pin_config = this->parent_->get_pin_config();
pin_config.data_in_num = this->din_pin_;
i2s_set_pin(this->parent_->get_port(), &pin_config);
this->state_ = microphone::STATE_RUNNING;
this->high_freq_.start();
}
void I2SAudioMicrophone::stop() {
if (this->state_ == microphone::STATE_STOPPED)
return;
this->state_ = microphone::STATE_STOPPING;
}
void I2SAudioMicrophone::stop_() {
i2s_stop(this->parent_->get_port());
i2s_driver_uninstall(this->parent_->get_port());
this->parent_->unlock();
this->state_ = microphone::STATE_STOPPED;
this->high_freq_.stop();
}
void I2SAudioMicrophone::read_() {
size_t bytes_read = 0;
esp_err_t err =
i2s_read(this->parent_->get_port(), this->buffer_.data(), BUFFER_SIZE, &bytes_read, (100 / portTICK_PERIOD_MS));
if (err != ESP_OK) {
ESP_LOGW(TAG, "Error reading from I2S microphone: %s", esp_err_to_name(err));
this->status_set_warning();
return;
}
this->status_clear_warning();
this->data_callbacks_.call(this->buffer_);
}
void I2SAudioMicrophone::loop() {
switch (this->state_) {
case microphone::STATE_STOPPED:
break;
case microphone::STATE_STARTING:
this->start_();
break;
case microphone::STATE_RUNNING:
this->read_();
break;
case microphone::STATE_STOPPING:
this->stop_();
break;
}
}
} // namespace i2s_audio
} // namespace esphome
#endif // USE_ESP32

View File

@@ -0,0 +1,37 @@
#pragma once
#ifdef USE_ESP32
#include "../i2s_audio.h"
#include "esphome/components/microphone/microphone.h"
#include "esphome/core/component.h"
namespace esphome {
namespace i2s_audio {
class I2SAudioMicrophone : public I2SAudioIn, public microphone::Microphone, public Component {
public:
void setup() override;
void start() override;
void stop() override;
void loop() override;
void set_din_pin(uint8_t pin) { this->din_pin_ = pin; }
protected:
void start_();
void stop_();
void read_();
uint8_t din_pin_{0};
std::vector<uint8_t> buffer_;
HighFrequencyLoopRequester high_freq_;
};
} // namespace i2s_audio
} // namespace esphome
#endif // USE_ESP32

View File

@@ -21,7 +21,7 @@ std::string ImprovBase::get_formatted_next_url_() {
// Ip address
pos = this->next_url_.find("{{ip_address}}");
if (pos != std::string::npos) {
std::string ip = network::IPAddress(network::get_ip_address()).str();
std::string ip = network::get_ip_address().str();
copy.replace(pos, 14, ip);
}

View File

@@ -60,7 +60,7 @@ LIGHT_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).ex
{
cv.GenerateID(): cv.declare_id(LightState),
cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTJSONLightComponent),
cv.Optional(CONF_RESTORE_MODE, default="restore_default_off"): cv.enum(
cv.Optional(CONF_RESTORE_MODE, default="ALWAYS_OFF"): cv.enum(
RESTORE_MODES, upper=True, space="_"
),
cv.Optional(CONF_ON_TURN_ON): auto.validate_automation(

View File

@@ -8,7 +8,6 @@ namespace light {
static const char *const TAG = "light";
LightState::LightState(const std::string &name, LightOutput *output) : EntityBase(name), output_(output) {}
LightState::LightState(LightOutput *output) : output_(output) {}
LightTraits LightState::get_traits() { return this->output_->get_traits(); }

View File

@@ -33,9 +33,6 @@ enum LightRestoreMode {
*/
class LightState : public EntityBase, public Component {
public:
/// Construct this LightState using the provided traits and name.
LightState(const std::string &name, LightOutput *output);
LightState(LightOutput *output);
LightTraits get_traits();

View File

@@ -24,8 +24,7 @@ const char *lock_state_to_string(LockState state) {
}
}
Lock::Lock(const std::string &name) : EntityBase(name), state(LOCK_STATE_NONE) {}
Lock::Lock() : Lock("") {}
Lock::Lock() : state(LOCK_STATE_NONE) {}
LockCall Lock::make_call() { return LockCall(this); }
void Lock::lock() {

View File

@@ -103,7 +103,6 @@ class LockCall {
class Lock : public EntityBase {
public:
explicit Lock();
explicit Lock(const std::string &name);
/** Make a lock device control call, this is used to control the lock device, see the LockCall description
* for more info.

View File

@@ -1,4 +1,5 @@
#include "logger.h"
#include <cinttypes>
#ifdef USE_ESP_IDF
#include <driver/uart.h>
@@ -292,7 +293,7 @@ const char *const UART_SELECTIONS[] = {"UART0", "UART1", "USB_CDC"};
void Logger::dump_config() {
ESP_LOGCONFIG(TAG, "Logger:");
ESP_LOGCONFIG(TAG, " Level: %s", LOG_LEVELS[ESPHOME_LOG_LEVEL]);
ESP_LOGCONFIG(TAG, " Log Baud Rate: %u", this->baud_rate_);
ESP_LOGCONFIG(TAG, " Log Baud Rate: %" PRIu32, this->baud_rate_);
ESP_LOGCONFIG(TAG, " Hardware UART: %s", UART_SELECTIONS[this->uart_]);
for (auto &it : this->log_levels_) {
ESP_LOGCONFIG(TAG, " Level for '%s': %s", it.tag.c_str(), LOG_LEVELS[it.level]);

View File

@@ -93,7 +93,7 @@ async def to_code(config):
cg.add(var.set_scroll(config[CONF_SCROLL_ENABLE]))
cg.add(var.set_scroll_mode(config[CONF_SCROLL_MODE]))
cg.add(var.set_reverse(config[CONF_REVERSE_ENABLE]))
cg.add(var.set_flip_x([CONF_FLIP_X]))
cg.add(var.set_flip_x(config[CONF_FLIP_X]))
if CONF_LAMBDA in config:
lambda_ = await cg.process_lambda(

View File

@@ -0,0 +1,91 @@
from esphome import automation
import esphome.config_validation as cv
import esphome.codegen as cg
from esphome.automation import maybe_simple_id
from esphome.const import CONF_ID, CONF_TRIGGER_ID
from esphome.core import CORE
from esphome.coroutine import coroutine_with_priority
CODEOWNERS = ["@jesserockz"]
IS_PLATFORM_COMPONENT = True
CONF_ON_DATA = "on_data"
microphone_ns = cg.esphome_ns.namespace("microphone")
Microphone = microphone_ns.class_("Microphone")
CaptureAction = microphone_ns.class_(
"CaptureAction", automation.Action, cg.Parented.template(Microphone)
)
StopCaptureAction = microphone_ns.class_(
"StopCaptureAction", automation.Action, cg.Parented.template(Microphone)
)
DataTrigger = microphone_ns.class_(
"DataTrigger",
automation.Trigger.template(cg.std_vector.template(cg.int16).operator("ref")),
)
IsCapturingCondition = microphone_ns.class_(
"IsCapturingCondition", automation.Condition
)
async def setup_microphone_core_(var, config):
for conf in config.get(CONF_ON_DATA, []):
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
await automation.build_automation(
trigger,
[(cg.std_vector.template(cg.uint8).operator("ref").operator("const"), "x")],
conf,
)
async def register_microphone(var, config):
if not CORE.has_id(config[CONF_ID]):
var = cg.Pvariable(config[CONF_ID], var)
await setup_microphone_core_(var, config)
MICROPHONE_SCHEMA = cv.Schema(
{
cv.Optional(CONF_ON_DATA): automation.validate_automation(
{
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DataTrigger),
}
),
}
)
MICROPHONE_ACTION_SCHEMA = maybe_simple_id({cv.GenerateID(): cv.use_id(Microphone)})
async def media_player_action(config, action_id, template_arg, args):
var = cg.new_Pvariable(action_id, template_arg)
await cg.register_parented(var, config[CONF_ID])
return var
automation.register_action(
"microphone.capture", CaptureAction, MICROPHONE_ACTION_SCHEMA
)(media_player_action)
automation.register_action(
"microphone.stop_capture", StopCaptureAction, MICROPHONE_ACTION_SCHEMA
)(media_player_action)
automation.register_condition(
"microphone.is_capturing", IsCapturingCondition, MICROPHONE_ACTION_SCHEMA
)(media_player_action)
@coroutine_with_priority(100.0)
async def to_code(config):
cg.add_global(microphone_ns.using)
cg.add_define("USE_MICROPHONE")

View File

@@ -0,0 +1,32 @@
#pragma once
#include "esphome/core/automation.h"
#include "microphone.h"
#include <vector>
namespace esphome {
namespace microphone {
template<typename... Ts> class CaptureAction : public Action<Ts...>, public Parented<Microphone> {
void play(Ts... x) override { this->parent_->start(); }
};
template<typename... Ts> class StopCaptureAction : public Action<Ts...>, public Parented<Microphone> {
void play(Ts... x) override { this->parent_->stop(); }
};
class DataTrigger : public Trigger<const std::vector<uint8_t> &> {
public:
explicit DataTrigger(Microphone *mic) {
mic->add_data_callback([this](const std::vector<uint8_t> &data) { this->trigger(data); });
}
};
template<typename... Ts> class IsCapturingActon : public Condition<Ts...>, public Parented<Microphone> {
public:
bool check(Ts... x) override { return this->parent_->is_running(); }
};
} // namespace microphone
} // namespace esphome

View File

@@ -0,0 +1,33 @@
#pragma once
#include "esphome/core/entity_base.h"
#include "esphome/core/helpers.h"
namespace esphome {
namespace microphone {
enum State : uint8_t {
STATE_STOPPED = 0,
STATE_STARTING,
STATE_RUNNING,
STATE_STOPPING,
};
class Microphone {
public:
virtual void start() = 0;
virtual void stop() = 0;
void add_data_callback(std::function<void(const std::vector<uint8_t> &)> &&data_callback) {
this->data_callbacks_.add(std::move(data_callback));
}
bool is_running() const { return this->state_ == STATE_RUNNING; }
protected:
State state_{STATE_STOPPED};
CallbackManager<void(const std::vector<uint8_t> &)> data_callbacks_{};
};
} // namespace microphone
} // namespace esphome

View File

@@ -0,0 +1 @@
CODEOWNERS = ["@benhoff"]

View File

@@ -0,0 +1,162 @@
#include "mmc5603.h"
#include "esphome/core/log.h"
namespace esphome {
namespace mmc5603 {
static const char *const TAG = "mmc5603";
static const uint8_t MMC5603_ADDRESS = 0x30;
static const uint8_t MMC56X3_PRODUCT_ID = 0x39;
static const uint8_t MMC56X3_DEFAULT_ADDRESS = 0x30;
static const uint8_t MMC56X3_CHIP_ID = 0x10;
static const uint8_t MMC56X3_ADDR_XOUT0 = 0x00;
static const uint8_t MMC56X3_ADDR_XOUT1 = 0x01;
static const uint8_t MMC56X3_ADDR_XOUT2 = 0x06;
static const uint8_t MMC56X3_ADDR_YOUT0 = 0x02;
static const uint8_t MMC56X3_ADDR_YOUT1 = 0x03;
static const uint8_t MMC56X3_ADDR_YOUT2 = 0x07;
static const uint8_t MMC56X3_ADDR_ZOUT0 = 0x04;
static const uint8_t MMC56X3_ADDR_ZOUT1 = 0x05;
static const uint8_t MMC56X3_ADDR_ZOUT2 = 0x08;
static const uint8_t MMC56X3_OUT_TEMP = 0x09;
static const uint8_t MMC56X3_STATUS_REG = 0x18;
static const uint8_t MMC56X3_CTRL0_REG = 0x1B;
static const uint8_t MMC56X3_CTRL1_REG = 0x1C;
static const uint8_t MMC56X3_CTRL2_REG = 0x1D;
static const uint8_t MMC5603_ODR_REG = 0x1A;
void MMC5603Component::setup() {
ESP_LOGCONFIG(TAG, "Setting up MMC5603...");
uint8_t id = 0;
if (!this->read_byte(MMC56X3_PRODUCT_ID, &id)) {
this->error_code_ = COMMUNICATION_FAILED;
this->mark_failed();
return;
}
if (id != MMC56X3_CHIP_ID) {
ESP_LOGCONFIG(TAG, "Chip Wrong");
this->error_code_ = ID_REGISTERS;
this->mark_failed();
return;
}
if (!this->write_byte(MMC56X3_CTRL1_REG, 0x80)) { // turn on set bit
ESP_LOGCONFIG(TAG, "Control 1 Failed for set bit");
this->error_code_ = COMMUNICATION_FAILED;
this->mark_failed();
return;
}
if (!this->write_byte(MMC56X3_CTRL0_REG, 0x08)) { // turn on set bit
ESP_LOGCONFIG(TAG, "Control 0 Failed for set bit");
this->error_code_ = COMMUNICATION_FAILED;
this->mark_failed();
return;
}
if (!this->write_byte(MMC56X3_CTRL0_REG, 0x10)) {
this->error_code_ = COMMUNICATION_FAILED;
this->mark_failed();
return;
}
uint8_t ctrl_2 = 0;
ctrl_2 &= ~0x10; // turn off cmm_en bit
if (!this->write_byte(MMC56X3_CTRL2_REG, ctrl_2)) {
this->error_code_ = COMMUNICATION_FAILED;
this->mark_failed();
return;
}
}
void MMC5603Component::dump_config() {
ESP_LOGCONFIG(TAG, "MMC5603:");
LOG_I2C_DEVICE(this);
if (this->error_code_ == COMMUNICATION_FAILED) {
ESP_LOGE(TAG, "Communication with MMC5603 failed!");
} else if (this->error_code_ == ID_REGISTERS) {
ESP_LOGE(TAG, "The ID registers don't match - Is this really an MMC5603?");
}
LOG_UPDATE_INTERVAL(this);
LOG_SENSOR(" ", "X Axis", this->x_sensor_);
LOG_SENSOR(" ", "Y Axis", this->y_sensor_);
LOG_SENSOR(" ", "Z Axis", this->z_sensor_);
LOG_SENSOR(" ", "Heading", this->heading_sensor_);
}
float MMC5603Component::get_setup_priority() const { return setup_priority::DATA; }
void MMC5603Component::update() {
if (!this->write_byte(MMC56X3_CTRL0_REG, 0x01)) {
this->status_set_warning();
return;
}
uint8_t status = 0;
if (!this->read_byte(MMC56X3_STATUS_REG, &status)) {
this->status_set_warning();
return;
}
uint8_t buffer[9] = {0};
if (!this->read_byte(MMC56X3_ADDR_XOUT0, &buffer[0]) || !this->read_byte(MMC56X3_ADDR_XOUT1, &buffer[1]) ||
!this->read_byte(MMC56X3_ADDR_XOUT2, &buffer[2])) {
this->status_set_warning();
return;
}
if (!this->read_byte(MMC56X3_ADDR_YOUT0, &buffer[3]) || !this->read_byte(MMC56X3_ADDR_YOUT1, &buffer[4]) ||
!this->read_byte(MMC56X3_ADDR_YOUT2, &buffer[5])) {
this->status_set_warning();
return;
}
if (!this->read_byte(MMC56X3_ADDR_ZOUT0, &buffer[6]) || !this->read_byte(MMC56X3_ADDR_ZOUT1, &buffer[7]) ||
!this->read_byte(MMC56X3_ADDR_ZOUT2, &buffer[8])) {
this->status_set_warning();
return;
}
int32_t raw_x = 0;
raw_x |= buffer[0] << 12;
raw_x |= buffer[1] << 4;
raw_x |= buffer[2] << 0;
const float x = 0.0625 * (raw_x - 524288);
int32_t raw_y = 0;
raw_y |= buffer[3] << 12;
raw_y |= buffer[4] << 4;
raw_y |= buffer[5] << 0;
const float y = 0.0625 * (raw_y - 524288);
int32_t raw_z = 0;
raw_z |= buffer[6] << 12;
raw_z |= buffer[7] << 4;
raw_z |= buffer[8] << 0;
const float z = 0.0625 * (raw_z - 524288);
const float heading = atan2f(0.0f - x, y) * 180.0f / M_PI;
ESP_LOGD(TAG, "Got x=%0.02fµT y=%0.02fµT z=%0.02fµT heading=%0.01f°", x, y, z, heading);
if (this->x_sensor_ != nullptr)
this->x_sensor_->publish_state(x);
if (this->y_sensor_ != nullptr)
this->y_sensor_->publish_state(y);
if (this->z_sensor_ != nullptr)
this->z_sensor_->publish_state(z);
if (this->heading_sensor_ != nullptr)
this->heading_sensor_->publish_state(heading);
}
} // namespace mmc5603
} // namespace esphome

View File

@@ -0,0 +1,43 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/i2c/i2c.h"
namespace esphome {
namespace mmc5603 {
enum MMC5603Datarate {
MMC5603_DATARATE_75_0_HZ,
MMC5603_DATARATE_150_0_HZ,
MMC5603_DATARATE_255_0_HZ,
};
class MMC5603Component : public PollingComponent, public i2c::I2CDevice {
public:
void setup() override;
void dump_config() override;
float get_setup_priority() const override;
void update() override;
void set_datarate(MMC5603Datarate datarate) { datarate_ = datarate; }
void set_x_sensor(sensor::Sensor *x_sensor) { x_sensor_ = x_sensor; }
void set_y_sensor(sensor::Sensor *y_sensor) { y_sensor_ = y_sensor; }
void set_z_sensor(sensor::Sensor *z_sensor) { z_sensor_ = z_sensor; }
void set_heading_sensor(sensor::Sensor *heading_sensor) { heading_sensor_ = heading_sensor; }
protected:
MMC5603Datarate datarate_;
sensor::Sensor *x_sensor_{nullptr};
sensor::Sensor *y_sensor_{nullptr};
sensor::Sensor *z_sensor_{nullptr};
sensor::Sensor *heading_sensor_{nullptr};
enum ErrorCode {
NONE = 0,
COMMUNICATION_FAILED,
ID_REGISTERS,
} error_code_;
};
} // namespace mmc5603
} // namespace esphome

View File

@@ -0,0 +1,91 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import i2c, sensor
from esphome.const import (
CONF_ADDRESS,
CONF_ID,
ICON_MAGNET,
STATE_CLASS_MEASUREMENT,
UNIT_MICROTESLA,
UNIT_DEGREES,
ICON_SCREEN_ROTATION,
CONF_UPDATE_INTERVAL,
)
DEPENDENCIES = ["i2c"]
mmc5603_ns = cg.esphome_ns.namespace("mmc5603")
CONF_FIELD_STRENGTH_X = "field_strength_x"
CONF_FIELD_STRENGTH_Y = "field_strength_y"
CONF_FIELD_STRENGTH_Z = "field_strength_z"
CONF_HEADING = "heading"
MMC5603Component = mmc5603_ns.class_(
"MMC5603Component", cg.PollingComponent, i2c.I2CDevice
)
MMC5603Datarate = mmc5603_ns.enum("MMC5603Datarate")
MMC5603Datarates = {
75: MMC5603Datarate.MMC5603_DATARATE_75_0_HZ,
150: MMC5603Datarate.MMC5603_DATARATE_150_0_HZ,
255: MMC5603Datarate.MMC5603_DATARATE_255_0_HZ,
}
field_strength_schema = sensor.sensor_schema(
unit_of_measurement=UNIT_MICROTESLA,
icon=ICON_MAGNET,
accuracy_decimals=1,
state_class=STATE_CLASS_MEASUREMENT,
)
heading_schema = sensor.sensor_schema(
unit_of_measurement=UNIT_DEGREES,
icon=ICON_SCREEN_ROTATION,
accuracy_decimals=1,
)
CONFIG_SCHEMA = (
cv.Schema(
{
cv.GenerateID(): cv.declare_id(MMC5603Component),
cv.Optional(CONF_ADDRESS): cv.i2c_address,
cv.Optional(CONF_FIELD_STRENGTH_X): field_strength_schema,
cv.Optional(CONF_FIELD_STRENGTH_Y): field_strength_schema,
cv.Optional(CONF_FIELD_STRENGTH_Z): field_strength_schema,
cv.Optional(CONF_HEADING): heading_schema,
}
)
.extend(cv.polling_component_schema("60s"))
.extend(i2c.i2c_device_schema(0x1E))
)
def auto_data_rate(config):
interval_msec = config[CONF_UPDATE_INTERVAL].total_milliseconds
interval_hz = 1000.0 / interval_msec
for datarate in sorted(MMC5603Datarates.keys()):
if float(datarate) >= interval_hz:
return MMC5603Datarates[datarate]
return MMC5603Datarates[75]
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
await i2c.register_i2c_device(var, config)
cg.add(var.set_datarate(auto_data_rate(config)))
if CONF_FIELD_STRENGTH_X in config:
sens = await sensor.new_sensor(config[CONF_FIELD_STRENGTH_X])
cg.add(var.set_x_sensor(sens))
if CONF_FIELD_STRENGTH_Y in config:
sens = await sensor.new_sensor(config[CONF_FIELD_STRENGTH_Y])
cg.add(var.set_y_sensor(sens))
if CONF_FIELD_STRENGTH_Z in config:
sens = await sensor.new_sensor(config[CONF_FIELD_STRENGTH_Z])
cg.add(var.set_z_sensor(sens))
if CONF_HEADING in config:
sens = await sensor.new_sensor(config[CONF_HEADING])
cg.add(var.set_heading_sensor(sens))

View File

@@ -44,6 +44,11 @@ NdefMessage::NdefMessage(std::vector<uint8_t> &data) {
index += id_length;
}
if ((data.begin() + index > data.end()) || (data.begin() + index + payload_length > data.end())) {
ESP_LOGE(TAG, "Corrupt record encountered; NdefMessage constructor aborting");
break;
}
std::vector<uint8_t> payload_data(data.begin() + index, data.begin() + index + payload_length);
std::unique_ptr<NdefRecord> record;

View File

@@ -42,8 +42,8 @@ class NdefRecord {
virtual const std::string &get_payload() const { return this->payload_; };
virtual std::vector<uint8_t> get_encoded_payload() {
std::vector<uint8_t> empty_payload;
return empty_payload;
std::vector<uint8_t> payload(this->payload_.begin(), this->payload_.end());
return payload;
};
protected:

View File

@@ -89,18 +89,18 @@ uint32_t get_mifare_classic_buffer_size(uint32_t message_length) {
}
bool mifare_classic_is_first_block(uint8_t block_num) {
if (block_num < 128) {
return (block_num % 4 == 0);
if (block_num < MIFARE_CLASSIC_BLOCKS_PER_SECT_LOW * MIFARE_CLASSIC_16BLOCK_SECT_START) {
return (block_num % MIFARE_CLASSIC_BLOCKS_PER_SECT_LOW == 0);
} else {
return (block_num % 16 == 0);
return (block_num % MIFARE_CLASSIC_BLOCKS_PER_SECT_HIGH == 0);
}
}
bool mifare_classic_is_trailer_block(uint8_t block_num) {
if (block_num < 128) {
return ((block_num + 1) % 4 == 0);
if (block_num < MIFARE_CLASSIC_BLOCKS_PER_SECT_LOW * MIFARE_CLASSIC_16BLOCK_SECT_START) {
return ((block_num + 1) % MIFARE_CLASSIC_BLOCKS_PER_SECT_LOW == 0);
} else {
return ((block_num + 1) % 16 == 0);
return ((block_num + 1) % MIFARE_CLASSIC_BLOCKS_PER_SECT_HIGH == 0);
}
}

View File

@@ -14,6 +14,9 @@ namespace nfc {
static const uint8_t MIFARE_CLASSIC_BLOCK_SIZE = 16;
static const uint8_t MIFARE_CLASSIC_LONG_TLV_SIZE = 4;
static const uint8_t MIFARE_CLASSIC_SHORT_TLV_SIZE = 2;
static const uint8_t MIFARE_CLASSIC_BLOCKS_PER_SECT_LOW = 4;
static const uint8_t MIFARE_CLASSIC_BLOCKS_PER_SECT_HIGH = 16;
static const uint8_t MIFARE_CLASSIC_16BLOCK_SECT_START = 32;
static const uint8_t MIFARE_ULTRALIGHT_PAGE_SIZE = 4;
static const uint8_t MIFARE_ULTRALIGHT_READ_SIZE = 4;
@@ -30,10 +33,18 @@ static const uint8_t TAG_TYPE_UNKNOWN = 99;
// Mifare Commands
static const uint8_t MIFARE_CMD_AUTH_A = 0x60;
static const uint8_t MIFARE_CMD_AUTH_B = 0x61;
static const uint8_t MIFARE_CMD_HALT = 0x50;
static const uint8_t MIFARE_CMD_READ = 0x30;
static const uint8_t MIFARE_CMD_WRITE = 0xA0;
static const uint8_t MIFARE_CMD_WRITE_ULTRALIGHT = 0xA2;
// Mifare Ack/Nak
static const uint8_t MIFARE_CMD_ACK = 0x0A;
static const uint8_t MIFARE_CMD_NAK_INVALID_XFER_BUFF_VALID = 0x00;
static const uint8_t MIFARE_CMD_NAK_CRC_ERROR_XFER_BUFF_VALID = 0x01;
static const uint8_t MIFARE_CMD_NAK_INVALID_XFER_BUFF_INVALID = 0x04;
static const uint8_t MIFARE_CMD_NAK_CRC_ERROR_XFER_BUFF_INVALID = 0x05;
static const char *const MIFARE_CLASSIC = "Mifare Classic";
static const char *const NFC_FORUM_TYPE_2 = "NFC Forum Type 2";
static const char *const ERROR = "Error";

View File

@@ -1,4 +1,3 @@
from typing import Optional
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome import automation
@@ -31,6 +30,7 @@ from esphome.const import (
DEVICE_CLASS_DISTANCE,
DEVICE_CLASS_EMPTY,
DEVICE_CLASS_ENERGY,
DEVICE_CLASS_ENERGY_STORAGE,
DEVICE_CLASS_FREQUENCY,
DEVICE_CLASS_GAS,
DEVICE_CLASS_HUMIDITY,
@@ -59,6 +59,7 @@ from esphome.const import (
DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS,
DEVICE_CLASS_VOLTAGE,
DEVICE_CLASS_VOLUME,
DEVICE_CLASS_VOLUME_STORAGE,
DEVICE_CLASS_WATER,
DEVICE_CLASS_WEIGHT,
DEVICE_CLASS_WIND_SPEED,
@@ -81,6 +82,7 @@ DEVICE_CLASSES = [
DEVICE_CLASS_DISTANCE,
DEVICE_CLASS_EMPTY,
DEVICE_CLASS_ENERGY,
DEVICE_CLASS_ENERGY_STORAGE,
DEVICE_CLASS_FREQUENCY,
DEVICE_CLASS_GAS,
DEVICE_CLASS_HUMIDITY,
@@ -109,6 +111,7 @@ DEVICE_CLASSES = [
DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS,
DEVICE_CLASS_VOLTAGE,
DEVICE_CLASS_VOLUME,
DEVICE_CLASS_VOLUME_STORAGE,
DEVICE_CLASS_WATER,
DEVICE_CLASS_WEIGHT,
DEVICE_CLASS_WIND_SPEED,
@@ -248,9 +251,7 @@ async def register_number(
)
async def new_number(
config, *, min_value: float, max_value: float, step: Optional[float] = None
):
async def new_number(config, *, min_value: float, max_value: float, step: float):
var = cg.new_Pvariable(config[CONF_ID])
await register_number(
var, config, min_value=min_value, max_value=max_value, step=step

View File

@@ -102,7 +102,7 @@ async def to_code(config):
conf[CONF_ADDRESSABLE_LIGHT_ID],
await cg.get_variable(conf[CONF_SINGLE_LIGHT_ID]),
)
light_state = cg.new_Pvariable(conf[CONF_LIGHT_ID], "", wrapper)
light_state = cg.new_Pvariable(conf[CONF_LIGHT_ID], wrapper)
await cg.register_component(light_state, conf)
segments.append(AddressableSegment(light_state, 0, 1, False))

View File

@@ -19,9 +19,12 @@ void PN532::setup() {
// Get version data
if (!this->write_command_({PN532_COMMAND_VERSION_DATA})) {
ESP_LOGE(TAG, "Error sending version command");
this->mark_failed();
return;
ESP_LOGW(TAG, "Error sending version command, trying again...");
if (!this->write_command_({PN532_COMMAND_VERSION_DATA})) {
ESP_LOGE(TAG, "Error sending version command");
this->mark_failed();
return;
}
}
std::vector<uint8_t> version_data;

View File

@@ -52,7 +52,13 @@ std::unique_ptr<nfc::NfcTag> PN532::read_mifare_classic_tag_(std::vector<uint8_t
current_block++;
}
}
buffer.erase(buffer.begin(), buffer.begin() + message_start_index);
if (buffer.begin() + message_start_index < buffer.end()) {
buffer.erase(buffer.begin(), buffer.begin() + message_start_index);
} else {
return make_unique<nfc::NfcTag>(uid, nfc::MIFARE_CLASSIC);
}
return make_unique<nfc::NfcTag>(uid, nfc::MIFARE_CLASSIC, buffer);
}

View File

@@ -86,7 +86,7 @@ void SenseAirComponent::background_calibration_result() {
}
// Check if 5th bit (register CI6) is set
ESP_LOGD(TAG, "SenseAir Result=%s (%02x%02x%02x %02x%02x %02x%02x)", (response[4] & 0b100000) != 0 ? "OK" : "NOT_OK",
ESP_LOGI(TAG, "SenseAir Result=%s (%02x%02x%02x %02x%02x %02x%02x)", (response[4] & 0b100000) != 0 ? "OK" : "NOT_OK",
response[0], response[1], response[2], response[3], response[4], response[5], response[6]);
}

View File

@@ -25,10 +25,12 @@ from esphome.const import (
CONF_STATE_CLASS,
CONF_TO,
CONF_TRIGGER_ID,
CONF_TYPE,
CONF_UNIT_OF_MEASUREMENT,
CONF_WINDOW_SIZE,
CONF_MQTT_ID,
CONF_FORCE_UPDATE,
CONF_VALUE,
DEVICE_CLASS_APPARENT_POWER,
DEVICE_CLASS_AQI,
DEVICE_CLASS_ATMOSPHERIC_PRESSURE,
@@ -43,6 +45,7 @@ from esphome.const import (
DEVICE_CLASS_DURATION,
DEVICE_CLASS_EMPTY,
DEVICE_CLASS_ENERGY,
DEVICE_CLASS_ENERGY_STORAGE,
DEVICE_CLASS_FREQUENCY,
DEVICE_CLASS_GAS,
DEVICE_CLASS_HUMIDITY,
@@ -72,6 +75,7 @@ from esphome.const import (
DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS,
DEVICE_CLASS_VOLTAGE,
DEVICE_CLASS_VOLUME,
DEVICE_CLASS_VOLUME_STORAGE,
DEVICE_CLASS_WATER,
DEVICE_CLASS_WEIGHT,
DEVICE_CLASS_WIND_SPEED,
@@ -97,6 +101,7 @@ DEVICE_CLASSES = [
DEVICE_CLASS_DURATION,
DEVICE_CLASS_EMPTY,
DEVICE_CLASS_ENERGY,
DEVICE_CLASS_ENERGY_STORAGE,
DEVICE_CLASS_FREQUENCY,
DEVICE_CLASS_GAS,
DEVICE_CLASS_HUMIDITY,
@@ -126,6 +131,7 @@ DEVICE_CLASSES = [
DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS,
DEVICE_CLASS_VOLTAGE,
DEVICE_CLASS_VOLUME,
DEVICE_CLASS_VOLUME_STORAGE,
DEVICE_CLASS_WATER,
DEVICE_CLASS_WEIGHT,
DEVICE_CLASS_WIND_SPEED,
@@ -472,21 +478,38 @@ async def lambda_filter_to_code(config, filter_id):
return cg.new_Pvariable(filter_id, lambda_)
DELTA_SCHEMA = cv.Schema(
{
cv.Required(CONF_VALUE): cv.positive_float,
cv.Optional(CONF_TYPE, default="absolute"): cv.one_of(
"absolute", "percentage", lower=True
),
}
)
def validate_delta(config):
try:
return (cv.positive_float(config), False)
value = cv.positive_float(config)
return DELTA_SCHEMA({CONF_VALUE: value, CONF_TYPE: "absolute"})
except cv.Invalid:
pass
try:
return (cv.percentage(config), True)
value = cv.percentage(config)
return DELTA_SCHEMA({CONF_VALUE: value, CONF_TYPE: "percentage"})
except cv.Invalid:
pass
raise cv.Invalid("Delta filter requires a positive number or percentage value.")
@FILTER_REGISTRY.register("delta", DeltaFilter, validate_delta)
@FILTER_REGISTRY.register("delta", DeltaFilter, cv.Any(DELTA_SCHEMA, validate_delta))
async def delta_filter_to_code(config, filter_id):
return cg.new_Pvariable(filter_id, *config)
percentage = config[CONF_TYPE] == "percentage"
return cg.new_Pvariable(
filter_id,
config[CONF_VALUE],
percentage,
)
@FILTER_REGISTRY.register("or", OrFilter, validate_filters)

View File

@@ -20,8 +20,7 @@ std::string state_class_to_string(StateClass state_class) {
}
}
Sensor::Sensor(const std::string &name) : EntityBase(name), state(NAN), raw_state(NAN) {}
Sensor::Sensor() : Sensor("") {}
Sensor::Sensor() : state(NAN), raw_state(NAN) {}
std::string Sensor::get_unit_of_measurement() {
if (this->unit_of_measurement_.has_value())

View File

@@ -57,7 +57,6 @@ std::string state_class_to_string(StateClass state_class);
class Sensor : public EntityBase {
public:
explicit Sensor();
explicit Sensor(const std::string &name);
/// Get the unit of measurement, using the manual override if set.
std::string get_unit_of_measurement();
@@ -162,7 +161,6 @@ class Sensor : public EntityBase {
CallbackManager<void(float)> raw_callback_; ///< Storage for raw state callbacks.
CallbackManager<void(float)> callback_; ///< Storage for filtered state callbacks.
bool has_state_{false};
Filter *filter_list_{nullptr}; ///< Store all active filters.
optional<std::string> unit_of_measurement_; ///< Unit of measurement override
@@ -170,6 +168,7 @@ class Sensor : public EntityBase {
optional<std::string> device_class_; ///< Device class override
optional<StateClass> state_class_{STATE_CLASS_NONE}; ///< State class override
bool force_update_{false}; ///< Force update mode
bool has_state_{false};
};
} // namespace sensor

View File

@@ -139,6 +139,11 @@ class BSDSocketImpl : public Socket {
return ::writev(fd_, iov, iovcnt);
#endif
}
ssize_t sendto(const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) override {
return ::sendto(fd_, buf, len, flags, to, tolen);
}
int setblocking(bool blocking) override {
int fl = ::fcntl(fd_, F_GETFL, 0);
if (blocking) {

View File

@@ -467,6 +467,10 @@ class LWIPRawImpl : public Socket {
}
return written;
}
ssize_t sendto(const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) override {
// return ::sendto(fd_, buf, len, flags, to, tolen);
return 0;
}
int setblocking(bool blocking) override {
if (pcb_ == nullptr) {
errno = ECONNRESET;

View File

@@ -1,7 +1,8 @@
#include "socket.h"
#include "esphome/core/log.h"
#include <cstring>
#include <cerrno>
#include <cstring>
#include <string>
#include "esphome/core/log.h"
namespace esphome {
namespace socket {
@@ -14,7 +15,7 @@ std::unique_ptr<Socket> socket_ip(int type, int protocol) {
#endif
}
socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const char *ip_address, uint16_t port) {
socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const std::string &ip_address, uint16_t port) {
#if LWIP_IPV6
if (addrlen < sizeof(sockaddr_in6)) {
errno = EINVAL;
@@ -24,9 +25,14 @@ socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const char *ip_
memset(server, 0, sizeof(sockaddr_in6));
server->sin6_family = AF_INET6;
server->sin6_port = htons(port);
ip6_addr_t ip6;
inet6_aton(ip_address, &ip6);
memcpy(server->sin6_addr.un.u32_addr, ip6.addr, sizeof(ip6.addr));
if (ip_address.find('.') != std::string::npos) {
server->sin6_addr.un.u32_addr[3] = inet_addr(ip_address.c_str());
} else {
ip6_addr_t ip6;
inet6_aton(ip_address.c_str(), &ip6);
memcpy(server->sin6_addr.un.u32_addr, ip6.addr, sizeof(ip6.addr));
}
return sizeof(sockaddr_in6);
#else
if (addrlen < sizeof(sockaddr_in)) {
@@ -36,7 +42,7 @@ socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const char *ip_
auto *server = reinterpret_cast<sockaddr_in *>(addr);
memset(server, 0, sizeof(sockaddr_in));
server->sin_family = AF_INET;
server->sin_addr.s_addr = inet_addr(ip_address);
server->sin_addr.s_addr = inet_addr(ip_address.c_str());
server->sin_port = htons(port);
return sizeof(sockaddr_in);
#endif

View File

@@ -1,9 +1,9 @@
#pragma once
#include <string>
#include <memory>
#include <string>
#include "headers.h"
#include "esphome/core/optional.h"
#include "headers.h"
namespace esphome {
namespace socket {
@@ -34,6 +34,8 @@ class Socket {
virtual ssize_t readv(const struct iovec *iov, int iovcnt) = 0;
virtual ssize_t write(const void *buf, size_t len) = 0;
virtual ssize_t writev(const struct iovec *iov, int iovcnt) = 0;
virtual ssize_t sendto(const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen);
virtual int setblocking(bool blocking) = 0;
virtual int loop() { return 0; };
};
@@ -45,7 +47,7 @@ std::unique_ptr<Socket> socket(int domain, int type, int protocol);
std::unique_ptr<Socket> socket_ip(int type, int protocol);
/// Set a sockaddr to the specified address and port for the IP version used by socket_ip().
socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const char *ip_address, uint16_t port);
socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const std::string &ip_address, uint16_t port);
/// Set a sockaddr to the any address and specified port for the IP version used by socket_ip().
socklen_t set_sockaddr_any(struct sockaddr *addr, socklen_t addrlen, uint16_t port);

View File

@@ -79,7 +79,7 @@ void SPIComponent::setup() {
#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)
this->hw_spi_ = new SPIClass(FSPI); // NOLINT(cppcoreguidelines-owning-memory)
#else
this->hw_spi_ = new SPIClass(VSPI); // NOLINT(cppcoreguidelines-owning-memory)
this->hw_spi_ = new SPIClass(HSPI); // NOLINT(cppcoreguidelines-owning-memory)
#endif // USE_ESP32_VARIANT
}
spi_bus_num++;

View File

@@ -27,6 +27,7 @@ MODELS = {
"SSD1306_96X16": SSD1306Model.SSD1306_MODEL_96_16,
"SSD1306_64X48": SSD1306Model.SSD1306_MODEL_64_48,
"SSD1306_64X32": SSD1306Model.SSD1306_MODEL_64_32,
"SSD1306_72X40": SSD1306Model.SSD1306_MODEL_72_40,
"SH1106_128X32": SSD1306Model.SH1106_MODEL_128_32,
"SH1106_128X64": SSD1306Model.SH1106_MODEL_128_64,
"SH1106_96X16": SSD1306Model.SH1106_MODEL_96_16,

View File

@@ -59,6 +59,7 @@ void SSD1306::setup() {
// Set Y offset (0xD3)
this->command(SSD1306_COMMAND_SET_DISPLAY_OFFSET_Y);
this->command(0x00 + this->offset_y_);
// Set start line at line 0 (0x40)
this->command(SSD1306_COMMAND_SET_START_LINE | 0x00);
@@ -100,6 +101,7 @@ void SSD1306::setup() {
case SH1107_MODEL_128_64:
case SSD1305_MODEL_128_32:
case SSD1305_MODEL_128_64:
case SSD1306_MODEL_72_40:
this->command(0x12);
break;
}
@@ -118,6 +120,9 @@ void SSD1306::setup() {
case SH1107_MODEL_128_64:
this->command(0x35);
break;
case SSD1306_MODEL_72_40:
this->command(0x20);
break;
default:
this->command(0x00);
break;
@@ -156,6 +161,10 @@ void SSD1306::display() {
this->command(0x20 + this->offset_x_);
this->command(0x20 + this->offset_x_ + this->get_width_internal() - 1);
break;
case SSD1306_MODEL_72_40:
this->command(0x1C + this->offset_x_);
this->command(0x1C + this->offset_x_ + this->get_width_internal() - 1);
break;
default:
this->command(0 + this->offset_x_); // Page start address, 0
this->command(this->get_width_internal() + this->offset_x_ - 1);
@@ -225,6 +234,8 @@ int SSD1306::get_height_internal() {
case SSD1306_MODEL_64_48:
case SH1106_MODEL_64_48:
return 48;
case SSD1306_MODEL_72_40:
return 40;
default:
return 0;
}
@@ -246,6 +257,8 @@ int SSD1306::get_width_internal() {
case SH1106_MODEL_64_48:
case SH1107_MODEL_128_64:
return 64;
case SSD1306_MODEL_72_40:
return 72;
default:
return 0;
}
@@ -294,6 +307,8 @@ const char *SSD1306::model_str_() {
return "SSD1306 96x16";
case SSD1306_MODEL_64_48:
return "SSD1306 64x48";
case SSD1306_MODEL_72_40:
return "SSD1306 72x40";
case SH1106_MODEL_128_32:
return "SH1106 128x32";
case SH1106_MODEL_128_64:

View File

@@ -13,6 +13,7 @@ enum SSD1306Model {
SSD1306_MODEL_96_16,
SSD1306_MODEL_64_48,
SSD1306_MODEL_64_32,
SSD1306_MODEL_72_40,
SH1106_MODEL_128_32,
SH1106_MODEL_128_64,
SH1106_MODEL_96_16,

View File

@@ -53,8 +53,14 @@ void HOT I2CSSD1306::write_display_data() {
}
}
} else {
size_t block_size = 16;
if ((this->get_buffer_length_() & 8) == 8) {
// use smaller block size for e.g. 72x40 displays where buffer size is multiple of 8, not 16
block_size = 8;
}
for (uint32_t i = 0; i < this->get_buffer_length_();) {
uint8_t data[16];
uint8_t data[block_size];
for (uint8_t &j : data)
j = this->buffer_[i++];
this->write_bytes(0x40, data, sizeof(data));

View File

@@ -92,7 +92,7 @@ def switch_schema(
device_class: str = _UNDEF,
icon: str = _UNDEF,
block_inverted: bool = False,
default_restore_mode: str = "RESTORE_DEFAULT_OFF",
default_restore_mode: str = "ALWAYS_OFF",
):
schema = _SWITCH_SCHEMA.extend(
{

View File

@@ -6,8 +6,7 @@ namespace switch_ {
static const char *const TAG = "switch";
Switch::Switch(const std::string &name) : EntityBase(name), state(false) {}
Switch::Switch() : Switch("") {}
Switch::Switch() : state(false) {}
void Switch::turn_on() {
ESP_LOGD(TAG, "'%s' Turning ON.", this->get_name().c_str());

View File

@@ -32,7 +32,6 @@ enum SwitchRestoreMode {
class Switch : public EntityBase {
public:
explicit Switch();
explicit Switch(const std::string &name);
/** Publish a state to the front-end from the back-end.
*

View File

@@ -6,9 +6,6 @@ namespace text_sensor {
static const char *const TAG = "text_sensor";
TextSensor::TextSensor() : TextSensor("") {}
TextSensor::TextSensor(const std::string &name) : EntityBase(name) {}
void TextSensor::publish_state(const std::string &state) {
this->raw_state = state;
this->raw_callback_.call(state);

View File

@@ -30,9 +30,6 @@ namespace text_sensor {
class TextSensor : public EntityBase {
public:
explicit TextSensor();
explicit TextSensor(const std::string &name);
/// Getter-syntax for .state.
std::string get_state() const;
/// Getter-syntax for .raw_state

View File

@@ -16,6 +16,7 @@ time_based_ns = cg.esphome_ns.namespace("time_based")
TimeBasedCover = time_based_ns.class_("TimeBasedCover", cover.Cover, cg.Component)
CONF_HAS_BUILT_IN_ENDSTOP = "has_built_in_endstop"
CONF_MANUAL_CONTROL = "manual_control"
CONFIG_SCHEMA = cover.COVER_SCHEMA.extend(
{
@@ -26,6 +27,7 @@ CONFIG_SCHEMA = cover.COVER_SCHEMA.extend(
cv.Required(CONF_CLOSE_ACTION): automation.validate_automation(single=True),
cv.Required(CONF_CLOSE_DURATION): cv.positive_time_period_milliseconds,
cv.Optional(CONF_HAS_BUILT_IN_ENDSTOP, default=False): cv.boolean,
cv.Optional(CONF_MANUAL_CONTROL, default=False): cv.boolean,
cv.Optional(CONF_ASSUMED_STATE, default=True): cv.boolean,
}
).extend(cv.COMPONENT_SCHEMA)
@@ -51,4 +53,5 @@ async def to_code(config):
)
cg.add(var.set_has_built_in_endstop(config[CONF_HAS_BUILT_IN_ENDSTOP]))
cg.add(var.set_manual_control(config[CONF_MANUAL_CONTROL]))
cg.add(var.set_assumed_state(config[CONF_ASSUMED_STATE]))

Some files were not shown because too many files have changed in this diff Show More