mirror of
https://github.com/esphome/esphome.git
synced 2026-09-17 18:18:43 +00:00
Merge remote-tracking branch 'upstream/dev' into integration
# Conflicts: # esphome/components/api/api_frame_helper.h # esphome/core/application.h
This commit is contained in:
@@ -228,13 +228,13 @@ class APIFrameHelper {
|
||||
EXPLICIT_REJECT = 8, // Noise only
|
||||
};
|
||||
|
||||
// Fast inline check for read_packet/write_protobuf_messages hot path.
|
||||
// In DATA state, state_action_() is a no-op (falls through all checks to return OK).
|
||||
// This avoids a 447-byte function call on every packet during normal operation.
|
||||
// Fast inline state check for read_packet/write_protobuf_messages hot path.
|
||||
// Returns OK only in DATA state; maps CLOSED/FAILED to BAD_STATE and any
|
||||
// other intermediate state to WOULD_BLOCK.
|
||||
inline APIError ESPHOME_ALWAYS_INLINE check_data_state_() const {
|
||||
if (state_ == State::DATA)
|
||||
if (this->state_ == State::DATA)
|
||||
return APIError::OK;
|
||||
if (state_ == State::CLOSED || state_ == State::FAILED)
|
||||
if (this->state_ == State::CLOSED || this->state_ == State::FAILED)
|
||||
return APIError::BAD_STATE;
|
||||
return APIError::WOULD_BLOCK;
|
||||
}
|
||||
|
||||
@@ -41,9 +41,9 @@ class DutyTimeSensor : public sensor::Sensor, public PollingComponent {
|
||||
sensor::Sensor *last_duty_time_sensor_{nullptr};
|
||||
ESPPreferenceObject pref_;
|
||||
|
||||
uint32_t total_sec_;
|
||||
uint32_t last_time_;
|
||||
uint32_t edge_time_;
|
||||
uint32_t total_sec_{0};
|
||||
uint32_t last_time_{0};
|
||||
uint32_t edge_time_{0};
|
||||
bool last_state_{false};
|
||||
bool restore_;
|
||||
};
|
||||
|
||||
@@ -56,8 +56,8 @@ class GrowattSolar : public PollingComponent, public modbus::ModbusDevice {
|
||||
}
|
||||
|
||||
protected:
|
||||
bool waiting_to_update_;
|
||||
uint32_t last_send_;
|
||||
bool waiting_to_update_{false};
|
||||
uint32_t last_send_{0};
|
||||
|
||||
struct GrowattPhase {
|
||||
sensor::Sensor *voltage_sensor_{nullptr};
|
||||
|
||||
@@ -18,8 +18,8 @@ class HTE501Component : public PollingComponent, public i2c::I2CDevice {
|
||||
void update() override;
|
||||
|
||||
protected:
|
||||
sensor::Sensor *temperature_sensor_;
|
||||
sensor::Sensor *humidity_sensor_;
|
||||
sensor::Sensor *temperature_sensor_{nullptr};
|
||||
sensor::Sensor *humidity_sensor_{nullptr};
|
||||
|
||||
enum ErrorCode { NONE = 0, COMMUNICATION_FAILED, CRC_CHECK_FAILED } error_code_{NONE};
|
||||
};
|
||||
|
||||
@@ -27,6 +27,9 @@ CONF_PRECISION = "precision"
|
||||
CONF_SKIP_CONNECTION_HANDSHAKE = "skip_connection_handshake"
|
||||
CONF_START_UP_PAGE = "start_up_page"
|
||||
CONF_STARTUP_OVERRIDE_MS = "startup_override_ms"
|
||||
CONF_TFT_UPLOAD_HTTP_RETRIES = "tft_upload_http_retries"
|
||||
CONF_TFT_UPLOAD_HTTP_TIMEOUT = "tft_upload_http_timeout"
|
||||
CONF_TFT_UPLOAD_WATCHDOG_TIMEOUT = "tft_upload_watchdog_timeout"
|
||||
CONF_TFT_URL = "tft_url"
|
||||
CONF_TOUCH_SLEEP_TIMEOUT = "touch_sleep_timeout"
|
||||
CONF_VARIABLE_NAME = "variable_name"
|
||||
|
||||
@@ -33,15 +33,24 @@ from .base_component import (
|
||||
CONF_SKIP_CONNECTION_HANDSHAKE,
|
||||
CONF_START_UP_PAGE,
|
||||
CONF_STARTUP_OVERRIDE_MS,
|
||||
CONF_TFT_UPLOAD_HTTP_RETRIES,
|
||||
CONF_TFT_UPLOAD_HTTP_TIMEOUT,
|
||||
CONF_TFT_UPLOAD_WATCHDOG_TIMEOUT,
|
||||
CONF_TFT_URL,
|
||||
CONF_TOUCH_SLEEP_TIMEOUT,
|
||||
CONF_WAKE_UP_PAGE,
|
||||
)
|
||||
|
||||
CODEOWNERS = ["@senexcrenshaw", "@edwardtfn"]
|
||||
|
||||
DEPENDENCIES = ["uart"]
|
||||
AUTO_LOAD = ["binary_sensor", "switch", "sensor", "text_sensor"]
|
||||
|
||||
|
||||
def AUTO_LOAD() -> list[str]:
|
||||
base = ["binary_sensor", "switch", "sensor", "text_sensor"]
|
||||
if CORE.is_esp32:
|
||||
base.append("watchdog")
|
||||
return base
|
||||
|
||||
|
||||
NextionSetBrightnessAction = nextion_ns.class_(
|
||||
"NextionSetBrightnessAction", automation.Action
|
||||
@@ -55,7 +64,24 @@ BufferOverflowTrigger = nextion_ns.class_(
|
||||
"BufferOverflowTrigger", automation.Trigger.template()
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
|
||||
def _validate_tft_upload(config):
|
||||
has_tft_url = CONF_TFT_URL in config
|
||||
for conf_key in (
|
||||
CONF_TFT_UPLOAD_HTTP_TIMEOUT,
|
||||
CONF_TFT_UPLOAD_HTTP_RETRIES,
|
||||
CONF_TFT_UPLOAD_WATCHDOG_TIMEOUT,
|
||||
):
|
||||
if conf_key in config and not has_tft_url:
|
||||
raise cv.Invalid(f"{conf_key} requires {CONF_TFT_URL} to be set")
|
||||
if CONF_TFT_UPLOAD_WATCHDOG_TIMEOUT in config and not CORE.is_esp32:
|
||||
raise cv.Invalid(
|
||||
f"{CONF_TFT_UPLOAD_WATCHDOG_TIMEOUT} is only available on ESP32"
|
||||
)
|
||||
return config
|
||||
|
||||
|
||||
CONFIG_SCHEMA = cv.All(
|
||||
display.BASIC_DISPLAY_SCHEMA.extend(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(Nextion),
|
||||
@@ -115,6 +141,14 @@ CONFIG_SCHEMA = (
|
||||
),
|
||||
),
|
||||
cv.Optional(CONF_START_UP_PAGE): cv.uint8_t,
|
||||
cv.Optional(CONF_TFT_UPLOAD_HTTP_RETRIES): cv.int_range(min=1, max=255),
|
||||
cv.Optional(CONF_TFT_UPLOAD_HTTP_TIMEOUT): cv.All(
|
||||
cv.positive_time_period_milliseconds,
|
||||
cv.Range(max=TimePeriod(milliseconds=65535)),
|
||||
),
|
||||
cv.Optional(
|
||||
CONF_TFT_UPLOAD_WATCHDOG_TIMEOUT
|
||||
): cv.positive_time_period_milliseconds,
|
||||
cv.Optional(CONF_TFT_URL): cv.url,
|
||||
cv.Optional(CONF_TOUCH_SLEEP_TIMEOUT): cv.Any(
|
||||
0, cv.int_range(min=3, max=65535)
|
||||
@@ -123,7 +157,8 @@ CONFIG_SCHEMA = (
|
||||
}
|
||||
)
|
||||
.extend(cv.polling_component_schema("5s"))
|
||||
.extend(uart.UART_DEVICE_SCHEMA)
|
||||
.extend(uart.UART_DEVICE_SCHEMA),
|
||||
_validate_tft_upload,
|
||||
)
|
||||
|
||||
|
||||
@@ -176,6 +211,29 @@ async def to_code(config):
|
||||
if CONF_TFT_URL in config:
|
||||
cg.add_define("USE_NEXTION_TFT_UPLOAD")
|
||||
cg.add(var.set_tft_url(config[CONF_TFT_URL]))
|
||||
|
||||
# TFT upload HTTP timeout (default: 4.5s)
|
||||
if CONF_TFT_UPLOAD_HTTP_TIMEOUT in config:
|
||||
cg.add(
|
||||
var.set_tft_upload_http_timeout(
|
||||
config[CONF_TFT_UPLOAD_HTTP_TIMEOUT].total_milliseconds
|
||||
)
|
||||
)
|
||||
|
||||
# TFT upload HTTP retries (default: 5)
|
||||
if CONF_TFT_UPLOAD_HTTP_RETRIES in config:
|
||||
cg.add(
|
||||
var.set_tft_upload_http_retries(config[CONF_TFT_UPLOAD_HTTP_RETRIES])
|
||||
)
|
||||
|
||||
# TFT upload watchdog timeout (default: 0 = no adjustment)
|
||||
if CONF_TFT_UPLOAD_WATCHDOG_TIMEOUT in config:
|
||||
cg.add(
|
||||
var.set_tft_upload_watchdog_timeout(
|
||||
config[CONF_TFT_UPLOAD_WATCHDOG_TIMEOUT].total_milliseconds
|
||||
)
|
||||
)
|
||||
|
||||
if CORE.is_esp32:
|
||||
# Re-enable ESP-IDF's HTTP client (excluded by default to save compile time)
|
||||
esp32.include_builtin_idf_component("esp_http_client")
|
||||
|
||||
@@ -191,6 +191,18 @@ void Nextion::dump_config() {
|
||||
#ifdef USE_NEXTION_MAX_QUEUE_SIZE
|
||||
ESP_LOGCONFIG(TAG, " Max queue size: %zu", this->max_queue_size_);
|
||||
#endif
|
||||
#ifdef USE_NEXTION_TFT_UPLOAD
|
||||
ESP_LOGCONFIG(TAG,
|
||||
" TFT URL: %s\n"
|
||||
" TFT upload HTTP timeout: %" PRIu16 "ms\n"
|
||||
" TFT upload HTTP retries: %u",
|
||||
this->tft_url_.c_str(), this->tft_upload_http_timeout_, this->tft_upload_http_retries_);
|
||||
#ifdef USE_ESP32
|
||||
if (this->tft_upload_watchdog_timeout_ > 0) {
|
||||
ESP_LOGCONFIG(TAG, " TFT upload WDT timeout: %" PRIu32 "ms", this->tft_upload_watchdog_timeout_);
|
||||
}
|
||||
#endif // USE_ESP32
|
||||
#endif // USE_NEXTION_TFT_UPLOAD
|
||||
}
|
||||
|
||||
void Nextion::update() {
|
||||
|
||||
@@ -1071,6 +1071,33 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
|
||||
bool send_command_printf(const char *format, ...) __attribute__((format(printf, 2, 3)));
|
||||
|
||||
#ifdef USE_NEXTION_TFT_UPLOAD
|
||||
/**
|
||||
* @brief Set the HTTP timeout for TFT upload requests.
|
||||
* @param timeout_ms Timeout in milliseconds. Defaults to 4500ms (4.5s).
|
||||
*/
|
||||
void set_tft_upload_http_timeout(uint16_t timeout_ms) { this->tft_upload_http_timeout_ = timeout_ms; }
|
||||
|
||||
#ifdef USE_ESP32
|
||||
/**
|
||||
* @brief Set the watchdog timeout during TFT upload.
|
||||
*
|
||||
* The system watchdog timeout is temporarily adjusted to this value
|
||||
* during the entire TFT transfer process and restored to the original
|
||||
* value after the transfer completes (whether successful or not).
|
||||
*
|
||||
* A value of 0 means no watchdog adjustment (default).
|
||||
*
|
||||
* @param timeout_ms Watchdog timeout in milliseconds. 0 = no adjustment.
|
||||
*/
|
||||
void set_tft_upload_watchdog_timeout(uint32_t timeout_ms) { this->tft_upload_watchdog_timeout_ = timeout_ms; }
|
||||
#endif // USE_ESP32
|
||||
|
||||
/**
|
||||
* @brief Set the number of HTTP retries for TFT upload requests.
|
||||
* @param retries Number of retries. Defaults to 5. Range: 1-255.
|
||||
*/
|
||||
void set_tft_upload_http_retries(uint8_t retries) { this->tft_upload_http_retries_ = retries; }
|
||||
|
||||
/**
|
||||
* Set the tft file URL.
|
||||
*/
|
||||
@@ -1439,8 +1466,12 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
|
||||
int tft_size_ = 0;
|
||||
uint32_t original_baud_rate_ = 0;
|
||||
bool upload_first_chunk_sent_ = false;
|
||||
uint16_t tft_upload_http_timeout_{4500}; ///< HTTP timeout in ms (default: 4.5s)
|
||||
uint8_t tft_upload_http_retries_{5}; ///< HTTP retry count (default: 5)
|
||||
|
||||
#ifdef USE_ESP32
|
||||
uint32_t tft_upload_watchdog_timeout_{0}; ///< WDT timeout in ms (0 = no adjustment)
|
||||
|
||||
/**
|
||||
* will request 4096 bytes chunks from the web server
|
||||
* and send each to Nextion
|
||||
|
||||
@@ -166,7 +166,7 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
||||
// Define the configuration for the HTTP client
|
||||
ESP_LOGV(TAG, "Init HTTP client, heap: %" PRIu32, EspClass::getFreeHeap());
|
||||
HTTPClient http_client;
|
||||
http_client.setTimeout(15000); // Yes 15 seconds.... Helps 8266s along
|
||||
http_client.setTimeout(this->tft_upload_http_timeout_);
|
||||
|
||||
bool begin_status = false;
|
||||
#ifdef USE_ESP8266
|
||||
@@ -192,15 +192,15 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
||||
http_client.collectHeaders(header_names, 1);
|
||||
ESP_LOGD(TAG, "URL: %s", this->tft_url_.c_str());
|
||||
http_client.setReuse(true);
|
||||
// try up to 5 times. DNS sometimes needs a second try or so
|
||||
|
||||
int tries = 1;
|
||||
int code = http_client.GET();
|
||||
delay(100); // NOLINT
|
||||
|
||||
App.feed_wdt();
|
||||
while (code != 200 && code != 206 && tries <= 5) {
|
||||
ESP_LOGW(TAG, "HTTP fail: URL: %s; Error: %s, retry %d/5", this->tft_url_.c_str(),
|
||||
HTTPClient::errorToString(code).c_str(), tries);
|
||||
while (code != 200 && code != 206 && tries <= this->tft_upload_http_retries_) {
|
||||
ESP_LOGW(TAG, "HTTP fail: URL: %s; Error: %s, retry %d/%u", this->tft_url_.c_str(),
|
||||
HTTPClient::errorToString(code).c_str(), tries, this->tft_upload_http_retries_);
|
||||
|
||||
delay(250); // NOLINT
|
||||
App.feed_wdt();
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <esp_http_client.h>
|
||||
#include <cinttypes>
|
||||
#include "esphome/components/network/util.h"
|
||||
#include "esphome/components/watchdog/watchdog.h"
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/defines.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
@@ -68,7 +69,7 @@ int Nextion::upload_by_chunks_(esp_http_client_handle_t http_client, uint32_t &r
|
||||
int partial_read_len = 0;
|
||||
uint8_t retries = 0;
|
||||
// Attempt to read the chunk with retries.
|
||||
while (retries < 5 && read_len < buffer_size) {
|
||||
while (retries < this->tft_upload_http_retries_ && read_len < buffer_size) {
|
||||
partial_read_len =
|
||||
esp_http_client_read(http_client, reinterpret_cast<char *>(buffer) + read_len, buffer_size - read_len);
|
||||
if (partial_read_len > 0) {
|
||||
@@ -167,6 +168,9 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Temporarily adjust watchdog timeout for the duration of the TFT upload
|
||||
watchdog::WatchdogManager wdm(this->tft_upload_watchdog_timeout_);
|
||||
|
||||
this->connection_state_.is_updating_ = true;
|
||||
|
||||
if (exit_reparse) {
|
||||
@@ -190,7 +194,7 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
||||
.url = this->tft_url_.c_str(),
|
||||
.cert_pem = nullptr,
|
||||
.method = HTTP_METHOD_HEAD,
|
||||
.timeout_ms = 15000,
|
||||
.timeout_ms = static_cast<int>(this->tft_upload_http_timeout_),
|
||||
.disable_auto_redirect = false,
|
||||
.max_redirection_count = 10,
|
||||
};
|
||||
|
||||
@@ -43,7 +43,7 @@ class SelectCall {
|
||||
Select *const parent_;
|
||||
optional<size_t> index_;
|
||||
SelectOperation operation_{SELECT_OP_NONE};
|
||||
bool cycle_;
|
||||
bool cycle_{false};
|
||||
};
|
||||
|
||||
} // namespace esphome::select
|
||||
|
||||
@@ -89,8 +89,8 @@ class UponorSmatrixComponent : public uart::UARTDevice, public Component {
|
||||
|
||||
std::vector<uint8_t> rx_buffer_;
|
||||
std::queue<std::vector<uint8_t>> tx_queue_;
|
||||
uint32_t last_rx_;
|
||||
uint32_t last_tx_;
|
||||
uint32_t last_rx_{0};
|
||||
uint32_t last_tx_{0};
|
||||
|
||||
#ifdef USE_TIME
|
||||
time::RealTimeClock *time_id_{nullptr};
|
||||
|
||||
@@ -23,7 +23,7 @@ class IPAddressWiFiInfo final : public Component, public text_sensor::TextSensor
|
||||
const network::IPAddress &dns2) override;
|
||||
|
||||
protected:
|
||||
std::array<text_sensor::TextSensor *, 5> ip_sensors_;
|
||||
std::array<text_sensor::TextSensor *, 5> ip_sensors_{};
|
||||
};
|
||||
|
||||
class DNSAddressWifiInfo final : public Component, public text_sensor::TextSensor, public wifi::WiFiIPStateListener {
|
||||
|
||||
@@ -25,9 +25,9 @@ class X9cOutput : public output::FloatOutput, public Component {
|
||||
InternalGPIOPin *cs_pin_;
|
||||
InternalGPIOPin *inc_pin_;
|
||||
InternalGPIOPin *ud_pin_;
|
||||
float initial_value_;
|
||||
float pot_value_;
|
||||
int step_delay_;
|
||||
float initial_value_{0.0f};
|
||||
float pot_value_{0.0f};
|
||||
int step_delay_{0};
|
||||
};
|
||||
|
||||
} // namespace x9c
|
||||
|
||||
@@ -33,9 +33,6 @@
|
||||
#include <lwip/sockets.h>
|
||||
#endif
|
||||
#endif
|
||||
#if defined(USE_ESP8266) && defined(USE_SOCKET_IMPL_LWIP_TCP)
|
||||
#include "esphome/components/socket/socket.h"
|
||||
#endif
|
||||
#endif // USE_SOCKET_SELECT_SUPPORT
|
||||
#if (defined(USE_ESP8266) || defined(USE_RP2040)) && defined(USE_SOCKET_IMPL_LWIP_TCP)
|
||||
namespace esphome::socket {
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
display:
|
||||
- id: !extend main_lcd
|
||||
tft_url: http://esphome.io/default35.tft
|
||||
tft_upload_http_timeout: 20s
|
||||
tft_upload_http_retries: 10
|
||||
@@ -0,0 +1,3 @@
|
||||
display:
|
||||
- id: !extend main_lcd
|
||||
tft_upload_watchdog_timeout: 30s
|
||||
@@ -1,7 +1,5 @@
|
||||
packages:
|
||||
uart: !include ../../test_build_components/common/uart/esp32-ard.yaml
|
||||
base: !include common.yaml
|
||||
|
||||
display:
|
||||
- id: !extend main_lcd
|
||||
tft_url: http://esphome.io/default35.tft
|
||||
tft_upload: !include common_tft_upload.yaml
|
||||
tft_upload_watchdog: !include common_tft_upload_watchdog.yaml
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
packages:
|
||||
uart: !include ../../test_build_components/common/uart/esp32-idf.yaml
|
||||
base: !include common.yaml
|
||||
|
||||
display:
|
||||
- id: !extend main_lcd
|
||||
tft_url: http://esphome.io/default35.tft
|
||||
tft_upload: !include common_tft_upload.yaml
|
||||
tft_upload_watchdog: !include common_tft_upload_watchdog.yaml
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
packages:
|
||||
uart: !include ../../test_build_components/common/uart/esp8266-ard.yaml
|
||||
base: !include common.yaml
|
||||
|
||||
display:
|
||||
- id: !extend main_lcd
|
||||
tft_url: http://esphome.io/default35.tft
|
||||
tft_upload: !include common_tft_upload.yaml
|
||||
|
||||
Reference in New Issue
Block a user