mirror of
https://github.com/esphome/esphome.git
synced 2024-12-28 08:21:44 +01:00
commit
ec683fc227
11 changed files with 143 additions and 41 deletions
|
@ -2,6 +2,7 @@ import esphome.codegen as cg
|
|||
import esphome.config_validation as cv
|
||||
from esphome.components import i2c
|
||||
from esphome.const import CONF_ID
|
||||
from esphome.core import CORE
|
||||
|
||||
CODEOWNERS = ["@trvrnrth"]
|
||||
DEPENDENCIES = ["i2c"]
|
||||
|
@ -44,7 +45,8 @@ CONFIG_SCHEMA = cv.Schema(
|
|||
cv.Optional(
|
||||
CONF_STATE_SAVE_INTERVAL, default="6hours"
|
||||
): cv.positive_time_period_minutes,
|
||||
}
|
||||
},
|
||||
cv.only_with_arduino,
|
||||
).extend(i2c.i2c_device_schema(0x76))
|
||||
|
||||
|
||||
|
@ -60,5 +62,9 @@ async def to_code(config):
|
|||
var.set_state_save_interval(config[CONF_STATE_SAVE_INTERVAL].total_milliseconds)
|
||||
)
|
||||
|
||||
if CORE.is_esp32:
|
||||
# Although this component does not use SPI, the BSEC library requires the SPI library
|
||||
cg.add_library("SPI", None)
|
||||
|
||||
cg.add_define("USE_BSEC")
|
||||
cg.add_library("BSEC Software Library", "1.6.1480")
|
||||
|
|
|
@ -21,12 +21,16 @@ from esphome.core import CORE, HexInt
|
|||
import esphome.config_validation as cv
|
||||
import esphome.codegen as cg
|
||||
|
||||
from .const import (
|
||||
from .const import ( # noqa
|
||||
KEY_BOARD,
|
||||
KEY_ESP32,
|
||||
KEY_SDKCONFIG_OPTIONS,
|
||||
KEY_VARIANT,
|
||||
VARIANT_ESP32,
|
||||
VARIANT_ESP32S2,
|
||||
VARIANT_ESP32S3,
|
||||
VARIANT_ESP32C3,
|
||||
VARIANT_ESP32H2,
|
||||
VARIANTS,
|
||||
)
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ optional<LightColorValues> AddressableLightTransformer::apply() {
|
|||
// dynamically-calculated alpha values to match the look.
|
||||
|
||||
float denom = (1.0f - smoothed_progress);
|
||||
float alpha = denom == 0.0f ? 0.0f : (smoothed_progress - this->last_transition_progress_) / denom;
|
||||
float alpha = denom == 0.0f ? 1.0f : (smoothed_progress - this->last_transition_progress_) / denom;
|
||||
|
||||
// We need to use a low-resolution alpha here which makes the transition set in only after ~half of the length
|
||||
// We solve this by accumulating the fractional part of the alpha over time.
|
||||
|
|
|
@ -16,24 +16,94 @@ class AddressableLightWrapper : public light::AddressableLight {
|
|||
|
||||
void clear_effect_data() override { this->wrapper_state_[4] = 0; }
|
||||
|
||||
light::LightTraits get_traits() override { return this->light_state_->get_traits(); }
|
||||
light::LightTraits get_traits() override {
|
||||
LightTraits traits;
|
||||
|
||||
// Choose which color mode to use.
|
||||
// This is ordered by how closely each color mode matches the underlying RGBW data structure used in LightPartition.
|
||||
ColorMode color_mode_precedence[] = {ColorMode::RGB_WHITE,
|
||||
ColorMode::RGB_COLD_WARM_WHITE,
|
||||
ColorMode::RGB_COLOR_TEMPERATURE,
|
||||
ColorMode::RGB,
|
||||
ColorMode::WHITE,
|
||||
ColorMode::COLD_WARM_WHITE,
|
||||
ColorMode::COLOR_TEMPERATURE,
|
||||
ColorMode::BRIGHTNESS,
|
||||
ColorMode::ON_OFF,
|
||||
ColorMode::UNKNOWN};
|
||||
|
||||
LightTraits parent_traits = this->light_state_->get_traits();
|
||||
for (auto cm : color_mode_precedence) {
|
||||
if (parent_traits.supports_color_mode(cm)) {
|
||||
this->color_mode_ = cm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Report a color mode that's compatible with both the partition and the underlying light
|
||||
switch (this->color_mode_) {
|
||||
case ColorMode::RGB_WHITE:
|
||||
case ColorMode::RGB_COLD_WARM_WHITE:
|
||||
case ColorMode::RGB_COLOR_TEMPERATURE:
|
||||
traits.set_supported_color_modes({light::ColorMode::RGB_WHITE});
|
||||
break;
|
||||
|
||||
case ColorMode::RGB:
|
||||
traits.set_supported_color_modes({light::ColorMode::RGB});
|
||||
break;
|
||||
|
||||
case ColorMode::WHITE:
|
||||
case ColorMode::COLD_WARM_WHITE:
|
||||
case ColorMode::COLOR_TEMPERATURE:
|
||||
case ColorMode::BRIGHTNESS:
|
||||
traits.set_supported_color_modes({light::ColorMode::BRIGHTNESS});
|
||||
break;
|
||||
|
||||
case ColorMode::ON_OFF:
|
||||
traits.set_supported_color_modes({light::ColorMode::ON_OFF});
|
||||
break;
|
||||
|
||||
default:
|
||||
traits.set_supported_color_modes({light::ColorMode::UNKNOWN});
|
||||
}
|
||||
|
||||
return traits;
|
||||
}
|
||||
|
||||
void write_state(light::LightState *state) override {
|
||||
// Don't overwrite state if the underlying light is turned on
|
||||
if (this->light_state_->remote_values.is_on()) {
|
||||
this->mark_shown_();
|
||||
return;
|
||||
}
|
||||
|
||||
float gamma = this->light_state_->get_gamma_correct();
|
||||
float r = gamma_uncorrect(this->wrapper_state_[0] / 255.0f, gamma);
|
||||
float g = gamma_uncorrect(this->wrapper_state_[1] / 255.0f, gamma);
|
||||
float b = gamma_uncorrect(this->wrapper_state_[2] / 255.0f, gamma);
|
||||
float w = gamma_uncorrect(this->wrapper_state_[3] / 255.0f, gamma);
|
||||
float brightness = fmaxf(r, fmaxf(g, b));
|
||||
|
||||
auto call = this->light_state_->make_call();
|
||||
call.set_state(true);
|
||||
call.set_brightness_if_supported(1.0f);
|
||||
call.set_color_brightness_if_supported(brightness);
|
||||
call.set_red_if_supported(r);
|
||||
call.set_green_if_supported(g);
|
||||
call.set_blue_if_supported(b);
|
||||
call.set_white_if_supported(w);
|
||||
|
||||
float color_brightness = fmaxf(r, fmaxf(g, b));
|
||||
float brightness = fmaxf(color_brightness, w);
|
||||
if (brightness == 0.0f) {
|
||||
call.set_state(false);
|
||||
} else {
|
||||
color_brightness /= brightness;
|
||||
w /= brightness;
|
||||
|
||||
call.set_state(true);
|
||||
call.set_color_mode_if_supported(this->color_mode_);
|
||||
call.set_brightness_if_supported(brightness);
|
||||
call.set_color_brightness_if_supported(color_brightness);
|
||||
call.set_red_if_supported(r);
|
||||
call.set_green_if_supported(g);
|
||||
call.set_blue_if_supported(b);
|
||||
call.set_white_if_supported(w);
|
||||
call.set_warm_white_if_supported(w);
|
||||
call.set_cold_white_if_supported(w);
|
||||
}
|
||||
call.set_transition_length_if_supported(0);
|
||||
call.set_publish(false);
|
||||
call.set_save(false);
|
||||
|
@ -50,6 +120,7 @@ class AddressableLightWrapper : public light::AddressableLight {
|
|||
|
||||
light::LightState *light_state_;
|
||||
uint8_t *wrapper_state_;
|
||||
ColorMode color_mode_{ColorMode::UNKNOWN};
|
||||
};
|
||||
|
||||
} // namespace light
|
||||
|
|
|
@ -39,7 +39,15 @@ class LightTransformer {
|
|||
|
||||
protected:
|
||||
/// The progress of this transition, on a scale of 0 to 1.
|
||||
float get_progress_() { return clamp((millis() - this->start_time_) / float(this->length_), 0.0f, 1.0f); }
|
||||
float get_progress_() {
|
||||
uint32_t now = esphome::millis();
|
||||
if (now < this->start_time_)
|
||||
return 0.0f;
|
||||
if (now >= this->start_time_ + this->length_)
|
||||
return 1.0f;
|
||||
|
||||
return clamp((now - this->start_time_) / float(this->length_), 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
uint32_t start_time_;
|
||||
uint32_t length_;
|
||||
|
|
|
@ -18,10 +18,13 @@ class LightTransitionTransformer : public LightTransformer {
|
|||
this->start_values_.set_brightness(0.0f);
|
||||
}
|
||||
|
||||
// When turning light off from on state, use source state and only decrease brightness to zero.
|
||||
// When turning light off from on state, use source state and only decrease brightness to zero. Use a second
|
||||
// variable for transition end state, as overwriting target_values breaks LightState logic.
|
||||
if (this->start_values_.is_on() && !this->target_values_.is_on()) {
|
||||
this->target_values_ = LightColorValues(this->start_values_);
|
||||
this->target_values_.set_brightness(0.0f);
|
||||
this->end_values_ = LightColorValues(this->start_values_);
|
||||
this->end_values_.set_brightness(0.0f);
|
||||
} else {
|
||||
this->end_values_ = LightColorValues(this->target_values_);
|
||||
}
|
||||
|
||||
// When changing color mode, go through off state, as color modes are orthogonal and there can't be two active.
|
||||
|
@ -43,7 +46,7 @@ class LightTransitionTransformer : public LightTransformer {
|
|||
}
|
||||
|
||||
LightColorValues &start = this->changing_color_mode_ && p > 0.5f ? this->intermediate_values_ : this->start_values_;
|
||||
LightColorValues &end = this->changing_color_mode_ && p < 0.5f ? this->intermediate_values_ : this->target_values_;
|
||||
LightColorValues &end = this->changing_color_mode_ && p < 0.5f ? this->intermediate_values_ : this->end_values_;
|
||||
if (this->changing_color_mode_)
|
||||
p = p < 0.5f ? p * 2 : (p - 0.5) * 2;
|
||||
|
||||
|
@ -57,6 +60,7 @@ class LightTransitionTransformer : public LightTransformer {
|
|||
static float smoothed_progress(float x) { return x * x * x * (x * (x * 6.0f - 15.0f) + 10.0f); }
|
||||
|
||||
bool changing_color_mode_{false};
|
||||
LightColorValues end_values_{};
|
||||
LightColorValues intermediate_values_{};
|
||||
};
|
||||
|
||||
|
@ -69,9 +73,7 @@ class LightFlashTransformer : public LightTransformer {
|
|||
if (this->transition_length_ * 2 > this->length_)
|
||||
this->transition_length_ = this->length_ / 2;
|
||||
|
||||
// do not create transition if length is 0
|
||||
if (this->transition_length_ == 0)
|
||||
return;
|
||||
this->begun_lightstate_restore_ = false;
|
||||
|
||||
// first transition to original target
|
||||
this->transformer_ = this->state_.get_output()->create_default_transition();
|
||||
|
@ -79,40 +81,45 @@ class LightFlashTransformer : public LightTransformer {
|
|||
}
|
||||
|
||||
optional<LightColorValues> apply() override {
|
||||
// transition transformer does not handle 0 length as progress returns nan
|
||||
if (this->transition_length_ == 0)
|
||||
return this->target_values_;
|
||||
optional<LightColorValues> result = {};
|
||||
|
||||
if (this->transformer_ == nullptr && millis() > this->start_time_ + this->length_ - this->transition_length_) {
|
||||
// second transition back to start value
|
||||
this->transformer_ = this->state_.get_output()->create_default_transition();
|
||||
this->transformer_->setup(this->state_.current_values, this->get_start_values(), this->transition_length_);
|
||||
this->begun_lightstate_restore_ = true;
|
||||
}
|
||||
|
||||
if (this->transformer_ != nullptr) {
|
||||
if (!this->transformer_->is_finished()) {
|
||||
return this->transformer_->apply();
|
||||
} else {
|
||||
result = this->transformer_->apply();
|
||||
|
||||
if (this->transformer_->is_finished()) {
|
||||
this->transformer_->stop();
|
||||
this->transformer_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (millis() > this->start_time_ + this->length_ - this->transition_length_) {
|
||||
// second transition back to start value
|
||||
this->transformer_ = this->state_.get_output()->create_default_transition();
|
||||
this->transformer_->setup(this->state_.current_values, this->get_start_values(), this->transition_length_);
|
||||
}
|
||||
|
||||
// once transition is complete, don't change states until next transition
|
||||
return optional<LightColorValues>();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Restore the original values after the flash.
|
||||
void stop() override {
|
||||
if (this->transformer_ != nullptr) {
|
||||
this->transformer_->stop();
|
||||
this->transformer_ = nullptr;
|
||||
}
|
||||
this->state_.current_values = this->get_start_values();
|
||||
this->state_.remote_values = this->get_start_values();
|
||||
this->state_.publish_state();
|
||||
}
|
||||
|
||||
bool is_finished() override { return this->begun_lightstate_restore_ && LightTransformer::is_finished(); }
|
||||
|
||||
protected:
|
||||
LightState &state_;
|
||||
uint32_t transition_length_;
|
||||
std::unique_ptr<LightTransformer> transformer_{nullptr};
|
||||
bool begun_lightstate_restore_;
|
||||
};
|
||||
|
||||
} // namespace light
|
||||
|
|
|
@ -19,6 +19,7 @@ from esphome.const import (
|
|||
CONF_TX_BUFFER_SIZE,
|
||||
)
|
||||
from esphome.core import CORE, EsphomeError, Lambda, coroutine_with_priority
|
||||
from esphome.components.esp32 import get_esp32_variant, VARIANT_ESP32S2, VARIANT_ESP32C3
|
||||
|
||||
CODEOWNERS = ["@esphome/core"]
|
||||
logger_ns = cg.esphome_ns.namespace("logger")
|
||||
|
@ -52,6 +53,10 @@ LOG_LEVEL_SEVERITY = [
|
|||
"VERY_VERBOSE",
|
||||
]
|
||||
|
||||
ESP32_REDUCED_VARIANTS = [VARIANT_ESP32C3, VARIANT_ESP32S2]
|
||||
|
||||
UART_SELECTION_ESP32_REDUCED = ["UART0", "UART1"]
|
||||
|
||||
UART_SELECTION_ESP32 = ["UART0", "UART1", "UART2"]
|
||||
|
||||
UART_SELECTION_ESP8266 = ["UART0", "UART0_SWAP", "UART1"]
|
||||
|
@ -75,6 +80,8 @@ is_log_level = cv.one_of(*LOG_LEVELS, upper=True)
|
|||
|
||||
def uart_selection(value):
|
||||
if CORE.is_esp32:
|
||||
if get_esp32_variant() in ESP32_REDUCED_VARIANTS:
|
||||
return cv.one_of(*UART_SELECTION_ESP32_REDUCED, upper=True)(value)
|
||||
return cv.one_of(*UART_SELECTION_ESP32, upper=True)(value)
|
||||
if CORE.is_esp8266:
|
||||
return cv.one_of(*UART_SELECTION_ESP8266, upper=True)(value)
|
||||
|
|
|
@ -153,13 +153,9 @@ void Logger::pre_setup() {
|
|||
case UART_SELECTION_UART1:
|
||||
this->hw_serial_ = &Serial1;
|
||||
break;
|
||||
#ifdef USE_ESP32
|
||||
#if defined(USE_ESP32) && !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32S2)
|
||||
case UART_SELECTION_UART2:
|
||||
#if !CONFIG_IDF_TARGET_ESP32S2 && !CONFIG_IDF_TARGET_ESP32C3
|
||||
// FIXME: Validate in config that UART2 can't be set for ESP32-S2 (only has
|
||||
// UART0-UART1)
|
||||
this->hw_serial_ = &Serial2;
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
@ -173,9 +169,11 @@ void Logger::pre_setup() {
|
|||
case UART_SELECTION_UART1:
|
||||
uart_num_ = UART_NUM_1;
|
||||
break;
|
||||
#if defined(USE_ESP32) && !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32S2)
|
||||
case UART_SELECTION_UART2:
|
||||
uart_num_ = UART_NUM_2;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
uart_config_t uart_config{};
|
||||
uart_config.baud_rate = (int) baud_rate_;
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace logger {
|
|||
enum UARTSelection {
|
||||
UART_SELECTION_UART0 = 0,
|
||||
UART_SELECTION_UART1,
|
||||
#ifdef USE_ESP32
|
||||
#if defined(USE_ESP32) && !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32S2)
|
||||
UART_SELECTION_UART2,
|
||||
#endif
|
||||
#ifdef USE_ESP8266
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "sgp30.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/application.h"
|
||||
#include <cinttypes>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"""Constants used by esphome."""
|
||||
|
||||
__version__ = "2021.10.0b2"
|
||||
__version__ = "2021.10.0b3"
|
||||
|
||||
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
|
||||
|
||||
|
|
Loading…
Reference in a new issue