[light] Keep the effect list in a flash table (#20204)

Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
This commit is contained in:
J. Nick Koston
2026-10-09 15:55:09 -10:00
committed by GitHub
co-authored by pre-commit-ci-lite[bot]
parent 6b03d68fac
commit 41cc96bbb8
19 changed files with 207 additions and 80 deletions
+2 -1
View File
@@ -32,6 +32,7 @@ esphome:
- lambda: |-
const auto &effects = id(test_monochromatic_light).get_effects();
auto &same = id(test_monochromatic_light).get_effects();
const auto copy = id(test_monochromatic_light).get_effects(); // the view is copyable
uint32_t total = effects.size();
for (auto *effect : effects) {
ESP_LOGD("test", "Effect %s", effect->get_name().c_str());
@@ -39,7 +40,7 @@ esphome:
if (total > 0) {
ESP_LOGD("test", "First %s", effects.at(0)->get_name().c_str());
// Raw pointer iterators on purpose: external code binds std::find's result to `const auto *`
auto *it = std::find(same.begin(), same.end(), effects[0]);
auto *it = std::find(same.begin(), same.end(), copy[0]);
ESP_LOGD("test", "Index %d", (int) (it - same.begin()));
}
@@ -1,6 +1,5 @@
#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"
@@ -18,36 +17,8 @@ class BrightnessOutput : public LightOutput {
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};