Compare commits

...

5 Commits

Author SHA1 Message Date
Jesse Hills
6a478b9070 Merge pull request #11506 from esphome/bump-2025.10.3
2025.10.3
2025-10-24 14:08:12 +13:00
Jesse Hills
a32a1d11fb Bump version to 2025.10.3 2025-10-24 07:51:38 +13:00
Markus
daeb8ef88c [core] handle mixed IP and DNS addresses correctly in resolve_ip_address (#11503)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2025-10-24 07:51:38 +13:00
Anton Sergunov
febee437d6 [uart] Make rx pin respect pullup and pulldown settings (#9248) 2025-10-24 07:51:38 +13:00
Peter Zich
de2f475dbd [hdc1080] Make HDC1080_CMD_CONFIGURATION failure a warning (and log it) (#11355)
Co-authored-by: J. Nick Koston <nick@koston.org>
2025-10-24 07:51:38 +13:00
9 changed files with 70 additions and 19 deletions

View File

@@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 2025.10.2
PROJECT_NUMBER = 2025.10.3
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a

View File

@@ -16,7 +16,8 @@ void HDC1080Component::setup() {
// if configuration fails - there is a problem
if (this->write_register(HDC1080_CMD_CONFIGURATION, config, 2) != i2c::ERROR_OK) {
this->mark_failed();
ESP_LOGW(TAG, "Failed to configure HDC1080");
this->status_set_warning();
return;
}
}

View File

@@ -56,6 +56,13 @@ uint32_t ESP8266UartComponent::get_config() {
}
void ESP8266UartComponent::setup() {
if (this->rx_pin_) {
this->rx_pin_->setup();
}
if (this->tx_pin_ && this->rx_pin_ != this->tx_pin_) {
this->tx_pin_->setup();
}
// Use Arduino HardwareSerial UARTs if all used pins match the ones
// preconfigured by the platform. For example if RX disabled but TX pin
// is 1 we still want to use Serial.

View File

@@ -6,6 +6,9 @@
#include "esphome/core/defines.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#include "esphome/core/gpio.h"
#include "driver/gpio.h"
#include "soc/gpio_num.h"
#ifdef USE_LOGGER
#include "esphome/components/logger/logger.h"
@@ -104,6 +107,13 @@ void IDFUARTComponent::load_settings(bool dump_config) {
return;
}
if (this->rx_pin_) {
this->rx_pin_->setup();
}
if (this->tx_pin_ && this->rx_pin_ != this->tx_pin_) {
this->tx_pin_->setup();
}
int8_t tx = this->tx_pin_ != nullptr ? this->tx_pin_->get_pin() : -1;
int8_t rx = this->rx_pin_ != nullptr ? this->rx_pin_->get_pin() : -1;
int8_t flow_control = this->flow_control_pin_ != nullptr ? this->flow_control_pin_->get_pin() : -1;

View File

@@ -46,6 +46,13 @@ uint16_t LibreTinyUARTComponent::get_config() {
}
void LibreTinyUARTComponent::setup() {
if (this->rx_pin_) {
this->rx_pin_->setup();
}
if (this->tx_pin_ && this->rx_pin_ != this->tx_pin_) {
this->tx_pin_->setup();
}
int8_t tx_pin = tx_pin_ == nullptr ? -1 : tx_pin_->get_pin();
int8_t rx_pin = rx_pin_ == nullptr ? -1 : rx_pin_->get_pin();
bool tx_inverted = tx_pin_ != nullptr && tx_pin_->is_inverted();

View File

@@ -52,6 +52,13 @@ uint16_t RP2040UartComponent::get_config() {
}
void RP2040UartComponent::setup() {
if (this->rx_pin_) {
this->rx_pin_->setup();
}
if (this->tx_pin_ && this->rx_pin_ != this->tx_pin_) {
this->tx_pin_->setup();
}
uint16_t config = get_config();
constexpr uint32_t valid_tx_uart_0 = __bitset({0, 12, 16, 28});

View File

@@ -4,7 +4,7 @@ from enum import Enum
from esphome.enum import StrEnum
__version__ = "2025.10.2"
__version__ = "2025.10.3"
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
VALID_SUBSTITUTIONS_CHARACTERS = (

View File

@@ -224,36 +224,37 @@ def resolve_ip_address(
return res
# Process hosts
cached_addresses: list[str] = []
uncached_hosts: list[str] = []
has_cache = address_cache is not None
for h in hosts:
if is_ip_address(h):
if has_cache:
# If we have a cache, treat IPs as cached
cached_addresses.append(h)
else:
# If no cache, pass IPs through to resolver with hostnames
uncached_hosts.append(h)
_add_ip_addresses_to_addrinfo([h], port, res)
elif address_cache and (cached := address_cache.get_addresses(h)):
# Found in cache
cached_addresses.extend(cached)
_add_ip_addresses_to_addrinfo(cached, port, res)
else:
# Not cached, need to resolve
if address_cache and address_cache.has_cache():
_LOGGER.info("Host %s not in cache, will need to resolve", h)
uncached_hosts.append(h)
# Process cached addresses (includes direct IPs and cached lookups)
_add_ip_addresses_to_addrinfo(cached_addresses, port, res)
# If we have uncached hosts (only non-IP hostnames), resolve them
if uncached_hosts:
from aioesphomeapi.host_resolver import AddrInfo as AioAddrInfo
from esphome.core import EsphomeError
from esphome.resolver import AsyncResolver
resolver = AsyncResolver(uncached_hosts, port)
addr_infos = resolver.resolve()
addr_infos: list[AioAddrInfo] = []
try:
addr_infos = resolver.resolve()
except EsphomeError as err:
if not res:
# No pre-resolved addresses available, DNS resolution is fatal
raise
_LOGGER.info("%s (using %d already resolved IP addresses)", err, len(res))
# Convert aioesphomeapi AddrInfo to our format
for addr_info in addr_infos:
sockaddr = addr_info.sockaddr

View File

@@ -454,9 +454,27 @@ def test_resolve_ip_address_mixed_list() -> None:
# Mix of IP and hostname - should use async resolver
result = helpers.resolve_ip_address(["192.168.1.100", "test.local"], 6053)
assert len(result) == 2
assert result[0][4][0] == "192.168.1.100"
assert result[1][4][0] == "192.168.1.200"
MockResolver.assert_called_once_with(["test.local"], 6053)
mock_resolver.resolve.assert_called_once()
def test_resolve_ip_address_mixed_list_fail() -> None:
"""Test resolving a mix of IPs and hostnames with resolve failed."""
with patch("esphome.resolver.AsyncResolver") as MockResolver:
mock_resolver = MockResolver.return_value
mock_resolver.resolve.side_effect = EsphomeError(
"Error resolving IP address: [test.local]"
)
# Mix of IP and hostname - should use async resolver
result = helpers.resolve_ip_address(["192.168.1.100", "test.local"], 6053)
assert len(result) == 1
assert result[0][4][0] == "192.168.1.200"
MockResolver.assert_called_once_with(["192.168.1.100", "test.local"], 6053)
assert result[0][4][0] == "192.168.1.100"
MockResolver.assert_called_once_with(["test.local"], 6053)
mock_resolver.resolve.assert_called_once()