Compare commits

..
Author SHA1 Message Date
J. Nick Koston e671c8ebdf Merge remote-tracking branch 'origin/esp8266-entity-names-flash' into esp8266-entity-names-components 2026-10-14 16:15:42 -10:00
J. Nick Koston fe2637356b Merge remote-tracking branch 'origin/api-action-strings-progmem' into esp8266-entity-names-flash 2026-10-14 16:15:04 -10:00
J. Nick Koston 6f7b875844 Merge remote-tracking branch 'origin/dev' into api-action-strings-progmem 2026-10-14 16:14:40 -10:00
J. Nick Koston 677516efcc Merge remote-tracking branch 'origin/esp8266-entity-names-flash' into esp8266-entity-names-components 2026-10-14 16:09:46 -10:00
Jonathan Swoboda f3eaf698d6 [mipi_rgb] Rotate pure RGB panels in software (#20757) 2026-10-14 22:05:01 -04:00
J. Nick Koston 52ec1c7ccf Merge remote-tracking branch 'origin/api-action-strings-progmem' into esp8266-entity-names-flash
# Conflicts:
#	esphome/core/string_ref.h
#	tests/components/core/test_progmem_string_ref.cpp
2026-10-14 16:01:49 -10:00
J. Nick Koston f7057e1270 [tests] Reset saved preferences before every C++ unit test (#20771) 2026-10-14 16:01:45 -10:00
J. Nick Koston 6edfbb594d [bluetooth_connection] Value-initialize the connection parameters for ESP-IDF 6.1 (#20774) 2026-10-14 22:00:07 -04:00
J. Nick Koston 22defcd704 [esp32_ble_client] Value-initialize the connection parameters for ESP-IDF 6.1 (#20776) 2026-10-14 21:59:56 -04:00
J. Nick Koston ef5b0861f1 Encode Home Assistant action names and data from flash 2026-10-14 15:59:41 -10:00
J. Nick Koston da561e08d6 Keep the RAM short string encode on memcpy; the ESP8266 shared copy moves to #20423 2026-10-14 15:59:41 -10:00
Jonathan Swoboda 0f408234d0 [core] Add ksz8851snl to the static analysis manifest for IDF 6 (#20788) 2026-10-14 21:53:17 -04:00
Jonathan Swoboda 92e0e6db6b [wifi] Call esp_supp_dpp_init without a callback on ESP-IDF 6 (#20789) 2026-10-15 01:40:07 +00:00
908c2f6778 [wifi] Add Wi-Fi Easy Connect (DPP) provisioning on the ESP32 (#17934)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-14 14:29:47 -10:00
Keith BurzinskiandClaude Opus 5.5 af709ac9a5 [openthread] Fail instead of aborting when NVS is unavailable (#20717)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 13:30:36 -10:00
Panoplian fe57eef3f6 [core] Test that includes inside a package resolve next to the package (#20739) 2026-10-14 13:28:01 -10:00
d0b9f195b0 [wifi] Apply reboot_timeout with a fallback AP unless a station is connected to it (#9958)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-10-14 13:23:37 -10:00
eafeef7cb8 [fusb302b] Add FUSB302B driver (#20760)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-14 13:18:20 -10:00
471774cdbf [ecocomfort2] Fix the clock sync and read boost from the unit state (#20782)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-10-14 13:14:04 -10:00
Kevin AhrendtandJ. Nick Koston 4df6291feb [api][sendspin] Add the Sendspin client id to the capabilities message (#20775)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-10-14 22:56:51 +00:00
d8ca4a9460 [audio_dac] Add ES9038Q2M Katana platform (#15017)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-14 22:50:41 +00:00
48a0a41cce [wifi] Implement access point WISP mode (#13633)
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-14 12:49:37 -10:00
esphome[bot] 0e2c4cf5c2 Bump aioesphomeapi from 46.11.0 to 46.12.0 (#20781)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-10-14 12:43:07 -10:00
ea76073d86 [micro_wake_word] Allow selecting the inference task core (#20126)
Co-authored-by: n-IA-hane <n-IA-hane@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-14 12:42:24 -10:00
J. Nick Koston dcb943ded3 [noise] Initialize the protocol id's reserved field for ESP-IDF 6.1 (#20779) 2026-10-14 11:45:54 -10:00
dependabot[bot] 2c6f59738c Bump filelock from 4.1.0 to 4.1.1 (#20778)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-14 21:41:28 +00:00
puddlyandJ. Nick Koston 04715fb32b [usb_uart] Expose interface_class and port_number (#20659)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-14 21:41:12 +00:00
nullable.ethandJ. Nick Koston 3df9360876 [i2s_audio] Add keep_alive option to speaker to prevent pop/click on audio start (#15565)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-14 11:39:30 -10:00
dependabot[bot] 61f3de0bc0 Bump pylint from 4.1.2 to 4.1.3 (#20773)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-14 21:30:26 +00:00
dependabot[bot] cd97c9a9cb Bump platformdirs from 4.12.4 to 4.13.0 (#20772)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-14 21:29:17 +00:00
J. Nick Koston d3668a7186 [mqtt] Match subscription topics in a loop instead of recursing per character (#20767) 2026-10-14 11:13:32 -10:00
J. Nick Koston ac74796263 [friedrich] Clear saved preferences in the test fixture (#20770) 2026-10-14 10:52:13 -10:00
c56bb14037 [mqtt] Print crash info over MQTT (#17935)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-10-14 10:39:55 -10:00
J. Nick Koston a4278b8dec [ci] Run benchmarks when a component the Python import benchmark imports changes (#20763) 2026-10-14 10:35:33 -10:00
Panoplian 6d173c7371 [bq25186] Set i2c_id in the component tests (#20742) 2026-10-14 10:35:01 -10:00
esphome[bot] 1779b011c9 Bump aioesphomeapi from 46.10.0 to 46.11.0 (#20766)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-10-14 20:21:45 +00:00
PanoplianandJ. Nick Koston 3c4cf50cb6 [core] Point compile errors after a lambda at the right line (#20740)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-14 10:02:51 -10:00
J. Nick Koston e869d1f7ab [ci] Give the BK72xx clang-tidy environment the static allocation flag the real build has (#20764) 2026-10-14 09:56:09 -10:00
e1a996435d [ld2450] Add polygon zones evaluated on the device (#20154)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-14 19:29:16 +00:00
Jonathan Swoboda c5a624a1f2 [tests] Count OTA key probe retries on a fake clock (#20761) 2026-10-14 15:21:35 -04:00
Remco van Essen 15fb7f775e [tmc2209] Add chopper and PWM tuning actions (#20753) 2026-10-14 08:59:21 -10:00
J. Nick Koston 3fa72e61c6 [mqtt] Build the mqtt triggers with build_trigger_callback (#20433) 2026-10-14 08:55:39 -10:00
Kevin Ahrendt 163b09a473 [microphone] Speed up MicrophoneSource audio conversion (#20755) 2026-10-14 08:47:25 -10:00
J. Nick Koston 7afc2768f8 [esp8266] Check that every component's saved values fit together (#20686) 2026-10-14 08:45:51 -10:00
56f1a2bf46 [midea_portasplit] Add Midea PortaSplit climate component (#18033)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-14 08:45:21 -10:00
Panoplian fee47fe2f1 [pcf85063] Convert the weekday to and from the chip's 0-6 range (#20736) 2026-10-14 08:43:23 -10:00
Panoplian b994e081c3 [bm8563] Convert the weekday to and from the chip's 0-6 range (#20737) 2026-10-14 08:42:47 -10:00
Jonathan Swoboda a1f740b71b [lvgl] Keep LV_CONF_PATH one argument when the build path has a space (#20758) 2026-10-14 08:36:17 -10:00
Remco van EssenandClaude Opus 5.5 7f144365ba [fusb302b] Add USB PD sink protocol (#20632)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 08:35:29 -10:00
Marcus VoßandJ. Nick Koston 928459d16f [cse7766] Keep last power reading between measurements at low load (#20631)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-10-14 08:33:11 -10:00
Jonathan Swoboda 9163359445 [core] Analyze the ethernet component under ESP-IDF (#20745) 2026-10-14 08:31:39 -10:00
Jonathan Swoboda 67307f0eeb [ci] Select the feature-gated files the platform clang-tidy jobs were missing (#20743) 2026-10-14 08:31:06 -10:00
91e0edc11d [pn532] Fix NDEF parsing greater than 255 bytes (#18188)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-10-14 08:15:48 -10:00
Jonathan Swoboda 9fe75e262f [ci] Add a host clang-tidy environment and job (#20747) 2026-10-14 08:09:53 -10:00
Kevin Ahrendt 0132f722a3 [audio] Bump esp-audio-libs to v4.1.0 (#20754) 2026-10-14 13:24:36 -04:00
Jonathan Swoboda 7d7a78308d [ci] Test tinyusb_keyboard in isolation (#20749) 2026-10-14 10:05:02 -04:00
J. Nick Koston 9c568525b0 [core] Add CodSpeed benchmarks for importing entity components (#20648) 2026-10-14 09:08:41 -04:00
J. Nick Koston 10f42e3e7c [shelly_dimmer] Build the STM32 firmware update path in CI (#20677) 2026-10-14 09:03:34 -04:00
J. Nick Koston 25d4b88605 [nfc] Add unit tests for the URI record prefix codes (#20724) 2026-10-14 09:01:59 -04:00
J. Nick Koston d6abf35138 [sx126x][sx127x] Stop the watchdog reset loop when a packet is sent before setup (#20727) 2026-10-14 09:01:10 -04:00
J. Nick Koston 66ea99ce65 [seeed_mr60fda2] Compile without binary sensors or selects (#20726) 2026-10-14 09:00:08 -04:00
J. Nick Koston d9298cb7b9 [seeed_mr60bha2] Compile without sensors or binary sensors (#20729) 2026-10-14 08:59:27 -04:00
J. Nick Koston 34e1cf96d5 [bmi270] Build the component on ESP8266 in CI (#20731) 2026-10-14 08:58:56 -04:00
56cc03c4d4 [haier] Haier Select component added (#16148)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: Pavlo Dudnytskyi <Pavlo.Dudnytskyi@addsecure.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-13 23:27:18 -10:00
35b416c6c0 [web_server_idf] Keep active SSE sessions out of the LRU purge (#17383)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-13 22:19:06 -10:00
Petar Petrov 7f2c3ba3f5 [display] Let other components draw into a display (#20622) 2026-10-14 06:11:47 +00:00
Keith BurzinskiandClaude Opus 5.5 a97604d574 [esp32_ble] Rely on preferences for NVS init (#20708)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:10:51 -10:00
Petar Petrov 1146b77836 [socket] Add TcpClientLink::connecting() (#20722) 2026-10-13 19:19:17 -10:00
J. Nick Koston 1338902ac5 [heatpumpir] Link only the configured protocol classes (#20707) 2026-10-14 17:06:22 +13:00
60a1d70805 [core] Move deferred include processing to parse_yaml (#16344)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-13 17:46:54 -10:00
Ryan LudwigandCursor 887d4c3a83 [esp32_can] Add NO_ACK mode (#20706)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-13 17:36:15 -10:00
J. Nick Koston c1fa73470e [display] Walk the blit fallback in frame buffer order and resolve the bitness once (#20651) 2026-10-13 17:31:13 -10:00
J. Nick Koston e41d16ba7e [haier] Keep the alarm message table in flash (#20641) 2026-10-14 03:23:28 +00:00
J. Nick Koston 5171113c87 [core] Let PROGMEM_STRING_TABLE hold more than 255 bytes (#20646) 2026-10-13 17:17:48 -10:00
techdregsandJ. Nick Koston 5718e4b779 [tmp102] Add text sensor for diagnostics (#20629)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-10-13 17:06:56 -10:00
J. Nick Koston 40e12cd0d8 [image] Add CodSpeed benchmarks for image, runtime image and display block draws (#20649) 2026-10-13 17:01:47 -10:00
Brandon HarveyandJ. Nick Koston 07029d0077 [sen6x] Add measurement control and maintenance actions (#18783)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-14 15:47:31 +13:00
Christopher Reimer bb1119d83f [esp32_can] Support 20 kbit/s on ESP32 revision 2 or later (#20426) 2026-10-13 22:34:03 -04:00
7b591b26d6 [sy6970] Service the I2C watchdog so charge/LED settings persist (#19424)
Co-authored-by: Willem Oldemans <>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-13 16:19:58 -10:00
f45e6f0bf4 [midea] Add display_control and send the display toggle over UART without a transmitter (#18671)
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-13 16:03:18 -10:00
Keith BurzinskiandClaude Opus 5.5 4b8af08155 [network] Notify listeners when the active interface changes (#20684)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:57:59 -05:00
613973b432 Bump ruff from 0.16.10 to 0.17.0 (#20694)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-10-13 21:53:44 -04:00
dependabot[bot] 9ee4314bc2 Bump esptool from 5.4.0 to 5.5.0 (#20693)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-13 15:41:30 -10:00
fredkotzeandJ. Nick Koston 59f55dbe9e [epaper_spi] Add Waveshare 2.13in-G (JD79660) display models (#18141)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-13 15:40:28 -10:00
dependabot[bot] 8fce95454a Bump github/codeql-action/init from 4.38.2 to 4.38.3 (#20701)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-13 15:39:49 -10:00
dependabot[bot] 16134ee993 Bump astral-sh/setup-uv from 10.2.0 to 10.3.0 (#20704)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-13 15:39:38 -10:00
dependabot[bot] bc39d56bb4 Bump CodSpeedHQ/action from 5.4.0 to 5.4.2 (#20705)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-13 15:39:29 -10:00
dependabot[bot] c5522abc71 Bump github/codeql-action/analyze from 4.38.2 to 4.38.3 (#20699)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-13 21:39:11 -04:00
dependabot[bot] 7cb5906d2a Bump actions/upload-artifact from 7.0.1 to 7.0.2 (#20702)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-14 01:38:42 +00:00
dependabot[bot] d452dbce30 Bump actions/download-artifact from 8.0.1 to 8.0.2 (#20703)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-14 01:38:39 +00:00
dependabot[bot] 81e5b50087 Bump backports-zstd from 1.7.0 to 1.8.0 (#20695)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-13 15:38:35 -10:00
dependabot[bot] 426a4a2dce Bump filelock from 4.0.12 to 4.1.0 (#20696)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-13 15:38:26 -10:00
dependabot[bot]andesphome[bot] c95c17c4e7 Bump pyupgrade from 3.21.2 to 3.22.0 (#20698)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-10-13 15:38:17 -10:00
dependabot[bot] 576d3325fe Bump astral-sh/setup-uv from 10.2.0 to 10.3.0 in /.github/actions/restore-python (#20700)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-13 15:37:47 -10:00
dependabot[bot] c9cf0ad92e Bump platformdirs from 4.12.3 to 4.12.4 (#20697)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-13 21:37:36 -04:00
Felipe Guedes f505212e64 [epaper_spi] Add Waveshare 2.66" e-Paper Module (B) support (#20546) 2026-10-13 15:03:05 -10:00
J. Nick Koston 52a5e6a007 [rpi_dpi_rgb] Set removal of the deprecated component for 2027.5.0 (#20691) 2026-10-14 13:32:18 +13:00
J. Nick Koston 3b261d2cf0 [st7789v] Set removal of the deprecated component for 2027.5.0 (#20689) 2026-10-14 13:30:52 +13:00
J. Nick Koston 9238fcc727 [st7735] Set removal of the deprecated component for 2027.5.0 (#20688) 2026-10-14 13:30:21 +13:00
J. Nick Koston 96902cc122 [qspi_dbi] Set removal of the deprecated component for 2027.5.0 (#20690) 2026-10-14 13:29:52 +13:00
J. Nick Koston 95711d83d1 [ili9xxx] Set removal of the deprecated component for 2027.5.0 (#20687) 2026-10-14 13:29:29 +13:00
Panoplian 3cdcf0417a [lvgl] Make the list_outside_block tests work offline (#20676) 2026-10-13 13:31:08 -10:00
J. Nick Koston c6e90de262 [ci] Catch out-of-class member log tags and keep midea's in flash (#20674) 2026-10-14 12:21:24 +13:00
J. Nick Koston 92f6ab8367 [ci] Lint log tags in headers and core (#20668) 2026-10-14 12:21:24 +13:00
J. Nick Koston f61955baa2 [core] Declare the remaining log tags with ESPHOME_LOG_TAG (#20666) 2026-10-14 12:21:23 +13:00
J. Nick Koston 36e1d831d3 [core] Add a decimal fast path to parse_number<float> (#20639) 2026-10-14 12:18:35 +13:00
J. Nick Koston 63616bf642 [rtttl] Play a configured song from static storage without copying it (#19569) 2026-10-14 12:06:27 +13:00
d275926f65 [mdns] Advertise the connected interface in the network TXT record (#20673)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-10-13 17:55:22 -05:00
Andrej Friesen f265c46c21 [PCA9505] Add PCA9505/PCA9506 40-channel GPIO expander (#20667) 2026-10-13 12:50:43 -10:00
J. Nick Koston a70f565a22 Default the autotuner id to empty, wrap the sonoff_d1 fallback and align the deprecation wording 2026-10-12 17:31:19 -10:00
J. Nick Koston 1e45d1893c Merge commit 'c4c19a00e07874d2a7a4a98df588bad3c971d806' into esp8266-entity-names-components 2026-10-12 17:27:46 -10:00
J. Nick Koston c4c19a00e0 Move the entity domain and MQTT log conversions to the stacked PR 2026-10-12 17:27:40 -10:00
J. Nick Koston 0f8d26e1dd Convert components to the flash-safe name accessors and deprecate get_name() 2026-10-12 17:19:06 -10:00
J. Nick Koston 522395de11 Read entity names flash-safely in web_server, MQTT and prometheus 2026-10-12 17:19:03 -10:00
J. Nick Koston 39d63a3166 Keep the entity domain log and dump helpers on the flash-safe name accessors 2026-10-12 17:10:33 -10:00
J. Nick Koston 36cfe5c785 Move the component conversions and the get_name() deprecation to a stacked PR 2026-10-12 17:02:29 -10:00
J. Nick Koston d8dd8cf36c Keep the flash object id hash in entity_base and read it with progmem_read_byte 2026-10-12 16:57:20 -10:00
J. Nick Koston 12c35c1545 Compute the object id hash when an external caller passes 0 2026-10-12 16:53:49 -10:00
J. Nick Koston 0e8a3dfb6f Fold dev's ProgmemStringRef struct into the class and share the progmem short string body 2026-10-12 16:53:49 -10:00
J. Nick Koston 65b32731d4 Keep the ESP8266 short string encode on the shared progmem copy 2026-10-12 16:53:23 -10:00
J. Nick Koston 00f8e89f28 Merge remote-tracking branch 'origin/dev' into esp8266-entity-names-flash 2026-10-12 16:49:42 -10:00
J. Nick Koston 9b873e2179 Keep the RAM short string encode on memcpy and drop unused ProgmemStringRef helpers 2026-10-12 16:47:08 -10:00
J. Nick Koston dd495be861 Fold dev's ProgmemStringRef struct into the class 2026-10-12 16:28:37 -10:00
J. Nick Koston a7fdb143cd Merge branch 'dev' into api-action-strings-progmem 2026-10-12 16:02:23 -10:00
J. Nick Koston 5326d1dfe9 Merge remote-tracking branch 'origin/dev' into esp8266-entity-names-flash
# Conflicts:
#	esphome/components/web_server/web_server.cpp
2026-10-11 16:06:33 -10:00
J. Nick Koston ba9705e19b Construct the get_name() copy with placement new 2026-10-11 15:39:22 -10:00
J. Nick Koston 543a818307 Merge remote-tracking branch 'origin/dev' into esp8266-entity-names-flash
# Conflicts:
#	esphome/components/uart/button/uart_button.cpp
#	esphome/components/uart/switch/uart_switch.cpp
2026-10-11 15:36:07 -10:00
J. Nick Koston 229aa22006 Merge remote-tracking branch 'origin/dev' into api-action-strings-progmem
# Conflicts:
#	esphome/components/api/__init__.py
#	tests/component_tests/api/test_action_metadata.py
2026-10-11 15:26:13 -10:00
J. Nick Koston b31bedd464 Merge remote-tracking branch 'origin/dev' into HEAD
# Conflicts:
#	esphome/components/mqtt/mqtt_button.cpp
#	esphome/components/mqtt/mqtt_lock.cpp
#	esphome/components/mqtt/mqtt_switch.cpp
#	esphome/components/mqtt/mqtt_update.cpp
2026-10-09 18:28:52 -10:00
J. Nick Koston 491a2e58d5 Merge remote-tracking branch 'origin/dev' into HEAD 2026-10-09 18:28:25 -10:00
J. Nick Koston c8d331d44b Merge remote-tracking branch 'origin/dev' into esp8266-entity-names-flash
# Conflicts:
#	esphome/components/current_based/current_based_cover.cpp
2026-10-09 09:37:51 -10:00
J. Nick Koston 40ec3067b6 Merge remote-tracking branch 'origin/dev' into api-action-strings-progmem 2026-10-08 22:14:06 -10:00
J. Nick Koston 62f79e007a Merge remote-tracking branch 'origin/dev' into esp8266-entity-names-flash 2026-10-08 22:14:05 -10:00
J. Nick Koston 4497dad959 Keep the inline short string encode off ESP8266 2026-10-08 22:07:35 -10:00
J. Nick Koston b989221c71 Print prometheus names from flash, keep the inline short string encode off ESP8266 2026-10-08 22:07:33 -10:00
J. Nick Koston 096921cddb Keep get_name() working on ESP8266 with a RAM copy made on first use 2026-10-08 22:00:40 -10:00
J. Nick Koston e3d33df379 Share the outlined PROGMEM append for the progmem string dump 2026-10-08 21:44:09 -10:00
J. Nick Koston 47655129e1 Share the outlined PROGMEM append for the progmem string dump 2026-10-08 21:44:06 -10:00
J. Nick Koston c263852df9 Dump progmem strings straight into the dump buffer 2026-10-08 21:34:34 -10:00
J. Nick Koston 40460f3e01 Dump progmem strings straight into the dump buffer, assert the scratch define is gone 2026-10-08 21:34:31 -10:00
J. Nick Koston 8378c935d6 Drop the scratch define assertion from the action metadata test 2026-10-08 20:17:56 -10:00
J. Nick Koston 7c58d26d13 [api] Add encode_progmem_string for progmem string fields
Generated code passes the ProgmemStringRef instead of spelling out the cast.
2026-10-08 20:17:55 -10:00
J. Nick Koston 1fa844a5d2 [api] Add encode_progmem_string for progmem string fields
Generated code passes the ProgmemStringRef instead of spelling out the cast.
2026-10-08 20:17:55 -10:00
J. Nick Koston 7b5a1f9de9 [api] Encode action strings straight from flash
The service name, description and argument strings are progmem fields, so
list entities no longer copies them into a stack scratch buffer, and the
ESP8266 per action string budget goes away.
2026-10-08 20:10:41 -10:00
J. Nick Koston b63b74f236 [api] Allow the progmem option on string fields
Mirrors the helper from the entity names change, so either PR can merge first.
2026-10-08 20:10:41 -10:00
J. Nick Koston 88f7fc7454 Allow progmem on any string field and split the ProgmemStringRef tests
Long or unforced progmem strings encode through encode_progmem_bytes, which
API action strings need. The ProgmemStringRef tests move to their own file.
2026-10-08 20:04:18 -10:00
J. Nick Koston 140488723d Keep get_name() returning a reference off ESP8266
ProgmemStringRef now holds a StringRef, so get_name() and friendly_name_() can
keep returning const StringRef & on other platforms. External components that
return get_name() from a const StringRef & getter would otherwise return a
reference to a temporary. friendly_name_() is deprecated there, not removed.
2026-10-08 19:55:29 -10:00
J. Nick Koston b626711d50 Build the list entities benchmark with the ProgmemStringRef name field 2026-10-08 19:36:01 -10:00
pre-commit-ci-lite[bot] a6cb560e90 apply automatic formatting fixes 2026-10-09 04:36:31 +00:00
J. Nick Koston a721574706 Hash the RAM fallback name directly and share the short string encoder
Only unnamed entities hash at runtime, and their fallback name is in RAM, so
configure_entity_ hashes it before wrapping and named entities keep the codegen
hash; fnv1_hash_object_id_P is no longer needed. On ESP8266 the short string
encoder uses the outlined flash safe copy for RAM strings too.
2026-10-08 18:32:39 -10:00
J. Nick Koston 568934cc91 Drop the remaining entity name copies in mqtt, pid and prometheus
mqtt puts the name into the discovery JSON straight from flash, the pid
autotuner keeps the entity's log name instead of a std::string, and
prometheus prints names and ids without building a std::string per scrape.
2026-10-08 18:22:29 -10:00
J. Nick Koston 13057b7ae3 Type the API progmem name field as ProgmemStringRef
Progmem string fields must take the short encode path, the outlined encode
helper takes a ProgmemStringRef, and the hasher test checks the Python value.
2026-10-08 18:22:29 -10:00
J. Nick Koston b4289aee59 Add a flash safe fnv1_hash_object_id_P()
calc_object_id_() hashes the name in place instead of copying it into a
stack buffer first.
2026-10-08 18:11:36 -10:00
J. Nick Koston 93aecdd435 Deprecate Sprinkler::valve_name() and guard ProgmemStringRef::write_to
valve_name() returned a flash pointer on ESP8266; it now follows get_name():
static_assert there, deprecated elsewhere, with valve_log_name() for logs.
2026-10-08 17:58:37 -10:00
J. Nick Koston afac871938 [api] Encode entity names straight from flash
Extend the progmem proto option to string fields and mark the entity info
name field with it, so ListEntities copies the name once instead of through
a stack buffer.
2026-10-08 17:58:37 -10:00
J. Nick Koston 4c6e6b5447 Move flash copy and compare into ProgmemStringRef
ProgmemStringRef owns write_to() and equals() with the platform split, so the
EntityBase accessors are inline forwarders. Adds ESPHOME_ENTITY_NAME_MAX_LEN
mirroring NAME_MAX_LENGTH and tidies the codegen and tests.
2026-10-08 17:44:53 -10:00
J. Nick Koston b5c06efb2f Store entity names as ProgmemStringRef and deprecate its c_str()
ProgmemStringRef has no byte-reading operations, so new comparisons or copies
of name_ fail to compile. c_str() stays for external log-only users and is
deprecated until 2027.5.0; in-tree logs now use get_log_name().
2026-10-08 17:37:28 -10:00
J. Nick Koston 5cbdf26993 Tidy comments and always wrap entity names in ESPHOME_PSTR 2026-10-08 17:21:11 -10:00
J. Nick Koston 6f5108eb70 Apply review cleanups and deprecate get_name() off ESP8266
Inline get_name_to() off ESP8266, add write_name_to() and name_equals() so
web_server avoids copies, always emit ESPHOME_PSTR, and follow the get_icon()
pattern: get_name() is a static_assert stub on ESP8266 and ESPDEPRECATED
elsewhere until 2027.5.0.
2026-10-08 17:18:00 -10:00
J. Nick Koston 4ef86fe534 [core] Keep entity names in flash on ESP8266
On ESP8266 codegen emits entity names with PSTR and EntityBase::get_name()
is removed there. get_name_to() copies the name into a caller buffer and
get_log_name() returns it for %s log arguments; both exist on every platform.
2026-10-08 16:57:25 -10:00
553 changed files with 14256 additions and 3674 deletions
+1 -1
View File
@@ -32,7 +32,7 @@ runs:
# detects the activated venv via ``VIRTUAL_ENV`` so the venv layout
# downstream jobs rely on is preserved.
if: steps.cache-venv.outputs.cache-hit != 'true'
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
with:
enable-cache: true
# Pull request saves land in per-PR scopes nothing else can
+2 -2
View File
@@ -29,7 +29,7 @@ jobs:
- name: Set up uv
# ``--system`` (below) installs into the setup-python interpreter;
# no venv is created or restored by this workflow.
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
with:
enable-cache: true
# Pull-request-only workflow: a save could never be shared and
@@ -97,7 +97,7 @@ jobs:
run: git diff
- if: failure()
name: Archive artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: generated-proto-files
path: |
+2 -2
View File
@@ -128,7 +128,7 @@ jobs:
- name: Upload compile-test image artifact
if: matrix.os == 'ubuntu-24.04' && matrix.build_type == 'docker'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
# The tar is already compressed, so upload it as-is. archive: false
# skips the redundant zip and makes the file name the artifact name
@@ -210,7 +210,7 @@ jobs:
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Download image artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: compile-test-image.tar.zst
- name: Load image
+36 -22
View File
@@ -49,7 +49,7 @@ jobs:
# detects the activated venv via ``VIRTUAL_ENV`` so downstream jobs
# that ``. venv/bin/activate`` see an identical layout.
if: steps.cache-venv.outputs.cache-hit != 'true'
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
with:
enable-cache: true
# Pull request saves land in per-PR scopes nothing else can
@@ -81,8 +81,8 @@ jobs:
- name: Install apt packages (cached)
uses: awalsh128/cache-apt-pkgs-action@553a35bb8ebd9fcabcb1c9451aa4c98e1b4ca8a9 # v1.6.3
with:
packages: libsdl2-dev ccache
version: 1.1
packages: libsdl2-dev libmbedtls-dev ccache
version: 1.2
determine-jobs:
name: Determine which jobs to run
@@ -415,8 +415,8 @@ jobs:
timeout-minutes: 10
uses: awalsh128/cache-apt-pkgs-action@553a35bb8ebd9fcabcb1c9451aa4c98e1b4ca8a9 # v1.6.3
with:
packages: libsdl2-dev ccache
version: 1.1
packages: libsdl2-dev libmbedtls-dev ccache
version: 1.2
- name: Set up Python 3.13
id: python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
@@ -438,7 +438,7 @@ jobs:
- name: Set up uv
# Only needed on cache miss to populate the venv.
if: steps.cache-venv.outputs.cache-hit != 'true'
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
with:
enable-cache: true
# Pull request saves land in per-PR scopes nothing else can
@@ -477,7 +477,7 @@ jobs:
# Tests that compare rendered output write the image they actually got here, so a
# failure can be looked at without reproducing the whole build locally.
if: failure()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: integration-test-artifacts-${{ matrix.bucket.name }}
path: test_artifacts/
@@ -488,7 +488,7 @@ jobs:
# script/update_integration_test_durations.py; only full matrix dev
# runs produce usable data.
if: github.ref == 'refs/heads/dev' && needs.determine-jobs.outputs.integration-run-all == 'true'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: junit-integration-${{ strategy.job-index }}
path: junit-integration.xml
@@ -528,7 +528,7 @@ jobs:
script/check_import_time.py --check --har importtime.har
- name: Upload waterfall HAR
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: import-time-waterfall
path: importtime.har
@@ -626,7 +626,7 @@ jobs:
apt-get install -y libc6-dbg
- name: Run CodSpeed benchmarks
uses: CodSpeedHQ/action@c4fd08a3a159bd0cc208da1e0edf32b8c47d75e5 # v5.4.0
uses: CodSpeedHQ/action@f842b9a3ffe213dbb81768fd7f7eeb4dfcf1c369 # v5.4.2
with:
run: |
. venv/bin/activate
@@ -680,7 +680,7 @@ jobs:
include:
- id: clang-tidy
name: Run script/clang-tidy for ESP8266
options: --environment esp8266-arduino-tidy --grep USE_ESP8266
options: --environment esp8266-arduino-tidy --grep USE_ESP8266 --grep USE_SOCKET_IMPL_LWIP_TCP --grep USE_SHD_FIRMWARE_DATA
pio_cache_key: tidyesp8266
- id: clang-tidy
name: Run script/clang-tidy for ESP32 Arduino
@@ -693,12 +693,16 @@ jobs:
ignore_errors: false
- id: clang-tidy
name: Run script/clang-tidy for RP2
options: --environment rp2-tidy --grep USE_RP2
options: --environment rp2-tidy --grep USE_RP2 --grep USE_BLE_SCAN_RESPONSE_MERGER
pio_cache_key: tidyrp2
- id: clang-tidy
name: Run script/clang-tidy for host
options: --environment host-tidy --grep USE_HOST
pio_cache_key: tidyhost
- id: clang-tidy
name: Run script/clang-tidy for LibreTiny
environments: bk72xx-tidy ln882h-tidy rtl87xxb-tidy rtl87xxc-tidy
options: --grep USE_LIBRETINY --grep USE_BK72XX --grep USE_RTL87XX --grep USE_LN882X
options: --grep USE_LIBRETINY --grep USE_BK72XX --grep USE_RTL87XX --grep USE_LN882X --grep USE_LN882H_BLE --grep USE_SOCKET_IMPL_LWIP_SOCKETS
pio_cache_key: tidylibretiny
steps:
@@ -707,6 +711,16 @@ jobs:
with:
# Need history for HEAD~1 to work for checking changed files
fetch-depth: 2
- name: Install apt packages (cached)
if: matrix.pio_cache_key == 'tidyhost'
# libsdl2-dev is needed by the sdl component on the host, libmbedtls-dev
# by dsmr and dlms_meter. Packages and version must match seed-apt-cache
# exactly.
timeout-minutes: 10
uses: awalsh128/cache-apt-pkgs-action@553a35bb8ebd9fcabcb1c9451aa4c98e1b4ca8a9 # v1.6.3
with:
packages: libsdl2-dev libmbedtls-dev ccache
version: 1.2
- name: Restore Python
id: restore-python
@@ -989,14 +1003,14 @@ jobs:
- id: clang-tidy
name: Run script/clang-tidy for ESP32 S3
# yamllint disable-line rule:line-length
options: --environment esp32s3-idf-tidy --grep SOC_TEMP_SENSOR_SUPPORTED --grep USE_ESP32_VARIANT_ESP32S3 --grep USE_LOGGER_USB_CDC
options: --environment esp32s3-idf-tidy --grep SOC_TEMP_SENSOR_SUPPORTED --grep USE_ESP32_VARIANT_ESP32S3 --grep USE_LOGGER_USB_CDC --grep SOC_I2S_SUPPORTS_TDM
tidy_environment: esp32s3-idf-tidy
- id: clang-tidy
name: Run script/clang-tidy for ESP32 P4
# P4 has no native Wi-Fi/BLE; those run over the hosted co-processor,
# so their code paths differ -- lint them under the P4 build too.
# yamllint disable-line rule:line-length
options: --environment esp32p4-idf-tidy --grep USE_ESP32_VARIANT_ESP32P4 --grep USE_ESP32_HOSTED --grep USE_WIFI --grep USE_BLE
options: --environment esp32p4-idf-tidy --grep USE_ESP32_VARIANT_ESP32P4 --grep CONFIG_IDF_TARGET_ESP32P4 --grep USE_ESP32_HOSTED --grep USE_WIFI --grep USE_BLE
tidy_environment: esp32p4-idf-tidy
- id: clang-tidy
name: Run script/clang-tidy for ESP32 C6
@@ -1102,8 +1116,8 @@ jobs:
timeout-minutes: 10
uses: awalsh128/cache-apt-pkgs-action@553a35bb8ebd9fcabcb1c9451aa4c98e1b4ca8a9 # v1.6.3
with:
packages: libsdl2-dev ccache
version: 1.1
packages: libsdl2-dev libmbedtls-dev ccache
version: 1.2
- name: Check out code from GitHub
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
@@ -1448,7 +1462,7 @@ jobs:
# install step (order-of-magnitude faster on cold boots,
# with its own wheel cache). actions/setup-python still
# provides the interpreter.
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
with:
enable-cache: true
# Pull request saves land in per-PR scopes nothing else can
@@ -1647,7 +1661,7 @@ jobs:
fi
- name: Upload memory analysis JSON
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: memory-analysis-target
path: memory-analysis-target.json
@@ -1710,7 +1724,7 @@ jobs:
--platform "$platform"
- name: Upload memory analysis JSON
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: memory-analysis-pr
path: memory-analysis-pr.json
@@ -1740,13 +1754,13 @@ jobs:
python-version: ${{ env.DEFAULT_PYTHON }}
cache-key: ${{ needs.common.outputs.cache-key }}
- name: Download target analysis JSON
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: memory-analysis-target
path: ./memory-analysis
continue-on-error: true
- name: Download PR analysis JSON
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: memory-analysis-pr
path: ./memory-analysis
+2 -2
View File
@@ -56,7 +56,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
uses: github/codeql-action/init@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
@@ -84,6 +84,6 @@ jobs:
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
uses: github/codeql-action/analyze@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
with:
category: "/language:${{matrix.language}}"
+2 -2
View File
@@ -162,7 +162,7 @@ jobs:
# version: ${{ needs.init.outputs.tag }}
- name: Upload digests
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: digests-${{ matrix.platform.arch }}
path: /tmp/digests
@@ -195,7 +195,7 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Download digests
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
pattern: digests-*
path: /tmp/digests
+1 -1
View File
@@ -47,7 +47,7 @@ jobs:
# setup-python interpreter so subsequent ``prek`` /
# ``script/run-in-env.py`` steps find the deps without a
# ``uv run`` prefix.
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
with:
enable-cache: true
# Pin uv version so the action does not have to fetch the
+2 -2
View File
@@ -10,7 +10,7 @@ ci:
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.16.10
rev: v0.17.0
hooks:
# Run the linter.
- id: ruff
@@ -36,7 +36,7 @@ repos:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/asottile/pyupgrade
rev: v3.21.2
rev: v3.22.0
hooks:
- id: pyupgrade
args: [--py312-plus]
+5
View File
@@ -183,6 +183,7 @@ esphome/components/es7243e/* @kbx81
esphome/components/es8156/* @kbx81
esphome/components/es8311/* @kahrendt @kroimon
esphome/components/es8388/* @P4uLT
esphome/components/es9038q2m_katana/* @GioMez
esphome/components/esp32/* @esphome/core
esphome/components/esp32_ble/* @bdraco @jesserockz @Rapsssito
esphome/components/esp32_ble_client/* @bdraco @jesserockz
@@ -219,6 +220,7 @@ esphome/components/friedrich/* @rwrozelle
esphome/components/fs3000/* @kahrendt
esphome/components/ft5x06/* @clydebarrow
esphome/components/ft63x6/* @gpambrozio
esphome/components/fusb302b/* @remcom
esphome/components/gcja5/* @gcormier
esphome/components/gdk101/* @Szewcson
esphome/components/gl_r01_i2c/* @pkejval
@@ -240,6 +242,7 @@ esphome/components/gt911/* @clydebarrow @jesserockz
esphome/components/haier/* @paveldn
esphome/components/haier/binary_sensor/* @paveldn
esphome/components/haier/button/* @paveldn
esphome/components/haier/select/* @paveldn
esphome/components/haier/sensor/* @paveldn
esphome/components/haier/switch/* @paveldn
esphome/components/haier/text_sensor/* @paveldn
@@ -385,6 +388,7 @@ esphome/components/microphone/* @jesserockz @kahrendt
esphome/components/mics_4514/* @jesserockz
esphome/components/midea/* @dudanov
esphome/components/midea_ir/* @dudanov
esphome/components/midea_portasplit/* @Fexiven
esphome/components/mipi_dsi/* @clydebarrow
esphome/components/mipi_rgb/* @clydebarrow
esphome/components/mipi_spi/* @clydebarrow
@@ -439,6 +443,7 @@ esphome/components/ota/* @esphome/core
esphome/components/output/* @esphome/core
esphome/components/packet_transport/* @clydebarrow
esphome/components/pca6416a/* @Mat931
esphome/components/pca9505/* @ajfriesen @ssieb
esphome/components/pca9554/* @bdraco @clydebarrow @hwstar
esphome/components/pcf85063/* @brogon
esphome/components/pcf8563/* @KoenBreeman
@@ -10,7 +10,7 @@ void AbsoluteHumidityComponent::setup() {
this->temperature_ = state;
this->enable_loop();
});
ESP_LOGD(TAG, " Added callback for temperature '%s'", this->temperature_sensor_->get_name().c_str());
ESP_LOGD(TAG, " Added callback for temperature '%s'", LOG_STR_ARG(this->temperature_sensor_->get_log_name()));
// Get initial value
if (this->temperature_sensor_->has_state()) {
this->temperature_ = this->temperature_sensor_->get_state();
@@ -20,7 +20,7 @@ void AbsoluteHumidityComponent::setup() {
this->humidity_ = state;
this->enable_loop();
});
ESP_LOGD(TAG, " Added callback for relative humidity '%s'", this->humidity_sensor_->get_name().c_str());
ESP_LOGD(TAG, " Added callback for relative humidity '%s'", LOG_STR_ARG(this->humidity_sensor_->get_log_name()));
// Get initial value
if (this->humidity_sensor_->has_state()) {
this->humidity_ = this->humidity_sensor_->get_state();
@@ -49,7 +49,8 @@ void AbsoluteHumidityComponent::dump_config() {
"Sources\n"
" Temperature: '%s'\n"
" Relative Humidity: '%s'",
this->temperature_sensor_->get_name().c_str(), this->humidity_sensor_->get_name().c_str());
LOG_STR_ARG(this->temperature_sensor_->get_log_name()),
LOG_STR_ARG(this->humidity_sensor_->get_log_name()));
}
void AbsoluteHumidityComponent::loop() {
+1 -1
View File
@@ -66,7 +66,7 @@ template class Aggregator<uint32_t>;
void ADCSensor::update() {
float value_v = this->sample();
ESP_LOGV(TAG, "'%s': Voltage=%.4fV", this->get_name().c_str(), value_v);
ESP_LOGV(TAG, "'%s': Voltage=%.4fV", LOG_STR_ARG(this->get_log_name()), value_v);
this->publish_state(value_v);
}
@@ -13,7 +13,7 @@ float ADS1115Sensor::sample() {
void ADS1115Sensor::update() {
float v = this->sample();
if (!std::isnan(v)) {
ESP_LOGD(TAG, "'%s': Got Voltage=%fV", this->get_name().c_str(), v);
ESP_LOGD(TAG, "'%s': Got Voltage=%fV", LOG_STR_ARG(this->get_log_name()), v);
this->publish_state(v);
}
}
@@ -21,7 +21,7 @@ float ADS1118Sensor::sample() {
void ADS1118Sensor::update() {
float v = this->sample();
if (!std::isnan(v)) {
ESP_LOGD(TAG, "'%s': Got Voltage=%fV", this->get_name().c_str(), v);
ESP_LOGD(TAG, "'%s': Got Voltage=%fV", LOG_STR_ARG(this->get_log_name()), v);
this->publish_state(v);
}
}
@@ -31,7 +31,7 @@ void AlarmControlPanel::publish_state(AlarmControlPanelState state) {
this->last_update_ = millis();
if (state != this->current_state_) {
auto prev_state = this->current_state_;
ESP_LOGV(TAG, "'%s' >> %s (was %s)", this->get_name().c_str(),
ESP_LOGV(TAG, "'%s' >> %s (was %s)", LOG_STR_ARG(this->get_log_name()),
LOG_STR_ARG(alarm_control_panel_state_to_string(state)),
LOG_STR_ARG(alarm_control_panel_state_to_string(prev_state)));
this->current_state_ = state;
+16 -13
View File
@@ -30,9 +30,9 @@ void Am43Component::loop() {
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);
ESP_LOGI(TAG, "[%s] Logging into AM43", this->get_name().c_str());
ESP_LOGI(TAG, "[%s] Logging into AM43", LOG_STR_ARG(this->get_log_name()));
if (status) {
ESP_LOGW(TAG, "[%s] Error writing set_pin to device, error = %d", this->get_name().c_str(), status);
ESP_LOGW(TAG, "[%s] Error writing set_pin to device, error = %d", LOG_STR_ARG(this->get_log_name()), status);
} else {
this->logged_in_ = true;
}
@@ -50,7 +50,7 @@ CoverTraits Am43Component::get_traits() {
void Am43Component::control(const CoverCall &call) {
if (this->node_state != espbt::ClientState::ESTABLISHED) {
ESP_LOGW(TAG, "[%s] Cannot send cover control, not connected", this->get_name().c_str());
ESP_LOGW(TAG, "[%s] Cannot send cover control, not connected", LOG_STR_ARG(this->get_log_name()));
return;
}
if (call.get_stop()) {
@@ -59,7 +59,7 @@ void Am43Component::control(const CoverCall &call) {
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);
ESP_LOGW(TAG, "[%s] Error writing stop command to device, error = %d", LOG_STR_ARG(this->get_log_name()), status);
}
}
auto opt_pos = call.get_position();
@@ -73,7 +73,8 @@ void Am43Component::control(const CoverCall &call) {
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);
ESP_LOGW(TAG, "[%s] Error writing set_position command to device, error = %d", LOG_STR_ARG(this->get_log_name()),
status);
}
}
}
@@ -89,9 +90,9 @@ void Am43Component::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
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());
ESP_LOGE(TAG, "[%s] Detected a Tuya AM43 which is not supported, sorry.", LOG_STR_ARG(this->get_log_name()));
} else {
ESP_LOGE(TAG, "[%s] No control service found at device, not an AM43..?", this->get_name().c_str());
ESP_LOGE(TAG, "[%s] No control service found at device, not an AM43..?", LOG_STR_ARG(this->get_log_name()));
}
break;
}
@@ -100,7 +101,8 @@ void Am43Component::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
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);
ESP_LOGW(TAG, "[%s] esp_ble_gattc_register_for_notify failed, status=%d", LOG_STR_ARG(this->get_log_name()),
status);
}
break;
}
@@ -126,25 +128,26 @@ 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());
ESP_LOGI(TAG, "[%s] AM43 pin accepted.", LOG_STR_ARG(this->get_log_name()));
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);
ESP_LOGW(TAG, "[%s] Error writing set_position to device, error = %d", LOG_STR_ARG(this->get_log_name()),
status);
}
} else {
ESP_LOGW(TAG, "[%s] AM43 pin rejected!", this->get_name().c_str());
ESP_LOGW(TAG, "[%s] AM43 pin rejected!", LOG_STR_ARG(this->get_log_name()));
}
}
if (this->decoder_->has_set_position_response() && !this->decoder_->set_position_ok_) {
ESP_LOGW(TAG, "[%s] Got nack after sending set_position. Bad pin?", this->get_name().c_str());
ESP_LOGW(TAG, "[%s] Got nack after sending set_position. Bad pin?", LOG_STR_ARG(this->get_log_name()));
}
if (this->decoder_->has_set_state_response() && !this->decoder_->set_state_ok_) {
ESP_LOGW(TAG, "[%s] Got nack after sending set_state. Bad pin?", this->get_name().c_str());
ESP_LOGW(TAG, "[%s] Got nack after sending set_state. Bad pin?", LOG_STR_ARG(this->get_log_name()));
}
break;
}
+5 -3
View File
@@ -67,8 +67,9 @@ void Anova::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_
case ESP_GATTC_SEARCH_CMPL_EVT: {
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());
ESP_LOGW(TAG, "[%s] No control service found at device, not an Anova..?", LOG_STR_ARG(this->get_log_name()));
ESP_LOGW(TAG, "[%s] Note, this component does not currently support Anova Nano.",
LOG_STR_ARG(this->get_log_name()));
break;
}
this->char_handle_ = chr->handle;
@@ -76,7 +77,8 @@ void Anova::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_
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);
ESP_LOGW(TAG, "[%s] esp_ble_gattc_register_for_notify failed, status=%d", LOG_STR_ARG(this->get_log_name()),
status);
}
break;
}
-33
View File
@@ -251,9 +251,6 @@ def _validate_supports_response(value: Any) -> str:
return cv.enum(SUPPORTS_RESPONSE_OPTIONS, lower=True)(value)
# ESP8266 copies every string of an action into a stack buffer sized by codegen; keep it small
ESP8266_ACTION_STRINGS_MAX_TOTAL = 384
VARIABLE_SCHEMA = cv.Schema(
{
cv.Required(CONF_TYPE): cv.one_of(*SERVICE_ARG_NATIVE_TYPES, lower=True),
@@ -484,29 +481,6 @@ def _action_strings(conf: ConfigType, has_metadata: bool) -> list[str | None]:
return strings
def _action_strings_size(strings: list[str | None]) -> int:
"""Bytes needed to copy every string out of flash, each with its terminator."""
return sum(
len(string.encode("utf-8")) + 1 for string in strings if string is not None
)
def _validate_esp8266_action_strings(config: ConfigType) -> ConfigType:
if not CORE.is_esp8266:
return config
actions = config.get(CONF_ACTIONS, [])
has_metadata = _has_action_metadata(actions)
for conf in actions:
size = _action_strings_size(_action_strings(conf, has_metadata))
if size > ESP8266_ACTION_STRINGS_MAX_TOTAL:
raise cv.Invalid(
f"Action '{conf[CONF_ACTION]}' has {size} bytes of name, variable name, "
f"description and example text; ESP8266 allows at most "
f"{ESP8266_ACTION_STRINGS_MAX_TOTAL} bytes per action"
)
return config
def _validate_outgoing_host_ipv6(config: ConfigType) -> ConfigType:
"""An IPv6 host can never be parsed, so never dialed, without IPv6."""
if (
@@ -531,7 +505,6 @@ def _validate_wizard(config: ConfigType) -> ConfigType:
FINAL_VALIDATE_SCHEMA = cv.All(
_validate_esp8266_action_strings,
_validate_outgoing_host_ipv6,
_validate_wizard,
)
@@ -587,7 +560,6 @@ async def to_code(config: ConfigType) -> None:
if config[CONF_HOMEASSISTANT_STATES]:
cg.add_define("USE_API_HOMEASSISTANT_STATES")
scratch_size = 0
if actions:
# Metadata is compiled in for every action once any action declares it, because the
# string table layout is fixed by the define rather than per action
@@ -639,8 +611,6 @@ async def to_code(config: ConfigType) -> None:
func_args.append((native, name))
strings = _action_strings(conf, has_metadata)
table = _add_action_strings(index, strings)
if CORE.is_esp8266:
scratch_size = max(scratch_size, _action_strings_size(strings))
# Template args: supports_response mode, then user service arg types
templ = cg.TemplateArguments(supports_response, *service_template_args)
# Key is hashed here because the name is not readable at runtime on ESP8266
@@ -667,9 +637,6 @@ async def to_code(config: ConfigType) -> None:
cg.add(auto.add_action(unregister_action))
# Register all services at once - single allocation, no reallocations
cg.add(var.initialize_user_services(triggers))
if CORE.is_esp8266 and has_user_actions:
# Stack buffer that list-entities copies PROGMEM strings into, sized for the largest action
cg.add_define("API_USER_ACTION_STRINGS_SCRATCH_SIZE", max(scratch_size, 1))
if (wizard_config := config.get(wizard.CONF_WIZARD)) is not None:
await wizard.to_code(wizard_config)
+42 -36
View File
@@ -403,6 +403,9 @@ message WizardCapabilities {
message SendspinCapabilities {
// Bitmask of the Sendspin features this device supports
uint32 feature_flags = 1;
// The Sendspin client_id: base64url of the client's static public key, 43 characters.
// Empty until the Sendspin client has started once since boot.
string client_id = 2 [(max_data_length) = 43];
}
message DeviceCapabilitiesResponse {
@@ -552,7 +555,7 @@ message ListEntitiesBinarySensorResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string device_class = 5 [(max_data_length) = 47];
@@ -586,7 +589,7 @@ message ListEntitiesCoverResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
bool assumed_state = 5;
@@ -670,7 +673,7 @@ message ListEntitiesFanResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
bool supports_oscillation = 5;
@@ -758,7 +761,7 @@ message ListEntitiesLightResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
repeated ColorMode supported_color_modes = 12 [(container_pointer_no_template) = "light::ColorModeMask"];
@@ -863,7 +866,7 @@ message ListEntitiesSensorResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
@@ -904,7 +907,7 @@ message ListEntitiesSwitchResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
@@ -949,7 +952,7 @@ message ListEntitiesTextSensorResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
@@ -1026,8 +1029,8 @@ message SubscribeHomeassistantServicesRequest {
}
message HomeassistantServiceMap {
string key = 1;
string value = 2;
string key = 1 [(progmem) = true];
string value = 2 [(progmem) = true];
}
message HomeassistantActionRequest {
@@ -1036,7 +1039,7 @@ message HomeassistantActionRequest {
option (no_delay) = true;
option (ifdef) = "USE_API_HOMEASSISTANT_SERVICES";
string service = 1;
string service = 1 [(progmem) = true];
repeated HomeassistantServiceMap data = 2 [(fixed_vector) = true];
repeated HomeassistantServiceMap data_template = 3 [(fixed_vector) = true];
repeated HomeassistantServiceMap variables = 4 [(fixed_vector) = true];
@@ -1157,21 +1160,21 @@ enum SupportsResponseType {
}
message ListEntitiesServicesArgument {
option (ifdef) = "USE_API_USER_DEFINED_ACTIONS";
string name = 1;
string name = 1 [(progmem) = true];
ServiceArgType type = 2;
string description = 3 [(field_ifdef) = "USE_API_USER_DEFINED_ACTION_METADATA"];
string example = 4 [(field_ifdef) = "USE_API_USER_DEFINED_ACTION_METADATA"];
string description = 3 [(field_ifdef) = "USE_API_USER_DEFINED_ACTION_METADATA", (progmem) = true];
string example = 4 [(field_ifdef) = "USE_API_USER_DEFINED_ACTION_METADATA", (progmem) = true];
}
message ListEntitiesServicesResponse {
option (id) = 41;
option (source) = SOURCE_SERVER;
option (ifdef) = "USE_API_USER_DEFINED_ACTIONS";
string name = 1;
string name = 1 [(progmem) = true];
fixed32 key = 2 [(force) = true];
repeated ListEntitiesServicesArgument args = 3 [(fixed_vector) = true];
SupportsResponseType supports_response = 4;
string description = 5 [(field_ifdef) = "USE_API_USER_DEFINED_ACTION_METADATA"];
string description = 5 [(field_ifdef) = "USE_API_USER_DEFINED_ACTION_METADATA", (progmem) = true];
}
message ExecuteServiceArgument {
option (ifdef) = "USE_API_USER_DEFINED_ACTIONS";
@@ -1220,7 +1223,7 @@ message ListEntitiesCameraResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
bool disabled_by_default = 5;
string icon = 6 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
@@ -1312,7 +1315,7 @@ message ListEntitiesClimateResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
bool supports_current_temperature = 5; // Deprecated: use feature_flags
@@ -1427,7 +1430,7 @@ message ListEntitiesWaterHeaterResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
string icon = 4 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
bool disabled_by_default = 5;
EntityCategory entity_category = 6;
@@ -1507,7 +1510,7 @@ message ListEntitiesNumberResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
@@ -1556,7 +1559,7 @@ message ListEntitiesSelectResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
@@ -1600,7 +1603,7 @@ message ListEntitiesSirenResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
@@ -1665,7 +1668,7 @@ message ListEntitiesLockResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
@@ -1714,7 +1717,7 @@ message ListEntitiesButtonResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
@@ -1781,7 +1784,7 @@ message ListEntitiesMediaPlayerResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
@@ -2373,7 +2376,7 @@ message ListEntitiesAlarmControlPanelResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
bool disabled_by_default = 6;
@@ -2420,7 +2423,7 @@ message ListEntitiesTextResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
bool disabled_by_default = 6;
@@ -2468,7 +2471,7 @@ message ListEntitiesDateResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
@@ -2515,7 +2518,7 @@ message ListEntitiesTimeResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
@@ -2562,7 +2565,7 @@ message ListEntitiesEventResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
@@ -2593,7 +2596,7 @@ message ListEntitiesValveResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
@@ -2648,7 +2651,7 @@ message ListEntitiesDateTimeResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
@@ -2691,7 +2694,7 @@ message ListEntitiesUpdateResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
@@ -2791,7 +2794,7 @@ message ListEntitiesInfraredResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
string icon = 4 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
bool disabled_by_default = 5;
EntityCategory entity_category = 6;
@@ -2860,7 +2863,7 @@ message ListEntitiesRadioFrequencyResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
string icon = 4 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
bool disabled_by_default = 5;
EntityCategory entity_category = 6;
@@ -3043,12 +3046,15 @@ enum SerialProxyIdentityFlag {
// IDs below are empty
}
// The descriptor fields of a USB device as seen by the host stack
// The descriptor fields of a USB device as seen by the host stack, and the port's index
// among those a vendor driver exposes on the interface
message UsbDeviceDescriptor {
uint32 vendor_id = 1;
uint32 product_id = 2;
uint32 bcd_device = 3;
uint32 interface_number = 4; // bInterfaceNumber the host driver binds to
uint32 interface_number = 4; // bInterfaceNumber the port is bound through
uint32 interface_class = 5; // bInterfaceClass of that interface
uint32 port_number = 6;
}
// The identity of the device behind a port. Identifies one physical device among others of
+14 -1
View File
@@ -1,4 +1,7 @@
#include "api_connection.h"
#if defined(USE_LOGGER) && defined(USE_CRASH_HANDLER)
#include "esphome/components/logger/logger.h"
#endif
#ifdef USE_API
#include "api_connection_buffer.h" // for the APIServer-dependent APIConnection inlines
#ifdef USE_API_NOISE
@@ -451,6 +454,15 @@ bool APIConnection::send_disconnect_response_() {
DisconnectResponse resp;
return this->send_message(resp);
}
void APIConnection::on_subscribe_logs_request(const SubscribeLogsRequest &msg) {
this->flags_.log_subscription = msg.level;
if (msg.dump_config)
App.schedule_dump_config();
#if defined(USE_LOGGER) && defined(USE_CRASH_HANDLER)
logger::log_crash_to_client();
#endif
}
void APIConnection::on_disconnect_response() {
// Don't close socket here, let APIServer::loop() do it
// so getpeername() still works for the disconnect trigger
@@ -474,7 +486,7 @@ uint16_t APIConnection::fill_and_encode_entity_info(EntityBase *entity, InfoResp
msg.key = entity->get_object_id_hash();
if (entity->has_own_name()) {
msg.name = entity->get_name();
msg.name = entity->get_name_progmem();
}
// Set common EntityBase properties
@@ -2119,6 +2131,7 @@ bool APIConnection::send_device_capabilities_response_() {
#endif
#if defined(USE_SENDSPIN) && defined(USE_ESP_IDF)
resp.sendspin.feature_flags = sendspin_::global_sendspin_hub->get_feature_flags();
resp.sendspin.client_id = sendspin_::global_sendspin_hub->get_client_id();
#endif
return this->send_message(resp);
}
+1 -24
View File
@@ -15,15 +15,6 @@
#include "subscribe_state.h"
#include "esphome/core/application.h"
#include "esphome/core/component.h"
#ifdef USE_ESP32_CRASH_HANDLER
#include "esphome/components/esp32/crash_handler.h"
#endif
#ifdef USE_RP2_CRASH_HANDLER
#include "esphome/components/rp2/crash_handler.h"
#endif
#ifdef USE_ESP8266_CRASH_HANDLER
#include "esphome/components/esp8266/crash_handler.h"
#endif
#include "esphome/core/entity_base.h"
#include "esphome/core/log.h"
#include "esphome/core/string_ref.h"
@@ -298,21 +289,7 @@ class APIConnection final : public APIServerConnectionBase {
this->begin_iterator_(ActiveIterator::INITIAL_STATE);
}
}
void on_subscribe_logs_request(const SubscribeLogsRequest &msg) {
this->flags_.log_subscription = msg.level;
if (msg.dump_config)
App.schedule_dump_config();
#ifdef USE_ESP32_CRASH_HANDLER
esp32::crash_handler_log();
esp32::crash_handler_clear();
#endif
#ifdef USE_RP2_CRASH_HANDLER
rp2::crash_handler_log();
#endif
#ifdef USE_ESP8266_CRASH_HANDLER
esp8266::crash_handler_log();
#endif
}
void on_subscribe_logs_request(const SubscribeLogsRequest &msg);
#ifdef USE_API_HOMEASSISTANT_SERVICES
void on_subscribe_homeassistant_services_request() { this->flags_.service_call_subscription = true; }
#endif
+1 -1
View File
@@ -123,7 +123,7 @@ extend google.protobuf.FieldOptions {
// from an absent one (e.g. a UTC ParsedTimezone, which is all zeros).
optional bool track_presence = 50020 [default=false];
// progmem: The pointer_to_buffer bytes field points into flash (PROGMEM).
// progmem: The string field, or pointer_to_buffer bytes field, points into flash (PROGMEM).
// The generated encode and dump copy it with progmem_memcpy, as ESP8266
// cannot read flash with ordinary loads.
optional bool progmem = 50021 [default=false];
+40 -34
View File
@@ -310,12 +310,14 @@ uint32_t WizardCapabilities::calc_size_msg(const void *self) {
uint8_t *SendspinCapabilities::encode_msg(const void *self, uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM) {
const auto &msg = *static_cast<const SendspinCapabilities *>(self);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, msg.feature_flags);
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, msg.client_id);
return pos;
}
uint32_t SendspinCapabilities::calc_size_msg(const void *self) {
const auto &msg = *static_cast<const SendspinCapabilities *>(self);
uint32_t size = 0;
size += ProtoSize::calc_uint32(1, msg.feature_flags);
size += !msg.client_id.empty() ? 2 + msg.client_id.size() : 0;
return size;
}
#endif
@@ -401,7 +403,7 @@ uint8_t *ListEntitiesBinarySensorResponse::encode_msg(const void *self,
const auto &msg = *static_cast<const ListEntitiesBinarySensorResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.device_class);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.is_status_binary_sensor);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, msg.disabled_by_default);
@@ -459,7 +461,7 @@ uint8_t *ListEntitiesCoverResponse::encode_msg(const void *self, uint8_t *__rest
const auto &msg = *static_cast<const ListEntitiesCoverResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.assumed_state);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.supports_position);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, msg.supports_tilt);
@@ -558,7 +560,7 @@ uint8_t *ListEntitiesFanResponse::encode_msg(const void *self, uint8_t *__restri
const auto &msg = *static_cast<const ListEntitiesFanResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.supports_oscillation);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.supports_speed);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, msg.supports_direction);
@@ -678,7 +680,7 @@ uint8_t *ListEntitiesLightResponse::encode_msg(const void *self, uint8_t *__rest
const auto &msg = *static_cast<const ListEntitiesLightResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
for (const auto &it : *msg.supported_color_modes) {
pos = ProtoEncode::encode_uint32_force(pos PROTO_ENCODE_DEBUG_ARG, 12, static_cast<uint32_t>(it));
}
@@ -884,7 +886,7 @@ uint8_t *ListEntitiesSensorResponse::encode_msg(const void *self, uint8_t *__res
const auto &msg = *static_cast<const ListEntitiesSensorResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
@@ -954,7 +956,7 @@ uint8_t *ListEntitiesSwitchResponse::encode_msg(const void *self, uint8_t *__res
const auto &msg = *static_cast<const ListEntitiesSwitchResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
@@ -1030,7 +1032,7 @@ uint8_t *ListEntitiesTextSensorResponse::encode_msg(const void *self,
const auto &msg = *static_cast<const ListEntitiesTextSensorResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
@@ -1140,8 +1142,8 @@ uint32_t NoiseEncryptionSetKeyResponse::calc_size_msg(const void *self) {
#ifdef USE_API_HOMEASSISTANT_SERVICES
uint8_t *HomeassistantServiceMap::encode_msg(const void *self, uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM) {
const auto &msg = *static_cast<const HomeassistantServiceMap *>(self);
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, msg.key);
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, msg.value);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 1, msg.key);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 2, msg.value);
return pos;
}
uint32_t HomeassistantServiceMap::calc_size_msg(const void *self) {
@@ -1153,7 +1155,7 @@ uint32_t HomeassistantServiceMap::calc_size_msg(const void *self) {
}
uint8_t *HomeassistantActionRequest::encode_msg(const void *self, uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM) {
const auto &msg = *static_cast<const HomeassistantActionRequest *>(self);
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, msg.service);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 1, msg.service);
for (auto &it : msg.data) {
pos = ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, 2, it);
}
@@ -1324,13 +1326,13 @@ void GetTimeResponse::decode_field(void *self, uint32_t tag, const uint8_t *data
uint8_t *ListEntitiesServicesArgument::encode_msg(const void *self,
uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM) {
const auto &msg = *static_cast<const ListEntitiesServicesArgument *>(self);
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, msg.name);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 1, msg.name);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, static_cast<uint32_t>(msg.type));
#ifdef USE_API_USER_DEFINED_ACTION_METADATA
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, msg.description);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 3, msg.description);
#endif
#ifdef USE_API_USER_DEFINED_ACTION_METADATA
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, msg.example);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 4, msg.example);
#endif
return pos;
}
@@ -1350,14 +1352,14 @@ uint32_t ListEntitiesServicesArgument::calc_size_msg(const void *self) {
uint8_t *ListEntitiesServicesResponse::encode_msg(const void *self,
uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM) {
const auto &msg = *static_cast<const ListEntitiesServicesResponse *>(self);
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, msg.name);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 1, msg.name);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
for (auto &it : msg.args) {
pos = ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, 3, it);
}
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, static_cast<uint32_t>(msg.supports_response));
#ifdef USE_API_USER_DEFINED_ACTION_METADATA
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.description);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.description);
#endif
return pos;
}
@@ -1478,7 +1480,7 @@ uint8_t *ListEntitiesCameraResponse::encode_msg(const void *self, uint8_t *__res
const auto &msg = *static_cast<const ListEntitiesCameraResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.disabled_by_default);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.icon);
@@ -1544,7 +1546,7 @@ uint8_t *ListEntitiesClimateResponse::encode_msg(const void *self, uint8_t *__re
const auto &msg = *static_cast<const ListEntitiesClimateResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.supports_current_temperature);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.supports_two_point_target_temperature);
for (const auto &it : *msg.supported_modes) {
@@ -1781,7 +1783,7 @@ uint8_t *ListEntitiesWaterHeaterResponse::encode_msg(const void *self,
const auto &msg = *static_cast<const ListEntitiesWaterHeaterResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, msg.icon);
#endif
@@ -1908,7 +1910,7 @@ uint8_t *ListEntitiesNumberResponse::encode_msg(const void *self, uint8_t *__res
const auto &msg = *static_cast<const ListEntitiesNumberResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
@@ -1999,7 +2001,7 @@ uint8_t *ListEntitiesSelectResponse::encode_msg(const void *self, uint8_t *__res
const auto &msg = *static_cast<const ListEntitiesSelectResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
@@ -2078,7 +2080,7 @@ uint8_t *ListEntitiesSirenResponse::encode_msg(const void *self, uint8_t *__rest
const auto &msg = *static_cast<const ListEntitiesSirenResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
@@ -2180,7 +2182,7 @@ uint8_t *ListEntitiesLockResponse::encode_msg(const void *self, uint8_t *__restr
const auto &msg = *static_cast<const ListEntitiesLockResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
@@ -2263,7 +2265,7 @@ uint8_t *ListEntitiesButtonResponse::encode_msg(const void *self, uint8_t *__res
const auto &msg = *static_cast<const ListEntitiesButtonResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
@@ -2332,7 +2334,7 @@ uint8_t *ListEntitiesMediaPlayerResponse::encode_msg(const void *self,
const auto &msg = *static_cast<const ListEntitiesMediaPlayerResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
@@ -3178,7 +3180,7 @@ uint8_t *ListEntitiesAlarmControlPanelResponse::encode_msg(const void *self,
const auto &msg = *static_cast<const ListEntitiesAlarmControlPanelResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
@@ -3258,7 +3260,7 @@ uint8_t *ListEntitiesTextResponse::encode_msg(const void *self, uint8_t *__restr
const auto &msg = *static_cast<const ListEntitiesTextResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
@@ -3337,7 +3339,7 @@ uint8_t *ListEntitiesDateResponse::encode_msg(const void *self, uint8_t *__restr
const auto &msg = *static_cast<const ListEntitiesDateResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
@@ -3418,7 +3420,7 @@ uint8_t *ListEntitiesTimeResponse::encode_msg(const void *self, uint8_t *__restr
const auto &msg = *static_cast<const ListEntitiesTimeResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
@@ -3499,7 +3501,7 @@ uint8_t *ListEntitiesEventResponse::encode_msg(const void *self, uint8_t *__rest
const auto &msg = *static_cast<const ListEntitiesEventResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
@@ -3561,7 +3563,7 @@ uint8_t *ListEntitiesValveResponse::encode_msg(const void *self, uint8_t *__rest
const auto &msg = *static_cast<const ListEntitiesValveResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
@@ -3649,7 +3651,7 @@ uint8_t *ListEntitiesDateTimeResponse::encode_msg(const void *self,
const auto &msg = *static_cast<const ListEntitiesDateTimeResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
@@ -3722,7 +3724,7 @@ uint8_t *ListEntitiesUpdateResponse::encode_msg(const void *self, uint8_t *__res
const auto &msg = *static_cast<const ListEntitiesUpdateResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
@@ -3878,7 +3880,7 @@ uint8_t *ListEntitiesInfraredResponse::encode_msg(const void *self,
const auto &msg = *static_cast<const ListEntitiesInfraredResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, msg.icon);
#endif
@@ -3996,7 +3998,7 @@ uint8_t *ListEntitiesRadioFrequencyResponse::encode_msg(const void *self,
const auto &msg = *static_cast<const ListEntitiesRadioFrequencyResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, msg.icon);
#endif
@@ -4175,6 +4177,8 @@ uint8_t *UsbDeviceDescriptor::encode_msg(const void *self, uint8_t *__restrict__
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, msg.product_id);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, msg.bcd_device);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, msg.interface_number);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.interface_class);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.port_number);
return pos;
}
uint32_t UsbDeviceDescriptor::calc_size_msg(const void *self) {
@@ -4184,6 +4188,8 @@ uint32_t UsbDeviceDescriptor::calc_size_msg(const void *self) {
size += ProtoSize::calc_uint32(1, msg.product_id);
size += ProtoSize::calc_uint32(1, msg.bcd_device);
size += ProtoSize::calc_uint32(1, msg.interface_number);
size += ProtoSize::calc_uint32(1, msg.interface_class);
size += ProtoSize::calc_uint32(1, msg.port_number);
return size;
}
uint8_t *SerialProxyIdentity::encode_msg(const void *self, uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM) {
+12 -9
View File
@@ -399,7 +399,7 @@ class InfoResponseProtoMessage : public ProtoMessage {
public:
StringRef object_id{};
uint32_t key{0};
StringRef name{};
ProgmemStringRef name{};
bool disabled_by_default{false};
#ifdef USE_ENTITY_ICON
StringRef icon{nullptr, 0}; // null until set, encode only
@@ -750,6 +750,7 @@ class WizardCapabilities final : public ProtoMessage {
class SendspinCapabilities final : public ProtoMessage {
public:
uint32_t feature_flags{0};
StringRef client_id{nullptr, 0}; // null until set, encode only
static uint8_t *encode_msg(const void *self, uint8_t *pos PROTO_ENCODE_DEBUG_PARAM);
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
return encode_msg(this, buffer.get_pos() PROTO_ENCODE_DEBUG_ARG);
@@ -1388,8 +1389,8 @@ class NoiseEncryptionSetKeyResponse final : public ProtoMessage {
#ifdef USE_API_HOMEASSISTANT_SERVICES
class HomeassistantServiceMap final : public ProtoMessage {
public:
StringRef key{nullptr, 0}; // null until set, encode only
StringRef value{nullptr, 0}; // null until set, encode only
ProgmemStringRef key{};
ProgmemStringRef value{};
static uint8_t *encode_msg(const void *self, uint8_t *pos PROTO_ENCODE_DEBUG_PARAM);
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
return encode_msg(this, buffer.get_pos() PROTO_ENCODE_DEBUG_ARG);
@@ -1409,7 +1410,7 @@ class HomeassistantActionRequest final : public ProtoMessage {
#ifdef HAS_PROTO_MESSAGE_DUMP
const LogString *message_name() const override { return LOG_STR("homeassistant_action_request"); }
#endif
StringRef service{nullptr, 0}; // null until set, encode only
ProgmemStringRef service{};
FixedVector<HomeassistantServiceMap> data{};
FixedVector<HomeassistantServiceMap> data_template{};
FixedVector<HomeassistantServiceMap> variables{};
@@ -1576,13 +1577,13 @@ class GetTimeResponse final : public ProtoDecodableMessage {
#ifdef USE_API_USER_DEFINED_ACTIONS
class ListEntitiesServicesArgument final : public ProtoMessage {
public:
StringRef name{nullptr, 0}; // null until set, encode only
ProgmemStringRef name{};
enums::ServiceArgType type{};
#ifdef USE_API_USER_DEFINED_ACTION_METADATA
StringRef description{nullptr, 0}; // null until set, encode only
ProgmemStringRef description{};
#endif
#ifdef USE_API_USER_DEFINED_ACTION_METADATA
StringRef example{nullptr, 0}; // null until set, encode only
ProgmemStringRef example{};
#endif
static uint8_t *encode_msg(const void *self, uint8_t *pos PROTO_ENCODE_DEBUG_PARAM);
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
@@ -1603,12 +1604,12 @@ class ListEntitiesServicesResponse final : public ProtoMessage {
#ifdef HAS_PROTO_MESSAGE_DUMP
const LogString *message_name() const override { return LOG_STR("list_entities_services_response"); }
#endif
StringRef name{nullptr, 0}; // null until set, encode only
ProgmemStringRef name{};
uint32_t key{0};
FixedVector<ListEntitiesServicesArgument> args{};
enums::SupportsResponseType supports_response{};
#ifdef USE_API_USER_DEFINED_ACTION_METADATA
StringRef description{nullptr, 0}; // null until set, encode only
ProgmemStringRef description{};
#endif
static uint8_t *encode_msg(const void *self, uint8_t *pos PROTO_ENCODE_DEBUG_PARAM);
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
@@ -4083,6 +4084,8 @@ class UsbDeviceDescriptor final : public ProtoMessage {
uint32_t product_id{0};
uint32_t bcd_device{0};
uint32_t interface_number{0};
uint32_t interface_class{0};
uint32_t port_number{0};
static uint8_t *encode_msg(const void *self, uint8_t *pos PROTO_ENCODE_DEBUG_PARAM);
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
return encode_msg(this, buffer.get_pos() PROTO_ENCODE_DEBUG_ARG);
+47 -36
View File
@@ -12,8 +12,9 @@ namespace esphome::api {
#ifdef USE_ESP8266
// Out-of-line to avoid inlining strlen_P/memcpy_P at every call site
void DumpBuffer::append_p_esp8266(const char *str) {
size_t len = strlen_P(str);
void DumpBuffer::append_p_esp8266(const char *str) { this->append_p_esp8266(str, strlen_P(str)); }
void DumpBuffer::append_p_esp8266(const char *str, size_t len) {
size_t space = CAPACITY - 1 - pos_;
if (len > space)
len = space;
@@ -134,6 +135,13 @@ static void dump_progmem_bytes_field(DumpBuffer &out, const char *field_name, co
progmem_memcpy(data_buf, data, len);
dump_bytes_field(out, field_name, data_buf, len, indent);
}
// Helper for string fields in flash
static void dump_progmem_string_field(DumpBuffer &out, const char *field_name, const ProgmemStringRef &value,
int indent = 2) {
append_field_prefix(out, field_name, indent);
out.append("'").append_p(value.progmem_ptr(), value.size()).append("'\n");
}
#pragma GCC diagnostic pop
template<> const char *proto_enum_to_string<enums::DisconnectReason>(enums::DisconnectReason value) {
@@ -1119,6 +1127,7 @@ const char *WizardCapabilities::dump_to(DumpBuffer &out) const {
const char *SendspinCapabilities::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("SendspinCapabilities"));
dump_field(out, ESPHOME_PSTR("feature_flags"), this->feature_flags);
dump_field(out, ESPHOME_PSTR("client_id"), this->client_id);
return out.c_str();
}
#endif
@@ -1182,7 +1191,7 @@ const char *ListEntitiesBinarySensorResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesBinarySensorResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
dump_field(out, ESPHOME_PSTR("device_class"), this->device_class);
dump_field(out, ESPHOME_PSTR("is_status_binary_sensor"), this->is_status_binary_sensor);
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
@@ -1211,7 +1220,7 @@ const char *ListEntitiesCoverResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesCoverResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
dump_field(out, ESPHOME_PSTR("assumed_state"), this->assumed_state);
dump_field(out, ESPHOME_PSTR("supports_position"), this->supports_position);
dump_field(out, ESPHOME_PSTR("supports_tilt"), this->supports_tilt);
@@ -1257,7 +1266,7 @@ const char *ListEntitiesFanResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesFanResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
dump_field(out, ESPHOME_PSTR("supports_oscillation"), this->supports_oscillation);
dump_field(out, ESPHOME_PSTR("supports_speed"), this->supports_speed);
dump_field(out, ESPHOME_PSTR("supports_direction"), this->supports_direction);
@@ -1312,7 +1321,7 @@ const char *ListEntitiesLightResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesLightResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
for (const auto &it : *this->supported_color_modes) {
dump_field(out, ESPHOME_PSTR("supported_color_modes"), static_cast<enums::ColorMode>(it), 4);
}
@@ -1391,7 +1400,7 @@ const char *ListEntitiesSensorResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesSensorResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
@@ -1423,7 +1432,7 @@ const char *ListEntitiesSwitchResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesSwitchResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
@@ -1461,7 +1470,7 @@ const char *ListEntitiesTextSensorResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesTextSensorResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
@@ -1511,13 +1520,13 @@ const char *NoiseEncryptionSetKeyResponse::dump_to(DumpBuffer &out) const {
#ifdef USE_API_HOMEASSISTANT_SERVICES
const char *HomeassistantServiceMap::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("HomeassistantServiceMap"));
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("value"), this->value);
dump_progmem_string_field(out, ESPHOME_PSTR("key"), this->key);
dump_progmem_string_field(out, ESPHOME_PSTR("value"), this->value);
return out.c_str();
}
const char *HomeassistantActionRequest::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("HomeassistantActionRequest"));
dump_field(out, ESPHOME_PSTR("service"), this->service);
dump_progmem_string_field(out, ESPHOME_PSTR("service"), this->service);
for (const auto &it : this->data) {
out.append(4, ' ').append_p(ESPHOME_PSTR("data")).append(": ");
it.dump_to(out);
@@ -1612,19 +1621,19 @@ const char *GetTimeResponse::dump_to(DumpBuffer &out) const {
#ifdef USE_API_USER_DEFINED_ACTIONS
const char *ListEntitiesServicesArgument::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesServicesArgument"));
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
dump_field(out, ESPHOME_PSTR("type"), static_cast<enums::ServiceArgType>(this->type));
#ifdef USE_API_USER_DEFINED_ACTION_METADATA
dump_field(out, ESPHOME_PSTR("description"), this->description);
dump_progmem_string_field(out, ESPHOME_PSTR("description"), this->description);
#endif
#ifdef USE_API_USER_DEFINED_ACTION_METADATA
dump_field(out, ESPHOME_PSTR("example"), this->example);
dump_progmem_string_field(out, ESPHOME_PSTR("example"), this->example);
#endif
return out.c_str();
}
const char *ListEntitiesServicesResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesServicesResponse"));
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
dump_field(out, ESPHOME_PSTR("key"), this->key);
for (const auto &it : this->args) {
out.append(4, ' ').append_p(ESPHOME_PSTR("args")).append(": ");
@@ -1633,7 +1642,7 @@ const char *ListEntitiesServicesResponse::dump_to(DumpBuffer &out) const {
}
dump_field(out, ESPHOME_PSTR("supports_response"), static_cast<enums::SupportsResponseType>(this->supports_response));
#ifdef USE_API_USER_DEFINED_ACTION_METADATA
dump_field(out, ESPHOME_PSTR("description"), this->description);
dump_progmem_string_field(out, ESPHOME_PSTR("description"), this->description);
#endif
return out.c_str();
}
@@ -1692,7 +1701,7 @@ const char *ListEntitiesCameraResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesCameraResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
@@ -1725,7 +1734,7 @@ const char *ListEntitiesClimateResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesClimateResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
dump_field(out, ESPHOME_PSTR("supports_current_temperature"), this->supports_current_temperature);
dump_field(out, ESPHOME_PSTR("supports_two_point_target_temperature"), this->supports_two_point_target_temperature);
for (const auto &it : *this->supported_modes) {
@@ -1823,7 +1832,7 @@ const char *ListEntitiesWaterHeaterResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesWaterHeaterResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
@@ -1877,7 +1886,7 @@ const char *ListEntitiesNumberResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesNumberResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
@@ -1919,7 +1928,7 @@ const char *ListEntitiesSelectResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesSelectResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
@@ -1958,7 +1967,7 @@ const char *ListEntitiesSirenResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesSirenResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
@@ -2005,7 +2014,7 @@ const char *ListEntitiesLockResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesLockResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
@@ -2046,7 +2055,7 @@ const char *ListEntitiesButtonResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesButtonResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
@@ -2081,7 +2090,7 @@ const char *ListEntitiesMediaPlayerResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesMediaPlayerResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
@@ -2471,7 +2480,7 @@ const char *ListEntitiesAlarmControlPanelResponse::dump_to(DumpBuffer &out) cons
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesAlarmControlPanelResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
@@ -2510,7 +2519,7 @@ const char *ListEntitiesTextResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesTextResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
@@ -2550,7 +2559,7 @@ const char *ListEntitiesDateResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesDateResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
@@ -2590,7 +2599,7 @@ const char *ListEntitiesTimeResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesTimeResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
@@ -2630,7 +2639,7 @@ const char *ListEntitiesEventResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesEventResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
@@ -2660,7 +2669,7 @@ const char *ListEntitiesValveResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesValveResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
@@ -2702,7 +2711,7 @@ const char *ListEntitiesDateTimeResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesDateTimeResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
@@ -2738,7 +2747,7 @@ const char *ListEntitiesUpdateResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesUpdateResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
@@ -2801,7 +2810,7 @@ const char *ListEntitiesInfraredResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesInfraredResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
@@ -2859,7 +2868,7 @@ const char *ListEntitiesRadioFrequencyResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesRadioFrequencyResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
@@ -2942,6 +2951,8 @@ const char *UsbDeviceDescriptor::dump_to(DumpBuffer &out) const {
dump_field(out, ESPHOME_PSTR("product_id"), this->product_id);
dump_field(out, ESPHOME_PSTR("bcd_device"), this->bcd_device);
dump_field(out, ESPHOME_PSTR("interface_number"), this->interface_number);
dump_field(out, ESPHOME_PSTR("interface_class"), this->interface_class);
dump_field(out, ESPHOME_PSTR("port_number"), this->port_number);
return out.c_str();
}
const char *SerialProxyIdentity::dump_to(DumpBuffer &out) const {
+1 -1
View File
@@ -547,7 +547,7 @@ void APIServer::send_homeassistant_action(const HomeassistantActionRequest &call
// arrive before the subscription and are lost - warn instead of failing silently.
ESP_LOGW(TAG, "Home Assistant %s '%.*s' dropped; %s",
call.is_event ? LOG_STR_LITERAL("event") : LOG_STR_LITERAL("action"),
static_cast<int>(call.service.size()), call.service.empty() ? "" : call.service.c_str(),
static_cast<int>(call.service.size()), call.service.empty() ? "" : call.service.progmem_ptr(),
this->is_connected() ? LOG_STR_LITERAL("client has not subscribed to actions (yet)")
: LOG_STR_LITERAL("no client connected"));
}
+8 -8
View File
@@ -247,7 +247,7 @@ class CustomAPIDevice {
*/
void call_homeassistant_service(const std::string &service_name) {
HomeassistantActionRequest resp;
resp.service = StringRef(service_name);
resp.service = ProgmemStringRef(StringRef(service_name));
global_api_server->send_homeassistant_action(resp);
}
@@ -267,12 +267,12 @@ class CustomAPIDevice {
*/
void call_homeassistant_service(const std::string &service_name, const std::map<std::string, std::string> &data) {
HomeassistantActionRequest resp;
resp.service = StringRef(service_name);
resp.service = ProgmemStringRef(StringRef(service_name));
resp.data.init(data.size());
for (auto &it : data) {
auto &kv = resp.data.emplace_back();
kv.key = StringRef(it.first);
kv.value = StringRef(it.second); // data map lives until send completes
kv.key = ProgmemStringRef(StringRef(it.first));
kv.value = ProgmemStringRef(StringRef(it.second)); // data map lives until send completes
}
global_api_server->send_homeassistant_action(resp);
}
@@ -289,7 +289,7 @@ class CustomAPIDevice {
*/
void fire_homeassistant_event(const std::string &event_name) {
HomeassistantActionRequest resp;
resp.service = StringRef(event_name);
resp.service = ProgmemStringRef(StringRef(event_name));
resp.is_event = true;
global_api_server->send_homeassistant_action(resp);
}
@@ -309,13 +309,13 @@ class CustomAPIDevice {
*/
void fire_homeassistant_event(const std::string &service_name, const std::map<std::string, std::string> &data) {
HomeassistantActionRequest resp;
resp.service = StringRef(service_name);
resp.service = ProgmemStringRef(StringRef(service_name));
resp.is_event = true;
resp.data.init(data.size());
for (auto &it : data) {
auto &kv = resp.data.emplace_back();
kv.key = StringRef(it.first);
kv.value = StringRef(it.second); // data map lives until send completes
kv.key = ProgmemStringRef(StringRef(it.first));
kv.value = ProgmemStringRef(StringRef(it.second)); // data map lives until send completes
}
global_api_server->send_homeassistant_action(resp);
}
+4 -28
View File
@@ -116,42 +116,18 @@ template<typename... Ts> class HomeAssistantServiceCallAction final : public Act
const Field *fields = this->fields_;
const size_t total = 1 + this->data_count_ + this->data_template_count_ + this->variables_count_;
// Lambda results, and on ESP8266 the RAM copies of the flash strings, must live until the send
// Lambda results must live until the send; the constant strings are encoded from flash where they are
size_t lambda_count = 0;
#ifdef USE_ESP8266
size_t flash_len = 0;
#endif
for (size_t i = 0; i < total; i++) {
for (size_t i = 0; i < total; i++)
lambda_count += fields[i].fn != nullptr;
#ifdef USE_ESP8266
if (fields[i].fn == nullptr)
flash_len += ESPHOME_strlen_P(fields[i].value);
if (fields[i].key != nullptr)
flash_len += ESPHOME_strlen_P(fields[i].key);
#endif
}
FixedVector<std::string> results;
results.init(lambda_count);
#ifdef USE_ESP8266
SmallBufferWithHeapFallback<128, char> flash_copy(flash_len);
char *cursor = flash_copy.get();
#endif
auto string_ref = [&](const char *str) {
#ifdef USE_ESP8266
size_t len = ESPHOME_strlen_P(str);
memcpy_P(cursor, str, len);
StringRef ref(cursor, len);
cursor += len;
return ref;
#else
return StringRef(str);
#endif
};
auto string_ref = [](const char *str) { return ProgmemStringRef(str, ESPHOME_strlen_P(str)); };
auto value_ref = [&](const Field &field) {
if (field.fn == nullptr)
return string_ref(field.value);
results.push_back(field.fn(x...));
return StringRef(results.back());
return ProgmemStringRef(StringRef(results.back()));
};
auto fill = [&](FixedVector<HomeassistantServiceMap> &dest, uint8_t count) {
dest.init(count);
+1 -2
View File
@@ -99,8 +99,7 @@ ListEntitiesIterator::ListEntitiesIterator(APIConnection *client) : client_(clie
static constexpr uint8_t SERVICE_YIELD_INTERVAL = 3;
bool ListEntitiesIterator::on_service(UserServiceDescriptor *service) {
UserActionScratch scratch;
auto resp = service->encode_list_service_response(scratch);
auto resp = service->encode_list_service_response();
if (!this->client_->send_message(resp))
return false;
// at_ is this service's index
+39
View File
@@ -409,6 +409,10 @@ class ProtoEncode {
/// Tag must be a single-byte varint (< 128). Always encodes (no zero check).
[[nodiscard]] static inline uint8_t *encode_short_string_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM,
uint8_t tag, const StringRef &ref) {
#ifdef USE_ESP8266
// memcpy_P reads RAM too, and sharing the progmem copy is smaller than an inline memcpy
return encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, tag, ProgmemStringRef(ref));
#else
#ifdef ESPHOME_DEBUG_API
assert(ref.size() < 128 && "encode_short_string_force: string exceeds max_data_length < 128");
#endif
@@ -417,6 +421,19 @@ class ProtoEncode {
pos[1] = static_cast<uint8_t>(ref.size());
std::memcpy(pos + 2, ref.c_str(), ref.size());
return pos + 2 + ref.size();
#endif
}
/// encode_short_string_force for a string that may be in flash (PROGMEM).
[[nodiscard]] static inline uint8_t *encode_short_progmem_string_force(
uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, uint8_t tag, const ProgmemStringRef &ref) {
#ifdef ESPHOME_DEBUG_API
assert(ref.size() < 128 && "encode_short_progmem_string_force: string exceeds max_data_length < 128");
#endif
PROTO_ENCODE_CHECK_BOUNDS(pos, 2 + ref.size());
pos[0] = tag;
pos[1] = static_cast<uint8_t>(ref.size());
progmem_memcpy(pos + 2, ref.progmem_ptr(), ref.size());
return pos + 2 + ref.size();
}
/// Write a precomputed tag byte + 32-bit value. Outlined on embedded: one copy beats inline stores per field.
[[nodiscard]] static PROTO_OUTLINE_FOR_SIZE uint8_t *write_tag_and_fixed32(
@@ -481,6 +498,17 @@ class ProtoEncode {
progmem_memcpy(pos, data, len);
return pos + len;
}
/// encode_progmem_bytes for a string field that may be in flash.
[[nodiscard]] static inline uint8_t *encode_progmem_string(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM,
uint32_t field_id, const ProgmemStringRef &ref) {
return encode_progmem_bytes(pos PROTO_ENCODE_DEBUG_ARG, field_id,
reinterpret_cast<const uint8_t *>(ref.progmem_ptr()), ref.size());
}
[[nodiscard]] static inline uint8_t *encode_progmem_string_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM,
uint32_t field_id, const ProgmemStringRef &ref) {
return encode_progmem_bytes_force(pos PROTO_ENCODE_DEBUG_ARG, field_id,
reinterpret_cast<const uint8_t *>(ref.progmem_ptr()), ref.size());
}
[[nodiscard]] static inline uint8_t *encode_uint32_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM,
uint32_t field_id, uint32_t value) {
pos = encode_field_raw(pos PROTO_ENCODE_DEBUG_ARG, field_id, 0);
@@ -680,9 +708,20 @@ class DumpBuffer {
return *this;
}
/// Append len bytes of a PROGMEM string
DumpBuffer &append_p(const char *str, size_t len) {
#ifdef USE_ESP8266
append_p_esp8266(str, len);
#else
append_impl_(str, len);
#endif
return *this;
}
#ifdef USE_ESP8266
/// Out-of-line ESP8266 PROGMEM append to avoid inlining strlen_P/memcpy_P at every call site
void append_p_esp8266(const char *str);
void append_p_esp8266(const char *str, size_t len);
#endif
const char *c_str() const { return buf_; }
+9 -20
View File
@@ -1,47 +1,36 @@
#include "user_services.h"
#include "esphome/core/hal.h"
#include "esphome/core/log.h"
#include "esphome/core/progmem.h"
#include "esphome/core/string_ref.h"
namespace esphome::api {
StringRef UserServiceStatic::str_(size_t idx, std::span<char> &scratch) const {
ProgmemStringRef UserServiceStatic::str_(size_t idx) const {
const char *s = progmem_read_ptr(&this->strings_[idx]);
if (s == nullptr)
return {};
#ifdef USE_ESP8266
// Codegen sizes the scratch buffer for the largest service; the bound only guards other callers
if (scratch.empty())
return {};
size_t len = strnlen_P(s, scratch.size() - 1);
progmem_memcpy(scratch.data(), s, len);
scratch[len] = '\0';
StringRef ref(scratch.data(), len);
scratch = scratch.subspan(len + 1);
return ref;
#else
return StringRef(s);
#endif
return ProgmemStringRef(s, ESPHOME_strlen_P(s));
}
ListEntitiesServicesResponse UserServiceStatic::encode_list_service_response_(
std::span<const enums::ServiceArgType> arg_types, std::span<char> scratch) const {
std::span<const enums::ServiceArgType> arg_types) const {
ListEntitiesServicesResponse msg;
msg.name = this->str_(0, scratch);
msg.name = this->str_(0);
msg.key = this->key_;
msg.supports_response = this->supports_response_;
#ifdef USE_API_USER_DEFINED_ACTION_METADATA
msg.description = this->str_(1, scratch);
msg.description = this->str_(1);
#endif
msg.args.init(arg_types.size());
for (size_t i = 0; i < arg_types.size(); i++) {
size_t base = USER_ACTION_HEADER_STRINGS + i * USER_ACTION_ARG_STRINGS;
auto &arg = msg.args.emplace_back();
arg.type = arg_types[i];
arg.name = this->str_(base, scratch);
arg.name = this->str_(base);
#ifdef USE_API_USER_DEFINED_ACTION_METADATA
arg.description = this->str_(base + 1, scratch);
arg.example = this->str_(base + 2, scratch);
arg.description = this->str_(base + 1);
arg.example = this->str_(base + 2);
#endif
}
return msg;
+10 -21
View File
@@ -20,9 +20,8 @@ class APIServer;
class UserServiceDescriptor {
public:
/// Build the list-entities message. On ESP8266 the strings live in PROGMEM and are copied into
/// `scratch`, so the returned message is only valid while `scratch` is; other platforms ignore it.
virtual ListEntitiesServicesResponse encode_list_service_response(std::span<char> scratch) = 0;
/// Build the list-entities message; its strings may point into flash (PROGMEM).
virtual ListEntitiesServicesResponse encode_list_service_response() = 0;
virtual bool execute_service(const ExecuteServiceRequest &req) = 0;
#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES
@@ -37,13 +36,6 @@ template<typename T> T get_execute_arg_value(const ExecuteServiceArgument &arg);
template<typename T> enums::ServiceArgType to_service_arg_type();
// Scratch buffer list-entities hands to encode_list_service_response(); only ESP8266 copies into it
#ifdef USE_ESP8266
using UserActionScratch = std::array<char, API_USER_ACTION_STRINGS_SCRATCH_SIZE>;
#else
using UserActionScratch = std::array<char, 0>;
#endif
// Non-template base for YAML-defined services so the list-entities encoder is compiled once.
// All strings live in one PROGMEM pointer table emitted by codegen (see _action_strings in
// __init__.py), so each service costs a single pointer of RAM. Layout: the action name, then
@@ -63,12 +55,9 @@ class UserServiceStatic : public UserServiceDescriptor {
: strings_(strings), key_(key), supports_response_(supports_response) {}
protected:
ListEntitiesServicesResponse encode_list_service_response_(std::span<const enums::ServiceArgType> arg_types,
std::span<char> scratch) const;
/// Reference table entry `idx`; nullptr gives an empty StringRef.
/// On ESP8266 the bytes are copied out of PROGMEM into `scratch` with a terminator, and the span
/// is advanced past the copy.
StringRef str_(size_t idx, std::span<char> &scratch) const;
ListEntitiesServicesResponse encode_list_service_response_(std::span<const enums::ServiceArgType> arg_types) const;
/// Table entry `idx` as it sits in flash; nullptr gives an empty string.
ProgmemStringRef str_(size_t idx) const;
const char *const *strings_; // PROGMEM pointer table, read with progmem_read_ptr()
uint32_t key_;
@@ -79,9 +68,9 @@ template<typename... Ts> class UserServiceBase : public UserServiceStatic {
public:
using UserServiceStatic::UserServiceStatic;
ListEntitiesServicesResponse encode_list_service_response(std::span<char> scratch) override {
ListEntitiesServicesResponse encode_list_service_response() override {
std::array<enums::ServiceArgType, sizeof...(Ts)> arg_types = {to_service_arg_type<Ts>()...};
return this->encode_list_service_response_(arg_types, scratch);
return this->encode_list_service_response_(arg_types);
}
bool execute_service(const ExecuteServiceRequest &req) override {
@@ -125,9 +114,9 @@ template<typename... Ts> class UserServiceDynamic : public UserServiceDescriptor
this->key_ = fnv1_hash(this->name_.c_str());
}
ListEntitiesServicesResponse encode_list_service_response(std::span<char> /*scratch*/) override {
ListEntitiesServicesResponse encode_list_service_response() override {
ListEntitiesServicesResponse msg;
msg.name = StringRef(this->name_);
msg.name = ProgmemStringRef(StringRef(this->name_));
msg.key = this->key_;
msg.supports_response = enums::SUPPORTS_RESPONSE_NONE; // Dynamic services don't support responses yet
std::array<enums::ServiceArgType, sizeof...(Ts)> arg_types = {to_service_arg_type<Ts>()...};
@@ -135,7 +124,7 @@ template<typename... Ts> class UserServiceDynamic : public UserServiceDescriptor
for (size_t i = 0; i < sizeof...(Ts); i++) {
auto &arg = msg.args.emplace_back();
arg.type = arg_types[i];
arg.name = StringRef(this->arg_names_[i]);
arg.name = ProgmemStringRef(StringRef(this->arg_names_[i]));
}
return msg;
}
+2 -2
View File
@@ -30,10 +30,10 @@ void AQISensor::dump_config() {
ESP_LOGCONFIG(TAG, " Extended Range: %s",
this->extended_range_ ? LOG_STR_LITERAL("enabled") : LOG_STR_LITERAL("disabled"));
if (this->pm_2_5_sensor_ != nullptr) {
ESP_LOGCONFIG(TAG, " PM2.5 Sensor: '%s'", this->pm_2_5_sensor_->get_name().c_str());
ESP_LOGCONFIG(TAG, " PM2.5 Sensor: '%s'", LOG_STR_ARG(this->pm_2_5_sensor_->get_log_name()));
}
if (this->pm_10_0_sensor_ != nullptr) {
ESP_LOGCONFIG(TAG, " PM10 Sensor: '%s'", this->pm_10_0_sensor_->get_name().c_str());
ESP_LOGCONFIG(TAG, " PM10 Sensor: '%s'", LOG_STR_ARG(this->pm_10_0_sensor_->get_log_name()));
}
LOG_SENSOR(" ", "AQI", this);
}
+1 -1
View File
@@ -1289,7 +1289,7 @@ void ATM90E32Component::check_phase_status() {
if (!status.empty()) {
status.pop_back(); // remove space
status.pop_back(); // remove semicolon
ESP_LOGW(TAG, "%s: %s", sensor->get_name().c_str(), status.c_str());
ESP_LOGW(TAG, "%s: %s", LOG_STR_ARG(sensor->get_log_name()), status.c_str());
sensor->publish_state(status);
} else {
sensor->publish_state("Okay");
@@ -8,11 +8,12 @@ ESPHOME_LOG_TAG(TAG, "atm90e32.button");
void ATM90E32GainCalibrationButton::press_action() {
if (this->parent_ == nullptr) {
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Gain Calibration button [%s]", this->get_name().c_str());
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Gain Calibration button [%s]",
LOG_STR_ARG(this->get_log_name()));
return;
}
ESP_LOGI(TAG, "%s", this->get_name().c_str());
ESP_LOGI(TAG, "%s", LOG_STR_ARG(this->get_log_name()));
ESP_LOGI(TAG,
"[CALIBRATION] Use gain_ct: & gain_voltage: under each phase_x: in your config file to save these values");
this->parent_->run_gain_calibrations();
@@ -20,21 +21,22 @@ void ATM90E32GainCalibrationButton::press_action() {
void ATM90E32ClearGainCalibrationButton::press_action() {
if (this->parent_ == nullptr) {
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Clear Gain button [%s]", this->get_name().c_str());
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Clear Gain button [%s]", LOG_STR_ARG(this->get_log_name()));
return;
}
ESP_LOGI(TAG, "%s", this->get_name().c_str());
ESP_LOGI(TAG, "%s", LOG_STR_ARG(this->get_log_name()));
this->parent_->clear_gain_calibrations();
}
void ATM90E32OffsetCalibrationButton::press_action() {
if (this->parent_ == nullptr) {
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Offset Calibration button [%s]", this->get_name().c_str());
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Offset Calibration button [%s]",
LOG_STR_ARG(this->get_log_name()));
return;
}
ESP_LOGI(TAG, "%s", this->get_name().c_str());
ESP_LOGI(TAG, "%s", LOG_STR_ARG(this->get_log_name()));
ESP_LOGI(TAG, "[CALIBRATION] **NOTE: CTs and ACVs must be 0 during this process. USB power only**");
ESP_LOGI(TAG, "[CALIBRATION] Use offset_voltage: & offset_current: under each phase_x: in your config file to save "
"these values");
@@ -43,21 +45,22 @@ void ATM90E32OffsetCalibrationButton::press_action() {
void ATM90E32ClearOffsetCalibrationButton::press_action() {
if (this->parent_ == nullptr) {
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Clear Offset button [%s]", this->get_name().c_str());
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Clear Offset button [%s]", LOG_STR_ARG(this->get_log_name()));
return;
}
ESP_LOGI(TAG, "%s", this->get_name().c_str());
ESP_LOGI(TAG, "%s", LOG_STR_ARG(this->get_log_name()));
this->parent_->clear_offset_calibrations();
}
void ATM90E32PowerOffsetCalibrationButton::press_action() {
if (this->parent_ == nullptr) {
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Power Calibration button [%s]", this->get_name().c_str());
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Power Calibration button [%s]",
LOG_STR_ARG(this->get_log_name()));
return;
}
ESP_LOGI(TAG, "%s", this->get_name().c_str());
ESP_LOGI(TAG, "%s", LOG_STR_ARG(this->get_log_name()));
ESP_LOGI(TAG, "[CALIBRATION] **NOTE: CTs must be 0 during this process. Voltage reference should be present**");
ESP_LOGI(TAG, "[CALIBRATION] Use offset_active_power: & offset_reactive_power: under each phase_x: in your config "
"file to save these values");
@@ -66,11 +69,11 @@ void ATM90E32PowerOffsetCalibrationButton::press_action() {
void ATM90E32ClearPowerOffsetCalibrationButton::press_action() {
if (this->parent_ == nullptr) {
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Clear Power button [%s]", this->get_name().c_str());
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Clear Power button [%s]", LOG_STR_ARG(this->get_log_name()));
return;
}
ESP_LOGI(TAG, "%s", this->get_name().c_str());
ESP_LOGI(TAG, "%s", LOG_STR_ARG(this->get_log_name()));
this->parent_->clear_power_offset_calibrations();
}
+1 -1
View File
@@ -338,7 +338,7 @@ async def to_code(config: ConfigType) -> None:
# HTTPS streams verify the server against the root certificate bundle
require_certificate_bundle()
add_idf_component(name="esphome/esp-audio-libs", ref="4.0.1")
add_idf_component(name="esphome/esp-audio-libs", ref="4.1.0")
data = _get_data()
+2 -1
View File
@@ -1,10 +1,11 @@
#pragma once
#include <set>
#include "esphome/core/log.h"
namespace esphome::bedjet {
static const char *const TAG = "bedjet";
ESPHOME_LOG_TAG(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) {
@@ -211,7 +211,7 @@ void BedJetClimate::control(const ClimateCall &call) {
} 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(),
ESP_LOGW(TAG, "[%s] Unsupported fan mode: %s", LOG_STR_ARG(this->get_log_name()),
LOG_STR_ARG(climate_fan_mode_to_string(fan_mode)));
return;
}
@@ -223,7 +223,7 @@ void BedJetClimate::control(const ClimateCall &call) {
auto fan_mode = call.get_custom_fan_mode();
auto fan_index = bedjet_fan_speed_to_step(fan_mode.c_str());
if (fan_index <= 19) {
ESP_LOGV(TAG, "[%s] Converted fan mode %.*s to bedjet fan step %d", this->get_name().c_str(),
ESP_LOGV(TAG, "[%s] Converted fan mode %.*s to bedjet fan step %d", LOG_STR_ARG(this->get_log_name()),
(int) fan_mode.size(), fan_mode.c_str(), fan_index);
bool result = this->parent_->set_fan_index(fan_index);
if (result) {
@@ -236,7 +236,7 @@ void BedJetClimate::control(const ClimateCall &call) {
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);
ESP_LOGV(TAG, "[%s] Handling on_status with data=%p", LOG_STR_ARG(this->get_log_name()), (void *) data);
auto converted_temp = bedjet_temp_to_c(data->target_temp_step);
if (converted_temp > 0)
@@ -310,11 +310,11 @@ void BedJetClimate::on_status(const BedjetStatusPacket *data) {
break;
default:
ESP_LOGW(TAG, "[%s] Unexpected mode: 0x%02X", this->get_name().c_str(), data->mode);
ESP_LOGW(TAG, "[%s] Unexpected mode: 0x%02X", LOG_STR_ARG(this->get_log_name()), data->mode);
break;
}
ESP_LOGV(TAG, "[%s] After on_status, new mode=%s", this->get_name().c_str(),
ESP_LOGV(TAG, "[%s] After on_status, new mode=%s", LOG_STR_ARG(this->get_log_name()),
LOG_STR_ARG(climate_mode_to_string(this->mode)));
// FIXME: compare new state to previous state.
this->publish_state();
@@ -351,11 +351,11 @@ bool BedJetClimate::update_status_() {
}
void BedJetClimate::update() {
ESP_LOGD(TAG, "[%s] update()", this->get_name().c_str());
ESP_LOGD(TAG, "[%s] update()", LOG_STR_ARG(this->get_log_name()));
// 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");
ESP_LOGD(TAG, "[%s] update_status result=%s", LOG_STR_ARG(this->get_log_name()), result ? "true" : "false");
}
} // namespace esphome::bedjet
+3 -3
View File
@@ -53,7 +53,7 @@ void BedJetFan::control(const fan::FanCall &call) {
}
void BedJetFan::on_status(const BedjetStatusPacket *data) {
ESP_LOGVV(TAG, "[%s] Handling on_status with data=%p", this->get_name().c_str(), (void *) data);
ESP_LOGVV(TAG, "[%s] Handling on_status with data=%p", LOG_STR_ARG(this->get_log_name()), (void *) data);
bool did_change = false;
bool new_state = data->mode != MODE_STANDBY && data->mode != MODE_WAIT;
@@ -96,11 +96,11 @@ bool BedJetFan::update_status_() {
}
void BedJetFan::update() {
ESP_LOGD(TAG, "[%s] update()", this->get_name().c_str());
ESP_LOGD(TAG, "[%s] update()", LOG_STR_ARG(this->get_log_name()));
// 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");
ESP_LOGD(TAG, "[%s] update_status result=%s", LOG_STR_ARG(this->get_log_name()), result ? "true" : "false");
}
/** Resets states to defaults. */
+2 -2
View File
@@ -75,7 +75,7 @@ void BH1750Sensor::dump_config() {
LOG_SENSOR("", "BH1750", this);
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL_FOR, this->get_name().c_str());
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL_FOR, LOG_STR_ARG(this->get_log_name()));
}
LOG_UPDATE_INTERVAL(this);
@@ -154,7 +154,7 @@ void BH1750Sensor::loop() {
break;
}
ESP_LOGV(TAG, "'%s': Illuminance=%.1flx", this->get_name().c_str(), lx);
ESP_LOGV(TAG, "'%s': Illuminance=%.1flx", LOG_STR_ARG(this->get_log_name()), lx);
this->status_clear_warning();
this->publish_state(lx);
this->state_ = IDLE;
@@ -13,7 +13,7 @@ void log_binary_sensor(const char *tag, const char *prefix, const char *type, Bi
return;
}
ESP_LOGCONFIG(tag, "%s%s '%s'", prefix, type, obj->get_name().c_str());
ESP_LOGCONFIG(tag, "%s%s '%s'", prefix, type, LOG_STR_ARG(obj->get_log_name()));
LOG_ENTITY_DEVICE_CLASS(tag, prefix, *obj);
}
@@ -38,7 +38,7 @@ bool BinarySensor::set_new_state(const optional<bool> &new_state) {
#if defined(USE_BINARY_SENSOR) && defined(USE_CONTROLLER_REGISTRY)
ControllerRegistry::notify_binary_sensor_update(this);
#endif
ESP_LOGV(TAG, "'%s' >> %s", this->get_name().c_str(), ONOFFMAYBE(new_state));
ESP_LOGV(TAG, "'%s' >> %s", LOG_STR_ARG(this->get_log_name()), ONOFFMAYBE(new_state));
return true;
}
return false;
@@ -47,7 +47,7 @@ void BinarySensorMap::process_group_() {
}
} else if (this->last_mask_ != 0ULL) {
// no buttons are pressed and the states have changed since last run, so publish NAN
ESP_LOGV(TAG, "'%s' - No binary sensor active, publishing NAN", this->name_.c_str());
ESP_LOGV(TAG, "'%s' - No binary sensor active, publishing NAN", LOG_STR_ARG(this->get_log_name()));
this->publish_state(NAN);
}
+1 -1
View File
@@ -191,7 +191,7 @@ float BL0940::update_temp_(sensor::Sensor *sensor, uint16_le_t temperature) cons
if (sensor != nullptr) {
if (sensor->has_state() && std::abs(converted_temp - sensor->get_state()) > max_temperature_diff_) {
ESP_LOGD(TAG, "Invalid temperature change. Sensor: '%s', Old temperature: %f, New temperature: %f",
sensor->get_name().c_str(), sensor->get_state(), converted_temp);
LOG_STR_ARG(sensor->get_log_name()), sensor->get_state(), converted_temp);
return 0.0f;
}
sensor->publish_state(converted_temp);
+1 -1
View File
@@ -4,7 +4,7 @@
namespace esphome::ble_client {
const char *const Automation::TAG = "ble_client.automation";
const char *const Automation::TAG = "ble_client.automation"; // NOLINT: ble_client never builds for ESP8266
} // namespace esphome::ble_client
@@ -63,7 +63,7 @@ void BLEClientRSSISensor::gap_event_handler(esp_gap_ble_cb_event_t event, esp_bl
void BLEClientRSSISensor::update() {
if (this->node_state != espbt::ClientState::ESTABLISHED) {
ESP_LOGW(TAG, "[%s] Cannot poll, not connected", this->get_name().c_str());
ESP_LOGW(TAG, "[%s] Cannot poll, not connected", LOG_STR_ARG(this->get_log_name()));
this->should_update_ = true;
return;
}
@@ -37,13 +37,13 @@ void BLESensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t ga
switch (event) {
case ESP_GATTC_OPEN_EVT: {
if (param->open.status == ESP_GATT_OK) {
ESP_LOGI(TAG, "[%s] Connected successfully!", this->get_name().c_str());
ESP_LOGI(TAG, "[%s] Connected successfully!", LOG_STR_ARG(this->get_log_name()));
break;
}
break;
}
case ESP_GATTC_CLOSE_EVT: {
ESP_LOGW(TAG, "[%s] Disconnected!", this->get_name().c_str());
ESP_LOGW(TAG, "[%s] Disconnected!", LOG_STR_ARG(this->get_log_name()));
this->status_set_warning();
this->publish_state(NAN);
break;
@@ -102,10 +102,10 @@ void BLESensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t ga
}
case ESP_GATTC_NOTIFY_EVT: {
if (param->notify.value_len == 0) {
ESP_LOGW(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: empty value", this->get_name().c_str());
ESP_LOGW(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: empty value", LOG_STR_ARG(this->get_log_name()));
break;
}
ESP_LOGD(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: handle=0x%x, value=0x%x", this->get_name().c_str(),
ESP_LOGD(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: handle=0x%x, value=0x%x", LOG_STR_ARG(this->get_log_name()),
param->notify.handle, param->notify.value[0]);
if (param->notify.handle != this->handle)
break;
@@ -143,11 +143,11 @@ float BLESensor::parse_data_(uint8_t *value, uint16_t value_len) {
void BLESensor::update() {
if (this->node_state != espbt::ClientState::ESTABLISHED) {
ESP_LOGW(TAG, "[%s] Cannot poll, not connected", this->get_name().c_str());
ESP_LOGW(TAG, "[%s] Cannot poll, not connected", LOG_STR_ARG(this->get_log_name()));
return;
}
if (this->handle == 0) {
ESP_LOGW(TAG, "[%s] Cannot poll, no service or characteristic found", this->get_name().c_str());
ESP_LOGW(TAG, "[%s] Cannot poll, no service or characteristic found", LOG_STR_ARG(this->get_log_name()));
return;
}
@@ -156,7 +156,7 @@ void BLESensor::update() {
if (status) {
this->status_set_warning();
this->publish_state(NAN);
ESP_LOGW(TAG, "[%s] Error sending read request for sensor, status=%d", this->get_name().c_str(), status);
ESP_LOGW(TAG, "[%s] Error sending read request for sensor, status=%d", LOG_STR_ARG(this->get_log_name()), status);
}
}
@@ -38,7 +38,7 @@ void BLETextSensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
switch (event) {
case ESP_GATTC_OPEN_EVT: {
if (param->open.status == ESP_GATT_OK) {
ESP_LOGI(TAG, "[%s] Connected successfully!", this->get_name().c_str());
ESP_LOGI(TAG, "[%s] Connected successfully!", LOG_STR_ARG(this->get_log_name()));
break;
}
break;
@@ -104,10 +104,10 @@ void BLETextSensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
if (param->notify.handle != this->handle)
break;
if (param->notify.value_len == 0) {
ESP_LOGW(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: empty value", this->get_name().c_str());
ESP_LOGW(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: empty value", LOG_STR_ARG(this->get_log_name()));
break;
}
ESP_LOGV(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: handle=0x%x, value=0x%x", this->get_name().c_str(),
ESP_LOGV(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: handle=0x%x, value=0x%x", LOG_STR_ARG(this->get_log_name()),
param->notify.handle, param->notify.value[0]);
this->publish_state(reinterpret_cast<const char *>(param->notify.value), param->notify.value_len);
break;
@@ -124,11 +124,11 @@ void BLETextSensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
void BLETextSensor::update() {
if (this->node_state != espbt::ClientState::ESTABLISHED) {
ESP_LOGW(TAG, "[%s] Cannot poll, not connected", this->get_name().c_str());
ESP_LOGW(TAG, "[%s] Cannot poll, not connected", LOG_STR_ARG(this->get_log_name()));
return;
}
if (this->handle == 0) {
ESP_LOGW(TAG, "[%s] Cannot poll, no service or characteristic found", this->get_name().c_str());
ESP_LOGW(TAG, "[%s] Cannot poll, no service or characteristic found", LOG_STR_ARG(this->get_log_name()));
return;
}
@@ -137,7 +137,7 @@ void BLETextSensor::update() {
if (status) {
this->status_set_warning();
this->publish_state("");
ESP_LOGW(TAG, "[%s] Error sending read request for sensor, status=%d", this->get_name().c_str(), status);
ESP_LOGW(TAG, "[%s] Error sending read request for sensor, status=%d", LOG_STR_ARG(this->get_log_name()), status);
}
}
@@ -382,7 +382,7 @@ void BluedroidGattClient::set_disconnecting_() {
esp_err_t BluedroidGattClient::update_conn_params_(uint16_t min_interval, uint16_t max_interval, uint16_t latency,
uint16_t timeout, const char *param_type) {
esp_ble_conn_update_params_t conn_params = {{0}};
esp_ble_conn_update_params_t conn_params = {};
memcpy(conn_params.bda, this->remote_bda_, sizeof(esp_bd_addr_t));
conn_params.min_int = min_interval;
conn_params.max_int = max_interval;
+3 -2
View File
@@ -100,7 +100,8 @@ void BM8563::get_date_(ESPTime &time) {
this->read_register(DATE_FIRST_REG, buf, sizeof(buf));
time.day_of_month = this->bcd2_to_byte_(buf[0] & 0x3f);
time.day_of_week = this->bcd2_to_byte_(buf[1] & 0x07);
// The chip counts weekdays 0-6 from Sunday (not BCD), ESPTime counts 1-7
time.day_of_week = (buf[1] & 0x07) + 1;
time.month = this->bcd2_to_byte_(buf[2] & 0x1f);
uint8_t year_byte = this->bcd2_to_byte_(buf[3] & 0xff);
@@ -115,7 +116,7 @@ void BM8563::get_date_(ESPTime &time) {
void BM8563::set_date_(const ESPTime &time) {
uint8_t buf[4] = {
this->byte_to_bcd2_(time.day_of_month),
this->byte_to_bcd2_(time.day_of_week),
static_cast<uint8_t>(time.day_of_week - 1),
this->byte_to_bcd2_(time.month),
this->byte_to_bcd2_(time.year % 100),
};
+2 -1
View File
@@ -2,10 +2,11 @@
#include "esphome/components/bme280_base/bme280_base.h"
#include "esphome/components/i2c/i2c.h"
#include "esphome/core/log.h"
namespace esphome::bme280_i2c {
static const char *const TAG = "bme280_i2c.sensor";
ESPHOME_LOG_TAG(TAG, "bme280_i2c.sensor");
class BME280I2CComponent final : public esphome::bme280_base::BME280Component, public i2c::I2CDevice {
bool read_byte(uint8_t a_register, uint8_t *data) override;
+2 -1
View File
@@ -2,10 +2,11 @@
#include "esphome/components/bmp280_base/bmp280_base.h"
#include "esphome/components/i2c/i2c.h"
#include "esphome/core/log.h"
namespace esphome::bmp280_i2c {
static const char *const TAG = "bmp280_i2c.sensor";
ESPHOME_LOG_TAG(TAG, "bmp280_i2c.sensor");
/// This class implements support for the BMP280 Temperature+Pressure i2c sensor.
class BMP280I2CComponent final : public esphome::bmp280_base::BMP280Component, public i2c::I2CDevice {
+2 -1
View File
@@ -2,10 +2,11 @@
#include "esphome/components/bmp581_base/bmp581_base.h"
#include "esphome/components/i2c/i2c.h"
#include "esphome/core/log.h"
namespace esphome::bmp581_i2c {
static const char *const TAG = "bmp581_i2c.sensor";
ESPHOME_LOG_TAG(TAG, "bmp581_i2c.sensor");
/// This class implements support for the BMP581 Temperature+Pressure i2c sensor.
class BMP581I2CComponent final : public esphome::bmp581_base::BMP581Component, public i2c::I2CDevice {
+2 -2
View File
@@ -11,12 +11,12 @@ void log_button(const char *tag, const char *prefix, const char *type, Button *o
return;
}
ESP_LOGCONFIG(tag, "%s%s '%s'", prefix, type, obj->get_name().c_str());
ESP_LOGCONFIG(tag, "%s%s '%s'", prefix, type, LOG_STR_ARG(obj->get_log_name()));
LOG_ENTITY_ICON(tag, prefix, *obj);
}
void Button::press() {
ESP_LOGV(TAG, "'%s' Pressed.", this->get_name().c_str());
ESP_LOGV(TAG, "'%s' Pressed.", LOG_STR_ARG(this->get_log_name()));
this->press_action();
this->press_callback_.call();
}
@@ -8,7 +8,7 @@
namespace esphome::chsc6x {
static const char *const TAG = "chsc6x.touchscreen";
ESPHOME_LOG_TAG(TAG, "chsc6x.touchscreen");
static const uint8_t CHSC6X_REG_STATUS = 0x00;
static const uint8_t CHSC6X_REG_STATUS_TOUCH = 0x00;
+10 -7
View File
@@ -46,7 +46,7 @@ constexpr StringToUint8 CLIMATE_SWING_MODES_BY_STR[] = {
void ClimateCall::perform() {
this->parent_->control_callback_.call(*this);
ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str());
ESP_LOGV(TAG, "'%s' - Setting", LOG_STR_ARG(this->parent_->get_log_name()));
this->validate_();
if (this->mode_.has_value()) {
const LogString *mode_s = climate_mode_to_string(*this->mode_);
@@ -183,7 +183,7 @@ ClimateCall &ClimateCall::set_mode(const char *mode, size_t len) {
return *this;
}
}
ESP_LOGW(TAG, "'%s' - Unrecognized mode %.*s", this->parent_->get_name().c_str(), (int) len, mode);
ESP_LOGW(TAG, "'%s' - Unrecognized mode %.*s", LOG_STR_ARG(this->parent_->get_log_name()), (int) len, mode);
return *this;
}
@@ -214,7 +214,8 @@ ClimateCall &ClimateCall::set_fan_mode(const char *custom_fan_mode, size_t len)
this->fan_mode_.reset();
return *this;
}
ESP_LOGW(TAG, "'%s' - Unrecognized fan mode %.*s", this->parent_->get_name().c_str(), (int) len, custom_fan_mode);
ESP_LOGW(TAG, "'%s' - Unrecognized fan mode %.*s", LOG_STR_ARG(this->parent_->get_log_name()), (int) len,
custom_fan_mode);
return *this;
}
@@ -252,7 +253,8 @@ ClimateCall &ClimateCall::set_preset(const char *custom_preset, size_t len) {
this->preset_.reset();
return *this;
}
ESP_LOGW(TAG, "'%s' - Unrecognized preset %.*s", this->parent_->get_name().c_str(), (int) len, custom_preset);
ESP_LOGW(TAG, "'%s' - Unrecognized preset %.*s", LOG_STR_ARG(this->parent_->get_log_name()), (int) len,
custom_preset);
return *this;
}
@@ -280,7 +282,8 @@ ClimateCall &ClimateCall::set_swing_mode(const char *swing_mode, size_t len) {
return *this;
}
}
ESP_LOGW(TAG, "'%s' - Unrecognized swing mode %.*s", this->parent_->get_name().c_str(), (int) len, swing_mode);
ESP_LOGW(TAG, "'%s' - Unrecognized swing mode %.*s", LOG_STR_ARG(this->parent_->get_log_name()), (int) len,
swing_mode);
return *this;
}
@@ -428,7 +431,7 @@ void Climate::save_state_(const ClimateTraits &traits) {
void Climate::publish_state() {
this->set_has_state(true);
ESP_LOGV(TAG, "'%s' >>", this->name_.c_str());
ESP_LOGV(TAG, "'%s' >>", LOG_STR_ARG(this->get_log_name()));
auto traits = this->get_traits();
ESP_LOGV(TAG, " Mode: %s", LOG_STR_ARG(climate_mode_to_string(this->mode)));
@@ -549,7 +552,7 @@ void ClimateDeviceRestoreState::apply(Climate *climate) {
if (traits.supports_mode(this->mode)) {
climate->mode = this->mode;
} else {
ESP_LOGW(TAG, "'%s' - Saved mode %s is no longer supported, keeping %s", climate->get_name().c_str(),
ESP_LOGW(TAG, "'%s' - Saved mode %s is no longer supported, keeping %s", LOG_STR_ARG(climate->get_log_name()),
LOG_STR_ARG(climate_mode_to_string(this->mode)), LOG_STR_ARG(climate_mode_to_string(climate->mode)));
}
if (traits.has_feature_flags(CLIMATE_SUPPORTS_TWO_POINT_TARGET_TEMPERATURE |
+1 -1
View File
@@ -14,7 +14,7 @@ namespace esphome::climate {
#define LOG_CLIMATE(prefix, type, obj) \
if ((obj) != nullptr) { \
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), LOG_STR_ARG((obj)->get_log_name())); \
}
class Climate;
@@ -30,14 +30,14 @@ void CombinationOneParameterComponent::add_source(Sensor *sensor, float value) {
void CombinationNoParameterComponent::log_source_sensors() {
ESP_LOGCONFIG(TAG, " Source Sensors:");
for (const auto &sensor : this->sensors_) {
ESP_LOGCONFIG(TAG, " - %s", sensor->get_name().c_str());
ESP_LOGCONFIG(TAG, " - %s", LOG_STR_ARG(sensor->get_log_name()));
}
}
void CombinationOneParameterComponent::log_source_sensors() {
ESP_LOGCONFIG(TAG, " Source Sensors:");
for (const auto &source : this->sensor_sources_) {
ESP_LOGCONFIG(TAG, " - %s", source.sensor->get_name().c_str());
ESP_LOGCONFIG(TAG, " - %s", LOG_STR_ARG(source.sensor->get_log_name()));
}
}
+4 -4
View File
@@ -39,7 +39,7 @@ CoverCall &CoverCall::set_command(const char *command) {
} else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("TOGGLE")) == 0) {
this->set_command_toggle();
} else {
ESP_LOGW(TAG, "'%s' - Unrecognized command %s", this->parent_->get_name().c_str(), command);
ESP_LOGW(TAG, "'%s' - Unrecognized command %s", LOG_STR_ARG(this->parent_->get_log_name()), command);
}
return *this;
}
@@ -68,7 +68,7 @@ CoverCall &CoverCall::set_tilt(float tilt) {
return *this;
}
void CoverCall::perform() {
ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str());
ESP_LOGV(TAG, "'%s' - Setting", LOG_STR_ARG(this->parent_->get_log_name()));
auto traits = this->parent_->get_traits();
this->validate_();
if (this->stop_) {
@@ -94,7 +94,7 @@ const optional<float> &CoverCall::get_tilt() const { return this->tilt_; }
const optional<bool> &CoverCall::get_toggle() const { return this->toggle_; }
void CoverCall::validate_() {
auto traits = this->parent_->get_traits();
const char *name = this->parent_->get_name().c_str();
const char *name = LOG_STR_ARG(this->parent_->get_log_name());
if (this->position_.has_value()) {
auto pos = *this->position_;
@@ -139,7 +139,7 @@ void Cover::publish_state(bool save) {
this->position = clamp(this->position, 0.0f, 1.0f);
this->tilt = clamp(this->tilt, 0.0f, 1.0f);
ESP_LOGV(TAG, "'%s' >>", this->name_.c_str());
ESP_LOGV(TAG, "'%s' >>", LOG_STR_ARG(this->get_log_name()));
auto traits = this->get_traits();
if (traits.get_supports_position()) {
ESP_LOGV(TAG, " Position: %.0f%%", this->position * 100.0f);
+1 -1
View File
@@ -15,7 +15,7 @@ static constexpr float COVER_CLOSED = 0.0f;
#define LOG_COVER(prefix, type, obj) \
if ((obj) != nullptr) { \
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), LOG_STR_ARG((obj)->get_log_name())); \
auto traits_ = (obj)->get_traits(); \
if (traits_.get_is_assumed_state()) { \
ESP_LOGCONFIG(TAG, "%s Assumed State: YES", prefix); \
+22 -4
View File
@@ -8,6 +8,9 @@ namespace esphome::cse7766 {
ESPHOME_LOG_TAG(TAG, "cse7766");
// The chip only sends the time since the last pulse once a cycle is longer than 1 s (in us)
static constexpr uint32_t MIN_HELD_POWER_CYCLE = 1000000;
void CSE7766Component::loop() {
const uint32_t now = App.get_loop_component_start_time();
if (now - this->last_transmission_ >= 500) {
@@ -154,18 +157,33 @@ void CSE7766Component::parse_data_() {
if (power_cycle_exceeds_range) {
// Datasheet: power cycle exceeding range means active power is 0
have_power = true;
this->last_power_cycle_ = 0;
if (this->power_sensor_ != nullptr) {
this->power_sensor_->publish_state(0.0f);
}
} else if (have_power) {
power = power_coeff / float(power_cycle);
this->last_power_cycle_ = power_cycle;
if (this->power_sensor_ != nullptr) {
this->power_sensor_->publish_state(power);
}
} else if (this->power_sensor_ != nullptr) {
// No valid power measurement from chip - publish 0W to avoid stale readings
// This typically happens when current is below the measurable threshold (~50mA)
this->power_sensor_->publish_state(0.0f);
} else if (this->last_power_cycle_ > MIN_HELD_POWER_CYCLE && power_cycle <= 2 * this->last_power_cycle_) {
// No new measurement in this frame. With cycles over 1 s the register holds the last
// cycle or the time elapsed since the last pulse. While that time is within twice the
// last cycle, the next pulse is not overdue, so the last measurement still applies.
// Shorter cycles never get here in normal operation and keep the previous behaviour.
have_power = true;
power = power_coeff / float(this->last_power_cycle_);
if (this->power_sensor_ != nullptr) {
this->power_sensor_->publish_state(power);
}
} else {
// The next pulse is overdue: the load has dropped, report 0 W. A load that drops to less
// than half also reads 0 W here until its first new pulse arrives.
this->last_power_cycle_ = 0;
if (this->power_sensor_ != nullptr) {
this->power_sensor_->publish_state(0.0f);
}
}
float current = 0.0f;
+3 -1
View File
@@ -36,6 +36,7 @@ class CSE7766Component final : public Component, public uart::UARTDevice {
uint8_t raw_data_[CSE7766_RAW_DATA_SIZE];
uint8_t raw_data_index_{0};
uint16_t cf_pulses_last_{0};
uint32_t last_transmission_{0};
sensor::Sensor *voltage_sensor_{nullptr};
sensor::Sensor *current_sensor_{nullptr};
@@ -45,7 +46,8 @@ class CSE7766Component final : public Component, public uart::UARTDevice {
sensor::Sensor *reactive_power_sensor_{nullptr};
sensor::Sensor *power_factor_sensor_{nullptr};
uint32_t cf_pulses_total_{0};
uint16_t cf_pulses_last_{0};
// Power cycle of the last frame that carried a new power measurement, 0 if none
uint32_t last_power_cycle_{0};
};
} // namespace esphome::cse7766
@@ -8,7 +8,7 @@
namespace esphome::cst816 {
static const char *const TAG = "cst816.touchscreen";
ESPHOME_LOG_TAG(TAG, "cst816.touchscreen");
static const uint8_t REG_STATUS = 0x00;
static const uint8_t REG_TOUCH_NUM = 0x02;
@@ -8,7 +8,7 @@
namespace esphome::cst9220 {
static const char *const TAG = "cst9220.touchscreen";
ESPHOME_LOG_TAG(TAG, "cst9220.touchscreen");
// The CST92xx family uses 16-bit (big-endian) register addresses.
static const uint16_t REG_TOUCH_DATA = 0xD000; // touch report
@@ -40,7 +40,8 @@ void CTClampSensor::update() {
if (rms_ac_squared > 0)
rms_ac = std::sqrt(rms_ac_squared);
ESP_LOGD(TAG, "'%s' - Raw AC Value: %.3fA after %" PRIu32 " different samples (%" PRIu32 " SPS)",
this->name_.c_str(), rms_ac, this->num_samples_, 1000 * this->num_samples_ / this->sample_duration_);
LOG_STR_ARG(this->get_log_name()), rms_ac, this->num_samples_,
1000 * this->num_samples_ / this->sample_duration_);
this->publish_state(rms_ac);
});
@@ -70,20 +70,20 @@ void CurrentBasedCover::loop() {
this->direction_idle_();
this->malfunction_trigger_.trigger();
ESP_LOGI(TAG, "'%s' - Malfunction detected during opening. Current flow detected in close circuit",
this->name_.c_str());
LOG_STR_ARG(this->get_log_name()));
} else if (this->is_opening_blocked_()) { // Blocked
ESP_LOGD(TAG, "'%s' - Obstacle detected during opening.", this->name_.c_str());
ESP_LOGD(TAG, "'%s' - Obstacle detected during opening.", LOG_STR_ARG(this->get_log_name()));
this->direction_idle_();
if (this->obstacle_rollback_ != 0) {
this->set_timeout(ROLLBACK_TIMEOUT_ID, 300, [this]() {
ESP_LOGD(TAG, "'%s' - Rollback.", this->name_.c_str());
ESP_LOGD(TAG, "'%s' - Rollback.", LOG_STR_ARG(this->get_log_name()));
this->target_position_ = clamp(this->position - this->obstacle_rollback_, 0.0F, 1.0F);
this->start_direction_(COVER_OPERATION_CLOSING);
});
}
} else if (this->is_initial_delay_finished_() && !this->is_opening_()) { // End reached
auto dur = (now - this->start_dir_time_) / 1e3f;
ESP_LOGD(TAG, "'%s' - Open position reached. Took %.1fs.", this->name_.c_str(), dur);
ESP_LOGD(TAG, "'%s' - Open position reached. Took %.1fs.", LOG_STR_ARG(this->get_log_name()), dur);
this->direction_idle_(COVER_OPEN);
}
} else if (this->current_operation == COVER_OPERATION_CLOSING) {
@@ -91,25 +91,25 @@ void CurrentBasedCover::loop() {
this->direction_idle_();
this->malfunction_trigger_.trigger();
ESP_LOGI(TAG, "'%s' - Malfunction detected during closing. Current flow detected in open circuit",
this->name_.c_str());
LOG_STR_ARG(this->get_log_name()));
} else if (this->is_closing_blocked_()) { // Blocked
ESP_LOGD(TAG, "'%s' - Obstacle detected during closing.", this->name_.c_str());
ESP_LOGD(TAG, "'%s' - Obstacle detected during closing.", LOG_STR_ARG(this->get_log_name()));
this->direction_idle_();
if (this->obstacle_rollback_ != 0) {
this->set_timeout(ROLLBACK_TIMEOUT_ID, 300, [this]() {
ESP_LOGD(TAG, "'%s' - Rollback.", this->name_.c_str());
ESP_LOGD(TAG, "'%s' - Rollback.", LOG_STR_ARG(this->get_log_name()));
this->target_position_ = clamp(this->position + this->obstacle_rollback_, 0.0F, 1.0F);
this->start_direction_(COVER_OPERATION_OPENING);
});
}
} else if (this->is_initial_delay_finished_() && !this->is_closing_()) { // End reached
auto dur = (now - this->start_dir_time_) / 1e3f;
ESP_LOGD(TAG, "'%s' - Close position reached. Took %.1fs.", this->name_.c_str(), dur);
ESP_LOGD(TAG, "'%s' - Close position reached. Took %.1fs.", LOG_STR_ARG(this->get_log_name()), dur);
this->direction_idle_(COVER_CLOSED);
}
}
if (now - this->start_dir_time_ > this->max_duration_) {
ESP_LOGD(TAG, "'%s' - Max duration reached. Stopping cover.", this->name_.c_str());
ESP_LOGD(TAG, "'%s' - Max duration reached. Stopping cover.", LOG_STR_ARG(this->get_log_name()));
this->direction_idle_();
}
@@ -53,7 +53,7 @@ void DallasTemperatureSensor::update() {
}
float tempc = this->get_temp_c_();
ESP_LOGD(TAG, "'%s': Got Temperature=%f°C", this->get_name().c_str(), tempc);
ESP_LOGD(TAG, "'%s': Got Temperature=%f°C", LOG_STR_ARG(this->get_log_name()), tempc);
this->publish_state(tempc);
});
}
@@ -65,7 +65,7 @@ bool DallasTemperatureSensor::read_scratch_pad_() {
i = this->bus_->read8();
}
} else {
ESP_LOGW(TAG, "'%s' - reading scratch pad failed bus reset", this->get_name().c_str());
ESP_LOGW(TAG, "'%s' - reading scratch pad failed bus reset", LOG_STR_ARG(this->get_log_name()));
this->status_set_warning(LOG_STR("bus reset failed"));
}
return success;
+2 -2
View File
@@ -30,7 +30,7 @@ void DateEntity::publish_state() {
return;
}
this->set_has_state(true);
ESP_LOGV(TAG, "'%s' >> %d-%d-%d", this->get_name().c_str(), this->year_, this->month_, this->day_);
ESP_LOGV(TAG, "'%s' >> %d-%d-%d", LOG_STR_ARG(this->get_log_name()), this->year_, this->month_, this->day_);
this->state_callback_.call();
#if defined(USE_DATETIME_DATE) && defined(USE_CONTROLLER_REGISTRY)
ControllerRegistry::notify_date_update(this);
@@ -81,7 +81,7 @@ void DateCall::validate_() {
void DateCall::perform() {
this->validate_();
ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str());
ESP_LOGV(TAG, "'%s' - Setting", LOG_STR_ARG(this->parent_->get_log_name()));
if (this->year_.has_value()) {
ESP_LOGV(TAG, " Year: %d", *this->year_);
+1 -1
View File
@@ -14,7 +14,7 @@ namespace esphome::datetime {
#define LOG_DATETIME_DATE(prefix, type, obj) \
if ((obj) != nullptr) { \
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), LOG_STR_ARG((obj)->get_log_name())); \
LOG_ENTITY_ICON(TAG, prefix, *(obj)); \
}
@@ -45,7 +45,7 @@ void DateTimeEntity::publish_state() {
return;
}
this->set_has_state(true);
ESP_LOGV(TAG, "'%s' >> %04u-%02u-%02u %02d:%02d:%02d", this->get_name().c_str(), this->year_, this->month_,
ESP_LOGV(TAG, "'%s' >> %04u-%02u-%02u %02d:%02d:%02d", LOG_STR_ARG(this->get_log_name()), this->year_, this->month_,
this->day_, this->hour_, this->minute_, this->second_);
this->state_callback_.call();
#if defined(USE_DATETIME_DATETIME) && defined(USE_CONTROLLER_REGISTRY)
@@ -125,7 +125,7 @@ void DateTimeCall::validate_() {
void DateTimeCall::perform() {
this->validate_();
ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str());
ESP_LOGV(TAG, "'%s' - Setting", LOG_STR_ARG(this->parent_->get_log_name()));
if (this->year_.has_value()) {
ESP_LOGV(TAG, " Year: %d", *this->year_);
@@ -14,7 +14,7 @@ namespace esphome::datetime {
#define LOG_DATETIME_DATETIME(prefix, type, obj) \
if ((obj) != nullptr) { \
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), LOG_STR_ARG((obj)->get_log_name())); \
LOG_ENTITY_ICON(TAG, prefix, *(obj)); \
}
+2 -2
View File
@@ -26,7 +26,7 @@ void TimeEntity::publish_state() {
return;
}
this->set_has_state(true);
ESP_LOGV(TAG, "'%s' >> %02d:%02d:%02d", this->get_name().c_str(), this->hour_, this->minute_, this->second_);
ESP_LOGV(TAG, "'%s' >> %02d:%02d:%02d", LOG_STR_ARG(this->get_log_name()), this->hour_, this->minute_, this->second_);
this->state_callback_.call();
#if defined(USE_DATETIME_TIME) && defined(USE_CONTROLLER_REGISTRY)
ControllerRegistry::notify_time_update(this);
@@ -50,7 +50,7 @@ void TimeCall::validate_() {
void TimeCall::perform() {
this->validate_();
ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str());
ESP_LOGV(TAG, "'%s' - Setting", LOG_STR_ARG(this->parent_->get_log_name()));
if (this->hour_.has_value()) {
ESP_LOGV(TAG, " Hour: %d", *this->hour_);
}
+1 -1
View File
@@ -14,7 +14,7 @@ namespace esphome::datetime {
#define LOG_DATETIME_TIME(prefix, type, obj) \
if ((obj) != nullptr) { \
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), LOG_STR_ARG((obj)->get_log_name())); \
LOG_ENTITY_ICON(TAG, prefix, *(obj)); \
}
+4 -3
View File
@@ -36,7 +36,8 @@ void DewPointComponent::dump_config() {
"Sources\n"
" Temperature: '%s'\n"
" Humidity: '%s'",
this->temperature_sensor_->get_name().c_str(), this->humidity_sensor_->get_name().c_str());
LOG_STR_ARG(this->temperature_sensor_->get_log_name()),
LOG_STR_ARG(this->humidity_sensor_->get_log_name()));
}
float DewPointComponent::get_setup_priority() const { return setup_priority::DATA; }
@@ -75,8 +76,8 @@ void DewPointComponent::loop() {
// Publish the calculated dew point
this->publish_state(dew_point);
ESP_LOGD(TAG, "'%s' >> %.1f°C (T: %.1f°C, RH: %.1f%%)", this->get_name().c_str(), dew_point, this->temperature_value_,
this->humidity_value_);
ESP_LOGD(TAG, "'%s' >> %.1f°C (T: %.1f°C, RH: %.1f%%)", LOG_STR_ARG(this->get_log_name()), dew_point,
this->temperature_value_, this->humidity_value_);
}
} // namespace esphome::dew_point
+36
View File
@@ -250,6 +250,42 @@ def add_metadata(
)
KEY_EXTERNAL_WRITERS = "external_writers"
def _get_external_writer_list() -> list[tuple[ID, str]]:
"""Get the raw external writer list. Each entry is (display id, owner)."""
return CORE.data.setdefault(DOMAIN, {}).setdefault(KEY_EXTERNAL_WRITERS, [])
def register_external_writer(display_id: ID, owner: str) -> None:
"""Declare that ``owner`` draws into the display from outside its lambda or pages.
Call from the owner's CONFIG_SCHEMA. The ID may still be unresolved; the ID pass
resolves it in place before final validation.
"""
_get_external_writer_list().append((display_id, owner))
def get_external_writers(display_id: ID) -> list[str]:
"""Get the owners registered for a display. Only valid once IDs are resolved."""
return [
owner
for id_, owner in _get_external_writer_list()
if id_.id is not None and id_.id == display_id.id
]
def has_external_writer(display_id: ID) -> bool:
"""Tell a driver's final validation that something else draws into the display.
LVGL anywhere in the config also counts, as the drivers assumed before.
"""
from esphome.components.lvgl import DOMAIN as LVGL_DOMAIN
return LVGL_DOMAIN in full_config.get() or bool(get_external_writers(display_id))
async def register_display(var, config):
await cg.register_component(var, config)
await setup_display_core_(var, config)
+53 -27
View File
@@ -5,6 +5,7 @@
#include "display_color_utils.h"
#include "esphome/core/application.h"
#include "esphome/core/hal.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
namespace esphome::display {
@@ -52,40 +53,65 @@ void Display::line_at_angle(int x, int y, int angle, int start_radius, int stop_
this->line(x1, y1, x2, y2, color);
}
void Display::draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorOrder order,
ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad) {
size_t line_stride = x_offset + w + x_pad; // length of each source line in pixels
uint32_t color_value;
// flatten keeps to_color() inlined in the pixel loop; in PSRAM builds GCC at
// -Os stops inlining it once there are two call sites, which costs a call and
// spills per pixel. Without PSRAM there is one call site and it changes
// nothing, and draw_pixel_at() stays a virtual call either way.
template<ColorBitness BITNESS>
static void __attribute__((flatten))
draw_packed_pixels(Display *display, int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorOrder order,
bool big_endian, int x_offset, int y_offset, int x_pad) {
const size_t line_stride = x_offset + w + x_pad; // length of each source line in pixels
// BITNESS is a constant here, so to_color()'s three per pixel divisions
// become a multiply and shift and its bitness switch folds.
const auto draw_source_pixel = [&](int x, int y, size_t source_idx) ESPHOME_ALWAYS_INLINE {
display->draw_pixel_at(
x + x_start, y + y_start,
ColorUtil::to_color(ColorUtil::read_packed<BITNESS>(ptr, source_idx, big_endian), order, BITNESS));
};
// The source and frame buffers are row-major, so walking rows keeps the read
// and the write sequential. When the display swaps the axes before writing,
// walking columns keeps the write sequential instead; with the frame buffer
// in PSRAM a strided write costs more than a strided read.
#ifdef USE_PSRAM
if (display->pixel_axes_swapped()) {
size_t column_idx = y_offset * line_stride + x_offset;
for (int x = 0; x != w; x++, column_idx++) {
size_t source_idx = column_idx;
for (int y = 0; y != h; y++, source_idx += line_stride) {
draw_source_pixel(x, y, source_idx);
}
}
return;
}
#endif
// Row walk: builds without PSRAM, and PSRAM builds whose axes are not swapped.
for (int y = 0; y != h; y++) {
size_t source_idx = (y_offset + y) * line_stride + x_offset;
size_t source_idx_mod;
for (int x = 0; x != w; x++, source_idx++) {
switch (bitness) {
default:
color_value = ptr[source_idx];
break;
case COLOR_BITNESS_565:
source_idx_mod = source_idx * 2;
if (big_endian) {
color_value = (ptr[source_idx_mod] << 8) + ptr[source_idx_mod + 1];
} else {
color_value = ptr[source_idx_mod] + (ptr[source_idx_mod + 1] << 8);
}
break;
case COLOR_BITNESS_888:
source_idx_mod = source_idx * 3;
if (big_endian) {
color_value = (ptr[source_idx_mod + 0] << 16) + (ptr[source_idx_mod + 1] << 8) + ptr[source_idx_mod + 2];
} else {
color_value = ptr[source_idx_mod + 0] + (ptr[source_idx_mod + 1] << 8) + (ptr[source_idx_mod + 2] << 16);
}
break;
}
this->draw_pixel_at(x + x_start, y + y_start, ColorUtil::to_color(color_value, order, bitness));
draw_source_pixel(x, y, source_idx);
}
}
}
void Display::draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorOrder order,
ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad) {
switch (bitness) {
case COLOR_BITNESS_565:
draw_packed_pixels<COLOR_BITNESS_565>(this, x_start, y_start, w, h, ptr, order, big_endian, x_offset, y_offset,
x_pad);
break;
case COLOR_BITNESS_888:
draw_packed_pixels<COLOR_BITNESS_888>(this, x_start, y_start, w, h, ptr, order, big_endian, x_offset, y_offset,
x_pad);
break;
default:
draw_packed_pixels<COLOR_BITNESS_332>(this, x_start, y_start, w, h, ptr, order, big_endian, x_offset, y_offset,
x_pad);
break;
}
}
void HOT Display::horizontal_line(int x, int y, int width, Color color) {
// Future: Could be made more efficient by manipulating buffer directly in certain rotations.
for (int i = x; i < x + width; i++)
+11
View File
@@ -139,6 +139,11 @@ enum DisplayRotation {
DISPLAY_ROTATION_270_DEGREES = 270,
};
/// Whether a rotation swaps the x and y axes.
constexpr bool rotation_swaps_axes(DisplayRotation rotation) {
return rotation == DISPLAY_ROTATION_90_DEGREES || rotation == DISPLAY_ROTATION_270_DEGREES;
}
const int EDGES_TRIGON = 3;
const int EDGES_TRIANGLE = 3;
const int EDGES_TETRAGON = 4;
@@ -717,6 +722,12 @@ class Display : public PollingComponent {
virtual DisplayRotation get_rotation() const { return this->rotation_; }
/// True when draw_pixel_at() swaps x and y before writing, so pixels that are
/// neighbours along x land a row apart in the frame buffer. Not the same as
/// get_width()/get_height() swapping: a display that rotates in hardware
/// reports swapped dimensions but writes unswapped pixels.
virtual bool pixel_axes_swapped() const { return rotation_swaps_axes(this->rotation_); }
/** Get the type of display that the buffer corresponds to. In case of dynamically configurable displays,
* returns the type the display is currently configured to.
*/
@@ -2,6 +2,7 @@
#include <array>
#include <cstdint>
#include "esphome/core/color.h"
#include "esphome/core/helpers.h"
namespace esphome::display {
enum ColorOrder : uint8_t { COLOR_ORDER_RGB = 0, COLOR_ORDER_BGR = 1, COLOR_ORDER_GRB = 2 };
@@ -10,6 +11,27 @@ inline static uint8_t esp_scale(uint8_t i, uint8_t scale, uint8_t max_value = 25
class ColorUtil {
public:
/// Reads one packed pixel of the given bitness from a source buffer into the
/// value to_color() takes. BITNESS is a template argument so the byte layout
/// folds; pass it on to to_color() as a constant too, and its channel scaling
/// divides by a constant, which the compiler turns into a multiply and shift.
template<ColorBitness BITNESS>
static ESPHOME_ALWAYS_INLINE uint32_t read_packed(const uint8_t *ptr, size_t index, bool big_endian) {
if constexpr (BITNESS == COLOR_BITNESS_565) {
const size_t idx = index * 2;
if (big_endian)
return (ptr[idx] << 8) + ptr[idx + 1];
return ptr[idx] + (ptr[idx + 1] << 8);
} else if constexpr (BITNESS == COLOR_BITNESS_888) {
const size_t idx = index * 3;
if (big_endian)
return (ptr[idx + 0] << 16) + (ptr[idx + 1] << 8) + ptr[idx + 2];
return ptr[idx + 0] + (ptr[idx + 1] << 8) + (ptr[idx + 2] << 16);
} else {
return ptr[index];
}
}
static Color to_color(uint32_t colorcode, ColorOrder color_order,
ColorBitness color_bitness = ColorBitness::COLOR_BITNESS_888, bool right_bit_aligned = true) {
uint8_t first_color, second_color, third_color;
@@ -36,7 +36,7 @@ void DutyCycleSensor::update() {
const float total_time = float(now - this->last_update_);
const float value = (on_time * 100.0f) / total_time;
ESP_LOGD(TAG, "'%s' Got duty cycle=%.1f%%", this->get_name().c_str(), value);
ESP_LOGD(TAG, "'%s' Got duty cycle=%.1f%%", LOG_STR_ARG(this->get_log_name()), value);
this->publish_state(value);
}
this->last_update_ = now;
@@ -118,13 +118,8 @@ void Ecocomfort2Fan::on_status() {
int new_speed = this->speed;
uint8_t base_speed = raw_speed & SPEED_MASK;
if (raw_speed & FLAG_BOOST) {
new_speed = SPEED_COUNT;
} else if (raw_speed & FLAG_NIGHT) {
new_speed = SPEED_SLEEP;
} else if (base_speed >= SPEED_SLEEP && base_speed <= SPEED_VEL3) {
if (base_speed >= SPEED_SLEEP && base_speed <= SPEED_VEL3)
new_speed = base_speed;
}
const Preset *preset = find_preset(mode, (raw_speed & FLAG_AUTO) != 0);
const char *new_preset = preset != nullptr ? preset->name : nullptr;
bool same_preset = new_preset == nullptr ? !this->has_preset_mode() : this->get_preset_mode().c_str() == new_preset;
@@ -205,6 +205,10 @@ void Ecocomfort2Hub::publish_unknown_() {
sensor->publish_state(NAN);
}
#endif
#ifdef USE_BINARY_SENSOR
if (this->boost_binary_sensor_ != nullptr)
this->boost_binary_sensor_->invalidate_state();
#endif
}
// C_OPER: mode byte, speed/flags byte
@@ -216,10 +220,6 @@ void Ecocomfort2Hub::on_oper_(const uint8_t *data, uint16_t len) {
this->mode_ = data[0];
this->speed_ = data[1];
ESP_LOGD(TAG, "[%s] C_OPER: mode=0x%02x, speed=0x%02x", this->parent_->address_str(), this->mode_, this->speed_);
#ifdef USE_BINARY_SENSOR
if (this->boost_binary_sensor_ != nullptr)
this->boost_binary_sensor_->publish_state((this->speed_ & FLAG_BOOST) != 0);
#endif
#ifdef ECOCOMFORT2_CHILD_COUNT
for (auto *child : this->children_) {
child->on_status();
@@ -227,7 +227,9 @@ void Ecocomfort2Hub::on_oper_(const uint8_t *data, uint16_t len) {
#endif
}
// C_STATE: bytes 3-4 temperature and 5-6 humidity in hundredths, 7-8 VOC in ppb, byte 2 the air flow direction
// C_STATE: bytes 0-1 the mode and speed the unit runs; byte 1 also has the boost flag (0x40) and the advanced
// control step (0x20). Byte 2 the air flow direction, bytes 3-4 temperature and 5-6 humidity in hundredths,
// 7-8 VOC in ppb
void Ecocomfort2Hub::on_state_(const uint8_t *data, uint16_t len) {
if (len < 9) {
ESP_LOGW(TAG, "[%s] C_STATE too short: %u bytes", this->parent_->address_str(), len);
@@ -236,8 +238,12 @@ void Ecocomfort2Hub::on_state_(const uint8_t *data, uint16_t len) {
const float temperature = static_cast<int16_t>(encode_uint16(data[3], data[4])) / 100.0f;
const float humidity = encode_uint16(data[5], data[6]) / 100.0f;
const uint16_t voc = encode_uint16(data[7], data[8]);
ESP_LOGD(TAG, "[%s] C_STATE: %.2f °C, %.2f %%, %u ppb, direction=%u", this->parent_->address_str(), temperature,
humidity, voc, data[2]);
ESP_LOGD(TAG, "[%s] C_STATE: mode=0x%02x, speed=0x%02x, %.2f °C, %.2f %%, %u ppb, direction=%u",
this->parent_->address_str(), data[0], data[1], temperature, humidity, voc, data[2]);
#ifdef USE_BINARY_SENSOR
if (this->boost_binary_sensor_ != nullptr)
this->boost_binary_sensor_->publish_state((data[1] & FLAG_BOOST) != 0);
#endif
#ifdef USE_SENSOR
if (this->temperature_sensor_ != nullptr)
this->temperature_sensor_->publish_state(temperature);
@@ -267,7 +273,7 @@ void Ecocomfort2Hub::on_info_(const uint8_t *data, uint16_t len) {
}
#ifdef USE_TIME
// C_CLOCK: hour, minute, second, weekday with Monday as 0, day, month, year as two bytes
// C_CLOCK: two-digit year, month, day, weekday with Monday as 0, hour, minute, second, automatic DST flag
void Ecocomfort2Hub::sync_clock_() {
if (!this->is_ready() || this->char_handle_clock_ == 0)
return;
@@ -276,15 +282,11 @@ void Ecocomfort2Hub::sync_clock_() {
return;
// ESPTime counts Sunday=1 .. Saturday=7, the unit Monday=0 .. Sunday=6
const uint8_t weekday = (now.day_of_week + 5) % 7;
uint8_t data[8]{now.hour,
now.minute,
now.second,
weekday,
now.day_of_month,
now.month,
static_cast<uint8_t>(now.year >> 8),
static_cast<uint8_t>(now.year)};
ESP_LOGD(TAG, "[%s] Syncing clock to %02u:%02u:%02u", this->parent_->address_str(), now.hour, now.minute, now.second);
// The time source already applies DST and every sync rewrites the clock, so the unit must not shift it again
uint8_t data[8]{
static_cast<uint8_t>(now.year % 100), now.month, now.day_of_month, weekday, now.hour, now.minute, now.second, 0};
ESP_LOGD(TAG, "[%s] Syncing clock to %04u-%02u-%02u %02u:%02u:%02u", this->parent_->address_str(), now.year,
now.month, now.day_of_month, now.hour, now.minute, now.second);
auto status =
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_clock_,
sizeof(data), data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
@@ -32,7 +32,8 @@ static constexpr uint8_t OPER_OUT = 0x02;
static constexpr uint8_t OPER_IN_OUT = 0x03;
static constexpr uint8_t OPER_SENSOR_OR_AUTO = 0x04;
// C_OPER byte 1: speed in the low nibble, flags in the high nibble
// Speed byte: speed in the low nibble, flags in the high nibble.
// C_OPER carries FLAG_AUTO; the unit reports FLAG_BOOST in byte 1 of C_STATE.
static constexpr uint8_t SPEED_OFF = 0x00;
static constexpr uint8_t SPEED_SLEEP = 0x01;
static constexpr uint8_t SPEED_VEL1 = 0x02;
@@ -41,7 +42,6 @@ static constexpr uint8_t SPEED_VEL3 = 0x04;
static constexpr uint8_t SPEED_MASK = 0x0F;
static constexpr uint8_t FLAG_AUTO = 0x10;
static constexpr uint8_t FLAG_BOOST = 0x40;
static constexpr uint8_t FLAG_NIGHT = 0x80;
/** Hub component for Ecocomfort 2.0 VMC via BLE. */
class Ecocomfort2Hub : public esphome::ble_client::BLEClientNode, public PollingComponent {
+3 -3
View File
@@ -70,20 +70,20 @@ void EndstopCover::loop() {
if (this->current_operation == COVER_OPERATION_OPENING && this->is_open_()) {
float dur = (now - this->start_dir_time_) / 1e3f;
ESP_LOGD(TAG, "'%s' - Open endstop reached. Took %.1fs.", this->name_.c_str(), dur);
ESP_LOGD(TAG, "'%s' - Open endstop reached. Took %.1fs.", LOG_STR_ARG(this->get_log_name()), dur);
this->start_direction_(COVER_OPERATION_IDLE);
this->position = COVER_OPEN;
this->publish_state();
} else if (this->current_operation == COVER_OPERATION_CLOSING && this->is_closed_()) {
float dur = (now - this->start_dir_time_) / 1e3f;
ESP_LOGD(TAG, "'%s' - Close endstop reached. Took %.1fs.", this->name_.c_str(), dur);
ESP_LOGD(TAG, "'%s' - Close endstop reached. Took %.1fs.", LOG_STR_ARG(this->get_log_name()), dur);
this->start_direction_(COVER_OPERATION_IDLE);
this->position = COVER_CLOSED;
this->publish_state();
} else if (now - this->start_dir_time_ > this->max_duration_) {
ESP_LOGD(TAG, "'%s' - Max duration reached. Stopping cover.", this->name_.c_str());
ESP_LOGD(TAG, "'%s' - Max duration reached. Stopping cover.", LOG_STR_ARG(this->get_log_name()));
this->start_direction_(COVER_OPERATION_IDLE);
this->publish_state();
}
+1 -6
View File
@@ -40,7 +40,6 @@ from esphome.const import (
CONF_WIDTH,
)
from esphome.cpp_generator import RawExpression
from esphome.final_validate import full_config
from . import models
@@ -198,15 +197,11 @@ def _final_validate(config) -> None:
"epaper_spi", require_miso=False, require_mosi=True
)(config)
global_config = full_config.get()
from esphome.components.lvgl import DOMAIN as LVGL_DOMAIN
if CONF_LAMBDA not in config and CONF_PAGES not in config:
if LVGL_DOMAIN in global_config:
if display.has_external_writer(config[CONF_ID]):
if CONF_UPDATE_INTERVAL not in config:
config[CONF_UPDATE_INTERVAL] = update_interval("never")
else:
# If no drawing methods are configured, and LVGL is not enabled, show a test card
config[CONF_SHOW_TEST_CARD] = True
elif CONF_UPDATE_INTERVAL not in config:
config[CONF_UPDATE_INTERVAL] = update_interval("1min")
@@ -106,6 +106,7 @@ class EPaperBase : public Display,
int get_width() override { return this->effective_transform_ & SWAP_XY ? this->height_ : this->width_; }
int get_height() override { return this->effective_transform_ & SWAP_XY ? this->width_ : this->height_; }
bool pixel_axes_swapped() const override { return this->effective_transform_ & SWAP_XY; }
void draw_pixel_at(int x, int y, Color color) override;
void draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorOrder order,
ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad) override;
@@ -87,6 +87,38 @@ jd79660.extend(
),
)
# Waveshare 2.13-G (V2 hardware/init revision, PCB marked "rev 2.1" or later)
#
# Vendor init derived from vendor sample code
# <https://github.com/waveshareteam/e-Paper/blob/master/E-paper_Separate_Program/2in13_e-Paper_G/ESP32/EPD_2in13g_V2.cpp>
# Compatible MIT license, see esphome/LICENSE file.
#
# Note: busy pin uses LOW=busy, HIGH=idle. Configure with inverted: true in YAML.
# Note: panel is 122px wide, but vendor code declares the TRES register as a fixed
# 124 on this revision. width=124 is declared here (rather than 122) purely so the
# transferred bytes-per-row matches what the vendor init tells the IC to expect; the
# extra 2 columns fall outside the visible glass. The model width must equal the
# TRES value in initsequence, so overriding dimensions: in YAML brings the shear back.
#
# fmt: off
jd79660.extend(
"Waveshare-2.13in-G",
width=124,
height=250,
initsequence=(
(0x61, 0x00, 0x7C, 0x00, 0xFA,), # TRES: 124x250 fixed (124 = TRES stride value)
(0xE9, 0x01,),
# Power On (0x04): Must be early part of init seq = Disabled later!
(0x04,),
),
fast_update=(
(0xE0, 0x02,),
(0xE6, 0x5A,),
(0xA5,),
),
)
# Waveshare 7.5-H
#
# Vendor init derived from vendor sample code
@@ -130,7 +162,7 @@ jd79660.extend(
# Note: busy pin uses LOW=busy, HIGH=idle.
#
# fmt: off
jd79660.extend(
gdey0213f51 = jd79660.extend(
"goodisplay-gdey0213f51-2.13",
width=128,
height=250,
@@ -154,3 +186,13 @@ jd79660.extend(
(0x04,),
),
)
# Waveshare 2.13-G (V1 hardware/init revision, older stock): the same panel and init as the Good
# Display entry above, byte for byte, so it only adds the name. Vendor sample:
# <https://github.com/waveshareteam/e-Paper/blob/master/E-paper_Separate_Program/2in13_e-Paper_G/ESP32/EPD_2in13g.cpp>
# Compatible MIT license, see esphome/LICENSE file.
#
# Note: busy pin uses LOW=busy, HIGH=idle. Configure with inverted: true in YAML.
# Note: width=128 is the TRES value the init sequence programs, not the 122 visible columns; overriding
# dimensions: in YAML shears the image. Not tested on V1 hardware.
gdey0213f51.extend("Waveshare-2.13in-G-V1")
@@ -24,3 +24,11 @@ WaveshareB(
data_rate="10MHz",
minimum_update_interval="1s",
)
WaveshareB(
"waveshare-2.66in-b",
width=152,
height=296,
data_rate="10MHz",
minimum_update_interval="15s",
)
@@ -0,0 +1,3 @@
CODEOWNERS = ["@GioMez"]
DEPENDENCIES = ["i2c"]
DOMAIN = "es9038q2m_katana"
@@ -0,0 +1,92 @@
import esphome.codegen as cg
from esphome.components import audio_dac, i2c
import esphome.config_validation as cv
from esphome.const import CONF_BITS_PER_SAMPLE, CONF_ID, CONF_SAMPLE_RATE
from esphome.types import ConfigType
CONF_DEEMPHASIS = "deemphasis"
CONF_DOP = "dop"
CONF_FILTER_SHAPE = "filter_shape"
# Fields of the Katana format register: channel layout, word length and rate code.
FORMAT_STEREO = 0x80
BITS_PER_SAMPLE_CODES = {16: 0x10, 24: 0x20, 32: 0x30}
SAMPLE_RATE_CODES = {
44100: 0x04,
48000: 0x05,
88200: 0x06,
96000: 0x07,
176400: 0x08,
192000: 0x09,
352800: 0x0A,
384000: 0x0B,
}
es9038q2m_katana_ns = cg.esphome_ns.namespace("es9038q2m_katana")
ES9038Q2MKatana = es9038q2m_katana_ns.class_(
"ES9038Q2MKatana",
audio_dac.AudioDac,
cg.Component,
i2c.I2CDevice,
)
FilterShape = es9038q2m_katana_ns.enum("FilterShape")
FILTER_SHAPES = {
"linear_phase_fast": FilterShape.FILTER_SHAPE_LINEAR_PHASE_FAST,
"linear_phase_slow": FilterShape.FILTER_SHAPE_LINEAR_PHASE_SLOW,
"minimum_phase_fast": FilterShape.FILTER_SHAPE_MIN_PHASE_FAST,
"minimum_phase_slow": FilterShape.FILTER_SHAPE_MIN_PHASE_SLOW,
"apodizing": FilterShape.FILTER_SHAPE_APODIZING,
"hybrid": FilterShape.FILTER_SHAPE_HYBRID,
"brick_wall": FilterShape.FILTER_SHAPE_BRICK_WALL,
}
DeemphasisMode = es9038q2m_katana_ns.enum("DeemphasisMode")
DEEMPHASIS_MODES = {
"bypass": DeemphasisMode.DEEMPHASIS_BYPASS,
"32khz": DeemphasisMode.DEEMPHASIS_32KHZ,
"44_1khz": DeemphasisMode.DEEMPHASIS_44_1KHZ,
"48khz": DeemphasisMode.DEEMPHASIS_48KHZ,
}
CONFIG_SCHEMA = (
cv.Schema(
{
cv.GenerateID(): cv.declare_id(ES9038Q2MKatana),
cv.Optional(CONF_FILTER_SHAPE, default="apodizing"): cv.enum(
FILTER_SHAPES, lower=True
),
cv.Optional(CONF_BITS_PER_SAMPLE, default="16bit"): cv.All(
cv.float_with_unit("bits", "bit"),
cv.one_of(*BITS_PER_SAMPLE_CODES, int=True),
),
cv.Optional(CONF_SAMPLE_RATE, default=48000): cv.one_of(
*SAMPLE_RATE_CODES, int=True
),
cv.Optional(CONF_DEEMPHASIS, default="bypass"): cv.enum(
DEEMPHASIS_MODES, lower=True
),
# Only switches the control logic; the source must already send DoP frames.
cv.Optional(CONF_DOP, default=False): cv.boolean,
}
)
.extend(cv.COMPONENT_SCHEMA)
.extend(i2c.i2c_device_schema(0x30))
)
async def to_code(config: ConfigType) -> None:
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
await i2c.register_i2c_device(var, config)
cg.add(var.set_filter_shape(config[CONF_FILTER_SHAPE]))
cg.add(
var.set_format(
FORMAT_STEREO
| BITS_PER_SAMPLE_CODES[config[CONF_BITS_PER_SAMPLE]]
| SAMPLE_RATE_CODES[config[CONF_SAMPLE_RATE]]
)
)
cg.add(var.set_deemphasis_mode(config[CONF_DEEMPHASIS]))
cg.add(var.set_dop_enabled(config[CONF_DOP]))
@@ -0,0 +1,176 @@
#include "es9038q2m_katana.h"
#include "esphome/core/hal.h"
#include "esphome/core/log.h"
#include <cmath>
namespace esphome::es9038q2m_katana {
ESPHOME_LOG_TAG(TAG, "es9038q2m_katana");
namespace {
constexpr uint8_t KATANA_CHIP_ID = 0x30;
constexpr uint8_t KATANA_REG_CHIP_ID = 0x00;
constexpr uint8_t KATANA_REG_RESET = 0x01;
constexpr uint8_t KATANA_REG_VOLUME_1 = 0x02;
constexpr uint8_t KATANA_REG_VOLUME_2 = 0x03;
constexpr uint8_t KATANA_REG_MUTE = 0x04;
constexpr uint8_t KATANA_REG_DSP_PROGRAM = 0x05;
constexpr uint8_t KATANA_REG_DEEMPHASIS = 0x06;
constexpr uint8_t KATANA_REG_DOP = 0x07;
constexpr uint8_t KATANA_REG_FORMAT = 0x08;
constexpr uint8_t KATANA_REG_COMMAND = 0x09;
constexpr uint8_t KATANA_REG_MUTE_STREAM = 0x0A;
constexpr float KATANA_VOLUME_MIDPOINT = 0.5f;
constexpr float KATANA_VOLUME_MIDPOINT_STEPS = 50.0f; // -25 dB at 50% volume.
// Cubic amplitude gain: -20 * log10(volume^3) / 0.5 attenuation steps.
constexpr float KATANA_VOLUME_CUBIC_SCALE = 120.0f;
constexpr uint8_t KATANA_VOLUME_FULL_ATTENUATION = 255;
// The control logic ignores writes for this long after a reset.
constexpr uint32_t RESET_SETTLE_DELAY_MS = 10;
const LogString *filter_shape_to_str(FilterShape shape) {
switch (shape) {
case FILTER_SHAPE_LINEAR_PHASE_FAST:
return LOG_STR("linear_phase_fast");
case FILTER_SHAPE_LINEAR_PHASE_SLOW:
return LOG_STR("linear_phase_slow");
case FILTER_SHAPE_MIN_PHASE_FAST:
return LOG_STR("minimum_phase_fast");
case FILTER_SHAPE_MIN_PHASE_SLOW:
return LOG_STR("minimum_phase_slow");
case FILTER_SHAPE_APODIZING:
return LOG_STR("apodizing");
case FILTER_SHAPE_HYBRID:
return LOG_STR("hybrid");
default:
return LOG_STR("brick_wall");
}
}
const LogString *deemphasis_to_str(DeemphasisMode mode) {
switch (mode) {
case DEEMPHASIS_32KHZ:
return LOG_STR("32khz");
case DEEMPHASIS_44_1KHZ:
return LOG_STR("44_1khz");
case DEEMPHASIS_48KHZ:
return LOG_STR("48khz");
default:
return LOG_STR("bypass");
}
}
} // namespace
void ES9038Q2MKatana::setup() {
uint8_t chip_id = 0;
if (!this->read_byte(KATANA_REG_CHIP_ID, &chip_id)) {
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
if (chip_id != KATANA_CHIP_ID) {
ESP_LOGE(TAG, "Unexpected chip ID 0x%02X", chip_id);
this->mark_failed(LOG_STR("Unexpected chip ID"));
return;
}
if (!this->write_byte(KATANA_REG_RESET, 0x01)) {
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
delay(RESET_SETTLE_DELAY_MS);
// MUTE_STREAM is the gate the Linux driver closes between streams; ESPHome has no such
// notion, so it stays open and mute is only ever driven through MUTE.
if (!this->write_byte(KATANA_REG_FORMAT, this->format_) || !this->write_byte(KATANA_REG_COMMAND, 0x00) ||
!this->write_byte(KATANA_REG_DSP_PROGRAM, this->filter_shape_) ||
!this->write_byte(KATANA_REG_DEEMPHASIS, this->deemphasis_mode_) ||
!this->write_byte(KATANA_REG_DOP, this->dop_enabled_ ? 1 : 0) || !this->write_volume_() ||
!this->write_byte(KATANA_REG_MUTE, this->is_muted_ ? 1 : 0) || !this->write_byte(KATANA_REG_MUTE_STREAM, 0x00)) {
this->mark_failed(LOG_STR("Failed to configure the control logic"));
}
}
void ES9038Q2MKatana::dump_config() {
ESP_LOGCONFIG(TAG,
"ES9038Q2M Katana:\n"
" Filter shape: %s\n"
" De-emphasis: %s\n"
" Format register: 0x%02X\n"
" DoP: %s",
LOG_STR_ARG(filter_shape_to_str(this->filter_shape_)),
LOG_STR_ARG(deemphasis_to_str(this->deemphasis_mode_)), this->format_, ONOFF(this->dop_enabled_));
LOG_I2C_DEVICE(this);
if (this->is_failed())
return;
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
for (uint8_t reg = KATANA_REG_CHIP_ID; reg <= KATANA_REG_MUTE_STREAM; reg++) {
uint8_t value = 0;
if (this->read_byte(reg, &value)) {
ESP_LOGV(TAG, " Register 0x%02X: 0x%02X", reg, value);
} else {
ESP_LOGV(TAG, " Register 0x%02X: read failed", reg);
}
}
#endif
}
// Both channel registers follow ESPHome's single master volume.
bool ES9038Q2MKatana::write_volume_() {
return this->write_byte(KATANA_REG_VOLUME_1, this->volume_reg_) &&
this->write_byte(KATANA_REG_VOLUME_2, this->volume_reg_);
}
// Records the outcome of a runtime write; the cached state only changes on success.
bool ES9038Q2MKatana::check_write_(bool ok) {
if (ok) {
this->status_clear_warning();
} else {
this->status_set_warning(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
}
return ok;
}
bool ES9038Q2MKatana::set_volume(float volume) {
if (this->is_failed())
return false;
volume = clamp(volume, 0.0f, 1.0f);
const uint8_t previous = this->volume_reg_;
float attenuation = KATANA_VOLUME_FULL_ATTENUATION;
if (volume >= KATANA_VOLUME_MIDPOINT) {
attenuation = KATANA_VOLUME_MIDPOINT_STEPS * (1.0f - volume) / (1.0f - KATANA_VOLUME_MIDPOINT);
} else if (volume > 0.0f) {
attenuation = KATANA_VOLUME_MIDPOINT_STEPS - KATANA_VOLUME_CUBIC_SCALE * log10f(volume / KATANA_VOLUME_MIDPOINT);
}
this->volume_reg_ =
static_cast<uint8_t>(lroundf(clamp(attenuation, 0.0f, static_cast<float>(KATANA_VOLUME_FULL_ATTENUATION))));
if (this->check_write_(this->write_volume_()))
return true;
this->volume_reg_ = previous;
return false;
}
float ES9038Q2MKatana::volume() {
if (this->volume_reg_ == KATANA_VOLUME_FULL_ATTENUATION)
return 0.0f;
if (this->volume_reg_ <= KATANA_VOLUME_MIDPOINT_STEPS)
return 1.0f - this->volume_reg_ * (1.0f - KATANA_VOLUME_MIDPOINT) / KATANA_VOLUME_MIDPOINT_STEPS;
return KATANA_VOLUME_MIDPOINT *
powf(10.0f, (KATANA_VOLUME_MIDPOINT_STEPS - this->volume_reg_) / KATANA_VOLUME_CUBIC_SCALE);
}
bool ES9038Q2MKatana::set_mute_state_(bool mute_state) {
if (this->is_failed())
return false;
if (!this->check_write_(this->write_byte(KATANA_REG_MUTE, mute_state ? 1 : 0)))
return false;
this->is_muted_ = mute_state;
return true;
}
} // namespace esphome::es9038q2m_katana
@@ -0,0 +1,62 @@
#pragma once
#include "esphome/components/audio_dac/audio_dac.h"
#include "esphome/components/i2c/i2c.h"
#include "esphome/core/component.h"
#include "esphome/core/helpers.h"
namespace esphome::es9038q2m_katana {
// DSP program numbers of the Katana control interface; there is no program 5.
enum FilterShape : uint8_t {
FILTER_SHAPE_LINEAR_PHASE_FAST = 0,
FILTER_SHAPE_LINEAR_PHASE_SLOW = 1,
FILTER_SHAPE_MIN_PHASE_FAST = 2,
FILTER_SHAPE_MIN_PHASE_SLOW = 3,
FILTER_SHAPE_APODIZING = 4,
FILTER_SHAPE_HYBRID = 6,
FILTER_SHAPE_BRICK_WALL = 7,
};
enum DeemphasisMode : uint8_t {
DEEMPHASIS_BYPASS = 0,
DEEMPHASIS_32KHZ = 1,
DEEMPHASIS_44_1KHZ = 2,
DEEMPHASIS_48KHZ = 3,
};
// Boards that expose an ES9038Q2M through the Allo Katana control logic at I2C address 0x30.
// Ported from the Linux driver sound/soc/bcm/allo-katana-codec.c; the DAC's own registers
// are never written, the control logic applies the configuration itself.
class ES9038Q2MKatana : public audio_dac::AudioDac, public Component, public i2c::I2CDevice {
public:
void setup() override;
void dump_config() override;
// Cubic below 50%, then 0.5 dB per 1% above, meeting at -25 dB.
// Zero selects full attenuation (-127.5 dB).
bool set_volume(float volume) override;
float volume() override;
bool set_mute_off() override { return this->set_mute_state_(false); }
bool set_mute_on() override { return this->set_mute_state_(true); }
bool is_muted() override { return this->is_muted_; }
void set_filter_shape(FilterShape shape) { this->filter_shape_ = shape; }
void set_format(uint8_t format) { this->format_ = format; }
void set_deemphasis_mode(DeemphasisMode mode) { this->deemphasis_mode_ = mode; }
void set_dop_enabled(bool enabled) { this->dop_enabled_ = enabled; }
protected:
bool set_mute_state_(bool mute_state);
bool write_volume_();
bool check_write_(bool ok);
FilterShape filter_shape_{FILTER_SHAPE_APODIZING};
DeemphasisMode deemphasis_mode_{DEEMPHASIS_BYPASS};
uint8_t format_{0};
// Attenuation in 0.5 dB steps: 0 is loudest, 255 quietest. Starts 20 dB down.
uint8_t volume_reg_{0x28};
bool dop_enabled_{false};
};
} // namespace esphome::es9038q2m_katana
+1
View File
@@ -2920,6 +2920,7 @@ async def _finalize_arduino_aware_flags():
if not arduino_linked:
cg.add_build_flag("-Wl,--wrap=esp_panic_handler")
cg.add_define("USE_ESP32_CRASH_HANDLER")
cg.add_define("USE_CRASH_HANDLER")
elif not CORE.using_arduino:
cg.add_build_flag("-DUSE_ARDUINO")
+3 -2
View File
@@ -161,7 +161,7 @@ static bool s_crash_data_valid = false; // NOLINT(cppcoreguidelines-avoid-non-c
namespace esphome::esp32 {
ESPHOME_LOG_TAG(TAG, "esp32.crash");
ESPHOME_LOG_TAG(TAG, CRASH_LOG_TAG);
// RAM copy of the build timestamp. The generated constant lives in flash,
// which the panic handler must not read (cache may be disabled during
@@ -175,7 +175,8 @@ static uint32_t s_current_build_time = static_cast<uint32_t>(ESPHOME_BUILD_TIME)
// Validate the NOINIT record. Runs on every has_data() call; re-running is
// harmless and the magic is left alone so the record survives an OTA
// rollback reboot, crash_handler_clear() drops it once an API client has it.
// rollback reboot, crash_handler_clear() drops it once a log client has it
// (logger::log_crash_to_client(), for the API and MQTT).
static void read_crash_data() {
if (s_raw_crash_data.magic == CRASH_MAGIC && s_raw_crash_data.version == CRASH_DATA_VERSION) {
s_crash_data_valid = true;
+3
View File
@@ -4,6 +4,9 @@
namespace esphome::esp32 {
/// The tag the crash record is logged under, so a client can check the level in force for it
inline constexpr const char *CRASH_LOG_TAG = "esp32.crash";
/// Log crash data if a crash was detected on previous boot.
void crash_handler_log();
+1
View File
@@ -131,6 +131,7 @@ bool ESP32PreferenceBackend::load(uint8_t *data, size_t len) {
void ESP32Preferences::open() {
// Runs from app_main() before the logger is initialized; any logging here
// must be deferred. See s_open_err and make_preference() below.
// Components that need NVS check nvs_handle instead of initializing it again.
nvs_flash_init();
esp_err_t err = nvs_open("esphome", NVS_READWRITE, &this->nvs_handle);
if (err == 0)
+4 -12
View File
@@ -5,6 +5,7 @@
#include "esphome/core/application.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#include "esphome/core/preferences.h"
#ifndef CONFIG_BT_CONTROLLER_DISABLED
#include <esp_bt.h>
@@ -28,7 +29,6 @@ extern "C" {
#include <freertos/FreeRTOS.h>
#include <freertos/FreeRTOSConfig.h>
#include <freertos/task.h>
#include <nvs_flash.h>
#ifdef USE_ARDUINO
// Prevent Arduino from releasing BT memory at startup (esp32-hal-misc.c).
@@ -77,8 +77,9 @@ static constexpr uint32_t HOSTED_BT_WDT_TIMEOUT_MS = 60000;
void ESP32BLE::setup() {
global_ble = this;
if (!ble_pre_setup_()) {
ESP_LOGE(TAG, "BLE could not be prepared for configuration");
// Preferences opens NVS in app_main(); a zero handle means it could not be opened, even after an erase
if (global_preferences->nvs_handle == 0) {
ESP_LOGE(TAG, "NVS unavailable");
this->mark_failed();
return;
}
@@ -185,15 +186,6 @@ void ESP32BLE::advertising_remove_service_uuid(ESPBTUUID uuid) {
}
#endif
bool ESP32BLE::ble_pre_setup_() {
esp_err_t err = nvs_flash_init();
if (err != ESP_OK) {
ESP_LOGE(TAG, "nvs_flash_init failed: %d", err);
return false;
}
return true;
}
#ifdef USE_ESP32_BLE_ADVERTISING
void ESP32BLE::advertising_init_() {
if (this->advertising_ != nullptr)
-1
View File
@@ -185,7 +185,6 @@ class ESP32BLE final : public Component {
}
this->ble_events_.get_and_reset_dropped_count();
}
bool ble_pre_setup_();
#ifdef USE_ESP32_BLE_ADVERTISING
void advertising_init_();
#endif
@@ -10,7 +10,6 @@
#include <esp_gap_ble_api.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <nvs_flash.h>
#include <cstring>
#include "esphome/core/hal.h"
@@ -300,7 +300,7 @@ void BLEClientBase::log_warning_(const char *message) {
esp_err_t BLEClientBase::update_conn_params_(uint16_t min_interval, uint16_t max_interval, uint16_t latency,
uint16_t timeout, const char *param_type) {
esp_ble_conn_update_params_t conn_params = {{0}};
esp_ble_conn_update_params_t conn_params = {};
memcpy(conn_params.bda, this->remote_bda_, sizeof(esp_bd_addr_t));
conn_params.min_int = min_interval;
conn_params.max_int = max_interval;
@@ -7,7 +7,6 @@
#ifdef USE_ESP32
#include <nvs_flash.h>
#include <freertos/FreeRTOSConfig.h>
#include <esp_bt_main.h>
#ifndef CONFIG_BT_CONTROLLER_DISABLED
@@ -16,7 +16,6 @@
#include <freertos/FreeRTOS.h>
#include <freertos/FreeRTOSConfig.h>
#include <freertos/task.h>
#include <nvs_flash.h>
#include <cinttypes>
#ifdef USE_OTA
@@ -132,9 +132,9 @@ void ESP32Camera::dump_config() {
" External Clock: Pin:%d Frequency:%u\n"
" I2C Pins: SDA:%d SCL:%d\n"
" Reset Pin: %d",
this->name_.c_str(), YESNO(this->is_internal()), conf.pin_d0, conf.pin_d1, conf.pin_d2, conf.pin_d3,
conf.pin_d4, conf.pin_d5, conf.pin_d6, conf.pin_d7, conf.pin_vsync, conf.pin_href, conf.pin_pclk,
conf.pin_xclk, conf.xclk_freq_hz, conf.pin_sccb_sda, conf.pin_sccb_scl, conf.pin_reset);
LOG_STR_ARG(this->get_log_name()), YESNO(this->is_internal()), conf.pin_d0, conf.pin_d1, conf.pin_d2,
conf.pin_d3, conf.pin_d4, conf.pin_d5, conf.pin_d6, conf.pin_d7, conf.pin_vsync, conf.pin_href,
conf.pin_pclk, conf.pin_xclk, conf.xclk_freq_hz, conf.pin_sccb_sda, conf.pin_sccb_scl, conf.pin_reset);
ESP_LOGCONFIG(TAG, " Resolution: %s", frame_size_to_str(this->config_.frame_size));
ESP_LOGCONFIG(TAG, " Pixel Format: %s", pixel_format_to_str(this->config_.pixel_format));

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