Avoid per-file HTTP HEAD requests during config validation when running
esphome logs against a previously-cached project. The skip_external_update
flag was already plumbed for git operations, but external_files.download_content
ignored it. Thread it through CORE so audio_file, micro_wake_word,
speaker/media_player, image, font, and bme68x_bsec2 reuse cached files
without per-URL network round-trips when the file already exists locally.
The TEMPLATABLE_VALUE C++ fields are typed `int`, but Python codegen
was passing `cg.int32` (`int32_t`). On ESP-IDF/xtensa toolchains where
`int32_t` is `long`, the codegen-generated lambda's function-pointer
type `int32_t (*)(...)` does not match `int (*)(...)`, causing
`TemplatableFn` to select its deprecated casting-trampoline overload
and emit a `-Wdeprecated-declarations` warning at every call site.
Use `cg.int_` so the lambda's return type matches the field exactly.
- Add `--` terminator before submodule paths (both clone and refresh
paths) so a path beginning with `-` cannot be parsed as a git option.
- Reword the refresh-fetch comment: this fetch also runs when ref is
None, in which case it pulls the remote default branch.
Fixesesphome/esphome#11550
When clone_or_update is called with a ref or submodules, the initial
clone uses --depth=1 but the subsequent git fetch and git submodule
update commands run deep, pulling the full history on every refresh.
This causes excess network traffic and disk usage for external_components,
packages, and dashboard imports.
Add --depth=1 to all four call sites (initial fetch, initial submodule
init, refresh fetch, refresh submodule update). Shallow fetches still
advance the local clone to the current remote tip when it moves, so the
refresh path keeps working as before.
The base sensor already logs the published state via the [S]
publish line, so the component-level [D] line was redundant
log spam on every update. Drop it to ESP_LOGV.
Wrap the on_finished_playback CallbackManager storage, registration
method and call site behind USE_RTTTL_FINISHED_PLAYBACK_CALLBACK so
configs without an on_finished_playback automation pay zero RAM and
zero flash for it.
Keeps CallbackManager rather than switching to StaticCallbackManager
because rtttl is MULTI_CONF — a per-class compile-time N would force
every instance to reserve max(callbacks_per_instance) slots.
safe_mode is a single-instance component, so a compile-time-sized
StaticVector backing for the callback list is a clean fit. Drop the
std::vector reallocation machinery (_M_realloc_insert) and size the
storage to the exact number of on_safe_mode automations via
ESPHOME_SAFE_MODE_CALLBACK_COUNT.
get_connection_(msg.address, true) already populates remote_bda_ via
set_address(): either the slot was found because get_address() == msg.address
(so address_ and remote_bda_ already encode it), or a free slot was reserved
and set_address(msg.address) was called, which writes remote_bda_[0..5] from
the same bytes. The follow-up uint64_to_bd_addr(msg.address, connection->remote_bda_)
just rewrites the identical bytes.
- Replace inverted comments in set_min_power/set_max_power clamp lines
(MIN>=MAX>=1.0 → min_power <= max <= 1.0) — pre-existing bug.
- Update FloatOutput class docstring to describe the conditional scaling
behavior under USE_OUTPUT_FLOAT_POWER_SCALING.
- Reword the zero_means_zero codegen comment to explain why we gate on
the value (schema default=False would otherwise force the define on).
- Add templated static_assert stubs for set_min_power/set_max_power/
set_zero_means_zero in the #else branch so calls from lambdas
(documented at esphome.io/components/output/#output-set_min_power_action)
produce a clear compile error pointing at the user's lambda site, with
the migration instruction inline (add 'min_power: 0%' / 'max_power: 100%'
/ 'zero_means_zero: true' to one output entry to enable scaling).
Templating on a default-false bool means the assert only fires on
instantiation (i.e. when the user actually calls the method), not on
every parse — so unused stubs in TUs that include the header (e.g.
output/automation.cpp when scaling actions aren't registered) don't
break the build.
Verified: a lambda calling id(out).set_min_power(0.2) without min_power
in YAML now fails compilation with a pointer at the lambda line and the
inline migration message; adding min_power: 0% to the output entry makes
the same config build clean.
The min_power / max_power / zero_means_zero scaling support on FloatOutput
costs 12 bytes per instance (max_power_, min_power_, zero_means_zero_ +
alignment padding) on every PWM channel, DAC channel, LEDC output, and
dimmer-chip channel — even on configs that never touch the feature.
Repo-wide usage is ~17 YAML lines, mostly in test fixtures and a couple
of LED-driver chip tests; the runtime set_min_power / set_max_power
actions added in #8934 have no usage outside the action's own test.
Add USE_OUTPUT_FLOAT_POWER_SCALING and gate the fields and scaling math
in FloatOutput::set_level() behind it, mirroring the USE_POWER_SUPPLY
pattern already used in BinaryOutput. Python codegen flips the define on
whenever:
- a min_power / max_power / zero_means_zero key is set on any output, or
- a non-default zero_means_zero value is provided, or
- an output.set_min_power / output.set_max_power action is registered
The action class templates (SetMinPowerAction, SetMaxPowerAction) are
also gated on the same define so their non-dependent member access on
FloatOutput::set_min_power doesn't fail to parse when the methods aren't
compiled in. zero_means_zero_ now has a default initializer (was UB
before — it was always written from setup, but only because the schema
default forced it).
For configs without scaling: 12 B .bss saved per FloatOutput instance,
plus a small flash saving from the elided multiply/subtract in
set_level(). For configs with scaling: behavior is unchanged.
Verified on tests/components/esp8266_pwm (no scaling): pstorage 0x28 → 0x1c
per output (40 B → 28 B). Verified on tests/components/output (uses
set_min_power/set_max_power actions): builds correctly with the define on.
On Xtensa under default -mserialize-volatile, GCC emits a memw before
every volatile load. esphome_lwip_socket_has_data() is called once per
socket per main-loop iteration (one for the listening socket in
APIServer::loop and one per connected client in APIConnection::loop),
making per-call memw a measurable cost on the idle path.
Replace the per-call memw with a single std::atomic_thread_fence
(memory_order_acquire) at the top of Application::loop. The fence pairs
with the TCP/IP thread's existing SYS_ARCH_UNPROTECT release on
rcvevent. The wake path (xTaskNotifyGive in the lwip event_callback
hook, ulTaskNotifyTake at the bottom of the loop) is independent of
rcvevent visibility and is non-losing, so writes that land between the
fence and sleep are picked up by the next iteration.
Gated on ESPHOME_THREAD_MULTI_ATOMICS so that BK72xx (which lacks
LDREX/STREX and is built without libatomic) keeps the original volatile
load path. ESP32, RTL87xx and LN882x get the optimization; ESP8266,
RP2040 and host use the socket_ready_fd fallback and are unaffected.
Disassembly (ESP32, gatetrigger): APIServer::loop -8 B, APIConnection
::loop -5 B; loop_task gains one memw for the fence. Net per idle
iteration with N clients: save N memw on ready paths, add 1 for the
fence (savings scale with client count and other Socket::ready callers
like AsyncClient and CaptivePortal DNS).
EsphomeLogsHandler.build_command now appends --no-states to the
spawned `esphome logs` argv when the WebSocket spawn message
includes `no_states: true`. This lets the dashboard frontend
suppress entity-state log lines for OTA log sessions without
requiring users to drop to the CLI.
Adds three unit tests covering the truthy, missing, and explicit-False
cases.