Compare commits

..
Author SHA1 Message Date
Jesse Hills 6c90b5c549 Merge pull request #21254 from esphome/bump-2026.10.0b6
2026.10.0b6
2026-10-21 16:39:54 +13:00
Jesse Hills c8df23a9cb Bump version to 2026.10.0b6 2026-10-21 16:17:51 +13:00
4fdce9d96b [web_server_idf] Reduce loopTask stack usage for state SSE (#21109)
Co-authored-by: Jeroen Jansen <jeroen@Jeroens-MacBook-Air.local>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-21 16:17:49 +13:00
J. Nick Koston 9d296a5748 [ota] Accept an unknown image size in the RP2040 backend so web_server OTA works (#21178) 2026-10-21 16:17:49 +13:00
esphome[bot] f2e013d71a Bump bundled esphome-device-builder to 1.25.0 (#21175) 2026-10-21 16:17:49 +13:00
Jesse Hills 2001dd2be8 Merge pull request #21097 from esphome/bump-2026.10.0b5
2026.10.0b5
2026-10-19 14:03:02 +13:00
Jesse Hills a6a4b49e75 Bump version to 2026.10.0b5 2026-10-19 11:29:05 +13:00
Bonne EgglestonandJ. Nick Koston 649f2c91f5 [api] Poll the outgoing dial every loop (#21085)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-10-19 11:29:02 +13:00
Bonne Eggleston ffa20abe96 [api] Poll the outgoing dial every loop on deep sleep builds (#21077) 2026-10-19 11:29:02 +13:00
J. Nick Koston f979ddcf0d [bl0906] Read stale receive bytes instead of spinning on flush() (#21035) 2026-10-19 11:29:02 +13:00
J. Nick Koston 26064f1415 [uart_tcp] Expose the connection entities as platforms (#21008) 2026-10-19 11:29:02 +13:00
J. Nick Koston c50ee215f2 [tcp_uart] Expose the connection entities as platforms (#21009) 2026-10-19 10:36:23 +13:00
Jonathan Swoboda 0fbba03522 [debug] Log uptime in dump_config (#20989) 2026-10-19 10:33:13 +13:00
Jonathan Swoboda 7ccaedfb9e [esp32] Bump recommended ESP-IDF to 5.5.6 (#20987) 2026-10-19 10:33:13 +13:00
esphome[bot] 0173127239 Bump bundled esphome-device-builder to 1.24.0 (#20851)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-10-19 10:33:13 +13:00
Clyde Stubbs 235c614e68 [epaper_spi] Ensure test card gets drawn (#20804) 2026-10-19 10:33:13 +13:00
Jonathan Swoboda 79823c89ab [mipi_rgb] Rotate pure RGB panels in software (#20757) 2026-10-19 10:33:13 +13:00
J. Nick Koston e09cb64756 [bluetooth_connection] Value-initialize the connection parameters for ESP-IDF 6.1 (#20774) 2026-10-19 10:33:13 +13:00
J. Nick Koston bd5b3fa641 [esp32_ble_client] Value-initialize the connection parameters for ESP-IDF 6.1 (#20776) 2026-10-19 10:33:13 +13:00
Kevin AhrendtandJ. Nick Koston f464994f85 [api][sendspin] Add the Sendspin client id to the capabilities message (#20775)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-10-19 10:33:13 +13:00
esphome[bot] 4552dbad7a 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-19 10:33:13 +13:00
J. Nick Koston ad8cd0dd3e [noise] Initialize the protocol id's reserved field for ESP-IDF 6.1 (#20779) 2026-10-19 10:33:13 +13:00
puddlyandJ. Nick Koston dd2582bdfd [usb_uart] Expose interface_class and port_number (#20659)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-19 10:33:13 +13:00
J. Nick Koston ba575600dc [mqtt] Match subscription topics in a loop instead of recursing per character (#20767) 2026-10-19 10:33:13 +13:00
esphome[bot] cd6c0dd402 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-19 10:33:13 +13:00
4645d34e1a [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-19 10:33:13 +13:00
dff1422e36 [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-19 10:33:13 +13:00
Jesse Hills 9d530f5c56 Merge pull request #20680 from esphome/bump-2026.10.0b4
2026.10.0b4
2026-10-14 11:14:49 +13:00
Jesse Hills 5a78f636b9 Bump version to 2026.10.0b4 2026-10-14 10:43:50 +13:00
tomaszduda23andClaude 53d504137b [nrf52] Accept S140 7.2.0 and 7.3.0 in the sd140_v7 DFU package (#20661)
Co-authored-by: Claude <noreply@anthropic.com>
2026-10-14 10:43:49 +13:00
bb0546fc0b [script] Keep the running script.wait item out of the queue while its chain runs (#20570)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-10-14 10:43:49 +13:00
emes30andJ. Nick Koston b43630cf8e [rp2_pio] Use pioasm 4.1.0 so PIO programs run on RP2350 (#19260)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-14 10:43:49 +13:00
Firat HajiyevandFirat17aze c9664d4e42 [wifi] Reject unsupported WPA3 on ESP8266 (#20592)
Co-authored-by: Firat17aze <187820330+Firat17aze@users.noreply.github.com>
2026-10-14 10:43:49 +13:00
Kevin Ahrendt 39ea6a3220 [audio] Bump microFLAC to v0.3.0 (#20591) 2026-10-14 10:43:49 +13:00
J. Nick Koston f4a6d6f18b [core] Create the PlatformIO HTTP cache dir before the prefetch resolve threads run (#20579) 2026-10-14 10:43:49 +13:00
esphome[bot] 6c24d4aa43 Bump aioesphomeapi from 46.9.0 to 46.10.0 (#20563) 2026-10-14 10:43:49 +13:00
Jesse Hills 2c4b1f3ed5 Merge pull request #20542 from esphome/bump-2026.10.0b3
2026.10.0b3
2026-10-12 15:42:25 +13:00
J. Nick Koston 0df7b0b366 [core] Move zstd_module from the api wizard to esphome.helpers (#20342) 2026-10-12 12:46:59 +13:00
Jesse Hills bd4b32873a Bump version to 2026.10.0b3 2026-10-12 11:52:33 +13:00
Bascht74 9e580db434 [uart] Reuse the ISR pin argument on an ESP8266 software serial reload (#20541) 2026-10-12 11:52:31 +13:00
Jesse Hills 87187c5391 [api] Let a wizard input pick multiple entities (#20537) 2026-10-12 11:52:31 +13:00
tomaszduda23andClaude 60402614cd [nrf52] fix zigbee time component (#20527)
Co-authored-by: Claude <noreply@anthropic.com>
2026-10-12 11:52:25 +13:00
puddly 2727d35655 [usb_uart] Fix invalid stop bits and parity enum mappings (#20408) 2026-10-12 11:51:44 +13:00
J. Nick Koston fb1ef29d54 [uart] Stop ESP8266 software serial RX ISR from blocking for a whole byte (#18519) 2026-10-12 11:51:39 +13:00
Frédéric MetrichandClaude Opus 5.5 7c0f63ea20 [core] Copy trigger arguments in wait_until and script.wait (#20536)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 11:46:44 +13:00
heikkikiiandJ. Nick Koston 5d75828ceb [seeed_mr24hpc1] Wait for the module to boot before sending UART traffic (#18860)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-12 11:46:44 +13:00
bd2e8d184d [gree] Keep display light on by default for YAN/YAA/YAC/YAC1FB9 (#18516)
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-12 11:46:44 +13:00
J. Nick Koston 3c7ce71d6f [uart_tcp] Prove the accept has run before checking what a new client receives (#20489) 2026-10-12 11:46:44 +13:00
Frédéric MetrichandClaude Opus 5.5 58e03a875f [teleinfo] Fix out-of-bounds read when splitting a frame into groups (#20513)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 11:46:44 +13:00
Clyde StubbsandClaude Opus 5.5 41a9fca881 [ci] Reset sdkconfig after ESP-IDF component discovery (#20511)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 11:46:44 +13:00
ec58e864f5 [canbus] Fix high frame rates causing crashes due to unbounded iteration (#14481)
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-12 11:46:44 +13:00
esphome[bot] 375fbd829e Bump bundled esphome-device-builder to 1.23.1 (#20497) 2026-10-12 11:46:44 +13:00
4bae89bd4a [nrf52] Fix BLE OTA/log device discovery & transport selection on macOS (#17101)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-12 11:46:43 +13:00
Bascht74andJ. Nick Koston 897b2f16a9 [tests] Close leftover server connections in the tcp_uart bridge and TCP client link tests (#20215)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-10-12 11:46:43 +13:00
tomaszduda23 93c8796ae8 [nrf52] fix build error on 3.4.0 with pch ON (#20474) 2026-10-12 11:46:43 +13:00
J. Nick Koston 654afb536e [core] Fix the native ESP8266 and host builds on Windows without ccache (#20468) 2026-10-12 11:46:43 +13:00
jabla 97154f9e5f [espidf] Clean the build when the IDF target changes (#20473) 2026-10-12 11:46:43 +13:00
c9e49b8e8f [teleinfo] Add predefined properties for main tags of TIC standard and historical (#9167)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-10-12 11:42:45 +13:00
J. Nick Koston 3ae52e21cf [usb_host] Warn instead of failing when a device duplicates a usb_uart entry (#20373) 2026-10-12 11:38:38 +13:00
Zhaoqi Xu f2395f9001 [heatpumpir] Fix fan speeds for mitsubishi_msc protocol (#20460) 2026-10-12 11:38:38 +13:00
Ali Alaeiandtomaszduda23 3d248496ab [zephyr_mcumgr] Enable MCUMGR_GRP_OS for UART transport, not just BLE (#18319)
Co-authored-by: tomaszduda23 <tomaszduda23@gmail.com>
2026-10-12 11:38:38 +13:00
esphome[bot] 34eca948c4 Bump bundled esphome-device-builder to 1.23.0 (#20446) 2026-10-12 11:38:37 +13:00
J. Nick Koston 58815575ef [core] Pass a single condition to actions directly instead of wrapping it in a group (#19223) 2026-10-12 11:38:37 +13:00
J. Nick Koston 28b012389d [ci] Keep bus group partners on the same runner (#20431) 2026-10-12 11:38:37 +13:00
J. Nick Koston 54f86537ad [esp32][libretiny] Skip registering static destructors that never run (#20440) 2026-10-12 11:38:37 +13:00
J. Nick Koston 3284d93a33 [nrf52] Fake a larger flash in testing mode (#20439) 2026-10-12 11:38:37 +13:00
J. Nick Koston 01686a5f67 [improv_serial] Use a numeric scheduler id for the Wi-Fi connect timeout (#20360) 2026-10-12 11:38:37 +13:00
J. Nick Koston 3b0c485701 [mqtt] Use a numeric scheduler id for the deferred state publish (#20359) 2026-10-12 11:38:37 +13:00
J. Nick Koston e61d348f0c [wifi] Use numeric scheduler ids instead of string names (#20357) 2026-10-12 11:38:37 +13:00
J. Nick Koston 22e594bc62 [esp32_ble_client] Track conn_id per attempt and stop logging an error on a failed open (#20417) 2026-10-12 11:38:37 +13:00
J. Nick Koston 061733672f [ci] Refit component batch estimates to a full run (#20401) 2026-10-12 11:38:37 +13:00
J. Nick Koston b1f5da9561 [esp8266] Keep ArduinoJson's float tables in flash (Arduino core 3.1.2-esphome.3) (#20416) 2026-10-12 11:38:37 +13:00
J. Nick Koston db517059a3 [ota] Collapse duplicate CI test variants (#20407) 2026-10-12 11:38:37 +13:00
J. Nick Koston 0b40892775 [mcp23xxx_base] Keep the interrupt handler in IRAM on ESP8266 (#20409) 2026-10-12 11:38:37 +13:00
J. Nick Koston 8e6ed71e2a [ethernet] Collapse duplicate CI test variants (#20406) 2026-10-12 11:38:37 +13:00
J. Nick Koston cf569702c4 [ci] Stop the toolchain tests from installing ESP-IDF (#20413) 2026-10-12 11:38:37 +13:00
2194 changed files with 7645 additions and 7928 deletions

No files matched your search

+1 -1
View File
@@ -53,7 +53,7 @@ module.exports = async ({ github, context }) => {
}); });
const currentLabels = currentLabelsData.map(label => label.name); const currentLabels = currentLabelsData.map(label => label.name);
const managedLabels = currentLabels.filter(label => const managedLabels = currentLabels.filter(label =>
label.startsWith('component: ') || label.startsWith('platform: ') || MANAGED_LABELS.includes(label) label.startsWith('component: ') || MANAGED_LABELS.includes(label)
); );
// Check for mega-PR early - if present, skip most automatic labeling // Check for mega-PR early - if present, skip most automatic labeling
+17 -13
View File
@@ -286,7 +286,7 @@ jobs:
fi fi
echo "version=$version" >> "$GITHUB_OUTPUT" echo "version=$version" >> "$GITHUB_OUTPUT"
- name: Run prek - name: Run prek
uses: j178/prek-action@1382ad72dea72f9d53832f2bcb65b3e87a947204 # v3.0.1 uses: j178/prek-action@4e14d07f9231acabce116ccfca13b13dd9755ece # v3.0.0
with: with:
prek-version: ${{ steps.prek.outputs.version }} prek-version: ${{ steps.prek.outputs.version }}
# This job only runs on pull requests, so nothing ever populates # This job only runs on pull requests, so nothing ever populates
@@ -1422,27 +1422,31 @@ jobs:
echo "::warning::ci_memory_impact_extract.py not found on target branch, skipping memory impact analysis" echo "::warning::ci_memory_impact_extract.py not found on target branch, skipping memory impact analysis"
fi fi
# The build below uses --base-only, so skip unless the target branch has # Check if test files exist on the target branch for the requested
# test.<platform>.yaml for every requested component (test-*.yaml # components and platform. When a PR adds new test files for a platform,
# variants alone compile nothing, and a partial set would compare a # the target branch won't have them yet, so skip instead of failing.
# smaller target build against the PR build). Checked here, not in # This check must be done here (not in determine-jobs.py) because
# determine-jobs.py, because determine-jobs runs on the PR branch and # determine-jobs runs on the PR branch and cannot see what the target
# cannot see the target branch. # branch has.
- name: Check for test files on target branch - name: Check for test files on target branch
id: check-tests id: check-tests
if: steps.check-script.outputs.skip != 'true' if: steps.check-script.outputs.skip != 'true'
run: | run: |
components='${{ toJSON(fromJSON(needs.determine-jobs.outputs.memory_impact).components) }}' components='${{ toJSON(fromJSON(needs.determine-jobs.outputs.memory_impact).components) }}'
platform="${{ fromJSON(needs.determine-jobs.outputs.memory_impact).platform }}" platform="${{ fromJSON(needs.determine-jobs.outputs.memory_impact).platform }}"
missing="" found=false
for component in $(echo "$components" | jq -r '.[]'); do for component in $(echo "$components" | jq -r '.[]'); do
if [ ! -f "tests/components/${component}/test.${platform}.yaml" ]; then # Check for test files matching the platform (test.platform.yaml or test-*.platform.yaml)
missing="${missing} ${component}" for f in tests/components/${component}/test*.${platform}.yaml; do
fi if [ -f "$f" ]; then
found=true
break 2
fi
done
done done
if [ -n "$missing" ]; then if [ "$found" = false ]; then
echo "skip=true" >> $GITHUB_OUTPUT echo "skip=true" >> $GITHUB_OUTPUT
echo "::warning::No test.${platform}.yaml on target branch for${missing}, skipping memory impact analysis" echo "::warning::No test files found on target branch for platform ${platform}, skipping memory impact analysis"
else else
echo "skip=false" >> $GITHUB_OUTPUT echo "skip=false" >> $GITHUB_OUTPUT
fi fi
@@ -15,8 +15,6 @@ on:
# base branch checkout, so fork code never runs with the token. # base branch checkout, so fork code never runs with the token.
pull_request_target: pull_request_target:
types: [opened, synchronize, reopened] types: [opened, synchronize, reopened]
branches:
- dev
paths: paths:
- requirements_dev.txt - requirements_dev.txt
- requirements_test.txt - requirements_test.txt
-31
View File
@@ -177,13 +177,6 @@ file does, and it is the authority when they disagree. The most useful starting
Pick the primitive by cadence: under 250 ms use a gated `loop()`; 500 ms and above use Pick the primitive by cadence: under 250 ms use a gated `loop()`; 500 ms and above use
`set_interval`. Full reasoning, including why `set_interval` costs more below 500 ms: `set_interval`. Full reasoning, including why `set_interval` costs more below 500 ms:
https://developers.esphome.io/architecture/components/advanced/#quick-rule-of-thumb https://developers.esphome.io/architecture/components/advanced/#quick-rule-of-thumb
* **Scheduler ids:** name a timer only when it must be cancelled or replaced, and use a
`static constexpr uint32_t` id, never a string. Ids are per component instance and cannot clash with other
components, so number them from 0 and keep all of a component's ids together in one place.
```cpp
static constexpr uint32_t READ_TIMEOUT_ID = 0;
this->set_timeout(READ_TIMEOUT_ID, 50, [this]() { this->read_(); });
```
* **Don't override a default with the same value:** if a base class method already returns what you * **Don't override a default with the same value:** if a base class method already returns what you
want, do not override it. `Component::get_setup_priority()` returns `setup_priority::DATA`, so a want, do not override it. `Component::get_setup_priority()` returns `setup_priority::DATA`, so a
component that wants `DATA` should simply leave it alone. component that wants `DATA` should simply leave it alone.
@@ -237,10 +230,6 @@ file does, and it is the authority when they disagree. The most useful starting
``` ```
* **Component Metadata:** * **Component Metadata:**
- `DOMAIN`: Required in every component's `__init__.py`, set to the component's own name as a plain
string (e.g. `DOMAIN = "my_component"`). Other code refers to the component through it, e.g.
`from esphome.components.my_component import DOMAIN`. Keep it in alphabetical order with the other
metadata constants. CI (`lint_component_domain`) fails without it.
- `DEPENDENCIES`: List of required components - `DEPENDENCIES`: List of required components
- `AUTO_LOAD`: Components to automatically load - `AUTO_LOAD`: Components to automatically load
- `CONFLICTS_WITH`: Incompatible components - `CONFLICTS_WITH`: Incompatible components
@@ -254,7 +243,6 @@ file does, and it is the authority when they disagree. The most useful starting
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.const import CONF_KEY, CONF_ID from esphome.const import CONF_KEY, CONF_ID
DOMAIN = "my_component"
CONF_PARAM = "param" # A constant that does not yet exist in esphome/const.py CONF_PARAM = "param" # A constant that does not yet exist in esphome/const.py
my_component_ns = cg.esphome_ns.namespace("my_component") my_component_ns = cg.esphome_ns.namespace("my_component")
@@ -396,25 +384,6 @@ file does, and it is the authority when they disagree. The most useful starting
) )
``` ```
When the callback's parameters differ from the automation's arguments, or the trigger should only
fire for some values, pass `params`, `forward` and `when`; the helper then generates a capture-less
lambda (stored inline, nothing allocated). Name the parent with `automation.parent_ref(var)` and build
`forward` from `MockObj` calls, not f-strings of C++:
```python
parent = automation.parent_ref(var)
index = cg.RawExpression("index")
await automation.build_callback_automation(
var,
"add_on_state_callback",
[(cg.StringRef, "x"), (cg.size_t, "i")],
conf,
params=[(cg.size_t, "index")],
forward=[cg.StringRef(parent.option_at(index)), index],
)
```
`build_parent_callback_automation`, `build_trigger_callback`, `build_callback_automations` and
`build_trigger_automations` cover the other shapes; see their docstrings in `esphome/automation.py`.
**C++ -- no trigger class needed.** The callback registration method must be templatized to accept both `std::function` and lightweight forwarder structs (which avoid heap allocation): **C++ -- no trigger class needed.** The callback registration method must be templatized to accept both `std::function` and lightweight forwarder structs (which avoid heap allocation):
```cpp ```cpp
class MyComponent : public Component { class MyComponent : public Component {
+1 -3
View File
@@ -188,7 +188,6 @@ esphome/components/esp32_rmt_led_strip/* @jesserockz
esphome/components/esp8266/* @esphome/core esphome/components/esp8266/* @esphome/core
esphome/components/esp_ldo/* @clydebarrow esphome/components/esp_ldo/* @clydebarrow
esphome/components/espectre/* @francescopace esphome/components/espectre/* @francescopace
esphome/components/esphome/ota/* @esphome/core
esphome/components/espnow/* @jesserockz esphome/components/espnow/* @jesserockz
esphome/components/espnow/packet_transport/* @EasilyBoredEngineer esphome/components/espnow/packet_transport/* @EasilyBoredEngineer
esphome/components/ethernet_info/* @gtjadsonsantos esphome/components/ethernet_info/* @gtjadsonsantos
@@ -519,7 +518,6 @@ esphome/components/sound_level/* @kahrendt
esphome/components/spa06_base/* @danielkent-net esphome/components/spa06_base/* @danielkent-net
esphome/components/spa06_i2c/* @danielkent-net esphome/components/spa06_i2c/* @danielkent-net
esphome/components/spa06_spi/* @danielkent-net esphome/components/spa06_spi/* @danielkent-net
esphome/components/spd2010/* @grischard
esphome/components/speaker/* @jesserockz @kahrendt esphome/components/speaker/* @jesserockz @kahrendt
esphome/components/speaker/media_player/* @kahrendt @synesthesiam esphome/components/speaker/media_player/* @kahrendt @synesthesiam
esphome/components/speaker_source/* @kahrendt esphome/components/speaker_source/* @kahrendt
@@ -570,7 +568,7 @@ esphome/components/tca9555/* @mobrembski
esphome/components/tcl112/* @glmnet esphome/components/tcl112/* @glmnet
esphome/components/tcp_uart/* @Bascht74 esphome/components/tcp_uart/* @Bascht74
esphome/components/tee501/* @Stock-M esphome/components/tee501/* @Stock-M
esphome/components/teleinfo/* @0hax esphome/components/teleinfo/* @0hax @FredM67
esphome/components/tem3200/* @bakerkj esphome/components/tem3200/* @bakerkj
esphome/components/template/alarm_control_panel/* @grahambrown11 @hwstar esphome/components/template/alarm_control_panel/* @grahambrown11 @hwstar
esphome/components/template/datetime/* @rfdarter esphome/components/template/datetime/* @rfdarter
+1 -1
View File
@@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome
# could be handy for archiving the generated documentation or if some version # could be handy for archiving the generated documentation or if some version
# control system is used. # control system is used.
PROJECT_NUMBER = 2026.11.0-dev PROJECT_NUMBER = 2026.10.0b6
# Using the PROJECT_BRIEF tag one can provide an optional one line description # Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a # for a project that appears at the top of each page and should give viewer a
+1 -1
View File
@@ -22,7 +22,7 @@ RUN \
-r /requirements.txt -r /requirements.txt
# Install the ESPHome Device Builder dashboard. # Install the ESPHome Device Builder dashboard.
RUN uv pip install --no-cache-dir esphome-device-builder==1.23.0 RUN uv pip install --no-cache-dir esphome-device-builder==1.25.0
RUN \ RUN \
platformio settings set enable_telemetry No \ platformio settings set enable_telemetry No \
+11 -11
View File
@@ -58,31 +58,31 @@ FRAMEWORK_RELEASES: dict[Version, FrameworkRelease] = {
TOOLCHAIN_PACKAGE = "toolchain-xtensa-lx106-elf" TOOLCHAIN_PACKAGE = "toolchain-xtensa-lx106-elf"
# gcc 10.3, the toolchain Arduino core 3.x builds with; the build # gcc 10.3, the toolchain Arduino core 3.x builds with; the build
# generator's compile flags are tuned to it. # generator's compile flags are tuned to it.
TOOLCHAIN_VERSION = "10.3.0-esphome.3" TOOLCHAIN_VERSION = "10.3.0-esphome.2"
_TOOLCHAIN_RELEASES = ( _TOOLCHAIN_RELEASES = (
"https://github.com/esphome-libs/xtensa-lx106-elf-toolchain/releases/" "https://github.com/esphome-libs/xtensa-lx106-elf-toolchain/releases/"
) )
# Registry system tag -> (sha256, size) of that host's archive # Registry system tag -> (sha256, size) of that host's archive
TOOLCHAIN_BUILDS: dict[str, tuple[str, int]] = { TOOLCHAIN_BUILDS: dict[str, tuple[str, int]] = {
"darwin_arm64": ( "darwin_arm64": (
"ad0ea929238d9b527c43e0d20257acc2a5680bdb0d2b1cf8f2c99169786217e9", "849cede44d4d5c6ea0f14099783239f559f46327bea314281814f2652b486201",
60747260, 60830321,
), ),
"darwin_x86_64": ( "darwin_x86_64": (
"997090cac80c8eb59604ec52b73fb3568e5f2d9b2971f83c3f2a5c545c9c949c", "ca69904daabf0c5983b372423e5e62f49182a793e992c052e94666852470c897",
64065752, 64149487,
), ),
"linux_aarch64": ( "linux_aarch64": (
"403f14d0d5755682fcd6eaea1e4c457a1d8cad30690e52fb0c804d8db266b908", "60a49a4f082bf246544bd409a9517dbbcab19bb30ac9decbee544b896aaccbd6",
67487067, 67573397,
), ),
"linux_x86_64": ( "linux_x86_64": (
"64f21fa3ba736b363dc8c234dbbb39e005e574e33de08a78e9a00c55a64ae706", "1fba33ca1494ec79f2776e0e37eca93282d30f8bb9992f5f4f9a655d6fff1db4",
68343668, 68431336,
), ),
"windows_amd64": ( "windows_amd64": (
"1e62abf8df041ce5158f5770dffef955f2f981ce7f7adee88fcd5a8197705aa6", "af9066b0e5bf036f04f2bd9d08b89b81a7f183c57dac0abcaff71dd861cf5f3b",
67536405, 67664137,
), ),
} }
+38 -173
View File
@@ -1,4 +1,4 @@
from collections.abc import Callable, Sequence from collections.abc import Callable
from dataclasses import dataclass, field from dataclasses import dataclass, field
import logging import logging
import string import string
@@ -23,7 +23,7 @@ from esphome.const import (
) )
from esphome.core import CORE, ID, EsphomeError, HexInt, Lambda from esphome.core import CORE, ID, EsphomeError, HexInt, Lambda
from esphome.cpp_generator import ( from esphome.cpp_generator import (
Expression, FlashStringLiteral,
LambdaExpression, LambdaExpression,
MockObj, MockObj,
MockObjClass, MockObjClass,
@@ -245,7 +245,9 @@ ApplyCondition = cg.esphome_ns.class_("ApplyCondition", Condition)
def flash_string(config: ConfigType, value: str) -> str: def flash_string(config: ConfigType, value: str) -> str:
"""Default renderer for ``std::string`` constants; copies the literal out of flash on ESP8266.""" """Default renderer for ``std::string`` constants; copies the literal out of flash on ESP8266."""
return str(cg.progmem_string(value)) if CORE.is_esp8266:
return f"progmem_string({FlashStringLiteral(value)})"
return str(cg.safe_exp(value))
def literal_with_length(config: ConfigType, value: str) -> str: def literal_with_length(config: ConfigType, value: str) -> str:
@@ -257,24 +259,13 @@ def literal_with_length(config: ConfigType, value: str) -> str:
return f"{cg.safe_exp(value)}, {len(value.encode('utf-8'))}" return f"{cg.safe_exp(value)}, {len(value.encode('utf-8'))}"
def string_ref_literal(config: ConfigType, value: str) -> str:
"""Renderer for a ``StringRef`` comparison: a flash literal on ESP8266, else ``StringRef(literal, length)``."""
if CORE.is_esp8266:
return str(cg.FlashStringLiteral(value))
return f"StringRef({literal_with_length(config, value)})"
def _names_parent(text: str) -> bool:
return any(f == "parent" for _, f, _, _ in string.Formatter().parse(text))
@dataclass(frozen=True) @dataclass(frozen=True)
class ApplyCall: class ApplyCall:
"""One statement from config keys, e.g. ``"set_range({}, {})"`` with ``((CONF_LOW, cg.float_), ...)``. """One statement from config keys, e.g. ``"set_range({}, {})"`` with ``((CONF_LOW, cg.float_), ...)``.
Each arg is ``(conf_key, type_)`` or ``(conf_key, type_, const_fn)``. A ``conf_key`` may be a Each arg is ``(conf_key, type_)`` or ``(conf_key, type_, const_fn)``. A ``conf_key`` may be a
path into nested sections. ``target`` and a plain ``str`` ``type_`` (raw C++ type text) may path into nested sections. A plain ``str`` ``type_`` is raw C++ type text and may use
name the parent object as ``{parent}``. ``const_fn(config, value)`` renders a constant's argument text; a lambda or an ``{parent}``. ``const_fn(config, value)`` renders a constant's argument text; a lambda or an
id bypasses it. The statement is skipped when none of its keys is set, always emitted when it id bypasses it. The statement is skipped when none of its keys is set, always emitted when it
has no keys, and a partial set is a config error. has no keys, and a partial set is a config error.
""" """
@@ -286,13 +277,13 @@ class ApplyCall:
fields = [ fields = [
f for _, f, _, _ in string.Formatter().parse(self.target) if f is not None f for _, f, _, _ in string.Formatter().parse(self.target) if f is not None
] ]
if any(f not in ("", "parent") for f in fields): if any(fields):
raise ValueError( raise ValueError(
f"apply target {self.target!r}: only {{}} and {{parent}} placeholders" f"apply target {self.target!r}: only bare {{}} placeholders"
) )
if (count := fields.count("")) != len(self.args): if len(fields) != len(self.args):
raise ValueError( raise ValueError(
f"apply target {self.target!r} has {count} " f"apply target {self.target!r} has {len(fields)} "
f"placeholder(s) for {len(self.args)} config key(s)" f"placeholder(s) for {len(self.args)} config key(s)"
) )
if any(len(arg) not in (2, 3) for arg in self.args): if any(len(arg) not in (2, 3) for arg in self.args):
@@ -300,12 +291,6 @@ class ApplyCall:
f"apply target {self.target!r}: each arg is (conf_key, type_[, const_fn])" f"apply target {self.target!r}: each arg is (conf_key, type_[, const_fn])"
) )
@property
def names_parent(self) -> bool:
return _names_parent(self.target) or any(
isinstance(arg[1], str) and _names_parent(arg[1]) for arg in self.args
)
@property @property
def members(self) -> list[tuple[Any, Any, Any]]: def members(self) -> list[tuple[Any, Any, Any]]:
"""Each arg as ``(conf_key, type_, const_fn or None)``.""" """Each arg as ``(conf_key, type_, const_fn or None)``."""
@@ -380,16 +365,9 @@ def _check_key_in_schema(
schema = schema.schema[markers[part]] schema = schema.schema[markers[part]]
def parent_ref(var: MockObj) -> MockObj:
"""``var`` named from global scope, so a trigger argument cannot shadow it.
Also how a generated callback names its Automation.
"""
return MockObj(f"::{var}", "->")
async def _apply_parent(config: ConfigType, id_key: str = CONF_ID) -> str: async def _apply_parent(config: ConfigType, id_key: str = CONF_ID) -> str:
return str(parent_ref(await cg.get_variable(config[id_key]))) # Global-scope qualified so a trigger arg named like the id cannot shadow it.
return f"::{await cg.get_variable(config[id_key])}"
def _apply_lambda_args(args: TemplateArgsType) -> TemplateArgsType: def _apply_lambda_args(args: TemplateArgsType) -> TemplateArgsType:
@@ -421,7 +399,7 @@ async def _render_values(
members: list[tuple[Any, Any, Any]], members: list[tuple[Any, Any, Any]],
values: list[Any], values: list[Any],
config: ConfigType, config: ConfigType,
parent: str | None, parent: str,
lambda_args: TemplateArgsType, lambda_args: TemplateArgsType,
compare: bool = False, compare: bool = False,
) -> list[str]: ) -> list[str]:
@@ -499,12 +477,12 @@ def register_apply_action(
statements: list[str] = [] statements: list[str] = []
for target, members in statements_spec: for target, members in statements_spec:
values = _apply_values(config, members) values = _apply_values(config, members)
if not _apply_call_active(members, values): if members and all(value is None for value in values):
continue continue
exprs = await _render_values( exprs = await _render_values(
name, target, members, values, config, parent, lambda_args name, target, members, values, config, parent, lambda_args
) )
statements.append(f"{receiver}{target.format(*exprs, parent=parent)};") statements.append(f"{receiver}{target.format(*exprs)};")
if call: if call:
statements = [ statements = [
f"auto apply_call = {parent}->{call}();", f"auto apply_call = {parent}->{call}();",
@@ -518,27 +496,6 @@ def register_apply_action(
register_action(name, ApplyAction, schema, synchronous=True)(builder) register_action(name, ApplyAction, schema, synchronous=True)(builder)
def _apply_call_active(members: list[tuple[Any, Any, Any]], values: list[Any]) -> bool:
"""An ``ApplyCall`` is emitted unless it has keys and none of them is set."""
return not members or any(value is not None for value in values)
async def _render_check(
name: str,
target: str,
members: list[tuple[Any, Any, Any]],
values: list[Any],
config: ConfigType,
parent: str | None,
lambda_args: TemplateArgsType,
) -> str:
"""Render a boolean check with ``values`` compared against config."""
exprs = await _render_values(
name, target, members, values, config, parent, lambda_args, compare=True
)
return target.format(*exprs, parent=parent)
def register_apply_condition( def register_apply_condition(
name: str, schema: cv.Schema, check: str | ApplyCall, id_key: str = CONF_ID name: str, schema: cv.Schema, check: str | ApplyCall, id_key: str = CONF_ID
) -> None: ) -> None:
@@ -564,16 +521,22 @@ def register_apply_condition(
) -> MockObj: ) -> MockObj:
parent = await _apply_parent(config, id_key) parent = await _apply_parent(config, id_key)
lambda_args = _apply_lambda_args(args) lambda_args = _apply_lambda_args(args)
values = _apply_values(config, members) exprs = await _render_values(
check = await _render_check( name,
name, call.target, members, values, config, parent, lambda_args call.target,
members,
_apply_values(config, members),
config,
parent,
lambda_args,
compare=True,
) )
return _apply_function( return _apply_function(
condition_id, condition_id,
cg.bool_, cg.bool_,
template_arg, template_arg,
lambda_args, lambda_args,
[f"return {parent}->{check};"], [f"return {parent}->{call.target.format(*exprs)};"],
) )
register_condition(name, ApplyCondition, schema)(builder) register_condition(name, ApplyCondition, schema)(builder)
@@ -1048,67 +1011,15 @@ def has_non_synchronous_actions(actions: ConfigType) -> bool:
return False return False
async def _new_automation(
args: TemplateArgsType, config: ConfigType, *ctor_args: MockObj
) -> MockObj:
"""Create the Automation for ``config`` with its actions."""
templ = cg.TemplateArguments(*(arg[0] for arg in args))
obj = cg.new_Pvariable(config[CONF_AUTOMATION_ID], templ, *ctor_args)
actions = await build_action_list(config[CONF_THEN], templ, args)
cg.add(obj.add_actions(actions))
return obj
async def build_automation( async def build_automation(
trigger: MockObj, args: TemplateArgsType, config: ConfigType trigger: MockObj, args: TemplateArgsType, config: ConfigType
) -> MockObj: ) -> MockObj:
return await _new_automation(args, config, trigger) arg_types = [arg[0] for arg in args]
templ = cg.TemplateArguments(*arg_types)
obj = cg.new_Pvariable(config[CONF_AUTOMATION_ID], templ, trigger)
async def build_trigger_callback( actions = await build_action_list(config[CONF_THEN], templ, args)
args: TemplateArgsType, cg.add(obj.add_actions(actions))
config: ConfigType, return obj
params: TemplateArgsType,
forward: Sequence[str | Expression] | None = None,
when: str | ApplyCall | None = None,
parent: MockObj | None = None,
) -> LambdaExpression:
"""Build the Automation for ``config`` and return a stateless callback that triggers it.
``params`` are the parent callback's parameters, ``forward`` the expressions passed to
``trigger()`` (default: the parameter names; write the parent as ``parent_ref(var)``),
``when`` a filter the callback returns early on, skipped like any ``ApplyCall`` when none
of its keys is set. ``when`` may name ``parent`` as ``{parent}``, e.g.
``"{parent}->is_fully_open()"``.
"""
members: list[tuple[Any, Any, Any]] = []
if when is not None:
call = when if isinstance(when, ApplyCall) else ApplyCall(when)
members = call.members
if parent is None and call.names_parent:
raise ValueError(f"trigger filter {call.target!r} names {{parent}}")
obj = await _new_automation(args, config)
lambda_args = _apply_lambda_args(params)
statements: list[str] = []
if when is not None:
values = _apply_values(config, members)
if _apply_call_active(members, values):
check = await _render_check(
"trigger filter",
call.target,
members,
values,
config,
None if parent is None else str(parent_ref(parent)),
lambda_args,
)
statements.append(f"if (!({check}))\n return;")
if forward is None:
forward = [name for _, name in params]
statements.append(f"{parent_ref(obj)}->trigger({', '.join(map(str, forward))});")
return LambdaExpression(
["\n".join(statements)], lambda_args, capture="", return_type=cg.void
)
async def build_callback_automation( async def build_callback_automation(
@@ -1117,9 +1028,6 @@ async def build_callback_automation(
args: TemplateArgsType, args: TemplateArgsType,
config: ConfigType, config: ConfigType,
forwarder: MockObj | MockObjClass | None = None, forwarder: MockObj | MockObjClass | None = None,
params: TemplateArgsType | None = None,
forward: Sequence[str | Expression] | None = None,
when: str | ApplyCall | None = None,
) -> None: ) -> None:
"""Build an Automation and register it as a callback on the parent. """Build an Automation and register it as a callback on the parent.
@@ -1131,9 +1039,6 @@ async def build_callback_automation(
pointer-sized (single Automation* field) to fit inline in Callback::ctx_ pointer-sized (single Automation* field) to fit inline in Callback::ctx_
and avoid heap allocation. and avoid heap allocation.
With ``params``, ``forward`` or ``when`` the callback is instead the stateless
lambda of ``build_trigger_callback``; ``forwarder`` cannot be combined with them.
:param parent: The component object (e.g., button, sensor). :param parent: The component object (e.g., button, sensor).
:param callback_method: Name of the callback method (e.g., "add_on_press_callback"). :param callback_method: Name of the callback method (e.g., "add_on_press_callback").
:param args: Automation template args as list of (type, name) tuples. :param args: Automation template args as list of (type, name) tuples.
@@ -1142,56 +1047,22 @@ async def build_callback_automation(
TriggerForwarder<Ts...>. Pass any struct type whose aggregate init takes TriggerForwarder<Ts...>. Pass any struct type whose aggregate init takes
a single Automation pointer (e.g., TriggerOnTrueForwarder). a single Automation pointer (e.g., TriggerOnTrueForwarder).
""" """
if params is not None or forward is not None or when is not None: arg_types = [arg[0] for arg in args]
if forwarder is not None: templ = cg.TemplateArguments(*arg_types)
raise ValueError( obj = cg.new_Pvariable(config[CONF_AUTOMATION_ID], templ)
"forwarder cannot be combined with params, forward or when" actions = await build_action_list(config[CONF_THEN], templ, args)
) cg.add(obj.add_actions(actions))
callback = await build_trigger_callback(
args, config, args if params is None else params, forward, when, parent
)
cg.add(getattr(parent, callback_method)(callback))
return
obj = await _new_automation(args, config)
# Use template forwarder structs for deduplication. The compiler generates # Use template forwarder structs for deduplication. The compiler generates
# one operator() per forwarder type; different automation pointers are just # one operator() per forwarder type; different automation pointers are just
# data in the struct. # data in the struct.
if forwarder is None: if forwarder is None:
forwarder = TriggerForwarder.template(*(arg[0] for arg in args)) forwarder = TriggerForwarder.template(templ)
# RawExpression for aggregate init — both forwarder and obj are codegen # RawExpression for aggregate init — both forwarder and obj are codegen
# MockObjs (not user input), and there's no Expression type for positional # MockObjs (not user input), and there's no Expression type for positional
# aggregate initialization (StructInitializer uses named fields). # aggregate initialization (StructInitializer uses named fields).
cg.add(getattr(parent, callback_method)(cg.RawExpression(f"{forwarder}{{{obj}}}"))) cg.add(getattr(parent, callback_method)(cg.RawExpression(f"{forwarder}{{{obj}}}")))
async def build_parent_callback_automation(
parent: MockObj, callback_method: str, arg: tuple[Any, str], config: ConfigType
) -> None:
"""Register an Automation that receives ``parent`` from a callback that carries nothing.
``arg`` is the automation's ``(type, name)``, e.g. ``(Fan.operator("ptr"), "x")``.
"""
await build_callback_automation(
parent, callback_method, [arg], config, params=[], forward=[parent_ref(parent)]
)
async def build_trigger_automations(
parent: MockObj | None,
config: ConfigType,
entries: tuple[tuple[str, TemplateArgsType], ...],
) -> None:
"""Instantiate each entry's Trigger class, with ``parent`` when given, and build its automations.
``entries`` are ``(conf_key, args)`` pairs; the class comes from the entry's ``CONF_TRIGGER_ID``.
"""
ctor_args = () if parent is None else (parent,)
for conf_key, args in entries:
for conf in config.get(conf_key, []):
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], *ctor_args)
await build_automation(trigger, args, conf)
@dataclass(frozen=True, slots=True) @dataclass(frozen=True, slots=True)
class CallbackAutomation: class CallbackAutomation:
"""A single callback automation entry for build_callback_automations.""" """A single callback automation entry for build_callback_automations."""
@@ -1200,9 +1071,6 @@ class CallbackAutomation:
callback_method: str callback_method: str
args: TemplateArgsType = field(default_factory=list) args: TemplateArgsType = field(default_factory=list)
forwarder: MockObj | MockObjClass | None = None forwarder: MockObj | MockObjClass | None = None
params: TemplateArgsType | None = None
forward: Sequence[str | Expression] | None = None
when: str | ApplyCall | None = None
async def build_callback_automations( async def build_callback_automations(
@@ -1224,7 +1092,4 @@ async def build_callback_automations(
entry.args, entry.args,
conf, conf,
forwarder=entry.forwarder, forwarder=entry.forwarder,
params=entry.params,
forward=entry.forward,
when=entry.when,
) )
+1 -1
View File
@@ -1057,7 +1057,7 @@ def write_project(paths: InstalledPaths, ccache: str | None) -> bool:
cxx = (toolchain_tool(paths.toolchain, "g++"),) cxx = (toolchain_tool(paths.toolchain, "g++"),)
lines = [ lines = [
*tool_lines((toolchain_tool(paths.toolchain, "gcc"),), cxx, ccache), *tool_lines((toolchain_tool(paths.toolchain, "gcc"),), cxx, ccache),
*compile_rule_lines(), *compile_rule_lines(ccache),
*ar_rule_lines(toolchain_tool(paths.toolchain, "ar")), *ar_rule_lines(toolchain_tool(paths.toolchain, "ar")),
*pch_rule_lines(), *pch_rule_lines(),
"rule link", "rule link",
+15 -51
View File
@@ -237,35 +237,6 @@ def idf_macro_matches(idf_path: Path) -> bool:
return live == _EXPECTED_MACRO return live == _EXPECTED_MACRO
def _cmake_args_for_write(minimal: bool) -> dict[str, str]:
"""The cg.add_cmake_arg() values for one project write.
The discovery (minimal) write lets every built-in component register so
the list it finds, cached per target, serves any exclusion set; the full
write drops the excluded names from that list and passes all of them to
IDF. Names outside the framework's components directory (managed
components) stay excluded on the discovery write too, since the list
only holds built-in ones. A checkout supplied through IDF_PATH caches
nothing, so its discovery keeps every exclusion.
"""
from esphome.espidf.toolchain import _esphome_manages_idf, _get_idf_path
args = dict(CORE.cmake_args)
if (
not minimal
or not _esphome_manages_idf()
or not (excluded := args.get("EXCLUDE_COMPONENTS"))
):
return args
root = _get_idf_path() / "components"
outside = [name for name in excluded.split(";") if not (root / name).is_dir()]
if outside:
args["EXCLUDE_COMPONENTS"] = ";".join(outside)
else:
del args["EXCLUDE_COMPONENTS"]
return args
def get_project_cmakelists( def get_project_cmakelists(
minimal: bool = False, builtin_components: list[str] | None = None minimal: bool = False, builtin_components: list[str] | None = None
) -> str: ) -> str:
@@ -329,10 +300,11 @@ def get_project_cmakelists(
# CMake variables registered via cg.add_cmake_arg(). Emitted before # CMake variables registered via cg.add_cmake_arg(). Emitted before
# include(project.cmake) so values like EXCLUDE_COMPONENTS are already # include(project.cmake) so values like EXCLUDE_COMPONENTS are already
# set when project.cmake seeds the component list. # set when project.cmake seeds the component list, and on minimal
# (discovery) writes too so excluded components never register.
cmake_args = "\n".join( cmake_args = "\n".join(
f"set({name} {_cmake_quote(value)})" f"set({name} {_cmake_quote(value)})"
for name, value in sorted(_cmake_args_for_write(minimal).items()) for name, value in sorted(CORE.cmake_args.items())
) )
# Per-project list exposed as a CMake variable so converted PIO libs # Per-project list exposed as a CMake variable so converted PIO libs
@@ -355,10 +327,10 @@ def get_project_cmakelists(
# component's REQUIRES including real IDF components). Referenced by # component's REQUIRES including real IDF components). Referenced by
# src/CMakeLists and by each converted PIO lib's CMakeLists. Skipped # src/CMakeLists and by each converted PIO lib's CMakeLists. Skipped
# on minimal writes because project_description.json may be stale. # on minimal writes because project_description.json may be stale.
# Excluded components are dropped here as well: the discovery list # Excluded components are dropped here as well: a stale
# (cached per target) still holds them, and requiring an excluded # project_description.json from a build without exclusions may still
# component pulls it back into the build (IDF requirement expansion # list them, and requiring an excluded component pulls it back into
# overrides EXCLUDE_COMPONENTS). # the build (IDF requirement expansion overrides EXCLUDE_COMPONENTS).
# Derived from the EXCLUDE_COMPONENTS cmake arg emitted above so the # Derived from the EXCLUDE_COMPONENTS cmake arg emitted above so the
# two can never disagree within one generated file. # two can never disagree within one generated file.
builtin_components_property = ( builtin_components_property = (
@@ -425,24 +397,15 @@ project({CORE.name})
# Emit per-memory-type JSON size data for ESPHome to read post-build. # Emit per-memory-type JSON size data for ESPHome to read post-build.
# json2 stays small; raw dumps every symbol (~2s on a large map) and # json2 stays small; raw dumps every symbol (~2s on a large map) and
# this command runs inside the link edge, blocking everything downstream. # this command runs inside the link edge, blocking everything downstream.
# IDF's size target depends on the map, so ninja has to know the link # The map is a BYPRODUCT so ninja knows the link writes it; IDF's size
# writes it for size to build in the same run as all. IDF declares the # target depends on the map and can then be built in the same run as all.
# map itself since espressif/esp-idf#19201 (and in cmakev2), and ninja # IDF's cmakev2 declares the map itself, so drop this line on that switch.
# rejects two rules for one output, so declare it here only when IDF has
# not. add_custom_command(OUTPUT) marks its outputs GENERATED.
get_source_file_property(esphome_map_declared
${{CMAKE_BINARY_DIR}}/${{CMAKE_PROJECT_NAME}}.map GENERATED)
if(esphome_map_declared)
set(esphome_map_byproducts)
else()
set(esphome_map_byproducts BYPRODUCTS ${{CMAKE_BINARY_DIR}}/${{CMAKE_PROJECT_NAME}}.map)
endif()
add_custom_command( add_custom_command(
TARGET ${{CMAKE_PROJECT_NAME}}.elf POST_BUILD TARGET ${{CMAKE_PROJECT_NAME}}.elf POST_BUILD
COMMAND ${{PYTHON}} -m esp_idf_size {size_ng_flag} --format=json2 COMMAND ${{PYTHON}} -m esp_idf_size {size_ng_flag} --format=json2
-o ${{CMAKE_BINARY_DIR}}/esp_idf_size.json -o ${{CMAKE_BINARY_DIR}}/esp_idf_size.json
${{CMAKE_PROJECT_NAME}}.map ${{CMAKE_PROJECT_NAME}}.map
${{esphome_map_byproducts}} BYPRODUCTS ${{CMAKE_BINARY_DIR}}/${{CMAKE_PROJECT_NAME}}.map
WORKING_DIRECTORY ${{CMAKE_BINARY_DIR}} WORKING_DIRECTORY ${{CMAKE_BINARY_DIR}}
VERBATIM VERBATIM
) )
@@ -591,9 +554,10 @@ def write_project(
) )
# Snapshot the exclusion set so has_outdated_files() can trigger a # Snapshot the exclusion set so has_outdated_files() can trigger a
# reconfigure when it changes. The ESPHOME_PROJECT_BUILTIN_COMPONENTS # discovery reconfigure when it changes. Excluded components never
# property drops excluded names, so re-including one (e.g. a config # register in project_description.json, so re-including one (e.g. a
# gains mqtt) needs a reconfigure to rebuild it from the discovery list. # config gains mqtt) requires a fresh discovery pass before the
# ESPHOME_PROJECT_BUILTIN_COMPONENTS property can list it.
write_file_if_changed( write_file_if_changed(
CORE.relative_build_path("exclude_components.esphomeinternal"), CORE.relative_build_path("exclude_components.esphomeinternal"),
";".join(get_excluded_builtin_components()), ";".join(get_excluded_builtin_components()),
+1 -1
View File
@@ -240,7 +240,7 @@ def write_project(compilers: HostCompilers, ccache: str | None) -> bool:
lines = [ lines = [
*tool_lines(compilers.cc, compilers.cxx, ccache), *tool_lines(compilers.cc, compilers.cxx, ccache),
*compile_rule_lines(), *compile_rule_lines(ccache),
*pch_rule_lines(), *pch_rule_lines(),
"rule link", "rule link",
" command = $cxx -o $out $linkflags @$out.rsp $archives $libdirflags $libflags", " command = $cxx -o $out $linkflags @$out.rsp $archives $libdirflags $libflags",
+14 -7
View File
@@ -74,33 +74,40 @@ def tool_lines(
# path gets # path gets
f"python = {_q(strip_win_long_path_prefix(sys.executable))}", f"python = {_q(strip_win_long_path_prefix(sys.executable))}",
f"buildtool = {_q(_BUILD_TOOL)}", f"buildtool = {_q(_BUILD_TOOL)}",
f"ccache = {_q(ccache) if ccache else ''}", *([f"ccache = {_q(ccache)}"] if ccache else []),
"", "",
] ]
def compile_rule_lines() -> list[str]: def compile_rule_lines(ccache: str | None) -> list[str]:
"""The compile rules; ``$own_includes`` is empty unless an edge sets it.""" """The compile rules; ``$own_includes`` is empty unless an edge sets it.
``ccache`` is the launcher ``tool_lines`` was given; the same test here
keeps the variable and the rules in step. It is spliced in rather than
left as an empty variable: a leading space on the command line makes
CreateProcess fail on Windows.
"""
launcher = "$ccache " if ccache else ""
return [ return [
"rule c", "rule c",
" command = $ccache $cc -MMD -MF $out.d $own_includes $cflags $flags -c $in -o $out", f" command = {launcher}$cc -MMD -MF $out.d $own_includes $cflags $flags -c $in -o $out",
" depfile = $out.d", " depfile = $out.d",
" deps = gcc", " deps = gcc",
" description = CC $out", " description = CC $out",
"rule cxx", "rule cxx",
" command = $ccache $cxx -MMD -MF $out.d $own_includes $cxxflags $flags -c $in -o $out", f" command = {launcher}$cxx -MMD -MF $out.d $own_includes $cxxflags $flags -c $in -o $out",
" depfile = $out.d", " depfile = $out.d",
" deps = gcc", " deps = gcc",
" description = CXX $out", " description = CXX $out",
"rule aspp", "rule aspp",
" command = $ccache $cc -MMD -MF $out.d -x assembler-with-cpp $own_includes $asflags $flags -c $in -o $out", f" command = {launcher}$cc -MMD -MF $out.d -x assembler-with-cpp $own_includes $asflags $flags -c $in -o $out",
" depfile = $out.d", " depfile = $out.d",
" deps = gcc", " deps = gcc",
" description = AS $out", " description = AS $out",
# Plain assembler, as SCons's ASCOM: no preprocessor, so no # Plain assembler, as SCons's ASCOM: no preprocessor, so no
# depfile and no $flags (defines/includes) either # depfile and no $flags (defines/includes) either
"rule asm", "rule asm",
" command = $ccache $cc -x assembler $asflags -c $in -o $out", f" command = {launcher}$cc -x assembler $asflags -c $in -o $out",
" description = AS $out", " description = AS $out",
] ]
-2
View File
@@ -34,13 +34,11 @@ from esphome.cpp_generator import ( # noqa: F401
extern_progmem_array, extern_progmem_array,
get_variable, get_variable,
get_variable_with_full_id, get_variable_with_full_id,
is_static_pointer,
is_template, is_template,
new_Pvariable, new_Pvariable,
new_variable, new_variable,
process_lambda, process_lambda,
progmem_array, progmem_array,
progmem_string,
safe_exp, safe_exp,
set_cpp_standard, set_cpp_standard,
shared_progmem_array, shared_progmem_array,
-1
View File
@@ -1,2 +1 @@
CODEOWNERS = ["@MrSuicideParrot"] CODEOWNERS = ["@MrSuicideParrot"]
DOMAIN = "a01nyub"
+1 -1
View File
@@ -6,7 +6,7 @@
namespace esphome::a01nyub { namespace esphome::a01nyub {
ESPHOME_LOG_TAG(TAG, "a01nyub.sensor"); static const char *const TAG = "a01nyub.sensor";
void A01nyubComponent::loop() { void A01nyubComponent::loop() {
uint8_t data; uint8_t data;
-1
View File
@@ -1,2 +1 @@
CODEOWNERS = ["@TH-Braemer"] CODEOWNERS = ["@TH-Braemer"]
DOMAIN = "a02yyuw"
+1 -1
View File
@@ -6,7 +6,7 @@
namespace esphome::a02yyuw { namespace esphome::a02yyuw {
ESPHOME_LOG_TAG(TAG, "a02yyuw.sensor"); static const char *const TAG = "a02yyuw.sensor";
void A02yyuwComponent::loop() { void A02yyuwComponent::loop() {
uint8_t data; uint8_t data;
-1
View File
@@ -1 +0,0 @@
DOMAIN = "a4988"
+1 -1
View File
@@ -3,7 +3,7 @@
namespace esphome::a4988 { namespace esphome::a4988 {
ESPHOME_LOG_TAG(TAG, "a4988.stepper"); static const char *const TAG = "a4988.stepper";
void A4988::setup() { void A4988::setup() {
if (this->sleep_pin_ != nullptr) { if (this->sleep_pin_ != nullptr) {
@@ -1,2 +1 @@
CODEOWNERS = ["@DAVe3283"] CODEOWNERS = ["@DAVe3283"]
DOMAIN = "absolute_humidity"
@@ -3,7 +3,7 @@
namespace esphome::absolute_humidity { namespace esphome::absolute_humidity {
ESPHOME_LOG_TAG(TAG, "absolute_humidity.sensor"); static const char *const TAG{"absolute_humidity.sensor"};
void AbsoluteHumidityComponent::setup() { void AbsoluteHumidityComponent::setup() {
this->temperature_sensor_->add_on_state_callback([this](float state) { this->temperature_sensor_->add_on_state_callback([this](float state) {
-1
View File
@@ -1 +0,0 @@
DOMAIN = "ac_dimmer"
+1 -1
View File
@@ -14,7 +14,7 @@
namespace esphome::ac_dimmer { namespace esphome::ac_dimmer {
ESPHOME_LOG_TAG(TAG, "ac_dimmer"); static const char *const TAG = "ac_dimmer";
// Global array to store dimmer objects // Global array to store dimmer objects
static AcDimmerDataStore *all_dimmers[32]; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) static AcDimmerDataStore *all_dimmers[32]; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
@@ -9,7 +9,7 @@
#include "esp_clk_tree.h" #include "esp_clk_tree.h"
#include "soc/clk_tree_defs.h" #include "soc/clk_tree_defs.h"
ESPHOME_LOG_TAG(TAG, "hw_timer_esp_idf"); static const char *const TAG = "hw_timer_esp_idf";
namespace esphome::ac_dimmer { namespace esphome::ac_dimmer {
-1
View File
@@ -9,7 +9,6 @@ from esphome.cpp_generator import MockObj
from esphome.types import ConfigType from esphome.types import ConfigType
DEPENDENCIES = ["uart"] DEPENDENCIES = ["uart"]
DOMAIN = "adalight"
adalight_ns = cg.esphome_ns.namespace("adalight") adalight_ns = cg.esphome_ns.namespace("adalight")
AdalightLightEffect = adalight_ns.class_( AdalightLightEffect = adalight_ns.class_(
@@ -3,7 +3,7 @@
namespace esphome::adalight { namespace esphome::adalight {
ESPHOME_LOG_TAG(TAG, "adalight_light_effect"); static const char *const TAG = "adalight_light_effect";
static const uint32_t ADALIGHT_ACK_INTERVAL = 1000; static const uint32_t ADALIGHT_ACK_INTERVAL = 1000;
static const uint32_t ADALIGHT_RECEIVE_TIMEOUT = 1000; static const uint32_t ADALIGHT_RECEIVE_TIMEOUT = 1000;
-1
View File
@@ -22,7 +22,6 @@ from esphome.core import CORE
from esphome.types import ConfigType from esphome.types import ConfigType
CODEOWNERS = ["@esphome/core"] CODEOWNERS = ["@esphome/core"]
DOMAIN = "adc"
adc_ns = cg.esphome_ns.namespace("adc") adc_ns = cg.esphome_ns.namespace("adc")
+1 -1
View File
@@ -3,7 +3,7 @@
namespace esphome::adc { namespace esphome::adc {
ESPHOME_LOG_TAG(TAG, "adc"); static const char *const TAG = "adc";
const LogString *sampling_mode_to_str(SamplingMode mode) { const LogString *sampling_mode_to_str(SamplingMode mode) {
switch (mode) { switch (mode) {
+1 -1
View File
@@ -6,7 +6,7 @@
namespace esphome::adc { namespace esphome::adc {
ESPHOME_LOG_TAG(TAG, "adc"); static const char *const TAG = "adc";
adc_oneshot_unit_handle_t ADCSensor::shared_adc_handles[2] = {nullptr, nullptr}; adc_oneshot_unit_handle_t ADCSensor::shared_adc_handles[2] = {nullptr, nullptr};
@@ -13,7 +13,7 @@ ADC_MODE(ADC_VCC)
namespace esphome::adc { namespace esphome::adc {
ESPHOME_LOG_TAG(TAG, "adc"); static const char *const TAG = "adc";
void ADCSensor::setup() { void ADCSensor::setup() {
#ifndef USE_ADC_SENSOR_VCC #ifndef USE_ADC_SENSOR_VCC
@@ -5,7 +5,7 @@
namespace esphome::adc { namespace esphome::adc {
ESPHOME_LOG_TAG(TAG, "adc"); static const char *const TAG = "adc";
void ADCSensor::setup() { void ADCSensor::setup() {
#ifndef USE_ADC_SENSOR_VCC #ifndef USE_ADC_SENSOR_VCC
+1 -1
View File
@@ -17,7 +17,7 @@
namespace esphome::adc { namespace esphome::adc {
ESPHOME_LOG_TAG(TAG, "adc"); static const char *const TAG = "adc";
// The on-die temperature sensor sits on the last ADC channel: input 4 on RP2040 // The on-die temperature sensor sits on the last ADC channel: input 4 on RP2040
// and RP2350A, but input 8 on RP2350B, which has eight external channels rather // and RP2350A, but input 8 on RP2350B, which has eight external channels rather
+1 -1
View File
@@ -7,7 +7,7 @@
namespace esphome::adc { namespace esphome::adc {
ESPHOME_LOG_TAG(TAG, "adc"); static const char *const TAG = "adc";
void ADCSensor::setup() { void ADCSensor::setup() {
if (!adc_is_ready_dt(this->channel_)) { if (!adc_is_ready_dt(this->channel_)) {
@@ -5,7 +5,6 @@ from esphome.const import CONF_ID
from esphome.types import ConfigType from esphome.types import ConfigType
DEPENDENCIES = ["spi"] DEPENDENCIES = ["spi"]
DOMAIN = "adc128s102"
MULTI_CONF = True MULTI_CONF = True
CODEOWNERS = ["@DeerMaximum"] CODEOWNERS = ["@DeerMaximum"]
+1 -1
View File
@@ -3,7 +3,7 @@
namespace esphome::adc128s102 { namespace esphome::adc128s102 {
ESPHOME_LOG_TAG(TAG, "adc128s102"); static const char *const TAG = "adc128s102";
float ADC128S102::get_setup_priority() const { return setup_priority::HARDWARE; } float ADC128S102::get_setup_priority() const { return setup_priority::HARDWARE; }
@@ -4,7 +4,7 @@
namespace esphome::adc128s102 { namespace esphome::adc128s102 {
ESPHOME_LOG_TAG(TAG, "adc128s102.sensor"); static const char *const TAG = "adc128s102.sensor";
ADC128S102Sensor::ADC128S102Sensor(uint8_t channel) : channel_(channel) {} ADC128S102Sensor::ADC128S102Sensor(uint8_t channel) : channel_(channel) {}
@@ -1 +0,0 @@
DOMAIN = "addressable_light"
@@ -3,7 +3,7 @@
namespace esphome::addressable_light { namespace esphome::addressable_light {
ESPHOME_LOG_TAG(TAG, "addressable_light.display"); static const char *const TAG = "addressable_light.display";
int AddressableLightDisplay::get_width_internal() { return this->width_; } int AddressableLightDisplay::get_width_internal() { return this->width_; }
int AddressableLightDisplay::get_height_internal() { return this->height_; } int AddressableLightDisplay::get_height_internal() { return this->height_; }
-1
View File
@@ -1 +0,0 @@
DOMAIN = "ade7880"
+1 -1
View File
@@ -15,7 +15,7 @@
namespace esphome::ade7880 { namespace esphome::ade7880 {
ESPHOME_LOG_TAG(TAG, "ade7880"); static const char *const TAG = "ade7880";
void IRAM_ATTR ADE7880Store::gpio_intr(ADE7880Store *arg) { arg->reset_done = true; } void IRAM_ATTR ADE7880Store::gpio_intr(ADE7880Store *arg) { arg->reset_done = true; }
-1
View File
@@ -1,2 +1 @@
CODEOWNERS = ["@angelnu"] CODEOWNERS = ["@angelnu"]
DOMAIN = "ade7953"
@@ -27,7 +27,6 @@ from esphome.cpp_generator import MockObj
from esphome.types import ConfigType from esphome.types import ConfigType
CODEOWNERS = ["@angelnu"] CODEOWNERS = ["@angelnu"]
DOMAIN = "ade7953_base"
CONF_CURRENT_A = "current_a" CONF_CURRENT_A = "current_a"
CONF_CURRENT_B = "current_b" CONF_CURRENT_B = "current_b"
@@ -5,7 +5,7 @@
namespace esphome::ade7953_base { namespace esphome::ade7953_base {
ESPHOME_LOG_TAG(TAG, "ade7953"); static const char *const TAG = "ade7953";
constexpr uint16_t CONFIG_DEFAULT = 0x8004u; constexpr uint16_t CONFIG_DEFAULT = 0x8004u;
constexpr uint16_t CONFIG_LOCK_BIT = 0x8000u; constexpr uint16_t CONFIG_LOCK_BIT = 0x8000u;
@@ -1,2 +1 @@
CODEOWNERS = ["@angelnu"] CODEOWNERS = ["@angelnu"]
DOMAIN = "ade7953_i2c"
@@ -4,7 +4,7 @@
namespace esphome::ade7953_i2c { namespace esphome::ade7953_i2c {
ESPHOME_LOG_TAG(TAG, "ade7953"); static const char *const TAG = "ade7953";
void AdE7953I2c::dump_config() { void AdE7953I2c::dump_config() {
ESP_LOGCONFIG(TAG, "ADE7953_i2c:"); ESP_LOGCONFIG(TAG, "ADE7953_i2c:");
@@ -1,2 +1 @@
CODEOWNERS = ["@angelnu"] CODEOWNERS = ["@angelnu"]
DOMAIN = "ade7953_spi"
@@ -4,7 +4,7 @@
namespace esphome::ade7953_spi { namespace esphome::ade7953_spi {
ESPHOME_LOG_TAG(TAG, "ade7953"); static const char *const TAG = "ade7953";
// Datasheet requires at least 1.2µs after clearing CONFIG LOCK_BIT before raising CS // Datasheet requires at least 1.2µs after clearing CONFIG LOCK_BIT before raising CS
constexpr uint8_t CONFIG_LOCK_SETTLE_US = 2; constexpr uint8_t CONFIG_LOCK_SETTLE_US = 2;
-1
View File
@@ -5,7 +5,6 @@ from esphome.const import CONF_ID
from esphome.types import ConfigType from esphome.types import ConfigType
DEPENDENCIES = ["i2c"] DEPENDENCIES = ["i2c"]
DOMAIN = "ads1115"
MULTI_CONF = True MULTI_CONF = True
ads1115_ns = cg.esphome_ns.namespace("ads1115") ads1115_ns = cg.esphome_ns.namespace("ads1115")
+1 -1
View File
@@ -4,7 +4,7 @@
namespace esphome::ads1115 { namespace esphome::ads1115 {
ESPHOME_LOG_TAG(TAG, "ads1115"); static const char *const TAG = "ads1115";
static const uint8_t ADS1115_REGISTER_CONVERSION = 0x00; static const uint8_t ADS1115_REGISTER_CONVERSION = 0x00;
static const uint8_t ADS1115_REGISTER_CONFIG = 0x01; static const uint8_t ADS1115_REGISTER_CONFIG = 0x01;
@@ -4,7 +4,7 @@
namespace esphome::ads1115 { namespace esphome::ads1115 {
ESPHOME_LOG_TAG(TAG, "ads1115.sensor"); static const char *const TAG = "ads1115.sensor";
float ADS1115Sensor::sample() { float ADS1115Sensor::sample() {
return this->parent_->request_measurement(this->multiplexer_, this->gain_, this->resolution_, this->samplerate_); return this->parent_->request_measurement(this->multiplexer_, this->gain_, this->resolution_, this->samplerate_);
-1
View File
@@ -6,7 +6,6 @@ from esphome.types import ConfigType
CODEOWNERS = ["@solomondg1"] CODEOWNERS = ["@solomondg1"]
DEPENDENCIES = ["spi"] DEPENDENCIES = ["spi"]
DOMAIN = "ads1118"
MULTI_CONF = True MULTI_CONF = True
CONF_ADS1118_ID = "ads1118_id" CONF_ADS1118_ID = "ads1118_id"
+1 -1
View File
@@ -4,7 +4,7 @@
namespace esphome::ads1118 { namespace esphome::ads1118 {
ESPHOME_LOG_TAG(TAG, "ads1118"); static const char *const TAG = "ads1118";
static const uint8_t ADS1118_DATA_RATE_860_SPS = 0b111; static const uint8_t ADS1118_DATA_RATE_860_SPS = 0b111;
void ADS1118::setup() { void ADS1118::setup() {
@@ -4,7 +4,7 @@
namespace esphome::ads1118 { namespace esphome::ads1118 {
ESPHOME_LOG_TAG(TAG, "ads1118.sensor"); static const char *const TAG = "ads1118.sensor";
void ADS1118Sensor::dump_config() { void ADS1118Sensor::dump_config() {
LOG_SENSOR(" ", "ADS1118 Sensor", this); LOG_SENSOR(" ", "ADS1118 Sensor", this);
-1
View File
@@ -1,2 +1 @@
CODEOWNERS = ["@mak-42"] CODEOWNERS = ["@mak-42"]
DOMAIN = "ags10"
+1 -1
View File
@@ -4,7 +4,7 @@
#include <cinttypes> #include <cinttypes>
namespace esphome::ags10 { namespace esphome::ags10 {
ESPHOME_LOG_TAG(TAG, "ags10"); static const char *const TAG = "ags10";
// Data acquisition. // Data acquisition.
static const uint8_t REG_TVOC = 0x00; static const uint8_t REG_TVOC = 0x00;
-1
View File
@@ -1 +0,0 @@
DOMAIN = "aht10"
+1 -1
View File
@@ -19,7 +19,7 @@
namespace esphome::aht10 { namespace esphome::aht10 {
ESPHOME_LOG_TAG(TAG, "aht10"); static const char *const TAG = "aht10";
static const uint8_t AHT10_INITIALIZE_CMD[] = {0xE1, 0x08, 0x00}; static const uint8_t AHT10_INITIALIZE_CMD[] = {0xE1, 0x08, 0x00};
static const uint8_t AHT20_INITIALIZE_CMD[] = {0xBE, 0x08, 0x00}; static const uint8_t AHT20_INITIALIZE_CMD[] = {0xBE, 0x08, 0x00};
static const uint8_t AHT10_MEASURE_CMD[] = {0xAC, 0x33, 0x00}; static const uint8_t AHT10_MEASURE_CMD[] = {0xAC, 0x33, 0x00};
-1
View File
@@ -1 +0,0 @@
DOMAIN = "aic3204"
+1 -1
View File
@@ -6,7 +6,7 @@
namespace esphome::aic3204 { namespace esphome::aic3204 {
ESPHOME_LOG_TAG(TAG, "aic3204"); static const char *const TAG = "aic3204";
#define ERROR_CHECK(err, msg) \ #define ERROR_CHECK(err, msg) \
if (!(err)) { \ if (!(err)) { \
@@ -6,7 +6,6 @@ from esphome.types import ConfigType
AUTO_LOAD = ["ble_device_base"] AUTO_LOAD = ["ble_device_base"]
CODEOWNERS = ["@jeromelaban"] CODEOWNERS = ["@jeromelaban"]
DOMAIN = "airthings_ble"
airthings_ble_ns = cg.esphome_ns.namespace("airthings_ble") airthings_ble_ns = cg.esphome_ns.namespace("airthings_ble")
AirthingsListener = airthings_ble_ns.class_( AirthingsListener = airthings_ble_ns.class_(
@@ -4,7 +4,7 @@
namespace esphome::airthings_ble { namespace esphome::airthings_ble {
ESPHOME_LOG_TAG(TAG, "airthings_ble"); static const char *const TAG = "airthings_ble";
bool AirthingsListener::parse_device(const ble_device_base::ESPBTDevice &device) { bool AirthingsListener::parse_device(const ble_device_base::ESPBTDevice &device) {
for (auto &it : device.get_manufacturer_datas()) { for (auto &it : device.get_manufacturer_datas()) {
@@ -24,7 +24,6 @@ from esphome.cpp_generator import MockObj
from esphome.types import ConfigType from esphome.types import ConfigType
CODEOWNERS = ["@ncareau", "@jeromelaban"] CODEOWNERS = ["@ncareau", "@jeromelaban"]
DOMAIN = "airthings_wave_base"
DEPENDENCIES = ["ble_client"] DEPENDENCIES = ["ble_client"]
@@ -8,10 +8,7 @@
namespace esphome::airthings_wave_base { namespace esphome::airthings_wave_base {
ESPHOME_LOG_TAG(TAG, "airthings_wave_base"); static const char *const TAG = "airthings_wave_base";
static constexpr uint32_t BATTERY_READ_TIMEOUT_ID = 0;
static constexpr uint32_t RESPONSE_TIMEOUT_ID = 1;
void AirthingsWaveBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, void AirthingsWaveBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
esp_ble_gattc_cb_param_t *param) { esp_ble_gattc_cb_param_t *param) {
@@ -184,7 +181,7 @@ void AirthingsWaveBase::read_battery_(uint8_t *raw_value, uint16_t value_len) {
// read the battery again at the configured update interval // read the battery again at the configured update interval
if (this->battery_update_interval_ != this->update_interval_) { if (this->battery_update_interval_ != this->update_interval_) {
this->read_battery_next_update_ = false; this->read_battery_next_update_ = false;
this->set_timeout(BATTERY_READ_TIMEOUT_ID, this->battery_update_interval_, this->set_timeout("battery", this->battery_update_interval_,
[this]() { this->read_battery_next_update_ = true; }); [this]() { this->read_battery_next_update_ = true; });
} }
} }
@@ -207,7 +204,7 @@ void AirthingsWaveBase::response_received_() {
} }
void AirthingsWaveBase::set_response_timeout_() { void AirthingsWaveBase::set_response_timeout_() {
this->set_timeout(RESPONSE_TIMEOUT_ID, 30 * 1000, [this]() { this->set_timeout("response_timeout", 30 * 1000, [this]() {
this->responses_pending_ = 1; this->responses_pending_ = 1;
this->response_received_(); this->response_received_();
}); });
@@ -1,2 +1 @@
CODEOWNERS = ["@ncareau"] CODEOWNERS = ["@ncareau"]
DOMAIN = "airthings_wave_mini"
@@ -4,7 +4,7 @@
namespace esphome::airthings_wave_mini { namespace esphome::airthings_wave_mini {
ESPHOME_LOG_TAG(TAG, "airthings_wave_mini"); static const char *const TAG = "airthings_wave_mini";
void AirthingsWaveMini::read_sensors(uint8_t *raw_value, uint16_t value_len) { void AirthingsWaveMini::read_sensors(uint8_t *raw_value, uint16_t value_len) {
auto *value = (WaveMiniReadings *) raw_value; auto *value = (WaveMiniReadings *) raw_value;
@@ -1,2 +1 @@
CODEOWNERS = ["@jeromelaban", "@precurse"] CODEOWNERS = ["@jeromelaban", "@precurse"]
DOMAIN = "airthings_wave_plus"
@@ -4,7 +4,7 @@
namespace esphome::airthings_wave_plus { namespace esphome::airthings_wave_plus {
ESPHOME_LOG_TAG(TAG, "airthings_wave_plus"); static const char *const TAG = "airthings_wave_plus";
void AirthingsWavePlus::read_sensors(uint8_t *raw_value, uint16_t value_len) { void AirthingsWavePlus::read_sensors(uint8_t *raw_value, uint16_t value_len) {
auto *value = (WavePlusReadings *) raw_value; auto *value = (WavePlusReadings *) raw_value;
@@ -21,7 +21,6 @@ from esphome.core.entity_helpers import (
from esphome.cpp_generator import MockObjClass from esphome.cpp_generator import MockObjClass
CODEOWNERS = ["@grahambrown11", "@hwstar"] CODEOWNERS = ["@grahambrown11", "@hwstar"]
DOMAIN = "alarm_control_panel"
IS_PLATFORM_COMPONENT = True IS_PLATFORM_COMPONENT = True
CONF_ON_TRIGGERED = "on_triggered" CONF_ON_TRIGGERED = "on_triggered"
@@ -10,7 +10,7 @@
namespace esphome::alarm_control_panel { namespace esphome::alarm_control_panel {
ESPHOME_LOG_TAG(TAG, "alarm_control_panel"); static const char *const TAG = "alarm_control_panel";
AlarmControlPanelCall AlarmControlPanel::make_call() { return AlarmControlPanelCall(this); } AlarmControlPanelCall AlarmControlPanel::make_call() { return AlarmControlPanelCall(this); }
@@ -6,7 +6,7 @@
namespace esphome::alarm_control_panel { namespace esphome::alarm_control_panel {
ESPHOME_LOG_TAG(TAG, "alarm_control_panel"); static const char *const TAG = "alarm_control_panel";
AlarmControlPanelCall::AlarmControlPanelCall(AlarmControlPanel *parent) : parent_(parent) {} AlarmControlPanelCall::AlarmControlPanelCall(AlarmControlPanel *parent) : parent_(parent) {}
-1
View File
@@ -1,2 +1 @@
CODEOWNERS = ["@jan-hofmeier"] CODEOWNERS = ["@jan-hofmeier"]
DOMAIN = "alpha3"
+1 -1
View File
@@ -7,7 +7,7 @@
namespace esphome::alpha3 { namespace esphome::alpha3 {
ESPHOME_LOG_TAG(TAG, "alpha3"); static const char *const TAG = "alpha3";
void Alpha3::dump_config() { void Alpha3::dump_config() {
ESP_LOGCONFIG(TAG, "ALPHA3"); ESP_LOGCONFIG(TAG, "ALPHA3");
-1
View File
@@ -1,2 +1 @@
CODEOWNERS = ["@swoboda1337"] CODEOWNERS = ["@swoboda1337"]
DOMAIN = "am2315c"
+1 -1
View File
@@ -26,7 +26,7 @@
namespace esphome::am2315c { namespace esphome::am2315c {
ESPHOME_LOG_TAG(TAG, "am2315c"); static const char *const TAG = "am2315c";
bool AM2315C::reset_register_(uint8_t reg) { bool AM2315C::reset_register_(uint8_t reg) {
// code based on demo code sent by www.aosong.com // code based on demo code sent by www.aosong.com
-1
View File
@@ -1 +0,0 @@
DOMAIN = "am2320"
+1 -1
View File
@@ -10,7 +10,7 @@
namespace esphome::am2320 { namespace esphome::am2320 {
ESPHOME_LOG_TAG(TAG, "am2320"); static const char *const TAG = "am2320";
void AM2320Component::update() { void AM2320Component::update() {
uint8_t data[8]; uint8_t data[8];
-1
View File
@@ -1,2 +1 @@
CODEOWNERS = ["@buxtronix"] CODEOWNERS = ["@buxtronix"]
DOMAIN = "am43"
+1 -1
View File
@@ -5,7 +5,7 @@
namespace esphome::am43 { namespace esphome::am43 {
ESPHOME_LOG_TAG(TAG, "am43_cover"); static const char *const TAG = "am43_cover";
using namespace esphome::cover; using namespace esphome::cover;
@@ -6,7 +6,7 @@
namespace esphome::am43 { namespace esphome::am43 {
ESPHOME_LOG_TAG(TAG, "am43"); static const char *const TAG = "am43";
void Am43::dump_config() { void Am43::dump_config() {
ESP_LOGCONFIG(TAG, "AM43"); ESP_LOGCONFIG(TAG, "AM43");
@@ -1,2 +1 @@
CODEOWNERS = ["@ianchi"] CODEOWNERS = ["@ianchi"]
DOMAIN = "analog_threshold"
@@ -3,7 +3,7 @@
namespace esphome::analog_threshold { namespace esphome::analog_threshold {
ESPHOME_LOG_TAG(TAG, "analog_threshold.binary_sensor"); static const char *const TAG = "analog_threshold.binary_sensor";
void AnalogThresholdBinarySensor::setup() { void AnalogThresholdBinarySensor::setup() {
float sensor_value = this->sensor_->get_state(); float sensor_value = this->sensor_->get_state();
-1
View File
@@ -1 +0,0 @@
DOMAIN = "anova"
+1 -1
View File
@@ -5,7 +5,7 @@
namespace esphome::anova { namespace esphome::anova {
ESPHOME_LOG_TAG(TAG, "anova"); static const char *const TAG = "anova";
using namespace esphome::climate; using namespace esphome::climate;
-1
View File
@@ -2,4 +2,3 @@
# https://www.mouser.ca/datasheet/2/678/AVGO_S_A0002854364_1-2574547.pdf # https://www.mouser.ca/datasheet/2/678/AVGO_S_A0002854364_1-2574547.pdf
CODEOWNERS = ["@aodrenah"] CODEOWNERS = ["@aodrenah"]
DOMAIN = "apds9306"
+1 -1
View File
@@ -7,7 +7,7 @@
namespace esphome::apds9306 { namespace esphome::apds9306 {
ESPHOME_LOG_TAG(TAG, "apds9306"); static const char *const TAG = "apds9306";
enum { // APDS9306 registers enum { // APDS9306 registers
APDS9306_MAIN_CTRL = 0x00, APDS9306_MAIN_CTRL = 0x00,
-1
View File
@@ -5,7 +5,6 @@ from esphome.const import CONF_ID
from esphome.types import ConfigType from esphome.types import ConfigType
DEPENDENCIES = ["i2c"] DEPENDENCIES = ["i2c"]
DOMAIN = "apds9960"
MULTI_CONF = True MULTI_CONF = True
CONF_APDS9960_ID = "apds9960_id" CONF_APDS9960_ID = "apds9960_id"
+1 -1
View File
@@ -4,7 +4,7 @@
namespace esphome::apds9960 { namespace esphome::apds9960 {
ESPHOME_LOG_TAG(TAG, "apds9960"); static const char *const TAG = "apds9960";
#define APDS9960_ERROR_CHECK(func) \ #define APDS9960_ERROR_CHECK(func) \
if (!(func)) { \ if (!(func)) { \
+1 -2
View File
@@ -8,7 +8,6 @@ from esphome.automation import Condition
import esphome.codegen as cg import esphome.codegen as cg
from esphome.components.const import CONF_DESCRIPTION, CONF_HOST from esphome.components.const import CONF_DESCRIPTION, CONF_HOST
from esphome.components.logger import request_log_listener from esphome.components.logger import request_log_listener
from esphome.components.network import DOMAIN as NETWORK_DOMAIN
# ENCRYPTION_SCHEMA and validate_encryption_key are re-exported for external # ENCRYPTION_SCHEMA and validate_encryption_key are re-exported for external
# components and downstream consumers that import them from api # components and downstream consumers that import them from api
@@ -515,7 +514,7 @@ def _validate_outgoing_host_ipv6(config: ConfigType) -> ConfigType:
or host.version != 6 or host.version != 6
): ):
return config return config
network_conf = fv.full_config.get().get(NETWORK_DOMAIN) or {} network_conf = fv.full_config.get().get("network") or {}
if not network_conf.get(CONF_ENABLE_IPV6): if not network_conf.get(CONF_ENABLE_IPV6):
raise cv.Invalid( raise cv.Invalid(
"outgoing_connection host is an IPv6 address but IPv6 is not " "outgoing_connection host is an IPv6 address but IPv6 is not "
+26 -7
View File
@@ -403,6 +403,9 @@ message WizardCapabilities {
message SendspinCapabilities { message SendspinCapabilities {
// Bitmask of the Sendspin features this device supports // Bitmask of the Sendspin features this device supports
uint32 feature_flags = 1; 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 { message DeviceCapabilitiesResponse {
@@ -444,7 +447,7 @@ message DeviceWizardRequest {
// {"version": 1, // {"version": 1,
// "pages": [{"title": "...", "description": "...", // "pages": [{"title": "...", "description": "...",
// "entities": [{"key": 123, "device_id": 456, "description": "..."}], // "entities": [{"key": 123, "device_id": 456, "description": "..."}],
// "inputs": [{"key": 789, "description": "...", // "inputs": [{"key": 789, "description": "...", "multiple": true, "max_length": 1023,
// "entity_filters": [{"integration": "...", "domain": ["..."], // "entity_filters": [{"integration": "...", "domain": ["..."],
// "device_class": ["..."], "supported_features": ["..."]}]}]}]} // "device_class": ["..."], "supported_features": ["..."]}]}]}]}
// //
@@ -468,6 +471,14 @@ message DeviceWizardRequest {
// an entity matches a filter when it satisfies every field that is set, and an entity // an entity matches a filter when it satisfies every field that is set, and an entity
// that matches any one of the filters is accepted. // that matches any one of the filters is accepted.
// //
// An input with "multiple": true lets the user pick several entities. The client sends
// them in one WizardInputSetRequest as a comma separated list with no spaces
// ("calendar.a,calendar.b"); the device also accepts spaces around each id and stores the
// list without them. "max_length" (only on a multiple input, 255 when left out) is the
// longest list in bytes the device accepts. The version stays 1: a client that does not
// know "multiple" ignores it, shows a single picker and sends one entity id, which a
// multiple input accepts.
//
// The device keeps the entity id of an input in RAM only and does not store it across // The device keeps the entity id of an input in RAM only and does not store it across
// restarts. The client therefore stores the choice itself and, after every connection // restarts. The client therefore stores the choice itself and, after every connection
// and before it sends SubscribeHomeAssistantStatesRequest, sends a WizardInputSetRequest // and before it sends SubscribeHomeAssistantStatesRequest, sends a WizardInputSetRequest
@@ -483,8 +494,13 @@ message DeviceWizardResponse {
// Sets the entity id of a wizard input (see WizardInputField.key). Clients send // Sets the entity id of a wizard input (see WizardInputField.key). Clients send
// this only when DeviceCapabilitiesResponse.wizard.configured is set. There is no // this only when DeviceCapabilitiesResponse.wizard.configured is set. There is no
// reply. The device ignores a request whose key matches no input or whose entity_id // reply. The device ignores a request whose key matches no input. A single input is
// is empty, longer than 255 bytes or has no '.'. Otherwise it keeps the id in RAM, // ignored when the entity_id is empty, longer than 255 bytes or has no '.'. A multiple
// input takes a comma separated list ("calendar.a,calendar.b"); the client sends no
// spaces, the device trims spaces around each id and stores the list without them. The
// whole request is ignored when any id is empty or has no '.', or when the list without
// spaces does not fit the input's max_length (255 by default). Otherwise it keeps the id
// or list in RAM,
// not across restarts, and when the input belongs to a homeassistant platform entity // not across restarts, and when the input belongs to a homeassistant platform entity
// it subscribes to that entity's state. Clients send this for every input right // it subscribes to that entity's state. Clients send this for every input right
// after connecting, before SubscribeHomeAssistantStatesRequest. A request that // after connecting, before SubscribeHomeAssistantStatesRequest. A request that
@@ -496,7 +512,7 @@ message WizardInputSetRequest {
option (ifdef) = "USE_API_WIZARD_INPUTS"; option (ifdef) = "USE_API_WIZARD_INPUTS";
fixed32 key = 1; fixed32 key = 1;
string entity_id = 2 [(max_data_length) = 255]; string entity_id = 2 [(max_data_length) = 4095];
} }
message ListEntitiesRequest { message ListEntitiesRequest {
@@ -760,7 +776,7 @@ message ListEntitiesLightResponse {
bool legacy_supports_color_temperature = 8 [deprecated=true]; bool legacy_supports_color_temperature = 8 [deprecated=true];
float min_mireds = 9; float min_mireds = 9;
float max_mireds = 10; float max_mireds = 10;
repeated string effects = 11 [(container_pointer_no_template) = "light::LightEffectNames"]; repeated string effects = 11 [(container_pointer_no_template) = "FixedVector<const char *>"];
bool disabled_by_default = 13; bool disabled_by_default = 13;
string icon = 14 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63]; string icon = 14 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
EntityCategory entity_category = 15; EntityCategory entity_category = 15;
@@ -3030,12 +3046,15 @@ enum SerialProxyIdentityFlag {
// IDs below are empty // 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 { message UsbDeviceDescriptor {
uint32 vendor_id = 1; uint32 vendor_id = 1;
uint32 product_id = 2; uint32 product_id = 2;
uint32 bcd_device = 3; 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 // The identity of the device behind a port. Identifies one physical device among others of
+12 -2
View File
@@ -91,7 +91,7 @@ static_assert(sizeof(ESPHOME_VERSION) - 1 <= 32, "Update max_data_length for esp
static_assert(ESPHOME_DEVICE_NAME_MAX_LEN <= 31, "Update max_data_length for name in api.proto"); static_assert(ESPHOME_DEVICE_NAME_MAX_LEN <= 31, "Update max_data_length for name in api.proto");
static_assert(ESPHOME_FRIENDLY_NAME_MAX_LEN <= 120, "Update max_data_length for friendly_name in api.proto"); static_assert(ESPHOME_FRIENDLY_NAME_MAX_LEN <= 120, "Update max_data_length for friendly_name in api.proto");
ESPHOME_LOG_TAG(TAG, "api.connection"); static const char *const TAG = "api.connection";
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_WARN #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_WARN
void log_dropped_message(const char *tag, int line, const LogString *what) { void log_dropped_message(const char *tag, int line, const LogString *what) {
@@ -644,7 +644,16 @@ uint16_t APIConnection::try_send_light_info(EntityBase *entity, APIConnection *c
msg.min_mireds = traits.get_min_mireds(); msg.min_mireds = traits.get_min_mireds();
msg.max_mireds = traits.get_max_mireds(); msg.max_mireds = traits.get_max_mireds();
} }
light::LightEffectNames effects_list(light->get_effects()); FixedVector<const char *> effects_list;
if (light->supports_effects()) {
auto &light_effects = light->get_effects();
effects_list.init(light_effects.size() + 1);
effects_list.push_back("None");
for (auto *effect : light_effects) {
// c_str() is safe as effect names are null-terminated strings from codegen
effects_list.push_back(effect->get_name().c_str());
}
}
msg.effects = &effects_list; msg.effects = &effects_list;
return fill_and_encode_entity_info(light, msg, conn, remaining_size); return fill_and_encode_entity_info(light, msg, conn, remaining_size);
} }
@@ -2119,6 +2128,7 @@ bool APIConnection::send_device_capabilities_response_() {
#endif #endif
#if defined(USE_SENDSPIN) && defined(USE_ESP_IDF) #if defined(USE_SENDSPIN) && defined(USE_ESP_IDF)
resp.sendspin.feature_flags = sendspin_::global_sendspin_hub->get_feature_flags(); resp.sendspin.feature_flags = sendspin_::global_sendspin_hub->get_feature_flags();
resp.sendspin.client_id = sendspin_::global_sendspin_hub->get_client_id();
#endif #endif
return this->send_message(resp); return this->send_message(resp);
} }
+1 -1
View File
@@ -10,7 +10,7 @@
namespace esphome::api { namespace esphome::api {
ESPHOME_LOG_TAG(TAG, "api.frame_helper"); static const char *const TAG = "api.frame_helper";
// Maximum bytes to log in hex format (168 * 3 = 504, under TX buffer size of 512) // Maximum bytes to log in hex format (168 * 3 = 504, under TX buffer size of 512)
static constexpr size_t API_MAX_LOG_BYTES = 168; static constexpr size_t API_MAX_LOG_BYTES = 168;
@@ -22,7 +22,7 @@ using noise::noise_err_to_logstr;
static_assert(MAX_HANDSHAKE_SIZE == noise::MAX_HANDSHAKE_SIZE, static_assert(MAX_HANDSHAKE_SIZE == noise::MAX_HANDSHAKE_SIZE,
"api and noise component handshake size limits must match"); "api and noise component handshake size limits must match");
ESPHOME_LOG_TAG(TAG, "api.noise"); static const char *const TAG = "api.noise";
static constexpr char PROLOGUE_INIT[] PROGMEM = "NoiseAPIInit"; static constexpr char PROLOGUE_INIT[] PROGMEM = "NoiseAPIInit";
static constexpr size_t PROLOGUE_INIT_LEN = 12; // strlen("NoiseAPIInit") static constexpr size_t PROLOGUE_INIT_LEN = 12; // strlen("NoiseAPIInit")
@@ -16,7 +16,7 @@
namespace esphome::api { namespace esphome::api {
ESPHOME_LOG_TAG(TAG, "api.plaintext"); static const char *const TAG = "api.plaintext";
// Maximum bytes to log in hex format (168 * 3 = 504, under TX buffer size of 512) // Maximum bytes to log in hex format (168 * 3 = 504, under TX buffer size of 512)
static constexpr size_t API_MAX_LOG_BYTES = 168; static constexpr size_t API_MAX_LOG_BYTES = 168;
@@ -15,7 +15,7 @@
namespace esphome::api { namespace esphome::api {
ESPHOME_LOG_TAG(TAG, "api.outgoing"); static const char *const TAG = "api.outgoing";
#ifndef API_OUTGOING_CONNECTION_HOST #ifndef API_OUTGOING_CONNECTION_HOST
static constexpr uint32_t OUTGOING_TARGET_PREF_HASH = 629847102UL; static constexpr uint32_t OUTGOING_TARGET_PREF_HASH = 629847102UL;
@@ -152,10 +152,7 @@ void OutgoingConnectionManager::loop(APIServer *server) {
void OutgoingConnectionManager::try_dial_(APIServer *server, uint32_t now) { void OutgoingConnectionManager::try_dial_(APIServer *server, uint32_t now) {
if (!network::is_connected()) { if (!network::is_connected()) {
// Flips within seconds of boot; recheck fast so a deep sleep wake return; // still WAITING with the wait elapsed, so the next loop rechecks
// window is not spent waiting
this->schedule_wait_(now, NETWORK_RETRY_MS);
return;
} }
struct sockaddr_storage addr; struct sockaddr_storage addr;
socklen_t addr_len = this->target_sockaddr_(&addr); socklen_t addr_len = this->target_sockaddr_(&addr);
@@ -197,7 +194,6 @@ void OutgoingConnectionManager::try_dial_(APIServer *server, uint32_t now) {
} }
this->state_ = DialState::DIAL_STATE_CONNECTING; this->state_ = DialState::DIAL_STATE_CONNECTING;
this->state_ts_ = now; this->state_ts_ = now;
this->last_poll_ = now;
} }
void OutgoingConnectionManager::poll_connect_(APIServer *server, uint32_t now) { void OutgoingConnectionManager::poll_connect_(APIServer *server, uint32_t now) {
@@ -206,10 +202,6 @@ void OutgoingConnectionManager::poll_connect_(APIServer *server, uint32_t now) {
this->schedule_retry_(now); this->schedule_retry_(now);
return; return;
} }
if (now - this->last_poll_ < CONNECT_POLL_INTERVAL_MS) {
return;
}
this->last_poll_ = now;
int err = 0; int err = 0;
switch (socket::poll_connect(*this->dial_socket_, err)) { switch (socket::poll_connect(*this->dial_socket_, err)) {
case socket::ConnectPollResult::CONNECT_POLL_RESULT_PENDING: case socket::ConnectPollResult::CONNECT_POLL_RESULT_PENDING:
@@ -59,8 +59,6 @@ class OutgoingConnectionManager {
static constexpr uint32_t BACKOFF_MIN_MS = 5000; static constexpr uint32_t BACKOFF_MIN_MS = 5000;
static constexpr uint32_t BACKOFF_MAX_MS = 300000; static constexpr uint32_t BACKOFF_MAX_MS = 300000;
static constexpr uint32_t CONNECT_TIMEOUT_MS = 10000; static constexpr uint32_t CONNECT_TIMEOUT_MS = 10000;
static constexpr uint32_t CONNECT_POLL_INTERVAL_MS = 250;
static constexpr uint32_t NETWORK_RETRY_MS = 500;
static constexpr uint32_t PRECONDITION_RETRY_MS = 5000; static constexpr uint32_t PRECONDITION_RETRY_MS = 5000;
// A deep sleep wake window is too short to spend on the delay, so those // A deep sleep wake window is too short to spend on the delay, so those
// builds dial out as soon as the target is gone // builds dial out as soon as the target is gone
@@ -104,7 +102,6 @@ class OutgoingConnectionManager {
uint32_t backoff_{BACKOFF_MIN_MS}; uint32_t backoff_{BACKOFF_MIN_MS};
uint32_t wait_{BOOT_WAIT_MS}; uint32_t wait_{BOOT_WAIT_MS};
uint32_t state_ts_{0}; uint32_t state_ts_{0};
uint32_t last_poll_{0};
// Byte-aligned types last // Byte-aligned types last
#ifndef API_OUTGOING_CONNECTION_HOST #ifndef API_OUTGOING_CONNECTION_HOST
+10 -4
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) { uint8_t *SendspinCapabilities::encode_msg(const void *self, uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM) {
const auto &msg = *static_cast<const SendspinCapabilities *>(self); const auto &msg = *static_cast<const SendspinCapabilities *>(self);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, msg.feature_flags); 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; return pos;
} }
uint32_t SendspinCapabilities::calc_size_msg(const void *self) { uint32_t SendspinCapabilities::calc_size_msg(const void *self) {
const auto &msg = *static_cast<const SendspinCapabilities *>(self); const auto &msg = *static_cast<const SendspinCapabilities *>(self);
uint32_t size = 0; uint32_t size = 0;
size += ProtoSize::calc_uint32(1, msg.feature_flags); size += ProtoSize::calc_uint32(1, msg.feature_flags);
size += !msg.client_id.empty() ? 2 + msg.client_id.size() : 0;
return size; return size;
} }
#endif #endif
@@ -688,8 +690,8 @@ uint8_t *ListEntitiesLightResponse::encode_msg(const void *self, uint8_t *__rest
if (uint32_t raw = float_to_raw(msg.max_mireds); raw != 0) [[likely]] { if (uint32_t raw = float_to_raw(msg.max_mireds); raw != 0) [[likely]] {
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 85, raw); pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 85, raw);
} }
for (const auto &it : *msg.effects) { for (const char *it : *msg.effects) {
pos = ProtoEncode::encode_string_force(pos PROTO_ENCODE_DEBUG_ARG, 11, it); pos = ProtoEncode::encode_string_force(pos PROTO_ENCODE_DEBUG_ARG, 11, it, strlen(it));
} }
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 13, msg.disabled_by_default); pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 13, msg.disabled_by_default);
#ifdef USE_ENTITY_ICON #ifdef USE_ENTITY_ICON
@@ -713,8 +715,8 @@ uint32_t ListEntitiesLightResponse::calc_size_msg(const void *self) {
size += ProtoSize::calc_float(1, msg.min_mireds); size += ProtoSize::calc_float(1, msg.min_mireds);
size += ProtoSize::calc_float(1, msg.max_mireds); size += ProtoSize::calc_float(1, msg.max_mireds);
if (!msg.effects->empty()) { if (!msg.effects->empty()) {
for (const auto &it : *msg.effects) { for (const char *it : *msg.effects) {
size += ProtoSize::calc_length_force(1, it.size()); size += ProtoSize::calc_length_force(1, strlen(it));
} }
} }
size += ProtoSize::calc_bool(1, msg.disabled_by_default); size += ProtoSize::calc_bool(1, msg.disabled_by_default);
@@ -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, 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, 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, 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; return pos;
} }
uint32_t UsbDeviceDescriptor::calc_size_msg(const void *self) { 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.product_id);
size += ProtoSize::calc_uint32(1, msg.bcd_device); size += ProtoSize::calc_uint32(1, msg.bcd_device);
size += ProtoSize::calc_uint32(1, msg.interface_number); 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; return size;
} }
uint8_t *SerialProxyIdentity::encode_msg(const void *self, uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM) { uint8_t *SerialProxyIdentity::encode_msg(const void *self, uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM) {
+4 -1
View File
@@ -750,6 +750,7 @@ class WizardCapabilities final : public ProtoMessage {
class SendspinCapabilities final : public ProtoMessage { class SendspinCapabilities final : public ProtoMessage {
public: public:
uint32_t feature_flags{0}; 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); 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 { uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
return encode_msg(this, buffer.get_pos() PROTO_ENCODE_DEBUG_ARG); return encode_msg(this, buffer.get_pos() PROTO_ENCODE_DEBUG_ARG);
@@ -1059,7 +1060,7 @@ class ListEntitiesLightResponse final : public InfoResponseProtoMessage {
const light::ColorModeMask *supported_color_modes{}; const light::ColorModeMask *supported_color_modes{};
float min_mireds{0.0f}; float min_mireds{0.0f};
float max_mireds{0.0f}; float max_mireds{0.0f};
const light::LightEffectNames *effects{}; const FixedVector<const char *> *effects{};
static uint8_t *encode_msg(const void *self, uint8_t *pos PROTO_ENCODE_DEBUG_PARAM); 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 { uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
return encode_msg(this, buffer.get_pos() PROTO_ENCODE_DEBUG_ARG); return encode_msg(this, buffer.get_pos() PROTO_ENCODE_DEBUG_ARG);
@@ -4083,6 +4084,8 @@ class UsbDeviceDescriptor final : public ProtoMessage {
uint32_t product_id{0}; uint32_t product_id{0};
uint32_t bcd_device{0}; uint32_t bcd_device{0};
uint32_t interface_number{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); 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 { uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
return encode_msg(this, buffer.get_pos() PROTO_ENCODE_DEBUG_ARG); return encode_msg(this, buffer.get_pos() PROTO_ENCODE_DEBUG_ARG);
+3
View File
@@ -1119,6 +1119,7 @@ const char *WizardCapabilities::dump_to(DumpBuffer &out) const {
const char *SendspinCapabilities::dump_to(DumpBuffer &out) const { const char *SendspinCapabilities::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("SendspinCapabilities")); MessageDumpHelper helper(out, ESPHOME_PSTR("SendspinCapabilities"));
dump_field(out, ESPHOME_PSTR("feature_flags"), this->feature_flags); dump_field(out, ESPHOME_PSTR("feature_flags"), this->feature_flags);
dump_field(out, ESPHOME_PSTR("client_id"), this->client_id);
return out.c_str(); return out.c_str();
} }
#endif #endif
@@ -2942,6 +2943,8 @@ const char *UsbDeviceDescriptor::dump_to(DumpBuffer &out) const {
dump_field(out, ESPHOME_PSTR("product_id"), this->product_id); 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("bcd_device"), this->bcd_device);
dump_field(out, ESPHOME_PSTR("interface_number"), this->interface_number); 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(); return out.c_str();
} }
const char *SerialProxyIdentity::dump_to(DumpBuffer &out) const { const char *SerialProxyIdentity::dump_to(DumpBuffer &out) const {
@@ -15,7 +15,6 @@
#endif #endif
#ifdef USE_LIGHT #ifdef USE_LIGHT
#include "esphome/components/light/light_effect_names.h"
#include "esphome/components/light/light_traits.h" #include "esphome/components/light/light_traits.h"
#endif #endif
Loaded 100 of 2194 files, more files were not shown because too many files have changed in this diff. Show more