Compare commits

..

704 Commits

Author SHA1 Message Date
Jesse Hills e8de6a3a67 Merge pull request #3883 from esphome/bump-2022.9.4
2022.9.4
2022-10-07 16:56:22 +13:00
Jesse Hills 3c320c4c83 Bump version to 2022.9.4 2022-10-07 16:34:39 +13:00
Jesse Hills 3b83f967e4 Dont add wifi block to yaml if discovered device uses ethernet (#3882) 2022-10-07 16:34:39 +13:00
Jesse Hills 5e96b8ef7c Bump esphome-dashboard to 20221007.0 (#3881) 2022-10-07 16:34:39 +13:00
Jesse Hills 5df0e82c37 Add network type to mdns service message (#3880) 2022-10-07 16:34:38 +13:00
Jesse Hills 2d58239b74 Merge pull request #3876 from esphome/bump-2022.9.3
2022.9.3
2022-10-06 09:57:39 +13:00
Jesse Hills 6b52f62531 Bump version to 2022.9.3 2022-10-06 09:22:01 +13:00
Jesse Hills 1001d9c04e Bluetooth Proxy active connections (#3817) 2022-10-06 09:22:00 +13:00
Jesse Hills 119c3f6f46 Merge pull request #3853 from esphome/bump-2022.9.2
2022.9.2
2022-09-29 16:18:21 +13:00
Jesse Hills d2c1c7507c Bump version to 2022.9.2 2022-09-29 16:00:55 +13:00
Guillermo Ruffino efdb3d1f40 Bump dashboard to 20220925.0 (#3846) 2022-09-29 16:00:55 +13:00
Jesse Hills 9dbc32b85f Merge pull request #3839 from esphome/bump-2022.9.1
2022.9.1
2022-09-22 07:51:52 +12:00
Jesse Hills 66226abb48 Bump version to 2022.9.1 2022-09-22 07:40:15 +12:00
Jesse Hills 34bef2f2ca Revert "fix spi timing issues" (#3838) 2022-09-22 07:40:15 +12:00
Jesse Hills fdd4ca6837 Merge pull request #3837 from esphome/bump-2022.9.0
2022.9.0
2022-09-21 15:59:34 +12:00
Jesse Hills 9655362f23 Bump version to 2022.9.0 2022-09-21 15:34:02 +12:00
Jesse Hills 130c9fad22 Merge branch 'beta' into bump-2022.9.0 2022-09-21 15:34:02 +12:00
Jesse Hills 3de0b601bf Merge pull request #3835 from esphome/bump-2022.9.0b5
2022.9.0b5
2022-09-21 15:23:41 +12:00
Jesse Hills 91560ae4e9 Bump version to 2022.9.0b5 2022-09-21 12:38:55 +12:00
Guillermo Ruffino fd6135aebb Bump dashboard to 20220920.1 (#3834) 2022-09-21 12:38:55 +12:00
Jesse Hills e5fe5d1249 Merge pull request #3833 from esphome/bump-2022.9.0b4
2022.9.0b4
2022-09-21 09:09:20 +12:00
Jesse Hills 63b42f3608 Bump version to 2022.9.0b4 2022-09-21 07:36:39 +12:00
Paulus Schoutsen d56107e97f Bump dashboard to 20220920.0 (#3831) 2022-09-21 07:36:39 +12:00
Guillermo Ruffino 33f296e05b Fix-esphome-validation-line-number (#3815) 2022-09-21 07:36:39 +12:00
Jesse Hills 97e067a277 Merge pull request #3829 from esphome/bump-2022.9.0b3
2022.9.0b3
2022-09-20 19:28:27 +12:00
Jesse Hills 5f56cf3128 Bump version to 2022.9.0b3 2022-09-20 17:14:51 +12:00
Paulus Schoutsen 5c4e83ebdc Bump dashboard to 20220919.1 (#3828) 2022-09-20 17:14:51 +12:00
Keith Burzinski 91f1c25fcc Make sprinkler reset_resume() method public (#3824) 2022-09-20 17:14:51 +12:00
h3ndrik 47a7a239ae [BME280] raise standby time (#3804) 2022-09-20 17:14:51 +12:00
Samuel Sieb fb9984e21f split pronto codes if they are too long (#3812)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2022-09-20 17:14:51 +12:00
Jesse Hills 71dd04b09e Merge pull request #3809 from esphome/bump-2022.9.0b2
2022.9.0b2
2022-09-15 13:35:54 +12:00
Jesse Hills 7deabbb512 Bump version to 2022.9.0b2 2022-09-15 13:02:40 +12:00
Azimath 625a575e49 Remove floating point calculation from ac_dimmer ISR (#3770) 2022-09-15 13:02:39 +12:00
Jesse Hills df4d0da221 Initialize all child sensors to nullptr (#3808) 2022-09-15 13:02:39 +12:00
RoboMagus 6b23b7cad7 Unify 'nullptr' initalization of class members; (#3805) 2022-09-15 13:02:39 +12:00
Guillermo Ruffino cea7deab91 Sim800l add calls, multiline sms and ussd (#3630)
Co-authored-by: Matus Ivanecky <matus.ivanecky@gmail.com>
Co-authored-by: Matus Ivanecky <maty535@users.noreply.github.com>
2022-09-15 13:02:39 +12:00
RoboMagus c61abf6aca null initialize total sensor for pulse counter (#3803)
* null initialize total sensor.

* pedantic styling fix

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

Co-authored-by: Guillermo Ruffino <glm.net@gmail.com>
2022-09-15 13:02:39 +12:00
Jesse Hills 6d267fda01 Merge pull request #3802 from esphome/bump-2022.9.0b1
2022.9.0b1
2022-09-14 17:27:01 +12:00
Jesse Hills e557dc7208 Bump version to 2022.9.0b1 2022-09-14 17:02:22 +12:00
Jesse Hills 3558806b0e Merge branch 'dev' into bump-2022.9.0b1 2022-09-14 17:02:21 +12:00
Ignacio Hernandez-Ros f1e8cc2cf0 fix spi timing issues (#3763) 2022-09-14 16:53:51 +12:00
Pascal Vizeli 6236db1a27 Add uFire ISE sensor (#3789)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-09-14 16:51:20 +12:00
Jesse Hills f4b0917239 Allow ble tracker to subscribe to ota start and stop the scanning (#3800) 2022-09-14 16:49:20 +12:00
Aleš Komárek a5e3cd1a42 Add Prometheus Service Discovery for online devices (#3788) 2022-09-14 15:22:59 +12:00
Jesse Hills b3cca5dcb6 Add stop action for ble scanning (#3799) 2022-09-14 14:57:45 +12:00
Jonathan V 49465223a4 esp32_ble_tracker continuous and one shot scanning modes (#3649)
Co-authored-by: Jonathan Valdez <@jonofmac>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-09-14 11:10:12 +12:00
dependabot[bot] 15f0e54cbf Bump frenck/action-yamllint from 1.2.0 to 1.3.0 (#3798)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-14 09:57:43 +12:00
Pascal Vizeli ed8f343aad Remove status_set_error from ufire_ec (#3792) 2022-09-13 11:17:33 +12:00
Jordan W. Cobb cbd8d70431 Add support for TM1638 Led and Key component (#3340) 2022-09-12 08:30:15 -07:00
dependabot[bot] 9ff187c3f8 Bump zeroconf from 0.39.0 to 0.39.1 (#3782)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-12 10:32:33 +12:00
Carlos Garcia Saura be473b97c4 [MPU6050] Support devices with WHOAMI 0x98 (#3784) 2022-09-12 10:32:07 +12:00
anatoly-savchenkov 9a5f865eea Add Factory Reset button and switch (#3724)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-09-12 10:23:46 +12:00
dependabot[bot] 790280ace9 Bump pylint from 2.15.0 to 2.15.2 (#3785)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-12 10:16:18 +12:00
David Buezas 8ba207fc7f Add support for BL0942 voltage, current, energy and power Sensor (#3777) 2022-09-12 09:36:09 +12:00
Keilin Bickar d66b2a1778 Add support for MPL3115A2 Pressure/Altitude and Temperature Sensor (#3371)
* Add support for mpl3115a2

* Add codeowner

* Linter/test updates

* Minor changes

* Made pressure/altitude exclusive

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-09-09 00:18:02 -05:00
Pascal Vizeli e3f2562047 u-fire EC sensor (#3774)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-09-08 22:30:07 +12:00
Philippe FOUQUET f77118a90c Add support to tm1621 display (#3737)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-09-08 11:40:27 +12:00
Jesse Hills 041eb8f6cc Merge pull request #3783 from esphome/bump-2022.8.3
2022.8.3
2022-09-06 18:54:28 +12:00
Jesse Hills 733a84df75 Bump version to 2022.8.3 2022-09-06 16:50:17 +12:00
Jesse Hills acd0b50b40 Fix HA addon auth using HA credentials (#3758) 2022-09-06 16:50:11 +12:00
Jesse Hills 635851807a Fix HA addon auth using HA credentials (#3758) 2022-09-06 16:41:23 +12:00
Jesse Hills 89fd367297 YAML linting (#3779) 2022-09-06 15:48:01 +12:00
Jesse Hills 60e46d485e Merge pull request #3781 from esphome/bump-2022.8.2
2022.8.2
2022-09-06 15:38:46 +12:00
Jesse Hills 5bf0c92318 Bump version to 2022.8.2 2022-09-06 13:12:00 +12:00
Avirsaam 39d493c278 Update modbus_controller.cpp (#3768) 2022-09-06 13:12:00 +12:00
anatoly-savchenkov d2ce62aa13 Ignore NaN states in the integration component (#3767) 2022-09-06 13:12:00 +12:00
Jesse Hills c8eb30ef27 Initial bluetooth_proxy support (#3736) 2022-09-06 13:11:54 +12:00
Jesse Hills c317422ed7 Move crc16 to helpers (#3780) 2022-09-06 12:57:21 +12:00
Jesse Hills 614eb81ad7 Remove unneeded line (spi component adds it) (#3778) 2022-09-06 11:54:32 +12:00
Avirsaam 219c5953f1 Update modbus_controller.cpp (#3768) 2022-09-05 12:50:27 +12:00
dependabot[bot] 5d712c73ea Bump pytest from 7.1.1 to 7.1.3 (#3766)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-04 20:24:26 +12:00
Andrey Yantsen 7097b7677e Add the same docker tags as used in HA (#3752) 2022-09-04 20:23:54 +12:00
anatoly-savchenkov 7a4cf13e0c Ignore NaN states in the integration component (#3767) 2022-09-04 19:21:17 +12:00
NP v/d Spek 4788a6182e I found some issue in the ili9341 driver (#3756) 2022-09-02 15:46:51 +12:00
dependabot[bot] e3dad7c632 Bump black from 22.6.0 to 22.8.0 (#3760)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-02 13:42:04 +12:00
RoboMagus 1b4156646e Esp32 pulsecounter optional pcnt (#3691)
Co-authored-by: RoboMagus <->
2022-09-02 13:22:34 +12:00
Jesse Hills 31ad75d01b Merge pull request #3757 from esphome/bump-2022.8.1
2022.8.1
2022-09-01 13:59:03 +12:00
Jesse Hills aa2eb29274 Bump version to 2022.8.1 2022-09-01 11:26:52 +12:00
Keith Burzinski 22eb4f9cb9 Fix SPI HW selection for ESP32 variants (#3728) 2022-09-01 11:26:51 +12:00
Samuel Sieb 3acc8e7479 fix grow password setting (#3722)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2022-09-01 11:26:51 +12:00
dependabot[bot] 2650441013 Bump pylint from 2.14.5 to 2.15.0 (#3746)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-08-31 17:01:36 +12:00
dependabot[bot] 71697df2b6 Bump aioesphomeapi from 10.11.0 to 10.13.0 (#3740)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-31 16:53:36 +12:00
Fabian Berthold acd55b9601 Add sum type to binary_sensor_map (#3541) 2022-08-31 16:52:16 +12:00
yuhei mukoyama 0907de8662 Add AEHA IR Protocol (#3726) 2022-08-31 16:43:33 +12:00
Wouter van der Wal 15eb9605a8 ibeacon support for the ble_rssi sensor (#3745) 2022-08-31 16:42:48 +12:00
Joe 6d5cb866db Add BedJet Fan child component (#3735) 2022-08-31 13:53:18 +12:00
Keith Burzinski 768490089e Add IP101 support to Ethernet component (#3751) 2022-08-31 13:45:30 +12:00
Jesse Hills 4d66fab360 Tidy up switch schemas (#3754) 2022-08-31 13:43:46 +12:00
Jesse Hills bd6bc283b6 Remove unnecessary schema extension on template button (#3753) 2022-08-31 11:45:06 +12:00
anatoly-savchenkov 3120a0ba83 Captive portal show nearby WiFi with no ssid configured (#3748) 2022-08-31 10:19:43 +12:00
andyboeh b2199d5464 mcp23017: read output latch registers during setup (#3744) 2022-08-31 10:07:40 +12:00
Jan Grewe 84bac8356a Add Prometheus metrics relabeling (#3734)
Co-authored-by: Guillermo Ruffino <glm.net@gmail.com>
2022-08-30 10:55:55 +12:00
Frank Riley 2819166539 Support high update rates and fix several bugs in the cse7766 component. (#3675) 2022-08-25 16:12:45 +12:00
MrEditor97 8fa18ca7c7 Support for MCP9600 Thermocouple Amplifier (#3700)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-08-25 15:49:31 +12:00
NP v/d Spek 63290a265c add color compare operator's (#3730) 2022-08-25 13:41:52 +12:00
Jesse Hills b854e17995 Initial bluetooth_proxy support (#3736) 2022-08-25 07:13:44 +12:00
Samuel Sieb 5dec9d88f6 add log messages for bad pronto codes (#3738)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2022-08-23 13:26:36 +12:00
Mike Ryan 3d0a85ee78 Add bitmap font support (#3573)
Co-authored-by: Otto Winter <otto@otto-winter.com>
2022-08-19 10:49:52 +12:00
Keith Burzinski ac3cdf487f Fix SPI HW selection for ESP32 variants (#3728) 2022-08-19 07:55:10 +12:00
Sebastian Lövdahl a47e92f2bc Let favicon be cached (#3729) 2022-08-19 07:54:10 +12:00
Keith Burzinski fc15ddfa91 Add dps310 sensor support (#3704)
Co-authored-by: Greg Arnold <greg@arnoldassociates.com>
2022-08-19 07:49:35 +12:00
Jesse Hills d546ef941f Add final validate for i2c with mix/max frequency (#3727)
Co-authored-by: MrEditor97 <mr.samuel.hughes@gmail.com>
2022-08-18 11:04:50 +12:00
Stijn Tintel b4bbe3d7b5 wifi: support 802.11k and 802.11v (#3600) 2022-08-17 21:10:43 +12:00
functionpointer 5561d4eaeb hydreon_rgxx: Support lens_bad, em_sat and temperature (#3642) 2022-08-17 16:07:33 +12:00
Samuel Sieb 0f6dab394a fix grow password setting (#3722)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2022-08-16 20:41:46 -07:00
Jesse Hills adc8c1aa38 Merge pull request #3721 from esphome/bump-2022.8.0
2022.8.0
2022-08-17 13:31:24 +12:00
Jesse Hills 3a82f500d4 Bump version to 2022.8.0 2022-08-17 12:58:30 +12:00
Jesse Hills 7d1d4831a8 Merge branch 'beta' into bump-2022.8.0 2022-08-17 12:58:29 +12:00
Samuel Sieb 43539f2dbf Send CR also for commands for sim800l (#3719) 2022-08-17 10:35:44 +12:00
Ignacio Hernandez-Ros df6830110d Improve OTA error messages adding return codes (#3698) 2022-08-16 21:51:05 +12:00
Jesse Hills 1a98e882dc Merge pull request #3718 from esphome/bump-2022.8.0b3
2022.8.0b3
2022-08-16 15:16:37 +12:00
Jesse Hills c943d84036 Bump version to 2022.8.0b3 2022-08-16 14:47:48 +12:00
rbaron d07a6704d5 Makes ble_client.ble_write's action value templatable (#3715) 2022-08-16 14:47:48 +12:00
rbaron 8cfcd5904c Fixes BLE remote address type when connecting (#3702) 2022-08-16 14:47:48 +12:00
buxtronix fb8846bb45 Only trigger ble_client on_connect after discovering services (#3710) 2022-08-16 14:47:48 +12:00
anatoly-savchenkov 0d0733dd94 Webui small fixes (#3713) 2022-08-16 14:47:47 +12:00
rbaron 1a524a5a50 Makes ble_client.ble_write's action value templatable (#3715) 2022-08-16 14:40:58 +12:00
rbaron 1a2288cccf Fixes BLE remote address type when connecting (#3702) 2022-08-15 15:09:33 +12:00
buxtronix 8df27d4c3f Only trigger ble_client on_connect after discovering services (#3710) 2022-08-15 15:06:05 +12:00
puuu 0688deca6b Add support for pvvx mithermometer display via ble client (#3333)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-08-15 10:56:25 +12:00
anatoly-savchenkov 01a4443b6c Webui small fixes (#3713) 2022-08-15 10:28:29 +12:00
Samuel Sieb e008b054cb support modifying the apds9960 settings (#3708)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-08-15 10:16:56 +12:00
Jesse Hills a67d58948d Merge pull request #3714 from esphome/bump-2022.8.0b2
2022.8.0b2
2022-08-15 09:08:44 +12:00
Jesse Hills 84c051d097 Bump version to 2022.8.0b2 2022-08-15 08:23:35 +12:00
NP v/d Spek b918abfd54 add gradient color V2.0 (#3709) 2022-08-15 08:23:35 +12:00
Peter Galantha 7f41b7cd93 Add state_class total (#3608)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-08-15 08:23:35 +12:00
Jesse Hills 4759b4fe2e Add vector include (#3707) 2022-08-15 08:23:35 +12:00
anatoly-savchenkov e2c8e69d12 Improve Web view for Climate components (#3706) 2022-08-15 08:23:35 +12:00
NP v/d Spek 1cf213dad8 add gradient color V2.0 (#3709) 2022-08-15 08:21:08 +12:00
Peter Galantha aeb81e547b Add state_class total (#3608)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-08-11 14:00:09 +12:00
Jesse Hills 479f7703a2 Add vector include (#3707) 2022-08-11 13:57:42 +12:00
anatoly-savchenkov c7dc396b6d Improve Web view for Climate components (#3706) 2022-08-11 13:32:55 +12:00
Jesse Hills 917e8e155c Merge pull request #3705 from esphome/bump-2022.8.0b1
2022.8.0b1
2022-08-10 15:45:17 +12:00
Jesse Hills 80e3030811 Bump version to 2022.9.0-dev 2022-08-10 15:26:02 +12:00
Jesse Hills a97e3d827d Bump version to 2022.8.0b1 2022-08-10 15:26:02 +12:00
RoboMagus 029014d9d6 Add priority to on_shutdown trigger (#3644) 2022-08-10 13:10:49 +12:00
dependabot[bot] e4c2922536 Bump pylint from 2.14.4 to 2.14.5 (#3697)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-10 12:34:56 +12:00
dependabot[bot] 7133ae6aaa Bump flake8 from 4.0.1 to 5.0.4 (#3703)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-10 09:21:25 +12:00
dependabot[bot] 2f7f0ff3a1 Bump pytest-mock from 3.8.1 to 3.8.2 (#3622)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-10 08:03:42 +12:00
dependabot[bot] df853bf61e Bump zeroconf from 0.38.7 to 0.39.0 (#3694)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-09 19:19:13 +12:00
dependabot[bot] f0ac753f9b Bump pytest-asyncio from 0.18.3 to 0.19.0 (#3695)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-09 19:16:49 +12:00
Adrián Panella 4d56a975e6 Create feedback cover component (#3253) 2022-08-09 17:21:27 +12:00
dependabot[bot] d56c53c848 Bump aioesphomeapi from 10.10.0 to 10.11.0 (#3669)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-09 13:53:30 +12:00
dependabot[bot] f83b16320d Bump pyupgrade from 2.34.0 to 2.37.3 (#3670)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-08-09 13:53:18 +12:00
anatoly-savchenkov ac10e27f08 [Nextion] Add on_page trigger (#3673) 2022-08-09 12:44:20 +12:00
NP v/d Spek 34df7a6072 add gradient color (#3687) 2022-08-09 12:29:41 +12:00
Keith Burzinski e2cddf1005 Sprinkler controller component (#2249)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-08-09 12:19:42 +12:00
Ian Blais ced423748e Adding support for Whynter ARC-14S/SH Air Conditioners (#3641) 2022-08-09 10:49:03 +12:00
davestubbs 77fb02729e Added support for setting the current animation frame (#3681) 2022-08-09 10:28:05 +12:00
Joe fef39b9fbe Refactor BedJet climate into Hub component (#3522) 2022-08-09 10:14:37 +12:00
Jesse Hills 02810105fb Add helpers to switch python for schema and codegen (#3693)
* Add helpers to switch python for schema and codegen

* Add icon back
2022-08-07 22:01:17 -05:00
rbaron baad92515b Introduces ble_client.ble_write Action (#3398) 2022-08-08 12:59:55 +12:00
Jesse Hills ab86ddcf02 Merge pull request #3692 from esphome/bump-2022.6.3
2022.6.3
2022-08-08 11:48:35 +12:00
Jesse Hills bf8eddb13b Bump version to 2022.6.3 2022-08-08 08:24:12 +12:00
Samuel Sieb e5eaf7a3fe Use correct struct members. (#3672) 2022-08-08 08:24:12 +12:00
Samuel Sieb 50f32a3aa5 Use application/json instead of text/json (#3671) 2022-08-08 08:24:11 +12:00
Bryan Berg eb878710c1 Add CO device class to binary_sensor (#3656) 2022-08-08 08:24:11 +12:00
Samuel Sieb 311980e0e4 Update inkbird_ibsth1_mini.cpp (#3664) 2022-08-08 08:24:11 +12:00
Javier Peletier df73170e5a modbus: fix queue deduplicator erasing custom commands (#3650) 2022-08-08 08:24:11 +12:00
dentra a12c6b5f35 Fix panic abort when BLEClient reconnects (#3594) 2022-08-08 07:57:43 +12:00
Keith Burzinski 522646c64d Extend ST7789V component to support additional displays (#3651)
Co-authored-by: definitio <37266727+definitio@users.noreply.github.com>
2022-08-08 07:54:48 +12:00
anatoly-savchenkov 4791093e48 Add get_ap() method to WiFi (#3684) 2022-08-08 07:51:09 +12:00
Donovan Baarda 599a455150 Add a soft reset in setup() for bme280. (#3615) 2022-08-08 07:50:15 +12:00
Samuel Sieb 2deef16ebe fix sx1509 use of pullup and pulldown (#3689)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2022-08-08 07:39:41 +12:00
RoboMagus 989b7be99b Pass optional args to 'new_Pvariable' when creating new entities (#3690) 2022-08-08 07:31:50 +12:00
Derek M cd473e1395 Adding option to report signal strength on pvvx_mithermometer (#3688)
Co-authored-by: doolbneerg <doolbneerg@outlook.com>
2022-08-08 07:30:30 +12:00
Jesse Hills e246ebfb2e Remove old unused code in mcp23xxx_base (#3685) 2022-08-07 09:56:52 +12:00
Borys Pierov 8546ae56da Allow GPIO20 for ESP32 (#3680) 2022-08-04 07:30:19 +12:00
Sybren A. Stüvel 9e227b0192 Upgrade rweather/Crypto from 0.2.0 to 0.4.0 (#3593)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-08-03 07:58:03 +12:00
Samuel Sieb ba7737e9f8 dalybms: support changing the address (#3676) 2022-08-03 07:48:02 +12:00
Jesse Hills 98aa3d51ed Show changes from python linting (#3677) 2022-08-03 07:27:45 +12:00
Samuel Sieb e7cfb5492e Use correct struct members. (#3672) 2022-08-02 17:09:17 +12:00
Samuel Sieb 9ed136dc3a Use application/json instead of text/json (#3671) 2022-08-02 17:07:32 +12:00
Bryan Berg 9217216723 Add CO device class to binary_sensor (#3656) 2022-08-02 11:32:02 +12:00
RoboMagus 936c408a58 List webserver service on MDNS if enabled. (#3662) 2022-08-02 11:31:06 +12:00
Samuel Sieb 54427eac9a Update inkbird_ibsth1_mini.cpp (#3664) 2022-08-01 13:08:19 +12:00
Samuel Sieb e809488cc0 Remove deprecated adc init call. (#3667) 2022-08-01 09:44:58 +12:00
DAVe3283 ed26c57d99 Rework NaN handling in sensor filters (#3610)
Co-authored-by: Otto Winter <otto@otto-winter.com>
2022-07-28 16:39:11 +12:00
piechade 2a49811f6e Add support for SMT100 Soil Moisture Sensor (#3654)
Co-authored-by: Dennis Piecha <d.piecha@ymail.com>
2022-07-28 11:22:49 +12:00
Peter Galantha c95acd2568 update packages: nginx-light-1.18.0-6.1+deb11u2 nano-5.4-2+deb11u1 (#3631) 2022-07-25 16:04:21 +12:00
Samuel Sieb 6a4e0cf667 add option to publish initial state of binary sensors (#3636)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2022-07-25 15:55:32 +12:00
RoboMagus 04f4dd8a22 Add 'set_total_pulses' action to 'pulse_counter' sensor. (#3640) 2022-07-25 14:20:15 +12:00
Javier Peletier f33d829ce9 FIX: NVS preferences being written even if unchanged (#3647) 2022-07-25 10:10:37 +12:00
RoboMagus 578671ea94 Fix configuration constants in core. (#3652) 2022-07-25 08:23:55 +12:00
Javier Peletier d10300c330 modbus: fix queue deduplicator erasing custom commands (#3650) 2022-07-25 08:06:18 +12:00
Andreas Hergert e0555e140f Improvement pipsolar crc (#3316)
Co-authored-by: Andreas <andreas.hergert@otrs.com>
2022-07-07 12:54:19 +12:00
Luca Adrian L 093989406f Added more sensor device classes (#3624) 2022-07-07 11:32:38 +12:00
dab0g cdb16f08f6 Update dfplayer condition function name (#3619) 2022-07-04 09:22:04 +12:00
dependabot[bot] 53139c293b Bump pytest-mock from 3.7.0 to 3.8.1 (#3616) 2022-07-01 14:54:37 +02:00
dependabot[bot] 6a8bdcc315 Bump pylint from 2.14.3 to 2.14.4 (#3617) 2022-07-01 14:54:13 +02:00
dependabot[bot] fe535939a3 Bump colorama from 0.4.4 to 0.4.5 (#3614) 2022-06-30 12:42:35 +02:00
dependabot[bot] 09e6c11d73 Bump black from 22.3.0 to 22.6.0 (#3613) 2022-06-30 12:42:28 +02:00
dependabot[bot] 8112bdfaa8 Bump pyupgrade from 2.32.1 to 2.34.0 (#3591)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Otto Winter <otto@otto-winter.com>
2022-06-30 11:59:53 +02:00
marshn f7db9aaa9f Fix slow_pwm output glitch (#3601) 2022-06-30 11:28:19 +02:00
Javier Peletier 435f972357 fix EDict to dict mapping in helpers.py (#3599) 2022-06-30 11:24:24 +02:00
dependabot[bot] f82b46c16b Bump zeroconf from 0.38.4 to 0.38.7 (#3562)
Bumps [zeroconf](https://github.com/jstasiak/python-zeroconf) from 0.38.4 to 0.38.7.
- [Release notes](https://github.com/jstasiak/python-zeroconf/releases)
- [Commits](https://github.com/jstasiak/python-zeroconf/compare/0.38.4...0.38.7)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-30 11:06:22 +02:00
Jesse Hills bca96f91b2 Remove min_save_interval from intergration and total_daily_energy (#3498) 2022-06-30 16:47:56 +12:00
Benoit3 6f83a49c63 #3358 Correct temperature validity detection issue in some conditions of pu… (#3545)
Co-authored-by: Otto Winter <otto@otto-winter.com>
2022-06-29 21:30:44 +02:00
André Klitzing 72cce391ab Fix some typos found by codespell (#3598) 2022-06-27 18:02:46 -03:00
Jesse Hills ccc13cc9e1 Merge pull request #3596 from esphome/bump-2022.6.2
2022.6.2
2022-06-23 11:30:31 +12:00
Jesse Hills 020b2c05c8 Bump version to 2022.6.2 2022-06-23 10:34:10 +12:00
Joe 4c37c17df1 Fix 2 small issues in BLEClient (#3544) 2022-06-23 10:34:09 +12:00
Sergey Dudanov 8f67acadd8 Media Player: added play_media action (#3579)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-06-23 10:34:09 +12:00
kahrendt ca13c4c1a6 Fix wrong type for voc_state*_ in sgp4x component (#3581)
Co-authored-by: Martin <25747549+martgras@users.noreply.github.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-06-23 10:34:09 +12:00
ShellAddicted d0c646c721 Fix: Make MQTT over TLS actually work (#3580) 2022-06-23 10:34:09 +12:00
lkomurcu 8a055675af Move gas mbus config option being a define to being a build flag since its used in external libraries. (#3575) 2022-06-23 10:34:09 +12:00
Jesse Hills 28d2949ebe Add github-actions to dependabot (#3595) 2022-06-23 07:51:05 +12:00
Sven Serlier c4a0015997 Update actions (#3592)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-06-23 07:50:55 +12:00
Jesse Hills f564be6aea Do two substitutions passes to allow substitutions inside substitutions (#3583) 2022-06-22 08:21:32 +12:00
dependabot[bot] 988f15e6af Bump aioesphomeapi from 10.8.2 to 10.10.0 (#3590)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-21 17:19:41 +12:00
Zimmermann Zsolt 37b6d442bd Correcting ESP32 flash save/load key calculation algorithm (#3416)
Co-authored-by: Otto Winter <otto@otto-winter.com>
Co-authored-by: Dr. Zimmermann Zsolt <cina@storage1.cina.hu>
2022-06-21 17:17:51 +12:00
Nick B fb2467f6f0 DAC7678 support (#3441)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-06-21 17:12:15 +12:00
dependabot[bot] 29045b0435 Bump pylint from 2.13.9 to 2.14.3 (#3589)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-06-21 16:27:33 +12:00
Jesse Hills 311a48c64e Bump platformio to 6.0.2 (#3566) 2022-06-21 11:53:51 +12:00
Mateus Demboski 01b3815f27 Map LOLIN C3 mini board pins (#3587) 2022-06-21 11:33:20 +12:00
Joe b0d1c801bd Fix 2 small issues in BLEClient (#3544) 2022-06-21 11:31:17 +12:00
RoboMagus 5aaac06f5b RestoringGlobalsComponent: Store value on shutdown (#3586) 2022-06-21 11:27:53 +12:00
RoboMagus 34adbf0588 Fix / Reverse order shutdown (#3585) 2022-06-21 11:26:34 +12:00
Jesse Hills 0a4213182e Merge branch 'release' into dev 2022-06-21 07:18:41 +12:00
Sergey Dudanov b0c0258e70 Media Player: added play_media action (#3579)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-06-20 12:17:20 +12:00
kahrendt 8110e591d0 Fix wrong type for voc_state*_ in sgp4x component (#3581)
Co-authored-by: Martin <25747549+martgras@users.noreply.github.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-06-20 11:27:00 +12:00
ShellAddicted fe05d7aec1 Fix: Make MQTT over TLS actually work (#3580) 2022-06-20 11:17:58 +12:00
lkomurcu 57f5884070 Move gas mbus config option being a define to being a build flag since its used in external libraries. (#3575) 2022-06-20 07:39:40 +12:00
Jesse Hills f329c74a15 Merge pull request #3578 from esphome/bump-2022.6.1
2022.6.1
2022-06-18 22:31:45 +12:00
Jesse Hills 7c86f3fa9e Bump version to 2022.6.1 2022-06-18 17:25:52 +12:00
Sergey Dudanov 203b8b01bf Media Player: added triggers (#3576) 2022-06-18 17:25:51 +12:00
Benjamin Klotz 8a1034a92f Bugfix for ExternalRAMAllocator copy constructor (#3571) 2022-06-18 17:25:51 +12:00
Jesse Hills aa0c2dedd9 Setup the mute pin if configured (#3568) 2022-06-18 17:25:51 +12:00
Sergey Dudanov d045908e05 Media Player: added triggers (#3576) 2022-06-18 17:21:42 +12:00
Guillermo Ruffino f002a23d2d Language schema 202204 (#3492) 2022-06-17 13:46:20 +12:00
gazoodle 29d6d0a906 Fix modbus user-defined function handling (#3527) 2022-06-17 13:35:25 +12:00
Benjamin Klotz c8b58b5c23 Bugfix for ExternalRAMAllocator copy constructor (#3571) 2022-06-17 13:32:43 +12:00
Jesse Hills 01bfafc5f1 Setup the mute pin if configured (#3568) 2022-06-17 13:30:21 +12:00
Jesse Hills 8c9948bb56 Merge pull request #3567 from esphome/bump-2022.6.0
2022.6.0
2022-06-16 12:59:26 +12:00
Jesse Hills 2d1abaa68e Bump version to 2022.6.0 2022-06-16 11:31:38 +12:00
Jesse Hills 664a3df0b4 Merge branch 'beta' into bump-2022.6.0 2022-06-16 11:31:38 +12:00
Jesse Hills 9ff893881c Merge pull request #3560 from esphome/bump-2022.6.0b4
2022.6.0b4
2022-06-14 22:42:06 +12:00
Jesse Hills 94f6c6861a Bump version to 2022.6.0b4 2022-06-14 20:41:46 +12:00
Martin b1d614e6c4 Bm3xx: Fix typo (#3559) 2022-06-14 20:41:46 +12:00
André Klitzing 7fceb070e5 Fix compilation with ESP32-S3 (#3543)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-06-14 20:41:46 +12:00
Martin 06440d0202 Bm3xx: Fix typo (#3559) 2022-06-14 20:38:09 +12:00
André Klitzing 0ecf9f4f2f Fix compilation with ESP32-S3 (#3543)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-06-14 20:36:38 +12:00
Jesse Hills 5c7c0834c0 Merge pull request #3554 from esphome/bump-2022.6.0b3
2022.6.0b3
2022-06-13 17:06:45 +12:00
Jesse Hills f3a25de11d Bump version to 2022.6.0b3 2022-06-13 13:32:43 +12:00
Jesse Hills 041bef8bcd Implement media player volume actions (#3551) 2022-06-13 13:32:43 +12:00
Jesse Hills 8998c5f6dd Implement media player volume actions (#3551) 2022-06-13 13:28:55 +12:00
Jesse Hills 6e83790308 Merge pull request #3540 from esphome/bump-2022.6.0b2
2022.6.0b2
2022-06-09 21:16:23 +12:00
Jesse Hills d2d4eb4eae Bump version to 2022.6.0b2 2022-06-09 20:27:22 +12:00
Viktor Nagy 5942a3898c Nextion brightness setting requires an assignment (#3533) 2022-06-09 20:27:22 +12:00
Samuel Sieb 93421f0fa7 publish fan speed count for discovery (#3537)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2022-06-09 20:27:22 +12:00
RoboMagus 3a9ab50dd2 Refactor vl53l0x to remove code from header. (#3536) 2022-06-09 16:24:56 +12:00
Viktor Nagy 5abd91d6d5 Nextion brightness setting requires an assignment (#3533) 2022-06-09 16:20:05 +12:00
Samuel Sieb c3da42516b publish fan speed count for discovery (#3537)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2022-06-09 15:27:04 +12:00
Jesse Hills 6cb5cd48c2 Merge pull request #3535 from esphome/bump-2022.6.0b1
2022.6.0b1
2022-06-08 23:26:21 +12:00
Jesse Hills ec1fae6883 Bump version to 2022.7.0-dev 2022-06-08 22:46:20 +12:00
Jesse Hills 746fd1122f Bump version to 2022.6.0b1 2022-06-08 22:46:20 +12:00
Jesse Hills 9663760ec5 Merge branch 'dev' into bump-2022.6.0b1 2022-06-08 22:46:20 +12:00
Wolfgang Tremmel a3d73d1e23 RG15 data is float/double, not int (#3512)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-06-08 22:34:50 +12:00
Jesse Hills d63e14a4b6 Implement the media player actions (#3534) 2022-06-08 22:33:21 +12:00
DAVe3283 03944e6cd8 Fix bogus reading on no communication with MAX31865 (#3505) 2022-06-08 09:58:32 +12:00
Maurice Makaay 0d1028be2e Cleanup deprecated EntityBase::hash_base() (#3525)
Co-authored-by: Maurice Makaay <mmakaay1@xs4all.net>
2022-06-08 09:13:11 +12:00
VitaliyKurokhtin 6a85259e4d Block Tuya light from reacting to dp changes if transitioning (#3076) 2022-06-07 23:07:08 +12:00
Maurice Makaay ebca936b7e Fix percentage validation for wrong data type input (#3524)
Co-authored-by: Maurice Makaay <mmakaay1@xs4all.net>
2022-06-07 23:00:27 +12:00
Nicholas Peters 31c4551890 Fix sdp3x error checking (#3531) 2022-06-07 22:43:46 +12:00
Samuel Sieb dd470d4197 support rotated ILI9341 (ILI9342) (#3526)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2022-06-07 22:42:13 +12:00
Maurice Makaay 612822490b Fix endless 'WiFi Unknown connection status 0' loop (#3530)
Co-authored-by: Maurice Makaay <mmakaay1@xs4all.net>
2022-06-07 12:08:29 +12:00
Maurice Makaay f8969605e8 Suppress first rotary encoder event (#3532)
Co-authored-by: Maurice Makaay <mmakaay1@xs4all.net>
2022-06-07 11:36:54 +12:00
Carlos Garcia Saura dd24ffa24e Correct ADC auto-range for ESP32-S2 variant (13 bit adc) (#3158)
Co-authored-by: Otto Winter <otto@otto-winter.com>
2022-06-03 16:07:35 +12:00
guillempages d0dda48932 Add display_type property to DisplayBuffer (#3430)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-06-03 15:39:04 +12:00
Eric van Blokland 6349b5f654 Added RC6 protocol support (#3514) 2022-06-03 15:37:04 +12:00
Joe a6ff02a3cf Refactor clock syncing (#3503)
* Expose `send_local_time()` as public, for use in lambdas.
  This will send the current time configured in `time_id`.
* Add a new `set_clock()` public method, separate from time_id.
  This allows setting the clock manually, without syncing from a Time
  Component. Again this can only be called from ESPHome; i.e.,
  generally from a lambda.
2022-06-03 13:53:20 +12:00
jimtng 4f57bf786b Add mqtt.on_connect and mqtt.on_disconnect triggers (#3520) 2022-06-03 13:51:50 +12:00
Jesse Hills 6221f6d47d Implement Media Player and I2S Media player (#3487) 2022-06-02 17:00:17 +12:00
Wolfgang Tremmel a922efeafa Change rain intensity sensor string (#3511) 2022-05-31 16:49:18 +12:00
jimtng 5aa42e5e66 Add variable substitutions for !include (#3510) 2022-05-31 16:45:18 +12:00
Joe 708672ec7e [BedJet] Add configurable heating strategy (#3519)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-05-31 15:45:01 +12:00
Jan Grewe d2cefbf224 Allow Prometheus component to export internal components (#3508)
Co-authored-by: Jan Grewe <jan.grewe@flixbus.com>
2022-05-31 07:29:57 +12:00
Michael Davidson adb7aa6950 Thermostat preset with modes (#3298)
* Rework HOME/AWAY support to being driven via a map of ClimatePreset/ThermostatClimateTargetTempConfig
This opens up to theoretically being able to support other presets (ECO, SLEEP, etc)

* Add support for additional presets
Configuration takes the form;
```
climate:
  platform: preset
  ...
  preset:
    [eco | away | boost | comfort | home | sleep | activity]:
      default_target_temperature_low: 20
      default_target_temperature_high: 24
```

These will be available in the Home Assistant UI and, like the existing Home/Away config will reset the temperature in line with these defaults when selected. The existing away_config/home_config is still respected (although preset->home/preset->away will be applied after them and override them if both styles are specified)

* Add support for specifying MODE, FAN_MODE and SWING_MODE on a preset
When switching presets these will implicitly flow through to the controller. However calls to climate.control which specify any of these will take precedence even when changing the mode (think of the preset version as the default for that preset)

* Add `preset_change` mode trigger
When defined this trigger will fire when the preset for the thermostat has been changed. The intent of this is similar to `auto_mode` - it's not intended to be used to control the preset's state (eg. communicate with the physical thermostat) but instead might be used to update a visual indicator, for instance.

* Apply lint, clang-format, and clang-tidy fixes

* Additional clang-format fixes

* Wrap log related strings in LOG_STR_ARG

* Add support for custom presets
This also changes the configuration syntax to;
```yaml
  preset:
    # Standard preset
    - name: [eco | away | boost | comfort | home | sleep | activity]
      default_target_temperature_low: 20
      ...
    # Custom preset
    - name: My custom preset
      default_target_temperature_low: 18
```

For the end user there is no difference between a custom and built in preset. For developers custom presets are set via `climate.control` `custom_preset` property instead of the `preset`

* Lint/clang-format/clang-tidy fixes

* Additional lint/clang-format/clang-tidy fixes

* Clang-tidy changes

* Sort imports

* Improve configuration validation for presets
- Unify temperature validation across default, away, and preset configuration
- Validate modes for presets have the required actions

* Trigger a refresh after changing internals of the thermostat

* Apply formatting fixes

* Validate mode, fan_mode, and swing_mode on presets

* Add preset temperature validation against visual min/max configuration

* Apply code formatting fixes

* Fix preset temperature validation
2022-05-24 22:44:26 -05:00
Jesse Hills 77f322166e Merge pull request #3499 from esphome/bump-2022.5.1
2022.5.1
2022-05-25 07:29:42 +12:00
Jesse Hills f3f6e54818 Bump version to 2022.5.1 2022-05-24 21:56:18 +12:00
Martin fb0fec1f25 esp32: fix NVS (#3497) 2022-05-24 21:56:18 +12:00
Jesse Hills b66af9fb4d Add missing import to bedjet (#3490) 2022-05-24 21:56:18 +12:00
user897943 6617d576a7 Update bedjet_const.h to remove blank spaces before speed steps, fixes Unknown Error when using climate.set_fan_mode in HA (#3476) 2022-05-24 21:56:18 +12:00
Wumpf cd35ead890 [scd4x] Fix not passing arguments to templatable value for perform_forced_calibration (#3495) 2022-05-24 13:00:06 +12:00
joseph douce 9dc804ee27 Output a true RMS voltage % (#3494) 2022-05-24 12:52:54 +12:00
Martin a8ceeaa7b0 esp32: fix NVS (#3497) 2022-05-23 20:56:26 +12:00
Sergey Dudanov 7092f7663e midea: New power_toggle action. Auto-use remote transmitter. (#3496) 2022-05-23 20:51:45 +12:00
Jesse Hills d9d2edeb08 Fix compile issues on windows (#3491) 2022-05-19 21:21:42 +12:00
Jesse Hills dda1ddcb26 Add missing import to bedjet (#3490) 2022-05-19 16:23:40 +12:00
Keilin Bickar f0c890f160 Remove deprecated fan speeds (#3397)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-05-19 12:50:44 +12:00
gazoodle 4f52d43347 add support user-defined modbus functions (#3461) 2022-05-19 12:49:12 +12:00
Martin 0ed7db979b Add support for SGP41 (#3382)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-05-19 12:47:33 +12:00
myml 9c78049359 feat: esp32-camera add stream event (#3285) 2022-05-19 12:23:50 +12:00
user897943 7882105661 Update bedjet_const.h to remove blank spaces before speed steps, fixes Unknown Error when using climate.set_fan_mode in HA (#3476) 2022-05-19 10:25:42 +12:00
Dave T c000e1d6dd Ili9341 8bit indexed mode pt1 (#2490) 2022-05-19 10:23:00 +12:00
Jesse Hills 420dacb22d Merge pull request #3488 from esphome/bump-2022.5.0
2022.5.0
2022-05-18 16:56:16 +12:00
Jesse Hills ae2f6ad4d1 Bump version to 2022.5.0 2022-05-18 16:30:20 +12:00
Jesse Hills 2c28d79bf8 Merge branch 'beta' into bump-2022.5.0 2022-05-18 16:30:19 +12:00
Jesse Hills c5069edc78 Merge pull request #3484 from esphome/bump-2022.5.0b4
2022.5.0b4
2022-05-17 23:42:51 +12:00
Jesse Hills 282d9e138c Revert adding spaces 2022-05-17 23:31:55 +12:00
Jesse Hills 72fcf2cbe1 Bump version to 2022.5.0b4 2022-05-17 23:23:37 +12:00
Samuel Sieb 6f49f5465b Retry Tuya init commands (#3482)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2022-05-17 23:23:33 +12:00
Martin 17b8bd8316 ESP32: Only save to NVS if data was changed (#3479) 2022-05-17 23:16:33 +12:00
Samuel Sieb 9b6b9c1fa2 Retry Tuya init commands (#3482)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2022-05-17 20:15:02 +12:00
Martin 609a2ca592 ESP32: Only save to NVS if data was changed (#3479) 2022-05-17 10:59:36 +12:00
[pʲɵs] 6dabf24bf3 MQTT cover: send state even if position is available (#3473) 2022-05-16 15:35:27 +12:00
Jesse Hills 7e88938932 Merge pull request #3478 from esphome/bump-2022.5.0b3
2022.5.0b3
2022-05-16 13:42:05 +12:00
Jesse Hills c707e64685 Bump version to 2022.5.0b3 2022-05-16 13:07:12 +12:00
Jesse Hills a639690716 Mark improv_serial and ESP-IDF usb based serial on c3/s2/s3 unsupported (#3477) 2022-05-16 13:07:12 +12:00
[pʲɵs] 01222dbab7 Increase JSON buffer size on overflow (#3475) 2022-05-16 13:07:12 +12:00
Jesse Hills 93e2506279 Mark improv_serial and ESP-IDF usb based serial on c3/s2/s3 unsupported (#3477) 2022-05-16 13:05:20 +12:00
Maxim Ocheretianko f62d5d3b9d Add Tuya select (#3469) 2022-05-16 07:49:40 +12:00
Maxim Ocheretianko 0665acd190 Tuya status gpio support (#3466) 2022-05-16 07:44:14 +12:00
[pʲɵs] fea05e9d33 Increase JSON buffer size on overflow (#3475) 2022-05-15 19:53:43 +12:00
dependabot[bot] 7a03c7d56f Bump pylint from 2.13.8 to 2.13.9 (#3470)
Bumps [pylint](https://github.com/PyCQA/pylint) from 2.13.8 to 2.13.9.
- [Release notes](https://github.com/PyCQA/pylint/releases)
- [Changelog](https://github.com/PyCQA/pylint/blob/main/ChangeLog)
- [Commits](https://github.com/PyCQA/pylint/compare/v2.13.8...v2.13.9)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-15 19:46:36 +12:00
dependabot[bot] 2dc2aec954 Bump esptool from 3.3 to 3.3.1 (#3468)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-13 13:44:24 +12:00
Dave T 39c6c2417a Remove duplicate convert_to_8bit_color_ function. (#2469)
Co-authored-by: Oxan van Leeuwen <oxan@oxanvanleeuwen.nl>
2022-05-12 22:18:51 +12:00
Jesse Hills ff72d6a146 Merge pull request #3465 from esphome/bump-2022.5.0b2
2022.5.0b2
2022-05-12 22:15:21 +12:00
Jesse Hills 603d0d0c7c Bump version to 2022.5.0b2 2022-05-12 17:00:14 +12:00
Brian Kaufman 28883f711b Update captive portal canHandle function (#3360) 2022-05-12 17:00:13 +12:00
Michael Davidson e914828add Make custom_fan and custom_preset templatable as per documentation (#3330) 2022-05-12 17:00:13 +12:00
James Szalay c1480029fb Use heat mode for heat. Move EXT HT to custom presets. (#3437)
* Use heat mode for heat. Move EXT HT to custom presets.

* Fix syntax error.
2022-05-12 17:00:13 +12:00
Niclas Larsson 40f622949e Shelly dimmer: Use unique_ptr to handle the lifetime of stm32_t (#3400)
Co-authored-by: Martin <25747549+martgras@users.noreply.github.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-05-12 17:00:13 +12:00
Maurice Makaay 63096ac2bc On epoch sync, restore local TZ (#3462)
Co-authored-by: Maurice Makaay <mmakaay1@xs4all.net>
2022-05-12 17:00:13 +12:00
Brian Kaufman 03d5a0ec1d Update captive portal canHandle function (#3360) 2022-05-12 16:57:50 +12:00
Michael Davidson 1c873e0034 Make custom_fan and custom_preset templatable as per documentation (#3330) 2022-05-12 16:54:45 +12:00
swifty99 bcb47c306c Tcs34725 automatic sampling settings for improved dynamics and accuracy (#3258)
Co-authored-by: Daniel Cousens <413395+dcousens@users.noreply.github.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-05-12 16:53:33 +12:00
James Szalay 01c4d3c225 Use heat mode for heat. Move EXT HT to custom presets. (#3437)
* Use heat mode for heat. Move EXT HT to custom presets.

* Fix syntax error.
2022-05-12 15:26:14 +12:00
Niclas Larsson c2aaae4818 Shelly dimmer: Use unique_ptr to handle the lifetime of stm32_t (#3400)
Co-authored-by: Martin <25747549+martgras@users.noreply.github.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-05-12 10:26:51 +12:00
Maurice Makaay 3f678e218d On epoch sync, restore local TZ (#3462)
Co-authored-by: Maurice Makaay <mmakaay1@xs4all.net>
2022-05-12 09:25:00 +12:00
Jesse Hills c2a59cb476 Merge pull request #3460 from esphome/bump-2022.5.0b1
2022.5.0b1
2022-05-11 15:51:44 +12:00
Jesse Hills f8a1bd4e79 Bump version to 2022.6.0-dev 2022-05-11 12:50:42 +12:00
Jesse Hills d6e039a1d1 Bump version to 2022.5.0b1 2022-05-11 12:50:42 +12:00
Jesse Hills 0f1a7c2b69 Merge branch 'dev' into bump-2022.5.0b1 2022-05-11 12:50:41 +12:00
Jesse Hills 40ad9f4911 Add deep_sleep.allow YAML action (#3459) 2022-05-11 12:47:50 +12:00
Ruben De Smet 4116caff6a Implement allow_deep_sleep (#3282) 2022-05-11 11:44:52 +12:00
Otto Winter 0b69f72315 Enable api transport encryption for new projects (#3142)
* Enable api transport encryption for new projects

* Format
2022-05-11 11:38:05 +12:00
Maurice Makaay c569f5ddcf Code cleanup fixes for the number component (#3458)
Co-authored-by: Maurice Makaay <mmakaay1@xs4all.net>
2022-05-11 11:02:49 +12:00
Maurice Makaay 62f9e181e0 Code cleanup fixes for the select component (#3457)
Co-authored-by: Maurice Makaay <mmakaay1@xs4all.net>
2022-05-11 10:58:28 +12:00
Otto Winter 235a97ea10 Make retry scheduler efficient (#3225) 2022-05-11 07:54:00 +12:00
MFlasskamp e541ae400c Esp32c3 deepsleep fix (#3454) 2022-05-10 22:03:59 +12:00
Massimo Cetra 4822abde86 Fix BLE280 setup when the sensor is marked as failed. (#3396) 2022-05-10 22:03:40 +12:00
Jesse Hills b7e52812f8 Fix tests (#3455) 2022-05-10 22:02:58 +12:00
LuBeDa 69118120d9 added prev_frame for animation (#3427) 2022-05-10 21:56:29 +12:00
Dennis 7cba0c6fb0 Fix cover set position by force pushing position_id datapoint (simila… (#3435) 2022-05-10 21:42:31 +12:00
Felix Storm 5fac67ce15 CAN bus: on_frame remote_transmission_request (#3376) 2022-05-10 21:39:18 +12:00
Matthew Garrett 98c733108e PMSX003: Add support for specifying the update interval and spinning down (#3053)
Co-authored-by: Otto Winter <otto@otto-winter.com>
2022-05-10 21:35:43 +12:00
Martin 782186e13d extend scd4x (#3409)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-05-10 21:25:44 +12:00
George 4e1f6518e8 Delonghi Penguino PAC W120HP ir support (#3124) 2022-05-10 21:22:22 +12:00
Andre Lengwenus 53e0fe8e51 Add SML (Smart Message Language) platform for energy meters (#2396)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-05-10 21:05:49 +12:00
Martin 0e547390da add support for Sen5x sensor series (#3383)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-05-10 20:15:02 +12:00
Martin 86b52df839 tca9548a fix channel selection (#3417) 2022-05-10 17:17:55 +12:00
MFlasskamp d685fdf54a mask deprecated adc_gpio_init() for esp32-s2 (#3445) 2022-05-10 17:16:16 +12:00
Maurice Makaay d9caab4108 Number enhancement (#3429)
Co-authored-by: Maurice Makaay <mmakaay1@xs4all.net>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-05-10 16:58:56 +12:00
Maurice Makaay 44b68f140e Select enhancement (#3423)
Co-authored-by: Maurice Makaay <mmakaay1@xs4all.net>
2022-05-10 16:41:16 +12:00
Unai 3a3d97dfa7 Add SERIAL_JTAG/CDC logger option for ESP-IDF platform for ESP32-S2/S3/C3 (#3105)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-05-10 13:28:22 +12:00
MFlasskamp 47898b527c Esp32c3 deepsleep fix (#3433) 2022-05-09 20:32:14 +12:00
dependabot[bot] a35f36ad39 Bump pylint from 2.13.5 to 2.13.8 (#3432)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-09 20:28:21 +12:00
dependabot[bot] d13a397f8e Bump pyupgrade from 2.32.0 to 2.32.1 (#3452)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-09 19:44:54 +12:00
Jesse Hills df999723f8 Force using name substitution when adopting a device (#3451) 2022-05-09 19:43:09 +12:00
Jesse Hills 8236e840a7 Fix spi transfer with miso pin defined on espidf (#3450) 2022-05-09 19:24:27 +12:00
dependabot[bot] e5b3625f73 Bump click from 8.1.2 to 8.1.3 (#3426)
Bumps [click](https://github.com/pallets/click) from 8.1.2 to 8.1.3.
- [Release notes](https://github.com/pallets/click/releases)
- [Changelog](https://github.com/pallets/click/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/click/compare/8.1.2...8.1.3)

---
updated-dependencies:
- dependency-name: click
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-09 19:22:47 +12:00
Jesse Hills 2e4645310b Also rename yaml filename with rename command (#3447) 2022-05-09 19:16:46 +12:00
Ingo Theiss 50a32b387e Add ENS210 Humidity & Temperature sensor component (#2942)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-05-09 17:23:38 +12:00
rainero84 2059283707 Early pin init (#3439)
* Added early_pin_init configuration parameter for ESP8266 platform

* Added #include to core

* Updated test3.yaml to include early_pin_init parameter

Co-authored-by: Rainer Oellermann <ro@playplaycode.com>
2022-05-09 17:21:43 +12:00
Patrick van der Leer 8e3af515c9 Waveshare epaper 7in5 v2alt (#3276)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-05-09 17:17:36 +12:00
Paulus Schoutsen 6f88f0ea3f Bump dashboard to 20220508.0 (#3448) 2022-05-09 17:17:21 +12:00
Jens-Christian Skibakk d2f37cf3f9 Support for Arduino 2 and serial port on ESP32-S2 and ESP32-C3 (#3436) 2022-05-09 16:17:22 +12:00
Paulus Schoutsen 7c30d6254e Add rename command handler (#3443) 2022-05-09 13:53:34 +12:00
Jesse Hills 64fb39a653 Add help text to rename command (#3442) 2022-05-09 10:18:24 +12:00
Dan Jackson 91895aa70c Allow wifi output_power down to 8.5dB (#3405) 2022-05-03 19:09:06 +12:00
LuBeDa 68dfaf238b added RGB565 image type (#3229)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-04-27 08:41:10 +12:00
Trevor North ebf13a0ba0 Queue sensor publishes so we don't block for too long (#3422) 2022-04-27 07:51:22 +12:00
code-review-doctor 2bff9937b7 Fix issue probably-meant-fstring found at https://codereview.doctor (#3415) 2022-04-27 07:43:35 +12:00
Jesse Hills 256395c28d Add duration device class for sensors (#3421) 2022-04-26 21:02:08 +12:00
quentin9696 3346bc8bba feat: add openssh-client on docker image (#1681) (#3319)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-04-26 10:09:49 +12:00
Martin 6fe22a7e62 SPS30: Add fan action (#3410)
* Add fan action to SPS30

* add codeowner
2022-04-26 09:50:36 +12:00
Jesse Hills 757b98748b Add "esphome rename" command (#3403)
* Add "esphome rename" command

* Only open file once

* Update esphome/__main__.py

Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>

* Add final return

* Use match.group consistently

* Validate name characters

* Add whitespace to regex so it is only replacing exact match

* Validate yaml config file after manipulation

Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
2022-04-21 22:08:01 -07:00
I. Tomita 7a778f3f33 Add support for BL0939 (Sonoff Dual R3 V2 powermeter) (#3300) 2022-04-21 10:11:25 +12:00
Jesse Hills 993044c870 Merge pull request #3408 from esphome/bump-2022.4.0
2022.4.0
2022-04-21 07:42:58 +12:00
Jesse Hills a8c1b63edb Bump version to 2022.4.0 2022-04-20 17:06:08 +12:00
Jesse Hills db7d946e1b Merge branch 'beta' into bump-2022.4.0 2022-04-20 17:06:08 +12:00
Jesse Hills 41d9059a2f Merge pull request #3407 from esphome/bump-2022.4.0b4
2022.4.0b4
2022-04-20 16:55:11 +12:00
Jesse Hills e26e0d7c01 Bump version to 2022.4.0b4 2022-04-20 16:35:43 +12:00
Jesse Hills ad41c07a1f Dont require {} for wifi ap with defaults (#3404) 2022-04-20 16:35:42 +12:00
James Duke 9576d246ee Add support for Mopeka Pro+ Residential sensor (#3393)
* Add support for Pro+ Residential sensor (enum)

The Mopeka Pro+ Residential sensor is very similar to the Pro sensor, but includes a longer range antenna, and maybe hardware? The Pro+ identifies itself with 0x08 sensor type.

* Add logic to support Pro+ Residential sensor

* Fix formatting
2022-04-20 12:50:24 +12:00
parats15 988d3ea8ba Multi conf for Teleinfo component (#3401) 2022-04-20 12:46:55 +12:00
Jesse Hills 0767b92b62 Dont require {} for wifi ap with defaults (#3404) 2022-04-20 06:56:09 +12:00
Jesse Hills 5732f3b044 Merge pull request #3402 from esphome/bump-2022.4.0b3
2022.4.0b3
2022-04-19 15:31:05 +12:00
Jesse Hills 712115b6ce Bump version to 2022.4.0b3 2022-04-19 12:33:38 +12:00
rnauber 9283559c6b Shelly Dimmer: Delete obsolete LICENSE.txt (#3394) 2022-04-19 12:33:38 +12:00
Michel van de Wetering 6b393438e9 Fix power_delivered/produced_phase sensor deviceclass in DSMR (#3395) 2022-04-19 12:33:38 +12:00
rnauber 2064abe16d Shelly Dimmer: Delete obsolete LICENSE.txt (#3394) 2022-04-19 08:43:34 +12:00
Michel van de Wetering b605982f94 Fix power_delivered/produced_phase sensor deviceclass in DSMR (#3395) 2022-04-19 08:42:02 +12:00
Jesse Hills 343b9ab455 Merge pull request #3390 from esphome/bump-2022.4.0b2
2022.4.0b2
2022-04-14 15:37:31 +12:00
Jesse Hills dcb226b202 Bump version to 2022.4.0b2 2022-04-14 13:48:35 +12:00
Janez Troha 2243021b58 Allocate smaller amount of buffer for JSON (#3384) 2022-04-14 13:48:35 +12:00
rnauber d5134e88b1 Add support for Shelly Dimmer 2 (#2954)
Co-authored-by: Niclas Larsson <niclas@edgesystems.se>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
Co-authored-by: Jernej Kos <jernej@kos.mx>
Co-authored-by: Richard Nauber <richard@nauber.dev>
2022-04-14 13:48:35 +12:00
matthias882 c59adf612f Changes accuracy of single cell voltage (#3387) 2022-04-14 13:48:35 +12:00
Janez Troha 93b628d9a8 Allocate smaller amount of buffer for JSON (#3384) 2022-04-14 13:42:43 +12:00
Joe 6bac551d9f Add BedJet BLE climate component (#2452) 2022-04-14 13:16:13 +12:00
rnauber 70a35656e4 Add support for Shelly Dimmer 2 (#2954)
Co-authored-by: Niclas Larsson <niclas@edgesystems.se>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
Co-authored-by: Jernej Kos <jernej@kos.mx>
Co-authored-by: Richard Nauber <richard@nauber.dev>
2022-04-14 13:13:51 +12:00
Jesse Hills 047c18eac0 Add default object_id_generator for mqtt (#3389) 2022-04-14 11:25:31 +12:00
matthias882 b4a86ce6cf Changes accuracy of single cell voltage (#3387) 2022-04-14 09:36:16 +12:00
Jesse Hills a82d8ea0c3 Merge pull request #3381 from esphome/bump-2022.4.0b1
2022.4.0b1
2022-04-13 16:14:08 +12:00
Jesse Hills b778eed419 Bump version to 2022.5.0-dev 2022-04-13 13:42:28 +12:00
Jesse Hills ad57faa9a9 Bump version to 2022.4.0b1 2022-04-13 13:42:28 +12:00
Jesse Hills a9b5e8d036 Merge branch 'dev' into bump-2022.4.0b1 2022-04-13 13:42:27 +12:00
Jesse Hills 8be704e591 Allow specifying deep sleep wakup clock time (#3312) 2022-04-13 12:55:26 +12:00
Jesse Hills b622a8fa58 Move PN532OnTagTrigger to nfc::NfcOnTagTrigger (#3379) 2022-04-13 12:26:55 +12:00
Jesse Hills a519e5c475 Fix silent config errors (#3380) 2022-04-13 12:26:25 +12:00
Martin d620b6dd5e Refactor Sensirion Sensors (#3374)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-04-13 10:19:48 +12:00
Janez Troha 99335d986e Use correct http defines (#3378)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-04-13 10:14:21 +12:00
cvwillegen 7895cd92cd Remote base pronto receive (#2826)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-04-13 07:39:38 +12:00
anatoly-savchenkov 8b2c032da6 Add Sonoff D1 Dimmer support (#2775)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-04-12 17:03:32 +12:00
Jesse Hills da336247eb Add Xiaomi RTCGQ02LM - Mi Motion Sensor 2 (#3186) 2022-04-12 16:19:16 +12:00
andrewpc dabd27d4be Addition of Deep Sleep RTC pin definition for ESP32-S2 (#3303) 2022-04-12 12:45:54 +12:00
functionpointer fdda47db6e Add integration hydreon_rgxx for rain sensors by Hydreon (#2711)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-04-11 14:50:56 +12:00
Jesse Hills efa6fd03e5 Make home_assistant imported sensors internal by default (#3372) 2022-04-11 12:45:15 +12:00
rrooggiieerr 9e3e34acf5 Add cover toggle support to endstop cover (#3358) 2022-04-11 10:55:45 +12:00
calco88 a2d0c1bf18 Fix HM3301 AQI int8 overflow (#3361) 2022-04-11 10:14:53 +12:00
dependabot[bot] 7663716ae8 Bump pylint from 2.13.4 to 2.13.5 (#3363)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-11 09:23:47 +12:00
dependabot[bot] c2cacb3478 Bump voluptuous from 0.13.0 to 0.13.1 (#3364)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-11 09:23:13 +12:00
dependabot[bot] 84666b54b9 Bump pyupgrade from 2.31.1 to 2.32.0 (#3366)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-11 09:22:54 +12:00
RadekHvizdos 2b91c23bf3 Extend mcp3204 to support 8 channels (mcp3208 variant) (#3332) 2022-04-11 08:44:11 +12:00
Samuel Sieb 3297267a16 Fix SHTC3 sensor detection (#3365)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2022-04-11 08:42:31 +12:00
Keilin Bickar a9e653724c Add parameter to control i2c stop signal at endTransmission (#3370) 2022-04-11 08:38:29 +12:00
djwlindenaar 5e79a1f500 Implement newer RTU protocol of Growatt inverters (#3315)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
Co-authored-by: Daniel Lindenaar <daniel-git@lindenaar.eu>
2022-04-11 08:06:11 +12:00
Tim Smeets d4ff98680a Add support for Electrolux heatpump and bump arduino-heatpumpir version (#3353)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-04-08 08:04:00 +12:00
Jesse Hills ba8d255cb4 Allow on_value_range for sensor and number to be templated (#3359) 2022-04-05 22:06:36 +12:00
dependabot[bot] 06f4ad922c Bump black from 22.1.0 to 22.3.0 (#3357)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Otto Winter <otto@otto-winter.com>
2022-04-05 11:50:51 +02:00
dependabot[bot] bff06e448b Bump pyupgrade from 2.31.0 to 2.31.1 (#3292)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Otto Winter <otto@otto-winter.com>
2022-04-04 20:06:42 +02:00
dependabot[bot] d48ffa2913 Bump tzlocal from 4.1 to 4.2 (#3356)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-04 19:39:45 +02:00
dependabot[bot] d97c3a7e01 Bump voluptuous from 0.12.2 to 0.13.0 (#3355)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-04 19:37:35 +02:00
Otto Winter 0b1161f7ef Bump docker dependencies (#3354) 2022-04-04 19:21:43 +02:00
dependabot[bot] 061e1a471d Bump pytest from 7.0.1 to 7.1.1 (#3313)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-04 19:13:11 +02:00
dependabot[bot] a39d874600 Bump pytest-asyncio from 0.18.2 to 0.18.3 (#3335)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-04 19:13:06 +02:00
dependabot[bot] de96376565 Bump pylint from 2.12.2 to 2.13.4 (#3348)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-04 19:11:04 +02:00
dependabot[bot] c54c20ab3c Bump click from 8.0.4 to 8.1.2 (#3351)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-04 19:10:53 +02:00
Michiel van Turnhout 70fafa473b Tm1637 binarysensor (#2792)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-04-04 11:42:10 +12:00
Felix Storm 2e436eae6b CAN bus: support remote transmission request flag for canbus.send (#3193)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-04-04 11:15:51 +12:00
Andrew J.Swan fd7e861ff5 Added a function to load custom characters in LCD display (#3279)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-04-04 11:13:59 +12:00
Martin 792108686c Add mqtt for idf (#2930)
Co-authored-by: Flaviu Tamas <me@flaviutamas.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
Co-authored-by: Oxan van Leeuwen <oxan@oxanvanleeuwen.nl>
2022-04-04 11:07:20 +12:00
Branden Cash fa1b5117fd feat: support ble_client that use security w/o pin codes (#3320) 2022-04-04 09:35:48 +12:00
Adrián Panella b0bd9e0a34 protobuf: fix incomplete 64 bits implementation (#3341) 2022-04-04 08:38:44 +12:00
Guillermo Ruffino 05dc97099a New vscode schema gen (#3336) 2022-04-03 19:30:22 +12:00
Ian Reinhart Geiser 9de61fcf58 Define touchscreen support when in use. (#3296) 2022-04-01 16:46:39 +13:00
Jesse Hills fc7348d46d Merge pull request #3346 from esphome/bump-2022.3.2
2022.3.2
2022-03-30 13:28:58 +13:00
Jesse Hills 8be2456c7e Bump version to 2022.3.2 2022-03-30 08:15:50 +13:00
Jesse Hills bb5f7249a6 Actually increase request memory for json parsing (#3331) 2022-03-30 08:15:50 +13:00
Jesse Hills 7f7175b184 Publish custom data when modbus number lambda fills vector (#3295) 2022-03-29 22:22:11 +13:00
Dan Jackson cf5c640ae4 Change beginning of file comments to avoid creating doxygen tag for esphome namespace (#3314) 2022-03-29 22:05:38 +13:00
Jesse Hills 6b9371d105 Actually increase request memory for json parsing (#3331) 2022-03-28 17:04:25 +13:00
Otto Winter 9a82057303 Font allow using google fonts directly (#3243) 2022-03-28 12:07:48 +13:00
Stanislav Meduna 48584e94c4 Allow to set user defined characters on LCD (#3322) 2022-03-24 19:37:48 +13:00
Jesse Hills fc94a5d0ee Merge pull request #3324 from esphome/bump-2022.3.1
2022.3.1
2022-03-24 16:45:14 +13:00
dependabot[bot] d8024a5928 Bump esptool from 3.2 to 3.3 (#3327)
Bumps [esptool](https://github.com/espressif/esptool) from 3.2 to 3.3.
- [Release notes](https://github.com/espressif/esptool/releases)
- [Commits](https://github.com/espressif/esptool/compare/v3.2...v3.3)

---
updated-dependencies:
- dependency-name: esptool
  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>
2022-03-24 14:29:43 +13:00
H. Árkosi Róbert 2034ab4f6c increase delay for Ethernet module warm up (#3326) 2022-03-24 14:28:21 +13:00
Jesse Hills 24029cc918 Bump version to 2022.3.1 2022-03-23 12:26:02 +13:00
Jesse Hills 9a9d5964ee Add small delay before setting up app in safe mode (#3323) 2022-03-23 12:26:02 +13:00
Jesse Hills 4e4a512107 Reserve less memory for json (#3289) 2022-03-23 12:26:02 +13:00
Jesse Hills 0729ed538e Webserver utilize Component Iterator to not overload eventstream (#3310) 2022-03-23 12:26:01 +13:00
wysiwyng 24b75b7ed6 Fix WDT reset during dallas search algorithm (#3293) 2022-03-23 12:26:01 +13:00
Jesse Hills 58b70b42dd Add small delay before setting up app in safe mode (#3323) 2022-03-23 11:12:22 +13:00
Jesse Hills 1496bc1b07 Reserve less memory for json (#3289) 2022-03-23 09:46:25 +13:00
Jesse Hills bfbf88b2ea Webserver utilize Component Iterator to not overload eventstream (#3310) 2022-03-23 09:45:05 +13:00
wysiwyng e621b938e3 Fix WDT reset during dallas search algorithm (#3293) 2022-03-16 20:33:05 +01:00
Jesse Hills ec3618ecb8 Merge pull request #3304 from esphome/bump-2022.3.0
2022.3.0
2022-03-16 23:38:01 +13:00
Jesse Hills 792a24f38d Bump version to 2022.3.0 2022-03-16 22:32:24 +13:00
Jesse Hills 652e8a015b Merge branch 'beta' into bump-2022.3.0 2022-03-16 22:32:24 +13:00
Jesse Hills 59e6e798dd Merge pull request #3302 from esphome/bump-2022.3.0b2
2022.3.0b2
2022-03-16 15:38:32 +13:00
Jesse Hills e5c2dbc7ec Bump version to 2022.3.0b2 2022-03-16 14:06:00 +13:00
Jesse Hills 756f71c382 Allow custom register type for modbus number (#3202) 2022-03-16 14:06:00 +13:00
Jesse Hills b7535693fa Add helper overloads for hex print 16-bit (#3297) 2022-03-16 14:06:00 +13:00
stegm 06a3505698 Add optimistic config flag to modbus select. (#3267) 2022-03-16 14:06:00 +13:00
Jesse Hills 0372d17a11 Allow custom register type for modbus number (#3202) 2022-03-16 13:43:05 +13:00
Jesse Hills 4525588116 Add helper overloads for hex print 16-bit (#3297) 2022-03-16 13:35:37 +13:00
rbaron 68e957c147 Adds support for b-parasite's v2 BLE protocol (#3290) 2022-03-16 11:05:29 +13:00
andrewpc 99f5ed1461 Add support for QMP6988 Pressure sensor (#3192) 2022-03-15 08:09:17 +13:00
Rai-Rai 59f67796dc Fixed wrong comment (#3286) 2022-03-14 08:00:00 +13:00
stegm aafdfa933e Add optimistic config flag to modbus select. (#3267) 2022-03-10 08:40:43 +13:00
Otto Winter 3208c8ed1e Bump docker dependencies (#3281) 2022-03-09 13:48:02 +01:00
dependabot[bot] 6bf733e24e Bump click from 8.0.3 to 8.0.4 (#3248)
Bumps [click](https://github.com/pallets/click) from 8.0.3 to 8.0.4.
- [Release notes](https://github.com/pallets/click/releases)
- [Changelog](https://github.com/pallets/click/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/click/compare/8.0.3...8.0.4)

---
updated-dependencies:
- dependency-name: click
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-09 13:27:56 +01:00
dependabot[bot] 65d3e8fbfc Bump zeroconf from 0.38.3 to 0.38.4 (#3257)
Bumps [zeroconf](https://github.com/jstasiak/python-zeroconf) from 0.38.3 to 0.38.4.
- [Release notes](https://github.com/jstasiak/python-zeroconf/releases)
- [Commits](https://github.com/jstasiak/python-zeroconf/compare/0.38.3...0.38.4)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-09 13:27:33 +01:00
dependabot[bot] a29d65d47c Bump pytest-asyncio from 0.18.1 to 0.18.2 (#3262)
Bumps [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) from 0.18.1 to 0.18.2.
- [Release notes](https://github.com/pytest-dev/pytest-asyncio/releases)
- [Commits](https://github.com/pytest-dev/pytest-asyncio/compare/v0.18.1...v0.18.2)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-09 13:27:15 +01:00
Jesse Hills efa8f0730d Merge pull request #3278 from esphome/bump-2022.3.0b1
2022.3.0b1
2022-03-09 20:57:07 +13:00
Jesse Hills 0af1edefff Bump version to 2022.4.0-dev 2022-03-09 20:07:50 +13:00
Jesse Hills 023d26f521 Bump version to 2022.3.0b1 2022-03-09 20:07:50 +13:00
Jesse Hills 5068619f1b Merge branch 'dev' into bump-2022.3.0b1 2022-03-09 20:07:49 +13:00
wilberforce 5b2457af0b Add visual step/min/max for webserver climate (#3275) 2022-03-09 10:28:16 +13:00
Jesse Hills 900b4f1af9 Bump esphome-dashboard to 20220309.0 (#3277) 2022-03-09 10:27:54 +13:00
JasperPlant 4c22a98b0b Add entity_category_diagnostics to SGP30 baseline sensors (#3272) 2022-03-08 15:21:13 +13:00
wilberforce 3b8ca80900 Webserver v2 (#2688)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-03-08 15:02:24 +13:00
Jesse Hills 1ef6fd8fb0 Merge pull request #3261 from esphome/bump-2022.2.6
2022.2.6
2022-03-02 22:54:51 +13:00
Jesse Hills 942b0de7fd Bump version to 2022.2.6 2022-03-02 17:07:08 +13:00
Jesse Hills 859cca49d1 Only get free memory size from internal (#3259) 2022-03-02 17:07:08 +13:00
Jesse Hills dc6eff83ea Only get free memory size from internal (#3259) 2022-03-02 16:44:35 +13:00
Jesse Hills 38ff66debd Remove stray define (#3260) 2022-03-02 16:32:45 +13:00
Sean Brogan 1d2e0f74ea Add Mopeka BLE and Mopeka Pro Check BLE Sensor (#2618)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-03-01 11:30:33 +13:00
Jesse Hills 8f7ff25624 Merge pull request #3252 from esphome/bump-2022.2.5
2022.2.5
2022-02-24 07:28:56 +13:00
Jesse Hills 97aca8e54c Bump version to 2022.2.5 2022-02-23 11:20:48 +13:00
Nicholas Peters 95acf19067 Fix regression caused by TSL2591 auto gain (#3249) 2022-02-23 11:20:48 +13:00
Martin Weinelt 3d0899aa58 Respect ESPHOME_USE_SUBPROCESS in esp32 post_build script (#3246) 2022-02-23 11:20:48 +13:00
Jesse Hills bf60e40d0b Add optional display page for touchscreen binary sensors (#3247) 2022-02-23 11:05:53 +13:00
RubyBailey c9094ca537 Add sensor support: Honeywell ABP (SPI version) (#3164)
Co-authored-by: RubyBailey <ruby_bailey11@hotmail.com>
2022-02-22 11:22:30 +01:00
Jesse Hills 68b3fd6b8f Store platform as uppercase (#3251) 2022-02-22 13:54:23 +13:00
Nicholas Peters 9323b3a248 Fix regression caused by TSL2591 auto gain (#3249) 2022-02-22 13:53:24 +13:00
Jesse Hills b55e9329d9 Fix template button after abstract press_action (#3250) 2022-02-22 13:47:16 +13:00
Micha Nordmann a5b4105971 support for waveshare 7.50in-hd-b (#3239) 2022-02-22 07:35:04 +13:00
Arturo Casal d1feaa935d Add device support: MCP4728 (#3174)
* Added MCP4728 output component.

* Added tests to test1.yaml

* Added codeowners

* Lint fixes

* Implemented code review changes

* Lint fixes

* Added i2c communication check on setup()

* Fixed tests

* Lint fix

* Update esphome/components/mcp4728/mcp4728_output.cpp

Changed log function

Co-authored-by: Otto Winter <otto@otto-winter.com>

Co-authored-by: Otto Winter <otto@otto-winter.com>
2022-02-21 12:47:03 +01:00
Martin Weinelt 6919930aaa Respect ESPHOME_USE_SUBPROCESS in esp32 post_build script (#3246) 2022-02-21 14:05:13 +13:00
EdJoPaTo 69633826bb Implement send_first_at for exponential_moving_average (#3240) 2022-02-21 13:13:06 +13:00
Niorix 771162bfb1 light: add RESTORE_AND_OFF/RESTORE_AND_ON LightRestoreMode (#3238) 2022-02-21 12:52:14 +13:00
Fabian Affolter ba785e29e9 Add support for MPU-6886 (#3183) 2022-02-21 12:23:26 +13:00
Jesse Hills 138d6e505b Merge pull request #3245 from esphome/bump-2022.2.4
2022.2.4
2022-02-21 10:54:54 +13:00
Jesse Hills 2748e6ba29 Bump version to 2022.2.4 2022-02-21 10:17:25 +13:00
Jesse Hills dbd4e927d8 Fix fatal erroring in addon startup script (#3244) 2022-02-21 10:17:24 +13:00
Jesse Hills e73d47918f Fix lilygo touchscreen rotation (#3221) 2022-02-21 10:17:24 +13:00
Tyler Bules b881bc071e ESP32-C3 deep sleep fix (#3066) 2022-02-21 10:17:24 +13:00
Otto Winter 1d0395d1c7 Improve ESP8266 iram usage (#3223) 2022-02-21 10:17:24 +13:00
Otto Winter 616c787e37 Fix ESP8266 climate memaccess warning (#3226) 2022-02-21 10:17:24 +13:00
Otto Winter 0c4de2bc97 Publish NAN when dallas conversion failed (#3227) 2022-02-21 10:17:24 +13:00
Jesse Hills 2c7b104f4a Fix fatal erroring in addon startup script (#3244) 2022-02-21 10:01:00 +13:00
Jesse Hills 78951c197a Fix lilygo touchscreen rotation (#3221) 2022-02-21 09:58:53 +13:00
cstaahl 07c1cf7137 Pulse meter internal filter mode (#3082)
Co-authored-by: Paul Daumlechner <paul.daumlechner@live.de>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
Co-authored-by: Otto Winter <otto@otto-winter.com>
2022-02-21 09:32:35 +13:00
Otto Winter d26141151a Button code cleanup (#3242) 2022-02-21 09:17:51 +13:00
Otto Winter f59dbe4a88 Add copy integration (#3241) 2022-02-21 09:13:37 +13:00
Otto Winter 8dae7f8225 Bump esphome-dashboard from 20220209.0 to 20220219.0 (#3231) 2022-02-19 15:57:52 +01:00
Otto Winter 5811389891 BH1750 dynamically calculate options (#3214)
* BH1750 dynamically calculate options

* Fix tests

* Fix NAN

* Convert setup to new-style

* Add myself as codeowner
2022-02-19 15:49:20 +01:00
Otto Winter debcaf6fb7 Add ESP32C3 and ESP32S2 support to dashboard (#3152)
* Add ESP32C3 and ESP32S2 support to dashboard

* Format

* Fix tests
2022-02-19 15:47:50 +01:00
Tyler Bules b8d10a62c2 ESP32-C3 deep sleep fix (#3066) 2022-02-19 15:13:48 +01:00
Otto Winter d2b209234f Improve ESP8266 iram usage (#3223) 2022-02-19 15:09:17 +01:00
Otto Winter 34c9d8be50 Lint trailing whitespace (#3230) 2022-02-19 14:46:27 +01:00
Otto Winter ae57ad0c81 Fix warning in test1.yaml (#3228) 2022-02-19 14:42:54 +01:00
Otto Winter 0c1520dd9c Fix ESP8266 climate memaccess warning (#3226) 2022-02-19 14:11:45 +01:00
Otto Winter d594f43ebd Publish NAN when dallas conversion failed (#3227) 2022-02-19 14:11:01 +01:00
Oxan van Leeuwen 125c693e3f Add ESP32 variant config validator function (#3088)
* Add esp32_variant config validator function

* Drop unused is_esp32c3 function

Co-authored-by: Otto Winter <otto@otto-winter.com>
2022-02-19 11:41:34 +01:00
mknjc ad2f857e15 [miscale] Add flag to clear last impedance reading if the newly received reading only contains weight (#3132) 2022-02-19 10:59:53 +01:00
Peter Valkov e445d6aada Fix for api disconnect detection. (#2909)
Co-authored-by: Otto Winter <otto@otto-winter.com>
2022-02-19 10:36:19 +01:00
Arturo Casal 88fbb0ffbb Add sensor support: MAX44009 (#3125)
Co-authored-by: Otto Winter <otto@otto-winter.com>
2022-02-19 09:49:45 +01:00
Borys Pierov 231908fe9f Implement text_sensor based on ble_client (#3079)
Co-authored-by: Otto Winter <otto@otto-winter.com>
2022-02-19 09:45:32 +01:00
ImSorryButWho f137cc10f4 Remote magiquest protocol (#2963)
Co-authored-by: Aaron Hertz <aaron@rockforest.org>
Co-authored-by: Otto Winter <otto@otto-winter.com>
2022-02-18 22:22:41 +01:00
Jesse Hills c2f5ac9eba Merge pull request #3220 from esphome/bump-2022.2.3
2022.2.3
2022-02-18 12:06:19 +13:00
Jesse Hills 5764c988af Bump version to 2022.2.3 2022-02-18 11:51:56 +13:00
dependabot[bot] ccc2fbfd67 Bump platformio from 5.2.4 to 5.2.5 (#3188)
* Bump platformio from 5.2.4 to 5.2.5

Bumps [platformio](https://github.com/platformio/platformio) from 5.2.4 to 5.2.5.
- [Release notes](https://github.com/platformio/platformio/releases)
- [Changelog](https://github.com/platformio/platformio-core/blob/develop/HISTORY.rst)
- [Commits](https://github.com/platformio/platformio/commits)

---
updated-dependencies:
- dependency-name: platformio
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

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

* Update requirements.txt

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Otto Winter <otto@otto-winter.com>
2022-02-18 11:51:56 +13:00
Michael Labuschke 1a8f8adc2a Read all cell voltages from DalyBMS (#3203)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-02-18 11:00:03 +13:00
Jesse Hills 7a242bb4ed Binary Sensor codegen tidyup (#3217) 2022-02-18 10:39:59 +13:00
Jesse Hills 10b4adb8e6 Merge pull request #3219 from esphome/bump-2022.2.2
2022.2.2
2022-02-18 10:36:33 +13:00
Jesse Hills 3b8bb09ae3 Add class as first positional arg to sensor_schema (#3216) 2022-02-18 10:27:20 +13:00
Jesse Hills 83b7181bcb Bump version to 2022.2.2 2022-02-18 10:16:11 +13:00
Jesse Hills 8886b7e141 Add LONG LONG flag for arduinojson (#3212) 2022-02-18 10:16:11 +13:00
Otto Winter 7dcc4d030b Fix platformio docker version mismstch (#3215) 2022-02-18 10:16:11 +13:00
Stewart b9398897c1 Set entity-category to diagnostic for debug component (#3209)
Co-authored-by: Stewart Morgan <stewart@arnos-vale.net>
Co-authored-by: root <root@build.servers.arnos-vale.net>
2022-02-18 10:16:11 +13:00
Jesse Hills 140db85d21 Add LONG LONG flag for arduinojson (#3212) 2022-02-18 10:11:22 +13:00
mipa87 ccce4b19e8 Fix pm1006 polling component definition (#3210) 2022-02-17 21:47:31 +01:00
Adrián Panella 8cb9be7560 Analog threshold (#3190)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-02-18 09:14:10 +13:00
Otto Winter 953f0569fb Docker ha-addon switch to nginx-light (#3218) 2022-02-17 12:07:36 +01:00
Otto Winter 34c229fd33 Fix platformio docker version mismstch (#3215) 2022-02-17 11:56:14 +01:00
Roi Tagar 958ad0d750 HttpRequestComponent::get_string - avoid copy (#2988) 2022-02-17 17:03:54 +13:00
wilberforce 36ddd9dd69 Simplify captive portal to compressed single page (#2872) 2022-02-17 17:02:10 +13:00
Felix Storm 38259c96c9 CAN bus: support bit mask for on_frame can_id (#3196) 2022-02-17 17:00:31 +13:00
Felix Storm c054fb8a2c CAN bus: read all queued messages (#3194) 2022-02-17 17:00:14 +13:00
Otto Winter 5a0b8328d8 ESP8266 early init for pins (#3144) 2022-02-17 16:59:46 +13:00
Jesse Hills ffa19426d7 Remove redundant name from binary_sensor constructor (#3213) 2022-02-17 16:56:44 +13:00
Stewart c123804294 Set entity-category to diagnostic for debug component (#3209)
Co-authored-by: Stewart Morgan <stewart@arnos-vale.net>
Co-authored-by: root <root@build.servers.arnos-vale.net>
2022-02-17 13:53:26 +13:00
Otto Winter 4e24551b90 Docker move deps install into base (#3207) 2022-02-16 22:25:04 +01:00
Jesse Hills 657b1c60ae Merge pull request #3208 from esphome/bump-2022.2.1
2022.2.1
2022-02-17 08:00:12 +13:00
Jesse Hills dc54b17778 Bump version to 2022.2.1 2022-02-17 07:36:14 +13:00
Stewart 1fb214165b Fix missed ARDUINO_VERSION_CODE to USE_ARDUINO_VERSION_CODE changes (#3206)
Co-authored-by: Stewart Morgan <stewart@arnos-vale.net>
2022-02-17 07:36:14 +13:00
Stewart 51cb5da7f0 Fix missed ARDUINO_VERSION_CODE to USE_ARDUINO_VERSION_CODE changes (#3206)
Co-authored-by: Stewart Morgan <stewart@arnos-vale.net>
2022-02-16 16:50:10 +01:00
Jesse Hills 81b2fd78f5 Merge pull request #3204 from esphome/bump-2022.2.0
2022.2.0
2022-02-16 21:12:45 +13:00
Jesse Hills 69002fb1e6 Bump version to 2022.2.0 2022-02-16 20:13:14 +13:00
Jesse Hills 75332a752d Merge branch 'beta' into bump-2022.2.0 2022-02-16 20:13:13 +13:00
Jesse Hills b528f48417 Merge pull request #3201 from esphome/bump-2022.2.0b3
2022.2.0b3
2022-02-16 11:10:31 +13:00
Jesse Hills ec7a79049a Bump version to 2022.2.0b3 2022-02-16 09:45:05 +13:00
Jesse Hills 6ddad6b299 Update HA addon token (#3200) 2022-02-16 09:45:05 +13:00
Maurice Makaay 16dc7762f9 Fix strlcpy() uses to make long SSIDs and passwords work (#3199)
Co-authored-by: Maurice Makaay <mmakaay1@xs4all.net>
2022-02-16 09:45:05 +13:00
Jesse Hills 41f84447cc Update HA addon token (#3200) 2022-02-16 09:11:46 +13:00
Maurice Makaay ce073a704b Fix strlcpy() uses to make long SSIDs and passwords work (#3199)
Co-authored-by: Maurice Makaay <mmakaay1@xs4all.net>
2022-02-16 08:54:21 +13:00
Guillermo Ruffino 113232ebb6 add sim800l diagnostics (#3136) 2022-02-15 17:01:50 +13:00
Jesse Hills dc0ed8857f Merge pull request #3198 from esphome/bump-2022.2.0b2
2022.2.0b2
2022-02-15 12:48:34 +13:00
Jesse Hills bb6b77bd98 Bump version to 2022.2.0b2 2022-02-15 12:00:12 +13:00
Jesse Hills dcc80f9032 Allow framework version validator to be maximum version (#3197) 2022-02-15 12:00:12 +13:00
Otto Winter dd554bcdf4 Make generating combined binary output verbose (#3127) 2022-02-15 12:00:12 +13:00
Jesse Hills f376a39e55 Clamp rotary_encoder restored value to min and max (#3184) 2022-02-15 12:00:12 +13:00
dependabot[bot] 8dcc9d6b66 Bump aioesphomeapi from 10.8.1 to 10.8.2 (#3182) 2022-02-15 12:00:11 +13:00
Jesse Hills a13a1225b7 Allow framework version validator to be maximum version (#3197) 2022-02-15 11:57:47 +13:00
dependabot[bot] 0ec84be5da Bump pytest from 7.0.0 to 7.0.1 (#3189) 2022-02-11 22:23:06 +01:00
dependabot[bot] b1cefb7e3e Bump pytest-asyncio from 0.18.0 to 0.18.1 (#3187)
Bumps [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) from 0.18.0 to 0.18.1.
- [Release notes](https://github.com/pytest-dev/pytest-asyncio/releases)
- [Commits](https://github.com/pytest-dev/pytest-asyncio/compare/v0.18.0...v0.18.1)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-11 13:58:10 +01:00
dependabot[bot] cc0c1c08b9 Bump platformio from 5.2.4 to 5.2.5 (#3188)
* Bump platformio from 5.2.4 to 5.2.5

Bumps [platformio](https://github.com/platformio/platformio) from 5.2.4 to 5.2.5.
- [Release notes](https://github.com/platformio/platformio/releases)
- [Changelog](https://github.com/platformio/platformio-core/blob/develop/HISTORY.rst)
- [Commits](https://github.com/platformio/platformio/commits)

---
updated-dependencies:
- dependency-name: platformio
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

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

* Update requirements.txt

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Otto Winter <otto@otto-winter.com>
2022-02-11 13:57:46 +01:00
Otto Winter 3a67884451 Improve dallas timing (#3181)
* Improve dallas timing

* Format
2022-02-11 09:06:06 +01:00
Otto Winter 72e716cdf1 Make generating combined binary output verbose (#3127) 2022-02-11 21:06:00 +13:00
Jesse Hills 40e06c9819 Raise minimum python version to 3.8 (#3176) 2022-02-10 09:55:11 +01:00
Jesse Hills ad6c5ff11d Clamp rotary_encoder restored value to min and max (#3184) 2022-02-09 23:12:05 +01:00
dependabot[bot] 335512e232 Bump aioesphomeapi from 10.8.1 to 10.8.2 (#3182) 2022-02-09 20:13:02 +01:00
Otto Winter 2622e59b0b Remove spurious Zeroconf instance from api client (#3143) 2022-02-09 14:57:00 +01:00
Otto Winter 35e6a13cd1 Remove unused obj attribute from AssignmentExpression (#3145) 2022-02-09 14:56:42 +01:00
Jesse Hills a576c9f21f Merge pull request #3180 from esphome/bump-2022.2.0b1
2022.2.0b1
2022-02-10 00:20:46 +13:00
Jesse Hills b48490badc Bump version to 2022.3.0-dev 2022-02-09 23:47:36 +13:00
Jesse Hills 71a438e2cb Bump version to 2022.2.0b1 2022-02-09 23:47:36 +13:00
Jesse Hills 272d6f2a8b Merge branch 'dev' into bump-2022.2.0b1 2022-02-09 23:47:36 +13:00
Jesse Hills 5c22065135 Change most references from hassio to ha-addon (#3178) 2022-02-09 23:46:20 +13:00
Borys Pierov e7dd6c52ac Allow to set manufacturer data for BLEAdvertising (#3179) 2022-02-09 23:29:32 +13:00
dependabot[bot] 3bf042dce9 Bump pytest-asyncio from 0.17.2 to 0.18.0 (#3168)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-09 12:57:12 +13:00
Jesse Hills 09ed1aed93 Merge pull request #3177 from esphome/bump-2022.1.4
2022.1.4
2022-02-09 12:42:47 +13:00
Jesse Hills 53d3718028 Bump version to 2022.1.4 2022-02-09 11:54:41 +13:00
Jesse Hills 2b5dce5232 Try fix canbus config validation (#3173) 2022-02-09 11:54:40 +13:00
Otto Winter 9ad84150aa Enable mDNS during OTA safe mode (#3146) 2022-02-09 11:54:40 +13:00
dependabot[bot] 64f798d4b2 Bump pytest from 6.2.5 to 7.0.0 (#3163)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-09 11:42:44 +13:00
Jesse Hills f43e04e15a Try fix canbus config validation (#3173) 2022-02-09 11:42:00 +13:00
Jesse Hills 88d72f8c9a Fix files CI after merging (#3175) 2022-02-09 08:04:44 +13:00
Andrej Komelj 9826726a72 Implement MQTT discovery object_id generator (#3114) 2022-02-08 22:58:38 +13:00
Jesse Hills c66d0550e8 Inkplate 6 PLUS (#3013) 2022-02-08 22:56:56 +13:00
mckaymatthew 4aeacfd16e Add max9611 High Side Current Shunt ADC (#2705)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-02-08 22:56:40 +13:00
stegm 58fa63ad88 Add Select for modbus (#3032)
Co-authored-by: Oxan van Leeuwen <oxan@oxanvanleeuwen.nl>
2022-02-08 22:27:22 +13:00
Jesse Hills 94f944dc9c Add Lilygo t5 4.7 Touchscreen (#3084) 2022-02-08 21:50:25 +13:00
Ashton Kemerling 116ddbdd01 Add require response option for BLE binary output (#3091) 2022-02-08 21:30:31 +13:00
Jesse Hills 1c0697b5d4 Dont warn on nonnull comparisons (#3123) 2022-02-08 21:28:12 +13:00
Otto Winter 434ca47ea0 Enable mDNS during OTA safe mode (#3146) 2022-02-08 21:21:52 +13:00
functionpointer 397ef72b16 MLX90393 three-axis magnetometer (#2770)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-02-08 20:42:11 +13:00
Jonas Bergler 7ca9245735 wifi_info, reduce polling interval (#3165)
Co-authored-by: Jonas Bergler <jbergler@meraki.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-02-08 20:27:39 +13:00
Jesse Hills 69856286e8 Text sensor schema generator similar to sensor (#3172) 2022-02-08 17:23:45 +13:00
Jeff Eberl ad43d6a5bc Added RadonEye RD200 Component (#3119)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-02-08 16:32:37 +13:00
mknjc 1e5004f495 [debug] Refactor debug sensors to use the normal sensor model. (#3162) 2022-02-08 12:45:27 +13:00
Otto Winter 253161d3d0 Fix copy_file_if_changed src permissions copied too (#3161) 2022-02-07 21:26:16 +01:00
Jesse Hills ab47e201c7 Bump improv library to 1.2.1 (#3160) 2022-02-04 19:15:00 +13:00
Samuel Sieb 42984fa72a Handle Tuya multi-datapoint messages (#3159)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2022-02-04 15:50:42 +13:00
Franck Nijhof e7864a28a1 Add device class support to Switch (#3012)
Co-authored-by: Oxan van Leeuwen <oxan@oxanvanleeuwen.nl>
2022-02-04 09:04:48 +13:00
Keilin Bickar 21803607e7 Add new Lock core component (#2958)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-02-04 07:24:31 +13:00
Jesse Hills c0523590b4 Merge pull request #3154 from esphome/bump-2022.1.3
2022.1.3
2022-02-03 07:17:52 +13:00
Jesse Hills c7f091ab10 Bump version to 2022.1.3 2022-02-02 22:16:24 +13:00
Jesse Hills 7479e0aada Fix backwards string case helpers (#3126) 2022-02-02 22:16:16 +13:00
Otto Winter 62b366a5ec Fix ESP32C3 toolchain requires stdarg import in helpers (#3151) 2022-02-01 13:05:59 +01:00
dependabot[bot] 2b39988707 Bump black from 21.12b0 to 22.1.0 (#3147)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Otto winter <otto@otto-winter.com>
2022-02-01 10:26:37 +01:00
Otto Winter f9e7291050 Bump pre-commit flake8 from 3.8.4 to 4.0.1 (#3149) 2022-02-01 10:22:43 +01:00
Otto Winter 4de642ff28 Bump esp-idf framework version from 4.3.0 to 4.3.2 (#3120) 2022-01-31 07:59:56 +01:00
Otto Winter 0384efcfc2 Disable platformio ldf for build (#3130) 2022-01-31 14:27:10 +13:00
Jesse Hills bf91443f38 Improv_serial scan and send wifi networks list (#3116) 2022-01-31 11:08:20 +13:00
Jesse Hills 4a5970b4af Fix backwards string case helpers (#3126) 2022-01-31 10:58:27 +13:00
dependabot[bot] e3fd68c849 Bump pytest-mock from 3.6.1 to 3.7.0 (#3128) 2022-01-29 13:27:41 +01:00
Otto Winter df0de2fc2d Bump docker dependencies (#3131) 2022-01-29 13:04:15 +01:00
Matt Hamilton 0c3568fad5 Add support for Waveshare 7.5in-bv2 (#3121) 2022-01-29 00:37:47 +13:00
Oxan van Leeuwen 976f5d91ed Logically group and document helper functions (#3112) 2022-01-27 20:35:42 +13:00
drug123 0f3d4d9a47 Add Xiaomi MHOC303 sensor e-ink clock (#3115) 2022-01-27 12:54:29 +13:00
Otto Winter ad1f4429c9 Fix lint for TSL2591 (#3118) 2022-01-26 13:50:43 +01:00
Martin 7590d5eacb set adc width to 13 bits for esp32-s2 (#3117) 2022-01-26 13:33:59 +01:00
Nicholas Peters c5974b8833 TSL2591 automatic gain control (#3071) 2022-01-26 22:48:51 +13:00
Otto Winter 511c8de6f3 ESP8266 Set recommended framework to 3.0.2 (#2606) 2022-01-26 22:41:57 +13:00
Wouter van der Wal a718ac7ee0 Add qr code support for displays (#2952)
Co-authored-by: Oxan van Leeuwen <oxan@oxanvanleeuwen.nl>
2022-01-26 22:20:45 +13:00
Jesse Hills ef832becf1 Create base touchscreen component and refactor ektf2232 (#3083)
Co-authored-by: Oxan van Leeuwen <oxan@oxanvanleeuwen.nl>
2022-01-26 16:26:46 +13:00
micronen 3a62455948 Add Heap Sensors - free/max block/fragmentation (#1578)
Co-authored-by: Oxan van Leeuwen <oxan@oxanvanleeuwen.nl>
Co-authored-by: Otto winter <otto@otto-winter.com>
2022-01-25 19:18:41 +01:00
Zebble 297824e2d7 Add support for additional colors on GROW R503 (#3087) 2022-01-25 17:18:36 +01:00
Jimmy Hedman d92f297bc0 Add IPv6 support for ESP-IDF framework (#2953)
Co-authored-by: Oxan van Leeuwen <oxan@oxanvanleeuwen.nl>
2022-01-25 09:55:33 +01:00
guillempages 7a0827e3d0 Configurable HTTP redirect following (#3100)
Co-authored-by: Oxan van Leeuwen <oxan@oxanvanleeuwen.nl>
2022-01-25 09:53:22 +01:00
Joshua Spence ef256a64b8 Fix config merging with null (#3113) 2022-01-25 09:24:59 +01:00
Dav-id 1de941e837 Esp32cam full control (#3090) 2022-01-25 11:53:47 +13:00
Joshua Spence 28b65cb810 Perform merges when substituting dict keys (#3062) 2022-01-25 11:46:42 +13:00
Martin 6ff3942e8b [TCS34725] remove duplicated endian conversion (#3037)
Co-authored-by: Oxan van Leeuwen <oxan@oxanvanleeuwen.nl>
2022-01-25 11:41:14 +13:00
Rebbe Pod ef5d959788 Add increment_day function to ESPTime (#2955) 2022-01-24 21:54:46 +01:00
Oxan van Leeuwen 6a2c58fcc0 Implement output button (#3109) 2022-01-25 09:30:48 +13:00
Oxan van Leeuwen 4e6bdb31ac Make CallbackManager invocable (#3089) 2022-01-25 08:57:26 +13:00
Oxan van Leeuwen 80d03a631e Force braces around multi-line statements (#3094)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-01-25 08:56:36 +13:00
Martin 6b27f2d2cf Remove unused polling_component_schema from modbus number (#3108) 2022-01-25 08:44:20 +13:00
dependabot[bot] 7cb6729fa7 Bump aioesphomeapi from 10.8.0 to 10.8.1 (#3110)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-25 08:37:35 +13:00
Oxan van Leeuwen 2f46267994 Add cv.require_esphome_version helper (#3103) 2022-01-24 20:10:27 +01:00
Oxan van Leeuwen cdda648360 Generate ARDUINO_VERSION_CODE in Python code (#3101)
Co-authored-by: Otto winter <otto@otto-winter.com>
2022-01-24 10:34:34 +01:00
Oxan van Leeuwen f2d677d51a Fix path to extra_scripts in platformio.ini (#3093) 2022-01-24 16:03:34 +13:00
Oxan van Leeuwen c2ee0f0864 Rename WEBSERVER_PORT define to USE_WEBSERVER_PORT (#3102) 2022-01-24 00:34:38 +01:00
Oxan van Leeuwen 2a84db7f85 Refactor fan platform to resemble climate/cover platforms (#2848)
Co-authored-by: Oxan van Leeuwen <oxan@oxanvanleeuwen.nl>
Co-authored-by: rob-deutsch <robzyb+altgithub@gmail.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-01-23 22:21:54 +13:00
VitaliyKurokhtin 8187a4bce9 Command retain option for MQTT component (#3078) 2022-01-23 21:05:37 +13:00
Oxan van Leeuwen 97681d142e Enable readability-redundant-access-specifiers check (#3096)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-01-23 20:47:22 +13:00
Oxan van Leeuwen b2430097f2 Enable readability-named-parameter check (#3098)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2022-01-23 20:39:07 +13:00
Oxan van Leeuwen 7da12a878f Enable readability-redundant-member-init check (#3097) 2022-01-23 20:34:43 +13:00
Oxan van Leeuwen a31700e16f Enable readability-qualified-auto check (#3095) 2022-01-23 20:29:58 +13:00
Oxan van Leeuwen 7854522792 Enable readability-const-return-type check (#3099) 2022-01-23 20:28:00 +13:00
Pavel Skuratovich a6a9ebfde2 slow_pwm: allow to restart a cycle on state change (#3004)
Co-authored-by: Oxan van Leeuwen <oxan@oxanvanleeuwen.nl>
2022-01-22 23:08:55 +01:00
Plácido Revilla c6cbe2748e Set the wrapped single light in light partition to internal (#3092) 2022-01-22 21:04:36 +01:00
Joshua Spence f9a7f00843 Add restore_mode to fan component (#3051) 2022-01-22 20:41:58 +01:00
William Charlton f0b183a552 Wake-on-LAN button (#3030)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
Co-authored-by: William Charlton <will.charlton1@icloud.com>
2022-01-23 00:13:46 +13:00
Jesse Hills 338ada5c9f Allow multiple configs for cd74hc4067 (#3085) 2022-01-22 19:33:15 +13:00
Jimmy Hedman ef88f9923f Implement IPv6 sockets for lwIP (#3015)
Co-authored-by: Oxan van Leeuwen <oxan@oxanvanleeuwen.nl>
2022-01-21 10:08:54 +01:00
Jesse Hills 6f8c7d9ec4 Add ektf2232 touchscreen support (#3027) 2022-01-21 15:45:49 +13:00
dependabot[bot] ec769ccf72 Bump aioesphomeapi from 10.6.0 to 10.8.0 (#3081)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-21 00:09:12 +01:00
Jesse Hills 045952939e Support simple transparent pngs for display (#3035) 2022-01-21 11:16:18 +13:00
Jesse Hills 1c51cac5ba Add initial_run to regular lambda light effect (#3059) 2022-01-21 11:09:07 +13:00
buxtronix ea11462e1e AM43: autoload "sensor" to avoid compile errors (#3077) 2022-01-20 13:33:42 +01:00
Otto Winter 62f9736b1d API: Expect a name for connections (#2533) 2022-01-20 12:03:32 +01:00
Jesse Hills 1f8a1f0046 Bump improv library version (#3072) 2022-01-20 15:21:44 +13:00
cwitting 172507acb5 Fix calibration parameter for bme680 humidity calculation (#3069) 2022-01-20 10:53:52 +13:00
Martin 434ab65c16 [modbus_controller] fix incorrect start address for number write (#3073) 2022-01-20 09:19:24 +13:00
Jesse Hills cb5f793ede Add *.py.script files to distributions (#3074) 2022-01-20 08:33:13 +13:00
Oxan van Leeuwen 737188ae50 Fail hard if no random bytes available for encryption (#3067) 2022-01-18 14:29:57 +13:00
dependabot[bot] db21731b14 Bump pytest-asyncio from 0.17.0 to 0.17.2 (#3064)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-18 00:19:08 +01:00
Martin cdb4fa2487 [modbus_controller] add missing skip_updates (#3063) 2022-01-18 09:05:13 +13:00
Paulus Schoutsen 514204f0d4 bump dashboard to 20220116.0 (#3061) 2022-01-18 08:44:18 +13:00
Jesse Hills 45ac577c4d Add number setting to web_server/rest_api (#3055) 2022-01-17 12:31:44 +13:00
Oxan van Leeuwen 09402fdb22 Fix argument order in gitpod config file (#3058) 2022-01-16 23:40:27 +01:00
Oxan van Leeuwen 89e7448007 Remove deprecated attribute from virtual entity methods (#3056) 2022-01-16 23:40:15 +01:00
dependabot[bot] 1ea6f957bc Bump pytest-asyncio from 0.16.0 to 0.17.0 (#3047)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-16 23:19:21 +01:00
Oxan van Leeuwen f44fca0a4b Rename post_build scripts to fix codeowners script (#3057) 2022-01-17 11:15:11 +13:00
Ohad Lutzky 52d2f62a57 Disable caching for binary download (#3054) 2022-01-17 11:14:45 +13:00
Paulus Schoutsen 2a8668ea60 Bump dashboard to 20220113.2 (#3041) 2022-01-12 23:22:19 -08:00
Paulus Schoutsen cc0d433621 Add factory to download name (#3040) 2022-01-13 19:35:30 +13:00
Jesse Hills 1fe89fb364 Bump version to 2022.2.0-dev 2022-01-13 11:02:08 +13:00
1101 changed files with 47659 additions and 10911 deletions
+4 -6
View File
@@ -68,8 +68,6 @@ Checks: >-
-modernize-use-nodiscard,
-mpi-*,
-objc-*,
-readability-braces-around-statements,
-readability-const-return-type,
-readability-convert-member-functions-to-static,
-readability-else-after-return,
-readability-function-cognitive-complexity,
@@ -77,10 +75,6 @@ Checks: >-
-readability-isolate-declaration,
-readability-magic-numbers,
-readability-make-member-function-const,
-readability-named-parameter,
-readability-qualified-auto,
-readability-redundant-access-specifiers,
-readability-redundant-member-init,
-readability-redundant-string-init,
-readability-uppercase-literal-suffix,
-readability-use-anyofallof,
@@ -114,6 +108,8 @@ CheckOptions:
value: 'make_unique'
- key: modernize-make-unique.MakeSmartPtrFunctionHeader
value: 'esphome/core/helpers.h'
- key: readability-braces-around-statements.ShortStatementLines
value: 2
- key: readability-identifier-naming.LocalVariableCase
value: 'lower_case'
- key: readability-identifier-naming.ClassCase
@@ -160,3 +156,5 @@ CheckOptions:
value: 'lower_case'
- key: readability-identifier-naming.VirtualMethodSuffix
value: ''
- key: readability-qualified-auto.AddConstToQualified
value: 0
+1 -2
View File
@@ -25,10 +25,9 @@ indent_size = 2
[*.{yaml,yml}]
indent_style = space
indent_size = 2
quote_type = single
quote_type = double
# JSON
[*.json]
indent_style = space
indent_size = 2
+1
View File
@@ -1,3 +1,4 @@
---
# These are supported funding model platforms
custom: https://www.nabucasa.com
+6 -3
View File
@@ -1,3 +1,4 @@
---
blank_issues_enabled: false
contact_links:
- name: Issue Tracker
@@ -5,8 +6,10 @@ contact_links:
about: Please create bug reports in the dedicated issue tracker.
- name: Feature Request Tracker
url: https://github.com/esphome/feature-requests
about: Please create feature requests in the dedicated feature request tracker.
about: |
Please create feature requests in the dedicated feature request tracker.
- name: Frequently Asked Question
url: https://esphome.io/guides/faq.html
about: Please view the FAQ for common questions and what to include in a bug report.
about: |
Please view the FAQ for common questions and what
to include in a bug report.
+2 -2
View File
@@ -1,4 +1,4 @@
# What does this implement/fix?
# What does this implement/fix?
Quick description and explanation of changes
@@ -35,6 +35,6 @@ Quick description and explanation of changes
## Checklist:
- [ ] The code change is tested and works locally.
- [ ] Tests have been added to verify that the new code works (under `tests/` folder).
If user exposed functionality or configuration variables are added/changed:
- [ ] Documentation added/updated in [esphome-docs](https://github.com/esphome/esphome-docs).
+8 -2
View File
@@ -1,9 +1,15 @@
---
version: 2
updates:
- package-ecosystem: "pip"
- package-ecosystem: pip
directory: "/"
schedule:
interval: "daily"
interval: daily
ignore:
# Hypotehsis is only used for testing and is updated quite often
- dependency-name: hypothesis
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10
+29 -27
View File
@@ -1,21 +1,23 @@
---
name: CI for docker images
# Only run when docker paths change
# yamllint disable-line rule:truthy
on:
push:
branches: [dev, beta, release]
paths:
- 'docker/**'
- '.github/workflows/**'
- 'requirements*.txt'
- 'platformio.ini'
- "docker/**"
- ".github/workflows/**"
- "requirements*.txt"
- "platformio.ini"
pull_request:
paths:
- 'docker/**'
- '.github/workflows/**'
- 'requirements*.txt'
- 'platformio.ini'
- "docker/**"
- ".github/workflows/**"
- "requirements*.txt"
- "platformio.ini"
permissions:
contents: read
@@ -30,24 +32,24 @@ jobs:
arch: [amd64, armv7, aarch64]
build_type: ["ha-addon", "docker", "lint"]
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.9"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set TAG
run: |
echo "TAG=check" >> $GITHUB_ENV
- name: Set TAG
run: |
echo "TAG=check" >> $GITHUB_ENV
- name: Run build
run: |
docker/build.py \
--tag "${TAG}" \
--arch "${{ matrix.arch }}" \
--build-type "${{ matrix.build_type }}" \
build
- name: Run build
run: |
docker/build.py \
--tag "${TAG}" \
--arch "${{ matrix.arch }}" \
--build-type "${{ matrix.build_type }}" \
build
+24 -9
View File
@@ -1,5 +1,7 @@
---
name: CI
# yamllint disable-line rule:truthy
on:
push:
branches: [dev, beta, release]
@@ -10,6 +12,7 @@ permissions:
contents: read
concurrency:
# yamllint disable-line rule:line-length
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
@@ -73,24 +76,28 @@ jobs:
name: Run script/clang-tidy for ESP32 IDF
options: --environment esp32-idf-tidy --grep USE_ESP_IDF
pio_cache_key: tidyesp32-idf
- id: yamllint
name: Run yamllint
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v2
uses: actions/setup-python@v4
id: python
with:
python-version: '3.7'
python-version: "3.8"
- name: Cache virtualenv
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: .venv
# yamllint disable-line rule:line-length
key: venv-${{ steps.python.outputs.python-version }}-${{ hashFiles('requirements*.txt') }}
restore-keys: |
venv-${{ steps.python.outputs.python-version }}-
- name: Set up virtualenv
# yamllint disable rule:line-length
run: |
python -m venv .venv
source .venv/bin/activate
@@ -99,12 +106,14 @@ jobs:
pip install -e .
echo "$GITHUB_WORKSPACE/.venv/bin" >> $GITHUB_PATH
echo "VIRTUAL_ENV=$GITHUB_WORKSPACE/.venv" >> $GITHUB_ENV
# yamllint enable rule:line-length
# Use per check platformio cache because checks use different parts
- name: Cache platformio
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: ~/.platformio
# yamllint disable-line rule:line-length
key: platformio-${{ matrix.pio_cache_key }}-${{ hashFiles('platformio.ini') }}
if: matrix.id == 'test' || matrix.id == 'clang-tidy'
@@ -131,7 +140,7 @@ jobs:
if: matrix.id == 'ci-custom'
- name: Lint Python
run: script/lint-python
run: script/lint-python -a
if: matrix.id == 'lint-python'
- run: esphome compile ${{ matrix.file }}
@@ -145,8 +154,9 @@ jobs:
pytest -vv --tb=native tests
if: matrix.id == 'pytest'
# Also run git-diff-index so that the step is marked as failed on formatting errors,
# since clang-format doesn't do anything but change files if -i is passed.
# Also run git-diff-index so that the step is marked as failed on
# formatting errors, since clang-format doesn't do anything but
# change files if -i is passed.
- name: Run clang-format
run: |
script/clang-format -i
@@ -161,6 +171,11 @@ jobs:
# Also cache libdeps, store them in a ~/.platformio subfolder
PLATFORMIO_LIBDEPS_DIR: ~/.platformio/libdeps
- name: Run yamllint
if: matrix.id == 'yamllint'
uses: frenck/action-yamllint@v1.3.0
- name: Suggested changes
run: script/ci-suggest-changes
if: always() && (matrix.id == 'clang-tidy' || matrix.id == 'clang-format')
# yamllint disable-line rule:line-length
if: always() && (matrix.id == 'clang-tidy' || matrix.id == 'clang-format' || matrix.id == 'lint-python')
+3 -1
View File
@@ -1,8 +1,10 @@
---
name: Lock
# yamllint disable-line rule:truthy
on:
schedule:
- cron: '30 0 * * *'
- cron: "30 0 * * *"
workflow_dispatch:
permissions:
+61 -55
View File
@@ -1,5 +1,7 @@
---
name: Publish Release
# yamllint disable-line rule:truthy
on:
workflow_dispatch:
release:
@@ -17,9 +19,10 @@ jobs:
outputs:
tag: ${{ steps.tag.outputs.tag }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Get tag
id: tag
# yamllint disable rule:line-length
run: |
if [[ "$GITHUB_EVENT_NAME" = "release" ]]; then
TAG="${GITHUB_REF#refs/tags/}"
@@ -29,17 +32,18 @@ jobs:
TAG="${TAG}${today}"
fi
echo "::set-output name=tag::${TAG}"
# yamllint enable rule:line-length
deploy-pypi:
name: Build and publish to PyPi
if: github.repository == 'esphome/esphome' && github.event_name == 'release'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v1
uses: actions/setup-python@v4
with:
python-version: '3.x'
python-version: "3.x"
- name: Set up python environment
run: |
script/setup
@@ -65,37 +69,37 @@ jobs:
arch: [amd64, armv7, aarch64]
build_type: ["ha-addon", "docker", "lint"]
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.9'
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.9"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Log in to docker hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Log in to the GitHub container registry
uses: docker/login-action@v1
with:
- name: Log in to docker hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Log in to the GitHub container registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
run: |
docker/build.py \
--tag "${{ needs.init.outputs.tag }}" \
--arch "${{ matrix.arch }}" \
--build-type "${{ matrix.build_type }}" \
build \
--push
- name: Build and push
run: |
docker/build.py \
--tag "${{ needs.init.outputs.tag }}" \
--arch "${{ matrix.arch }}" \
--build-type "${{ matrix.build_type }}" \
build \
--push
deploy-docker-manifest:
if: github.repository == 'esphome/esphome'
@@ -108,47 +112,49 @@ jobs:
matrix:
build_type: ["ha-addon", "docker", "lint"]
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: Enable experimental manifest support
run: |
mkdir -p ~/.docker
echo "{\"experimental\": \"enabled\"}" > ~/.docker/config.json
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.9"
- name: Enable experimental manifest support
run: |
mkdir -p ~/.docker
echo "{\"experimental\": \"enabled\"}" > ~/.docker/config.json
- name: Log in to docker hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Log in to the GitHub container registry
uses: docker/login-action@v1
with:
- name: Log in to docker hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Log in to the GitHub container registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Run manifest
run: |
docker/build.py \
--tag "${{ needs.init.outputs.tag }}" \
--build-type "${{ matrix.build_type }}" \
manifest
- name: Run manifest
run: |
docker/build.py \
--tag "${{ needs.init.outputs.tag }}" \
--build-type "${{ matrix.build_type }}" \
manifest
deploy-hassio-repo:
deploy-ha-addon-repo:
if: github.repository == 'esphome/esphome' && github.event_name == 'release'
runs-on: ubuntu-latest
needs: [deploy-docker]
steps:
- env:
TOKEN: ${{ secrets.DEPLOY_HASSIO_TOKEN }}
TOKEN: ${{ secrets.DEPLOY_HA_ADDON_REPO_TOKEN }}
# yamllint disable rule:line-length
run: |
TAG="${GITHUB_REF#refs/tags/}"
curl \
-u ":$TOKEN" \
-X POST \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/esphome/hassio/actions/workflows/bump-version.yml/dispatches \
https://api.github.com/repos/esphome/home-assistant-addon/actions/workflows/bump-version.yml/dispatches \
-d "{\"ref\":\"main\",\"inputs\":{\"version\":\"$TAG\"}}"
# yamllint enable rule:line-length
+7 -4
View File
@@ -1,8 +1,10 @@
---
name: Stale
# yamllint disable-line rule:truthy
on:
schedule:
- cron: '30 0 * * *'
- cron: "30 0 * * *"
workflow_dispatch:
permissions:
@@ -16,7 +18,7 @@ jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v4
- uses: actions/stale@v5
with:
days-before-pr-stale: 90
days-before-pr-close: 7
@@ -31,11 +33,12 @@ jobs:
and will be closed if no further activity occurs within 7 days.
Thank you for your contributions.
# Use stale to automatically close issues with a reference to the issue tracker
# Use stale to automatically close issues with a
# reference to the issue tracker
close-issues:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v4
- uses: actions/stale@v5
with:
days-before-pr-stale: -1
days-before-pr-close: -1
+1
View File
@@ -77,6 +77,7 @@ venv/
ENV/
env.bak/
venv.bak/
venv-*/
# mypy
.mypy_cache/
+6 -4
View File
@@ -1,6 +1,8 @@
---
ports:
- port: 6052
onOpen: open-preview
- port: 6052
onOpen: open-preview
tasks:
- before: pyenv local $(pyenv version | grep '^3\.' | cut -d ' ' -f 1) && script/setup
command: python -m esphome config dashboard
# yamllint disable-line rule:line-length
- before: pyenv local $(pyenv version | grep '^3\.' | cut -d ' ' -f 1) && script/setup
command: python -m esphome dashboard config
+13 -7
View File
@@ -1,16 +1,17 @@
---
# 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: 20.8b1
rev: 22.6.0
hooks:
- id: black
args:
- --safe
- --quiet
files: ^((esphome|script|tests)/.+)?[^/]+\.py$
- id: black
args:
- --safe
- --quiet
files: ^((esphome|script|tests)/.+)?[^/]+\.py$
- repo: https://gitlab.com/pycqa/flake8
rev: 3.8.4
rev: 4.0.1
hooks:
- id: flake8
additional_dependencies:
@@ -25,3 +26,8 @@ repos:
- --branch=dev
- --branch=release
- --branch=beta
- repo: https://github.com/asottile/pyupgrade
rev: v2.37.3
hooks:
- id: pyupgrade
args: [--py38-plus]
+3
View File
@@ -0,0 +1,3 @@
---
ignore: |
venv/
+59 -2
View File
@@ -19,6 +19,7 @@ esphome/components/airthings_wave_mini/* @ncareau
esphome/components/airthings_wave_plus/* @jeromelaban
esphome/components/am43/* @buxtronix
esphome/components/am43/cover/* @buxtronix
esphome/components/analog_threshold/* @ianchi
esphome/components/animation/* @syndlex
esphome/components/anova/* @buxtronix
esphome/components/api/* @OttoWinter
@@ -27,9 +28,16 @@ esphome/components/atc_mithermometer/* @ahpohl
esphome/components/b_parasite/* @rbaron
esphome/components/ballu/* @bazuchan
esphome/components/bang_bang/* @OttoWinter
esphome/components/bedjet/* @jhansche
esphome/components/bedjet/climate/* @jhansche
esphome/components/bedjet/fan/* @jhansche
esphome/components/bh1750/* @OttoWinter
esphome/components/binary_sensor/* @esphome/core
esphome/components/bl0939/* @ziceva
esphome/components/bl0940/* @tobias-
esphome/components/bl0942/* @dbuezas
esphome/components/ble_client/* @buxtronix
esphome/components/bluetooth_proxy/* @jesserockz
esphome/components/bme680_bsec/* @trvrnrth
esphome/components/bmp3xx/* @martgras
esphome/components/button/* @esphome/core
@@ -42,20 +50,27 @@ esphome/components/climate/* @esphome/core
esphome/components/climate_ir/* @glmnet
esphome/components/color_temperature/* @jesserockz
esphome/components/coolix/* @glmnet
esphome/components/copy/* @OttoWinter
esphome/components/cover/* @esphome/core
esphome/components/cs5460a/* @balrog-kun
esphome/components/cse7761/* @berfenger
esphome/components/ct_clamp/* @jesserockz
esphome/components/current_based/* @djwmarcx
esphome/components/dac7678/* @NickB1
esphome/components/daly_bms/* @s1lvi0
esphome/components/dashboard_import/* @esphome/core
esphome/components/debug/* @OttoWinter
esphome/components/delonghi/* @grob6000
esphome/components/dfplayer/* @glmnet
esphome/components/dht/* @OttoWinter
esphome/components/dps310/* @kbx81
esphome/components/ds1307/* @badbadc0ffee
esphome/components/dsmr/* @glmnet @zuidwijk
esphome/components/ektf2232/* @jesserockz
esphome/components/ens210/* @itn3rd77
esphome/components/esp32/* @esphome/core
esphome/components/esp32_ble/* @jesserockz
esphome/components/esp32_ble_client/* @jesserockz
esphome/components/esp32_ble_server/* @jesserockz
esphome/components/esp32_camera_web_server/* @ayufan
esphome/components/esp32_can/* @Sympatron
@@ -63,7 +78,9 @@ esphome/components/esp32_improv/* @jesserockz
esphome/components/esp8266/* @esphome/core
esphome/components/exposure_notifications/* @OttoWinter
esphome/components/ezo/* @ssieb
esphome/components/factory_reset/* @anatoly-savchenkov
esphome/components/fastled_base/* @OttoWinter
esphome/components/feedback/* @ianchi
esphome/components/fingerprint_grow/* @OnFreund @loongyh
esphome/components/globals/* @esphome/core
esphome/components/gpio/* @esphome/core
@@ -76,8 +93,11 @@ esphome/components/hbridge/light/* @DotNetDann
esphome/components/heatpumpir/* @rob-deutsch
esphome/components/hitachi_ac424/* @sourabhjaiswal
esphome/components/homeassistant/* @OttoWinter
esphome/components/honeywellabp/* @RubyBailey
esphome/components/hrxl_maxsonar_wr/* @netmikey
esphome/components/hydreon_rgxx/* @functionpointer
esphome/components/i2c/* @esphome/core
esphome/components/i2s_audio/* @jesserockz
esphome/components/improv_serial/* @esphome/core
esphome/components/ina260/* @MrEditor97
esphome/components/inkbird_ibsth1_mini/* @fkirill
@@ -88,9 +108,14 @@ esphome/components/json/* @OttoWinter
esphome/components/kalman_combinator/* @Cat-Ion
esphome/components/ledc/* @OttoWinter
esphome/components/light/* @esphome/core
esphome/components/lilygo_t5_47/touchscreen/* @jesserockz
esphome/components/lock/* @esphome/core
esphome/components/logger/* @esphome/core
esphome/components/ltr390/* @sjtrny
esphome/components/max31865/* @DAVe3283
esphome/components/max44009/* @berfenger
esphome/components/max7219digit/* @rspaargaren
esphome/components/max9611/* @mckaymatthew
esphome/components/mcp23008/* @jesserockz
esphome/components/mcp23017/* @jesserockz
esphome/components/mcp23s08/* @SenexCrenshaw @jesserockz
@@ -100,20 +125,29 @@ esphome/components/mcp23x17_base/* @jesserockz
esphome/components/mcp23xxx_base/* @jesserockz
esphome/components/mcp2515/* @danielschramm @mvturnho
esphome/components/mcp3204/* @rsumner
esphome/components/mcp4728/* @berfenger
esphome/components/mcp47a1/* @jesserockz
esphome/components/mcp9600/* @MrEditor97
esphome/components/mcp9808/* @k7hpn
esphome/components/md5/* @esphome/core
esphome/components/mdns/* @esphome/core
esphome/components/media_player/* @jesserockz
esphome/components/midea/* @dudanov
esphome/components/midea_ir/* @dudanov
esphome/components/mitsubishi/* @RubyBailey
esphome/components/mlx90393/* @functionpointer
esphome/components/modbus_controller/* @martgras
esphome/components/modbus_controller/binary_sensor/* @martgras
esphome/components/modbus_controller/number/* @martgras
esphome/components/modbus_controller/output/* @martgras
esphome/components/modbus_controller/select/* @martgras @stegm
esphome/components/modbus_controller/sensor/* @martgras
esphome/components/modbus_controller/switch/* @martgras
esphome/components/modbus_controller/text_sensor/* @martgras
esphome/components/mopeka_ble/* @spbrogan
esphome/components/mopeka_pro_check/* @spbrogan
esphome/components/mpl3115a2/* @kbickar
esphome/components/mpu6886/* @fabaff
esphome/components/network/* @esphome/core
esphome/components/nextion/* @senexcrenshaw
esphome/components/nextion/binary_sensor/* @senexcrenshaw
@@ -134,8 +168,12 @@ esphome/components/pn532_spi/* @OttoWinter @jesserockz
esphome/components/power_supply/* @esphome/core
esphome/components/preferences/* @esphome/core
esphome/components/psram/* @esphome/core
esphome/components/pulse_meter/* @stevebaxter
esphome/components/pulse_meter/* @cstaahl @stevebaxter
esphome/components/pvvx_mithermometer/* @pasiz
esphome/components/qmp6988/* @andrewpc
esphome/components/qr_code/* @wjtje
esphome/components/radon_eye_ble/* @jeffeb3
esphome/components/radon_eye_rd200/* @jeffeb3
esphome/components/rc522/* @glmnet
esphome/components/rc522_i2c/* @glmnet
esphome/components/rc522_spi/* @glmnet
@@ -144,20 +182,29 @@ esphome/components/rf_bridge/* @jesserockz
esphome/components/rgbct/* @jesserockz
esphome/components/rtttl/* @glmnet
esphome/components/safe_mode/* @jsuanet @paulmonigatti
esphome/components/scd4x/* @sjtrny
esphome/components/scd4x/* @martgras @sjtrny
esphome/components/script/* @esphome/core
esphome/components/sdm_meter/* @jesserockz @polyfaces
esphome/components/sdp3x/* @Azimath
esphome/components/selec_meter/* @sourabhjaiswal
esphome/components/select/* @esphome/core
esphome/components/sen5x/* @martgras
esphome/components/sensirion_common/* @martgras
esphome/components/sensor/* @esphome/core
esphome/components/sgp40/* @SenexCrenshaw
esphome/components/sgp4x/* @SenexCrenshaw @martgras
esphome/components/shelly_dimmer/* @edge90 @rnauber
esphome/components/sht4x/* @sjtrny
esphome/components/shutdown/* @esphome/core @jsuanet
esphome/components/sim800l/* @glmnet
esphome/components/sm2135/* @BoukeHaarsma23
esphome/components/sml/* @alengwenus
esphome/components/smt100/* @piechade
esphome/components/socket/* @esphome/core
esphome/components/sonoff_d1/* @anatoly-savchenkov
esphome/components/spi/* @esphome/core
esphome/components/sprinkler/* @kbx81
esphome/components/sps30/* @martgras
esphome/components/ssd1322_base/* @kbx81
esphome/components/ssd1322_spi/* @kbx81
esphome/components/ssd1325_base/* @kbx81
@@ -182,23 +229,33 @@ esphome/components/teleinfo/* @0hax
esphome/components/thermostat/* @kbx81
esphome/components/time/* @OttoWinter
esphome/components/tlc5947/* @rnauber
esphome/components/tm1621/* @Philippe12
esphome/components/tm1637/* @glmnet
esphome/components/tm1638/* @skykingjwc
esphome/components/tmp102/* @timsavage
esphome/components/tmp117/* @Azimath
esphome/components/tof10120/* @wstrzalka
esphome/components/toshiba/* @kbx81
esphome/components/touchscreen/* @jesserockz
esphome/components/tsl2591/* @wjcarpenter
esphome/components/tuya/binary_sensor/* @jesserockz
esphome/components/tuya/climate/* @jesserockz
esphome/components/tuya/number/* @frankiboy1
esphome/components/tuya/select/* @bearpawmaxim
esphome/components/tuya/sensor/* @jesserockz
esphome/components/tuya/switch/* @jesserockz
esphome/components/tuya/text_sensor/* @dentra
esphome/components/uart/* @esphome/core
esphome/components/ufire_ec/* @pvizeli
esphome/components/ufire_ise/* @pvizeli
esphome/components/ultrasonic/* @OttoWinter
esphome/components/version/* @esphome/core
esphome/components/wake_on_lan/* @willwill2will54
esphome/components/web_server_base/* @OttoWinter
esphome/components/whirlpool/* @glmnet
esphome/components/whynter/* @aeonsablaze
esphome/components/xiaomi_lywsd03mmc/* @ahpohl
esphome/components/xiaomi_mhoc303/* @drug123
esphome/components/xiaomi_mhoc401/* @vevsvevs
esphome/components/xiaomi_rtcgq02lm/* @jesserockz
esphome/components/xpt2046/* @numo68
+1 -1
View File
@@ -5,7 +5,7 @@ For a detailed guide, please see https://esphome.io/guides/contributing.html#con
Things to note when contributing:
- Please test your changes :)
- If a new feature is added or an existing user-facing feature is changed, you should also
- If a new feature is added or an existing user-facing feature is changed, you should also
update the [docs](https://github.com/esphome/esphome-docs). See [contributing to esphome-docs](https://esphome.io/guides/contributing.html#contributing-to-esphomedocs)
for more information.
- Please also update the tests in the `tests/` folder. You can do so by just adding a line in one of the YAML files
+21 -28
View File
@@ -5,12 +5,14 @@
# One of "docker", "hassio"
ARG BASEIMGTYPE=docker
FROM ghcr.io/hassio-addons/debian-base/amd64:5.2.3 AS base-hassio-amd64
FROM ghcr.io/hassio-addons/debian-base/aarch64:5.2.3 AS base-hassio-arm64
FROM ghcr.io/hassio-addons/debian-base/armv7:5.2.3 AS base-hassio-armv7
FROM debian:bullseye-20211220-slim AS base-docker-amd64
FROM debian:bullseye-20211220-slim AS base-docker-arm64
FROM debian:bullseye-20211220-slim AS base-docker-armv7
# https://github.com/hassio-addons/addon-debian-base/releases
FROM ghcr.io/hassio-addons/debian-base/amd64:5.3.0 AS base-hassio-amd64
FROM ghcr.io/hassio-addons/debian-base/aarch64:5.3.0 AS base-hassio-arm64
FROM ghcr.io/hassio-addons/debian-base/armv7:5.3.0 AS base-hassio-armv7
# https://hub.docker.com/_/debian?tab=tags&page=1&name=bullseye
FROM debian:bullseye-20220328-slim AS base-docker-amd64
FROM debian:bullseye-20220328-slim AS base-docker-arm64
FROM debian:bullseye-20220328-slim AS base-docker-armv7
# Use TARGETARCH/TARGETVARIANT defined by docker
# https://docs.docker.com/engine/reference/builder/#automatic-platform-args-in-the-global-scope
@@ -21,13 +23,14 @@ RUN \
# Use pinned versions so that we get updates with build caching
&& apt-get install -y --no-install-recommends \
python3=3.9.2-3 \
python3-pip=20.3.4-4 \
python3-pip=20.3.4-4+deb11u1 \
python3-setuptools=52.0.0-4 \
python3-pil=8.1.2+dfsg-0.3 \
python3-pil=8.1.2+dfsg-0.3+deb11u1 \
python3-cryptography=3.3.2-1 \
iputils-ping=3:20210202-1 \
git=1:2.30.2-1 \
curl=7.74.0-1.3+deb11u1 \
openssh-client=1:8.4p1-5 \
&& rm -rf \
/tmp/* \
/var/{cache,log}/* \
@@ -43,25 +46,23 @@ RUN \
# Ubuntu python3-pip is missing wheel
pip3 install --no-cache-dir \
wheel==0.37.1 \
platformio==5.2.4 \
platformio==6.0.2 \
# Change some platformio settings
&& platformio settings set enable_telemetry No \
&& platformio settings set check_libraries_interval 1000000 \
&& platformio settings set check_platformio_interval 1000000 \
&& platformio settings set check_platforms_interval 1000000 \
&& mkdir -p /piolibs
# ======================= docker-type image =======================
FROM base AS docker
# First install requirements to leverage caching when requirements don't change
COPY requirements.txt requirements_optional.txt docker/platformio_install_deps.py platformio.ini /
RUN \
pip3 install --no-cache-dir -r /requirements.txt -r /requirements_optional.txt \
&& /platformio_install_deps.py /platformio.ini
# ======================= docker-type image =======================
FROM base AS docker
# Copy esphome and install
COPY . /esphome
RUN pip3 install --no-cache-dir --no-use-pep517 -e /esphome
@@ -93,7 +94,7 @@ RUN \
apt-get update \
# Use pinned versions so that we get updates with build caching
&& apt-get install -y --no-install-recommends \
nginx=1.18.0-6.1 \
nginx-light=1.18.0-6.1+deb11u2 \
&& rm -rf \
/tmp/* \
/var/{cache,log}/* \
@@ -102,13 +103,7 @@ RUN \
ARG BUILD_VERSION=dev
# Copy root filesystem
COPY docker/hassio-rootfs/ /
# First install requirements to leverage caching when requirements don't change
COPY requirements.txt requirements_optional.txt docker/platformio_install_deps.py platformio.ini /
RUN \
pip3 install --no-cache-dir -r /requirements.txt -r /requirements_optional.txt \
&& /platformio_install_deps.py /platformio.ini
COPY docker/ha-addon-rootfs/ /
# Copy esphome and install
COPY . /esphome
@@ -139,7 +134,7 @@ RUN \
clang-tidy-11=1:11.0.1-2 \
patch=2.7.6-7 \
software-properties-common=0.96.20.2-2.1 \
nano=5.4-2 \
nano=5.4-2+deb11u1 \
build-essential=12.9 \
python3-dev=3.9.2-3 \
&& rm -rf \
@@ -147,10 +142,8 @@ RUN \
/var/{cache,log}/* \
/var/lib/apt/lists/*
COPY requirements.txt requirements_optional.txt requirements_test.txt docker/platformio_install_deps.py platformio.ini /
RUN \
pip3 install --no-cache-dir -r /requirements.txt -r /requirements_optional.txt -r /requirements_test.txt \
&& /platformio_install_deps.py /platformio.ini
COPY requirements_test.txt /
RUN pip3 install --no-cache-dir -r /requirements_test.txt
VOLUME ["/esphome"]
WORKDIR /esphome
+9 -2
View File
@@ -88,10 +88,12 @@ def main():
sys.exit(1)
# detect channel from tag
match = re.match(r'^\d+\.\d+(?:\.\d+)?(b\d+)?$', args.tag)
match = re.match(r"^(\d+\.\d+)(?:\.\d+)?(b\d+)?$", args.tag)
major_minor_version = None
if match is None:
channel = CHANNEL_DEV
elif match.group(1) is None:
elif match.group(2) is None:
major_minor_version = match.group(1)
channel = CHANNEL_RELEASE
else:
channel = CHANNEL_BETA
@@ -106,6 +108,11 @@ def main():
tags_to_push.append("beta")
tags_to_push.append("latest")
# Compatibility with HA tags
if major_minor_version:
tags_to_push.append("stable")
tags_to_push.append(major_minor_version)
if args.command == "build":
# 1. pull cache image
params = DockerParams.for_type_arch(args.build_type, args.arch)
@@ -7,12 +7,12 @@
# Check SSL requirements, if enabled
if bashio::config.true 'ssl'; then
if ! bashio::config.has_value 'certfile'; then
bashio::fatal 'SSL is enabled, but no certfile was specified.'
bashio::log.fatal 'SSL is enabled, but no certfile was specified.'
bashio::exit.nok
fi
if ! bashio::config.has_value 'keyfile'; then
bashio::fatal 'SSL is enabled, but no keyfile was specified'
bashio::log.fatal 'SSL is enabled, but no keyfile was specified'
bashio::exit.nok
fi
@@ -10,7 +10,7 @@ server {
ssl_certificate_key /ssl/%%keyfile%%;
# Clear Hass.io Ingress header
proxy_set_header X-Hassio-Ingress "";
proxy_set_header X-HA-Ingress "";
# Redirect http requests to https on the same port.
# https://rageagainstshell.com/2016/11/redirect-http-to-https-on-the-same-port-in-nginx/
@@ -4,7 +4,7 @@ server {
include /etc/nginx/includes/server_params.conf;
include /etc/nginx/includes/proxy_params.conf;
# Clear Hass.io Ingress header
proxy_set_header X-Hassio-Ingress "";
proxy_set_header X-HA-Ingress "";
location / {
proxy_pass http://esphome;
@@ -3,8 +3,8 @@ server {
include /etc/nginx/includes/server_params.conf;
include /etc/nginx/includes/proxy_params.conf;
# Set Hass.io Ingress header
proxy_set_header X-Hassio-Ingress "YES";
# Set Home Assistant Ingress header
proxy_set_header X-HA-Ingress "YES";
location / {
# Only allow from Hass.io supervisor
@@ -4,7 +4,7 @@
# Runs the ESPHome dashboard
# ==============================================================================
export ESPHOME_IS_HASSIO=true
export ESPHOME_IS_HA_ADDON=true
if bashio::config.true 'leave_front_door_open'; then
export DISABLE_HA_AUTHENTICATION=true
@@ -32,4 +32,4 @@ export PLATFORMIO_CACHE_DIR="${pio_cache_base}/cache"
export PLATFORMIO_GLOBALLIB_DIR=/piolibs
bashio::log.info "Starting ESPHome dashboard..."
exec esphome dashboard /config/esphome --socket /var/run/esphome.sock --hassio
exec esphome dashboard /config/esphome --socket /var/run/esphome.sock --ha-addon
+110 -4
View File
@@ -2,6 +2,7 @@ import argparse
import functools
import logging
import os
import re
import sys
from datetime import datetime
@@ -9,15 +10,18 @@ from esphome import const, writer, yaml_util
import esphome.codegen as cg
from esphome.config import iter_components, read_config, strip_default_ids
from esphome.const import (
ALLOWED_NAME_CHARS,
CONF_BAUD_RATE,
CONF_BROKER,
CONF_DEASSERT_RTS_DTR,
CONF_LOGGER,
CONF_NAME,
CONF_OTA,
CONF_PASSWORD,
CONF_PORT,
CONF_ESPHOME,
CONF_PLATFORMIO_OPTIONS,
CONF_SUBSTITUTIONS,
SECRETS_FILES,
)
from esphome.core import CORE, EsphomeError, coroutine
@@ -481,6 +485,98 @@ def command_idedata(args, config):
return 0
def command_rename(args, config):
for c in args.name:
if c not in ALLOWED_NAME_CHARS:
print(
color(
Fore.BOLD_RED,
f"'{c}' is an invalid character for names. Valid characters are: "
f"{ALLOWED_NAME_CHARS} (lowercase, no spaces)",
)
)
return 1
# Load existing yaml file
with open(CORE.config_path, mode="r+", encoding="utf-8") as raw_file:
raw_contents = raw_file.read()
yaml = yaml_util.load_yaml(CORE.config_path)
if CONF_ESPHOME not in yaml or CONF_NAME not in yaml[CONF_ESPHOME]:
print(
color(Fore.BOLD_RED, "Complex YAML files cannot be automatically renamed.")
)
return 1
old_name = yaml[CONF_ESPHOME][CONF_NAME]
match = re.match(r"^\$\{?([a-zA-Z0-9_]+)\}?$", old_name)
if match is None:
new_raw = re.sub(
rf"name:\s+[\"']?{old_name}[\"']?",
f'name: "{args.name}"',
raw_contents,
)
else:
old_name = yaml[CONF_SUBSTITUTIONS][match.group(1)]
if (
len(
re.findall(
rf"^\s+{match.group(1)}:\s+[\"']?{old_name}[\"']?",
raw_contents,
flags=re.MULTILINE,
)
)
> 1
):
print(color(Fore.BOLD_RED, "Too many matches in YAML to safely rename"))
return 1
new_raw = re.sub(
rf"^(\s+{match.group(1)}):\s+[\"']?{old_name}[\"']?",
f'\\1: "{args.name}"',
raw_contents,
flags=re.MULTILINE,
)
new_path = os.path.join(CORE.config_dir, args.name + ".yaml")
print(
f"Updating {color(Fore.CYAN, CORE.config_path)} to {color(Fore.CYAN, new_path)}"
)
print()
with open(new_path, mode="w", encoding="utf-8") as new_file:
new_file.write(new_raw)
rc = run_external_process("esphome", "config", new_path)
if rc != 0:
print(color(Fore.BOLD_RED, "Rename failed. Reverting changes."))
os.remove(new_path)
return 1
cli_args = [
"run",
new_path,
"--no-logs",
"--device",
CORE.address,
]
if args.dashboard:
cli_args.insert(0, "--dashboard")
try:
rc = run_external_process("esphome", *cli_args)
except KeyboardInterrupt:
rc = 1
if rc != 0:
os.remove(new_path)
return 1
os.remove(CORE.config_path)
print(color(Fore.BOLD_GREEN, "SUCCESS"))
print()
return 0
PRE_CONFIG_ACTIONS = {
"wizard": command_wizard,
"version": command_version,
@@ -499,6 +595,7 @@ POST_CONFIG_ACTIONS = {
"mqtt-fingerprint": command_mqtt_fingerprint,
"clean": command_clean,
"idedata": command_idedata,
"rename": command_rename,
}
@@ -661,7 +758,7 @@ def parse_args(argv):
"--open-ui", help="Open the dashboard UI in a browser.", action="store_true"
)
parser_dashboard.add_argument(
"--hassio", help=argparse.SUPPRESS, action="store_true"
"--ha-addon", help=argparse.SUPPRESS, action="store_true"
)
parser_dashboard.add_argument(
"--socket", help="Make the dashboard serve under a unix socket", type=str
@@ -681,6 +778,15 @@ def parse_args(argv):
"configuration", help="Your YAML configuration file(s).", nargs=1
)
parser_rename = subparsers.add_parser(
"rename",
help="Rename a device in YAML, compile the binary and upload it.",
)
parser_rename.add_argument(
"configuration", help="Your YAML configuration file.", nargs=1
)
parser_rename.add_argument("name", help="The new name for the device.", type=str)
# Keep backward compatibility with the old command line format of
# esphome <config> <command>.
#
@@ -778,10 +884,10 @@ def run_esphome(argv):
_LOGGER.warning("Please instead use:")
_LOGGER.warning(" esphome %s", " ".join(args.deprecated_argv_suggestion))
if sys.version_info < (3, 7, 0):
if sys.version_info < (3, 8, 0):
_LOGGER.error(
"You're running ESPHome with Python <3.7. ESPHome is no longer compatible "
"with this Python version. Please reinstall ESPHome with Python 3.7+"
"You're running ESPHome with Python <3.8. ESPHome is no longer compatible "
"with this Python version. Please reinstall ESPHome with Python 3.8+"
)
return 1
+14 -22
View File
@@ -12,7 +12,7 @@ from esphome.const import (
CONF_TYPE_ID,
CONF_TIME,
)
from esphome.jsonschema import jschema_extractor
from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor
from esphome.util import Registry
@@ -23,11 +23,10 @@ def maybe_simple_id(*validators):
def maybe_conf(conf, *validators):
validator = cv.All(*validators)
@jschema_extractor("maybe")
@schema_extractor("maybe")
def validate(value):
# pylint: disable=comparison-with-callable
if value == jschema_extractor:
return validator
if value == SCHEMA_EXTRACT:
return (validator, conf)
if isinstance(value, dict):
return validator(value)
@@ -111,11 +110,9 @@ def validate_automation(extra_schema=None, extra_validators=None, single=False):
# This should only happen with invalid configs, but let's have a nice error message.
return [schema(value)]
@jschema_extractor("automation")
@schema_extractor("automation")
def validator(value):
# hack to get the schema
# pylint: disable=comparison-with-callable
if value == jschema_extractor:
if value == SCHEMA_EXTRACT:
return schema
value = validator_(value)
@@ -262,21 +259,16 @@ async def repeat_action_to_code(config, action_id, template_arg, args):
return var
def validate_wait_until(value):
schema = cv.Schema(
{
cv.Required(CONF_CONDITION): validate_potentially_and_condition,
cv.Optional(CONF_TIMEOUT): cv.templatable(
cv.positive_time_period_milliseconds
),
}
)
if isinstance(value, dict) and CONF_CONDITION in value:
return schema(value)
return validate_wait_until({CONF_CONDITION: value})
_validate_wait_until = cv.maybe_simple_value(
{
cv.Required(CONF_CONDITION): validate_potentially_and_condition,
cv.Optional(CONF_TIMEOUT): cv.templatable(cv.positive_time_period_milliseconds),
},
key=CONF_CONDITION,
)
@register_action("wait_until", WaitUntilAction, validate_wait_until)
@register_action("wait_until", WaitUntilAction, _validate_wait_until)
async def wait_until_action_to_code(config, action_id, template_arg, args):
conditions = await build_condition(config[CONF_CONDITION], template_arg, args)
var = cg.new_Pvariable(action_id, template_arg, conditions)
+3
View File
@@ -63,6 +63,8 @@ from esphome.cpp_types import ( # noqa
uint32,
uint64,
int32,
int64,
size_t,
const_char_ptr,
NAN,
esphome_ns,
@@ -81,4 +83,5 @@ from esphome.cpp_types import ( # noqa
InternalGPIOPin,
gpio_Flags,
EntityCategory,
Parented,
)
+10 -6
View File
@@ -52,10 +52,10 @@ uint32_t IRAM_ATTR HOT AcDimmerDataStore::timer_intr(uint32_t now) {
this->gate_pin.digital_write(false);
}
if (time_since_zc < this->enable_time_us)
if (time_since_zc < this->enable_time_us) {
// Next event is enable, return time until that event
return this->enable_time_us - time_since_zc;
else if (time_since_zc < disable_time_us) {
} else if (time_since_zc < disable_time_us) {
// Next event is disable, return time until that event
return this->disable_time_us - time_since_zc;
}
@@ -74,9 +74,10 @@ uint32_t IRAM_ATTR HOT timer_interrupt() {
uint32_t min_dt_us = 1000;
uint32_t now = micros();
for (auto *dimmer : all_dimmers) {
if (dimmer == nullptr)
if (dimmer == nullptr) {
// no more dimmers
break;
}
uint32_t res = dimmer->timer_intr(now);
if (res != 0 && res < min_dt_us)
min_dt_us = res;
@@ -121,6 +122,7 @@ void IRAM_ATTR HOT AcDimmerDataStore::gpio_intr() {
// also take into account min_power
auto min_us = this->cycle_time_us * this->min_power / 1000;
this->enable_time_us = std::max((uint32_t) 1, ((65535 - this->value) * (this->cycle_time_us - min_us)) / 65535);
if (this->method == DIM_METHOD_LEADING_PULSE) {
// Minimum pulse time should be enough for the triac to trigger when it is close to the ZC zone
// this is for brightness near 99%
@@ -201,6 +203,7 @@ void AcDimmer::setup() {
#endif
}
void AcDimmer::write_state(float state) {
state = std::acos(1 - (2 * state)) / 3.14159; // RMS power compensation
auto new_value = static_cast<uint16_t>(roundf(state * 65535));
if (new_value != 0 && this->store_.value == 0)
this->store_.init_cycle = this->init_with_half_cycle_;
@@ -212,12 +215,13 @@ void AcDimmer::dump_config() {
LOG_PIN(" Zero-Cross Pin: ", this->zero_cross_pin_);
ESP_LOGCONFIG(TAG, " Min Power: %.1f%%", this->store_.min_power / 10.0f);
ESP_LOGCONFIG(TAG, " Init with half cycle: %s", YESNO(this->init_with_half_cycle_));
if (method_ == DIM_METHOD_LEADING_PULSE)
if (method_ == DIM_METHOD_LEADING_PULSE) {
ESP_LOGCONFIG(TAG, " Method: leading pulse");
else if (method_ == DIM_METHOD_LEADING)
} else if (method_ == DIM_METHOD_LEADING) {
ESP_LOGCONFIG(TAG, " Method: leading");
else
} else {
ESP_LOGCONFIG(TAG, " Method: trailing");
}
LOG_FLOAT_OUTPUT(this);
ESP_LOGV(TAG, " Estimated Frequency: %.3fHz", 1e6f / this->store_.cycle_time_us / 2);
@@ -13,7 +13,6 @@ class AdalightLightEffect : public light::AddressableLightEffect, public uart::U
public:
AdalightLightEffect(const std::string &name);
public:
void start() override;
void stop() override;
void apply(light::AddressableLight &it, const Color &current_color) override;
@@ -30,7 +29,6 @@ class AdalightLightEffect : public light::AddressableLightEffect, public uart::U
void blank_all_leds_(light::AddressableLight &it);
Frame parse_frame_(light::AddressableLight &it);
protected:
uint32_t last_ack_{0};
uint32_t last_byte_{0};
uint32_t last_reset_{0};
+36 -23
View File
@@ -16,6 +16,22 @@ namespace adc {
static const char *const TAG = "adc";
// 13bit for S2, and 12bit for all other esp32 variants
#ifdef USE_ESP32
static const adc_bits_width_t ADC_WIDTH_MAX_SOC_BITS = static_cast<adc_bits_width_t>(ADC_WIDTH_MAX - 1);
#ifndef SOC_ADC_RTC_MAX_BITWIDTH
#if USE_ESP32_VARIANT_ESP32S2
static const int SOC_ADC_RTC_MAX_BITWIDTH = 13;
#else
static const int SOC_ADC_RTC_MAX_BITWIDTH = 12;
#endif
#endif
static const int ADC_MAX = (1 << SOC_ADC_RTC_MAX_BITWIDTH) - 1; // 4095 (12 bit) or 8191 (13 bit)
static const int ADC_HALF = (1 << SOC_ADC_RTC_MAX_BITWIDTH) >> 1; // 2048 (12 bit) or 4096 (13 bit)
#endif
void ADCSensor::setup() {
ESP_LOGCONFIG(TAG, "Setting up ADC '%s'...", this->get_name().c_str());
#ifndef USE_ADC_SENSOR_VCC
@@ -23,14 +39,14 @@ void ADCSensor::setup() {
#endif
#ifdef USE_ESP32
adc1_config_width(ADC_WIDTH_BIT_12);
adc1_config_width(ADC_WIDTH_MAX_SOC_BITS);
if (!autorange_) {
adc1_config_channel_atten(channel_, attenuation_);
}
// load characteristics for each attenuation
for (int i = 0; i < (int) ADC_ATTEN_MAX; i++) {
auto cal_value = esp_adc_cal_characterize(ADC_UNIT_1, (adc_atten_t) i, ADC_WIDTH_BIT_12,
auto cal_value = esp_adc_cal_characterize(ADC_UNIT_1, (adc_atten_t) i, ADC_WIDTH_MAX_SOC_BITS,
1100, // default vref
&cal_characteristics_[i]);
switch (cal_value) {
@@ -46,10 +62,6 @@ void ADCSensor::setup() {
}
}
// adc_gpio_init doesn't exist on ESP32-C3 or ESP32-H2
#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32H2)
adc_gpio_init(ADC_UNIT_1, (adc_channel_t) channel_);
#endif
#endif // USE_ESP32
}
@@ -65,25 +77,26 @@ void ADCSensor::dump_config() {
#ifdef USE_ESP32
LOG_PIN(" Pin: ", pin_);
if (autorange_)
if (autorange_) {
ESP_LOGCONFIG(TAG, " Attenuation: auto");
else
} else {
switch (this->attenuation_) {
case ADC_ATTEN_DB_0:
ESP_LOGCONFIG(TAG, " Attenuation: 0db (max 1.1V)");
ESP_LOGCONFIG(TAG, " Attenuation: 0db");
break;
case ADC_ATTEN_DB_2_5:
ESP_LOGCONFIG(TAG, " Attenuation: 2.5db (max 1.5V)");
ESP_LOGCONFIG(TAG, " Attenuation: 2.5db");
break;
case ADC_ATTEN_DB_6:
ESP_LOGCONFIG(TAG, " Attenuation: 6db (max 2.2V)");
ESP_LOGCONFIG(TAG, " Attenuation: 6db");
break;
case ADC_ATTEN_DB_11:
ESP_LOGCONFIG(TAG, " Attenuation: 11db (max 3.9V)");
ESP_LOGCONFIG(TAG, " Attenuation: 11db");
break;
default: // This is to satisfy the unused ADC_ATTEN_MAX
break;
}
}
#endif // USE_ESP32
LOG_UPDATE_INTERVAL(this);
}
@@ -123,16 +136,16 @@ float ADCSensor::sample() {
return mv / 1000.0f;
}
int raw11, raw6 = 4095, raw2 = 4095, raw0 = 4095;
int raw11, raw6 = ADC_MAX, raw2 = ADC_MAX, raw0 = ADC_MAX;
adc1_config_channel_atten(channel_, ADC_ATTEN_DB_11);
raw11 = adc1_get_raw(channel_);
if (raw11 < 4095) {
if (raw11 < ADC_MAX) {
adc1_config_channel_atten(channel_, ADC_ATTEN_DB_6);
raw6 = adc1_get_raw(channel_);
if (raw6 < 4095) {
if (raw6 < ADC_MAX) {
adc1_config_channel_atten(channel_, ADC_ATTEN_DB_2_5);
raw2 = adc1_get_raw(channel_);
if (raw2 < 4095) {
if (raw2 < ADC_MAX) {
adc1_config_channel_atten(channel_, ADC_ATTEN_DB_0);
raw0 = adc1_get_raw(channel_);
}
@@ -148,15 +161,15 @@ float ADCSensor::sample() {
uint32_t mv2 = esp_adc_cal_raw_to_voltage(raw2, &cal_characteristics_[(int) ADC_ATTEN_DB_2_5]);
uint32_t mv0 = esp_adc_cal_raw_to_voltage(raw0, &cal_characteristics_[(int) ADC_ATTEN_DB_0]);
// Contribution of each value, in range 0-2048
uint32_t c11 = std::min(raw11, 2048);
uint32_t c6 = 2048 - std::abs(raw6 - 2048);
uint32_t c2 = 2048 - std::abs(raw2 - 2048);
uint32_t c0 = std::min(4095 - raw0, 2048);
// max theoretical csum value is 2048*4 = 8192
// Contribution of each value, in range 0-2048 (12 bit ADC) or 0-4096 (13 bit ADC)
uint32_t c11 = std::min(raw11, ADC_HALF);
uint32_t c6 = ADC_HALF - std::abs(raw6 - ADC_HALF);
uint32_t c2 = ADC_HALF - std::abs(raw2 - ADC_HALF);
uint32_t c0 = std::min(ADC_MAX - raw0, ADC_HALF);
// max theoretical csum value is 4096*4 = 16384
uint32_t csum = c11 + c6 + c2 + c0;
// each mv is max 3900; so max value is 3900*2048*4, fits in unsigned
// each mv is max 3900; so max value is 3900*4096*4, fits in unsigned32
uint32_t mv_scaled = (mv11 * c11) + (mv6 * c6) + (mv2 * c2) + (mv0 * c0);
return mv_scaled / (float) (csum * 1000U);
}
+1 -1
View File
@@ -133,6 +133,7 @@ ADCSensor = adc_ns.class_(
CONFIG_SCHEMA = cv.All(
sensor.sensor_schema(
ADCSensor,
unit_of_measurement=UNIT_VOLT,
accuracy_decimals=2,
device_class=DEVICE_CLASS_VOLTAGE,
@@ -140,7 +141,6 @@ CONFIG_SCHEMA = cv.All(
)
.extend(
{
cv.GenerateID(): cv.declare_id(ADCSensor),
cv.Required(CONF_PIN): validate_adc_pin,
cv.Optional(CONF_RAW, default=False): cv.boolean,
cv.SplitDefault(CONF_ATTENUATION, esp32="0db"): cv.All(
@@ -40,6 +40,8 @@ class AddressableLightDisplay : public display::DisplayBuffer, public PollingCom
void setup() override;
void display();
display::DisplayType get_display_type() override { return display::DisplayType::DISPLAY_TYPE_COLOR; }
protected:
int get_width_internal() override;
int get_height_internal() override;
+1 -1
View File
@@ -82,7 +82,7 @@ class ADE7953 : public i2c::I2CDevice, public PollingComponent {
return i2c::ERROR_OK;
}
InternalGPIOPin *irq_pin_ = nullptr;
InternalGPIOPin *irq_pin_{nullptr};
bool is_setup_{false};
sensor::Sensor *voltage_sensor_{nullptr};
sensor::Sensor *current_a_sensor_{nullptr};
+1 -1
View File
@@ -52,6 +52,7 @@ ADS1115Sensor = ads1115_ns.class_(
CONF_ADS1115_ID = "ads1115_id"
CONFIG_SCHEMA = (
sensor.sensor_schema(
ADS1115Sensor,
unit_of_measurement=UNIT_VOLT,
accuracy_decimals=3,
device_class=DEVICE_CLASS_VOLTAGE,
@@ -59,7 +60,6 @@ CONFIG_SCHEMA = (
)
.extend(
{
cv.GenerateID(): cv.declare_id(ADS1115Sensor),
cv.GenerateID(CONF_ADS1115_ID): cv.use_id(ADS1115Component),
cv.Required(CONF_MULTIPLEXER): cv.enum(MUX, upper=True, space="_"),
cv.Required(CONF_GAIN): validate_gain,
+2 -2
View File
@@ -18,8 +18,8 @@ class AHT10Component : public PollingComponent, public i2c::I2CDevice {
void set_humidity_sensor(sensor::Sensor *humidity_sensor) { humidity_sensor_ = humidity_sensor; }
protected:
sensor::Sensor *temperature_sensor_;
sensor::Sensor *humidity_sensor_;
sensor::Sensor *temperature_sensor_{nullptr};
sensor::Sensor *humidity_sensor_{nullptr};
};
} // namespace aht10
@@ -24,7 +24,7 @@ void AirthingsWaveMini::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt
case ESP_GATTC_SEARCH_CMPL_EVT: {
this->handle_ = 0;
auto chr = this->parent()->get_characteristic(service_uuid_, sensors_data_characteristic_uuid_);
auto *chr = this->parent()->get_characteristic(service_uuid_, sensors_data_characteristic_uuid_);
if (chr == nullptr) {
ESP_LOGW(TAG, "No sensor characteristic found at service %s char %s", service_uuid_.to_string().c_str(),
sensors_data_characteristic_uuid_.to_string().c_str());
@@ -38,7 +38,7 @@ void AirthingsWaveMini::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt
}
case ESP_GATTC_READ_CHAR_EVT: {
if (param->read.conn_id != this->parent()->conn_id)
if (param->read.conn_id != this->parent()->get_conn_id())
break;
if (param->read.status != ESP_GATT_OK) {
ESP_LOGW(TAG, "Error reading char at handle %d, status=%d", param->read.handle, param->read.status);
@@ -56,7 +56,7 @@ void AirthingsWaveMini::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt
}
void AirthingsWaveMini::read_sensors_(uint8_t *raw_value, uint16_t value_len) {
auto value = (WaveMiniReadings *) raw_value;
auto *value = (WaveMiniReadings *) raw_value;
if (sizeof(WaveMiniReadings) <= value_len) {
this->humidity_sensor_->publish_state(value->humidity / 100.0f);
@@ -88,8 +88,8 @@ void AirthingsWaveMini::update() {
}
void AirthingsWaveMini::request_read_values_() {
auto status =
esp_ble_gattc_read_char(this->parent()->gattc_if, this->parent()->conn_id, this->handle_, ESP_GATT_AUTH_REQ_NONE);
auto status = esp_ble_gattc_read_char(this->parent()->get_gattc_if(), this->parent()->get_conn_id(), this->handle_,
ESP_GATT_AUTH_REQ_NONE);
if (status) {
ESP_LOGW(TAG, "Error sending read request for sensor, status=%d", status);
}
@@ -24,7 +24,7 @@ void AirthingsWavePlus::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt
case ESP_GATTC_SEARCH_CMPL_EVT: {
this->handle_ = 0;
auto chr = this->parent()->get_characteristic(service_uuid_, sensors_data_characteristic_uuid_);
auto *chr = this->parent()->get_characteristic(service_uuid_, sensors_data_characteristic_uuid_);
if (chr == nullptr) {
ESP_LOGW(TAG, "No sensor characteristic found at service %s char %s", service_uuid_.to_string().c_str(),
sensors_data_characteristic_uuid_.to_string().c_str());
@@ -38,7 +38,7 @@ void AirthingsWavePlus::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt
}
case ESP_GATTC_READ_CHAR_EVT: {
if (param->read.conn_id != this->parent()->conn_id)
if (param->read.conn_id != this->parent()->get_conn_id())
break;
if (param->read.status != ESP_GATT_OK) {
ESP_LOGW(TAG, "Error reading char at handle %d, status=%d", param->read.handle, param->read.status);
@@ -56,7 +56,7 @@ void AirthingsWavePlus::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt
}
void AirthingsWavePlus::read_sensors_(uint8_t *raw_value, uint16_t value_len) {
auto value = (WavePlusReadings *) raw_value;
auto *value = (WavePlusReadings *) raw_value;
if (sizeof(WavePlusReadings) <= value_len) {
ESP_LOGD(TAG, "version = %d", value->version);
@@ -109,8 +109,8 @@ void AirthingsWavePlus::update() {
}
void AirthingsWavePlus::request_read_values_() {
auto status =
esp_ble_gattc_read_char(this->parent()->gattc_if, this->parent()->conn_id, this->handle_, ESP_GATT_AUTH_REQ_NONE);
auto status = esp_ble_gattc_read_char(this->parent()->get_gattc_if(), this->parent()->get_conn_id(), this->handle_,
ESP_GATT_AUTH_REQ_NONE);
if (status) {
ESP_LOGW(TAG, "Error sending read request for sensor, status=%d", status);
}
+3 -19
View File
@@ -4,31 +4,15 @@
// - Arduino - AM2320: https://github.com/EngDial/AM2320/blob/master/src/AM2320.cpp
#include "am2320.h"
#include "esphome/core/log.h"
#include "esphome/core/hal.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
namespace esphome {
namespace am2320 {
static const char *const TAG = "am2320";
// ---=== Calc CRC16 ===---
uint16_t crc_16(uint8_t *ptr, uint8_t length) {
uint16_t crc = 0xFFFF;
uint8_t i;
//------------------------------
while (length--) {
crc ^= *ptr++;
for (i = 0; i < 8; i++)
if ((crc & 0x01) != 0) {
crc >>= 1;
crc ^= 0xA001;
} else
crc >>= 1;
}
return crc;
}
void AM2320Component::update() {
uint8_t data[8];
data[0] = 0;
@@ -96,7 +80,7 @@ bool AM2320Component::read_data_(uint8_t *data) {
checksum = data[7] << 8;
checksum += data[6];
if (crc_16(data, 6) != checksum) {
if (crc16(data, 6) != checksum) {
ESP_LOGW(TAG, "AM2320 Checksum invalid!");
return false;
}
+2 -2
View File
@@ -21,8 +21,8 @@ class AM2320Component : public PollingComponent, public i2c::I2CDevice {
bool read_data_(uint8_t *data);
bool read_bytes_(uint8_t a_register, uint8_t *data, uint8_t len, uint32_t conversion = 0);
sensor::Sensor *temperature_sensor_;
sensor::Sensor *humidity_sensor_;
sensor::Sensor *temperature_sensor_{nullptr};
sensor::Sensor *humidity_sensor_{nullptr};
};
} // namespace am2320
+10 -9
View File
@@ -39,7 +39,7 @@ void Am43::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_i
break;
}
case ESP_GATTC_SEARCH_CMPL_EVT: {
auto chr = this->parent_->get_characteristic(AM43_SERVICE_UUID, AM43_CHARACTERISTIC_UUID);
auto *chr = this->parent_->get_characteristic(AM43_SERVICE_UUID, AM43_CHARACTERISTIC_UUID);
if (chr == nullptr) {
if (this->parent_->get_characteristic(AM43_TUYA_SERVICE_UUID, AM43_TUYA_CHARACTERISTIC_UUID) != nullptr) {
ESP_LOGE(TAG, "[%s] Detected a Tuya AM43 which is not supported, sorry.",
@@ -75,13 +75,14 @@ void Am43::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_i
if (this->current_sensor_ > 0) {
if (this->illuminance_ != nullptr) {
auto packet = this->encoder_->get_light_level_request();
auto status = esp_ble_gattc_write_char(this->parent_->gattc_if, this->parent_->conn_id, this->char_handle_,
packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP,
ESP_GATT_AUTH_REQ_NONE);
if (status)
auto *packet = this->encoder_->get_light_level_request();
auto status = esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(),
this->char_handle_, packet->length, packet->data,
ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
if (status) {
ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(),
status);
}
}
this->current_sensor_ = 0;
}
@@ -99,10 +100,10 @@ void Am43::update() {
}
if (this->current_sensor_ == 0) {
if (this->battery_ != nullptr) {
auto packet = this->encoder_->get_battery_level_request();
auto *packet = this->encoder_->get_battery_level_request();
auto status =
esp_ble_gattc_write_char(this->parent_->gattc_if, this->parent_->conn_id, this->char_handle_, packet->length,
packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
if (status)
ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(), status);
}
+1 -1
View File
@@ -5,7 +5,7 @@ from esphome.const import CONF_ID, CONF_PIN
CODEOWNERS = ["@buxtronix"]
DEPENDENCIES = ["ble_client"]
AUTO_LOAD = ["am43"]
AUTO_LOAD = ["am43", "sensor"]
CONF_INVERT_POSITION = "invert_position"
+19 -17
View File
@@ -25,15 +25,16 @@ void Am43Component::setup() {
void Am43Component::loop() {
if (this->node_state == espbt::ClientState::ESTABLISHED && !this->logged_in_) {
auto packet = this->encoder_->get_send_pin_request(this->pin_);
auto *packet = this->encoder_->get_send_pin_request(this->pin_);
auto status =
esp_ble_gattc_write_char(this->parent_->gattc_if, this->parent_->conn_id, this->char_handle_, packet->length,
packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
ESP_LOGI(TAG, "[%s] Logging into AM43", this->get_name().c_str());
if (status)
if (status) {
ESP_LOGW(TAG, "[%s] Error writing set_pin to device, error = %d", this->get_name().c_str(), status);
else
} else {
this->logged_in_ = true;
}
}
}
@@ -51,10 +52,10 @@ void Am43Component::control(const CoverCall &call) {
return;
}
if (call.get_stop()) {
auto packet = this->encoder_->get_stop_request();
auto *packet = this->encoder_->get_stop_request();
auto status =
esp_ble_gattc_write_char(this->parent_->gattc_if, this->parent_->conn_id, this->char_handle_, packet->length,
packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
if (status)
ESP_LOGW(TAG, "[%s] Error writing stop command to device, error = %d", this->get_name().c_str(), status);
}
@@ -63,10 +64,10 @@ void Am43Component::control(const CoverCall &call) {
if (this->invert_position_)
pos = 1 - pos;
auto packet = this->encoder_->get_set_position_request(100 - (uint8_t)(pos * 100));
auto *packet = this->encoder_->get_set_position_request(100 - (uint8_t)(pos * 100));
auto status =
esp_ble_gattc_write_char(this->parent_->gattc_if, this->parent_->conn_id, this->char_handle_, packet->length,
packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
if (status)
ESP_LOGW(TAG, "[%s] Error writing set_position command to device, error = %d", this->get_name().c_str(), status);
}
@@ -80,7 +81,7 @@ void Am43Component::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
break;
}
case ESP_GATTC_SEARCH_CMPL_EVT: {
auto chr = this->parent_->get_characteristic(AM43_SERVICE_UUID, AM43_CHARACTERISTIC_UUID);
auto *chr = this->parent_->get_characteristic(AM43_SERVICE_UUID, AM43_CHARACTERISTIC_UUID);
if (chr == nullptr) {
if (this->parent_->get_characteristic(AM43_TUYA_SERVICE_UUID, AM43_TUYA_CHARACTERISTIC_UUID) != nullptr) {
ESP_LOGE(TAG, "[%s] Detected a Tuya AM43 which is not supported, sorry.", this->get_name().c_str());
@@ -91,7 +92,8 @@ void Am43Component::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
}
this->char_handle_ = chr->handle;
auto status = esp_ble_gattc_register_for_notify(this->parent_->gattc_if, this->parent_->remote_bda, chr->handle);
auto status = esp_ble_gattc_register_for_notify(this->parent_->get_gattc_if(), this->parent_->get_remote_bda(),
chr->handle);
if (status) {
ESP_LOGW(TAG, "[%s] esp_ble_gattc_register_for_notify failed, status=%d", this->get_name().c_str(), status);
}
@@ -120,10 +122,10 @@ void Am43Component::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
if (this->decoder_->has_pin_response()) {
if (this->decoder_->pin_ok_) {
ESP_LOGI(TAG, "[%s] AM43 pin accepted.", this->get_name().c_str());
auto packet = this->encoder_->get_position_request();
auto status = esp_ble_gattc_write_char(this->parent_->gattc_if, this->parent_->conn_id, this->char_handle_,
packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP,
ESP_GATT_AUTH_REQ_NONE);
auto *packet = this->encoder_->get_position_request();
auto status = esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(),
this->char_handle_, packet->length, packet->data,
ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
if (status)
ESP_LOGW(TAG, "[%s] Error writing set_position to device, error = %d", this->get_name().c_str(), status);
} else {
@@ -0,0 +1 @@
CODEOWNERS = ["@ianchi"]
@@ -0,0 +1,40 @@
#include "analog_threshold_binary_sensor.h"
#include "esphome/core/log.h"
namespace esphome {
namespace analog_threshold {
static const char *const TAG = "analog_threshold.binary_sensor";
void AnalogThresholdBinarySensor::setup() {
float sensor_value = this->sensor_->get_state();
// TRUE state is defined to be when sensor is >= threshold
// so when undefined sensor value initialize to FALSE
if (std::isnan(sensor_value)) {
this->publish_initial_state(false);
} else {
this->publish_initial_state(sensor_value >= (this->lower_threshold_ + this->upper_threshold_) / 2.0f);
}
}
void AnalogThresholdBinarySensor::set_sensor(sensor::Sensor *analog_sensor) {
this->sensor_ = analog_sensor;
this->sensor_->add_on_state_callback([this](float sensor_value) {
// if there is an invalid sensor reading, ignore the change and keep the current state
if (!std::isnan(sensor_value)) {
this->publish_state(sensor_value >= (this->state ? this->lower_threshold_ : this->upper_threshold_));
}
});
}
void AnalogThresholdBinarySensor::dump_config() {
LOG_BINARY_SENSOR("", "Analog Threshold Binary Sensor", this);
LOG_SENSOR(" ", "Sensor", this->sensor_);
ESP_LOGCONFIG(TAG, " Upper threshold: %.11f", this->upper_threshold_);
ESP_LOGCONFIG(TAG, " Lower threshold: %.11f", this->lower_threshold_);
}
} // namespace analog_threshold
} // namespace esphome
@@ -0,0 +1,29 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/components/binary_sensor/binary_sensor.h"
#include "esphome/components/sensor/sensor.h"
namespace esphome {
namespace analog_threshold {
class AnalogThresholdBinarySensor : public Component, public binary_sensor::BinarySensor {
public:
void dump_config() override;
void setup() override;
float get_setup_priority() const override { return setup_priority::DATA; }
void set_sensor(sensor::Sensor *analog_sensor);
void set_upper_threshold(float threshold) { this->upper_threshold_ = threshold; }
void set_lower_threshold(float threshold) { this->lower_threshold_ = threshold; }
protected:
sensor::Sensor *sensor_{nullptr};
float upper_threshold_;
float lower_threshold_;
};
} // namespace analog_threshold
} // namespace esphome
@@ -0,0 +1,44 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import binary_sensor, sensor
from esphome.const import (
CONF_SENSOR_ID,
CONF_THRESHOLD,
)
analog_threshold_ns = cg.esphome_ns.namespace("analog_threshold")
AnalogThresholdBinarySensor = analog_threshold_ns.class_(
"AnalogThresholdBinarySensor", binary_sensor.BinarySensor, cg.Component
)
CONF_UPPER = "upper"
CONF_LOWER = "lower"
CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend(
{
cv.GenerateID(): cv.declare_id(AnalogThresholdBinarySensor),
cv.Required(CONF_SENSOR_ID): cv.use_id(sensor.Sensor),
cv.Required(CONF_THRESHOLD): cv.Any(
cv.float_,
cv.Schema(
{cv.Required(CONF_UPPER): cv.float_, cv.Required(CONF_LOWER): cv.float_}
),
),
}
).extend(cv.COMPONENT_SCHEMA)
async def to_code(config):
var = await binary_sensor.new_binary_sensor(config)
await cg.register_component(var, config)
sens = await cg.get_variable(config[CONF_SENSOR_ID])
cg.add(var.set_sensor(sens))
if isinstance(config[CONF_THRESHOLD], float):
cg.add(var.set_upper_threshold(config[CONF_THRESHOLD]))
cg.add(var.set_lower_threshold(config[CONF_THRESHOLD]))
else:
cg.add(var.set_upper_threshold(config[CONF_THRESHOLD][CONF_UPPER]))
cg.add(var.set_lower_threshold(config[CONF_THRESHOLD][CONF_LOWER]))
+23
View File
@@ -94,6 +94,29 @@ async def to_code(config):
data[pos] = pix[2]
pos += 1
elif config[CONF_TYPE] == "RGB565":
data = [0 for _ in range(height * width * 2 * frames)]
pos = 0
for frameIndex in range(frames):
image.seek(frameIndex)
frame = image.convert("RGB")
if CONF_RESIZE in config:
frame = frame.resize([width, height])
pixels = list(frame.getdata())
if len(pixels) != height * width:
raise core.EsphomeError(
f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height*width})"
)
for pix in pixels:
R = pix[0] >> 3
G = pix[1] >> 2
B = pix[2] >> 3
rgb = (R << 11) | (G << 5) | B
data[pos] = rgb >> 8
pos += 1
data[pos] = rgb & 255
pos += 1
elif config[CONF_TYPE] == "BINARY":
width8 = ((width + 7) // 8) * 8
data = [0 for _ in range((height * width8 // 8) * frames)]
+19 -14
View File
@@ -34,15 +34,17 @@ void Anova::control(const ClimateCall &call) {
ESP_LOGW(TAG, "Unsupported mode: %d", mode);
return;
}
auto status = esp_ble_gattc_write_char(this->parent_->gattc_if, this->parent_->conn_id, this->char_handle_,
pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
auto status =
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
if (status)
ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(), status);
}
if (call.get_target_temperature().has_value()) {
auto pkt = this->codec_->get_set_target_temp_request(*call.get_target_temperature());
auto status = esp_ble_gattc_write_char(this->parent_->gattc_if, this->parent_->conn_id, this->char_handle_,
pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
auto *pkt = this->codec_->get_set_target_temp_request(*call.get_target_temperature());
auto status =
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
if (status)
ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(), status);
}
@@ -57,7 +59,7 @@ void Anova::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_
break;
}
case ESP_GATTC_SEARCH_CMPL_EVT: {
auto chr = this->parent_->get_characteristic(ANOVA_SERVICE_UUID, ANOVA_CHARACTERISTIC_UUID);
auto *chr = this->parent_->get_characteristic(ANOVA_SERVICE_UUID, ANOVA_CHARACTERISTIC_UUID);
if (chr == nullptr) {
ESP_LOGW(TAG, "[%s] No control service found at device, not an Anova..?", this->get_name().c_str());
ESP_LOGW(TAG, "[%s] Note, this component does not currently support Anova Nano.", this->get_name().c_str());
@@ -65,7 +67,8 @@ void Anova::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_
}
this->char_handle_ = chr->handle;
auto status = esp_ble_gattc_register_for_notify(this->parent_->gattc_if, this->parent_->remote_bda, chr->handle);
auto status = esp_ble_gattc_register_for_notify(this->parent_->get_gattc_if(), this->parent_->get_remote_bda(),
chr->handle);
if (status) {
ESP_LOGW(TAG, "[%s] esp_ble_gattc_register_for_notify failed, status=%d", this->get_name().c_str(), status);
}
@@ -92,7 +95,7 @@ void Anova::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_
}
if (this->codec_->has_unit()) {
this->fahrenheit_ = (this->codec_->unit_ == 'f');
ESP_LOGD(TAG, "Anova units is %s", this->fahrenheit_ ? "fahrenheit" : "celcius");
ESP_LOGD(TAG, "Anova units is %s", this->fahrenheit_ ? "fahrenheit" : "celsius");
this->current_request_++;
}
this->publish_state();
@@ -112,11 +115,12 @@ void Anova::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_
}
if (pkt != nullptr) {
auto status =
esp_ble_gattc_write_char(this->parent_->gattc_if, this->parent_->conn_id, this->char_handle_, pkt->length,
pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
if (status)
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
if (status) {
ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(),
status);
}
}
}
break;
@@ -133,11 +137,12 @@ void Anova::update() {
return;
if (this->current_request_ < 2) {
auto pkt = this->codec_->get_read_device_status_request();
auto *pkt = this->codec_->get_read_device_status_request();
if (this->current_request_ == 0)
this->codec_->get_set_unit_request(this->fahrenheit_ ? 'f' : 'c');
auto status = esp_ble_gattc_write_char(this->parent_->gattc_if, this->parent_->conn_id, this->char_handle_,
pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
auto status =
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
if (status)
ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(), status);
this->current_request_++;
+1 -1
View File
@@ -36,7 +36,7 @@ class Anova : public climate::Climate, public esphome::ble_client::BLEClientNode
traits.set_visual_temperature_step(0.1);
return traits;
}
void set_unit_of_measurement(const char *);
void set_unit_of_measurement(const char *unit);
protected:
std::unique_ptr<AnovaCodec> codec_;
+41
View File
@@ -8,6 +8,27 @@ AUTO_LOAD = ["sensor", "binary_sensor"]
MULTI_CONF = True
CONF_APDS9960_ID = "apds9960_id"
CONF_LED_DRIVE = "led_drive"
CONF_PROXIMITY_GAIN = "proximity_gain"
CONF_AMBIENT_LIGHT_GAIN = "ambient_light_gain"
CONF_GESTURE_LED_DRIVE = "gesture_led_drive"
CONF_GESTURE_GAIN = "gesture_gain"
CONF_GESTURE_WAIT_TIME = "gesture_wait_time"
DRIVE_LEVELS = {"100ma": 0, "50ma": 1, "25ma": 2, "12.5ma": 3}
PROXIMITY_LEVELS = {"1x": 0, "2x": 1, "4x": 2, "8x": 3}
AMBIENT_LEVELS = {"1x": 0, "4x": 1, "16x": 2, "64x": 3}
GESTURE_LEVELS = {"1x": 0, "2x": 1, "4x": 2, "8x": 3}
GESTURE_WAIT_TIMES = {
"0ms": 0,
"2.8ms": 1,
"5.6ms": 2,
"8.4ms": 3,
"14ms": 4,
"22.4ms": 5,
"30.8ms": 6,
"39.2ms": 7,
}
apds9960_nds = cg.esphome_ns.namespace("apds9960")
APDS9960 = apds9960_nds.class_("APDS9960", cg.PollingComponent, i2c.I2CDevice)
@@ -16,6 +37,20 @@ CONFIG_SCHEMA = (
cv.Schema(
{
cv.GenerateID(): cv.declare_id(APDS9960),
cv.Optional(CONF_LED_DRIVE, "100mA"): cv.enum(DRIVE_LEVELS, lower=True),
cv.Optional(CONF_PROXIMITY_GAIN, "4x"): cv.enum(
PROXIMITY_LEVELS, lower=True
),
cv.Optional(CONF_AMBIENT_LIGHT_GAIN, "4x"): cv.enum(
AMBIENT_LEVELS, lower=True
),
cv.Optional(CONF_GESTURE_LED_DRIVE, "100mA"): cv.enum(
DRIVE_LEVELS, lower=True
),
cv.Optional(CONF_GESTURE_GAIN, "4x"): cv.enum(GESTURE_LEVELS, lower=True),
cv.Optional(CONF_GESTURE_WAIT_TIME, "2.8ms"): cv.enum(
GESTURE_WAIT_TIMES, lower=True
),
}
)
.extend(cv.polling_component_schema("60s"))
@@ -27,3 +62,9 @@ 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_led_drive(config[CONF_LED_DRIVE]))
cg.add(var.set_proximity_gain(config[CONF_PROXIMITY_GAIN]))
cg.add(var.set_ambient_gain(config[CONF_AMBIENT_LIGHT_GAIN]))
cg.add(var.set_gesture_led_drive(config[CONF_GESTURE_LED_DRIVE]))
cg.add(var.set_gesture_gain(config[CONF_GESTURE_GAIN]))
cg.add(var.set_gesture_wait_time(config[CONF_GESTURE_WAIT_TIME]))
+13 -13
View File
@@ -46,16 +46,16 @@ void APDS9960::setup() {
uint8_t val = 0;
APDS9960_ERROR_CHECK(this->read_byte(0x8F, &val));
val &= 0b00111111;
uint8_t led_drive = 0; // led drive, 0 -> 100mA, 1 -> 50mA, 2 -> 25mA, 3 -> 12.5mA
val |= (led_drive & 0b11) << 6;
// led drive, 0 -> 100mA, 1 -> 50mA, 2 -> 25mA, 3 -> 12.5mA
val |= (this->led_drive_ & 0b11) << 6;
val &= 0b11110011;
uint8_t proximity_gain = 2; // proximity gain, 0 -> 1x, 1 -> 2X, 2 -> 4X, 4 -> 8X
val |= (proximity_gain & 0b11) << 2;
// proximity gain, 0 -> 1x, 1 -> 2X, 2 -> 4X, 3 -> 8X
val |= (this->proximity_gain_ & 0b11) << 2;
val &= 0b11111100;
uint8_t ambient_gain = 1; // ambient light gain, 0 -> 1x, 1 -> 4x, 2 -> 16x, 3 -> 64x
val |= (ambient_gain & 0b11) << 0;
// ambient light gain, 0 -> 1x, 1 -> 4x, 2 -> 16x, 3 -> 64x
val |= (this->ambient_gain_ & 0b11) << 0;
APDS9960_WRITE_BYTE(0x8F, val);
// Pers (0x8C) -> 0x11 (2 consecutive proximity or ALS for interrupt)
@@ -75,19 +75,18 @@ void APDS9960::setup() {
// GConf 2 (0xA3, gesture config 2) ->
APDS9960_ERROR_CHECK(this->read_byte(0xA3, &val));
val &= 0b10011111;
uint8_t gesture_gain = 2; // gesture gain, 0 -> 1x, 1 -> 2x, 2 -> 4x, 3 -> 8x
val |= (gesture_gain & 0b11) << 5;
// gesture gain, 0 -> 1x, 1 -> 2x, 2 -> 4x, 3 -> 8x
val |= (this->gesture_gain_ & 0b11) << 5;
val &= 0b11100111;
uint8_t gesture_led_drive = 0; // gesture led drive, 0 -> 100mA, 1 -> 50mA, 2 -> 25mA, 3 -> 12.5mA
val |= (gesture_led_drive & 0b11) << 3;
// gesture led drive, 0 -> 100mA, 1 -> 50mA, 2 -> 25mA, 3 -> 12.5mA
val |= (this->gesture_led_drive_ & 0b11) << 3;
val &= 0b11111000;
// gesture wait time
// 0 -> 0ms, 1 -> 2.8ms, 2 -> 5.6ms, 3 -> 8.4ms
// 4 -> 14.0ms, 5 -> 22.4 ms, 6 -> 30.8ms, 7 -> 39.2 ms
uint8_t gesture_wait_time = 1; // gesture wait time
val |= (gesture_wait_time & 0b111) << 0;
val |= (this->gesture_wait_time_ & 0b111) << 0;
APDS9960_WRITE_BYTE(0xA3, val);
// GOffsetU (0xA4) -> 0x00 (no offset)
@@ -225,9 +224,10 @@ void APDS9960::read_gesture_data_() {
uint8_t fifo_level;
APDS9960_WARNING_CHECK(this->read_byte(0xAE, &fifo_level), "Reading FIFO level failed.");
if (fifo_level == 0)
if (fifo_level == 0) {
// no data to process
return;
}
APDS9960_WARNING_CHECK(fifo_level <= 32, "FIFO level has invalid value.")
+14
View File
@@ -16,6 +16,13 @@ class APDS9960 : public PollingComponent, public i2c::I2CDevice {
void update() override;
void loop() override;
void set_led_drive(uint8_t level) { this->led_drive_ = level; }
void set_proximity_gain(uint8_t gain) { this->proximity_gain_ = gain; }
void set_ambient_gain(uint8_t gain) { this->ambient_gain_ = gain; }
void set_gesture_led_drive(uint8_t level) { this->gesture_led_drive_ = level; }
void set_gesture_gain(uint8_t gain) { this->gesture_gain_ = gain; }
void set_gesture_wait_time(uint8_t wait_time) { this->gesture_wait_time_ = wait_time; }
void set_red_channel(sensor::Sensor *red_channel) { red_channel_ = red_channel; }
void set_green_channel(sensor::Sensor *green_channel) { green_channel_ = green_channel; }
void set_blue_channel(sensor::Sensor *blue_channel) { blue_channel_ = blue_channel; }
@@ -36,6 +43,13 @@ class APDS9960 : public PollingComponent, public i2c::I2CDevice {
void report_gesture_(int gesture);
void process_dataset_(int up, int down, int left, int right);
uint8_t led_drive_;
uint8_t proximity_gain_;
uint8_t ambient_gain_;
uint8_t gesture_led_drive_;
uint8_t gesture_gain_;
uint8_t gesture_wait_time_;
sensor::Sensor *red_channel_{nullptr};
sensor::Sensor *green_channel_{nullptr};
sensor::Sensor *blue_channel_{nullptr};
+5 -6
View File
@@ -1,7 +1,7 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import binary_sensor
from esphome.const import CONF_DIRECTION, CONF_DEVICE_CLASS, DEVICE_CLASS_MOVING
from esphome.const import CONF_DIRECTION, DEVICE_CLASS_MOVING
from . import APDS9960, CONF_APDS9960_ID
DEPENDENCIES = ["apds9960"]
@@ -13,13 +13,12 @@ DIRECTIONS = {
"RIGHT": "set_right_direction",
}
CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend(
CONFIG_SCHEMA = binary_sensor.binary_sensor_schema(
device_class=DEVICE_CLASS_MOVING
).extend(
{
cv.Required(CONF_DIRECTION): cv.one_of(*DIRECTIONS, upper=True),
cv.GenerateID(CONF_APDS9960_ID): cv.use_id(APDS9960),
cv.Optional(
CONF_DEVICE_CLASS, default=DEVICE_CLASS_MOVING
): binary_sensor.device_class,
cv.Required(CONF_DIRECTION): cv.one_of(*DIRECTIONS, upper=True),
}
)
+321
View File
@@ -41,6 +41,18 @@ service APIConnection {
rpc number_command (NumberCommandRequest) returns (void) {}
rpc select_command (SelectCommandRequest) returns (void) {}
rpc button_command (ButtonCommandRequest) returns (void) {}
rpc lock_command (LockCommandRequest) returns (void) {}
rpc media_player_command (MediaPlayerCommandRequest) returns (void) {}
rpc subscribe_bluetooth_le_advertisements(SubscribeBluetoothLEAdvertisementsRequest) returns (void) {}
rpc bluetooth_device_request(BluetoothDeviceRequest) returns (void) {}
rpc bluetooth_gatt_get_services(BluetoothGATTGetServicesRequest) returns (void) {}
rpc bluetooth_gatt_read(BluetoothGATTReadRequest) returns (void) {}
rpc bluetooth_gatt_write(BluetoothGATTWriteRequest) returns (void) {}
rpc bluetooth_gatt_read_descriptor(BluetoothGATTReadDescriptorRequest) returns (void) {}
rpc bluetooth_gatt_write_descriptor(BluetoothGATTWriteDescriptorRequest) returns (void) {}
rpc bluetooth_gatt_notify(BluetoothGATTNotifyRequest) returns (void) {}
rpc subscribe_bluetooth_connections_free(SubscribeBluetoothConnectionsFreeRequest) returns (BluetoothConnectionsFreeResponse) {}
}
@@ -75,6 +87,8 @@ message HelloRequest {
// Not strictly necessary to send but nice for debugging
// purposes.
string client_info = 1;
uint32 api_version_major = 2;
uint32 api_version_minor = 3;
}
// Confirmation of successful connection request.
@@ -95,6 +109,9 @@ message HelloResponse {
// and only exists for debugging/logging purposes.
// For example "ESPHome v1.10.0 on ESP8266"
string server_info = 3;
// The name of the server (App.get_name())
string name = 4;
}
// Message sent at the beginning of each connection to authenticate the client
@@ -185,6 +202,8 @@ message DeviceInfoResponse {
string project_version = 9;
uint32 webserver_port = 10;
uint32 bluetooth_proxy_version = 11;
}
message ListEntitiesRequest {
@@ -468,6 +487,7 @@ enum SensorStateClass {
STATE_CLASS_NONE = 0;
STATE_CLASS_MEASUREMENT = 1;
STATE_CLASS_TOTAL_INCREASING = 2;
STATE_CLASS_TOTAL = 3;
}
enum SensorLastResetType {
@@ -525,6 +545,7 @@ message ListEntitiesSwitchResponse {
bool assumed_state = 6;
bool disabled_by_default = 7;
EntityCategory entity_category = 8;
string device_class = 9;
}
message SwitchStateResponse {
option (id) = 26;
@@ -953,6 +974,63 @@ message SelectCommandRequest {
string state = 2;
}
// ==================== LOCK ====================
enum LockState {
LOCK_STATE_NONE = 0;
LOCK_STATE_LOCKED = 1;
LOCK_STATE_UNLOCKED = 2;
LOCK_STATE_JAMMED = 3;
LOCK_STATE_LOCKING = 4;
LOCK_STATE_UNLOCKING = 5;
}
enum LockCommand {
LOCK_UNLOCK = 0;
LOCK_LOCK = 1;
LOCK_OPEN = 2;
}
message ListEntitiesLockResponse {
option (id) = 58;
option (source) = SOURCE_SERVER;
option (ifdef) = "USE_LOCK";
string object_id = 1;
fixed32 key = 2;
string name = 3;
string unique_id = 4;
string icon = 5;
bool disabled_by_default = 6;
EntityCategory entity_category = 7;
bool assumed_state = 8;
bool supports_open = 9;
bool requires_code = 10;
// Not yet implemented:
string code_format = 11;
}
message LockStateResponse {
option (id) = 59;
option (source) = SOURCE_SERVER;
option (ifdef) = "USE_LOCK";
option (no_delay) = true;
fixed32 key = 1;
LockState state = 2;
}
message LockCommandRequest {
option (id) = 60;
option (source) = SOURCE_CLIENT;
option (ifdef) = "USE_LOCK";
option (no_delay) = true;
fixed32 key = 1;
LockCommand command = 2;
// Not yet implemented:
bool has_code = 3;
string code = 4;
}
// ==================== BUTTON ====================
message ListEntitiesButtonResponse {
option (id) = 61;
@@ -977,3 +1055,246 @@ message ButtonCommandRequest {
fixed32 key = 1;
}
// ==================== MEDIA PLAYER ====================
enum MediaPlayerState {
MEDIA_PLAYER_STATE_NONE = 0;
MEDIA_PLAYER_STATE_IDLE = 1;
MEDIA_PLAYER_STATE_PLAYING = 2;
MEDIA_PLAYER_STATE_PAUSED = 3;
}
enum MediaPlayerCommand {
MEDIA_PLAYER_COMMAND_PLAY = 0;
MEDIA_PLAYER_COMMAND_PAUSE = 1;
MEDIA_PLAYER_COMMAND_STOP = 2;
MEDIA_PLAYER_COMMAND_MUTE = 3;
MEDIA_PLAYER_COMMAND_UNMUTE = 4;
}
message ListEntitiesMediaPlayerResponse {
option (id) = 63;
option (source) = SOURCE_SERVER;
option (ifdef) = "USE_MEDIA_PLAYER";
string object_id = 1;
fixed32 key = 2;
string name = 3;
string unique_id = 4;
string icon = 5;
bool disabled_by_default = 6;
EntityCategory entity_category = 7;
bool supports_pause = 8;
}
message MediaPlayerStateResponse {
option (id) = 64;
option (source) = SOURCE_SERVER;
option (ifdef) = "USE_MEDIA_PLAYER";
option (no_delay) = true;
fixed32 key = 1;
MediaPlayerState state = 2;
float volume = 3;
bool muted = 4;
}
message MediaPlayerCommandRequest {
option (id) = 65;
option (source) = SOURCE_CLIENT;
option (ifdef) = "USE_MEDIA_PLAYER";
option (no_delay) = true;
fixed32 key = 1;
bool has_command = 2;
MediaPlayerCommand command = 3;
bool has_volume = 4;
float volume = 5;
bool has_media_url = 6;
string media_url = 7;
}
// ==================== BLUETOOTH ====================
message SubscribeBluetoothLEAdvertisementsRequest {
option (id) = 66;
option (source) = SOURCE_CLIENT;
}
message BluetoothServiceData {
string uuid = 1;
repeated uint32 legacy_data = 2 [deprecated = true];
bytes data = 3; // Changed in proto version 1.7
}
message BluetoothLEAdvertisementResponse {
option (id) = 67;
option (source) = SOURCE_SERVER;
option (ifdef) = "USE_BLUETOOTH_PROXY";
option (no_delay) = true;
uint64 address = 1;
string name = 2;
sint32 rssi = 3;
repeated string service_uuids = 4;
repeated BluetoothServiceData service_data = 5;
repeated BluetoothServiceData manufacturer_data = 6;
}
enum BluetoothDeviceRequestType {
BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT = 0;
BLUETOOTH_DEVICE_REQUEST_TYPE_DISCONNECT = 1;
BLUETOOTH_DEVICE_REQUEST_TYPE_PAIR = 2;
BLUETOOTH_DEVICE_REQUEST_TYPE_UNPAIR = 3;
}
message BluetoothDeviceRequest {
option (id) = 68;
option (source) = SOURCE_CLIENT;
option (ifdef) = "USE_BLUETOOTH_PROXY";
uint64 address = 1;
BluetoothDeviceRequestType request_type = 2;
}
message BluetoothDeviceConnectionResponse {
option (id) = 69;
option (source) = SOURCE_SERVER;
option (ifdef) = "USE_BLUETOOTH_PROXY";
uint64 address = 1;
bool connected = 2;
uint32 mtu = 3;
int32 error = 4;
}
message BluetoothGATTGetServicesRequest {
option (id) = 70;
option (source) = SOURCE_CLIENT;
option (ifdef) = "USE_BLUETOOTH_PROXY";
uint64 address = 1;
}
message BluetoothGATTDescriptor {
repeated uint64 uuid = 1;
uint32 handle = 2;
}
message BluetoothGATTCharacteristic {
repeated uint64 uuid = 1;
uint32 handle = 2;
uint32 properties = 3;
repeated BluetoothGATTDescriptor descriptors = 4;
}
message BluetoothGATTService {
repeated uint64 uuid = 1;
uint32 handle = 2;
repeated BluetoothGATTCharacteristic characteristics = 3;
}
message BluetoothGATTGetServicesResponse {
option (id) = 71;
option (source) = SOURCE_SERVER;
option (ifdef) = "USE_BLUETOOTH_PROXY";
uint64 address = 1;
repeated BluetoothGATTService services = 2;
}
message BluetoothGATTGetServicesDoneResponse {
option (id) = 72;
option (source) = SOURCE_SERVER;
option (ifdef) = "USE_BLUETOOTH_PROXY";
uint64 address = 1;
}
message BluetoothGATTReadRequest {
option (id) = 73;
option (source) = SOURCE_CLIENT;
option (ifdef) = "USE_BLUETOOTH_PROXY";
uint64 address = 1;
uint32 handle = 2;
}
message BluetoothGATTReadResponse {
option (id) = 74;
option (source) = SOURCE_SERVER;
option (ifdef) = "USE_BLUETOOTH_PROXY";
uint64 address = 1;
uint32 handle = 2;
bytes data = 3;
}
message BluetoothGATTWriteRequest {
option (id) = 75;
option (source) = SOURCE_CLIENT;
option (ifdef) = "USE_BLUETOOTH_PROXY";
uint64 address = 1;
uint32 handle = 2;
bool response = 3;
bytes data = 4;
}
message BluetoothGATTReadDescriptorRequest {
option (id) = 76;
option (source) = SOURCE_CLIENT;
option (ifdef) = "USE_BLUETOOTH_PROXY";
uint64 address = 1;
uint32 handle = 2;
}
message BluetoothGATTWriteDescriptorRequest {
option (id) = 77;
option (source) = SOURCE_CLIENT;
option (ifdef) = "USE_BLUETOOTH_PROXY";
uint64 address = 1;
uint32 handle = 2;
bytes data = 3;
}
message BluetoothGATTNotifyRequest {
option (id) = 78;
option (source) = SOURCE_CLIENT;
option (ifdef) = "USE_BLUETOOTH_PROXY";
uint64 address = 1;
uint32 handle = 2;
bool enable = 3;
}
message BluetoothGATTNotifyDataResponse {
option (id) = 79;
option (source) = SOURCE_SERVER;
option (ifdef) = "USE_BLUETOOTH_PROXY";
uint64 address = 1;
uint32 handle = 2;
bytes data = 3;
}
message SubscribeBluetoothConnectionsFreeRequest {
option (id) = 80;
option (source) = SOURCE_CLIENT;
option (ifdef) = "USE_BLUETOOTH_PROXY";
}
message BluetoothConnectionsFreeResponse {
option (id) = 81;
option (source) = SOURCE_SERVER;
option (ifdef) = "USE_BLUETOOTH_PROXY";
uint32 free = 1;
uint32 limit = 2;
}
+169 -27
View File
@@ -1,10 +1,10 @@
#include "api_connection.h"
#include "esphome/core/entity_base.h"
#include "esphome/core/log.h"
#include "esphome/components/network/util.h"
#include "esphome/core/version.h"
#include "esphome/core/hal.h"
#include <cerrno>
#include "esphome/components/network/util.h"
#include "esphome/core/entity_base.h"
#include "esphome/core/hal.h"
#include "esphome/core/log.h"
#include "esphome/core/version.h"
#ifdef USE_DEEP_SLEEP
#include "esphome/components/deep_sleep/deep_sleep_component.h"
@@ -12,8 +12,8 @@
#ifdef USE_HOMEASSISTANT_TIME
#include "esphome/components/homeassistant/time/homeassistant_time.h"
#endif
#ifdef USE_FAN
#include "esphome/components/fan/fan_helpers.h"
#ifdef USE_BLUETOOTH_PROXY
#include "esphome/components/bluetooth_proxy/bluetooth_proxy.h"
#endif
namespace esphome {
@@ -23,7 +23,7 @@ static const char *const TAG = "api.connection";
static const int ESP32_CAMERA_STOP_STREAM = 5000;
APIConnection::APIConnection(std::unique_ptr<socket::Socket> sock, APIServer *parent)
: parent_(parent), initial_state_iterator_(parent, this), list_entities_iterator_(parent, this) {
: parent_(parent), initial_state_iterator_(this), list_entities_iterator_(this) {
this->proto_write_buffer_.reserve(64);
#if defined(USE_API_PLAINTEXT)
@@ -105,6 +105,7 @@ void APIConnection::loop() {
ESP_LOGW(TAG, "%s didn't respond to ping request in time. Disconnecting...", this->client_info_.c_str());
}
} else if (now - this->last_traffic_ > keepalive) {
ESP_LOGVV(TAG, "Sending keepalive PING...");
this->sent_ping_ = true;
this->send_ping_request(PingRequest());
}
@@ -252,10 +253,7 @@ void APIConnection::cover_command(const CoverCommandRequest &msg) {
#endif
#ifdef USE_FAN
// Shut-up about usage of deprecated speed_level_to_enum/speed_enum_to_level functions for a bit.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
bool APIConnection::send_fan_state(fan::FanState *fan) {
bool APIConnection::send_fan_state(fan::Fan *fan) {
if (!this->state_subscription_)
return false;
@@ -267,13 +265,12 @@ bool APIConnection::send_fan_state(fan::FanState *fan) {
resp.oscillating = fan->oscillating;
if (traits.supports_speed()) {
resp.speed_level = fan->speed;
resp.speed = static_cast<enums::FanSpeed>(fan::speed_level_to_enum(fan->speed, traits.supported_speed_count()));
}
if (traits.supports_direction())
resp.direction = static_cast<enums::FanDirection>(fan->direction);
return this->send_fan_state_response(resp);
}
bool APIConnection::send_fan_info(fan::FanState *fan) {
bool APIConnection::send_fan_info(fan::Fan *fan) {
auto traits = fan->get_traits();
ListEntitiesFanResponse msg;
msg.key = fan->get_object_id_hash();
@@ -290,12 +287,10 @@ bool APIConnection::send_fan_info(fan::FanState *fan) {
return this->send_list_entities_fan_response(msg);
}
void APIConnection::fan_command(const FanCommandRequest &msg) {
fan::FanState *fan = App.get_fan_by_key(msg.key);
fan::Fan *fan = App.get_fan_by_key(msg.key);
if (fan == nullptr)
return;
auto traits = fan->get_traits();
auto call = fan->make_call();
if (msg.has_state)
call.set_state(msg.state);
@@ -304,14 +299,11 @@ void APIConnection::fan_command(const FanCommandRequest &msg) {
if (msg.has_speed_level) {
// Prefer level
call.set_speed(msg.speed_level);
} else if (msg.has_speed) {
call.set_speed(fan::speed_enum_to_level(static_cast<fan::FanSpeed>(msg.speed), traits.supported_speed_count()));
}
if (msg.has_direction)
call.set_direction(static_cast<fan::FanDirection>(msg.direction));
call.perform();
}
#pragma GCC diagnostic pop
#endif
#ifdef USE_LIGHT
@@ -462,6 +454,7 @@ bool APIConnection::send_switch_info(switch_::Switch *a_switch) {
msg.assumed_state = a_switch->assumed_state();
msg.disabled_by_default = a_switch->is_disabled_by_default();
msg.entity_category = static_cast<enums::EntityCategory>(a_switch->get_entity_category());
msg.device_class = a_switch->get_device_class();
return this->send_list_entities_switch_response(msg);
}
void APIConnection::switch_command(const SwitchCommandRequest &msg) {
@@ -469,10 +462,11 @@ void APIConnection::switch_command(const SwitchCommandRequest &msg) {
if (a_switch == nullptr)
return;
if (msg.state)
if (msg.state) {
a_switch->turn_on();
else
} else {
a_switch->turn_off();
}
}
#endif
@@ -699,6 +693,95 @@ void APIConnection::button_command(const ButtonCommandRequest &msg) {
}
#endif
#ifdef USE_LOCK
bool APIConnection::send_lock_state(lock::Lock *a_lock, lock::LockState state) {
if (!this->state_subscription_)
return false;
LockStateResponse resp{};
resp.key = a_lock->get_object_id_hash();
resp.state = static_cast<enums::LockState>(state);
return this->send_lock_state_response(resp);
}
bool APIConnection::send_lock_info(lock::Lock *a_lock) {
ListEntitiesLockResponse msg;
msg.key = a_lock->get_object_id_hash();
msg.object_id = a_lock->get_object_id();
msg.name = a_lock->get_name();
msg.unique_id = get_default_unique_id("lock", a_lock);
msg.icon = a_lock->get_icon();
msg.assumed_state = a_lock->traits.get_assumed_state();
msg.disabled_by_default = a_lock->is_disabled_by_default();
msg.entity_category = static_cast<enums::EntityCategory>(a_lock->get_entity_category());
msg.supports_open = a_lock->traits.get_supports_open();
msg.requires_code = a_lock->traits.get_requires_code();
return this->send_list_entities_lock_response(msg);
}
void APIConnection::lock_command(const LockCommandRequest &msg) {
lock::Lock *a_lock = App.get_lock_by_key(msg.key);
if (a_lock == nullptr)
return;
switch (msg.command) {
case enums::LOCK_UNLOCK:
a_lock->unlock();
break;
case enums::LOCK_LOCK:
a_lock->lock();
break;
case enums::LOCK_OPEN:
a_lock->open();
break;
}
}
#endif
#ifdef USE_MEDIA_PLAYER
bool APIConnection::send_media_player_state(media_player::MediaPlayer *media_player) {
if (!this->state_subscription_)
return false;
MediaPlayerStateResponse resp{};
resp.key = media_player->get_object_id_hash();
resp.state = static_cast<enums::MediaPlayerState>(media_player->state);
resp.volume = media_player->volume;
resp.muted = media_player->is_muted();
return this->send_media_player_state_response(resp);
}
bool APIConnection::send_media_player_info(media_player::MediaPlayer *media_player) {
ListEntitiesMediaPlayerResponse msg;
msg.key = media_player->get_object_id_hash();
msg.object_id = media_player->get_object_id();
msg.name = media_player->get_name();
msg.unique_id = get_default_unique_id("media_player", media_player);
msg.icon = media_player->get_icon();
msg.disabled_by_default = media_player->is_disabled_by_default();
msg.entity_category = static_cast<enums::EntityCategory>(media_player->get_entity_category());
auto traits = media_player->get_traits();
msg.supports_pause = traits.get_supports_pause();
return this->send_list_entities_media_player_response(msg);
}
void APIConnection::media_player_command(const MediaPlayerCommandRequest &msg) {
media_player::MediaPlayer *media_player = App.get_media_player_by_key(msg.key);
if (media_player == nullptr)
return;
auto call = media_player->make_call();
if (msg.has_command) {
call.set_command(static_cast<media_player::MediaPlayerCommand>(msg.command));
}
if (msg.has_volume) {
call.set_volume(msg.volume);
}
if (msg.has_media_url) {
call.set_media_url(msg.media_url);
}
call.perform();
}
#endif
#ifdef USE_ESP32_CAMERA
void APIConnection::send_camera_state(std::shared_ptr<esp32_camera::CameraImage> image) {
if (!this->state_subscription_)
@@ -743,6 +826,56 @@ void APIConnection::on_get_time_response(const GetTimeResponse &value) {
}
#endif
#ifdef USE_BLUETOOTH_PROXY
bool APIConnection::send_bluetooth_le_advertisement(const BluetoothLEAdvertisementResponse &msg) {
if (!this->bluetooth_le_advertisement_subscription_)
return false;
if (this->client_api_version_major_ < 1 || this->client_api_version_minor_ < 7) {
BluetoothLEAdvertisementResponse resp = msg;
for (auto &service : resp.service_data) {
service.legacy_data.assign(service.data.begin(), service.data.end());
service.data.clear();
}
for (auto &manufacturer_data : resp.manufacturer_data) {
manufacturer_data.legacy_data.assign(manufacturer_data.data.begin(), manufacturer_data.data.end());
manufacturer_data.data.clear();
}
return this->send_bluetooth_le_advertisement_response(resp);
}
return this->send_bluetooth_le_advertisement_response(msg);
}
void APIConnection::bluetooth_device_request(const BluetoothDeviceRequest &msg) {
bluetooth_proxy::global_bluetooth_proxy->bluetooth_device_request(msg);
}
void APIConnection::bluetooth_gatt_read(const BluetoothGATTReadRequest &msg) {
bluetooth_proxy::global_bluetooth_proxy->bluetooth_gatt_read(msg);
}
void APIConnection::bluetooth_gatt_write(const BluetoothGATTWriteRequest &msg) {
bluetooth_proxy::global_bluetooth_proxy->bluetooth_gatt_write(msg);
}
void APIConnection::bluetooth_gatt_read_descriptor(const BluetoothGATTReadDescriptorRequest &msg) {
bluetooth_proxy::global_bluetooth_proxy->bluetooth_gatt_read_descriptor(msg);
}
void APIConnection::bluetooth_gatt_write_descriptor(const BluetoothGATTWriteDescriptorRequest &msg) {
bluetooth_proxy::global_bluetooth_proxy->bluetooth_gatt_write_descriptor(msg);
}
void APIConnection::bluetooth_gatt_get_services(const BluetoothGATTGetServicesRequest &msg) {
bluetooth_proxy::global_bluetooth_proxy->bluetooth_gatt_send_services(msg);
}
void APIConnection::bluetooth_gatt_notify(const BluetoothGATTNotifyRequest &msg) {
bluetooth_proxy::global_bluetooth_proxy->bluetooth_gatt_notify(msg);
}
BluetoothConnectionsFreeResponse APIConnection::subscribe_bluetooth_connections_free(
const SubscribeBluetoothConnectionsFreeRequest &msg) {
BluetoothConnectionsFreeResponse resp;
resp.free = bluetooth_proxy::global_bluetooth_proxy->get_bluetooth_connections_free();
resp.limit = bluetooth_proxy::global_bluetooth_proxy->get_bluetooth_connections_limit();
return resp;
}
#endif
bool APIConnection::send_log_message(int level, const char *tag, const char *line) {
if (this->log_subscription_ < level)
return false;
@@ -760,12 +893,17 @@ bool APIConnection::send_log_message(int level, const char *tag, const char *lin
HelloResponse APIConnection::hello(const HelloRequest &msg) {
this->client_info_ = msg.client_info + " (" + this->helper_->getpeername() + ")";
this->helper_->set_log_info(client_info_);
ESP_LOGV(TAG, "Hello from client: '%s'", this->client_info_.c_str());
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(),
this->client_api_version_major_, this->client_api_version_minor_);
HelloResponse resp;
resp.api_version_major = 1;
resp.api_version_minor = 6;
resp.api_version_minor = 7;
resp.server_info = App.get_name() + " (esphome v" ESPHOME_VERSION ")";
resp.name = App.get_name();
this->connection_state_ = ConnectionState::CONNECTED;
return resp;
}
@@ -803,15 +941,19 @@ DeviceInfoResponse APIConnection::device_info(const DeviceInfoRequest &msg) {
resp.project_version = ESPHOME_PROJECT_VERSION;
#endif
#ifdef USE_WEBSERVER
resp.webserver_port = WEBSERVER_PORT;
resp.webserver_port = USE_WEBSERVER_PORT;
#endif
#ifdef USE_BLUETOOTH_PROXY
resp.bluetooth_proxy_version = bluetooth_proxy::global_bluetooth_proxy->has_active() ? 2 : 1;
#endif
return resp;
}
void APIConnection::on_home_assistant_state_response(const HomeAssistantStateResponse &msg) {
for (auto &it : this->parent_->get_state_subs())
for (auto &it : this->parent_->get_state_subs()) {
if (it.entity_id == msg.entity_id && it.attribute.value() == msg.attribute) {
it.callback(msg.state);
}
}
}
void APIConnection::execute_service(const ExecuteServiceRequest &msg) {
bool found = false;
@@ -860,7 +1002,7 @@ bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint32_t message_type)
}
return false;
}
this->last_traffic_ = millis();
// Do not set last_traffic_ on send
return true;
}
void APIConnection::on_unauthenticated_access() {
+35 -5
View File
@@ -1,11 +1,11 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/core/application.h"
#include "api_frame_helper.h"
#include "api_pb2.h"
#include "api_pb2_service.h"
#include "api_server.h"
#include "api_frame_helper.h"
#include "esphome/core/application.h"
#include "esphome/core/component.h"
namespace esphome {
namespace api {
@@ -32,8 +32,8 @@ class APIConnection : public APIServerConnection {
void cover_command(const CoverCommandRequest &msg) override;
#endif
#ifdef USE_FAN
bool send_fan_state(fan::FanState *fan);
bool send_fan_info(fan::FanState *fan);
bool send_fan_state(fan::Fan *fan);
bool send_fan_info(fan::Fan *fan);
void fan_command(const FanCommandRequest &msg) override;
#endif
#ifdef USE_LIGHT
@@ -77,6 +77,16 @@ class APIConnection : public APIServerConnection {
#ifdef USE_BUTTON
bool send_button_info(button::Button *button);
void button_command(const ButtonCommandRequest &msg) override;
#endif
#ifdef USE_LOCK
bool send_lock_state(lock::Lock *a_lock, lock::LockState state);
bool send_lock_info(lock::Lock *a_lock);
void lock_command(const LockCommandRequest &msg) override;
#endif
#ifdef USE_MEDIA_PLAYER
bool send_media_player_state(media_player::MediaPlayer *media_player);
bool send_media_player_info(media_player::MediaPlayer *media_player);
void media_player_command(const MediaPlayerCommandRequest &msg) override;
#endif
bool send_log_message(int level, const char *tag, const char *line);
void send_homeassistant_service_call(const HomeassistantServiceResponse &call) {
@@ -84,6 +94,20 @@ class APIConnection : public APIServerConnection {
return;
this->send_homeassistant_service_response(call);
}
#ifdef USE_BLUETOOTH_PROXY
bool send_bluetooth_le_advertisement(const BluetoothLEAdvertisementResponse &msg);
void bluetooth_device_request(const BluetoothDeviceRequest &msg) override;
void bluetooth_gatt_read(const BluetoothGATTReadRequest &msg) override;
void bluetooth_gatt_write(const BluetoothGATTWriteRequest &msg) override;
void bluetooth_gatt_read_descriptor(const BluetoothGATTReadDescriptorRequest &msg) override;
void bluetooth_gatt_write_descriptor(const BluetoothGATTWriteDescriptorRequest &msg) override;
void bluetooth_gatt_get_services(const BluetoothGATTGetServicesRequest &msg) override;
void bluetooth_gatt_notify(const BluetoothGATTNotifyRequest &msg) override;
BluetoothConnectionsFreeResponse subscribe_bluetooth_connections_free(
const SubscribeBluetoothConnectionsFreeRequest &msg) override;
#endif
#ifdef USE_HOMEASSISTANT_TIME
void send_time_request() {
GetTimeRequest req;
@@ -124,6 +148,9 @@ 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();
@@ -157,6 +184,8 @@ class APIConnection : public APIServerConnection {
std::unique_ptr<APIFrameHelper> helper_;
std::string client_info_;
uint32_t client_api_version_major_{0};
uint32_t client_api_version_minor_{0};
#ifdef USE_ESP32_CAMERA
esp32_camera::CameraImageReader image_reader_;
#endif
@@ -166,6 +195,7 @@ class APIConnection : public APIServerConnection {
uint32_t last_traffic_;
bool sent_ping_{false};
bool service_call_subscription_{false};
bool bluetooth_le_advertisement_subscription_{false};
bool next_close_ = false;
APIServer *parent_;
InitialStateIterator initial_state_iterator_;
+14 -6
View File
@@ -3,6 +3,7 @@
#include "esphome/core/log.h"
#include "esphome/core/hal.h"
#include "esphome/core/helpers.h"
#include "esphome/core/application.h"
#include "proto.h"
#include <cstring>
@@ -269,7 +270,7 @@ APIError APINoiseFrameHelper::try_read_frame_(ParsedFrame *frame) {
*
* If the handshake is still active when this method returns and a read/write can't take place at
* the moment, returns WOULD_BLOCK.
* If an error occured, returns that error. Only returns OK if the transport is ready for data
* If an error occurred, returns that error. Only returns OK if the transport is ready for data
* traffic.
*/
APIError APINoiseFrameHelper::state_action_() {
@@ -302,9 +303,16 @@ APIError APINoiseFrameHelper::state_action_() {
}
if (state_ == State::SERVER_HELLO) {
// send server hello
uint8_t msg[1];
msg[0] = 0x01; // chosen proto
aerr = write_frame_(msg, 1);
std::vector<uint8_t> msg;
// chosen proto
msg.push_back(0x01);
// node name, terminated by null byte
const std::string &name = App.get_name();
const uint8_t *name_ptr = reinterpret_cast<const uint8_t *>(name.c_str());
msg.insert(msg.end(), name_ptr, name_ptr + name.size() + 1);
aerr = write_frame_(msg.data(), msg.size());
if (aerr != APIError::OK)
return aerr;
@@ -578,7 +586,7 @@ APIError APINoiseFrameHelper::write_raw_(const struct iovec *iov, int iovcnt) {
}
return APIError::OK;
} else if (sent == -1) {
// an error occured
// an error occurred
state_ = State::FAILED;
HELPER_LOG("Socket write failed with errno %d", errno);
return APIError::SOCKET_WRITE_FAILED;
@@ -972,7 +980,7 @@ APIError APIPlaintextFrameHelper::write_raw_(const struct iovec *iov, int iovcnt
}
return APIError::OK;
} else if (sent == -1) {
// an error occured
// an error occurred
state_ = State::FAILED;
HELPER_LOG("Socket write failed with errno %d", errno);
return APIError::SOCKET_WRITE_FAILED;
+3 -3
View File
@@ -116,9 +116,9 @@ class APINoiseFrameHelper : public APIFrameHelper {
std::vector<uint8_t> prologue_;
std::shared_ptr<APINoiseContext> ctx_;
NoiseHandshakeState *handshake_ = nullptr;
NoiseCipherState *send_cipher_ = nullptr;
NoiseCipherState *recv_cipher_ = nullptr;
NoiseHandshakeState *handshake_{nullptr};
NoiseCipherState *send_cipher_{nullptr};
NoiseCipherState *recv_cipher_{nullptr};
NoiseProtocolId nid_;
enum class State {
File diff suppressed because it is too large Load Diff
+402
View File
@@ -53,6 +53,7 @@ enum SensorStateClass : uint32_t {
STATE_CLASS_NONE = 0,
STATE_CLASS_MEASUREMENT = 1,
STATE_CLASS_TOTAL_INCREASING = 2,
STATE_CLASS_TOTAL = 3,
};
enum SensorLastResetType : uint32_t {
LAST_RESET_NONE = 0,
@@ -128,12 +129,46 @@ enum NumberMode : uint32_t {
NUMBER_MODE_BOX = 1,
NUMBER_MODE_SLIDER = 2,
};
enum LockState : uint32_t {
LOCK_STATE_NONE = 0,
LOCK_STATE_LOCKED = 1,
LOCK_STATE_UNLOCKED = 2,
LOCK_STATE_JAMMED = 3,
LOCK_STATE_LOCKING = 4,
LOCK_STATE_UNLOCKING = 5,
};
enum LockCommand : uint32_t {
LOCK_UNLOCK = 0,
LOCK_LOCK = 1,
LOCK_OPEN = 2,
};
enum MediaPlayerState : uint32_t {
MEDIA_PLAYER_STATE_NONE = 0,
MEDIA_PLAYER_STATE_IDLE = 1,
MEDIA_PLAYER_STATE_PLAYING = 2,
MEDIA_PLAYER_STATE_PAUSED = 3,
};
enum MediaPlayerCommand : uint32_t {
MEDIA_PLAYER_COMMAND_PLAY = 0,
MEDIA_PLAYER_COMMAND_PAUSE = 1,
MEDIA_PLAYER_COMMAND_STOP = 2,
MEDIA_PLAYER_COMMAND_MUTE = 3,
MEDIA_PLAYER_COMMAND_UNMUTE = 4,
};
enum BluetoothDeviceRequestType : uint32_t {
BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT = 0,
BLUETOOTH_DEVICE_REQUEST_TYPE_DISCONNECT = 1,
BLUETOOTH_DEVICE_REQUEST_TYPE_PAIR = 2,
BLUETOOTH_DEVICE_REQUEST_TYPE_UNPAIR = 3,
};
} // namespace enums
class HelloRequest : public ProtoMessage {
public:
std::string client_info{};
uint32_t api_version_major{0};
uint32_t api_version_minor{0};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
@@ -141,12 +176,14 @@ class HelloRequest : public ProtoMessage {
protected:
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
class HelloResponse : public ProtoMessage {
public:
uint32_t api_version_major{0};
uint32_t api_version_minor{0};
std::string server_info{};
std::string name{};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
@@ -235,6 +272,7 @@ class DeviceInfoResponse : public ProtoMessage {
std::string project_name{};
std::string project_version{};
uint32_t webserver_port{0};
uint32_t bluetooth_proxy_version{0};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
@@ -566,6 +604,7 @@ class ListEntitiesSwitchResponse : public ProtoMessage {
bool assumed_state{false};
bool disabled_by_default{false};
enums::EntityCategory entity_category{};
std::string device_class{};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
@@ -1048,6 +1087,58 @@ class SelectCommandRequest : public ProtoMessage {
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
};
class ListEntitiesLockResponse : public ProtoMessage {
public:
std::string object_id{};
uint32_t key{0};
std::string name{};
std::string unique_id{};
std::string icon{};
bool disabled_by_default{false};
enums::EntityCategory entity_category{};
bool assumed_state{false};
bool supports_open{false};
bool requires_code{false};
std::string code_format{};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
#endif
protected:
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
class LockStateResponse : public ProtoMessage {
public:
uint32_t key{0};
enums::LockState state{};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
#endif
protected:
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
class LockCommandRequest : public ProtoMessage {
public:
uint32_t key{0};
enums::LockCommand command{};
bool has_code{false};
std::string code{};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
#endif
protected:
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
class ListEntitiesButtonResponse : public ProtoMessage {
public:
std::string object_id{};
@@ -1079,6 +1170,317 @@ class ButtonCommandRequest : public ProtoMessage {
protected:
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
};
class ListEntitiesMediaPlayerResponse : public ProtoMessage {
public:
std::string object_id{};
uint32_t key{0};
std::string name{};
std::string unique_id{};
std::string icon{};
bool disabled_by_default{false};
enums::EntityCategory entity_category{};
bool supports_pause{false};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
#endif
protected:
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
class MediaPlayerStateResponse : public ProtoMessage {
public:
uint32_t key{0};
enums::MediaPlayerState state{};
float volume{0.0f};
bool muted{false};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
#endif
protected:
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
class MediaPlayerCommandRequest : public ProtoMessage {
public:
uint32_t key{0};
bool has_command{false};
enums::MediaPlayerCommand command{};
bool has_volume{false};
float volume{0.0f};
bool has_media_url{false};
std::string media_url{};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
#endif
protected:
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
class SubscribeBluetoothLEAdvertisementsRequest : 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 BluetoothServiceData : public ProtoMessage {
public:
std::string uuid{};
std::vector<uint32_t> legacy_data{};
std::string 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;
};
class BluetoothLEAdvertisementResponse : public ProtoMessage {
public:
uint64_t address{0};
std::string name{};
int32_t rssi{0};
std::vector<std::string> service_uuids{};
std::vector<BluetoothServiceData> service_data{};
std::vector<BluetoothServiceData> manufacturer_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;
};
class BluetoothDeviceRequest : public ProtoMessage {
public:
uint64_t address{0};
enums::BluetoothDeviceRequestType request_type{};
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 BluetoothDeviceConnectionResponse : public ProtoMessage {
public:
uint64_t address{0};
bool connected{false};
uint32_t mtu{0};
int32_t error{0};
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 BluetoothGATTGetServicesRequest : public ProtoMessage {
public:
uint64_t address{0};
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 BluetoothGATTDescriptor : public ProtoMessage {
public:
std::vector<uint64_t> uuid{};
uint32_t handle{0};
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 BluetoothGATTCharacteristic : public ProtoMessage {
public:
std::vector<uint64_t> uuid{};
uint32_t handle{0};
uint32_t properties{0};
std::vector<BluetoothGATTDescriptor> descriptors{};
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;
};
class BluetoothGATTService : public ProtoMessage {
public:
std::vector<uint64_t> uuid{};
uint32_t handle{0};
std::vector<BluetoothGATTCharacteristic> characteristics{};
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;
};
class BluetoothGATTGetServicesResponse : public ProtoMessage {
public:
uint64_t address{0};
std::vector<BluetoothGATTService> services{};
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;
};
class BluetoothGATTGetServicesDoneResponse : public ProtoMessage {
public:
uint64_t address{0};
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 BluetoothGATTReadRequest : public ProtoMessage {
public:
uint64_t address{0};
uint32_t handle{0};
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 BluetoothGATTReadResponse : public ProtoMessage {
public:
uint64_t address{0};
uint32_t handle{0};
std::string 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;
};
class BluetoothGATTWriteRequest : public ProtoMessage {
public:
uint64_t address{0};
uint32_t handle{0};
bool response{false};
std::string 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;
};
class BluetoothGATTReadDescriptorRequest : public ProtoMessage {
public:
uint64_t address{0};
uint32_t handle{0};
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 BluetoothGATTWriteDescriptorRequest : public ProtoMessage {
public:
uint64_t address{0};
uint32_t handle{0};
std::string 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;
};
class BluetoothGATTNotifyRequest : public ProtoMessage {
public:
uint64_t address{0};
uint32_t handle{0};
bool enable{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 BluetoothGATTNotifyDataResponse : public ProtoMessage {
public:
uint64_t address{0};
uint32_t handle{0};
std::string 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;
};
class SubscribeBluetoothConnectionsFreeRequest : 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 BluetoothConnectionsFreeResponse : public ProtoMessage {
public:
uint32_t free{0};
uint32_t limit{0};
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;
};
} // namespace api
} // namespace esphome
+374
View File
@@ -282,6 +282,24 @@ bool APIServerConnectionBase::send_select_state_response(const SelectStateRespon
#endif
#ifdef USE_SELECT
#endif
#ifdef USE_LOCK
bool APIServerConnectionBase::send_list_entities_lock_response(const ListEntitiesLockResponse &msg) {
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "send_list_entities_lock_response: %s", msg.dump().c_str());
#endif
return this->send_message_<ListEntitiesLockResponse>(msg, 58);
}
#endif
#ifdef USE_LOCK
bool APIServerConnectionBase::send_lock_state_response(const LockStateResponse &msg) {
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "send_lock_state_response: %s", msg.dump().c_str());
#endif
return this->send_message_<LockStateResponse>(msg, 59);
}
#endif
#ifdef USE_LOCK
#endif
#ifdef USE_BUTTON
bool APIServerConnectionBase::send_list_entities_button_response(const ListEntitiesButtonResponse &msg) {
#ifdef HAS_PROTO_MESSAGE_DUMP
@@ -292,6 +310,97 @@ bool APIServerConnectionBase::send_list_entities_button_response(const ListEntit
#endif
#ifdef USE_BUTTON
#endif
#ifdef USE_MEDIA_PLAYER
bool APIServerConnectionBase::send_list_entities_media_player_response(const ListEntitiesMediaPlayerResponse &msg) {
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "send_list_entities_media_player_response: %s", msg.dump().c_str());
#endif
return this->send_message_<ListEntitiesMediaPlayerResponse>(msg, 63);
}
#endif
#ifdef USE_MEDIA_PLAYER
bool APIServerConnectionBase::send_media_player_state_response(const MediaPlayerStateResponse &msg) {
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "send_media_player_state_response: %s", msg.dump().c_str());
#endif
return this->send_message_<MediaPlayerStateResponse>(msg, 64);
}
#endif
#ifdef USE_MEDIA_PLAYER
#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());
#endif
return this->send_message_<BluetoothLEAdvertisementResponse>(msg, 67);
}
#endif
#ifdef USE_BLUETOOTH_PROXY
#endif
#ifdef USE_BLUETOOTH_PROXY
bool APIServerConnectionBase::send_bluetooth_device_connection_response(const BluetoothDeviceConnectionResponse &msg) {
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "send_bluetooth_device_connection_response: %s", msg.dump().c_str());
#endif
return this->send_message_<BluetoothDeviceConnectionResponse>(msg, 69);
}
#endif
#ifdef USE_BLUETOOTH_PROXY
#endif
#ifdef USE_BLUETOOTH_PROXY
bool APIServerConnectionBase::send_bluetooth_gatt_get_services_response(const BluetoothGATTGetServicesResponse &msg) {
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "send_bluetooth_gatt_get_services_response: %s", msg.dump().c_str());
#endif
return this->send_message_<BluetoothGATTGetServicesResponse>(msg, 71);
}
#endif
#ifdef USE_BLUETOOTH_PROXY
bool APIServerConnectionBase::send_bluetooth_gatt_get_services_done_response(
const BluetoothGATTGetServicesDoneResponse &msg) {
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "send_bluetooth_gatt_get_services_done_response: %s", msg.dump().c_str());
#endif
return this->send_message_<BluetoothGATTGetServicesDoneResponse>(msg, 72);
}
#endif
#ifdef USE_BLUETOOTH_PROXY
#endif
#ifdef USE_BLUETOOTH_PROXY
bool APIServerConnectionBase::send_bluetooth_gatt_read_response(const BluetoothGATTReadResponse &msg) {
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "send_bluetooth_gatt_read_response: %s", msg.dump().c_str());
#endif
return this->send_message_<BluetoothGATTReadResponse>(msg, 74);
}
#endif
#ifdef USE_BLUETOOTH_PROXY
#endif
#ifdef USE_BLUETOOTH_PROXY
#endif
#ifdef USE_BLUETOOTH_PROXY
#endif
#ifdef USE_BLUETOOTH_PROXY
#endif
#ifdef USE_BLUETOOTH_PROXY
bool APIServerConnectionBase::send_bluetooth_gatt_notify_data_response(const BluetoothGATTNotifyDataResponse &msg) {
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "send_bluetooth_gatt_notify_data_response: %s", msg.dump().c_str());
#endif
return this->send_message_<BluetoothGATTNotifyDataResponse>(msg, 79);
}
#endif
#ifdef USE_BLUETOOTH_PROXY
#endif
#ifdef USE_BLUETOOTH_PROXY
bool APIServerConnectionBase::send_bluetooth_connections_free_response(const BluetoothConnectionsFreeResponse &msg) {
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "send_bluetooth_connections_free_response: %s", msg.dump().c_str());
#endif
return this->send_message_<BluetoothConnectionsFreeResponse>(msg, 81);
}
#endif
bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) {
switch (msg_type) {
case 1: {
@@ -523,6 +632,17 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
ESP_LOGVV(TAG, "on_select_command_request: %s", msg.dump().c_str());
#endif
this->on_select_command_request(msg);
#endif
break;
}
case 60: {
#ifdef USE_LOCK
LockCommandRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_lock_command_request: %s", msg.dump().c_str());
#endif
this->on_lock_command_request(msg);
#endif
break;
}
@@ -534,6 +654,114 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
ESP_LOGVV(TAG, "on_button_command_request: %s", msg.dump().c_str());
#endif
this->on_button_command_request(msg);
#endif
break;
}
case 65: {
#ifdef USE_MEDIA_PLAYER
MediaPlayerCommandRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_media_player_command_request: %s", msg.dump().c_str());
#endif
this->on_media_player_command_request(msg);
#endif
break;
}
case 66: {
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);
break;
}
case 68: {
#ifdef USE_BLUETOOTH_PROXY
BluetoothDeviceRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_bluetooth_device_request: %s", msg.dump().c_str());
#endif
this->on_bluetooth_device_request(msg);
#endif
break;
}
case 70: {
#ifdef USE_BLUETOOTH_PROXY
BluetoothGATTGetServicesRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_bluetooth_gatt_get_services_request: %s", msg.dump().c_str());
#endif
this->on_bluetooth_gatt_get_services_request(msg);
#endif
break;
}
case 73: {
#ifdef USE_BLUETOOTH_PROXY
BluetoothGATTReadRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_bluetooth_gatt_read_request: %s", msg.dump().c_str());
#endif
this->on_bluetooth_gatt_read_request(msg);
#endif
break;
}
case 75: {
#ifdef USE_BLUETOOTH_PROXY
BluetoothGATTWriteRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_bluetooth_gatt_write_request: %s", msg.dump().c_str());
#endif
this->on_bluetooth_gatt_write_request(msg);
#endif
break;
}
case 76: {
#ifdef USE_BLUETOOTH_PROXY
BluetoothGATTReadDescriptorRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_bluetooth_gatt_read_descriptor_request: %s", msg.dump().c_str());
#endif
this->on_bluetooth_gatt_read_descriptor_request(msg);
#endif
break;
}
case 77: {
#ifdef USE_BLUETOOTH_PROXY
BluetoothGATTWriteDescriptorRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_bluetooth_gatt_write_descriptor_request: %s", msg.dump().c_str());
#endif
this->on_bluetooth_gatt_write_descriptor_request(msg);
#endif
break;
}
case 78: {
#ifdef USE_BLUETOOTH_PROXY
BluetoothGATTNotifyRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_bluetooth_gatt_notify_request: %s", msg.dump().c_str());
#endif
this->on_bluetooth_gatt_notify_request(msg);
#endif
break;
}
case 80: {
#ifdef USE_BLUETOOTH_PROXY
SubscribeBluetoothConnectionsFreeRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
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;
}
@@ -771,6 +999,152 @@ void APIServerConnection::on_button_command_request(const ButtonCommandRequest &
this->button_command(msg);
}
#endif
#ifdef USE_LOCK
void APIServerConnection::on_lock_command_request(const LockCommandRequest &msg) {
if (!this->is_connection_setup()) {
this->on_no_setup_connection();
return;
}
if (!this->is_authenticated()) {
this->on_unauthenticated_access();
return;
}
this->lock_command(msg);
}
#endif
#ifdef USE_MEDIA_PLAYER
void APIServerConnection::on_media_player_command_request(const MediaPlayerCommandRequest &msg) {
if (!this->is_connection_setup()) {
this->on_no_setup_connection();
return;
}
if (!this->is_authenticated()) {
this->on_unauthenticated_access();
return;
}
this->media_player_command(msg);
}
#endif
void APIServerConnection::on_subscribe_bluetooth_le_advertisements_request(
const SubscribeBluetoothLEAdvertisementsRequest &msg) {
if (!this->is_connection_setup()) {
this->on_no_setup_connection();
return;
}
if (!this->is_authenticated()) {
this->on_unauthenticated_access();
return;
}
this->subscribe_bluetooth_le_advertisements(msg);
}
#ifdef USE_BLUETOOTH_PROXY
void APIServerConnection::on_bluetooth_device_request(const BluetoothDeviceRequest &msg) {
if (!this->is_connection_setup()) {
this->on_no_setup_connection();
return;
}
if (!this->is_authenticated()) {
this->on_unauthenticated_access();
return;
}
this->bluetooth_device_request(msg);
}
#endif
#ifdef USE_BLUETOOTH_PROXY
void APIServerConnection::on_bluetooth_gatt_get_services_request(const BluetoothGATTGetServicesRequest &msg) {
if (!this->is_connection_setup()) {
this->on_no_setup_connection();
return;
}
if (!this->is_authenticated()) {
this->on_unauthenticated_access();
return;
}
this->bluetooth_gatt_get_services(msg);
}
#endif
#ifdef USE_BLUETOOTH_PROXY
void APIServerConnection::on_bluetooth_gatt_read_request(const BluetoothGATTReadRequest &msg) {
if (!this->is_connection_setup()) {
this->on_no_setup_connection();
return;
}
if (!this->is_authenticated()) {
this->on_unauthenticated_access();
return;
}
this->bluetooth_gatt_read(msg);
}
#endif
#ifdef USE_BLUETOOTH_PROXY
void APIServerConnection::on_bluetooth_gatt_write_request(const BluetoothGATTWriteRequest &msg) {
if (!this->is_connection_setup()) {
this->on_no_setup_connection();
return;
}
if (!this->is_authenticated()) {
this->on_unauthenticated_access();
return;
}
this->bluetooth_gatt_write(msg);
}
#endif
#ifdef USE_BLUETOOTH_PROXY
void APIServerConnection::on_bluetooth_gatt_read_descriptor_request(const BluetoothGATTReadDescriptorRequest &msg) {
if (!this->is_connection_setup()) {
this->on_no_setup_connection();
return;
}
if (!this->is_authenticated()) {
this->on_unauthenticated_access();
return;
}
this->bluetooth_gatt_read_descriptor(msg);
}
#endif
#ifdef USE_BLUETOOTH_PROXY
void APIServerConnection::on_bluetooth_gatt_write_descriptor_request(const BluetoothGATTWriteDescriptorRequest &msg) {
if (!this->is_connection_setup()) {
this->on_no_setup_connection();
return;
}
if (!this->is_authenticated()) {
this->on_unauthenticated_access();
return;
}
this->bluetooth_gatt_write_descriptor(msg);
}
#endif
#ifdef USE_BLUETOOTH_PROXY
void APIServerConnection::on_bluetooth_gatt_notify_request(const BluetoothGATTNotifyRequest &msg) {
if (!this->is_connection_setup()) {
this->on_no_setup_connection();
return;
}
if (!this->is_authenticated()) {
this->on_unauthenticated_access();
return;
}
this->bluetooth_gatt_notify(msg);
}
#endif
#ifdef USE_BLUETOOTH_PROXY
void APIServerConnection::on_subscribe_bluetooth_connections_free_request(
const SubscribeBluetoothConnectionsFreeRequest &msg) {
if (!this->is_connection_setup()) {
this->on_no_setup_connection();
return;
}
if (!this->is_authenticated()) {
this->on_unauthenticated_access();
return;
}
BluetoothConnectionsFreeResponse ret = this->subscribe_bluetooth_connections_free(msg);
if (!this->send_bluetooth_connections_free_response(ret)) {
this->on_fatal_error();
}
}
#endif
} // namespace api
} // namespace esphome
+128
View File
@@ -130,11 +130,76 @@ class APIServerConnectionBase : public ProtoService {
#ifdef USE_SELECT
virtual void on_select_command_request(const SelectCommandRequest &value){};
#endif
#ifdef USE_LOCK
bool send_list_entities_lock_response(const ListEntitiesLockResponse &msg);
#endif
#ifdef USE_LOCK
bool send_lock_state_response(const LockStateResponse &msg);
#endif
#ifdef USE_LOCK
virtual void on_lock_command_request(const LockCommandRequest &value){};
#endif
#ifdef USE_BUTTON
bool send_list_entities_button_response(const ListEntitiesButtonResponse &msg);
#endif
#ifdef USE_BUTTON
virtual void on_button_command_request(const ButtonCommandRequest &value){};
#endif
#ifdef USE_MEDIA_PLAYER
bool send_list_entities_media_player_response(const ListEntitiesMediaPlayerResponse &msg);
#endif
#ifdef USE_MEDIA_PLAYER
bool send_media_player_state_response(const MediaPlayerStateResponse &msg);
#endif
#ifdef USE_MEDIA_PLAYER
virtual void on_media_player_command_request(const MediaPlayerCommandRequest &value){};
#endif
virtual void on_subscribe_bluetooth_le_advertisements_request(
const SubscribeBluetoothLEAdvertisementsRequest &value){};
#ifdef USE_BLUETOOTH_PROXY
bool send_bluetooth_le_advertisement_response(const BluetoothLEAdvertisementResponse &msg);
#endif
#ifdef USE_BLUETOOTH_PROXY
virtual void on_bluetooth_device_request(const BluetoothDeviceRequest &value){};
#endif
#ifdef USE_BLUETOOTH_PROXY
bool send_bluetooth_device_connection_response(const BluetoothDeviceConnectionResponse &msg);
#endif
#ifdef USE_BLUETOOTH_PROXY
virtual void on_bluetooth_gatt_get_services_request(const BluetoothGATTGetServicesRequest &value){};
#endif
#ifdef USE_BLUETOOTH_PROXY
bool send_bluetooth_gatt_get_services_response(const BluetoothGATTGetServicesResponse &msg);
#endif
#ifdef USE_BLUETOOTH_PROXY
bool send_bluetooth_gatt_get_services_done_response(const BluetoothGATTGetServicesDoneResponse &msg);
#endif
#ifdef USE_BLUETOOTH_PROXY
virtual void on_bluetooth_gatt_read_request(const BluetoothGATTReadRequest &value){};
#endif
#ifdef USE_BLUETOOTH_PROXY
bool send_bluetooth_gatt_read_response(const BluetoothGATTReadResponse &msg);
#endif
#ifdef USE_BLUETOOTH_PROXY
virtual void on_bluetooth_gatt_write_request(const BluetoothGATTWriteRequest &value){};
#endif
#ifdef USE_BLUETOOTH_PROXY
virtual void on_bluetooth_gatt_read_descriptor_request(const BluetoothGATTReadDescriptorRequest &value){};
#endif
#ifdef USE_BLUETOOTH_PROXY
virtual void on_bluetooth_gatt_write_descriptor_request(const BluetoothGATTWriteDescriptorRequest &value){};
#endif
#ifdef USE_BLUETOOTH_PROXY
virtual void on_bluetooth_gatt_notify_request(const BluetoothGATTNotifyRequest &value){};
#endif
#ifdef USE_BLUETOOTH_PROXY
bool send_bluetooth_gatt_notify_data_response(const BluetoothGATTNotifyDataResponse &msg);
#endif
#ifdef USE_BLUETOOTH_PROXY
virtual void on_subscribe_bluetooth_connections_free_request(const SubscribeBluetoothConnectionsFreeRequest &value){};
#endif
#ifdef USE_BLUETOOTH_PROXY
bool send_bluetooth_connections_free_response(const BluetoothConnectionsFreeResponse &msg);
#endif
protected:
bool read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) override;
@@ -180,6 +245,38 @@ class APIServerConnection : public APIServerConnectionBase {
#endif
#ifdef USE_BUTTON
virtual void button_command(const ButtonCommandRequest &msg) = 0;
#endif
#ifdef USE_LOCK
virtual void lock_command(const LockCommandRequest &msg) = 0;
#endif
#ifdef USE_MEDIA_PLAYER
virtual void media_player_command(const MediaPlayerCommandRequest &msg) = 0;
#endif
virtual void subscribe_bluetooth_le_advertisements(const SubscribeBluetoothLEAdvertisementsRequest &msg) = 0;
#ifdef USE_BLUETOOTH_PROXY
virtual void bluetooth_device_request(const BluetoothDeviceRequest &msg) = 0;
#endif
#ifdef USE_BLUETOOTH_PROXY
virtual void bluetooth_gatt_get_services(const BluetoothGATTGetServicesRequest &msg) = 0;
#endif
#ifdef USE_BLUETOOTH_PROXY
virtual void bluetooth_gatt_read(const BluetoothGATTReadRequest &msg) = 0;
#endif
#ifdef USE_BLUETOOTH_PROXY
virtual void bluetooth_gatt_write(const BluetoothGATTWriteRequest &msg) = 0;
#endif
#ifdef USE_BLUETOOTH_PROXY
virtual void bluetooth_gatt_read_descriptor(const BluetoothGATTReadDescriptorRequest &msg) = 0;
#endif
#ifdef USE_BLUETOOTH_PROXY
virtual void bluetooth_gatt_write_descriptor(const BluetoothGATTWriteDescriptorRequest &msg) = 0;
#endif
#ifdef USE_BLUETOOTH_PROXY
virtual void bluetooth_gatt_notify(const BluetoothGATTNotifyRequest &msg) = 0;
#endif
#ifdef USE_BLUETOOTH_PROXY
virtual BluetoothConnectionsFreeResponse subscribe_bluetooth_connections_free(
const SubscribeBluetoothConnectionsFreeRequest &msg) = 0;
#endif
protected:
void on_hello_request(const HelloRequest &msg) override;
@@ -221,6 +318,37 @@ class APIServerConnection : public APIServerConnectionBase {
#ifdef USE_BUTTON
void on_button_command_request(const ButtonCommandRequest &msg) override;
#endif
#ifdef USE_LOCK
void on_lock_command_request(const LockCommandRequest &msg) override;
#endif
#ifdef USE_MEDIA_PLAYER
void on_media_player_command_request(const MediaPlayerCommandRequest &msg) override;
#endif
void on_subscribe_bluetooth_le_advertisements_request(const SubscribeBluetoothLEAdvertisementsRequest &msg) override;
#ifdef USE_BLUETOOTH_PROXY
void on_bluetooth_device_request(const BluetoothDeviceRequest &msg) override;
#endif
#ifdef USE_BLUETOOTH_PROXY
void on_bluetooth_gatt_get_services_request(const BluetoothGATTGetServicesRequest &msg) override;
#endif
#ifdef USE_BLUETOOTH_PROXY
void on_bluetooth_gatt_read_request(const BluetoothGATTReadRequest &msg) override;
#endif
#ifdef USE_BLUETOOTH_PROXY
void on_bluetooth_gatt_write_request(const BluetoothGATTWriteRequest &msg) override;
#endif
#ifdef USE_BLUETOOTH_PROXY
void on_bluetooth_gatt_read_descriptor_request(const BluetoothGATTReadDescriptorRequest &msg) override;
#endif
#ifdef USE_BLUETOOTH_PROXY
void on_bluetooth_gatt_write_descriptor_request(const BluetoothGATTWriteDescriptorRequest &msg) override;
#endif
#ifdef USE_BLUETOOTH_PROXY
void on_bluetooth_gatt_notify_request(const BluetoothGATTNotifyRequest &msg) override;
#endif
#ifdef USE_BLUETOOTH_PROXY
void on_subscribe_bluetooth_connections_free_request(const SubscribeBluetoothConnectionsFreeRequest &msg) override;
#endif
};
} // namespace api
+84 -10
View File
@@ -24,7 +24,7 @@ static const char *const TAG = "api";
void APIServer::setup() {
ESP_LOGCONFIG(TAG, "Setting up Home Assistant API server...");
this->setup_controller();
socket_ = socket::socket(AF_INET, SOCK_STREAM, 0);
socket_ = socket::socket_ip(SOCK_STREAM, 0);
if (socket_ == nullptr) {
ESP_LOGW(TAG, "Could not create socket.");
this->mark_failed();
@@ -43,13 +43,16 @@ void APIServer::setup() {
return;
}
struct sockaddr_in server;
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = ESPHOME_INADDR_ANY;
server.sin_port = htons(this->port_);
struct sockaddr_storage server;
err = socket_->bind((struct sockaddr *) &server, sizeof(server));
socklen_t sl = socket::set_sockaddr_any((struct sockaddr *) &server, sizeof(server), htons(this->port_));
if (sl == 0) {
ESP_LOGW(TAG, "Socket unable to set sockaddr: errno %d", errno);
this->mark_failed();
return;
}
err = socket_->bind((struct sockaddr *) &server, sl);
if (err != 0) {
ESP_LOGW(TAG, "Socket unable to bind: errno %d", errno);
this->mark_failed();
@@ -80,9 +83,10 @@ void APIServer::setup() {
if (esp32_camera::global_esp32_camera != nullptr && !esp32_camera::global_esp32_camera->is_internal()) {
esp32_camera::global_esp32_camera->add_image_callback(
[this](const std::shared_ptr<esp32_camera::CameraImage> &image) {
for (auto &c : this->clients_)
for (auto &c : this->clients_) {
if (!c->remove_)
c->send_camera_state(image);
}
});
}
#endif
@@ -188,7 +192,7 @@ void APIServer::on_cover_update(cover::Cover *obj) {
#endif
#ifdef USE_FAN
void APIServer::on_fan_update(fan::FanState *obj) {
void APIServer::on_fan_update(fan::Fan *obj) {
if (obj->is_internal())
return;
for (auto &c : this->clients_)
@@ -251,7 +255,7 @@ void APIServer::on_number_update(number::Number *obj, float state) {
#endif
#ifdef USE_SELECT
void APIServer::on_select_update(select::Select *obj, const std::string &state) {
void APIServer::on_select_update(select::Select *obj, const std::string &state, size_t index) {
if (obj->is_internal())
return;
for (auto &c : this->clients_)
@@ -259,6 +263,24 @@ void APIServer::on_select_update(select::Select *obj, const std::string &state)
}
#endif
#ifdef USE_LOCK
void APIServer::on_lock_update(lock::Lock *obj) {
if (obj->is_internal())
return;
for (auto &c : this->clients_)
c->send_lock_state(obj, obj->state);
}
#endif
#ifdef USE_MEDIA_PLAYER
void APIServer::on_media_player_update(media_player::MediaPlayer *obj) {
if (obj->is_internal())
return;
for (auto &c : this->clients_)
c->send_media_player_state(obj);
}
#endif
float APIServer::get_setup_priority() const { return setup_priority::AFTER_WIFI; }
void APIServer::set_port(uint16_t port) { this->port_ = port; }
APIServer *global_api_server = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
@@ -269,6 +291,58 @@ void APIServer::send_homeassistant_service_call(const HomeassistantServiceRespon
client->send_homeassistant_service_call(call);
}
}
#ifdef USE_BLUETOOTH_PROXY
void APIServer::send_bluetooth_le_advertisement(const BluetoothLEAdvertisementResponse &call) {
for (auto &client : this->clients_) {
client->send_bluetooth_le_advertisement(call);
}
}
void APIServer::send_bluetooth_device_connection(uint64_t address, bool connected, uint16_t mtu, esp_err_t error) {
BluetoothDeviceConnectionResponse call;
call.address = address;
call.connected = connected;
call.mtu = mtu;
call.error = error;
for (auto &client : this->clients_) {
client->send_bluetooth_device_connection_response(call);
}
}
void APIServer::send_bluetooth_connections_free(uint8_t free, uint8_t limit) {
BluetoothConnectionsFreeResponse call;
call.free = free;
call.limit = limit;
for (auto &client : this->clients_) {
client->send_bluetooth_connections_free_response(call);
}
}
void APIServer::send_bluetooth_gatt_read_response(const BluetoothGATTReadResponse &call) {
for (auto &client : this->clients_) {
client->send_bluetooth_gatt_read_response(call);
}
}
void APIServer::send_bluetooth_gatt_notify_data_response(const BluetoothGATTNotifyDataResponse &call) {
for (auto &client : this->clients_) {
client->send_bluetooth_gatt_notify_data_response(call);
}
}
void APIServer::send_bluetooth_gatt_services(const BluetoothGATTGetServicesResponse &call) {
for (auto &client : this->clients_) {
client->send_bluetooth_gatt_get_services_response(call);
}
}
void APIServer::send_bluetooth_gatt_services_done(uint64_t address) {
BluetoothGATTGetServicesDoneResponse call;
call.address = address;
for (auto &client : this->clients_) {
client->send_bluetooth_gatt_get_services_done_response(call);
}
}
#endif
APIServer::APIServer() { global_api_server = this; }
void APIServer::subscribe_home_assistant_state(std::string entity_id, optional<std::string> attribute,
std::function<void(std::string)> f) {
+17 -3
View File
@@ -7,7 +7,6 @@
#include "esphome/components/socket/socket.h"
#include "api_pb2.h"
#include "api_pb2_service.h"
#include "util.h"
#include "list_entities.h"
#include "subscribe_state.h"
#include "user_services.h"
@@ -44,7 +43,7 @@ class APIServer : public Component, public Controller {
void on_cover_update(cover::Cover *obj) override;
#endif
#ifdef USE_FAN
void on_fan_update(fan::FanState *obj) override;
void on_fan_update(fan::Fan *obj) override;
#endif
#ifdef USE_LIGHT
void on_light_update(light::LightState *obj) override;
@@ -65,9 +64,24 @@ class APIServer : public Component, public Controller {
void on_number_update(number::Number *obj, float state) override;
#endif
#ifdef USE_SELECT
void on_select_update(select::Select *obj, const std::string &state) override;
void on_select_update(select::Select *obj, const std::string &state, size_t index) override;
#endif
#ifdef USE_LOCK
void on_lock_update(lock::Lock *obj) override;
#endif
#ifdef USE_MEDIA_PLAYER
void on_media_player_update(media_player::MediaPlayer *obj) override;
#endif
void send_homeassistant_service_call(const HomeassistantServiceResponse &call);
#ifdef USE_BLUETOOTH_PROXY
void send_bluetooth_le_advertisement(const BluetoothLEAdvertisementResponse &call);
void send_bluetooth_device_connection(uint64_t address, bool connected, uint16_t mtu, esp_err_t error = ESP_OK);
void send_bluetooth_connections_free(uint8_t free, uint8_t limit);
void send_bluetooth_gatt_read_response(const BluetoothGATTReadResponse &call);
void send_bluetooth_gatt_notify_data_response(const BluetoothGATTNotifyDataResponse &call);
void send_bluetooth_gatt_services(const BluetoothGATTGetServicesResponse &call);
void send_bluetooth_gatt_services_done(uint64_t address);
#endif
void register_user_service(UserServiceDescriptor *descriptor) { this->user_services_.push_back(descriptor); }
#ifdef USE_HOMEASSISTANT_TIME
void request_time();
-1
View File
@@ -21,7 +21,6 @@ async def async_run_logs(config, address):
if CONF_ENCRYPTION in conf:
noise_psk = conf[CONF_ENCRYPTION][CONF_KEY]
_LOGGER.info("Starting log output from %s using esphome API", address)
zc = zeroconf.Zeroconf()
cli = APIClient(
address,
port,
+11 -3
View File
@@ -16,7 +16,7 @@ bool ListEntitiesIterator::on_binary_sensor(binary_sensor::BinarySensor *binary_
bool ListEntitiesIterator::on_cover(cover::Cover *cover) { return this->client_->send_cover_info(cover); }
#endif
#ifdef USE_FAN
bool ListEntitiesIterator::on_fan(fan::FanState *fan) { return this->client_->send_fan_info(fan); }
bool ListEntitiesIterator::on_fan(fan::Fan *fan) { return this->client_->send_fan_info(fan); }
#endif
#ifdef USE_LIGHT
bool ListEntitiesIterator::on_light(light::LightState *light) { return this->client_->send_light_info(light); }
@@ -35,10 +35,12 @@ bool ListEntitiesIterator::on_text_sensor(text_sensor::TextSensor *text_sensor)
return this->client_->send_text_sensor_info(text_sensor);
}
#endif
#ifdef USE_LOCK
bool ListEntitiesIterator::on_lock(lock::Lock *a_lock) { return this->client_->send_lock_info(a_lock); }
#endif
bool ListEntitiesIterator::on_end() { return this->client_->send_list_info_done(); }
ListEntitiesIterator::ListEntitiesIterator(APIServer *server, APIConnection *client)
: ComponentIterator(server), client_(client) {}
ListEntitiesIterator::ListEntitiesIterator(APIConnection *client) : client_(client) {}
bool ListEntitiesIterator::on_service(UserServiceDescriptor *service) {
auto resp = service->encode_list_service_response();
return this->client_->send_list_entities_services_response(resp);
@@ -62,5 +64,11 @@ bool ListEntitiesIterator::on_number(number::Number *number) { return this->clie
bool ListEntitiesIterator::on_select(select::Select *select) { return this->client_->send_select_info(select); }
#endif
#ifdef USE_MEDIA_PLAYER
bool ListEntitiesIterator::on_media_player(media_player::MediaPlayer *media_player) {
return this->client_->send_media_player_info(media_player);
}
#endif
} // namespace api
} // namespace esphome
+9 -5
View File
@@ -1,8 +1,8 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/core/component_iterator.h"
#include "esphome/core/defines.h"
#include "util.h"
namespace esphome {
namespace api {
@@ -11,7 +11,7 @@ class APIConnection;
class ListEntitiesIterator : public ComponentIterator {
public:
ListEntitiesIterator(APIServer *server, APIConnection *client);
ListEntitiesIterator(APIConnection *client);
#ifdef USE_BINARY_SENSOR
bool on_binary_sensor(binary_sensor::BinarySensor *binary_sensor) override;
#endif
@@ -19,7 +19,7 @@ class ListEntitiesIterator : public ComponentIterator {
bool on_cover(cover::Cover *cover) override;
#endif
#ifdef USE_FAN
bool on_fan(fan::FanState *fan) override;
bool on_fan(fan::Fan *fan) override;
#endif
#ifdef USE_LIGHT
bool on_light(light::LightState *light) override;
@@ -48,6 +48,12 @@ class ListEntitiesIterator : public ComponentIterator {
#endif
#ifdef USE_SELECT
bool on_select(select::Select *select) override;
#endif
#ifdef USE_LOCK
bool on_lock(lock::Lock *a_lock) override;
#endif
#ifdef USE_MEDIA_PLAYER
bool on_media_player(media_player::MediaPlayer *media_player) override;
#endif
bool on_end() override;
@@ -57,5 +63,3 @@ class ListEntitiesIterator : public ComponentIterator {
} // namespace api
} // namespace esphome
#include "api_server.h"
-1
View File
@@ -1,5 +1,4 @@
#include "proto.h"
#include "util.h"
#include "esphome/core/log.h"
namespace esphome {
+33 -7
View File
@@ -55,20 +55,22 @@ class ProtoVarInt {
}
int32_t as_sint32() const {
// with ZigZag encoding
if (this->value_ & 1)
if (this->value_ & 1) {
return static_cast<int32_t>(~(this->value_ >> 1));
else
} else {
return static_cast<int32_t>(this->value_ >> 1);
}
}
int64_t as_sint64() const {
// with ZigZag encoding
if (this->value_ & 1)
if (this->value_ & 1) {
return static_cast<int64_t>(~(this->value_ >> 1));
else
} else {
return static_cast<int64_t>(this->value_ >> 1);
}
}
void encode(std::vector<uint8_t> &out) {
uint32_t val = this->value_;
uint64_t val = this->value_;
if (val <= 0x7F) {
out.push_back(val);
return;
@@ -193,6 +195,20 @@ class ProtoWriteBuffer {
this->write((value >> 16) & 0xFF);
this->write((value >> 24) & 0xFF);
}
void encode_fixed64(uint32_t field_id, uint64_t value, bool force = false) {
if (value == 0 && !force)
return;
this->encode_field_raw(field_id, 5);
this->write((value >> 0) & 0xFF);
this->write((value >> 8) & 0xFF);
this->write((value >> 16) & 0xFF);
this->write((value >> 24) & 0xFF);
this->write((value >> 32) & 0xFF);
this->write((value >> 40) & 0xFF);
this->write((value >> 48) & 0xFF);
this->write((value >> 56) & 0xFF);
}
template<typename T> void encode_enum(uint32_t field_id, T value, bool force = false) {
this->encode_uint32(field_id, static_cast<uint32_t>(value), force);
}
@@ -220,12 +236,22 @@ class ProtoWriteBuffer {
}
void encode_sint32(uint32_t field_id, int32_t value, bool force = false) {
uint32_t uvalue;
if (value < 0)
if (value < 0) {
uvalue = ~(value << 1);
else
} else {
uvalue = value << 1;
}
this->encode_uint32(field_id, uvalue, force);
}
void encode_sint64(uint32_t field_id, int64_t value, bool force = false) {
uint64_t uvalue;
if (value < 0) {
uvalue = ~(value << 1);
} else {
uvalue = value << 1;
}
this->encode_uint64(field_id, uvalue, force);
}
template<class C> void encode_message(uint32_t field_id, const C &value, bool force = false) {
this->encode_field_raw(field_id, 2);
size_t begin = this->buffer_->size();
+10 -3
View File
@@ -14,7 +14,7 @@ bool InitialStateIterator::on_binary_sensor(binary_sensor::BinarySensor *binary_
bool InitialStateIterator::on_cover(cover::Cover *cover) { return this->client_->send_cover_state(cover); }
#endif
#ifdef USE_FAN
bool InitialStateIterator::on_fan(fan::FanState *fan) { return this->client_->send_fan_state(fan); }
bool InitialStateIterator::on_fan(fan::Fan *fan) { return this->client_->send_fan_state(fan); }
#endif
#ifdef USE_LIGHT
bool InitialStateIterator::on_light(light::LightState *light) { return this->client_->send_light_state(light); }
@@ -47,8 +47,15 @@ bool InitialStateIterator::on_select(select::Select *select) {
return this->client_->send_select_state(select, select->state);
}
#endif
InitialStateIterator::InitialStateIterator(APIServer *server, APIConnection *client)
: ComponentIterator(server), client_(client) {}
#ifdef USE_LOCK
bool InitialStateIterator::on_lock(lock::Lock *a_lock) { return this->client_->send_lock_state(a_lock, a_lock->state); }
#endif
#ifdef USE_MEDIA_PLAYER
bool InitialStateIterator::on_media_player(media_player::MediaPlayer *media_player) {
return this->client_->send_media_player_state(media_player);
}
#endif
InitialStateIterator::InitialStateIterator(APIConnection *client) : client_(client) {}
} // namespace api
} // namespace esphome
+9 -5
View File
@@ -1,9 +1,9 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/core/component_iterator.h"
#include "esphome/core/controller.h"
#include "esphome/core/defines.h"
#include "util.h"
namespace esphome {
namespace api {
@@ -12,7 +12,7 @@ class APIConnection;
class InitialStateIterator : public ComponentIterator {
public:
InitialStateIterator(APIServer *server, APIConnection *client);
InitialStateIterator(APIConnection *client);
#ifdef USE_BINARY_SENSOR
bool on_binary_sensor(binary_sensor::BinarySensor *binary_sensor) override;
#endif
@@ -20,7 +20,7 @@ class InitialStateIterator : public ComponentIterator {
bool on_cover(cover::Cover *cover) override;
#endif
#ifdef USE_FAN
bool on_fan(fan::FanState *fan) override;
bool on_fan(fan::Fan *fan) override;
#endif
#ifdef USE_LIGHT
bool on_light(light::LightState *light) override;
@@ -45,6 +45,12 @@ class InitialStateIterator : public ComponentIterator {
#endif
#ifdef USE_SELECT
bool on_select(select::Select *select) override;
#endif
#ifdef USE_LOCK
bool on_lock(lock::Lock *a_lock) override;
#endif
#ifdef USE_MEDIA_PLAYER
bool on_media_player(media_player::MediaPlayer *media_player) override;
#endif
protected:
APIConnection *client_;
@@ -52,5 +58,3 @@ class InitialStateIterator : public ComponentIterator {
} // namespace api
} // namespace esphome
#include "api_server.h"
+1 -1
View File
@@ -52,7 +52,7 @@ template<typename... Ts> class UserServiceBase : public UserServiceDescriptor {
protected:
virtual void execute(Ts... x) = 0;
template<int... S> void execute_(std::vector<ExecuteServiceArgument> args, seq<S...>) {
template<int... S> void execute_(std::vector<ExecuteServiceArgument> args, seq<S...> type) {
this->execute((get_execute_arg_value<Ts>(args[S]))...);
}
+3 -2
View File
@@ -58,10 +58,11 @@ void AS3935Component::loop() {
void AS3935Component::write_indoor(bool indoor) {
ESP_LOGV(TAG, "Setting indoor to %d", indoor);
if (indoor)
if (indoor) {
this->write_register(AFE_GAIN, GAIN_MASK, INDOOR, 1);
else
} else {
this->write_register(AFE_GAIN, GAIN_MASK, OUTDOOR, 1);
}
}
// REG0x01, bits[3:0], manufacturer default: 0010 (2).
// This setting determines the threshold for events that trigger the
+3 -3
View File
@@ -92,9 +92,9 @@ 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_;
sensor::Sensor *energy_sensor_;
binary_sensor::BinarySensor *thunder_alert_binary_sensor_;
sensor::Sensor *distance_sensor_{nullptr};
sensor::Sensor *energy_sensor_{nullptr};
binary_sensor::BinarySensor *thunder_alert_binary_sensor_{nullptr};
GPIOPin *irq_pin_;
bool indoor_;
+1 -1
View File
@@ -5,7 +5,7 @@ from . import AS3935, CONF_AS3935_ID
DEPENDENCIES = ["as3935"]
CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend(
CONFIG_SCHEMA = binary_sensor.binary_sensor_schema().extend(
{
cv.GenerateID(CONF_AS3935_ID): cv.use_id(AS3935),
}
-3
View File
@@ -4,7 +4,6 @@ from esphome.components import sensor
from esphome.const import (
CONF_DISTANCE,
CONF_LIGHTNING_ENERGY,
STATE_CLASS_NONE,
UNIT_KILOMETER,
ICON_SIGNAL_DISTANCE_VARIANT,
ICON_FLASH,
@@ -20,12 +19,10 @@ CONFIG_SCHEMA = cv.Schema(
unit_of_measurement=UNIT_KILOMETER,
icon=ICON_SIGNAL_DISTANCE_VARIANT,
accuracy_decimals=1,
state_class=STATE_CLASS_NONE,
),
cv.Optional(CONF_LIGHTNING_ENERGY): sensor.sensor_schema(
icon=ICON_FLASH,
accuracy_decimals=1,
state_class=STATE_CLASS_NONE,
),
}
).extend(cv.COMPONENT_SCHEMA)
+11 -5
View File
@@ -38,7 +38,7 @@ bool BParasite::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
const auto &data = service_data.data;
const uint8_t protocol_version = data[0] >> 4;
if (protocol_version != 1) {
if (protocol_version != 1 && protocol_version != 2) {
ESP_LOGE(TAG, "Unsupported protocol version: %u", protocol_version);
return false;
}
@@ -57,9 +57,15 @@ bool BParasite::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
uint16_t battery_millivolt = data[2] << 8 | data[3];
float battery_voltage = battery_millivolt / 1000.0f;
// Temperature in 1000 * Celsius.
uint16_t temp_millicelcius = data[4] << 8 | data[5];
float temp_celcius = temp_millicelcius / 1000.0f;
// Temperature in 1000 * Celsius (protocol v1) or 100 * Celsius (protocol v2).
float temp_celsius;
if (protocol_version == 1) {
uint16_t temp_millicelsius = data[4] << 8 | data[5];
temp_celsius = temp_millicelsius / 1000.0f;
} else {
int16_t temp_centicelsius = data[4] << 8 | data[5];
temp_celsius = temp_centicelsius / 100.0f;
}
// Relative air humidity in the range [0, 2^16).
uint16_t humidity = data[6] << 8 | data[7];
@@ -76,7 +82,7 @@ bool BParasite::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
battery_voltage_->publish_state(battery_voltage);
}
if (temperature_ != nullptr) {
temperature_->publish_state(temp_celcius);
temperature_->publish_state(temp_celsius);
}
if (humidity_ != nullptr) {
humidity_->publish_state(humidity_percent);
+3 -3
View File
@@ -97,7 +97,7 @@ void BalluClimate::transmit_state() {
// Send code
auto transmit = this->transmitter_->transmit();
auto data = transmit.get_data();
auto *data = transmit.get_data();
data->set_carrier_frequency(38000);
@@ -130,10 +130,10 @@ bool BalluClimate::on_receive(remote_base::RemoteReceiveData data) {
for (int i = 0; i < BALLU_STATE_LENGTH; i++) {
// Read bit
for (int j = 0; j < 8; j++) {
if (data.expect_item(BALLU_BIT_MARK, BALLU_ONE_SPACE))
if (data.expect_item(BALLU_BIT_MARK, BALLU_ONE_SPACE)) {
remote_state[i] |= 1 << j;
else if (!data.expect_item(BALLU_BIT_MARK, BALLU_ZERO_SPACE)) {
} else if (!data.expect_item(BALLU_BIT_MARK, BALLU_ZERO_SPACE)) {
ESP_LOGV(TAG, "Byte %d bit %d fail", i, j);
return false;
}
@@ -21,12 +21,13 @@ void BangBangClimate::setup() {
restore->to_call(this).perform();
} else {
// restore from defaults, change_away handles those for us
if (supports_cool_ && supports_heat_)
if (supports_cool_ && supports_heat_) {
this->mode = climate::CLIMATE_MODE_HEAT_COOL;
else if (supports_cool_)
} else if (supports_cool_) {
this->mode = climate::CLIMATE_MODE_COOL;
else if (supports_heat_)
} else if (supports_heat_) {
this->mode = climate::CLIMATE_MODE_HEAT;
}
this->change_away_(false);
}
}
@@ -56,11 +57,12 @@ climate::ClimateTraits BangBangClimate::traits() {
if (supports_cool_ && supports_heat_)
traits.add_supported_mode(climate::CLIMATE_MODE_HEAT_COOL);
traits.set_supports_two_point_target_temperature(true);
if (supports_away_)
if (supports_away_) {
traits.set_supported_presets({
climate::CLIMATE_PRESET_HOME,
climate::CLIMATE_PRESET_AWAY,
});
}
traits.set_supports_action(true);
return traits;
}
@@ -82,17 +84,19 @@ void BangBangClimate::compute_state_() {
if (too_cold) {
// too cold -> enable heating if possible and enabled, else idle
if (this->supports_heat_ &&
(this->mode == climate::CLIMATE_MODE_HEAT_COOL || this->mode == climate::CLIMATE_MODE_HEAT))
(this->mode == climate::CLIMATE_MODE_HEAT_COOL || this->mode == climate::CLIMATE_MODE_HEAT)) {
target_action = climate::CLIMATE_ACTION_HEATING;
else
} else {
target_action = climate::CLIMATE_ACTION_IDLE;
}
} else if (too_hot) {
// too hot -> enable cooling if possible and enabled, else idle
if (this->supports_cool_ &&
(this->mode == climate::CLIMATE_MODE_HEAT_COOL || this->mode == climate::CLIMATE_MODE_COOL))
(this->mode == climate::CLIMATE_MODE_HEAT_COOL || this->mode == climate::CLIMATE_MODE_COOL)) {
target_action = climate::CLIMATE_ACTION_COOLING;
else
} else {
target_action = climate::CLIMATE_ACTION_IDLE;
}
} else {
// neither too hot nor too cold -> in range
if (this->supports_cool_ && this->supports_heat_ && this->mode == climate::CLIMATE_MODE_HEAT_COOL) {
@@ -107,9 +111,10 @@ void BangBangClimate::compute_state_() {
this->switch_to_action_(target_action);
}
void BangBangClimate::switch_to_action_(climate::ClimateAction action) {
if (action == this->action)
if (action == this->action) {
// already in target mode
return;
}
if ((action == climate::CLIMATE_ACTION_OFF && this->action == climate::CLIMATE_ACTION_IDLE) ||
(action == climate::CLIMATE_ACTION_IDLE && this->action == climate::CLIMATE_ACTION_OFF)) {
+52
View File
@@ -0,0 +1,52 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import ble_client, time
from esphome.const import (
CONF_ID,
CONF_RECEIVE_TIMEOUT,
CONF_TIME_ID,
)
CODEOWNERS = ["@jhansche"]
DEPENDENCIES = ["ble_client"]
MULTI_CONF = True
CONF_BEDJET_ID = "bedjet_id"
bedjet_ns = cg.esphome_ns.namespace("bedjet")
BedJetHub = bedjet_ns.class_("BedJetHub", ble_client.BLEClientNode, cg.PollingComponent)
CONFIG_SCHEMA = (
cv.COMPONENT_SCHEMA.extend(
{
cv.GenerateID(): cv.declare_id(BedJetHub),
cv.Optional(CONF_TIME_ID): cv.use_id(time.RealTimeClock),
cv.Optional(
CONF_RECEIVE_TIMEOUT, default="0s"
): cv.positive_time_period_milliseconds,
}
)
.extend(ble_client.BLE_CLIENT_SCHEMA)
.extend(cv.polling_component_schema("15s"))
)
BEDJET_CLIENT_SCHEMA = cv.Schema(
{
cv.Required(CONF_BEDJET_ID): cv.use_id(BedJetHub),
}
)
async def register_bedjet_child(var, config):
parent = await cg.get_variable(config[CONF_BEDJET_ID])
cg.add(parent.register_child(var))
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
await ble_client.register_ble_node(var, config)
if CONF_TIME_ID in config:
time_ = await cg.get_variable(config[CONF_TIME_ID])
cg.add(var.set_time_id(time_))
if CONF_RECEIVE_TIMEOUT in config:
cg.add(var.set_status_timeout(config[CONF_RECEIVE_TIMEOUT]))
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#include "bedjet_codec.h"
#include "esphome/core/helpers.h"
namespace esphome {
namespace bedjet {
// Forward declare BedJetHub
class BedJetHub;
class BedJetClient : public Parented<BedJetHub> {
public:
virtual void on_status(const BedjetStatusPacket *data) = 0;
virtual void on_bedjet_state(bool is_ready) = 0;
protected:
friend BedJetHub;
virtual std::string describe() = 0;
};
} // namespace bedjet
} // namespace esphome
+161
View File
@@ -0,0 +1,161 @@
#include "bedjet_codec.h"
#include <cstdio>
#include <cstring>
namespace esphome {
namespace bedjet {
/// Converts a BedJet temp step into degrees Fahrenheit.
float bedjet_temp_to_f(const uint8_t temp) {
// BedJet temp is "C*2"; to get F, multiply by 0.9 (half 1.8) and add 32.
return 0.9f * temp + 32.0f;
}
/** Cleans up the packet before sending. */
BedjetPacket *BedjetCodec::clean_packet_() {
// So far no commands require more than 2 bytes of data.
assert(this->packet_.data_length <= 2);
for (int i = this->packet_.data_length; i < 2; i++) {
this->packet_.data[i] = '\0';
}
ESP_LOGV(TAG, "Created packet: %02X, %02X %02X", this->packet_.command, this->packet_.data[0], this->packet_.data[1]);
return &this->packet_;
}
/** Returns a BedjetPacket that will initiate a BedjetButton press. */
BedjetPacket *BedjetCodec::get_button_request(BedjetButton button) {
this->packet_.command = CMD_BUTTON;
this->packet_.data_length = 1;
this->packet_.data[0] = button;
return this->clean_packet_();
}
/** Returns a BedjetPacket that will set the device's target `temperature`. */
BedjetPacket *BedjetCodec::get_set_target_temp_request(float temperature) {
this->packet_.command = CMD_SET_TEMP;
this->packet_.data_length = 1;
this->packet_.data[0] = temperature * 2;
return this->clean_packet_();
}
/** Returns a BedjetPacket that will set the device's target fan speed. */
BedjetPacket *BedjetCodec::get_set_fan_speed_request(const uint8_t fan_step) {
this->packet_.command = CMD_SET_FAN;
this->packet_.data_length = 1;
this->packet_.data[0] = fan_step;
return this->clean_packet_();
}
/** Returns a BedjetPacket that will set the device's current time. */
BedjetPacket *BedjetCodec::get_set_time_request(const uint8_t hour, const uint8_t minute) {
this->packet_.command = CMD_SET_CLOCK;
this->packet_.data_length = 2;
this->packet_.data[0] = hour;
this->packet_.data[1] = minute;
return this->clean_packet_();
}
/** Returns a BedjetPacket that will set the device's remaining runtime. */
BedjetPacket *BedjetCodec::get_set_runtime_remaining_request(const uint8_t hour, const uint8_t minute) {
this->packet_.command = CMD_SET_RUNTIME;
this->packet_.data_length = 2;
this->packet_.data[0] = hour;
this->packet_.data[1] = minute;
return this->clean_packet_();
}
/** Decodes the extra bytes that were received after being notified with a partial packet. */
void BedjetCodec::decode_extra(const uint8_t *data, uint16_t length) {
ESP_LOGVV(TAG, "Received extra: %d bytes: %d %d %d %d", length, data[1], data[2], data[3], data[4]);
uint8_t offset = this->last_buffer_size_;
if (offset > 0 && length + offset <= sizeof(BedjetStatusPacket)) {
memcpy(((uint8_t *) (&this->buf_)) + offset, data, length);
ESP_LOGVV(TAG,
"Extra bytes: skip1=0x%08x, skip2=0x%04x, skip3=0x%02x; update phase=0x%02x, "
"flags=BedjetFlags <conn=%c, leds=%c, units=%c, mute=%c; packed=%02x>",
this->buf_.unused_1, this->buf_.unused_2, this->buf_.unused_3, this->buf_.update_phase,
this->buf_.flags.conn_test_passed ? '1' : '0', this->buf_.flags.leds_enabled ? '1' : '0',
this->buf_.flags.units_setup ? '1' : '0', this->buf_.flags.beeps_muted ? '1' : '0',
this->buf_.flags_packed);
} else {
ESP_LOGI(TAG, "Could not determine where to append to, last offset=%d, max size=%u, new size would be %d", offset,
sizeof(BedjetStatusPacket), length + offset);
}
}
/** Decodes the incoming status packet received on the BEDJET_STATUS_UUID.
*
* @return `true` if the packet was decoded and represents a "partial" packet; `false` otherwise.
*/
bool BedjetCodec::decode_notify(const uint8_t *data, uint16_t length) {
ESP_LOGV(TAG, "Received: %d bytes: %d %d %d %d", length, data[1], data[2], data[3], data[4]);
if (data[1] == PACKET_FORMAT_V3_HOME && data[3] == PACKET_TYPE_STATUS) {
// Clear old buffer
memset(&this->buf_, 0, sizeof(BedjetStatusPacket));
// Copy new data into buffer
memcpy(&this->buf_, data, length);
this->last_buffer_size_ = length;
// TODO: validate the packet checksum?
if (this->buf_.mode < 7 && this->buf_.target_temp_step >= 38 && this->buf_.target_temp_step <= 86 &&
this->buf_.actual_temp_step > 1 && this->buf_.actual_temp_step <= 100 && this->buf_.ambient_temp_step > 1 &&
this->buf_.ambient_temp_step <= 100) {
// and save it for the update() loop
this->status_packet_ = &this->buf_;
return this->buf_.is_partial;
} else {
this->status_packet_ = nullptr;
// TODO: log a warning if we detect that we connected to a non-V3 device.
ESP_LOGW(TAG, "Received potentially invalid packet (len %d):", length);
}
} else if (data[1] == PACKET_FORMAT_DEBUG || data[3] == PACKET_TYPE_DEBUG) {
// We don't actually know the packet format for this. Dump packets to log, in case a pattern presents itself.
ESP_LOGVV(TAG,
"received DEBUG packet: set1=%01fF, set2=%01fF, air=%01fF; [7]=%d, [8]=%d, [9]=%d, [10]=%d, [11]=%d, "
"[12]=%d, [-1]=%d",
bedjet_temp_to_f(data[4]), bedjet_temp_to_f(data[5]), bedjet_temp_to_f(data[6]), data[7], data[8],
data[9], data[10], data[11], data[12], data[length - 1]);
if (this->has_status()) {
this->status_packet_->ambient_temp_step = data[6];
}
} else {
// TODO: log a warning if we detect that we connected to a non-V3 device.
}
return false;
}
/** @return `true` if the new packet is meaningfully different from the last seen packet. */
bool BedjetCodec::compare(const uint8_t *data, uint16_t length) {
if (data == nullptr) {
return false;
}
if (length < 17) {
// New packet looks small, skip it.
return false;
}
if (this->buf_.packet_format != PACKET_FORMAT_V3_HOME ||
this->buf_.packet_type != PACKET_TYPE_STATUS) { // No last seen packet, so take the new one.
return true;
}
if (data[1] != PACKET_FORMAT_V3_HOME || data[3] != PACKET_TYPE_STATUS) { // New packet is not a v3 status, skip it.
return false;
}
// Now coerce it to a status packet and compare some key fields
const BedjetStatusPacket *test = reinterpret_cast<const BedjetStatusPacket *>(data);
// These are fields that will only change due to explicit action.
// That is why we do not check ambient or actual temp here, because those are environmental.
bool explicit_fields_changed = this->buf_.mode != test->mode || this->buf_.fan_step != test->fan_step ||
this->buf_.target_temp_step != test->target_temp_step;
return explicit_fields_changed;
}
} // namespace bedjet
} // namespace esphome
+191
View File
@@ -0,0 +1,191 @@
#pragma once
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#include "bedjet_const.h"
namespace esphome {
namespace bedjet {
struct BedjetPacket {
uint8_t data_length;
BedjetCommand command;
uint8_t data[2];
};
enum BedjetPacketFormat : uint8_t {
PACKET_FORMAT_DEBUG = 0x05, // 5
PACKET_FORMAT_V3_HOME = 0x56, // 86
};
enum BedjetPacketType : uint8_t {
PACKET_TYPE_STATUS = 0x1,
PACKET_TYPE_DEBUG = 0x2,
};
enum BedjetNotification : uint8_t {
NOTIFY_NONE = 0, ///< No notification pending
NOTIFY_FILTER = 1, ///< Clean Filter / Please check BedJet air filter and clean if necessary.
NOTIFY_UPDATE = 2, ///< Firmware Update / A newer version of firmware is available.
NOTIFY_UPDATE_FAIL = 3, ///< Firmware Update / Unable to connect to the firmware update server.
NOTIFY_BIO_FAIL_CLOCK_NOT_SET = 4, ///< The specified sequence cannot be run because the clock is not set
NOTIFY_BIO_FAIL_TOO_LONG = 5, ///< The specified sequence cannot be run because it contains steps that would be too
///< long running from the current time.
// Note: after handling a notification, send MAGIC_NOTIFY_ACK
};
/** The format of a BedJet V3 status packet. */
struct BedjetStatusPacket {
// [0]
bool is_partial : 8; ///< `1` indicates that this is a partial packet, and more data can be read directly from the
///< characteristic.
BedjetPacketFormat packet_format : 8; ///< BedjetPacketFormat::PACKET_FORMAT_V3_HOME for BedJet V3 status packet
///< format. BedjetPacketFormat::PACKET_FORMAT_DEBUG for debugging packets.
uint8_t expecting_length : 8; ///< The expected total length of the status packet after merging the extra packet.
BedjetPacketType packet_type : 8; ///< Typically BedjetPacketType::PACKET_TYPE_STATUS for BedJet V3 status packet.
// [4]
uint8_t time_remaining_hrs : 8; ///< Hours remaining in program runtime
uint8_t time_remaining_mins : 8; ///< Minutes remaining in program runtime
uint8_t time_remaining_secs : 8; ///< Seconds remaining in program runtime
// [7]
uint8_t actual_temp_step : 8; ///< Actual temp of the air blown by the BedJet fan; value represents `2 *
///< degrees_celsius`. See #bedjet_temp_to_c and #bedjet_temp_to_f
uint8_t target_temp_step : 8; ///< Target temp that the BedJet will try to heat to. See #actual_temp_step.
// [9]
BedjetMode mode : 8; ///< BedJet operating mode.
// [10]
uint8_t fan_step : 8; ///< BedJet fan speed; value is in the 0-19 range, representing 5% increments (5%-100%): `5 + 5
///< * fan_step`
uint8_t max_hrs : 8; ///< Max hours of mode runtime
uint8_t max_mins : 8; ///< Max minutes of mode runtime
uint8_t min_temp_step : 8; ///< Min temp allowed in mode. See #actual_temp_step.
uint8_t max_temp_step : 8; ///< Max temp allowed in mode. See #actual_temp_step.
// [15-16]
uint16_t turbo_time : 16; ///< Time remaining in BedjetMode::MODE_TURBO.
// [17]
uint8_t ambient_temp_step : 8; ///< Current ambient air temp. This is the coldest air the BedJet can blow. See
///< #actual_temp_step.
uint8_t shutdown_reason : 8; ///< The reason for the last device shutdown.
// [19-25]; the initial partial packet cuts off here after [19]
uint8_t unused_1 : 8; // Unknown [19] = 0x01
uint8_t unused_2 : 8; // Unknown [20] = 0x81
uint8_t unused_3 : 8; // Unknown [21] = 0x01
// [22]: 0x2=is_dual_zone, ...?
struct {
int unused_1 : 1; // 0x80
int unused_2 : 1; // 0x40
int unused_3 : 1; // 0x20
int unused_4 : 1; // 0x10
int unused_5 : 1; // 0x8
int unused_6 : 1; // 0x4
bool is_dual_zone : 1; /// Is part of a Dual Zone configuration
int unused_7 : 1; // 0x1
} dual_zone_flags;
uint8_t unused_4 : 8; // Unknown 23-24 = 0x1310
uint8_t unused_5 : 8; // Unknown 23-24 = 0x1310
uint8_t unused_6 : 8; // Unknown 25 = 0x00
// [26]
// 0x18(24) = "Connection test has completed OK"
// 0x1a(26) = "Firmware update is not needed"
uint8_t update_phase : 8; ///< The current status/phase of a firmware update.
// [27]
union {
uint8_t flags_packed;
struct {
/* uint8_t */
int unused_1 : 1; // 0x80
int unused_2 : 1; // 0x40
bool conn_test_passed : 1; ///< (0x20) Bit is set `1` if the last connection test passed.
bool leds_enabled : 1; ///< (0x10) Bit is set `1` if the LEDs on the device are enabled.
int unused_3 : 1; // 0x08
bool units_setup : 1; ///< (0x04) Bit is set `1` if the device's units have been configured.
int unused_4 : 1; // 0x02
bool beeps_muted : 1; ///< (0x01) Bit is set `1` if the device's sound output is muted.
} __attribute__((packed)) flags;
};
// [28] = (biorhythm?) sequence step
uint8_t bio_sequence_step : 8; /// Biorhythm sequence step number
// [29] = notify_code:
BedjetNotification notify_code : 8; /// See BedjetNotification
uint16_t unused_7 : 16; // Unknown
} __attribute__((packed));
/** This class is responsible for encoding command packets and decoding status packets.
*
* Status Packets
* ==============
* The BedJet protocol depends on registering for notifications on the esphome::BedJet::BEDJET_SERVICE_UUID
* characteristic. If the BedJet is on, it will send rapid updates as notifications. If it is off,
* it generally will not notify of any status.
*
* As the BedJet V3's BedjetStatusPacket exceeds the buffer size allowed for BLE notification packets,
* the notification packet will contain `BedjetStatusPacket::is_partial == 1`. When that happens, an additional
* read of the esphome::BedJet::BEDJET_SERVICE_UUID characteristic will contain the second portion of the
* full status packet.
*
* Command Packets
* ===============
* This class supports encoding a number of BedjetPacket commands:
* - Button press
* This simulates a press of one of the BedjetButton values.
* - BedjetPacket#command = BedjetCommand::CMD_BUTTON
* - BedjetPacket#data [0] contains the BedjetButton value
* - Set target temp
* This sets the BedJet's target temp to a concrete temperature value.
* - BedjetPacket#command = BedjetCommand::CMD_SET_TEMP
* - BedjetPacket#data [0] contains the BedJet temp value; see BedjetStatusPacket#actual_temp_step
* - Set fan speed
* This sets the BedJet fan speed.
* - BedjetPacket#command = BedjetCommand::CMD_SET_FAN
* - BedjetPacket#data [0] contains the BedJet fan step in the range 0-19.
* - Set current time
* The BedJet needs to have its clock set properly in order to run the biorhythm programs, which might
* contain time-of-day based step rules.
* - BedjetPacket#command = BedjetCommand::CMD_SET_CLOCK
* - BedjetPacket#data [0] is hours, [1] is minutes
*/
class BedjetCodec {
public:
BedjetPacket *get_button_request(BedjetButton button);
BedjetPacket *get_set_target_temp_request(float temperature);
BedjetPacket *get_set_fan_speed_request(uint8_t fan_step);
BedjetPacket *get_set_time_request(uint8_t hour, uint8_t minute);
BedjetPacket *get_set_runtime_remaining_request(uint8_t hour, uint8_t minute);
bool decode_notify(const uint8_t *data, uint16_t length);
void decode_extra(const uint8_t *data, uint16_t length);
bool compare(const uint8_t *data, uint16_t length);
inline bool has_status() { return this->status_packet_ != nullptr; }
const BedjetStatusPacket *get_status_packet() const { return this->status_packet_; }
void clear_status() { this->status_packet_ = nullptr; }
protected:
BedjetPacket *clean_packet_();
uint8_t last_buffer_size_ = 0;
BedjetPacket packet_;
BedjetStatusPacket *status_packet_;
BedjetStatusPacket buf_;
};
} // namespace bedjet
} // namespace esphome
+99
View File
@@ -0,0 +1,99 @@
#pragma once
#include <set>
namespace esphome {
namespace bedjet {
static const char *const TAG = "bedjet";
/// Converts a BedJet fan step to a speed percentage, in the range of 5% to 100%.
inline static uint8_t bedjet_fan_step_to_speed(const uint8_t fan) {
// 0 = 5%
// 19 = 100%
return 5 * fan + 5;
}
inline static uint8_t bedjet_fan_speed_to_index(const uint8_t speed) { return speed / 5 - 1; }
enum BedjetMode : uint8_t {
/// BedJet is Off
MODE_STANDBY = 0,
/// BedJet is in Heat mode (limited to 4 hours)
MODE_HEAT = 1,
/// BedJet is in Turbo mode (high heat, limited time)
MODE_TURBO = 2,
/// BedJet is in Extended Heat mode (limited to 10 hours)
MODE_EXTHT = 3,
/// BedJet is in Cool mode (actually "Fan only" mode)
MODE_COOL = 4,
/// BedJet is in Dry mode (high speed, no heat)
MODE_DRY = 5,
/// BedJet is in "wait" mode, a step during a biorhythm program
MODE_WAIT = 6,
};
/** Optional heating strategies to use for climate::CLIMATE_MODE_HEAT. */
enum BedjetHeatMode {
/// HVACMode.HEAT is handled using BTN_HEAT (default)
HEAT_MODE_HEAT,
/// HVACMode.HEAT is handled using BTN_EXTHT
HEAT_MODE_EXTENDED,
};
enum BedjetButton : uint8_t {
/// Turn BedJet off
BTN_OFF = 0x1,
/// Enter Cool mode (fan only)
BTN_COOL = 0x2,
/// Enter Heat mode (limited to 4 hours)
BTN_HEAT = 0x3,
/// Enter Turbo mode (high heat, limited to 10 minutes)
BTN_TURBO = 0x4,
/// Enter Dry mode (high speed, no heat)
BTN_DRY = 0x5,
/// Enter Extended Heat mode (limited to 10 hours)
BTN_EXTHT = 0x6,
/// Start the M1 biorhythm/preset program
BTN_M1 = 0x20,
/// Start the M2 biorhythm/preset program
BTN_M2 = 0x21,
/// Start the M3 biorhythm/preset program
BTN_M3 = 0x22,
/* These are "MAGIC" buttons */
/// Turn debug mode on/off
MAGIC_DEBUG_ON = 0x40,
MAGIC_DEBUG_OFF = 0x41,
/// Perform a connection test.
MAGIC_CONNTEST = 0x42,
/// Request a firmware update. This will also restart the Bedjet.
MAGIC_UPDATE = 0x43,
/// Acknowledge notification handled. See BedjetNotify
MAGIC_NOTIFY_ACK = 0x52,
};
enum BedjetCommand : uint8_t {
CMD_BUTTON = 0x1,
CMD_SET_RUNTIME = 0x2,
CMD_SET_TEMP = 0x3,
CMD_STATUS = 0x6,
CMD_SET_FAN = 0x7,
CMD_SET_CLOCK = 0x8,
};
#define BEDJET_FAN_STEP_NAMES_ \
{ \
"5%", "10%", "15%", "20%", "25%", "30%", "35%", "40%", "45%", "50%", "55%", "60%", "65%", "70%", "75%", "80%", \
"85%", "90%", "95%", "100%" \
}
static const uint8_t BEDJET_FAN_SPEED_COUNT = 20;
static const char *const BEDJET_FAN_STEP_NAMES[BEDJET_FAN_SPEED_COUNT] = BEDJET_FAN_STEP_NAMES_;
static const std::string BEDJET_FAN_STEP_NAME_STRINGS[BEDJET_FAN_SPEED_COUNT] = BEDJET_FAN_STEP_NAMES_;
static const std::set<std::string> BEDJET_FAN_STEP_NAMES_SET BEDJET_FAN_STEP_NAMES_;
} // namespace bedjet
} // namespace esphome
+543
View File
@@ -0,0 +1,543 @@
#include "bedjet_hub.h"
#include "bedjet_child.h"
#include "bedjet_const.h"
namespace esphome {
namespace bedjet {
static const LogString *bedjet_button_to_string(BedjetButton button) {
switch (button) {
case BTN_OFF:
return LOG_STR("OFF");
case BTN_COOL:
return LOG_STR("COOL");
case BTN_HEAT:
return LOG_STR("HEAT");
case BTN_EXTHT:
return LOG_STR("EXT HT");
case BTN_TURBO:
return LOG_STR("TURBO");
case BTN_DRY:
return LOG_STR("DRY");
case BTN_M1:
return LOG_STR("M1");
case BTN_M2:
return LOG_STR("M2");
case BTN_M3:
return LOG_STR("M3");
default:
return LOG_STR("unknown");
}
}
/* Public */
void BedJetHub::upgrade_firmware() {
auto *pkt = this->codec_->get_button_request(MAGIC_UPDATE);
auto status = this->write_bedjet_packet_(pkt);
if (status) {
ESP_LOGW(TAG, "[%s] MAGIC_UPDATE button failed, status=%d", this->get_name().c_str(), status);
}
}
bool BedJetHub::button_heat() { return this->send_button(BTN_HEAT); }
bool BedJetHub::button_ext_heat() { return this->send_button(BTN_EXTHT); }
bool BedJetHub::button_turbo() { return this->send_button(BTN_TURBO); }
bool BedJetHub::button_cool() { return this->send_button(BTN_COOL); }
bool BedJetHub::button_dry() { return this->send_button(BTN_DRY); }
bool BedJetHub::button_off() { return this->send_button(BTN_OFF); }
bool BedJetHub::button_memory1() { return this->send_button(BTN_M1); }
bool BedJetHub::button_memory2() { return this->send_button(BTN_M2); }
bool BedJetHub::button_memory3() { return this->send_button(BTN_M3); }
bool BedJetHub::set_fan_index(uint8_t fan_speed_index) {
if (fan_speed_index > 19) {
ESP_LOGW(TAG, "Invalid fan speed index %d, expecting 0-19.", fan_speed_index);
return false;
}
auto *pkt = this->codec_->get_set_fan_speed_request(fan_speed_index);
auto status = this->write_bedjet_packet_(pkt);
if (status) {
ESP_LOGW(TAG, "[%s] writing fan speed failed, status=%d", this->get_name().c_str(), status);
}
return status == 0;
}
uint8_t BedJetHub::get_fan_index() {
auto *status = this->codec_->get_status_packet();
if (status != nullptr) {
return status->fan_step;
}
return 0;
}
bool BedJetHub::set_target_temp(float temp_c) {
auto *pkt = this->codec_->get_set_target_temp_request(temp_c);
auto status = this->write_bedjet_packet_(pkt);
if (status) {
ESP_LOGW(TAG, "[%s] writing target temp failed, status=%d", this->get_name().c_str(), status);
}
return status == 0;
}
bool BedJetHub::set_time_remaining(uint8_t hours, uint8_t mins) {
// FIXME: this may fail depending on current mode or other restrictions enforced by the unit.
auto *pkt = this->codec_->get_set_runtime_remaining_request(hours, mins);
auto status = this->write_bedjet_packet_(pkt);
if (status) {
ESP_LOGW(TAG, "[%s] writing remaining runtime failed, status=%d", this->get_name().c_str(), status);
}
return status == 0;
}
bool BedJetHub::send_button(BedjetButton button) {
auto *pkt = this->codec_->get_button_request(button);
auto status = this->write_bedjet_packet_(pkt);
if (status) {
ESP_LOGW(TAG, "[%s] writing button %s failed, status=%d", this->get_name().c_str(),
LOG_STR_ARG(bedjet_button_to_string(button)), status);
} else {
ESP_LOGD(TAG, "[%s] writing button %s success", this->get_name().c_str(),
LOG_STR_ARG(bedjet_button_to_string(button)));
}
return status == 0;
}
uint16_t BedJetHub::get_time_remaining() {
auto *status = this->codec_->get_status_packet();
if (status != nullptr) {
return status->time_remaining_secs + status->time_remaining_mins * 60 + status->time_remaining_hrs * 3600;
}
return 0;
}
/* Bluetooth/GATT */
uint8_t BedJetHub::write_bedjet_packet_(BedjetPacket *pkt) {
if (!this->is_connected()) {
if (!this->parent_->enabled) {
ESP_LOGI(TAG, "[%s] Cannot write packet: Not connected, enabled=false", this->get_name().c_str());
} else {
ESP_LOGW(TAG, "[%s] Cannot write packet: Not connected", this->get_name().c_str());
}
return -1;
}
auto status = esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(),
this->char_handle_cmd_, pkt->data_length + 1, (uint8_t *) &pkt->command,
ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
return status;
}
/** Configures the local ESP BLE client to register (`true`) or unregister (`false`) for status notifications. */
uint8_t BedJetHub::set_notify_(const bool enable) {
uint8_t status;
if (enable) {
status = esp_ble_gattc_register_for_notify(this->parent_->get_gattc_if(), this->parent_->get_remote_bda(),
this->char_handle_status_);
if (status) {
ESP_LOGW(TAG, "[%s] esp_ble_gattc_register_for_notify failed, status=%d", this->get_name().c_str(), status);
}
} else {
status = esp_ble_gattc_unregister_for_notify(this->parent_->get_gattc_if(), this->parent_->get_remote_bda(),
this->char_handle_status_);
if (status) {
ESP_LOGW(TAG, "[%s] esp_ble_gattc_unregister_for_notify failed, status=%d", this->get_name().c_str(), status);
}
}
ESP_LOGV(TAG, "[%s] set_notify: enable=%d; result=%d", this->get_name().c_str(), enable, status);
return status;
}
bool BedJetHub::discover_characteristics_() {
bool result = true;
esphome::ble_client::BLECharacteristic *chr;
if (!this->char_handle_cmd_) {
chr = this->parent_->get_characteristic(BEDJET_SERVICE_UUID, BEDJET_COMMAND_UUID);
if (chr == nullptr) {
ESP_LOGW(TAG, "[%s] No control service found at device, not a BedJet..?", this->get_name().c_str());
result = false;
} else {
this->char_handle_cmd_ = chr->handle;
}
}
if (!this->char_handle_status_) {
chr = this->parent_->get_characteristic(BEDJET_SERVICE_UUID, BEDJET_STATUS_UUID);
if (chr == nullptr) {
ESP_LOGW(TAG, "[%s] No status service found at device, not a BedJet..?", this->get_name().c_str());
result = false;
} else {
this->char_handle_status_ = chr->handle;
}
}
if (!this->config_descr_status_) {
// We also need to obtain the config descriptor for this handle.
// Otherwise once we set node_state=Established, the parent will flush all handles/descriptors, and we won't be
// able to look it up.
auto *descr = this->parent_->get_config_descriptor(this->char_handle_status_);
if (descr == nullptr) {
ESP_LOGW(TAG, "No config descriptor for status handle 0x%x. Will not be able to receive status notifications",
this->char_handle_status_);
result = false;
} else if (descr->uuid.get_uuid().len != ESP_UUID_LEN_16 ||
descr->uuid.get_uuid().uuid.uuid16 != ESP_GATT_UUID_CHAR_CLIENT_CONFIG) {
ESP_LOGW(TAG, "Config descriptor 0x%x (uuid %s) is not a client config char uuid", this->char_handle_status_,
descr->uuid.to_string().c_str());
result = false;
} else {
this->config_descr_status_ = descr->handle;
}
}
if (!this->char_handle_name_) {
chr = this->parent_->get_characteristic(BEDJET_SERVICE_UUID, BEDJET_NAME_UUID);
if (chr == nullptr) {
ESP_LOGW(TAG, "[%s] No name service found at device, not a BedJet..?", this->get_name().c_str());
result = false;
} else {
this->char_handle_name_ = chr->handle;
auto status = esp_ble_gattc_read_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(),
this->char_handle_name_, ESP_GATT_AUTH_REQ_NONE);
if (status) {
ESP_LOGI(TAG, "[%s] Unable to read name characteristic: %d", this->get_name().c_str(), status);
}
}
}
ESP_LOGI(TAG, "[%s] Discovered service characteristics: ", this->get_name().c_str());
ESP_LOGI(TAG, " - Command char: 0x%x", this->char_handle_cmd_);
ESP_LOGI(TAG, " - Status char: 0x%x", this->char_handle_status_);
ESP_LOGI(TAG, " - config descriptor: 0x%x", this->config_descr_status_);
ESP_LOGI(TAG, " - Name char: 0x%x", this->char_handle_name_);
return result;
}
void BedJetHub::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
esp_ble_gattc_cb_param_t *param) {
switch (event) {
case ESP_GATTC_DISCONNECT_EVT: {
ESP_LOGV(TAG, "Disconnected: reason=%d", param->disconnect.reason);
this->status_set_warning();
this->dispatch_state_(false);
break;
}
case ESP_GATTC_SEARCH_CMPL_EVT: {
auto result = this->discover_characteristics_();
if (result) {
ESP_LOGD(TAG, "[%s] Services complete: obtained char handles.", this->get_name().c_str());
this->node_state = espbt::ClientState::ESTABLISHED;
this->set_notify_(true);
#ifdef USE_TIME
if (this->time_id_.has_value()) {
this->send_local_time();
}
#endif
this->dispatch_state_(true);
} else {
ESP_LOGW(TAG, "[%s] Failed discovering service characteristics.", this->get_name().c_str());
this->parent()->set_enabled(false);
this->status_set_warning();
this->dispatch_state_(false);
}
break;
}
case ESP_GATTC_WRITE_DESCR_EVT: {
if (param->write.status != ESP_GATT_OK) {
if (param->write.status == ESP_GATT_INVALID_ATTR_LEN) {
// This probably means that our hack for notify_en (8 bit vs 16 bit) didn't work right.
// Should we try to fall back to BLEClient's way?
ESP_LOGW(TAG, "[%s] Invalid attr length writing descr at handle 0x%04d, status=%d", this->get_name().c_str(),
param->write.handle, param->write.status);
} else {
ESP_LOGW(TAG, "[%s] Error writing descr at handle 0x%04d, status=%d", this->get_name().c_str(),
param->write.handle, param->write.status);
}
break;
}
ESP_LOGD(TAG, "[%s] Write to handle 0x%04x status=%d", this->get_name().c_str(), param->write.handle,
param->write.status);
break;
}
case ESP_GATTC_WRITE_CHAR_EVT: {
if (param->write.status != ESP_GATT_OK) {
ESP_LOGW(TAG, "Error writing char at handle 0x%04d, status=%d", param->write.handle, param->write.status);
break;
}
if (param->write.handle == this->char_handle_cmd_) {
if (this->force_refresh_) {
// Command write was successful. Publish the pending state, hoping that notify will kick in.
// FIXME: better to wait until we know the status has changed
this->dispatch_status_();
}
}
break;
}
case ESP_GATTC_READ_CHAR_EVT: {
if (param->read.conn_id != this->parent_->get_conn_id())
break;
if (param->read.status != ESP_GATT_OK) {
ESP_LOGW(TAG, "Error reading char at handle %d, status=%d", param->read.handle, param->read.status);
break;
}
if (param->read.handle == this->char_handle_status_) {
// This is the additional packet that doesn't fit in the notify packet.
this->codec_->decode_extra(param->read.value, param->read.value_len);
this->status_packet_ready_();
} else if (param->read.handle == this->char_handle_name_) {
// The data should represent the name.
if (param->read.status == ESP_GATT_OK && param->read.value_len > 0) {
std::string bedjet_name(reinterpret_cast<char const *>(param->read.value), param->read.value_len);
ESP_LOGV(TAG, "[%s] Got BedJet name: '%s'", this->get_name().c_str(), bedjet_name.c_str());
this->set_name_(bedjet_name);
}
}
break;
}
case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
// This event means that ESP received the request to enable notifications on the client side. But we also have to
// tell the server that we want it to send notifications. Normally BLEClient parent would handle this
// automatically, but as soon as we set our status to Established, the parent is going to purge all the
// service/char/descriptor handles, and then get_config_descriptor() won't work anymore. There's no way to disable
// the BLEClient parent behavior, so our only option is to write the handle anyway, and hope a double-write
// doesn't break anything.
if (param->reg_for_notify.handle != this->char_handle_status_) {
ESP_LOGW(TAG, "[%s] Register for notify on unexpected handle 0x%04x, expecting 0x%04x",
this->get_name().c_str(), param->reg_for_notify.handle, this->char_handle_status_);
break;
}
this->write_notify_config_descriptor_(true);
this->last_notify_ = 0;
this->force_refresh_ = true;
break;
}
case ESP_GATTC_UNREG_FOR_NOTIFY_EVT: {
// This event is not handled by the parent BLEClient, so we need to do this either way.
if (param->unreg_for_notify.handle != this->char_handle_status_) {
ESP_LOGW(TAG, "[%s] Unregister for notify on unexpected handle 0x%04x, expecting 0x%04x",
this->get_name().c_str(), param->unreg_for_notify.handle, this->char_handle_status_);
break;
}
this->write_notify_config_descriptor_(false);
this->last_notify_ = 0;
// Now we wait until the next update() poll to re-register notify...
break;
}
case ESP_GATTC_NOTIFY_EVT: {
if (this->processing_)
break;
if (param->notify.conn_id != this->parent_->get_conn_id()) {
ESP_LOGW(TAG, "[%s] Received notify event for unexpected parent conn: expect %x, got %x",
this->get_name().c_str(), this->parent_->get_conn_id(), param->notify.conn_id);
// FIXME: bug in BLEClient holding wrong conn_id.
}
if (param->notify.handle != this->char_handle_status_) {
ESP_LOGW(TAG, "[%s] Unexpected notify handle, wanted %04X, got %04X", this->get_name().c_str(),
this->char_handle_status_, param->notify.handle);
break;
}
// FIXME: notify events come in every ~200-300 ms, which is too fast to be helpful. So we
// throttle the updates to once every MIN_NOTIFY_THROTTLE (5 seconds).
// Another idea would be to keep notify off by default, and use update() as an opportunity to turn on
// notify to get enough data to update status, then turn off notify again.
uint32_t now = millis();
auto delta = now - this->last_notify_;
if (!this->force_refresh_ && this->codec_->compare(param->notify.value, param->notify.value_len)) {
// If the packet is meaningfully different, trigger children as well
this->force_refresh_ = true;
ESP_LOGV(TAG, "[%s] Incoming packet indicates a significant change.", this->get_name().c_str());
}
if (this->last_notify_ == 0 || delta > MIN_NOTIFY_THROTTLE || this->force_refresh_) {
// Set reentrant flag to prevent processing multiple packets.
this->processing_ = true;
ESP_LOGVV(TAG, "[%s] Decoding packet: last=%d, delta=%d, force=%s", this->get_name().c_str(),
this->last_notify_, delta, this->force_refresh_ ? "y" : "n");
bool needs_extra = this->codec_->decode_notify(param->notify.value, param->notify.value_len);
if (needs_extra) {
// This means the packet was partial, so read the status characteristic to get the second part.
// Ideally this will complete quickly. We won't process additional notification events until it does.
auto status = esp_ble_gattc_read_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(),
this->char_handle_status_, ESP_GATT_AUTH_REQ_NONE);
if (status) {
ESP_LOGI(TAG, "[%s] Unable to read extended status packet", this->get_name().c_str());
}
} else {
this->status_packet_ready_();
}
}
break;
}
default:
ESP_LOGVV(TAG, "[%s] gattc unhandled event: enum=%d", this->get_name().c_str(), event);
break;
}
}
inline void BedJetHub::status_packet_ready_() {
this->last_notify_ = millis();
this->processing_ = false;
if (this->force_refresh_) {
// If we requested an immediate update, do that now.
this->update();
this->force_refresh_ = false;
}
}
/** Reimplementation of BLEClient.gattc_event_handler() for ESP_GATTC_REG_FOR_NOTIFY_EVT.
*
* This is a copy of ble_client's automatic handling of `ESP_GATTC_REG_FOR_NOTIFY_EVT`, in order
* to undo the same on unregister. It also allows us to maintain the config descriptor separately,
* since the parent BLEClient is going to purge all descriptors once we set our connection status
* to `Established`.
*/
uint8_t BedJetHub::write_notify_config_descriptor_(bool enable) {
auto handle = this->config_descr_status_;
if (handle == 0) {
ESP_LOGW(TAG, "No descriptor found for notify of handle 0x%x", this->char_handle_status_);
return -1;
}
// NOTE: BLEClient uses `uint8_t*` of length 1, but BLE spec requires 16 bits.
uint16_t notify_en = enable ? 1 : 0;
auto status = esp_ble_gattc_write_char_descr(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), handle,
sizeof(notify_en), (uint8_t *) &notify_en, ESP_GATT_WRITE_TYPE_RSP,
ESP_GATT_AUTH_REQ_NONE);
if (status) {
ESP_LOGW(TAG, "esp_ble_gattc_write_char_descr error, status=%d", status);
return status;
}
ESP_LOGD(TAG, "[%s] wrote notify=%s to status config 0x%04x, for conn %d", this->get_name().c_str(),
enable ? "true" : "false", handle, this->parent_->get_conn_id());
return ESP_GATT_OK;
}
/* Time Component */
#ifdef USE_TIME
void BedJetHub::send_local_time() {
if (this->time_id_.has_value()) {
auto *time_id = *this->time_id_;
time::ESPTime now = time_id->now();
if (now.is_valid()) {
this->set_clock(now.hour, now.minute);
ESP_LOGD(TAG, "Using time component to set BedJet clock: %d:%02d", now.hour, now.minute);
}
} else {
ESP_LOGI(TAG, "`time_id` is not configured: will not sync BedJet clock.");
}
}
void BedJetHub::setup_time_() {
if (this->time_id_.has_value()) {
this->send_local_time();
auto *time_id = *this->time_id_;
time_id->add_on_time_sync_callback([this] { this->send_local_time(); });
} else {
ESP_LOGI(TAG, "`time_id` is not configured: will not sync BedJet clock.");
}
}
#endif
void BedJetHub::set_clock(uint8_t hour, uint8_t minute) {
if (!this->is_connected()) {
ESP_LOGV(TAG, "[%s] Not connected, cannot send time.", this->get_name().c_str());
return;
}
BedjetPacket *pkt = this->codec_->get_set_time_request(hour, minute);
auto status = this->write_bedjet_packet_(pkt);
if (status) {
ESP_LOGW(TAG, "Failed setting BedJet clock: %d", status);
} else {
ESP_LOGD(TAG, "[%s] BedJet clock set to: %d:%02d", this->get_name().c_str(), hour, minute);
}
}
/* Internal */
void BedJetHub::loop() {}
void BedJetHub::update() { this->dispatch_status_(); }
void BedJetHub::dump_config() {
ESP_LOGCONFIG(TAG, "BedJet Hub '%s'", this->get_name().c_str());
ESP_LOGCONFIG(TAG, " ble_client.app_id: %d", this->parent()->app_id);
ESP_LOGCONFIG(TAG, " ble_client.conn_id: %d", this->parent()->get_conn_id());
LOG_UPDATE_INTERVAL(this)
ESP_LOGCONFIG(TAG, " Child components (%d):", this->children_.size());
for (auto *child : this->children_) {
ESP_LOGCONFIG(TAG, " - %s", child->describe().c_str());
}
}
void BedJetHub::dispatch_state_(bool is_ready) {
for (auto *child : this->children_) {
child->on_bedjet_state(is_ready);
}
}
void BedJetHub::dispatch_status_() {
auto *status = this->codec_->get_status_packet();
if (!this->is_connected()) {
ESP_LOGD(TAG, "[%s] Not connected, will not send status.", this->get_name().c_str());
} else if (status != nullptr) {
ESP_LOGD(TAG, "[%s] Notifying %d children of latest status @%p.", this->get_name().c_str(), this->children_.size(),
status);
for (auto *child : this->children_) {
child->on_status(status);
}
} else {
uint32_t now = millis();
uint32_t diff = now - this->last_notify_;
if (this->last_notify_ == 0) {
// This means we're connected and haven't received a notification, so it likely means that the BedJet is off.
// However, it could also mean that it's running, but failing to send notifications.
// We can try to unregister for notifications now, and then re-register, hoping to clear it up...
// But how do we know for sure which state we're in, and how do we actually clear out the buggy state?
ESP_LOGI(TAG, "[%s] Still waiting for first GATT notify event.", this->get_name().c_str());
} else if (diff > NOTIFY_WARN_THRESHOLD) {
ESP_LOGW(TAG, "[%s] Last GATT notify was %d seconds ago.", this->get_name().c_str(), diff / 1000);
}
if (this->timeout_ > 0 && diff > this->timeout_ && this->parent()->enabled) {
ESP_LOGW(TAG, "[%s] Timed out after %d sec. Retrying...", this->get_name().c_str(), this->timeout_);
// set_enabled(false) will only close the connection if state != IDLE.
this->parent()->set_state(espbt::ClientState::CONNECTING);
this->parent()->set_enabled(false);
this->parent()->set_enabled(true);
}
}
}
void BedJetHub::register_child(BedJetClient *obj) {
this->children_.push_back(obj);
obj->set_parent(this);
}
} // namespace bedjet
} // namespace esphome
+176
View File
@@ -0,0 +1,176 @@
#pragma once
#include "esphome/components/ble_client/ble_client.h"
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
#include "esphome/core/component.h"
#include "esphome/core/defines.h"
#include "esphome/core/hal.h"
#include "bedjet_child.h"
#include "bedjet_codec.h"
#ifdef USE_TIME
#include "esphome/components/time/real_time_clock.h"
#endif
#ifdef USE_ESP32
#include <esp_gattc_api.h>
namespace esphome {
namespace bedjet {
namespace espbt = esphome::esp32_ble_tracker;
// Forward declare BedJetClient
class BedJetClient;
static const espbt::ESPBTUUID BEDJET_SERVICE_UUID = espbt::ESPBTUUID::from_raw("00001000-bed0-0080-aa55-4265644a6574");
static const espbt::ESPBTUUID BEDJET_STATUS_UUID = espbt::ESPBTUUID::from_raw("00002000-bed0-0080-aa55-4265644a6574");
static const espbt::ESPBTUUID BEDJET_COMMAND_UUID = espbt::ESPBTUUID::from_raw("00002004-bed0-0080-aa55-4265644a6574");
static const espbt::ESPBTUUID BEDJET_NAME_UUID = espbt::ESPBTUUID::from_raw("00002001-bed0-0080-aa55-4265644a6574");
/**
* Hub component connecting to the BedJet device over Bluetooth.
*/
class BedJetHub : public esphome::ble_client::BLEClientNode, public PollingComponent {
public:
/* BedJet functionality exposed to `BedJetClient` children and/or accessible from action lambdas. */
/** Attempts to check for and apply firmware updates. */
void upgrade_firmware();
/** Press the OFF button. */
bool button_off();
/** Press the HEAT button. */
bool button_heat();
/** Press the EXT HT button. */
bool button_ext_heat();
/** Press the TURBO button. */
bool button_turbo();
/** Press the COOL button. */
bool button_cool();
/** Press the DRY button. */
bool button_dry();
/** Press the M1 (memory recall) button. */
bool button_memory1();
/** Press the M2 (memory recall) button. */
bool button_memory2();
/** Press the M3 (memory recall) button. */
bool button_memory3();
/** Send the `button`. */
bool send_button(BedjetButton button);
/** Set the target temperature to `temp_c` in °C. */
bool set_target_temp(float temp_c);
/** Set the fan speed to a stepped index in the range 0-19. */
bool set_fan_index(uint8_t fan_speed_index);
/** Set the fan speed to a percent in the range 5% - 100%, at 5% increments. */
bool set_fan_speed(uint8_t fan_speed_pct) { return this->set_fan_index(bedjet_fan_speed_to_index(fan_speed_pct)); }
/** Return the fan speed index, in the range 0-19. */
uint8_t get_fan_index();
/** Return the fan speed as a percent in the range 5%-100%. */
uint8_t get_fan_speed() { return bedjet_fan_step_to_speed(this->get_fan_index()); }
/** Set the operational runtime remaining.
*
* The unit establishes and enforces runtime limits for some modes, so this call is not guaranteed to succeed.
*/
bool set_time_remaining(uint8_t hours, uint8_t mins);
/** Return the remaining runtime, in seconds. */
uint16_t get_time_remaining();
/** @return `true` if the `BLEClient::node_state` is `ClientState::ESTABLISHED`. */
bool is_connected() { return this->node_state == espbt::ClientState::ESTABLISHED; }
bool has_status() { return this->codec_->has_status(); }
const BedjetStatusPacket *get_status_packet() const { return this->codec_->get_status_packet(); }
/** Register a `BedJetClient` child component. */
void register_child(BedJetClient *obj);
/** Set the status timeout.
*
* This is the max time to wait for a status update before the connection is presumed unusable.
*/
void set_status_timeout(uint32_t timeout) { this->timeout_ = timeout; }
#ifdef USE_TIME
/** Set the `time::RealTimeClock` implementation. */
void set_time_id(time::RealTimeClock *time_id) { this->time_id_ = time_id; }
/** Attempts to sync the local time (via `time_id`) to the BedJet device. */
void send_local_time();
#endif
/** Attempt to set the BedJet device's clock to the specified time. */
void set_clock(uint8_t hour, uint8_t minute);
/* Component overrides */
void loop() override;
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; }
/** @return The BedJet's configured name, or the MAC address if not discovered yet. */
std::string get_name() {
if (this->name_.empty()) {
return this->parent_->address_str();
} else {
return this->name_;
}
}
/* BLEClient overrides */
void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
esp_ble_gattc_cb_param_t *param) override;
protected:
std::vector<BedJetClient *> children_;
void dispatch_status_();
void dispatch_state_(bool is_ready);
#ifdef USE_TIME
/** Initializes time sync callbacks to support syncing current time to the BedJet. */
void setup_time_();
optional<time::RealTimeClock *> time_id_{};
#endif
uint32_t timeout_{DEFAULT_STATUS_TIMEOUT};
static const uint32_t MIN_NOTIFY_THROTTLE = 15000;
static const uint32_t NOTIFY_WARN_THRESHOLD = 300000;
static const uint32_t DEFAULT_STATUS_TIMEOUT = 900000;
uint8_t set_notify_(bool enable);
/** Send the `BedjetPacket` to the device. */
uint8_t write_bedjet_packet_(BedjetPacket *pkt);
void set_name_(const std::string &name) { this->name_ = name; }
std::string name_;
uint32_t last_notify_ = 0;
inline void status_packet_ready_();
bool force_refresh_ = false;
bool processing_ = false;
std::unique_ptr<BedjetCodec> codec_;
bool discover_characteristics_();
uint16_t char_handle_cmd_;
uint16_t char_handle_name_;
uint16_t char_handle_status_;
uint16_t config_descr_status_;
uint8_t write_notify_config_descriptor_(bool enable);
};
} // namespace bedjet
} // namespace esphome
#endif
@@ -0,0 +1,65 @@
import logging
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import climate, ble_client
from esphome.const import (
CONF_HEAT_MODE,
CONF_ID,
CONF_RECEIVE_TIMEOUT,
CONF_TIME_ID,
)
from .. import (
BEDJET_CLIENT_SCHEMA,
bedjet_ns,
register_bedjet_child,
)
_LOGGER = logging.getLogger(__name__)
CODEOWNERS = ["@jhansche"]
DEPENDENCIES = ["bedjet"]
BedJetClimate = bedjet_ns.class_("BedJetClimate", climate.Climate, cg.PollingComponent)
BedjetHeatMode = bedjet_ns.enum("BedjetHeatMode")
BEDJET_HEAT_MODES = {
"heat": BedjetHeatMode.HEAT_MODE_HEAT,
"extended": BedjetHeatMode.HEAT_MODE_EXTENDED,
}
CONFIG_SCHEMA = (
climate.CLIMATE_SCHEMA.extend(
{
cv.GenerateID(): cv.declare_id(BedJetClimate),
cv.Optional(CONF_HEAT_MODE, default="heat"): cv.enum(
BEDJET_HEAT_MODES, lower=True
),
}
)
.extend(cv.polling_component_schema("60s"))
.extend(
# TODO: remove compat layer.
{
cv.Optional(ble_client.CONF_BLE_CLIENT_ID): cv.invalid(
"The 'ble_client_id' option has been removed. Please migrate "
"to the new `bedjet_id` option in the `bedjet` component.\n"
"See https://esphome.io/components/climate/bedjet.html"
),
cv.Optional(CONF_TIME_ID): cv.invalid(
"The 'time_id' option has been moved to the `bedjet` component."
),
cv.Optional(CONF_RECEIVE_TIMEOUT): cv.invalid(
"The 'receive_timeout' option has been moved to the `bedjet` component."
),
}
)
.extend(BEDJET_CLIENT_SCHEMA)
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
await climate.register_climate(var, config)
await register_bedjet_child(var, config)
cg.add(var.set_heating_mode(config[CONF_HEAT_MODE]))
@@ -0,0 +1,354 @@
#include "bedjet_climate.h"
#include "esphome/core/log.h"
#ifdef USE_ESP32
namespace esphome {
namespace bedjet {
using namespace esphome::climate;
/// Converts a BedJet temp step into degrees Celsius.
float bedjet_temp_to_c(const uint8_t temp) {
// BedJet temp is "C*2"; to get C, divide by 2.
return temp / 2.0f;
}
static const std::string *bedjet_fan_step_to_fan_mode(const uint8_t fan_step) {
if (fan_step < BEDJET_FAN_SPEED_COUNT)
return &BEDJET_FAN_STEP_NAME_STRINGS[fan_step];
return nullptr;
}
static uint8_t bedjet_fan_speed_to_step(const std::string &fan_step_percent) {
for (int i = 0; i < BEDJET_FAN_SPEED_COUNT; i++) {
if (fan_step_percent == BEDJET_FAN_STEP_NAME_STRINGS[i]) {
return i;
}
}
return -1;
}
static inline BedjetButton heat_button(BedjetHeatMode mode) {
return mode == HEAT_MODE_EXTENDED ? BTN_EXTHT : BTN_HEAT;
}
std::string BedJetClimate::describe() { return "BedJet Climate"; }
void BedJetClimate::dump_config() {
LOG_CLIMATE("", "BedJet Climate", this);
auto traits = this->get_traits();
ESP_LOGCONFIG(TAG, " Supported modes:");
for (auto mode : traits.get_supported_modes()) {
ESP_LOGCONFIG(TAG, " - %s", LOG_STR_ARG(climate_mode_to_string(mode)));
}
if (this->heating_mode_ == HEAT_MODE_EXTENDED) {
ESP_LOGCONFIG(TAG, " - BedJet heating mode: EXT HT");
} else {
ESP_LOGCONFIG(TAG, " - BedJet heating mode: HEAT");
}
ESP_LOGCONFIG(TAG, " Supported fan modes:");
for (const auto &mode : traits.get_supported_fan_modes()) {
ESP_LOGCONFIG(TAG, " - %s", LOG_STR_ARG(climate_fan_mode_to_string(mode)));
}
for (const auto &mode : traits.get_supported_custom_fan_modes()) {
ESP_LOGCONFIG(TAG, " - %s (c)", mode.c_str());
}
ESP_LOGCONFIG(TAG, " Supported presets:");
for (auto preset : traits.get_supported_presets()) {
ESP_LOGCONFIG(TAG, " - %s", LOG_STR_ARG(climate_preset_to_string(preset)));
}
for (const auto &preset : traits.get_supported_custom_presets()) {
ESP_LOGCONFIG(TAG, " - %s (c)", preset.c_str());
}
}
void BedJetClimate::setup() {
// restore set points
auto restore = this->restore_state_();
if (restore.has_value()) {
ESP_LOGI(TAG, "Restored previous saved state.");
restore->apply(this);
} else {
// Initial status is unknown until we connect
this->reset_state_();
}
}
/** Resets states to defaults. */
void BedJetClimate::reset_state_() {
this->mode = CLIMATE_MODE_OFF;
this->action = CLIMATE_ACTION_IDLE;
this->target_temperature = NAN;
this->current_temperature = NAN;
this->preset.reset();
this->custom_preset.reset();
this->publish_state();
}
void BedJetClimate::loop() {}
void BedJetClimate::control(const ClimateCall &call) {
ESP_LOGD(TAG, "Received BedJetClimate::control");
if (!this->parent_->is_connected()) {
ESP_LOGW(TAG, "Not connected, cannot handle control call yet.");
return;
}
if (call.get_mode().has_value()) {
ClimateMode mode = *call.get_mode();
bool button_result;
switch (mode) {
case CLIMATE_MODE_OFF:
button_result = this->parent_->button_off();
break;
case CLIMATE_MODE_HEAT:
button_result = this->parent_->send_button(heat_button(this->heating_mode_));
break;
case CLIMATE_MODE_FAN_ONLY:
button_result = this->parent_->button_cool();
break;
case CLIMATE_MODE_DRY:
button_result = this->parent_->button_dry();
break;
default:
ESP_LOGW(TAG, "Unsupported mode: %d", mode);
return;
}
if (button_result) {
this->mode = mode;
// We're using (custom) preset for Turbo, EXT HT, & M1-3 presets, so changing climate mode will clear those
this->custom_preset.reset();
this->preset.reset();
}
}
if (call.get_target_temperature().has_value()) {
auto target_temp = *call.get_target_temperature();
auto result = this->parent_->set_target_temp(target_temp);
if (result) {
this->target_temperature = target_temp;
}
}
if (call.get_preset().has_value()) {
ClimatePreset preset = *call.get_preset();
bool result;
if (preset == CLIMATE_PRESET_BOOST) {
// We use BOOST preset for TURBO mode, which is a short-lived/high-heat mode.
result = this->parent_->button_turbo();
if (result) {
this->mode = CLIMATE_MODE_HEAT;
this->preset = CLIMATE_PRESET_BOOST;
this->custom_preset.reset();
}
} else if (preset == CLIMATE_PRESET_NONE && this->preset.has_value()) {
if (this->mode == CLIMATE_MODE_HEAT && this->preset == CLIMATE_PRESET_BOOST) {
// We were in heat mode with Boost preset, and now preset is set to None, so revert to normal heat.
result = this->parent_->send_button(heat_button(this->heating_mode_));
if (result) {
this->preset.reset();
this->custom_preset.reset();
}
} else {
ESP_LOGD(TAG, "Ignoring preset '%s' call; with current mode '%s' and preset '%s'",
LOG_STR_ARG(climate_preset_to_string(preset)), LOG_STR_ARG(climate_mode_to_string(this->mode)),
LOG_STR_ARG(climate_preset_to_string(this->preset.value_or(CLIMATE_PRESET_NONE))));
}
} else {
ESP_LOGW(TAG, "Unsupported preset: %d", preset);
return;
}
} else if (call.get_custom_preset().has_value()) {
std::string preset = *call.get_custom_preset();
bool result;
if (preset == "M1") {
result = this->parent_->button_memory1();
} else if (preset == "M2") {
result = this->parent_->button_memory2();
} else if (preset == "M3") {
result = this->parent_->button_memory3();
} else if (preset == "LTD HT") {
result = this->parent_->button_heat();
} else if (preset == "EXT HT") {
result = this->parent_->button_ext_heat();
} else {
ESP_LOGW(TAG, "Unsupported preset: %s", preset.c_str());
return;
}
if (result) {
this->custom_preset = preset;
this->preset.reset();
}
}
if (call.get_fan_mode().has_value()) {
// Climate fan mode only supports low/med/high, but the BedJet supports 5-100% increments.
// We can still support a ClimateCall that requests low/med/high, and just translate it to a step increment here.
auto fan_mode = *call.get_fan_mode();
bool result;
if (fan_mode == CLIMATE_FAN_LOW) {
result = this->parent_->set_fan_speed(20);
} else if (fan_mode == CLIMATE_FAN_MEDIUM) {
result = this->parent_->set_fan_speed(50);
} else if (fan_mode == CLIMATE_FAN_HIGH) {
result = this->parent_->set_fan_speed(75);
} else {
ESP_LOGW(TAG, "[%s] Unsupported fan mode: %s", this->get_name().c_str(),
LOG_STR_ARG(climate_fan_mode_to_string(fan_mode)));
return;
}
if (result) {
this->fan_mode = fan_mode;
this->custom_fan_mode.reset();
}
} else if (call.get_custom_fan_mode().has_value()) {
auto fan_mode = *call.get_custom_fan_mode();
auto fan_index = bedjet_fan_speed_to_step(fan_mode);
if (fan_index <= 19) {
ESP_LOGV(TAG, "[%s] Converted fan mode %s to bedjet fan step %d", this->get_name().c_str(), fan_mode.c_str(),
fan_index);
bool result = this->parent_->set_fan_index(fan_index);
if (result) {
this->custom_fan_mode = fan_mode;
this->fan_mode.reset();
}
}
}
}
void BedJetClimate::on_bedjet_state(bool is_ready) {}
void BedJetClimate::on_status(const BedjetStatusPacket *data) {
ESP_LOGV(TAG, "[%s] Handling on_status with data=%p", this->get_name().c_str(), (void *) data);
auto converted_temp = bedjet_temp_to_c(data->target_temp_step);
if (converted_temp > 0)
this->target_temperature = converted_temp;
converted_temp = bedjet_temp_to_c(data->ambient_temp_step);
if (converted_temp > 0)
this->current_temperature = converted_temp;
const auto *fan_mode_name = bedjet_fan_step_to_fan_mode(data->fan_step);
if (fan_mode_name != nullptr) {
this->custom_fan_mode = *fan_mode_name;
}
// TODO: Get biorhythm data to determine which preset (M1-3) is running, if any.
switch (data->mode) {
case MODE_WAIT: // Biorhythm "wait" step: device is idle
case MODE_STANDBY:
this->mode = CLIMATE_MODE_OFF;
this->action = CLIMATE_ACTION_IDLE;
this->fan_mode = CLIMATE_FAN_OFF;
this->custom_preset.reset();
this->preset.reset();
break;
case MODE_HEAT:
this->mode = CLIMATE_MODE_HEAT;
this->action = CLIMATE_ACTION_HEATING;
this->preset.reset();
if (this->heating_mode_ == HEAT_MODE_EXTENDED) {
this->set_custom_preset_("LTD HT");
} else {
this->custom_preset.reset();
}
break;
case MODE_EXTHT:
this->mode = CLIMATE_MODE_HEAT;
this->action = CLIMATE_ACTION_HEATING;
this->preset.reset();
if (this->heating_mode_ == HEAT_MODE_EXTENDED) {
this->custom_preset.reset();
} else {
this->set_custom_preset_("EXT HT");
}
break;
case MODE_COOL:
this->mode = CLIMATE_MODE_FAN_ONLY;
this->action = CLIMATE_ACTION_COOLING;
this->custom_preset.reset();
this->preset.reset();
break;
case MODE_DRY:
this->mode = CLIMATE_MODE_DRY;
this->action = CLIMATE_ACTION_DRYING;
this->custom_preset.reset();
this->preset.reset();
break;
case MODE_TURBO:
this->preset = CLIMATE_PRESET_BOOST;
this->custom_preset.reset();
this->mode = CLIMATE_MODE_HEAT;
this->action = CLIMATE_ACTION_HEATING;
break;
default:
ESP_LOGW(TAG, "[%s] Unexpected mode: 0x%02X", this->get_name().c_str(), data->mode);
break;
}
ESP_LOGV(TAG, "[%s] After on_status, new mode=%s", this->get_name().c_str(),
LOG_STR_ARG(climate_mode_to_string(this->mode)));
// FIXME: compare new state to previous state.
this->publish_state();
}
/** Attempts to update the climate device from the last received BedjetStatusPacket.
*
* This will be called from #on_status() when the parent dispatches new status packets,
* and from #update() when the polling interval is triggered.
*
* @return `true` if the status has been applied; `false` if there is nothing to apply.
*/
bool BedJetClimate::update_status_() {
if (!this->parent_->is_connected())
return false;
if (!this->parent_->has_status())
return false;
auto *status = this->parent_->get_status_packet();
if (status == nullptr)
return false;
this->on_status(status);
if (this->is_valid_()) {
// TODO: only if state changed?
this->publish_state();
this->status_clear_warning();
return true;
}
return false;
}
void BedJetClimate::update() {
ESP_LOGD(TAG, "[%s] update()", this->get_name().c_str());
// TODO: if the hub component is already polling, do we also need to include polling?
// We're already going to get on_status() at the hub's polling interval.
auto result = this->update_status_();
ESP_LOGD(TAG, "[%s] update_status result=%s", this->get_name().c_str(), result ? "true" : "false");
}
} // namespace bedjet
} // namespace esphome
#endif
@@ -0,0 +1,91 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/core/defines.h"
#include "esphome/core/hal.h"
#include "esphome/components/bedjet/bedjet_child.h"
#include "esphome/components/bedjet/bedjet_codec.h"
#include "esphome/components/bedjet/bedjet_hub.h"
#include "esphome/components/climate/climate.h"
#ifdef USE_ESP32
namespace esphome {
namespace bedjet {
class BedJetClimate : public climate::Climate, public BedJetClient, public PollingComponent {
public:
void setup() override;
void loop() override;
void update() override;
void dump_config() override;
float get_setup_priority() const override { return setup_priority::AFTER_WIFI; }
/* BedJetClient status update */
void on_status(const BedjetStatusPacket *data) override;
void on_bedjet_state(bool is_ready) override;
std::string describe() override;
/** Sets the default strategy to use for climate::CLIMATE_MODE_HEAT. */
void set_heating_mode(BedjetHeatMode mode) { this->heating_mode_ = mode; }
climate::ClimateTraits traits() override {
auto traits = climate::ClimateTraits();
traits.set_supports_action(true);
traits.set_supports_current_temperature(true);
traits.set_supported_modes({
climate::CLIMATE_MODE_OFF,
climate::CLIMATE_MODE_HEAT,
// climate::CLIMATE_MODE_TURBO // Not supported by Climate: see presets instead
climate::CLIMATE_MODE_FAN_ONLY,
climate::CLIMATE_MODE_DRY,
});
// It would be better if we had a slider for the fan modes.
traits.set_supported_custom_fan_modes(BEDJET_FAN_STEP_NAMES_SET);
traits.set_supported_presets({
// If we support NONE, then have to decide what happens if the user switches to it (turn off?)
// climate::CLIMATE_PRESET_NONE,
// Climate doesn't have a "TURBO" mode, but we can use the BOOST preset instead.
climate::CLIMATE_PRESET_BOOST,
});
traits.set_supported_custom_presets({
// We could fetch biodata from bedjet and set these names that way.
// But then we have to invert the lookup in order to send the right preset.
// For now, we can leave them as M1-3 to match the remote buttons.
// EXT HT added to match remote button.
"EXT HT",
"M1",
"M2",
"M3",
});
if (this->heating_mode_ == HEAT_MODE_EXTENDED) {
traits.add_supported_custom_preset("LTD HT");
} else {
traits.add_supported_custom_preset("EXT HT");
}
traits.set_visual_min_temperature(19.0);
traits.set_visual_max_temperature(43.0);
traits.set_visual_temperature_step(1.0);
return traits;
}
protected:
void control(const climate::ClimateCall &call) override;
BedjetHeatMode heating_mode_ = HEAT_MODE_HEAT;
void reset_state_();
bool update_status_();
bool is_valid_() {
// FIXME: find a better way to check this?
return !std::isnan(this->current_temperature) && !std::isnan(this->target_temperature) &&
this->current_temperature > 1 && this->target_temperature > 1;
}
};
} // namespace bedjet
} // namespace esphome
#endif
+36
View File
@@ -0,0 +1,36 @@
import logging
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import fan
from esphome.const import (
CONF_ID,
)
from .. import (
BEDJET_CLIENT_SCHEMA,
bedjet_ns,
register_bedjet_child,
)
_LOGGER = logging.getLogger(__name__)
CODEOWNERS = ["@jhansche"]
DEPENDENCIES = ["bedjet"]
BedJetFan = bedjet_ns.class_("BedJetFan", fan.Fan, cg.PollingComponent)
CONFIG_SCHEMA = (
fan.FAN_SCHEMA.extend(
{
cv.GenerateID(): cv.declare_id(BedJetFan),
}
)
.extend(cv.polling_component_schema("60s"))
.extend(BEDJET_CLIENT_SCHEMA)
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
await fan.register_fan(var, config)
await register_bedjet_child(var, config)

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