11#ifdef USE_LIGHT_POWER_ESTIMATION
32 for (int32_t i = 0; i <
count; i++) {
34 const uint8_t levels[4] = {view.get_red_raw(), view.get_green_raw(), view.get_blue_raw(), view.get_white_raw()};
35 for (
size_t channel = 0; channel < 4; channel++) {
36 sums[channel] += levels[channel];
37 lit[channel] += levels[channel] != 0;
40 if (slack_ma !=
nullptr) {
43 for (
size_t channel = 0; channel < 4; channel++)
52 for (
size_t channel = 0; channel < 4; channel++)
53 ma += sums[channel] * power.ma_per_level[channel];
59 power.
idle_ma = this->
size() * power.idle_ma_per_led;
60 power.last_frame_ma = NAN;
61 if (std::isnan(power.max_current_ma))
63 power.budget_ma = power.max_current_ma - power.idle_ma;
64 if (power.budget_ma <= 0.0f) {
65 ESP_LOGW(TAG,
"max_current_ma %.0f leaves nothing for the pixels after the idle draw of %.0f mA",
66 power.max_current_ma, power.idle_ma);
71static uint8_t rescale_level(uint8_t level, uint8_t scale, uint8_t previous) {
75 const uint32_t moved = scale < previous ? (scaled + previous - 1) / previous : scaled / previous;
77 return std::clamp<uint32_t>(moved, 1, 255);
83 if (power ==
nullptr || std::isnan(power->budget_ma))
88 const float frame_ma = this->
frame_ma_(&slack_ma);
89 if (frame_ma == power->last_frame_ma)
91 power->last_frame_ma = frame_ma;
94 const float intended_ma = (frame_ma - power->idle_ma) * 255.0f / previous;
96 const uint8_t scale = intended_ma <= power->budget_ma
98 :
static_cast<uint8_t
>(std::max(power->budget_ma / intended_ma * 255.0f, 1.0f));
99 if (scale == previous)
104 if (previous < 255 && scale < previous && frame_ma - power->idle_ma - slack_ma <= power->budget_ma)
109 for (
size_t level = 0; level < 256; level++)
110 map[level] = rescale_level(level, scale, previous);
112 for (
auto view : *
this) {
113 const uint8_t r = map[view.get_red_raw()], g = map[view.get_green_raw()],
b = map[view.get_blue_raw()],
114 w = map[view.get_white_raw()];
115 view.set_raw(r, g,
b, w);
121 power->last_frame_ma = this->
draw_ma_(sums);
128#ifdef USE_LIGHT_POWER_ESTIMATION
133#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
136 ESP_LOGVV(TAG,
"Addressable Light '%s' (effect_active=%s)", name, YESNO(this->
effect_active_));
137 for (
int i = 0; i < this->
size(); i++) {
138 auto color = this->
get(i);
139 ESP_LOGVV(TAG,
" [%2d] Color: R=%3u G=%3u B=%3u W=%3u", i, color.get_red_raw(), color.get_green_raw(),
140 color.get_blue_raw(), color.get_white_raw());
148 return make_unique<AddressableLightTransformer>(*
this);
152 auto r = to_uint8_scale(
val.get_color_brightness() *
val.get_red());
153 auto g = to_uint8_scale(
val.get_color_brightness() *
val.get_green());
154 auto b = to_uint8_scale(
val.get_color_brightness() *
val.get_blue());
155 auto w = to_uint8_scale(
val.get_white());
161 auto max_brightness = to_uint8_scale(
val.get_brightness() *
val.get_state());
182 this->
target_color_ *= to_uint8_scale(end_values.get_brightness() * end_values.get_state());
192 return uint8_t(int32_t(a) - (((int32_t(a) - int32_t(
b)) * scale) / 256));
239 for (int32_t i = 1; i < this->
light_.
size(); i++) {
240 if (this->
light_[i].get() != first) {
267 for (
auto led : this->
light_) {
268 led.set_rgbw(r, g,
b, w);
273 for (
auto led : this->
light_) {
virtual void setup()
Where the component's initialization should happen.
void set_interval(const char *name, uint32_t interval, std::function< void()> &&f)
Set an interval function with a const char* name.
const LogString * get_log_name() const
Get the name for a "%s" log argument (LOG_STR_ARG).
float draw_ma_(const uint32_t sums[4]) const
virtual ESPColorView get_view_internal(int32_t index) const =0
LightState * state_parent_
ESPColorView get(int32_t index)
float frame_ma_(float *slack_ma=nullptr) const
void setup_power_budget_()
float get_estimated_current_ma() const
virtual int32_t size() const =0
void call_setup() override
PowerEstimation * power_estimation_
bool is_effect_active() const
void update_state(LightState *state) override
std::unique_ptr< LightTransformer > create_default_transition() override
ESPColorCorrection correction_
float get_estimated_current_ma() const
void set_power_brightness(uint8_t power_brightness)
void set_local_brightness(uint8_t local_brightness)
uint8_t get_power_brightness() const
This class represents the color state for a light object.
static LightColorValues lerp(const LightColorValues &start, const LightColorValues &end, float completion)
Linearly interpolate between the values in start to the values in end.
This class represents the communication layer between the front-end MQTT layer and the hardware outpu...
void apply_effect_and_transformer_()
bool next_write_
Whether the light value should be written in the next cycle.
LightOutput * output_
Store the output to allow effects to have more access.
Color color_from_light_color_values(LightColorValues val)
Convert the color information from a LightColorValues object to a Color object (does not apply bright...
ESPHOME_LOG_TAG(TAG, "light.addressable")
constexpr uint8_t subtract_scaled_difference(uint8_t a, uint8_t b, int32_t scale)