mirror of
https://github.com/esphome/esphome.git
synced 2025-09-02 03:12:20 +01:00
[light] Add support for querying effects by index (#10195)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
This commit is contained in:
@@ -44,6 +44,13 @@ class AddressableLightEffect : public LightEffect {
|
||||
this->apply(*this->get_addressable_(), current_color);
|
||||
}
|
||||
|
||||
/// Get effect index specifically for addressable effects.
|
||||
/// Can be used by effects to modify behavior based on their position in the list.
|
||||
uint32_t get_effect_index() const { return this->get_index(); }
|
||||
|
||||
/// Check if this is the currently running addressable effect.
|
||||
bool is_current_effect() const { return this->is_active() && this->get_addressable_()->is_effect_active(); }
|
||||
|
||||
protected:
|
||||
AddressableLight *get_addressable_() const { return (AddressableLight *) this->state_->get_output(); }
|
||||
};
|
||||
|
@@ -125,6 +125,10 @@ class LambdaLightEffect : public LightEffect {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the current effect index for use in lambda functions.
|
||||
/// This can be useful for lambda effects that need to know their own index.
|
||||
uint32_t get_current_index() const { return this->get_index(); }
|
||||
|
||||
protected:
|
||||
std::function<void(bool initial_run)> f_;
|
||||
uint32_t update_interval_;
|
||||
@@ -143,6 +147,10 @@ class AutomationLightEffect : public LightEffect {
|
||||
}
|
||||
Trigger<> *get_trig() const { return trig_; }
|
||||
|
||||
/// Get the current effect index for use in automations.
|
||||
/// Useful for automations that need to know which effect is running.
|
||||
uint32_t get_current_index() const { return this->get_index(); }
|
||||
|
||||
protected:
|
||||
Trigger<> *trig_{new Trigger<>};
|
||||
};
|
||||
|
36
esphome/components/light/light_effect.cpp
Normal file
36
esphome/components/light/light_effect.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#include "light_effect.h"
|
||||
#include "light_state.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace light {
|
||||
|
||||
uint32_t LightEffect::get_index() const {
|
||||
if (this->state_ == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
return this->get_index_in_parent_();
|
||||
}
|
||||
|
||||
bool LightEffect::is_active() const {
|
||||
if (this->state_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return this->get_index() != 0 && this->state_->get_current_effect_index() == this->get_index();
|
||||
}
|
||||
|
||||
uint32_t LightEffect::get_index_in_parent_() const {
|
||||
if (this->state_ == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const auto &effects = this->state_->get_effects();
|
||||
for (size_t i = 0; i < effects.size(); i++) {
|
||||
if (effects[i] == this) {
|
||||
return i + 1; // Effects are 1-indexed in the API
|
||||
}
|
||||
}
|
||||
return 0; // Not found
|
||||
}
|
||||
|
||||
} // namespace light
|
||||
} // namespace esphome
|
@@ -34,9 +34,23 @@ class LightEffect {
|
||||
this->init();
|
||||
}
|
||||
|
||||
/// Get the index of this effect in the parent light's effect list.
|
||||
/// Returns 0 if not found or not initialized.
|
||||
uint32_t get_index() const;
|
||||
|
||||
/// Check if this effect is currently active.
|
||||
bool is_active() const;
|
||||
|
||||
/// Get a reference to the parent light state.
|
||||
/// Returns nullptr if not initialized.
|
||||
LightState *get_light_state() const { return this->state_; }
|
||||
|
||||
protected:
|
||||
LightState *state_{nullptr};
|
||||
std::string name_;
|
||||
|
||||
/// Internal method to find this effect's index in the parent light's effect list.
|
||||
uint32_t get_index_in_parent_() const;
|
||||
};
|
||||
|
||||
} // namespace light
|
||||
|
@@ -36,8 +36,11 @@ static constexpr const char *get_color_mode_json_str(ColorMode mode) {
|
||||
|
||||
void LightJSONSchema::dump_json(LightState &state, JsonObject root) {
|
||||
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
||||
if (state.supports_effects())
|
||||
if (state.supports_effects()) {
|
||||
root["effect"] = state.get_effect_name();
|
||||
root["effect_index"] = state.get_current_effect_index();
|
||||
root["effect_count"] = state.get_effect_count();
|
||||
}
|
||||
|
||||
auto values = state.remote_values;
|
||||
auto traits = state.get_output()->get_traits();
|
||||
@@ -160,6 +163,11 @@ void LightJSONSchema::parse_json(LightState &state, LightCall &call, JsonObject
|
||||
const char *effect = root["effect"];
|
||||
call.set_effect(effect);
|
||||
}
|
||||
|
||||
if (root["effect_index"].is<uint32_t>()) {
|
||||
uint32_t effect_index = root["effect_index"];
|
||||
call.set_effect(effect_index);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace light
|
||||
|
@@ -163,6 +163,44 @@ class LightState : public EntityBase, public Component {
|
||||
/// Add effects for this light state.
|
||||
void add_effects(const std::vector<LightEffect *> &effects);
|
||||
|
||||
/// Get the total number of effects available for this light.
|
||||
size_t get_effect_count() const { return this->effects_.size(); }
|
||||
|
||||
/// Get the currently active effect index (0 = no effect, 1+ = effect index).
|
||||
uint32_t get_current_effect_index() const { return this->active_effect_index_; }
|
||||
|
||||
/// Get effect index by name. Returns 0 if effect not found.
|
||||
uint32_t get_effect_index(const std::string &effect_name) const {
|
||||
if (strcasecmp(effect_name.c_str(), "none") == 0) {
|
||||
return 0;
|
||||
}
|
||||
for (size_t i = 0; i < this->effects_.size(); i++) {
|
||||
if (strcasecmp(effect_name.c_str(), this->effects_[i]->get_name().c_str()) == 0) {
|
||||
return i + 1; // Effects are 1-indexed in active_effect_index_
|
||||
}
|
||||
}
|
||||
return 0; // Effect not found
|
||||
}
|
||||
|
||||
/// Get effect by index. Returns nullptr if index is invalid.
|
||||
LightEffect *get_effect_by_index(uint32_t index) const {
|
||||
if (index == 0 || index > this->effects_.size()) {
|
||||
return nullptr;
|
||||
}
|
||||
return this->effects_[index - 1]; // Effects are 1-indexed in active_effect_index_
|
||||
}
|
||||
|
||||
/// Get effect name by index. Returns "None" for index 0, empty string for invalid index.
|
||||
std::string get_effect_name_by_index(uint32_t index) const {
|
||||
if (index == 0) {
|
||||
return "None";
|
||||
}
|
||||
if (index > this->effects_.size()) {
|
||||
return ""; // Invalid index
|
||||
}
|
||||
return this->effects_[index - 1]->get_name();
|
||||
}
|
||||
|
||||
/// The result of all the current_values_as_* methods have gamma correction applied.
|
||||
void current_values_as_binary(bool *binary);
|
||||
|
||||
|
Reference in New Issue
Block a user