Merge branch 'dev' into nvds-new-espnow

This commit is contained in:
NP v/d Spek 2024-10-13 14:14:48 +02:00 committed by GitHub
commit 1797853f57
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
35 changed files with 441 additions and 855 deletions

View file

@ -22,7 +22,7 @@ runs:
python-version: ${{ inputs.python-version }} python-version: ${{ inputs.python-version }}
- name: Restore Python virtual environment - name: Restore Python virtual environment
id: cache-venv id: cache-venv
uses: actions/cache/restore@v4.1.0 uses: actions/cache/restore@v4.1.1
with: with:
path: venv path: venv
# yamllint disable-line rule:line-length # yamllint disable-line rule:line-length

View file

@ -46,7 +46,7 @@ jobs:
python-version: ${{ env.DEFAULT_PYTHON }} python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment - name: Restore Python virtual environment
id: cache-venv id: cache-venv
uses: actions/cache@v4.1.0 uses: actions/cache@v4.1.1
with: with:
path: venv path: venv
# yamllint disable-line rule:line-length # yamllint disable-line rule:line-length
@ -302,20 +302,22 @@ jobs:
- name: Cache platformio - name: Cache platformio
if: github.ref == 'refs/heads/dev' if: github.ref == 'refs/heads/dev'
uses: actions/cache@v4.1.0 uses: actions/cache@v4.1.1
with: with:
path: ~/.platformio path: ~/.platformio
key: platformio-${{ matrix.pio_cache_key }} key: platformio-${{ matrix.pio_cache_key }}
- name: Cache platformio - name: Cache platformio
if: github.ref != 'refs/heads/dev' if: github.ref != 'refs/heads/dev'
uses: actions/cache/restore@v4.1.0 uses: actions/cache/restore@v4.1.1
with: with:
path: ~/.platformio path: ~/.platformio
key: platformio-${{ matrix.pio_cache_key }} key: platformio-${{ matrix.pio_cache_key }}
- name: Install clang-tidy - name: Install clang-tidy
run: sudo apt-get install clang-tidy-14 run: |
sudo apt-get update
sudo apt-get install clang-tidy-14
- name: Register problem matchers - name: Register problem matchers
run: | run: |
@ -397,7 +399,9 @@ jobs:
file: ${{ fromJson(needs.list-components.outputs.components) }} file: ${{ fromJson(needs.list-components.outputs.components) }}
steps: steps:
- name: Install dependencies - name: Install dependencies
run: sudo apt-get install libsdl2-dev run: |
sudo apt-get update
sudo apt-get install libsdl2-dev
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v4.1.7 uses: actions/checkout@v4.1.7
@ -451,7 +455,9 @@ jobs:
run: echo ${{ matrix.components }} run: echo ${{ matrix.components }}
- name: Install dependencies - name: Install dependencies
run: sudo apt-get install libsdl2-dev run: |
sudo apt-get update
sudo apt-get install libsdl2-dev
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v4.1.7 uses: actions/checkout@v4.1.7

View file

@ -141,7 +141,7 @@ jobs:
echo name=$(cat /tmp/platform) >> $GITHUB_OUTPUT echo name=$(cat /tmp/platform) >> $GITHUB_OUTPUT
- name: Upload digests - name: Upload digests
uses: actions/upload-artifact@v4.4.1 uses: actions/upload-artifact@v4.4.3
with: with:
name: digests-${{ steps.sanitize.outputs.name }} name: digests-${{ steps.sanitize.outputs.name }}
path: /tmp/digests path: /tmp/digests

View file

@ -244,7 +244,7 @@ void CSE7766Component::dump_config() {
LOG_SENSOR(" ", "Apparent Power", this->apparent_power_sensor_); LOG_SENSOR(" ", "Apparent Power", this->apparent_power_sensor_);
LOG_SENSOR(" ", "Reactive Power", this->reactive_power_sensor_); LOG_SENSOR(" ", "Reactive Power", this->reactive_power_sensor_);
LOG_SENSOR(" ", "Power Factor", this->power_factor_sensor_); LOG_SENSOR(" ", "Power Factor", this->power_factor_sensor_);
this->check_uart_settings(4800); this->check_uart_settings(4800, 1, uart::UART_CONFIG_PARITY_EVEN);
} }
} // namespace cse7766 } // namespace cse7766

View file

