[light] Shrink LightState by 12 bytes per light (#19711)

This commit is contained in:
J. Nick Koston
2026-09-27 11:53:03 +02:00
committed by GitHub
parent ea4754e798
commit 2844236e77
13 changed files with 215 additions and 48 deletions
+2
View File
@@ -8,6 +8,8 @@ def override_manifest(manifest: ComponentManifestOverride) -> None:
cg.add_define("USE_WEBSERVER")
# api_connection.cpp reports the port whenever USE_WEBSERVER is set
cg.add_define("USE_WEBSERVER_PORT", 80)
# The gamma table and its stored gamma are behind this define
cg.add_define("USE_LIGHT_GAMMA_LUT")
manifest.to_code = to_code_testing
manifest.dependencies = manifest.dependencies + ["json"]
+1
View File
@@ -254,6 +254,7 @@ light:
state: INITIAL
brightness: INITIAL
- platform: monochromatic
flash_transition_length: 100ms
id: test_monochromatic_light
name: Monochromatic Light
output: test_ledc_1
@@ -0,0 +1,68 @@
#include <gtest/gtest.h>
#include "esphome/components/light/light_effect.h"
#include "esphome/components/light/light_output.h"
#include "esphome/components/light/light_state.h"
namespace esphome::light::testing {
namespace {
class BrightnessOutput : public LightOutput {
public:
LightTraits get_traits() override {
LightTraits traits;
traits.set_supported_color_modes({ColorMode::BRIGHTNESS});
return traits;
}
void write_state(LightState *state) override {}
};
class NoopEffect : public LightEffect {
public:
using LightEffect::LightEffect;
void apply() override {}
};
// start_effect_() is where the uint32_t index is narrowed to the stored uint16_t.
class TestableLightState : public LightState {
public:
using LightState::LightState;
using LightState::start_effect_;
};
} // namespace
// add_effects() is public, so an external component can exceed the codegen cap on effect count;
// an index the uint16_t can't hold must be ignored rather than wrap onto another effect.
TEST(LightStateEffect, IndexAboveUint16IsIgnoredAndKeepsTheActiveEffect) {
BrightnessOutput output;
TestableLightState state(&output);
NoopEffect effect("Noop");
state.add_effects({&effect});
state.start_effect_(1);
ASSERT_EQ(state.get_current_effect_index(), 1u);
state.start_effect_(0x10000u); // unchecked narrowing wraps this to 0, which stops the effect
EXPECT_EQ(state.get_current_effect_index(), 1u);
}
// get_gamma_correct() reads the gamma codegen stores after the lookup table, rounded to two decimals.
TEST(LightStateGamma, ReadsTheGammaStoredWithTheTable) {
static constexpr GammaTable TABLE{{}, 280};
BrightnessOutput output;
LightState state(&output);
state.set_gamma_table(&TABLE);
EXPECT_FLOAT_EQ(state.get_gamma_correct(), 2.8f);
EXPECT_EQ(state.get_gamma_table(), TABLE.lut);
}
TEST(LightStateGamma, IsZeroWithoutATable) {
BrightnessOutput output;
LightState state(&output);
EXPECT_FLOAT_EQ(state.get_gamma_correct(), 0.0f);
EXPECT_EQ(state.get_gamma_table(), nullptr);
}
} // namespace esphome::light::testing