- 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.