@ -1,11 +1,10 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome import pins from esphome import pins
import esphome.codegen as cg
from esphome.components import i2c, touchscreen from esphome.components import i2c, touchscreen
from esphome.const import CONF_INTERRUPT_PIN, CONF_ID, CONF_RESET_PIN import esphome.config_validation as cv
from .. import cst816_ns from esphome.const import CONF_ID, CONF_INTERRUPT_PIN, CONF_RESET_PIN
from .. import cst816_ns
CST816Touchscreen = cst816_ns.class_( CST816Touchscreen = cst816_ns.class_(
"CST816Touchscreen", "CST816Touchscreen",
@ -14,11 +13,14 @@ CST816Touchscreen = cst816_ns.class_(
) )
CST816ButtonListener = cst816_ns.class_("CST816ButtonListener") CST816ButtonListener = cst816_ns.class_("CST816ButtonListener")
CONF_SKIP_PROBE = "skip_probe"
CONFIG_SCHEMA = touchscreen.TOUCHSCREEN_SCHEMA.extend( CONFIG_SCHEMA = touchscreen.TOUCHSCREEN_SCHEMA.extend(
{ {
cv.GenerateID(): cv.declare_id(CST816Touchscreen), cv.GenerateID(): cv.declare_id(CST816Touchscreen),
cv.Optional(CONF_INTERRUPT_PIN): pins.internal_gpio_input_pin_schema, cv.Optional(CONF_INTERRUPT_PIN): pins.internal_gpio_input_pin_schema,
cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema,
cv.Optional(CONF_SKIP_PROBE, default=False): cv.boolean,
} }
).extend(i2c.i2c_device_schema(0x15)) ).extend(i2c.i2c_device_schema(0x15))
@ -28,6 +30,7 @@ async def to_code(config):
await touchscreen.register_touchscreen(var, config) await touchscreen.register_touchscreen(var, config)
await i2c.register_i2c_device(var, config) await i2c.register_i2c_device(var, config)
cg.add(var.set_skip_probe(config[CONF_SKIP_PROBE]))
if interrupt_pin := config.get(CONF_INTERRUPT_PIN): if interrupt_pin := config.get(CONF_INTERRUPT_PIN):
cg.add(var.set_interrupt_pin(await cg.gpio_pin_expression(interrupt_pin))) cg.add(var.set_interrupt_pin(await cg.gpio_pin_expression(interrupt_pin)))
if reset_pin := config.get(CONF_RESET_PIN): if reset_pin := config.get(CONF_RESET_PIN):

View file

@ -8,32 +8,33 @@ void CST816Touchscreen::continue_setup_() {
this->interrupt_pin_->setup(); this->interrupt_pin_->setup();
this->attach_interrupt_(this->interrupt_pin_, gpio::INTERRUPT_FALLING_EDGE); this->attach_interrupt_(this->interrupt_pin_, gpio::INTERRUPT_FALLING_EDGE);
} }
if (!this->read_byte(REG_CHIP_ID, &this->chip_id_)) { if (this->read_byte(REG_CHIP_ID, &this->chip_id_)) {
switch (this->chip_id_) {
case CST820_CHIP_ID:
case CST826_CHIP_ID:
case CST716_CHIP_ID:
case CST816S_CHIP_ID:
case CST816D_CHIP_ID:
case CST816T_CHIP_ID:
break;
default:
this->mark_failed();
this->status_set_error(str_sprintf("Unknown chip ID 0x%02X", this->chip_id_).c_str());
return;
}
this->write_byte(REG_IRQ_CTL, IRQ_EN_MOTION);
} else if (!this->skip_probe_) {
this->status_set_error("Failed to read chip id");
this->mark_failed(); this->mark_failed();
esph_log_e(TAG, "Failed to read chip id");
return; return;
} }
switch (this->chip_id_) {
case CST820_CHIP_ID:
case CST826_CHIP_ID:
case CST716_CHIP_ID:
case CST816S_CHIP_ID:
case CST816D_CHIP_ID:
case CST816T_CHIP_ID:
break;
default:
this->mark_failed();
esph_log_e(TAG, "Unknown chip ID 0x%02X", this->chip_id_);
return;
}
this->write_byte(REG_IRQ_CTL, IRQ_EN_MOTION);
if (this->x_raw_max_ == this->x_raw_min_) { if (this->x_raw_max_ == this->x_raw_min_) {
this->x_raw_max_ = this->display_->get_native_width(); this->x_raw_max_ = this->display_->get_native_width();
} }
if (this->y_raw_max_ == this->y_raw_min_) { if (this->y_raw_max_ == this->y_raw_min_) {
this->y_raw_max_ = this->display_->get_native_height(); this->y_raw_max_ = this->display_->get_native_height();
} }
esph_log_config(TAG, "CST816 Touchscreen setup complete"); ESP_LOGCONFIG(TAG, "CST816 Touchscreen setup complete");
} }
void CST816Touchscreen::update_button_state_(bool state) { void CST816Touchscreen::update_button_state_(bool state) {
@ -45,7 +46,7 @@ void CST816Touchscreen::update_button_state_(bool state) {
} }
void CST816Touchscreen::setup() { void CST816Touchscreen::setup() {
esph_log_config(TAG, "Setting up CST816 Touchscreen..."); ESP_LOGCONFIG(TAG, "Setting up CST816 Touchscreen...");
if (this->reset_pin_ != nullptr) { if (this->reset_pin_ != nullptr) {
this->reset_pin_->setup(); this->reset_pin_->setup();
this->reset_pin_->digital_write(true); this->reset_pin_->digital_write(true);
@ -73,7 +74,7 @@ void CST816Touchscreen::update_touches() {
uint16_t x = encode_uint16(data[REG_XPOS_HIGH] & 0xF, data[REG_XPOS_LOW]); uint16_t x = encode_uint16(data[REG_XPOS_HIGH] & 0xF, data[REG_XPOS_LOW]);
uint16_t y = encode_uint16(data[REG_YPOS_HIGH] & 0xF, data[REG_YPOS_LOW]); uint16_t y = encode_uint16(data[REG_YPOS_HIGH] & 0xF, data[REG_YPOS_LOW]);
esph_log_v(TAG, "Read touch %d/%d", x, y); ESP_LOGV(TAG, "Read touch %d/%d", x, y);
if (x >= this->x_raw_max_) { if (x >= this->x_raw_max_) {
this->update_button_state_(true); this->update_button_state_(true);
} else { } else {

View file

@ -45,6 +45,7 @@ class CST816Touchscreen : public touchscreen::Touchscreen, public i2c::I2CDevice
void set_interrupt_pin(InternalGPIOPin *pin) { this->interrupt_pin_ = pin; } void set_interrupt_pin(InternalGPIOPin *pin) { this->interrupt_pin_ = pin; }
void set_reset_pin(GPIOPin *pin) { this->reset_pin_ = pin; } void set_reset_pin(GPIOPin *pin) { this->reset_pin_ = pin; }
void set_skip_probe(bool skip_probe) { this->skip_probe_ = skip_probe; }
protected: protected:
void continue_setup_(); void continue_setup_();
@ -53,6 +54,7 @@ class CST816Touchscreen : public touchscreen::Touchscreen, public i2c::I2CDevice
InternalGPIOPin *interrupt_pin_{}; InternalGPIOPin *interrupt_pin_{};
GPIOPin *reset_pin_{}; GPIOPin *reset_pin_{};
uint8_t chip_id_{}; uint8_t chip_id_{};
bool skip_probe_{}; // if set, do not expect to be able to probe the controller on the i2c bus.
std::vector<CST816ButtonListener *> button_listeners_; std::vector<CST816ButtonListener *> button_listeners_;
bool button_touched_{}; bool button_touched_{};
}; };

View file

@ -36,7 +36,8 @@ std::string DebugComponent::get_reset_reason_() {
break; break;
#if defined(USE_ESP32_VARIANT_ESP32) #if defined(USE_ESP32_VARIANT_ESP32)
case SW_RESET: case SW_RESET:
#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) #elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || \
defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32C6)
case RTC_SW_SYS_RESET: case RTC_SW_SYS_RESET:
#endif #endif
reset_reason = "Software Reset Digital Core"; reset_reason = "Software Reset Digital Core";
@ -72,14 +73,16 @@ std::string DebugComponent::get_reset_reason_() {
case TGWDT_CPU_RESET: case TGWDT_CPU_RESET:
reset_reason = "Timer Group Reset CPU"; reset_reason = "Timer Group Reset CPU";
break; break;
#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) #elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || \
defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32C6)
case TG0WDT_CPU_RESET: case TG0WDT_CPU_RESET:
reset_reason = "Timer Group 0 Reset CPU"; reset_reason = "Timer Group 0 Reset CPU";
break; break;
#endif #endif
#if defined(USE_ESP32_VARIANT_ESP32) #if defined(USE_ESP32_VARIANT_ESP32)
case SW_CPU_RESET: case SW_CPU_RESET:
#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) #elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || \
defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32C6)
case RTC_SW_CPU_RESET: case RTC_SW_CPU_RESET:
#endif #endif
reset_reason = "Software Reset CPU"; reset_reason = "Software Reset CPU";
@ -98,27 +101,32 @@ std::string DebugComponent::get_reset_reason_() {
case RTCWDT_RTC_RESET: case RTCWDT_RTC_RESET:
reset_reason = "RTC Watch Dog Reset Digital Core And RTC Module"; reset_reason = "RTC Watch Dog Reset Digital Core And RTC Module";
break; break;
#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) #if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) || \
defined(USE_ESP32_VARIANT_ESP32C6)
case TG1WDT_CPU_RESET: case TG1WDT_CPU_RESET:
reset_reason = "Timer Group 1 Reset CPU"; reset_reason = "Timer Group 1 Reset CPU";
break; break;
case SUPER_WDT_RESET: case SUPER_WDT_RESET:
reset_reason = "Super Watchdog Reset Digital Core And RTC Module"; reset_reason = "Super Watchdog Reset Digital Core And RTC Module";
break; break;
case GLITCH_RTC_RESET:
reset_reason = "Glitch Reset Digital Core And RTC Module";
break;
case EFUSE_RESET: case EFUSE_RESET:
reset_reason = "eFuse Reset Digital Core"; reset_reason = "eFuse Reset Digital Core";
break; break;
#endif #endif
#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S3) #if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)
case GLITCH_RTC_RESET:
reset_reason = "Glitch Reset Digital Core And RTC Module";
break;
#endif
#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32C6)
case USB_UART_CHIP_RESET: case USB_UART_CHIP_RESET:
reset_reason = "USB UART Reset Digital Core"; reset_reason = "USB UART Reset Digital Core";
break; break;
case USB_JTAG_CHIP_RESET: case USB_JTAG_CHIP_RESET:
reset_reason = "USB JTAG Reset Digital Core"; reset_reason = "USB JTAG Reset Digital Core";
break; break;
#endif
#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S3)
case POWER_GLITCH_RESET: case POWER_GLITCH_RESET:
reset_reason = "Power Glitch Reset Digital Core And RTC Module"; reset_reason = "Power Glitch Reset Digital Core And RTC Module";
break; break;

View file

@ -22,7 +22,7 @@ void ESP32RMTLEDStripLightOutput::setup() {
size_t buffer_size = this->get_buffer_size_(); size_t buffer_size = this->get_buffer_size_();
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE); RAMAllocator<uint8_t> allocator(this->use_psram_ ? 0 : RAMAllocator<uint8_t>::ALLOC_INTERNAL);
this->buf_ = allocator.allocate(buffer_size); this->buf_ = allocator.allocate(buffer_size);
if (this->buf_ == nullptr) { if (this->buf_ == nullptr) {
ESP_LOGE(TAG, "Cannot allocate LED buffer!"); ESP_LOGE(TAG, "Cannot allocate LED buffer!");
@ -37,7 +37,7 @@ void ESP32RMTLEDStripLightOutput::setup() {
return; return;
} }
ExternalRAMAllocator<rmt_item32_t> rmt_allocator(ExternalRAMAllocator<rmt_item32_t>::ALLOW_FAILURE); RAMAllocator<rmt_item32_t> rmt_allocator(this->use_psram_ ? 0 : RAMAllocator<rmt_item32_t>::ALLOC_INTERNAL);
this->rmt_buf_ = rmt_allocator.allocate(buffer_size * 8 + this->rmt_buf_ = rmt_allocator.allocate(buffer_size * 8 +
1); // 8 bits per byte, 1 rmt_item32_t per bit + 1 rmt_item32_t for reset 1); // 8 bits per byte, 1 rmt_item32_t per bit + 1 rmt_item32_t for reset

View file

@ -45,6 +45,7 @@ class ESP32RMTLEDStripLightOutput : public light::AddressableLight {
void set_num_leds(uint16_t num_leds) { this->num_leds_ = num_leds; } void set_num_leds(uint16_t num_leds) { this->num_leds_ = num_leds; }
void set_is_rgbw(bool is_rgbw) { this->is_rgbw_ = is_rgbw; } void set_is_rgbw(bool is_rgbw) { this->is_rgbw_ = is_rgbw; }
void set_is_wrgb(bool is_wrgb) { this->is_wrgb_ = is_wrgb; } void set_is_wrgb(bool is_wrgb) { this->is_wrgb_ = is_wrgb; }
void set_use_psram(bool use_psram) { this->use_psram_ = use_psram; }
/// Set a maximum refresh rate in µs as some lights do not like being updated too often. /// Set a maximum refresh rate in µs as some lights do not like being updated too often.
void set_max_refresh_rate(uint32_t interval_us) { this->max_refresh_rate_ = interval_us; } void set_max_refresh_rate(uint32_t interval_us) { this->max_refresh_rate_ = interval_us; }
@ -75,6 +76,7 @@ class ESP32RMTLEDStripLightOutput : public light::AddressableLight {
uint16_t num_leds_; uint16_t num_leds_;
bool is_rgbw_; bool is_rgbw_;
bool is_wrgb_; bool is_wrgb_;
bool use_psram_;
rmt_item32_t bit0_, bit1_, reset_; rmt_item32_t bit0_, bit1_, reset_;
RGBOrder rgb_order_; RGBOrder rgb_order_;

View file

@ -55,7 +55,7 @@ CHIPSETS = {
"SM16703": LEDStripTimings(300, 900, 900, 300, 0, 0), "SM16703": LEDStripTimings(300, 900, 900, 300, 0, 0),
} }
CONF_USE_PSRAM = "use_psram"
CONF_IS_WRGB = "is_wrgb" CONF_IS_WRGB = "is_wrgb"
CONF_BIT0_HIGH = "bit0_high" CONF_BIT0_HIGH = "bit0_high"
CONF_BIT0_LOW = "bit0_low" CONF_BIT0_LOW = "bit0_low"
@ -77,6 +77,7 @@ CONFIG_SCHEMA = cv.All(
cv.Optional(CONF_CHIPSET): cv.one_of(*CHIPSETS, upper=True), cv.Optional(CONF_CHIPSET): cv.one_of(*CHIPSETS, upper=True),
cv.Optional(CONF_IS_RGBW, default=False): cv.boolean, cv.Optional(CONF_IS_RGBW, default=False): cv.boolean,
cv.Optional(CONF_IS_WRGB, default=False): cv.boolean, cv.Optional(CONF_IS_WRGB, default=False): cv.boolean,
cv.Optional(CONF_USE_PSRAM, default=True): cv.boolean,
cv.Inclusive( cv.Inclusive(
CONF_BIT0_HIGH, CONF_BIT0_HIGH,
"custom", "custom",
@ -145,6 +146,7 @@ async def to_code(config):
cg.add(var.set_rgb_order(config[CONF_RGB_ORDER])) cg.add(var.set_rgb_order(config[CONF_RGB_ORDER]))
cg.add(var.set_is_rgbw(config[CONF_IS_RGBW])) cg.add(var.set_is_rgbw(config[CONF_IS_RGBW]))
cg.add(var.set_is_wrgb(config[CONF_IS_WRGB])) cg.add(var.set_is_wrgb(config[CONF_IS_WRGB]))
cg.add(var.set_use_psram(config[CONF_USE_PSRAM]))
cg.add( cg.add(
var.set_rmt_channel( var.set_rmt_channel(

View file

@ -98,13 +98,13 @@ def validate_pillow_installed(value):
except ImportError as err: except ImportError as err:
raise cv.Invalid( raise cv.Invalid(
"Please install the pillow python package to use this feature. " "Please install the pillow python package to use this feature. "
'(pip install "pillow==10.2.0")' '(pip install "pillow==10.4.0")'
) from err ) from err
if version.parse(PIL.__version__) != version.parse("10.2.0"): if version.parse(PIL.__version__) != version.parse("10.4.0"):
raise cv.Invalid( raise cv.Invalid(
"Please update your pillow installation to 10.2.0. " "Please update your pillow installation to 10.4.0. "
'(pip install "pillow==10.2.0")' '(pip install "pillow==10.4.0")'
) )
return value return value

View file

@ -3,27 +3,39 @@ import esphome.codegen as cg
from esphome.components import mqtt, power_supply, web_server from esphome.components import mqtt, power_supply, web_server
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.const import ( from esphome.const import (
CONF_BLUE,
CONF_BRIGHTNESS,
CONF_COLD_WHITE,
CONF_COLD_WHITE_COLOR_TEMPERATURE, CONF_COLD_WHITE_COLOR_TEMPERATURE,
CONF_COLOR_BRIGHTNESS,
CONF_COLOR_CORRECT, CONF_COLOR_CORRECT,
CONF_COLOR_MODE,
CONF_COLOR_TEMPERATURE,
CONF_DEFAULT_TRANSITION_LENGTH, CONF_DEFAULT_TRANSITION_LENGTH,
CONF_EFFECTS, CONF_EFFECTS,
CONF_FLASH_TRANSITION_LENGTH, CONF_FLASH_TRANSITION_LENGTH,
CONF_GAMMA_CORRECT, CONF_GAMMA_CORRECT,
CONF_GREEN,
CONF_ID, CONF_ID,
CONF_INITIAL_STATE,
CONF_MQTT_ID, CONF_MQTT_ID,
CONF_ON_STATE, CONF_ON_STATE,
CONF_ON_TURN_OFF, CONF_ON_TURN_OFF,
CONF_ON_TURN_ON, CONF_ON_TURN_ON,
CONF_POWER_SUPPLY, CONF_POWER_SUPPLY,
CONF_RED,
CONF_RESTORE_MODE, CONF_RESTORE_MODE,
CONF_STATE,
CONF_TRIGGER_ID, CONF_TRIGGER_ID,
CONF_WARM_WHITE,
CONF_WARM_WHITE_COLOR_TEMPERATURE, CONF_WARM_WHITE_COLOR_TEMPERATURE,
CONF_WEB_SERVER, CONF_WEB_SERVER,
CONF_WHITE,
) )
from esphome.core import coroutine_with_priority from esphome.core import coroutine_with_priority
from esphome.cpp_helpers import setup_entity from esphome.cpp_helpers import setup_entity
from .automation import light_control_to_code # noqa from .automation import LIGHT_STATE_SCHEMA
from .effects import ( from .effects import (
ADDRESSABLE_EFFECTS, ADDRESSABLE_EFFECTS,
BINARY_EFFECTS, BINARY_EFFECTS,
@ -35,8 +47,10 @@ from .effects import (
from .types import ( # noqa from .types import ( # noqa
AddressableLight, AddressableLight,
AddressableLightState, AddressableLightState,
ColorMode,
LightOutput, LightOutput,
LightState, LightState,
LightStateRTCState,
LightStateTrigger, LightStateTrigger,
LightTurnOffTrigger, LightTurnOffTrigger,
LightTurnOnTrigger, LightTurnOnTrigger,
@ -85,6 +99,7 @@ LIGHT_SCHEMA = (
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LightStateTrigger), cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LightStateTrigger),
} }
), ),
cv.Optional(CONF_INITIAL_STATE): LIGHT_STATE_SCHEMA,
} }
) )
) )
@ -145,6 +160,22 @@ async def setup_light_core_(light_var, output_var, config):
cg.add(light_var.set_restore_mode(config[CONF_RESTORE_MODE])) cg.add(light_var.set_restore_mode(config[CONF_RESTORE_MODE]))
if (initial_state_config := config.get(CONF_INITIAL_STATE)) is not None:
initial_state = LightStateRTCState(
initial_state_config.get(CONF_COLOR_MODE, ColorMode.UNKNOWN),
initial_state_config.get(CONF_STATE, False),
initial_state_config.get(CONF_BRIGHTNESS, 1.0),
initial_state_config.get(CONF_COLOR_BRIGHTNESS, 1.0),
initial_state_config.get(CONF_RED, 1.0),
initial_state_config.get(CONF_GREEN, 1.0),
initial_state_config.get(CONF_BLUE, 1.0),
initial_state_config.get(CONF_WHITE, 1.0),
initial_state_config.get(CONF_COLOR_TEMPERATURE, 1.0),
initial_state_config.get(CONF_COLD_WHITE, 1.0),
initial_state_config.get(CONF_WARM_WHITE, 1.0),
)
cg.add(light_var.set_initial_state(initial_state))
if ( if (
default_transition_length := config.get(CONF_DEFAULT_TRANSITION_LENGTH) default_transition_length := config.get(CONF_DEFAULT_TRANSITION_LENGTH)
) is not None: ) is not None:

View file

@ -1,41 +1,42 @@
from esphome import automation
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome import automation
from esphome.const import ( from esphome.const import (
CONF_ID,
CONF_COLOR_MODE,
CONF_TRANSITION_LENGTH,
CONF_STATE,
CONF_FLASH_LENGTH,
CONF_EFFECT,
CONF_BRIGHTNESS,
CONF_COLOR_BRIGHTNESS,
CONF_RED,
CONF_GREEN,
CONF_BLUE, CONF_BLUE,
CONF_WHITE, CONF_BRIGHTNESS,
CONF_COLOR_TEMPERATURE, CONF_BRIGHTNESS_LIMITS,
CONF_COLD_WHITE, CONF_COLD_WHITE,
CONF_WARM_WHITE, CONF_COLOR_BRIGHTNESS,
CONF_COLOR_MODE,
CONF_COLOR_TEMPERATURE,
CONF_EFFECT,
CONF_FLASH_LENGTH,
CONF_GREEN,
CONF_ID,
CONF_LIMIT_MODE,
CONF_MAX_BRIGHTNESS,
CONF_MIN_BRIGHTNESS,
CONF_RANGE_FROM, CONF_RANGE_FROM,
CONF_RANGE_TO, CONF_RANGE_TO,
CONF_BRIGHTNESS_LIMITS, CONF_RED,
CONF_LIMIT_MODE, CONF_STATE,
CONF_MIN_BRIGHTNESS, CONF_TRANSITION_LENGTH,
CONF_MAX_BRIGHTNESS, CONF_WARM_WHITE,
CONF_WHITE,
) )
from .types import ( from .types import (
ColorMode,
COLOR_MODES, COLOR_MODES,
LIMIT_MODES, LIMIT_MODES,
DimRelativeAction,
ToggleAction,
LightState,
LightControlAction,
AddressableLightState, AddressableLightState,
AddressableSet, AddressableSet,
LightIsOnCondition, ColorMode,
DimRelativeAction,
LightControlAction,
LightIsOffCondition, LightIsOffCondition,
LightIsOnCondition,
LightState,
ToggleAction,
) )
@ -62,18 +63,10 @@ async def light_toggle_to_code(config, action_id, template_arg, args):
return var return var
LIGHT_CONTROL_ACTION_SCHEMA = cv.Schema( LIGHT_STATE_SCHEMA = cv.Schema(
{ {
cv.Required(CONF_ID): cv.use_id(LightState),
cv.Optional(CONF_COLOR_MODE): cv.enum(COLOR_MODES, upper=True, space="_"), cv.Optional(CONF_COLOR_MODE): cv.enum(COLOR_MODES, upper=True, space="_"),
cv.Optional(CONF_STATE): cv.templatable(cv.boolean), cv.Optional(CONF_STATE): cv.templatable(cv.boolean),
cv.Exclusive(CONF_TRANSITION_LENGTH, "transformer"): cv.templatable(
cv.positive_time_period_milliseconds
),
cv.Exclusive(CONF_FLASH_LENGTH, "transformer"): cv.templatable(
cv.positive_time_period_milliseconds
),
cv.Exclusive(CONF_EFFECT, "transformer"): cv.templatable(cv.string),
cv.Optional(CONF_BRIGHTNESS): cv.templatable(cv.percentage), cv.Optional(CONF_BRIGHTNESS): cv.templatable(cv.percentage),
cv.Optional(CONF_COLOR_BRIGHTNESS): cv.templatable(cv.percentage), cv.Optional(CONF_COLOR_BRIGHTNESS): cv.templatable(cv.percentage),
cv.Optional(CONF_RED): cv.templatable(cv.percentage), cv.Optional(CONF_RED): cv.templatable(cv.percentage),
@ -85,6 +78,20 @@ LIGHT_CONTROL_ACTION_SCHEMA = cv.Schema(
cv.Optional(CONF_WARM_WHITE): cv.templatable(cv.percentage), cv.Optional(CONF_WARM_WHITE): cv.templatable(cv.percentage),
} }
) )
LIGHT_CONTROL_ACTION_SCHEMA = LIGHT_STATE_SCHEMA.extend(
{
cv.Required(CONF_ID): cv.use_id(LightState),
cv.Exclusive(CONF_TRANSITION_LENGTH, "transformer"): cv.templatable(
cv.positive_time_period_milliseconds
),
cv.Exclusive(CONF_FLASH_LENGTH, "transformer"): cv.templatable(
cv.positive_time_period_milliseconds
),
cv.Exclusive(CONF_EFFECT, "transformer"): cv.templatable(cv.string),
}
)
LIGHT_TURN_OFF_ACTION_SCHEMA = automation.maybe_simple_id( LIGHT_TURN_OFF_ACTION_SCHEMA = automation.maybe_simple_id(
{ {
cv.Required(CONF_ID): cv.use_id(LightState), cv.Required(CONF_ID): cv.use_id(LightState),

View file

@ -1,59 +1,59 @@
from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor from esphome import automation
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome import automation
from esphome.const import ( from esphome.const import (
CONF_NAME,
CONF_LAMBDA,
CONF_UPDATE_INTERVAL,
CONF_TRANSITION_LENGTH,
CONF_COLORS,
CONF_STATE,
CONF_DURATION,
CONF_BRIGHTNESS,
CONF_COLOR_MODE,
CONF_COLOR_BRIGHTNESS,
CONF_RED,
CONF_GREEN,
CONF_BLUE,
CONF_WHITE,
CONF_COLOR_TEMPERATURE,
CONF_COLD_WHITE,
CONF_WARM_WHITE,
CONF_ALPHA, CONF_ALPHA,
CONF_BLUE,
CONF_BRIGHTNESS,
CONF_COLD_WHITE,
CONF_COLOR_BRIGHTNESS,
CONF_COLOR_MODE,
CONF_COLOR_TEMPERATURE,
CONF_COLORS,
CONF_DURATION,
CONF_GREEN,
CONF_INTENSITY, CONF_INTENSITY,
CONF_SPEED, CONF_LAMBDA,
CONF_WIDTH,
CONF_NUM_LEDS,
CONF_RANDOM,
CONF_SEQUENCE,
CONF_MAX_BRIGHTNESS, CONF_MAX_BRIGHTNESS,
CONF_MIN_BRIGHTNESS, CONF_MIN_BRIGHTNESS,
CONF_NAME,
CONF_NUM_LEDS,
CONF_RANDOM,
CONF_RED,
CONF_SEQUENCE,
CONF_SPEED,
CONF_STATE,
CONF_TRANSITION_LENGTH,
CONF_UPDATE_INTERVAL,
CONF_WARM_WHITE,
CONF_WHITE,
CONF_WIDTH,
) )
from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor
from esphome.util import Registry from esphome.util import Registry
from .types import ( from .types import (
ColorMode,
COLOR_MODES, COLOR_MODES,
AddressableColorWipeEffect,
AddressableColorWipeEffectColor,
AddressableFireworksEffect,
AddressableFlickerEffect,
AddressableLambdaLightEffect,
AddressableLightRef,
AddressableRainbowLightEffect,
AddressableRandomTwinkleEffect,
AddressableScanEffect,
AddressableTwinkleEffect,
AutomationLightEffect,
Color,
ColorMode,
FlickerLightEffect,
LambdaLightEffect, LambdaLightEffect,
LightColorValues,
PulseLightEffect, PulseLightEffect,
RandomLightEffect, RandomLightEffect,
StrobeLightEffect, StrobeLightEffect,
StrobeLightEffectColor, StrobeLightEffectColor,
LightColorValues,
AddressableLightRef,
AddressableLambdaLightEffect,
FlickerLightEffect,
AddressableRainbowLightEffect,
AddressableColorWipeEffect,
AddressableColorWipeEffectColor,
AddressableScanEffect,
AddressableTwinkleEffect,
AddressableRandomTwinkleEffect,
AddressableFireworksEffect,
AddressableFlickerEffect,
AutomationLightEffect,
Color,
) )
CONF_ADD_LED_INTERVAL = "add_led_interval" CONF_ADD_LED_INTERVAL = "add_led_interval"

View file

@ -1,6 +1,7 @@
#include "esphome/core/log.h" #include "esphome/core/log.h"
#include "light_state.h"
#include "light_output.h" #include "light_output.h"
#include "light_state.h"
#include "transformers.h" #include "transformers.h"
namespace esphome { namespace esphome {
@ -16,21 +17,6 @@ LightCall LightState::turn_off() { return this->make_call().set_state(false); }
LightCall LightState::toggle() { return this->make_call().set_state(!this->remote_values.is_on()); } LightCall LightState::toggle() { return this->make_call().set_state(!this->remote_values.is_on()); }
LightCall LightState::make_call() { return LightCall(this); } LightCall LightState::make_call() { return LightCall(this); }
struct LightStateRTCState {
ColorMode color_mode{ColorMode::UNKNOWN};
bool state{false};
float brightness{1.0f};
float color_brightness{1.0f};
float red{1.0f};
float green{1.0f};
float blue{1.0f};
float white{1.0f};
float color_temp{1.0f};
float cold_white{1.0f};
float warm_white{1.0f};
uint32_t effect{0};
};
void LightState::setup() { void LightState::setup() {
ESP_LOGCONFIG(TAG, "Setting up light '%s'...", this->get_name().c_str()); ESP_LOGCONFIG(TAG, "Setting up light '%s'...", this->get_name().c_str());
@ -48,6 +34,9 @@ void LightState::setup() {
auto call = this->make_call(); auto call = this->make_call();
LightStateRTCState recovered{}; LightStateRTCState recovered{};
if (this->initial_state_.has_value()) {
recovered = *this->initial_state_;
}
switch (this->restore_mode_) { switch (this->restore_mode_) {
case LIGHT_RESTORE_DEFAULT_OFF: case LIGHT_RESTORE_DEFAULT_OFF:
case LIGHT_RESTORE_DEFAULT_ON: case LIGHT_RESTORE_DEFAULT_ON:
@ -175,6 +164,7 @@ void LightState::set_flash_transition_length(uint32_t flash_transition_length) {
uint32_t LightState::get_flash_transition_length() const { return this->flash_transition_length_; } uint32_t LightState::get_flash_transition_length() const { return this->flash_transition_length_; }
void LightState::set_gamma_correct(float gamma_correct) { this->gamma_correct_ = gamma_correct; } void LightState::set_gamma_correct(float gamma_correct) { this->gamma_correct_ = gamma_correct; }
void LightState::set_restore_mode(LightRestoreMode restore_mode) { this->restore_mode_ = restore_mode; } void LightState::set_restore_mode(LightRestoreMode restore_mode) { this->restore_mode_ = restore_mode; }
void LightState::set_initial_state(const LightStateRTCState &initial_state) { this->initial_state_ = initial_state; }
bool LightState::supports_effects() { return !this->effects_.empty(); } bool LightState::supports_effects() { return !this->effects_.empty(); }
const std::vector<LightEffect *> &LightState::get_effects() const { return this->effects_; } const std::vector<LightEffect *> &LightState::get_effects() const { return this->effects_; }
void LightState::add_effects(const std::vector<LightEffect *> &effects) { void LightState::add_effects(const std::vector<LightEffect *> &effects) {

View file

@ -28,6 +28,35 @@ enum LightRestoreMode {
LIGHT_RESTORE_AND_ON, LIGHT_RESTORE_AND_ON,
}; };
struct LightStateRTCState {
LightStateRTCState(ColorMode color_mode, bool state, float brightness, float color_brightness, float red, float green,
float blue, float white, float color_temp, float cold_white, float warm_white)
: color_mode(color_mode),
state(state),
brightness(brightness),
color_brightness(color_brightness),
red(red),
green(green),
blue(blue),
white(white),
color_temp(color_temp),
cold_white(cold_white),
warm_white(warm_white) {}
LightStateRTCState() = default;
ColorMode color_mode{ColorMode::UNKNOWN};
bool state{false};
float brightness{1.0f};
float color_brightness{1.0f};
float red{1.0f};
float green{1.0f};
float blue{1.0f};
float white{1.0f};
float color_temp{1.0f};
float cold_white{1.0f};
float warm_white{1.0f};
uint32_t effect{0};
};
/** This class represents the communication layer between the front-end MQTT layer and the /** This class represents the communication layer between the front-end MQTT layer and the
* hardware output layer. * hardware output layer.
*/ */
@ -116,6 +145,9 @@ class LightState : public EntityBase, public Component {
/// Set the restore mode of this light /// Set the restore mode of this light
void set_restore_mode(LightRestoreMode restore_mode); void set_restore_mode(LightRestoreMode restore_mode);
/// Set the initial state of this light
void set_initial_state(const LightStateRTCState &initial_state);
/// Return whether the light has any effects that meet the trait requirements. /// Return whether the light has any effects that meet the trait requirements.
bool supports_effects(); bool supports_effects();
@ -212,6 +244,8 @@ class LightState : public EntityBase, public Component {
float gamma_correct_{}; float gamma_correct_{};
/// Restore mode of the light. /// Restore mode of the light.
LightRestoreMode restore_mode_; LightRestoreMode restore_mode_;
/// Initial state of the light.
optional<LightStateRTCState> initial_state_{};
/// List of effects for this light. /// List of effects for this light.
std::vector<LightEffect *> effects_; std::vector<LightEffect *> effects_;

View file

@ -1,5 +1,5 @@
import esphome.codegen as cg
from esphome import automation from esphome import automation
import esphome.codegen as cg
# Base # Base
light_ns = cg.esphome_ns.namespace("light") light_ns = cg.esphome_ns.namespace("light")
@ -12,6 +12,8 @@ AddressableLightRef = AddressableLight.operator("ref")
Color = cg.esphome_ns.class_("Color") Color = cg.esphome_ns.class_("Color")
LightColorValues = light_ns.class_("LightColorValues") LightColorValues = light_ns.class_("LightColorValues")
LightStateRTCState = light_ns.struct("LightStateRTCState")
# Color modes # Color modes
ColorMode = light_ns.enum("ColorMode", is_class=True) ColorMode = light_ns.enum("ColorMode", is_class=True)
COLOR_MODES = { COLOR_MODES = {

View file

@ -34,13 +34,13 @@ async def to_code(config):
widget = widget[0] widget = widget[0]
await wait_for_widgets() await wait_for_widgets()
async with LambdaContext([(cg.std_string, "text_value")]) as control: async with LambdaContext([(cg.std_string, "text_value")]) as control:
await widget.set_property("text", "text_value.c_str())") await widget.set_property("text", "text_value.c_str()")
lv.event_send(widget.obj, API_EVENT, None) lv.event_send(widget.obj, API_EVENT, cg.nullptr)
control.add(textvar.publish_state(widget.get_value())) control.add(textvar.publish_state(widget.get_value()))
async with LambdaContext(EVENT_ARG) as lamb: async with LambdaContext(EVENT_ARG) as lamb:
lv_add(textvar.publish_state(widget.get_value())) lv_add(textvar.publish_state(widget.get_value()))
async with LvContext(paren): async with LvContext(paren):
widget.var.set_control_lambda(await control.get_lambda()) lv_add(textvar.set_control_lambda(await control.get_lambda()))
lv_add( lv_add(
paren.add_event_cb( paren.add_event_cb(
widget.obj, widget.obj,

View file

@ -1,5 +1,7 @@
#include "radon_eye_listener.h" #include "radon_eye_listener.h"
#include "esphome/core/log.h" #include "esphome/core/log.h"
#include <algorithm>
#include <vector>
#ifdef USE_ESP32 #ifdef USE_ESP32
@ -10,9 +12,14 @@ static const char *const TAG = "radon_eye_ble";
bool RadonEyeListener::parse_device(const esp32_ble_tracker::ESPBTDevice &device) { bool RadonEyeListener::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
if (not device.get_name().empty()) { if (not device.get_name().empty()) {
if (device.get_name().rfind("FR:R", 0) == 0) { // Vector containing the prefixes to search for
// This is an RD200, I think std::vector<std::string> prefixes = {"FR:R", "FR:I", "FR:H"};
ESP_LOGD(TAG, "Found Radon Eye RD200 device Name: %s (MAC: %s)", device.get_name().c_str(),
// Check if the device name starts with any of the prefixes
if (std::any_of(prefixes.begin(), prefixes.end(),
[&](const std::string &prefix) { return device.get_name().rfind(prefix, 0) == 0; })) {
// Device found
ESP_LOGD(TAG, "Found Radon Eye device Name: %s (MAC: %s)", device.get_name().c_str(),
device.address_str().c_str()); device.address_str().c_str());
} }
} }

View file

@ -1,8 +1,10 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome import automation from esphome import automation
import esphome.codegen as cg
from esphome.components import binary_sensor from esphome.components import binary_sensor
from esphome.const import CONF_ID, CONF_LAMBDA, CONF_STATE import esphome.config_validation as cv
from esphome.const import CONF_CONDITION, CONF_ID, CONF_LAMBDA, CONF_STATE
from esphome.cpp_generator import LambdaExpression
from .. import template_ns from .. import template_ns
TemplateBinarySensor = template_ns.class_( TemplateBinarySensor = template_ns.class_(
@ -13,7 +15,10 @@ CONFIG_SCHEMA = (
binary_sensor.binary_sensor_schema(TemplateBinarySensor) binary_sensor.binary_sensor_schema(TemplateBinarySensor)
.extend( .extend(
{ {
cv.Optional(CONF_LAMBDA): cv.returning_lambda, cv.Exclusive(CONF_LAMBDA, CONF_CONDITION): cv.returning_lambda,
cv.Exclusive(
CONF_CONDITION, CONF_CONDITION
): automation.validate_potentially_and_condition,
} }
) )
.extend(cv.COMPONENT_SCHEMA) .extend(cv.COMPONENT_SCHEMA)
@ -24,9 +29,17 @@ async def to_code(config):
var = await binary_sensor.new_binary_sensor(config) var = await binary_sensor.new_binary_sensor(config)
await cg.register_component(var, config) await cg.register_component(var, config)
if CONF_LAMBDA in config: if lamb := config.get(CONF_LAMBDA):
template_ = await cg.process_lambda( template_ = await cg.process_lambda(
config[CONF_LAMBDA], [], return_type=cg.optional.template(bool) lamb, [], return_type=cg.optional.template(bool)
)
cg.add(var.set_template(template_))
if condition := config.get(CONF_CONDITION):
condition = await automation.build_condition(
condition, cg.TemplateArguments(), []
)
template_ = LambdaExpression(
f"return {condition.check()};", [], return_type=cg.optional.template(bool)
) )
cg.add(var.set_template(template_)) cg.add(var.set_template(template_))

View file

@ -1,6 +1,6 @@
"""Constants used by esphome.""" """Constants used by esphome."""
__version__ = "2024.10.0-dev" __version__ = "2024.11.0-dev"
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
VALID_SUBSTITUTIONS_CHARACTERS = ( VALID_SUBSTITUTIONS_CHARACTERS = (
@ -398,6 +398,7 @@ CONF_INDOOR = "indoor"
CONF_INFRARED = "infrared" CONF_INFRARED = "infrared"
CONF_INITIAL_MODE = "initial_mode" CONF_INITIAL_MODE = "initial_mode"
CONF_INITIAL_OPTION = "initial_option" CONF_INITIAL_OPTION = "initial_option"
CONF_INITIAL_STATE = "initial_state"
CONF_INITIAL_VALUE = "initial_value" CONF_INITIAL_VALUE = "initial_value"
CONF_INPUT = "input" CONF_INPUT = "input"
CONF_INTEGRATION_TIME = "integration_time" CONF_INTEGRATION_TIME = "integration_time"

View file

@ -651,35 +651,45 @@ void delay_microseconds_safe(uint32_t us);
/// @name Memory management /// @name Memory management
///@{ ///@{
/** An STL allocator that uses SPI RAM. /** An STL allocator that uses SPI or internal RAM.
* Returns `nullptr` in case no memory is available.
* *
* By setting flags, it can be configured to don't try main memory if SPI RAM is full or unavailable, and to return * By setting flags, it can be configured to:
* `nulllptr` instead of aborting when no memory is available. * - perform external allocation falling back to main memory if SPI RAM is full or unavailable
* - perform external allocation only
* - perform internal allocation only
*/ */
template<class T> class ExternalRAMAllocator { template<class T> class RAMAllocator {
public: public:
using value_type = T; using value_type = T;
enum Flags { enum Flags {
NONE = 0, NONE = 0, // Perform external allocation and fall back to internal memory
REFUSE_INTERNAL = 1 << 0, ///< Refuse falling back to internal memory when external RAM is full or unavailable. ALLOC_EXTERNAL = 1 << 0, // Perform external allocation only.
ALLOW_FAILURE = 1 << 1, ///< Don't abort when memory allocation fails. ALLOC_INTERNAL = 1 << 1, // Perform internal allocation only.
ALLOW_FAILURE = 1 << 2, // Does nothing. Kept for compatibility.
}; };
ExternalRAMAllocator() = default; RAMAllocator() = default;
ExternalRAMAllocator(Flags flags) : flags_{flags} {} RAMAllocator(uint8_t flags) : flags_{flags} {}
template<class U> constexpr ExternalRAMAllocator(const ExternalRAMAllocator<U> &other) : flags_{other.flags_} {} template<class U> constexpr RAMAllocator(const RAMAllocator<U> &other) : flags_{other.flags_} {}
T *allocate(size_t n) { T *allocate(size_t n) {
size_t size = n * sizeof(T); size_t size = n * sizeof(T);
T *ptr = nullptr; T *ptr = nullptr;
#ifdef USE_ESP32 #ifdef USE_ESP32
ptr = static_cast<T *>(heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT)); // External allocation by default or if explicitely requested
#endif if ((this->flags_ & Flags::ALLOC_EXTERNAL) || ((this->flags_ & Flags::ALLOC_INTERNAL) == 0)) {
if (ptr == nullptr && (this->flags_ & Flags::REFUSE_INTERNAL) == 0) ptr = static_cast<T *>(heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT));
}
// Fallback to internal allocation if explicitely requested or no flag is specified
if (ptr == nullptr && ((this->flags_ & Flags::ALLOC_INTERNAL) || (this->flags_ & Flags::ALLOC_EXTERNAL) == 0)) {
ptr = static_cast<T *>(malloc(size)); // NOLINT(cppcoreguidelines-owning-memory,cppcoreguidelines-no-malloc) ptr = static_cast<T *>(malloc(size)); // NOLINT(cppcoreguidelines-owning-memory,cppcoreguidelines-no-malloc)
if (ptr == nullptr && (this->flags_ & Flags::ALLOW_FAILURE) == 0) }
abort(); #else
// Ignore ALLOC_EXTERNAL/ALLOC_INTERNAL flags if external allocation is not supported
ptr = static_cast<T *>(malloc(size)); // NOLINT(cppcoreguidelines-owning-memory,cppcoreguidelines-no-malloc)
#endif
return ptr; return ptr;
} }
@ -688,9 +698,11 @@ template<class T> class ExternalRAMAllocator {
} }
private: private:
Flags flags_{Flags::ALLOW_FAILURE}; uint8_t flags_{Flags::ALLOW_FAILURE};
}; };
template<class T> using ExternalRAMAllocator = RAMAllocator<T>;
/// @} /// @}
/// @name Internal functions /// @name Internal functions

View file

@ -1,2 +1,2 @@
pillow==10.2.0 pillow==10.4.0
cairosvg==2.7.1 cairosvg==2.7.1

View file

@ -4,6 +4,7 @@ touchscreen:
interrupt_pin: interrupt_pin:
number: 21 number: 21
reset_pin: GPIO16 reset_pin: GPIO16
skip_probe: false
transform: transform:
mirror_x: false mirror_x: false
mirror_y: false mirror_y: false
@ -11,14 +12,14 @@ touchscreen:
i2c: i2c:
sda: 3 sda: 3
scl: 2 scl: 4
display: display:
- id: my_display - id: my_display
platform: ili9xxx platform: ili9xxx
dimensions: 480x320 dimensions: 480x320
model: ST7796 model: ST7796
cs_pin: 15 cs_pin: 18
dc_pin: 20 dc_pin: 20
reset_pin: 22 reset_pin: 22
transform: transform:

View file

@ -0,0 +1,125 @@
esphome:
on_boot:
then:
- light.toggle: test_binary_light
- light.turn_off: test_rgb_light
- light.turn_on:
id: test_rgb_light
brightness: 100%
red: 100%
green: 100%
blue: 1.0
- light.control:
id: test_monochromatic_light
state: on
- light.dim_relative:
id: test_monochromatic_light
relative_brightness: 5%
brightness_limits:
max_brightness: 90%
light:
- platform: binary
id: test_binary_light
name: Binary Light
output: test_binary
effects:
- strobe:
on_state:
- logger.log: Binary light state changed
- platform: monochromatic
id: test_monochromatic_light
name: Monochromatic Light
output: test_ledc_1
gamma_correct: 2.8
default_transition_length: 2s
effects:
- strobe:
- flicker:
- flicker:
name: My Flicker
alpha: 98%
intensity: 1.5%
- lambda:
name: My Custom Effect
update_interval: 1s
lambda: |-
static int state = 0;
state += 1;
if (state == 4)
state = 0;
- pulse:
transition_length: 10s
update_interval: 20s
min_brightness: 10%
max_brightness: 90%
- pulse:
name: pulse2
transition_length:
on_length: 10s
off_length: 5s
update_interval: 15s
min_brightness: 10%
max_brightness: 90%
- platform: rgb
id: test_rgb_light
name: RGB Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
- platform: rgbw
id: test_rgbw_light
name: RGBW Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
white: test_ledc_4
color_interlock: true
- platform: rgbww
id: test_rgbww_light
name: RGBWW Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
cold_white: test_ledc_4
warm_white: test_ledc_5
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds
color_interlock: true
- platform: rgbct
id: test_rgbct_light
name: RGBCT Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
color_temperature: test_ledc_4
white_brightness: test_ledc_5
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds
color_interlock: true
- platform: cwww
id: test_cwww_light
name: CWWW Light
cold_white: test_ledc_1
warm_white: test_ledc_2
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds
constant_brightness: true
- platform: color_temperature
id: test_color_temperature_light
name: CT Light
color_temperature: test_ledc_1
brightness: test_ledc_2
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds
- platform: rgb
id: test_rgb_light_initial_state
name: RGB Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
initial_state:
color_mode: rgb
red: 100%
green: 50%
blue: 50%

View file

@ -1,23 +1,3 @@
esphome:
on_boot:
then:
- light.toggle: test_binary_light
- light.turn_off: test_rgb_light
- light.turn_on:
id: test_rgb_light
brightness: 100%
red: 100%
green: 100%
blue: 1.0
- light.control:
id: test_monochromatic_light
state: on
- light.dim_relative:
id: test_monochromatic_light
relative_brightness: 5%
brightness_limits:
max_brightness: 90%
output: output:
- platform: gpio - platform: gpio
id: test_binary id: test_binary
@ -38,97 +18,4 @@ output:
id: test_ledc_5 id: test_ledc_5
pin: 17 pin: 17
light: <<: !include common.yaml
- platform: binary
id: test_binary_light
name: Binary Light
output: test_binary
effects:
- strobe:
on_state:
- logger.log: Binary light state changed
- platform: monochromatic
id: test_monochromatic_light
name: Monochromatic Light
output: test_ledc_1
gamma_correct: 2.8
default_transition_length: 2s
effects:
- strobe:
- flicker:
- flicker:
name: My Flicker
alpha: 98%
intensity: 1.5%
- lambda:
name: My Custom Effect
update_interval: 1s
lambda: |-
static int state = 0;
state += 1;
if (state == 4)
state = 0;
- pulse:
transition_length: 10s
update_interval: 20s
min_brightness: 10%
max_brightness: 90%
- pulse:
name: pulse2
transition_length:
on_length: 10s
off_length: 5s
update_interval: 15s
min_brightness: 10%
max_brightness: 90%
- platform: rgb
id: test_rgb_light
name: RGB Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
- platform: rgbw
id: test_rgbw_light
name: RGBW Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
white: test_ledc_4
color_interlock: true
- platform: rgbww
id: test_rgbww_light
name: RGBWW Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
cold_white: test_ledc_4
warm_white: test_ledc_5
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds
color_interlock: true
- platform: rgbct
id: test_rgbct_light
name: RGBCT Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
color_temperature: test_ledc_4
white_brightness: test_ledc_5
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds
color_interlock: true
- platform: cwww
id: test_cwww_light
name: CWWW Light
cold_white: test_ledc_1
warm_white: test_ledc_2
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds
constant_brightness: true
- platform: color_temperature
id: test_color_temperature_light
name: CT Light
color_temperature: test_ledc_1
brightness: test_ledc_2
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds

View file

@ -1,23 +1,3 @@
esphome:
on_boot:
then:
- light.toggle: test_binary_light
- light.turn_off: test_rgb_light
- light.turn_on:
id: test_rgb_light
brightness: 100%
red: 100%
green: 100%
blue: 1.0
- light.control:
id: test_monochromatic_light
state: on
- light.dim_relative:
id: test_monochromatic_light
relative_brightness: 5%
brightness_limits:
max_brightness: 90%
output: output:
- platform: gpio - platform: gpio
id: test_binary id: test_binary
@ -38,97 +18,4 @@ output:
id: test_ledc_5 id: test_ledc_5
pin: 5 pin: 5
light: <<: !include common.yaml
- platform: binary
id: test_binary_light
name: Binary Light
output: test_binary
effects:
- strobe:
on_state:
- logger.log: Binary light state changed
- platform: monochromatic
id: test_monochromatic_light
name: Monochromatic Light
output: test_ledc_1
gamma_correct: 2.8
default_transition_length: 2s
effects:
- strobe:
- flicker:
- flicker:
name: My Flicker
alpha: 98%
intensity: 1.5%
- lambda:
name: My Custom Effect
update_interval: 1s
lambda: |-
static int state = 0;
state += 1;
if (state == 4)
state = 0;
- pulse:
transition_length: 10s
update_interval: 20s
min_brightness: 10%
max_brightness: 90%
- pulse:
name: pulse2
transition_length:
on_length: 10s
off_length: 5s
update_interval: 15s
min_brightness: 10%
max_brightness: 90%
- platform: rgb
id: test_rgb_light
name: RGB Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
- platform: rgbw
id: test_rgbw_light
name: RGBW Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
white: test_ledc_4
color_interlock: true
- platform: rgbww
id: test_rgbww_light
name: RGBWW Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
cold_white: test_ledc_4
warm_white: test_ledc_5
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds
color_interlock: true
- platform: rgbct
id: test_rgbct_light
name: RGBCT Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
color_temperature: test_ledc_4
white_brightness: test_ledc_5
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds
color_interlock: true
- platform: cwww
id: test_cwww_light
name: CWWW Light
cold_white: test_ledc_1
warm_white: test_ledc_2
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds
constant_brightness: true
- platform: color_temperature
id: test_color_temperature_light
name: CT Light
color_temperature: test_ledc_1
brightness: test_ledc_2
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds

View file

@ -1,23 +1,3 @@
esphome:
on_boot:
then:
- light.toggle: test_binary_light
- light.turn_off: test_rgb_light
- light.turn_on:
id: test_rgb_light
brightness: 100%
red: 100%
green: 100%
blue: 1.0
- light.control:
id: test_monochromatic_light
state: on
- light.dim_relative:
id: test_monochromatic_light
relative_brightness: 5%
brightness_limits:
max_brightness: 90%
output: output:
- platform: gpio - platform: gpio
id: test_binary id: test_binary
@ -38,97 +18,4 @@ output:
id: test_ledc_5 id: test_ledc_5
pin: 5 pin: 5
light: <<: !include common.yaml
- platform: binary
id: test_binary_light
name: Binary Light
output: test_binary
effects:
- strobe:
on_state:
- logger.log: Binary light state changed
- platform: monochromatic
id: test_monochromatic_light
name: Monochromatic Light
output: test_ledc_1
gamma_correct: 2.8
default_transition_length: 2s
effects:
- strobe:
- flicker:
- flicker:
name: My Flicker
alpha: 98%
intensity: 1.5%
- lambda:
name: My Custom Effect
update_interval: 1s
lambda: |-
static int state = 0;
state += 1;
if (state == 4)
state = 0;
- pulse:
transition_length: 10s
update_interval: 20s
min_brightness: 10%
max_brightness: 90%
- pulse:
name: pulse2
transition_length:
on_length: 10s
off_length: 5s
update_interval: 15s
min_brightness: 10%
max_brightness: 90%
- platform: rgb
id: test_rgb_light
name: RGB Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
- platform: rgbw
id: test_rgbw_light
name: RGBW Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
white: test_ledc_4
color_interlock: true
- platform: rgbww
id: test_rgbww_light
name: RGBWW Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
cold_white: test_ledc_4
warm_white: test_ledc_5
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds
color_interlock: true
- platform: rgbct
id: test_rgbct_light
name: RGBCT Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
color_temperature: test_ledc_4
white_brightness: test_ledc_5
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds
color_interlock: true
- platform: cwww
id: test_cwww_light
name: CWWW Light
cold_white: test_ledc_1
warm_white: test_ledc_2
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds
constant_brightness: true
- platform: color_temperature
id: test_color_temperature_light
name: CT Light
color_temperature: test_ledc_1
brightness: test_ledc_2
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds

View file

@ -1,23 +1,3 @@
esphome:
on_boot:
then:
- light.toggle: test_binary_light
- light.turn_off: test_rgb_light
- light.turn_on:
id: test_rgb_light
brightness: 100%
red: 100%
green: 100%
blue: 1.0
- light.control:
id: test_monochromatic_light
state: on
- light.dim_relative:
id: test_monochromatic_light
relative_brightness: 5%
brightness_limits:
max_brightness: 90%
output: output:
- platform: gpio - platform: gpio
id: test_binary id: test_binary
@ -38,97 +18,4 @@ output:
id: test_ledc_5 id: test_ledc_5
pin: 17 pin: 17
light: <<: !include common.yaml
- platform: binary
id: test_binary_light
name: Binary Light
output: test_binary
effects:
- strobe:
on_state:
- logger.log: Binary light state changed
- platform: monochromatic
id: test_monochromatic_light
name: Monochromatic Light
output: test_ledc_1
gamma_correct: 2.8
default_transition_length: 2s
effects:
- strobe:
- flicker:
- flicker:
name: My Flicker
alpha: 98%
intensity: 1.5%
- lambda:
name: My Custom Effect
update_interval: 1s
lambda: |-
static int state = 0;
state += 1;
if (state == 4)
state = 0;
- pulse:
transition_length: 10s
update_interval: 20s
min_brightness: 10%
max_brightness: 90%
- pulse:
name: pulse2
transition_length:
on_length: 10s
off_length: 5s
update_interval: 15s
min_brightness: 10%
max_brightness: 90%
- platform: rgb
id: test_rgb_light
name: RGB Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
- platform: rgbw
id: test_rgbw_light
name: RGBW Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
white: test_ledc_4
color_interlock: true
- platform: rgbww
id: test_rgbww_light
name: RGBWW Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
cold_white: test_ledc_4
warm_white: test_ledc_5
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds
color_interlock: true
- platform: rgbct
id: test_rgbct_light
name: RGBCT Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
color_temperature: test_ledc_4
white_brightness: test_ledc_5
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds
color_interlock: true
- platform: cwww
id: test_cwww_light
name: CWWW Light
cold_white: test_ledc_1
warm_white: test_ledc_2
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds
constant_brightness: true
- platform: color_temperature
id: test_color_temperature_light
name: CT Light
color_temperature: test_ledc_1
brightness: test_ledc_2
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds

View file

@ -1,23 +1,3 @@
esphome:
on_boot:
then:
- light.toggle: test_binary_light
- light.turn_off: test_rgb_light
- light.turn_on:
id: test_rgb_light
brightness: 100%
red: 100%
green: 100%
blue: 1.0
- light.control:
id: test_monochromatic_light
state: on
- light.dim_relative:
id: test_monochromatic_light
relative_brightness: 5%
brightness_limits:
max_brightness: 90%
output: output:
- platform: gpio - platform: gpio
id: test_binary id: test_binary
@ -38,97 +18,4 @@ output:
id: test_ledc_5 id: test_ledc_5
pin: 16 pin: 16
light: <<: !include common.yaml
- platform: binary
id: test_binary_light
name: Binary Light
output: test_binary
effects:
- strobe:
on_state:
- logger.log: Binary light state changed
- platform: monochromatic
id: test_monochromatic_light
name: Monochromatic Light
output: test_ledc_1
gamma_correct: 2.8
default_transition_length: 2s
effects:
- strobe:
- flicker:
- flicker:
name: My Flicker
alpha: 98%
intensity: 1.5%
- lambda:
name: My Custom Effect
update_interval: 1s
lambda: |-
static int state = 0;
state += 1;
if (state == 4)
state = 0;
- pulse:
transition_length: 10s
update_interval: 20s
min_brightness: 10%
max_brightness: 90%
- pulse:
name: pulse2
transition_length:
on_length: 10s
off_length: 5s
update_interval: 15s
min_brightness: 10%
max_brightness: 90%
- platform: rgb
id: test_rgb_light
name: RGB Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
- platform: rgbw
id: test_rgbw_light
name: RGBW Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
white: test_ledc_4
color_interlock: true
- platform: rgbww
id: test_rgbww_light
name: RGBWW Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
cold_white: test_ledc_4
warm_white: test_ledc_5
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds
color_interlock: true
- platform: rgbct
id: test_rgbct_light
name: RGBCT Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
color_temperature: test_ledc_4
white_brightness: test_ledc_5
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds
color_interlock: true
- platform: cwww
id: test_cwww_light
name: CWWW Light
cold_white: test_ledc_1
warm_white: test_ledc_2
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds
constant_brightness: true
- platform: color_temperature
id: test_color_temperature_light
name: CT Light
color_temperature: test_ledc_1
brightness: test_ledc_2
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds

View file

@ -1,23 +1,3 @@
esphome:
on_boot:
then:
- light.toggle: test_binary_light
- light.turn_off: test_rgb_light
- light.turn_on:
id: test_rgb_light
brightness: 100%
red: 100%
green: 100%
blue: 1.0
- light.control:
id: test_monochromatic_light
state: on
- light.dim_relative:
id: test_monochromatic_light
relative_brightness: 5%
brightness_limits:
max_brightness: 90%
output: output:
- platform: gpio - platform: gpio
id: test_binary id: test_binary
@ -38,97 +18,4 @@ output:
id: test_ledc_5 id: test_ledc_5
pin: 5 pin: 5
light: <<: !include common.yaml
- platform: binary
id: test_binary_light
name: Binary Light
output: test_binary
effects:
- strobe:
on_state:
- logger.log: Binary light state changed
- platform: monochromatic
id: test_monochromatic_light
name: Monochromatic Light
output: test_ledc_1
gamma_correct: 2.8
default_transition_length: 2s
effects:
- strobe:
- flicker:
- flicker:
name: My Flicker
alpha: 98%
intensity: 1.5%
- lambda:
name: My Custom Effect
update_interval: 1s
lambda: |-
static int state = 0;
state += 1;
if (state == 4)
state = 0;
- pulse:
transition_length: 10s
update_interval: 20s
min_brightness: 10%
max_brightness: 90%
- pulse:
name: pulse2
transition_length:
on_length: 10s
off_length: 5s
update_interval: 15s
min_brightness: 10%
max_brightness: 90%
- platform: rgb
id: test_rgb_light
name: RGB Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
- platform: rgbw
id: test_rgbw_light
name: RGBW Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
white: test_ledc_4
color_interlock: true
- platform: rgbww
id: test_rgbww_light
name: RGBWW Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
cold_white: test_ledc_4
warm_white: test_ledc_5
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds
color_interlock: true
- platform: rgbct
id: test_rgbct_light
name: RGBCT Light
red: test_ledc_1
green: test_ledc_2
blue: test_ledc_3
color_temperature: test_ledc_4
white_brightness: test_ledc_5
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds
color_interlock: true
- platform: cwww
id: test_cwww_light
name: CWWW Light
cold_white: test_ledc_1
warm_white: test_ledc_2
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds
constant_brightness: true
- platform: color_temperature
id: test_color_temperature_light
name: CT Light
color_temperature: test_ledc_1
brightness: test_ledc_2
cold_white_color_temperature: 153 mireds
warm_white_color_temperature: 500 mireds

View file

@ -135,3 +135,9 @@ wifi:
time: time:
platform: sntp platform: sntp
id: time_id id: time_id
text:
- id: lvgl_text
platform: lvgl
widget: hello_label
mode: text

View file

@ -151,6 +151,10 @@ lvgl:
align: center align: center
text_font: montserrat_40 text_font: montserrat_40
border_post: true border_post: true
on_press:
lvgl.label.update:
id: hello_label
text: Goodbye
on_click: on_click:
then: then:
- lvgl.animimg.stop: anim_img - lvgl.animimg.stop: anim_img

View file

@ -46,6 +46,13 @@ binary_sensor:
// Garage Door is closed. // Garage Door is closed.
return false; return false;
} }
- platform: template
id: other_binary_sensor
name: "Garage Door Closed"
condition:
sensor.in_range:
id: template_sens
below: 30.0
output: output:
- platform: template - platform: template