Various follow-up fixes to color mode changes (#2118)

This commit is contained in:
Oxan van Leeuwen 2021-08-05 01:28:39 +02:00 committed by GitHub
parent 768c71830b
commit 0d104776bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 38 additions and 31 deletions

View File

@ -53,6 +53,9 @@ void LightCall::perform() {
ESP_LOGD(TAG, " Brightness: %.0f%%", v.get_brightness() * 100.0f); ESP_LOGD(TAG, " Brightness: %.0f%%", v.get_brightness() * 100.0f);
} }
if (this->color_brightness_.has_value()) {
ESP_LOGD(TAG, " Color brightness: %.0f%%", v.get_color_brightness() * 100.0f);
}
if (this->red_.has_value() || this->green_.has_value() || this->blue_.has_value()) { if (this->red_.has_value() || this->green_.has_value() || this->blue_.has_value()) {
ESP_LOGD(TAG, " Red: %.0f%%, Green: %.0f%%, Blue: %.0f%%", v.get_red() * 100.0f, v.get_green() * 100.0f, ESP_LOGD(TAG, " Red: %.0f%%, Green: %.0f%%, Blue: %.0f%%", v.get_red() * 100.0f, v.get_green() * 100.0f,
v.get_blue() * 100.0f); v.get_blue() * 100.0f);
@ -149,7 +152,7 @@ LightColorValues LightCall::validate_() {
this->transform_parameters_(); this->transform_parameters_();
// Brightness exists check // Brightness exists check
if (this->brightness_.has_value() && !(color_mode & ColorCapability::BRIGHTNESS)) { if (this->brightness_.has_value() && *this->brightness_ > 0.0f && !(color_mode & ColorCapability::BRIGHTNESS)) {
ESP_LOGW(TAG, "'%s' - This light does not support setting brightness!", name); ESP_LOGW(TAG, "'%s' - This light does not support setting brightness!", name);
this->brightness_.reset(); this->brightness_.reset();
} }
@ -162,13 +165,14 @@ LightColorValues LightCall::validate_() {
} }
// Color brightness exists check // Color brightness exists check
if (this->color_brightness_.has_value() && !(color_mode & ColorCapability::RGB)) { if (this->color_brightness_.has_value() && *this->color_brightness_ > 0.0f && !(color_mode & ColorCapability::RGB)) {
ESP_LOGW(TAG, "'%s' - This color mode does not support setting RGB brightness!", name); ESP_LOGW(TAG, "'%s' - This color mode does not support setting RGB brightness!", name);
this->color_brightness_.reset(); this->color_brightness_.reset();
} }
// RGB exists check // RGB exists check
if (this->red_.has_value() || this->green_.has_value() || this->blue_.has_value()) { if ((this->red_.has_value() && *this->red_ > 0.0f) || (this->green_.has_value() && *this->green_ > 0.0f) ||
(this->blue_.has_value() && *this->blue_ > 0.0f)) {
if (!(color_mode & ColorCapability::RGB)) { if (!(color_mode & ColorCapability::RGB)) {
ESP_LOGW(TAG, "'%s' - This color mode does not support setting RGB color!", name); ESP_LOGW(TAG, "'%s' - This color mode does not support setting RGB color!", name);
this->red_.reset(); this->red_.reset();
@ -178,7 +182,7 @@ LightColorValues LightCall::validate_() {
} }
// White value exists check // White value exists check
if (this->white_.has_value() && if (this->white_.has_value() && *this->white_ > 0.0f &&
!(color_mode & ColorCapability::WHITE || color_mode & ColorCapability::COLD_WARM_WHITE)) { !(color_mode & ColorCapability::WHITE || color_mode & ColorCapability::COLD_WARM_WHITE)) {
ESP_LOGW(TAG, "'%s' - This color mode does not support setting white value!", name); ESP_LOGW(TAG, "'%s' - This color mode does not support setting white value!", name);
this->white_.reset(); this->white_.reset();
@ -192,7 +196,8 @@ LightColorValues LightCall::validate_() {
} }
// Cold/warm white value exists check // Cold/warm white value exists check
if (this->cold_white_.has_value() || this->warm_white_.has_value()) { if ((this->cold_white_.has_value() && *this->cold_white_ > 0.0f) ||
(this->warm_white_.has_value() && *this->warm_white_ > 0.0f)) {
if (!(color_mode & ColorCapability::COLD_WARM_WHITE)) { if (!(color_mode & ColorCapability::COLD_WARM_WHITE)) {
ESP_LOGW(TAG, "'%s' - This color mode does not support setting cold/warm white value!", name); ESP_LOGW(TAG, "'%s' - This color mode does not support setting cold/warm white value!", name);
this->cold_white_.reset(); this->cold_white_.reset();
@ -200,15 +205,15 @@ LightColorValues LightCall::validate_() {
} }
} }
#define VALIDATE_RANGE_(name_, upper_name) \ #define VALIDATE_RANGE_(name_, upper_name, min, max) \
if (name_##_.has_value()) { \ if (name_##_.has_value()) { \
auto val = *name_##_; \ auto val = *name_##_; \
if (val < 0.0f || val > 1.0f) { \ if (val < (min) || val > (max)) { \
ESP_LOGW(TAG, "'%s' - %s value %.2f is out of range [0.0 - 1.0]!", name, upper_name, val); \ ESP_LOGW(TAG, "'%s' - %s value %.2f is out of range [%.1f - %.1f]!", name, upper_name, val, (min), (max)); \
name_##_ = clamp(val, 0.0f, 1.0f); \ name_##_ = clamp(val, (min), (max)); \
} \ } \
} }
#define VALIDATE_RANGE(name, upper_name) VALIDATE_RANGE_(name, upper_name) #define VALIDATE_RANGE(name, upper_name) VALIDATE_RANGE_(name, upper_name, 0.0f, 1.0f)
// Range checks // Range checks
VALIDATE_RANGE(brightness, "Brightness") VALIDATE_RANGE(brightness, "Brightness")
@ -219,6 +224,13 @@ LightColorValues LightCall::validate_() {
VALIDATE_RANGE(white, "White") VALIDATE_RANGE(white, "White")
VALIDATE_RANGE(cold_white, "Cold white") VALIDATE_RANGE(cold_white, "Cold white")
VALIDATE_RANGE(warm_white, "Warm white") VALIDATE_RANGE(warm_white, "Warm white")
VALIDATE_RANGE_(color_temperature, "Color temperature", traits.get_min_mireds(), traits.get_max_mireds())
// Turn off when brightness is set to zero, and reset brightness (so that it has nonzero brightness when turned on).
if (this->brightness_.has_value() && *this->brightness_ == 0.0f) {
this->state_ = optional<float>(false);
this->brightness_ = optional<float>(1.0f);
}
// Set color brightness to 100% if currently zero and a color is set. // Set color brightness to 100% if currently zero and a color is set.
if (this->red_.has_value() || this->green_.has_value() || this->blue_.has_value()) { if (this->red_.has_value() || this->green_.has_value() || this->blue_.has_value()) {
@ -250,7 +262,7 @@ LightColorValues LightCall::validate_() {
if (this->warm_white_.has_value()) if (this->warm_white_.has_value())
v.set_warm_white(*this->warm_white_); v.set_warm_white(*this->warm_white_);
v.normalize_color(traits); v.normalize_color();
// Flash length check // Flash length check
if (this->has_flash_() && *this->flash_length_ == 0) { if (this->has_flash_() && *this->flash_length_ == 0) {

View File

@ -2,6 +2,7 @@
#include "esphome/core/optional.h" #include "esphome/core/optional.h"
#include "light_color_values.h" #include "light_color_values.h"
#include <set>
namespace esphome { namespace esphome {
namespace light { namespace light {

View File

@ -1,12 +1,7 @@
#pragma once #pragma once
#include "esphome/core/helpers.h" #include "esphome/core/helpers.h"
#include "esphome/core/defines.h" #include "color_mode.h"
#include "light_traits.h"
#ifdef USE_JSON
#include "esphome/components/json/json_util.h"
#endif
namespace esphome { namespace esphome {
namespace light { namespace light {
@ -112,7 +107,7 @@ class LightColorValues {
* *
* @param traits Used for determining which attributes to consider. * @param traits Used for determining which attributes to consider.
*/ */
void normalize_color(const LightTraits &traits) { void normalize_color() {
if (this->color_mode_ & ColorCapability::RGB) { if (this->color_mode_ & ColorCapability::RGB) {
float max_value = fmaxf(this->get_red(), fmaxf(this->get_green(), this->get_blue())); float max_value = fmaxf(this->get_red(), fmaxf(this->get_green(), this->get_blue()));
if (max_value == 0.0f) { if (max_value == 0.0f) {
@ -125,13 +120,6 @@ class LightColorValues {
this->set_blue(this->get_blue() / max_value); this->set_blue(this->get_blue() / max_value);
} }
} }
if (this->color_mode_ & ColorCapability::BRIGHTNESS && this->get_brightness() == 0.0f) {
// 0% brightness means off
this->set_state(false);
// reset brightness to 100%
this->set_brightness(1.0f);
}
} }
// Note that method signature of as_* methods is kept as-is for compatibility reasons, so not all parameters // Note that method signature of as_* methods is kept as-is for compatibility reasons, so not all parameters

View File

@ -3,8 +3,6 @@
#include <utility> #include <utility>
#include "esphome/core/component.h" #include "esphome/core/component.h"
#include "light_color_values.h"
#include "light_state.h"
namespace esphome { namespace esphome {
namespace light { namespace light {

View File

@ -1,10 +1,13 @@
#pragma once #pragma once
#include "light_call.h" #include "esphome/core/defines.h"
#include "light_state.h"
#ifdef USE_JSON #ifdef USE_JSON
#include "esphome/components/json/json_util.h"
#include "light_call.h"
#include "light_state.h"
namespace esphome { namespace esphome {
namespace light { namespace light {

View File

@ -7,8 +7,6 @@
namespace esphome { namespace esphome {
namespace light { namespace light {
class LightState;
/// Interface to write LightStates to hardware. /// Interface to write LightStates to hardware.
class LightOutput { class LightOutput {
public: public:

View File

@ -54,6 +54,8 @@ class LightState : public Nameable, public Component {
* property will be changed continuously (in contrast to .remote_values, where they * property will be changed continuously (in contrast to .remote_values, where they
* are constant during transitions). * are constant during transitions).
* *
* This value does not have gamma correction applied.
*
* This property is read-only for users. Any changes to it will be ignored. * This property is read-only for users. Any changes to it will be ignored.
*/ */
LightColorValues current_values; LightColorValues current_values;
@ -64,6 +66,8 @@ class LightState : public Nameable, public Component {
* continuously change the "current" values. But the remote values will immediately * continuously change the "current" values. But the remote values will immediately
* switch to the target value for a transition, reducing the number of packets sent. * switch to the target value for a transition, reducing the number of packets sent.
* *
* This value does not have gamma correction applied.
*
* This property is read-only for users. Any changes to it will be ignored. * This property is read-only for users. Any changes to it will be ignored.
*/ */
LightColorValues remote_values; LightColorValues remote_values;
@ -112,6 +116,7 @@ class LightState : public Nameable, public Component {
/// Add effects for this light state. /// Add effects for this light state.
void add_effects(const std::vector<LightEffect *> &effects); void add_effects(const std::vector<LightEffect *> &effects);
/// The result of all the current_values_as_* methods have gamma correction applied.
void current_values_as_binary(bool *binary); void current_values_as_binary(bool *binary);
void current_values_as_brightness(float *brightness); void current_values_as_brightness(float *brightness);

View File

@ -85,6 +85,8 @@ class LightTransitionTransformer : public LightTransformer {
bool publish_at_end() override { return false; } bool publish_at_end() override { return false; }
bool is_transition() override { return true; } bool is_transition() override { return true; }
// This looks crazy, but it reduces to 6x^5 - 15x^4 + 10x^3 which is just a smooth sigmoid-like
// transition from 0 to 1 on x = [0, 1]
static float smoothed_progress(float x) { return x * x * x * (x * (x * 6.0f - 15.0f) + 10.0f); } static float smoothed_progress(float x) { return x * x * x * (x * (x * 6.0f - 15.0f) + 10.0f); }
protected: protected: