1
0
mirror of https://github.com/esphome/esphome.git synced 2025-11-01 15:41:52 +00:00

Compare commits

...

21 Commits

Author SHA1 Message Date
Jesse Hills
ae65f76dfe Merge pull request #8272 from esphome/bump-2025.2.0b6
2025.2.0b6
2025-02-19 10:44:08 +13:00
Jesse Hills
4d380214df Bump version to 2025.2.0b6 2025-02-19 09:22:52 +13:00
J. Nick Koston
c5ebf7683e Bump zeroconf to 0.145.1 (#8267) 2025-02-19 09:22:52 +13:00
G-Two
a973adda67 Increase default repeat delay for Toto remote transmitter protocol (#8265) 2025-02-19 09:22:52 +13:00
J. Nick Koston
d9b419eaf5 Bump openssh-client to 1:9.2p1-2+deb12u4 to fix docker builds (#8269) 2025-02-19 09:22:52 +13:00
Jesse Hills
2bc9782ce7 Merge pull request #8264 from esphome/bump-2025.2.0b5
2025.2.0b5
2025-02-18 14:13:33 +13:00
Jesse Hills
6583e17810 Bump version to 2025.2.0b5 2025-02-18 13:39:42 +13:00
J. Nick Koston
64c8bcef2e Bump aioesphomeapi to 29.1.0 (#8105) 2025-02-18 13:39:42 +13:00
J. Nick Koston
f9da8dbfb8 Replace glyphsets with esphome_glyphsets (#8261) 2025-02-18 13:39:42 +13:00
Jesse Hills
26d25464da Merge pull request #8259 from esphome/bump-2025.2.0b4
2025.2.0b4
2025-02-17 13:09:45 +13:00
Jesse Hills
78b55e22ee Bump version to 2025.2.0b4 2025-02-17 12:14:06 +13:00
Ali Jafri
9ee5227fe0 DHT platform now supports modules with inbuilt external resistor (#8257) 2025-02-17 12:14:06 +13:00
J. Nick Koston
e89603fe3b Bump zeroconf to 0.144.3 (#8253) 2025-02-17 12:14:06 +13:00
Djordje Mandic
c0804d665d [scd30] Increase minimal CONF_UPDATE_INTERVAL from 1 to 2 seconds (#8256) 2025-02-17 12:14:05 +13:00
Samuel Sieb
a67b85eabf don't crash on null pages (#8254)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2025-02-17 12:14:05 +13:00
Jesse Hills
6e45a7c9af Merge pull request #8251 from esphome/bump-2025.2.0b3
2025.2.0b3
2025-02-14 16:43:58 +13:00
Jesse Hills
e17582544e Bump version to 2025.2.0b3 2025-02-14 14:28:42 +13:00
Jesse Hills
daa7960031 Fix crash when storage file doesnt exist yet (#8249) 2025-02-14 14:28:41 +13:00
Dániel Márai
6999cc0581 Add support for the DAC on the S2 (#8030)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2025-02-14 14:28:41 +13:00
Jonathan Swoboda
92ad6286aa [logger] Fix bug causing global log level to be overwritten (#8248) 2025-02-14 14:28:41 +13:00
guillempages
1111aa167f [online_image]Fix reset if buffer not allocated (#8236) 2025-02-14 14:28:41 +13:00
20 changed files with 110 additions and 47 deletions

View File

@@ -35,7 +35,7 @@ RUN \
iputils-ping=3:20221126-1+deb12u1 \
git=1:2.39.5-0+deb12u1 \
curl=7.88.1-10+deb12u8 \
openssh-client=1:9.2p1-2+deb12u3 \
openssh-client=1:9.2p1-2+deb12u4 \
python3-cffi=1.15.1-5 \
libcairo2=1.16.0-7 \
libmagic1=1:5.44-3 \

View File

@@ -1,12 +1,11 @@
from __future__ import annotations
import asyncio
import logging
from datetime import datetime
from typing import Any
import logging
from typing import TYPE_CHECKING, Any
from aioesphomeapi import APIClient
from aioesphomeapi.api_pb2 import SubscribeLogsResponse
from aioesphomeapi.log_runner import async_run
from esphome.const import CONF_KEY, CONF_PASSWORD, CONF_PORT, __version__
@@ -14,6 +13,12 @@ from esphome.core import CORE
from . import CONF_ENCRYPTION
if TYPE_CHECKING:
from aioesphomeapi.api_pb2 import (
SubscribeLogsResponse, # pylint: disable=no-name-in-module
)
_LOGGER = logging.getLogger(__name__)

View File

@@ -23,6 +23,7 @@ void DHT::dump_config() {
} else {
ESP_LOGCONFIG(TAG, " Model: DHT22 (or equivalent)");
}
ESP_LOGCONFIG(TAG, " Internal Pull-up: %s", ONOFF(this->pin_->get_flags() & gpio::FLAG_PULLUP));
LOG_UPDATE_INTERVAL(this);
@@ -101,7 +102,7 @@ bool HOT IRAM_ATTR DHT::read_sensor_(float *temperature, float *humidity, bool r
} else {
delayMicroseconds(800);
}
this->pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
this->pin_->pin_mode(this->pin_->get_flags());
{
InterruptLock lock;

View File

@@ -34,7 +34,7 @@ DHT = dht_ns.class_("DHT", cg.PollingComponent)
CONFIG_SCHEMA = cv.Schema(
{
cv.GenerateID(): cv.declare_id(DHT),
cv.Required(CONF_PIN): pins.internal_gpio_input_pin_schema,
cv.Required(CONF_PIN): pins.internal_gpio_input_pullup_pin_schema,
cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
unit_of_measurement=UNIT_CELSIUS,
accuracy_decimals=1,

View File

@@ -815,8 +815,20 @@ void Display::test_card() {
DisplayPage::DisplayPage(display_writer_t writer) : writer_(std::move(writer)) {}
void DisplayPage::show() { this->parent_->show_page(this); }
void DisplayPage::show_next() { this->next_->show(); }
void DisplayPage::show_prev() { this->prev_->show(); }
void DisplayPage::show_next() {
if (this->next_ == nullptr) {
ESP_LOGE(TAG, "no next page");
return;
}
this->next_->show();
}
void DisplayPage::show_prev() {
if (this->prev_ == nullptr) {
ESP_LOGE(TAG, "no previous page");
return;
}
this->prev_->show();
}
void DisplayPage::set_parent(Display *parent) { this->parent_ = parent; }
void DisplayPage::set_prev(DisplayPage *prev) { this->prev_ = prev; }
void DisplayPage::set_next(DisplayPage *next) { this->next_ = next; }

View File

@@ -7,13 +7,16 @@
#ifdef USE_ARDUINO
#include <esp32-hal-dac.h>
#endif
#ifdef USE_ESP_IDF
#include <driver/dac.h>
#endif
namespace esphome {
namespace esp32_dac {
#ifdef USE_ESP32_VARIANT_ESP32S2
static constexpr uint8_t DAC0_PIN = 17;
#else
static constexpr uint8_t DAC0_PIN = 25;
#endif
static const char *const TAG = "esp32_dac";
void ESP32DAC::setup() {
@@ -22,8 +25,15 @@ void ESP32DAC::setup() {
this->turn_off();
#ifdef USE_ESP_IDF
auto channel = pin_->get_pin() == 25 ? DAC_CHANNEL_1 : DAC_CHANNEL_2;
dac_output_enable(channel);
const dac_channel_t channel = this->pin_->get_pin() == DAC0_PIN ? DAC_CHAN_0 : DAC_CHAN_1;
const dac_oneshot_config_t oneshot_cfg{channel};
dac_oneshot_new_channel(&oneshot_cfg, &this->dac_handle_);
#endif
}
void ESP32DAC::on_safe_shutdown() {
#ifdef USE_ESP_IDF
dac_oneshot_del_channel(this->dac_handle_);
#endif
}
@@ -40,8 +50,7 @@ void ESP32DAC::write_state(float state) {
state = state * 255;
#ifdef USE_ESP_IDF
auto channel = pin_->get_pin() == 25 ? DAC_CHANNEL_1 : DAC_CHANNEL_2;
dac_output_voltage(channel, (uint8_t) state);
dac_oneshot_output_voltage(this->dac_handle_, state);
#endif
#ifdef USE_ARDUINO
dacWrite(this->pin_->get_pin(), state);

View File

@@ -7,6 +7,10 @@
#ifdef USE_ESP32
#ifdef USE_ESP_IDF
#include <driver/dac_oneshot.h>
#endif
namespace esphome {
namespace esp32_dac {
@@ -16,6 +20,7 @@ class ESP32DAC : public output::FloatOutput, public Component {
/// Initialize pin
void setup() override;
void on_safe_shutdown() override;
void dump_config() override;
/// HARDWARE setup_priority
float get_setup_priority() const override { return setup_priority::HARDWARE; }
@@ -24,6 +29,9 @@ class ESP32DAC : public output::FloatOutput, public Component {
void write_state(float state) override;
InternalGPIOPin *pin_;
#ifdef USE_ESP_IDF
dac_oneshot_handle_t dac_handle_;
#endif
};
} // namespace esp32_dac

View File

@@ -1,15 +1,27 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome import pins
from esphome.components import output
import esphome.config_validation as cv
import esphome.codegen as cg
from esphome.components.esp32 import get_esp32_variant
from esphome.components.esp32.const import VARIANT_ESP32, VARIANT_ESP32S2
from esphome.const import CONF_ID, CONF_NUMBER, CONF_PIN
DEPENDENCIES = ["esp32"]
DAC_PINS = {
VARIANT_ESP32: (25, 26),
VARIANT_ESP32S2: (17, 18),
}
def valid_dac_pin(value):
num = value[CONF_NUMBER]
cv.one_of(25, 26)(num)
variant = get_esp32_variant()
try:
valid_pins = DAC_PINS[variant]
except KeyError as ex:
raise cv.Invalid(f"DAC is not supported on {variant}") from ex
given_pin = value[CONF_NUMBER]
cv.one_of(*valid_pins)(given_pin)
return value

View File

@@ -5,8 +5,8 @@ import os
from pathlib import Path
import re
import esphome_glyphsets as glyphsets
import freetype
import glyphsets
import requests
from esphome import core, external_files

View File

@@ -247,8 +247,8 @@ async def to_code(config):
)
cg.add(log.pre_setup())
for tag, level in config[CONF_LOGS].items():
cg.add(log.set_log_level(tag, LOG_LEVELS[level]))
for tag, log_level in config[CONF_LOGS].items():
cg.add(log.set_log_level(tag, LOG_LEVELS[log_level]))
cg.add_define("USE_LOGGER")
this_severity = LOG_LEVEL_SEVERITY.index(level)

View File

@@ -102,9 +102,6 @@ void Logger::log_vprintf_(int level, const char *tag, int line, const __FlashStr
#endif
int HOT Logger::level_for(const char *tag) {
// Uses std::vector<> for low memory footprint, though the vector
// could be sorted to minimize lookup times. This feature isn't used that
// much anyway so it doesn't matter too much.
if (this->log_levels_.count(tag) != 0)
return this->log_levels_[tag];
return this->current_level_;

View File

@@ -9,10 +9,10 @@ namespace online_image {
static const char *const TAG = "online_image.decoder";
bool ImageDecoder::set_size(int width, int height) {
bool resized = this->image_->resize_(width, height);
bool success = this->image_->resize_(width, height) > 0;
this->x_scale_ = static_cast<double>(this->image_->buffer_width_) / width;
this->y_scale_ = static_cast<double>(this->image_->buffer_height_) / height;
return resized;
return success;
}
void ImageDecoder::draw(int x, int y, int w, int h, const Color &color) {
@@ -51,8 +51,9 @@ size_t DownloadBuffer::read(size_t len) {
}
size_t DownloadBuffer::resize(size_t size) {
if (this->size_ == size) {
return size;
if (this->size_ >= size) {
// Avoid useless reallocations; if the buffer is big enough, don't reallocate.
return this->size_;
}
this->allocator_.deallocate(this->buffer_, this->size_);
this->buffer_ = this->allocator_.allocate(size);
@@ -61,6 +62,8 @@ size_t DownloadBuffer::resize(size_t size) {
this->size_ = size;
return size;
} else {
ESP_LOGE(TAG, "allocation of %zu bytes failed. Biggest block in heap: %zu Bytes", size,
this->allocator_.get_max_free_block_size());
this->size_ = 0;
return 0;
}

View File

@@ -58,7 +58,7 @@ int HOT JpegDecoder::decode(uint8_t *buffer, size_t size) {
}
if (!this->jpeg_.openRAM(buffer, size, draw_callback)) {
ESP_LOGE(TAG, "Could not open image for decoding.");
ESP_LOGE(TAG, "Could not open image for decoding: %d", this->jpeg_.getLastError());
return DECODE_ERROR_INVALID_TYPE;
}
auto jpeg_type = this->jpeg_.getJPEGType();
@@ -73,7 +73,9 @@ int HOT JpegDecoder::decode(uint8_t *buffer, size_t size) {
this->jpeg_.setUserPointer(this);
this->jpeg_.setPixelType(RGB8888);
this->set_size(this->jpeg_.getWidth(), this->jpeg_.getHeight());
if (!this->set_size(this->jpeg_.getWidth(), this->jpeg_.getHeight())) {
return DECODE_ERROR_OUT_OF_MEMORY;
}
if (!this->jpeg_.decode(0, 0, 0)) {
ESP_LOGE(TAG, "Error while decoding.");
this->jpeg_.close();

View File

@@ -64,33 +64,34 @@ void OnlineImage::release() {
}
}
bool OnlineImage::resize_(int width_in, int height_in) {
size_t OnlineImage::resize_(int width_in, int height_in) {
int width = this->fixed_width_;
int height = this->fixed_height_;
if (this->auto_resize_()) {
if (this->is_auto_resize_()) {
width = width_in;
height = height_in;
if (this->width_ != width && this->height_ != height) {
this->release();
}
}
if (this->buffer_) {
return false;
}
size_t new_size = this->get_buffer_size_(width, height);
if (this->buffer_) {
// Buffer already allocated => no need to resize
return new_size;
}
ESP_LOGD(TAG, "Allocating new buffer of %zu bytes", new_size);
this->buffer_ = this->allocator_.allocate(new_size);
if (this->buffer_ == nullptr) {
ESP_LOGE(TAG, "allocation of %zu bytes failed. Biggest block in heap: %zu Bytes", new_size,
this->allocator_.get_max_free_block_size());
this->end_connection_();
return false;
return 0;
}
this->buffer_width_ = width;
this->buffer_height_ = height;
this->width_ = width;
ESP_LOGV(TAG, "New size: (%d, %d)", width, height);
return true;
return new_size;
}
void OnlineImage::update() {

View File

@@ -99,9 +99,22 @@ class OnlineImage : public PollingComponent,
int get_position_(int x, int y) const { return (x + y * this->buffer_width_) * this->get_bpp() / 8; }
ESPHOME_ALWAYS_INLINE bool auto_resize_() const { return this->fixed_width_ == 0 || this->fixed_height_ == 0; }
ESPHOME_ALWAYS_INLINE bool is_auto_resize_() const { return this->fixed_width_ == 0 || this->fixed_height_ == 0; }
bool resize_(int width, int height);
/**
* @brief Resize the image buffer to the requested dimensions.
*
* The buffer will be allocated if not existing.
* If the dimensions have been fixed in the yaml config, the buffer will be created
* with those dimensions and not resized, even on request.
* Otherwise, the old buffer will be deallocated and a new buffer with the requested
* allocated
*
* @param width
* @param height
* @return 0 if no memory could be allocated, the size of the new buffer otherwise.
*/
size_t resize_(int width, int height);
/**
* @brief Draw a pixel into the buffer.

View File

@@ -36,7 +36,7 @@ template<typename... Ts> class TotoAction : public RemoteTransmitterActionBase<T
data.rc_code_2 = this->rc_code_2_.value(x...);
data.command = this->command_.value(x...);
this->set_send_times(this->send_times_.value_or(x..., 3));
this->set_send_wait(this->send_wait_.value_or(x..., 32000));
this->set_send_wait(this->send_wait_.value_or(x..., 36000));
TotoProtocol().encode(dst, data);
}
};

View File

@@ -75,7 +75,7 @@ CONFIG_SCHEMA = (
cv.Optional(CONF_UPDATE_INTERVAL, default="60s"): cv.All(
cv.positive_time_period_seconds,
cv.Range(
min=core.TimePeriod(seconds=1), max=core.TimePeriod(seconds=1800)
min=core.TimePeriod(seconds=2), max=core.TimePeriod(seconds=1800)
),
),
}

View File

@@ -1,6 +1,6 @@
"""Constants used by esphome."""
__version__ = "2025.2.0b2"
__version__ = "2025.2.0b6"
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
VALID_SUBSTITUTIONS_CHARACTERS = (

View File

@@ -853,7 +853,7 @@ class InfoRequestHandler(BaseHandler):
dashboard = DASHBOARD
entry = dashboard.entries.get(yaml_path)
if not entry:
if not entry or entry.storage is None:
self.set_status(404)
return

View File

@@ -13,11 +13,11 @@ platformio==6.1.16 # When updating platformio, also update Dockerfile
esptool==4.7.0
click==8.1.7
esphome-dashboard==20250212.0
aioesphomeapi==24.6.2
zeroconf==0.144.1
aioesphomeapi==29.1.0
zeroconf==0.145.1
puremagic==1.27
ruamel.yaml==0.18.6 # dashboard_import
glyphsets==1.0.0
esphome-glyphsets==0.1.0
pillow==10.4.0
freetype-py==2.5.1