mirror of
https://github.com/esphome/esphome.git
synced 2026-02-25 04:45:29 -07:00
Merge remote-tracking branch 'upstream/dev' into setup_heap_stats
# Conflicts: # esphome/core/defines.h
This commit is contained in:
@@ -213,6 +213,7 @@ esphome/components/hbridge/light/* @DotNetDann
|
||||
esphome/components/hbridge/switch/* @dwmw2
|
||||
esphome/components/hc8/* @omartijn
|
||||
esphome/components/hdc2010/* @optimusprimespace @ssieb
|
||||
esphome/components/hdc302x/* @joshuasing
|
||||
esphome/components/he60r/* @clydebarrow
|
||||
esphome/components/heatpumpir/* @rob-deutsch
|
||||
esphome/components/hitachi_ac424/* @sourabhjaiswal
|
||||
|
||||
@@ -92,10 +92,7 @@ void AbsoluteHumidityComponent::loop() {
|
||||
// Calculate absolute humidity
|
||||
const float absolute_humidity = vapor_density(es, hr, temperature_k);
|
||||
|
||||
ESP_LOGD(TAG,
|
||||
"Saturation vapor pressure %f kPa\n"
|
||||
"Publishing absolute humidity %f g/m³",
|
||||
es, absolute_humidity);
|
||||
ESP_LOGD(TAG, "Saturation vapor pressure %f kPa, absolute humidity %f g/m³", es, absolute_humidity);
|
||||
|
||||
// Publish absolute humidity
|
||||
this->status_clear_warning();
|
||||
|
||||
@@ -67,10 +67,8 @@ void Anova::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_
|
||||
case ESP_GATTC_SEARCH_CMPL_EVT: {
|
||||
auto *chr = this->parent_->get_characteristic(ANOVA_SERVICE_UUID, ANOVA_CHARACTERISTIC_UUID);
|
||||
if (chr == nullptr) {
|
||||
ESP_LOGW(TAG,
|
||||
"[%s] No control service found at device, not an Anova..?\n"
|
||||
"[%s] Note, this component does not currently support Anova Nano.",
|
||||
this->get_name().c_str(), this->get_name().c_str());
|
||||
ESP_LOGW(TAG, "[%s] No control service found at device, not an Anova..?", this->get_name().c_str());
|
||||
ESP_LOGW(TAG, "[%s] Note, this component does not currently support Anova Nano.", this->get_name().c_str());
|
||||
break;
|
||||
}
|
||||
this->char_handle_ = chr->handle;
|
||||
|
||||
@@ -233,8 +233,8 @@ def _consume_api_sockets(config: ConfigType) -> ConfigType:
|
||||
|
||||
# API needs 1 listening socket + typically 3 concurrent client connections
|
||||
# (not max_connections, which is the upper limit rarely reached)
|
||||
sockets_needed = 1 + 3
|
||||
socket.consume_sockets(sockets_needed, "api")(config)
|
||||
socket.consume_sockets(3, "api")(config)
|
||||
socket.consume_sockets(1, "api", socket.SocketType.TCP_LISTEN)(config)
|
||||
return config
|
||||
|
||||
|
||||
|
||||
@@ -1346,9 +1346,8 @@ uint16_t APIConnection::try_send_water_heater_state(EntityBase *entity, APIConne
|
||||
resp.target_temperature_low = wh->get_target_temperature_low();
|
||||
resp.target_temperature_high = wh->get_target_temperature_high();
|
||||
resp.state = wh->get_state();
|
||||
resp.key = wh->get_object_id_hash();
|
||||
|
||||
return encode_message_to_buffer(resp, WaterHeaterStateResponse::MESSAGE_TYPE, conn, remaining_size);
|
||||
return fill_and_encode_entity_state(wh, resp, WaterHeaterStateResponse::MESSAGE_TYPE, conn, remaining_size);
|
||||
}
|
||||
uint16_t APIConnection::try_send_water_heater_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
|
||||
auto *wh = static_cast<water_heater::WaterHeater *>(entity);
|
||||
|
||||
@@ -307,9 +307,9 @@ void AS3935Component::tune_antenna() {
|
||||
uint8_t tune_val = this->read_capacitance();
|
||||
ESP_LOGI(TAG,
|
||||
"Starting antenna tuning\n"
|
||||
"Division Ratio is set to: %d\n"
|
||||
"Internal Capacitor is set to: %d\n"
|
||||
"Displaying oscillator on INT pin. Measure its frequency - multiply value by Division Ratio",
|
||||
" Division Ratio is set to: %d\n"
|
||||
" Internal Capacitor is set to: %d\n"
|
||||
" Displaying oscillator on INT pin. Measure its frequency - multiply value by Division Ratio",
|
||||
div_ratio, tune_val);
|
||||
this->display_oscillator(true, ANTFREQ);
|
||||
}
|
||||
|
||||
@@ -77,14 +77,14 @@ void AT581XComponent::dump_config() { LOG_I2C_DEVICE(this); }
|
||||
bool AT581XComponent::i2c_write_config() {
|
||||
ESP_LOGCONFIG(TAG,
|
||||
"Writing new config for AT581X\n"
|
||||
"Frequency: %dMHz\n"
|
||||
"Sensing distance: %d\n"
|
||||
"Power: %dµA\n"
|
||||
"Gain: %d\n"
|
||||
"Trigger base time: %dms\n"
|
||||
"Trigger keep time: %dms\n"
|
||||
"Protect time: %dms\n"
|
||||
"Self check time: %dms",
|
||||
" Frequency: %dMHz\n"
|
||||
" Sensing distance: %d\n"
|
||||
" Power: %dµA\n"
|
||||
" Gain: %d\n"
|
||||
" Trigger base time: %dms\n"
|
||||
" Trigger keep time: %dms\n"
|
||||
" Protect time: %dms\n"
|
||||
" Self check time: %dms",
|
||||
this->freq_, this->delta_, this->power_, this->gain_, this->trigger_base_time_ms_,
|
||||
this->trigger_keep_time_ms_, this->protect_time_ms_, this->self_check_time_ms_);
|
||||
|
||||
|
||||
@@ -562,6 +562,7 @@ async def setup_binary_sensor_core_(var, config):
|
||||
if inverted := config.get(CONF_INVERTED):
|
||||
cg.add(var.set_inverted(inverted))
|
||||
if filters_config := config.get(CONF_FILTERS):
|
||||
cg.add_define("USE_BINARY_SENSOR_FILTER")
|
||||
filters = await cg.build_registry_list(FILTER_REGISTRY, filters_config)
|
||||
cg.add(var.add_filters(filters))
|
||||
|
||||
|
||||
@@ -29,10 +29,8 @@ void MultiClickTrigger::on_state_(bool state) {
|
||||
// Start matching
|
||||
MultiClickTriggerEvent evt = this->timing_[0];
|
||||
if (evt.state == state) {
|
||||
ESP_LOGV(TAG,
|
||||
"START min=%" PRIu32 " max=%" PRIu32 "\n"
|
||||
"Multi Click: Starting multi click action!",
|
||||
evt.min_length, evt.max_length);
|
||||
ESP_LOGV(TAG, "START min=%" PRIu32 " max=%" PRIu32, evt.min_length, evt.max_length);
|
||||
ESP_LOGV(TAG, "Multi Click: Starting multi click action!");
|
||||
this->at_index_ = 1;
|
||||
if (this->timing_.size() == 1 && evt.max_length == 4294967294UL) {
|
||||
this->set_timeout(MULTICLICK_TRIGGER_ID, evt.min_length, [this]() { this->trigger_(); });
|
||||
|
||||
@@ -18,11 +18,15 @@ void log_binary_sensor(const char *tag, const char *prefix, const char *type, Bi
|
||||
}
|
||||
|
||||
void BinarySensor::publish_state(bool new_state) {
|
||||
#ifdef USE_BINARY_SENSOR_FILTER
|
||||
if (this->filter_list_ == nullptr) {
|
||||
#endif
|
||||
this->send_state_internal(new_state);
|
||||
#ifdef USE_BINARY_SENSOR_FILTER
|
||||
} else {
|
||||
this->filter_list_->input(new_state);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
void BinarySensor::publish_initial_state(bool new_state) {
|
||||
this->invalidate_state();
|
||||
@@ -47,6 +51,7 @@ bool BinarySensor::set_new_state(const optional<bool> &new_state) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef USE_BINARY_SENSOR_FILTER
|
||||
void BinarySensor::add_filter(Filter *filter) {
|
||||
filter->parent_ = this;
|
||||
if (this->filter_list_ == nullptr) {
|
||||
@@ -63,6 +68,7 @@ void BinarySensor::add_filters(std::initializer_list<Filter *> filters) {
|
||||
this->add_filter(filter);
|
||||
}
|
||||
}
|
||||
#endif // USE_BINARY_SENSOR_FILTER
|
||||
bool BinarySensor::is_status_binary_sensor() const { return false; }
|
||||
|
||||
} // namespace esphome::binary_sensor
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
#include "esphome/core/entity_base.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#ifdef USE_BINARY_SENSOR_FILTER
|
||||
#include "esphome/components/binary_sensor/filter.h"
|
||||
#endif
|
||||
|
||||
#include <initializer_list>
|
||||
|
||||
@@ -45,8 +47,10 @@ class BinarySensor : public StatefulEntityBase<bool>, public EntityBase_DeviceCl
|
||||
*/
|
||||
void publish_initial_state(bool new_state);
|
||||
|
||||
#ifdef USE_BINARY_SENSOR_FILTER
|
||||
void add_filter(Filter *filter);
|
||||
void add_filters(std::initializer_list<Filter *> filters);
|
||||
#endif
|
||||
|
||||
// ========== INTERNAL METHODS ==========
|
||||
// (In most use cases you won't need these)
|
||||
@@ -60,7 +64,9 @@ class BinarySensor : public StatefulEntityBase<bool>, public EntityBase_DeviceCl
|
||||
bool state{};
|
||||
|
||||
protected:
|
||||
#ifdef USE_BINARY_SENSOR_FILTER
|
||||
Filter *filter_list_{nullptr};
|
||||
#endif
|
||||
|
||||
bool set_new_state(const optional<bool> &new_state) override;
|
||||
};
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#include "esphome/core/defines.h"
|
||||
#ifdef USE_BINARY_SENSOR_FILTER
|
||||
|
||||
#include "filter.h"
|
||||
|
||||
#include "binary_sensor.h"
|
||||
@@ -142,3 +145,5 @@ optional<bool> SettleFilter::new_value(bool value) {
|
||||
float SettleFilter::get_setup_priority() const { return setup_priority::HARDWARE; }
|
||||
|
||||
} // namespace esphome::binary_sensor
|
||||
|
||||
#endif // USE_BINARY_SENSOR_FILTER
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/defines.h"
|
||||
#ifdef USE_BINARY_SENSOR_FILTER
|
||||
|
||||
#include "esphome/core/automation.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
@@ -138,3 +141,5 @@ class SettleFilter : public Filter, public Component {
|
||||
};
|
||||
|
||||
} // namespace esphome::binary_sensor
|
||||
|
||||
#endif // USE_BINARY_SENSOR_FILTER
|
||||
|
||||
@@ -182,7 +182,10 @@ void BL0940::recalibrate_() {
|
||||
|
||||
ESP_LOGD(TAG,
|
||||
"Recalibrated reference values:\n"
|
||||
"Voltage: %f\n, Current: %f\n, Power: %f\n, Energy: %f\n",
|
||||
" Voltage: %f\n"
|
||||
" Current: %f\n"
|
||||
" Power: %f\n"
|
||||
" Energy: %f",
|
||||
this->voltage_reference_cal_, this->current_reference_cal_, this->power_reference_cal_,
|
||||
this->energy_reference_cal_);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "esphome/core/preferences.h"
|
||||
#include "esphome/core/defines.h"
|
||||
#include <map>
|
||||
#include <queue>
|
||||
|
||||
#ifdef USE_BSEC
|
||||
#include <bsec.h>
|
||||
|
||||
@@ -76,13 +76,15 @@ def _final_validate(config: ConfigType) -> ConfigType:
|
||||
|
||||
# Register socket needs for DNS server and additional HTTP connections
|
||||
# - 1 UDP socket for DNS server
|
||||
# - 3 additional TCP sockets for captive portal detection probes + configuration requests
|
||||
# - 3 TCP sockets for captive portal detection probes + configuration requests
|
||||
# OS captive portal detection makes multiple probe requests that stay in TIME_WAIT.
|
||||
# Need headroom for actual user configuration requests.
|
||||
# LRU purging will reclaim idle sockets to prevent exhaustion from repeated attempts.
|
||||
# The listening socket is registered by web_server_base (shared HTTP server).
|
||||
from esphome.components import socket
|
||||
|
||||
socket.consume_sockets(4, "captive_portal")(config)
|
||||
socket.consume_sockets(3, "captive_portal")(config)
|
||||
socket.consume_sockets(1, "captive_portal", socket.SocketType.UDP)(config)
|
||||
|
||||
return config
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ from esphome.const import (
|
||||
CONF_DATA,
|
||||
CONF_FREQUENCY,
|
||||
CONF_ID,
|
||||
CONF_OUTPUT_POWER,
|
||||
CONF_VALUE,
|
||||
CONF_WAIT_TIME,
|
||||
)
|
||||
@@ -22,7 +23,6 @@ ns = cg.esphome_ns.namespace("cc1101")
|
||||
CC1101Component = ns.class_("CC1101Component", cg.Component, spi.SPIDevice)
|
||||
|
||||
# Config keys
|
||||
CONF_OUTPUT_POWER = "output_power"
|
||||
CONF_RX_ATTENUATION = "rx_attenuation"
|
||||
CONF_DC_BLOCKING_FILTER = "dc_blocking_filter"
|
||||
CONF_IF_FREQUENCY = "if_frequency"
|
||||
|
||||
@@ -124,9 +124,11 @@ bool CH422GComponent::write_outputs_() {
|
||||
|
||||
float CH422GComponent::get_setup_priority() const { return setup_priority::IO; }
|
||||
|
||||
#ifdef USE_LOOP_PRIORITY
|
||||
// Run our loop() method very early in the loop, so that we cache read values
|
||||
// before other components call our digital_read() method.
|
||||
float CH422GComponent::get_loop_priority() const { return 9.0f; } // Just after WIFI
|
||||
#endif
|
||||
|
||||
void CH422GGPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); }
|
||||
bool CH422GGPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) ^ this->inverted_; }
|
||||
|
||||
@@ -23,7 +23,9 @@ class CH422GComponent : public Component, public i2c::I2CDevice {
|
||||
void pin_mode(uint8_t pin, gpio::Flags flags);
|
||||
|
||||
float get_setup_priority() const override;
|
||||
#ifdef USE_LOOP_PRIORITY
|
||||
float get_loop_priority() const override;
|
||||
#endif
|
||||
void dump_config() override;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -129,9 +129,11 @@ bool CH423Component::write_outputs_() {
|
||||
|
||||
float CH423Component::get_setup_priority() const { return setup_priority::IO; }
|
||||
|
||||
#ifdef USE_LOOP_PRIORITY
|
||||
// Run our loop() method very early in the loop, so that we cache read values
|
||||
// before other components call our digital_read() method.
|
||||
float CH423Component::get_loop_priority() const { return 9.0f; } // Just after WIFI
|
||||
#endif
|
||||
|
||||
void CH423GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); }
|
||||
bool CH423GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) ^ this->inverted_; }
|
||||
|
||||
@@ -22,7 +22,9 @@ class CH423Component : public Component, public i2c::I2CDevice {
|
||||
void pin_mode(uint8_t pin, gpio::Flags flags);
|
||||
|
||||
float get_setup_priority() const override;
|
||||
#ifdef USE_LOOP_PRIORITY
|
||||
float get_loop_priority() const override;
|
||||
#endif
|
||||
void dump_config() override;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -148,14 +148,14 @@ void CurrentBasedCover::dump_config() {
|
||||
}
|
||||
ESP_LOGCONFIG(TAG,
|
||||
" Close Duration: %.1fs\n"
|
||||
"Obstacle Rollback: %.1f%%",
|
||||
" Obstacle Rollback: %.1f%%",
|
||||
this->close_duration_ / 1e3f, this->obstacle_rollback_ * 100);
|
||||
if (this->max_duration_ != UINT32_MAX) {
|
||||
ESP_LOGCONFIG(TAG, "Maximum duration: %.1fs", this->max_duration_ / 1e3f);
|
||||
ESP_LOGCONFIG(TAG, " Maximum duration: %.1fs", this->max_duration_ / 1e3f);
|
||||
}
|
||||
ESP_LOGCONFIG(TAG,
|
||||
"Start sensing delay: %.1fs\n"
|
||||
"Malfunction detection: %s",
|
||||
" Start sensing delay: %.1fs\n"
|
||||
" Malfunction detection: %s",
|
||||
this->start_sensing_delay_ / 1e3f, YESNO(this->malfunction_detection_));
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +79,6 @@ const char *DebugComponent::get_reset_reason_(std::span<char, RESET_REASON_BUFFE
|
||||
} else {
|
||||
snprintf(buf, size, "unknown source");
|
||||
}
|
||||
ESP_LOGD(TAG, "Reset Reason: %s", buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
@@ -107,7 +106,6 @@ const char *DebugComponent::get_wakeup_cause_(std::span<char, RESET_REASON_BUFFE
|
||||
} else {
|
||||
wake_reason = "unknown source";
|
||||
}
|
||||
ESP_LOGD(TAG, "Wakeup Reason: %s", wake_reason);
|
||||
// Return the static string directly - no need to copy to buffer
|
||||
return wake_reason;
|
||||
}
|
||||
@@ -172,7 +170,6 @@ size_t DebugComponent::get_device_info_(std::span<char, DEVICE_INFO_BUFFER_SIZE>
|
||||
}
|
||||
uint32_t flash_size = ESP.getFlashChipSize() / 1024; // NOLINT
|
||||
uint32_t flash_speed = ESP.getFlashChipSpeed() / 1000000; // NOLINT
|
||||
ESP_LOGD(TAG, "Flash Chip: Size=%" PRIu32 "kB Speed=%" PRIu32 "MHz Mode=%s", flash_size, flash_speed, flash_mode);
|
||||
pos = buf_append_printf(buf, size, pos, "|Flash: %" PRIu32 "kB Speed:%" PRIu32 "MHz Mode:%s", flash_size, flash_speed,
|
||||
flash_mode);
|
||||
#endif
|
||||
@@ -194,39 +191,46 @@ size_t DebugComponent::get_device_info_(std::span<char, DEVICE_INFO_BUFFER_SIZE>
|
||||
if (info.features != 0) {
|
||||
pos = buf_append_printf(buf, size, pos, "%sOther:0x%" PRIx32, first_feature ? "" : ", ", info.features);
|
||||
}
|
||||
ESP_LOGD(TAG, "Chip: Model=%s, Cores=%u, Revision=%u", model, info.cores, info.revision);
|
||||
pos = buf_append_printf(buf, size, pos, " Cores:%u Revision:%u", info.cores, info.revision);
|
||||
|
||||
uint32_t cpu_freq_mhz = arch_get_cpu_freq_hz() / 1000000;
|
||||
ESP_LOGD(TAG, "CPU Frequency: %" PRIu32 " MHz", cpu_freq_mhz);
|
||||
pos = buf_append_printf(buf, size, pos, "|CPU Frequency: %" PRIu32 " MHz", cpu_freq_mhz);
|
||||
|
||||
// Framework detection
|
||||
#ifdef USE_ARDUINO
|
||||
ESP_LOGD(TAG, "Framework: Arduino");
|
||||
pos = buf_append_printf(buf, size, pos, "|Framework: Arduino");
|
||||
#elif defined(USE_ESP32)
|
||||
ESP_LOGD(TAG, "Framework: ESP-IDF");
|
||||
pos = buf_append_printf(buf, size, pos, "|Framework: ESP-IDF");
|
||||
#else
|
||||
ESP_LOGW(TAG, "Framework: UNKNOWN");
|
||||
pos = buf_append_printf(buf, size, pos, "|Framework: UNKNOWN");
|
||||
#endif
|
||||
|
||||
ESP_LOGD(TAG, "ESP-IDF Version: %s", esp_get_idf_version());
|
||||
pos = buf_append_printf(buf, size, pos, "|ESP-IDF: %s", esp_get_idf_version());
|
||||
|
||||
uint8_t mac[6];
|
||||
get_mac_address_raw(mac);
|
||||
ESP_LOGD(TAG, "EFuse MAC: %02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
pos = buf_append_printf(buf, size, pos, "|EFuse MAC: %02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3],
|
||||
mac[4], mac[5]);
|
||||
|
||||
char reason_buffer[RESET_REASON_BUFFER_SIZE];
|
||||
const char *reset_reason = get_reset_reason_(std::span<char, RESET_REASON_BUFFER_SIZE>(reason_buffer));
|
||||
pos = buf_append_printf(buf, size, pos, "|Reset: %s", reset_reason);
|
||||
|
||||
const char *wakeup_cause = get_wakeup_cause_(std::span<char, RESET_REASON_BUFFER_SIZE>(reason_buffer));
|
||||
|
||||
uint8_t mac[6];
|
||||
get_mac_address_raw(mac);
|
||||
|
||||
ESP_LOGD(TAG,
|
||||
"ESP32 debug info:\n"
|
||||
" Chip: %s\n"
|
||||
" Cores: %u\n"
|
||||
" Revision: %u\n"
|
||||
" CPU Frequency: %" PRIu32 " MHz\n"
|
||||
" ESP-IDF Version: %s\n"
|
||||
" EFuse MAC: %02X:%02X:%02X:%02X:%02X:%02X\n"
|
||||
" Reset Reason: %s\n"
|
||||
" Wakeup Cause: %s",
|
||||
model, info.cores, info.revision, cpu_freq_mhz, esp_get_idf_version(), mac[0], mac[1], mac[2], mac[3],
|
||||
mac[4], mac[5], reset_reason, wakeup_cause);
|
||||
#if defined(USE_ARDUINO)
|
||||
ESP_LOGD(TAG, " Flash: Size=%" PRIu32 "kB Speed=%" PRIu32 "MHz Mode=%s", flash_size, flash_speed, flash_mode);
|
||||
#endif
|
||||
// Framework detection
|
||||
#ifdef USE_ARDUINO
|
||||
ESP_LOGD(TAG, " Framework: Arduino");
|
||||
pos = buf_append_printf(buf, size, pos, "|Framework: Arduino");
|
||||
#else
|
||||
ESP_LOGD(TAG, " Framework: ESP-IDF");
|
||||
pos = buf_append_printf(buf, size, pos, "|Framework: ESP-IDF");
|
||||
#endif
|
||||
|
||||
pos = buf_append_printf(buf, size, pos, "|ESP-IDF: %s", esp_get_idf_version());
|
||||
pos = buf_append_printf(buf, size, pos, "|EFuse MAC: %02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3],
|
||||
mac[4], mac[5]);
|
||||
pos = buf_append_printf(buf, size, pos, "|Reset: %s", reset_reason);
|
||||
pos = buf_append_printf(buf, size, pos, "|Wakeup: %s", wakeup_cause);
|
||||
|
||||
return pos;
|
||||
|
||||
@@ -128,14 +128,16 @@ size_t DebugComponent::get_device_info_(std::span<char, DEVICE_INFO_BUFFER_SIZE>
|
||||
// NOLINTEND(readability-static-accessed-through-instance)
|
||||
|
||||
ESP_LOGD(TAG,
|
||||
"Chip ID: 0x%08" PRIX32 "\n"
|
||||
"SDK Version: %s\n"
|
||||
"Core Version: %s\n"
|
||||
"Boot Version=%u Mode=%u\n"
|
||||
"CPU Frequency: %u\n"
|
||||
"Flash Chip ID=0x%08" PRIX32 "\n"
|
||||
"Reset Reason: %s\n"
|
||||
"Reset Info: %s",
|
||||
"ESP8266 debug info:\n"
|
||||
" Chip ID: 0x%08" PRIX32 "\n"
|
||||
" SDK Version: %s\n"
|
||||
" Core Version: %s\n"
|
||||
" Boot Version: %u\n"
|
||||
" Boot Mode: %u\n"
|
||||
" CPU Frequency: %u\n"
|
||||
" Flash Chip ID: 0x%08" PRIX32 "\n"
|
||||
" Reset Reason: %s\n"
|
||||
" Reset Info: %s",
|
||||
chip_id, sdk_version, get_core_version_str(core_version_buffer), boot_version, boot_mode, cpu_freq,
|
||||
flash_chip_id, reset_reason, get_reset_info_str(reset_info_buffer, resetInfo.reason));
|
||||
|
||||
|
||||
@@ -27,12 +27,14 @@ size_t DebugComponent::get_device_info_(std::span<char, DEVICE_INFO_BUFFER_SIZE>
|
||||
uint32_t mac_id = lt_cpu_get_mac_id();
|
||||
|
||||
ESP_LOGD(TAG,
|
||||
"LibreTiny Version: %s\n"
|
||||
"Chip: %s (%04x) @ %u MHz\n"
|
||||
"Chip ID: 0x%06" PRIX32 "\n"
|
||||
"Board: %s\n"
|
||||
"Flash: %" PRIu32 " KiB / RAM: %" PRIu32 " KiB\n"
|
||||
"Reset Reason: %s",
|
||||
"LibreTiny debug info:\n"
|
||||
" Version: %s\n"
|
||||
" Chip: %s (%04x) @ %u MHz\n"
|
||||
" Chip ID: 0x%06" PRIX32 "\n"
|
||||
" Board: %s\n"
|
||||
" Flash: %" PRIu32 " KiB\n"
|
||||
" RAM: %" PRIu32 " KiB\n"
|
||||
" Reset Reason: %s",
|
||||
lt_get_version(), lt_cpu_get_model_name(), lt_cpu_get_model(), lt_cpu_get_freq_mhz(), mac_id,
|
||||
lt_get_board_code(), flash_kib, ram_kib, reset_reason);
|
||||
|
||||
|
||||
@@ -79,13 +79,13 @@ static void fa_cb(const struct flash_area *fa, void *user_data) {
|
||||
void DebugComponent::log_partition_info_() {
|
||||
#if CONFIG_FLASH_MAP_LABELS
|
||||
ESP_LOGCONFIG(TAG, "ID | Device | Device Name "
|
||||
"| Label | Offset | Size\n"
|
||||
"--------------------------------------------"
|
||||
"| Label | Offset | Size");
|
||||
ESP_LOGCONFIG(TAG, "--------------------------------------------"
|
||||
"-----------------------------------------------");
|
||||
#else
|
||||
ESP_LOGCONFIG(TAG, "ID | Device | Device Name "
|
||||
"| Offset | Size\n"
|
||||
"-----------------------------------------"
|
||||
"| Offset | Size");
|
||||
ESP_LOGCONFIG(TAG, "-----------------------------------------"
|
||||
"------------------------------");
|
||||
#endif
|
||||
flash_area_foreach(fa_cb, nullptr);
|
||||
@@ -284,11 +284,12 @@ size_t DebugComponent::get_device_info_(std::span<char, DEVICE_INFO_BUFFER_SIZE>
|
||||
char mac_pretty[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
|
||||
get_mac_address_pretty_into_buffer(mac_pretty);
|
||||
ESP_LOGD(TAG,
|
||||
"Code page size: %u, code size: %u, device id: 0x%08x%08x\n"
|
||||
"Encryption root: 0x%08x%08x%08x%08x, Identity Root: 0x%08x%08x%08x%08x\n"
|
||||
"Device address type: %s, address: %s\n"
|
||||
"Part code: nRF%x, version: %c%c%c%c, package: %s\n"
|
||||
"RAM: %ukB, Flash: %ukB, production test: %sdone",
|
||||
"nRF debug info:\n"
|
||||
" Code page size: %u, code size: %u, device id: 0x%08x%08x\n"
|
||||
" Encryption root: 0x%08x%08x%08x%08x, Identity Root: 0x%08x%08x%08x%08x\n"
|
||||
" Device address type: %s, address: %s\n"
|
||||
" Part code: nRF%x, version: %c%c%c%c, package: %s\n"
|
||||
" RAM: %ukB, Flash: %ukB, production test: %sdone",
|
||||
NRF_FICR->CODEPAGESIZE, NRF_FICR->CODESIZE, NRF_FICR->DEVICEID[1], NRF_FICR->DEVICEID[0], NRF_FICR->ER[0],
|
||||
NRF_FICR->ER[1], NRF_FICR->ER[2], NRF_FICR->ER[3], NRF_FICR->IR[0], NRF_FICR->IR[1], NRF_FICR->IR[2],
|
||||
NRF_FICR->IR[3], (NRF_FICR->DEVICEADDRTYPE & 0x1 ? "Random" : "Public"), mac_pretty, NRF_FICR->INFO.PART,
|
||||
@@ -299,23 +300,22 @@ size_t DebugComponent::get_device_info_(std::span<char, DEVICE_INFO_BUFFER_SIZE>
|
||||
(NRF_UICR->PSELRESET[0] & UICR_PSELRESET_CONNECT_Msk) == UICR_PSELRESET_CONNECT_Connected
|
||||
<< UICR_PSELRESET_CONNECT_Pos;
|
||||
ESP_LOGD(
|
||||
TAG, "GPIO as NFC pins: %s, GPIO as nRESET pin: %s",
|
||||
TAG, " GPIO as NFC pins: %s, GPIO as nRESET pin: %s",
|
||||
YESNO((NRF_UICR->NFCPINS & UICR_NFCPINS_PROTECT_Msk) == (UICR_NFCPINS_PROTECT_NFC << UICR_NFCPINS_PROTECT_Pos)),
|
||||
YESNO(n_reset_enabled));
|
||||
if (n_reset_enabled) {
|
||||
uint8_t port = (NRF_UICR->PSELRESET[0] & UICR_PSELRESET_PORT_Msk) >> UICR_PSELRESET_PORT_Pos;
|
||||
uint8_t pin = (NRF_UICR->PSELRESET[0] & UICR_PSELRESET_PIN_Msk) >> UICR_PSELRESET_PIN_Pos;
|
||||
ESP_LOGD(TAG, "nRESET port P%u.%02u", port, pin);
|
||||
ESP_LOGD(TAG, " nRESET port P%u.%02u", port, pin);
|
||||
}
|
||||
#ifdef USE_BOOTLOADER_MCUBOOT
|
||||
ESP_LOGD(TAG, "bootloader: mcuboot");
|
||||
ESP_LOGD(TAG, " Bootloader: mcuboot");
|
||||
#else
|
||||
ESP_LOGD(TAG, "bootloader: Adafruit, version %u.%u.%u", (BOOTLOADER_VERSION_REGISTER >> 16) & 0xFF,
|
||||
ESP_LOGD(TAG, " Bootloader: Adafruit, version %u.%u.%u", (BOOTLOADER_VERSION_REGISTER >> 16) & 0xFF,
|
||||
(BOOTLOADER_VERSION_REGISTER >> 8) & 0xFF, BOOTLOADER_VERSION_REGISTER & 0xFF);
|
||||
ESP_LOGD(TAG,
|
||||
"MBR bootloader addr 0x%08x, UICR bootloader addr 0x%08x\n"
|
||||
"MBR param page addr 0x%08x, UICR param page addr 0x%08x",
|
||||
read_mem_u32(MBR_BOOTLOADER_ADDR), NRF_UICR->NRFFW[0], read_mem_u32(MBR_PARAM_PAGE_ADDR),
|
||||
ESP_LOGD(TAG, " MBR bootloader addr 0x%08x, UICR bootloader addr 0x%08x", read_mem_u32(MBR_BOOTLOADER_ADDR),
|
||||
NRF_UICR->NRFFW[0]);
|
||||
ESP_LOGD(TAG, " MBR param page addr 0x%08x, UICR param page addr 0x%08x", read_mem_u32(MBR_PARAM_PAGE_ADDR),
|
||||
NRF_UICR->NRFFW[1]);
|
||||
if (is_sd_present()) {
|
||||
uint32_t const sd_id = sd_id_get();
|
||||
@@ -326,7 +326,7 @@ size_t DebugComponent::get_device_info_(std::span<char, DEVICE_INFO_BUFFER_SIZE>
|
||||
ver[1] = (sd_version - ver[0] * 1000000) / 1000;
|
||||
ver[2] = (sd_version - ver[0] * 1000000 - ver[1] * 1000);
|
||||
|
||||
ESP_LOGD(TAG, "SoftDevice: S%u %u.%u.%u", sd_id, ver[0], ver[1], ver[2]);
|
||||
ESP_LOGD(TAG, " SoftDevice: S%u %u.%u.%u", sd_id, ver[0], ver[1], ver[2]);
|
||||
#ifdef USE_SOFTDEVICE_ID
|
||||
#ifdef USE_SOFTDEVICE_VERSION
|
||||
if (USE_SOFTDEVICE_ID != sd_id || USE_SOFTDEVICE_VERSION != ver[0]) {
|
||||
@@ -352,10 +352,8 @@ size_t DebugComponent::get_device_info_(std::span<char, DEVICE_INFO_BUFFER_SIZE>
|
||||
}
|
||||
return res;
|
||||
};
|
||||
ESP_LOGD(TAG,
|
||||
"NRFFW %s\n"
|
||||
"NRFHW %s",
|
||||
uicr(NRF_UICR->NRFFW, 13).c_str(), uicr(NRF_UICR->NRFHW, 12).c_str());
|
||||
ESP_LOGD(TAG, " NRFFW %s", uicr(NRF_UICR->NRFFW, 13).c_str());
|
||||
ESP_LOGD(TAG, " NRFHW %s", uicr(NRF_UICR->NRFHW, 12).c_str());
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
@@ -40,9 +40,11 @@ void DeepSleepComponent::loop() {
|
||||
this->begin_sleep();
|
||||
}
|
||||
|
||||
#ifdef USE_LOOP_PRIORITY
|
||||
float DeepSleepComponent::get_loop_priority() const {
|
||||
return -100.0f; // run after everything else is ready
|
||||
}
|
||||
#endif
|
||||
|
||||
void DeepSleepComponent::set_sleep_duration(uint32_t time_ms) { this->sleep_duration_ = uint64_t(time_ms) * 1000; }
|
||||
|
||||
|
||||
@@ -113,7 +113,9 @@ class DeepSleepComponent : public Component {
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
void loop() override;
|
||||
#ifdef USE_LOOP_PRIORITY
|
||||
float get_loop_priority() const override;
|
||||
#endif
|
||||
float get_setup_priority() const override;
|
||||
|
||||
/// Helper to enter deep sleep mode
|
||||
|
||||
@@ -187,18 +187,18 @@ uint8_t DetRangeCfgCommand::on_message(std::string &message) {
|
||||
} else if (message == "Done") {
|
||||
ESP_LOGI(TAG,
|
||||
"Updated detection area config:\n"
|
||||
"Detection area 1 from %.02fm to %.02fm.",
|
||||
" Detection area 1 from %.02fm to %.02fm.",
|
||||
this->min1_, this->max1_);
|
||||
if (this->min2_ >= 0 && this->max2_ >= 0) {
|
||||
ESP_LOGI(TAG, "Detection area 2 from %.02fm to %.02fm.", this->min2_, this->max2_);
|
||||
ESP_LOGI(TAG, " Detection area 2 from %.02fm to %.02fm.", this->min2_, this->max2_);
|
||||
}
|
||||
if (this->min3_ >= 0 && this->max3_ >= 0) {
|
||||
ESP_LOGI(TAG, "Detection area 3 from %.02fm to %.02fm.", this->min3_, this->max3_);
|
||||
ESP_LOGI(TAG, " Detection area 3 from %.02fm to %.02fm.", this->min3_, this->max3_);
|
||||
}
|
||||
if (this->min4_ >= 0 && this->max4_ >= 0) {
|
||||
ESP_LOGI(TAG, "Detection area 4 from %.02fm to %.02fm.", this->min4_, this->max4_);
|
||||
ESP_LOGI(TAG, " Detection area 4 from %.02fm to %.02fm.", this->min4_, this->max4_);
|
||||
}
|
||||
ESP_LOGD(TAG, "Used command: %s", this->cmd_.c_str());
|
||||
ESP_LOGD(TAG, " Used command: %s", this->cmd_.c_str());
|
||||
return 1; // Command done
|
||||
}
|
||||
return 0; // Command not done yet.
|
||||
@@ -222,10 +222,10 @@ uint8_t SetLatencyCommand::on_message(std::string &message) {
|
||||
} else if (message == "Done") {
|
||||
ESP_LOGI(TAG,
|
||||
"Updated output latency config:\n"
|
||||
"Signal that someone was detected is delayed by %.03f s.\n"
|
||||
"Signal that nobody is detected anymore is delayed by %.03f s.",
|
||||
" Signal that someone was detected is delayed by %.03f s.\n"
|
||||
" Signal that nobody is detected anymore is delayed by %.03f s.",
|
||||
this->delay_after_detection_, this->delay_after_disappear_);
|
||||
ESP_LOGD(TAG, "Used command: %s", this->cmd_.c_str());
|
||||
ESP_LOGD(TAG, " Used command: %s", this->cmd_.c_str());
|
||||
return 1; // Command done
|
||||
}
|
||||
return 0; // Command not done yet
|
||||
|
||||
@@ -153,10 +153,7 @@ void EmmetiClimate::reverse_add_(T val, size_t len, esphome::remote_base::Remote
|
||||
|
||||
bool EmmetiClimate::check_checksum_(uint8_t checksum) {
|
||||
uint8_t expected = this->gen_checksum_();
|
||||
ESP_LOGV(TAG,
|
||||
"Expected checksum: %X\n"
|
||||
"Checksum received: %X",
|
||||
expected, checksum);
|
||||
ESP_LOGV(TAG, "Expected checksum: %X, Checksum received: %X", expected, checksum);
|
||||
|
||||
return checksum == expected;
|
||||
}
|
||||
@@ -266,10 +263,7 @@ bool EmmetiClimate::on_receive(remote_base::RemoteReceiveData data) {
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG,
|
||||
"Swing: %d\n"
|
||||
"Sleep: %d",
|
||||
(curr_state.bitmap >> 1) & 0x01, (curr_state.bitmap >> 2) & 0x01);
|
||||
ESP_LOGD(TAG, "Swing: %d, Sleep: %d", (curr_state.bitmap >> 1) & 0x01, (curr_state.bitmap >> 2) & 0x01);
|
||||
|
||||
for (size_t pos = 0; pos < 4; pos++) {
|
||||
if (data.expect_item(EMMETI_BIT_MARK, EMMETI_ONE_SPACE)) {
|
||||
@@ -295,13 +289,8 @@ bool EmmetiClimate::on_receive(remote_base::RemoteReceiveData data) {
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG,
|
||||
"Turbo: %d\n"
|
||||
"Light: %d\n"
|
||||
"Tree: %d\n"
|
||||
"Blow: %d",
|
||||
(curr_state.bitmap >> 3) & 0x01, (curr_state.bitmap >> 4) & 0x01, (curr_state.bitmap >> 5) & 0x01,
|
||||
(curr_state.bitmap >> 6) & 0x01);
|
||||
ESP_LOGD(TAG, "Turbo: %d, Light: %d, Tree: %d, Blow: %d", (curr_state.bitmap >> 3) & 0x01,
|
||||
(curr_state.bitmap >> 4) & 0x01, (curr_state.bitmap >> 5) & 0x01, (curr_state.bitmap >> 6) & 0x01);
|
||||
|
||||
uint16_t control_data = 0;
|
||||
for (size_t pos = 0; pos < 11; pos++) {
|
||||
|
||||
@@ -152,12 +152,13 @@ void ENS160Component::update() {
|
||||
|
||||
// verbose status logging
|
||||
ESP_LOGV(TAG,
|
||||
"Status: ENS160 STATAS bit 0x%x\n"
|
||||
"Status: ENS160 STATER bit 0x%x\n"
|
||||
"Status: ENS160 VALIDITY FLAG 0x%02x\n"
|
||||
"Status: ENS160 NEWDAT bit 0x%x\n"
|
||||
"Status: ENS160 NEWGPR bit 0x%x",
|
||||
(ENS160_DATA_STATUS_STATAS & (status_value)) == ENS160_DATA_STATUS_STATAS,
|
||||
"ENS160 Status Register: 0x%02x\n"
|
||||
" STATAS bit 0x%x\n"
|
||||
" STATER bit 0x%x\n"
|
||||
" VALIDITY FLAG 0x%02x\n"
|
||||
" NEWDAT bit 0x%x\n"
|
||||
" NEWGPR bit 0x%x",
|
||||
status_value, (ENS160_DATA_STATUS_STATAS & (status_value)) == ENS160_DATA_STATUS_STATAS,
|
||||
(ENS160_DATA_STATUS_STATER & (status_value)) == ENS160_DATA_STATUS_STATER,
|
||||
(ENS160_DATA_STATUS_VALIDITY & status_value) >> 2,
|
||||
(ENS160_DATA_STATUS_NEWDAT & (status_value)) == ENS160_DATA_STATUS_NEWDAT,
|
||||
|
||||
@@ -209,9 +209,10 @@ bool ES8388::set_dac_output(DacOutputLine line) {
|
||||
};
|
||||
|
||||
ESP_LOGV(TAG,
|
||||
"Setting ES8388_DACPOWER to 0x%02X\n"
|
||||
"Setting ES8388_DACCONTROL24 / ES8388_DACCONTROL25 to 0x%02X\n"
|
||||
"Setting ES8388_DACCONTROL26 / ES8388_DACCONTROL27 to 0x%02X",
|
||||
"DAC output config:\n"
|
||||
" DACPOWER: 0x%02X\n"
|
||||
" DACCONTROL24/25: 0x%02X\n"
|
||||
" DACCONTROL26/27: 0x%02X",
|
||||
dac_power, reg_out1, reg_out2);
|
||||
|
||||
ES8388_ERROR_CHECK(this->write_byte(ES8388_DACCONTROL24, reg_out1)); // LOUT1VOL
|
||||
|
||||
@@ -1258,21 +1258,15 @@ def _configure_lwip_max_sockets(conf: dict) -> None:
|
||||
This function runs in to_code() after all components have registered their socket needs.
|
||||
User-provided sdkconfig_options take precedence.
|
||||
"""
|
||||
from esphome.components.socket import KEY_SOCKET_CONSUMERS
|
||||
from esphome.components.socket import get_socket_counts
|
||||
|
||||
# Check if user manually specified CONFIG_LWIP_MAX_SOCKETS
|
||||
user_max_sockets = conf[CONF_SDKCONFIG_OPTIONS].get("CONFIG_LWIP_MAX_SOCKETS")
|
||||
|
||||
socket_consumers: dict[str, int] = CORE.data.get(KEY_SOCKET_CONSUMERS, {})
|
||||
total_sockets = sum(socket_consumers.values())
|
||||
|
||||
# Early return if no sockets registered and no user override
|
||||
if total_sockets == 0 and user_max_sockets is None:
|
||||
return
|
||||
|
||||
components_list = ", ".join(
|
||||
f"{name}={count}" for name, count in sorted(socket_consumers.items())
|
||||
)
|
||||
# CONFIG_LWIP_MAX_SOCKETS is a single VFS socket pool shared by all socket
|
||||
# types (TCP clients, TCP listeners, and UDP). Include all three counts.
|
||||
sc = get_socket_counts()
|
||||
total_sockets = sc.tcp + sc.udp + sc.tcp_listen
|
||||
|
||||
# User specified their own value - respect it but warn if insufficient
|
||||
if user_max_sockets is not None:
|
||||
@@ -1281,22 +1275,23 @@ def _configure_lwip_max_sockets(conf: dict) -> None:
|
||||
user_max_sockets,
|
||||
)
|
||||
|
||||
# Warn if user's value is less than what components need
|
||||
if total_sockets > 0:
|
||||
user_sockets_int = 0
|
||||
with contextlib.suppress(ValueError, TypeError):
|
||||
user_sockets_int = int(user_max_sockets)
|
||||
user_sockets_int = 0
|
||||
with contextlib.suppress(ValueError, TypeError):
|
||||
user_sockets_int = int(user_max_sockets)
|
||||
|
||||
if user_sockets_int < total_sockets:
|
||||
_LOGGER.warning(
|
||||
"CONFIG_LWIP_MAX_SOCKETS is set to %d but your configuration "
|
||||
"needs %d sockets (registered: %s). You may experience socket "
|
||||
"exhaustion errors. Consider increasing to at least %d.",
|
||||
user_sockets_int,
|
||||
total_sockets,
|
||||
components_list,
|
||||
total_sockets,
|
||||
)
|
||||
if user_sockets_int < total_sockets:
|
||||
_LOGGER.warning(
|
||||
"CONFIG_LWIP_MAX_SOCKETS is set to %d but your configuration "
|
||||
"needs %d sockets (%d TCP + %d UDP + %d TCP_LISTEN). You may "
|
||||
"experience socket exhaustion errors. Consider increasing to "
|
||||
"at least %d.",
|
||||
user_sockets_int,
|
||||
total_sockets,
|
||||
sc.tcp,
|
||||
sc.udp,
|
||||
sc.tcp_listen,
|
||||
total_sockets,
|
||||
)
|
||||
# User's value already added via sdkconfig_options processing
|
||||
return
|
||||
|
||||
@@ -1305,11 +1300,19 @@ def _configure_lwip_max_sockets(conf: dict) -> None:
|
||||
max_sockets = max(DEFAULT_MAX_SOCKETS, total_sockets)
|
||||
|
||||
log_level = logging.INFO if max_sockets > DEFAULT_MAX_SOCKETS else logging.DEBUG
|
||||
sock_min = " (min)" if max_sockets > total_sockets else ""
|
||||
_LOGGER.log(
|
||||
log_level,
|
||||
"Setting CONFIG_LWIP_MAX_SOCKETS to %d (registered: %s)",
|
||||
"Setting CONFIG_LWIP_MAX_SOCKETS to %d%s "
|
||||
"(TCP=%d [%s], UDP=%d [%s], TCP_LISTEN=%d [%s])",
|
||||
max_sockets,
|
||||
components_list,
|
||||
sock_min,
|
||||
sc.tcp,
|
||||
sc.tcp_details,
|
||||
sc.udp,
|
||||
sc.udp_details,
|
||||
sc.tcp_listen,
|
||||
sc.tcp_listen_details,
|
||||
)
|
||||
|
||||
add_idf_sdkconfig_option("CONFIG_LWIP_MAX_SOCKETS", max_sockets)
|
||||
|
||||
@@ -423,10 +423,8 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
|
||||
for (auto &svc : this->services_) {
|
||||
char uuid_buf[espbt::UUID_STR_LEN];
|
||||
svc->uuid.to_str(uuid_buf);
|
||||
ESP_LOGV(TAG,
|
||||
"[%d] [%s] Service UUID: %s\n"
|
||||
"[%d] [%s] start_handle: 0x%x end_handle: 0x%x",
|
||||
this->connection_index_, this->address_str_, uuid_buf, this->connection_index_, this->address_str_,
|
||||
ESP_LOGV(TAG, "[%d] [%s] Service UUID: %s", this->connection_index_, this->address_str_, uuid_buf);
|
||||
ESP_LOGV(TAG, "[%d] [%s] start_handle: 0x%x end_handle: 0x%x", this->connection_index_, this->address_str_,
|
||||
svc->start_handle, svc->end_handle);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -20,8 +20,10 @@ def _consume_camera_web_server_sockets(config: ConfigType) -> ConfigType:
|
||||
from esphome.components import socket
|
||||
|
||||
# Each camera web server instance needs 1 listening socket + 2 client connections
|
||||
sockets_needed = 3
|
||||
socket.consume_sockets(sockets_needed, "esp32_camera_web_server")(config)
|
||||
socket.consume_sockets(2, "esp32_camera_web_server")(config)
|
||||
socket.consume_sockets(1, "esp32_camera_web_server", socket.SocketType.TCP_LISTEN)(
|
||||
config
|
||||
)
|
||||
return config
|
||||
|
||||
|
||||
|
||||
@@ -106,11 +106,12 @@ void Esp32HostedUpdate::setup() {
|
||||
esp_app_desc_t *app_desc = (esp_app_desc_t *) (this->firmware_data_ + app_desc_offset);
|
||||
if (app_desc->magic_word == ESP_APP_DESC_MAGIC_WORD) {
|
||||
ESP_LOGD(TAG,
|
||||
"Firmware version: %s\n"
|
||||
"Project name: %s\n"
|
||||
"Build date: %s\n"
|
||||
"Build time: %s\n"
|
||||
"IDF version: %s",
|
||||
"ESP32 Hosted firmware:\n"
|
||||
" Firmware version: %s\n"
|
||||
" Project name: %s\n"
|
||||
" Build date: %s\n"
|
||||
" Build time: %s\n"
|
||||
" IDF version: %s",
|
||||
app_desc->version, app_desc->project_name, app_desc->date, app_desc->time, app_desc->idf_ver);
|
||||
this->update_info_.latest_version = app_desc->version;
|
||||
if (this->update_info_.latest_version != this->update_info_.current_version) {
|
||||
|
||||
@@ -97,8 +97,9 @@ def _consume_ota_sockets(config: ConfigType) -> ConfigType:
|
||||
"""Register socket needs for OTA component."""
|
||||
from esphome.components import socket
|
||||
|
||||
# OTA needs 1 listening socket (client connections are temporary during updates)
|
||||
socket.consume_sockets(1, "ota")(config)
|
||||
# OTA needs 1 listening socket. The active transfer connection during an update
|
||||
# uses a TCP PCB from the general pool, covered by MIN_TCP_SOCKETS headroom.
|
||||
socket.consume_sockets(1, "ota", socket.SocketType.TCP_LISTEN)(config)
|
||||
return config
|
||||
|
||||
|
||||
|
||||
@@ -21,11 +21,9 @@ void ESPNowTransport::setup() {
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG,
|
||||
"Registering ESP-NOW handlers\n"
|
||||
"Peer address: %02X:%02X:%02X:%02X:%02X:%02X",
|
||||
this->peer_address_[0], this->peer_address_[1], this->peer_address_[2], this->peer_address_[3],
|
||||
this->peer_address_[4], this->peer_address_[5]);
|
||||
ESP_LOGI(TAG, "Registering ESP-NOW handlers, peer: %02X:%02X:%02X:%02X:%02X:%02X", this->peer_address_[0],
|
||||
this->peer_address_[1], this->peer_address_[2], this->peer_address_[3], this->peer_address_[4],
|
||||
this->peer_address_[5]);
|
||||
|
||||
// Register received handler
|
||||
this->parent_->register_received_handler(this);
|
||||
|
||||
@@ -866,10 +866,7 @@ void EthernetComponent::write_phy_register_(esp_eth_mac_t *mac, PHYRegister regi
|
||||
}
|
||||
#endif
|
||||
|
||||
ESP_LOGD(TAG,
|
||||
"Writing to PHY Register Address: 0x%02" PRIX32 "\n"
|
||||
"Writing to PHY Register Value: 0x%04" PRIX32,
|
||||
register_data.address, register_data.value);
|
||||
ESP_LOGD(TAG, "Writing PHY reg 0x%02" PRIX32 " = 0x%04" PRIX32, register_data.address, register_data.value);
|
||||
err = mac->write_phy_reg(mac, this->phy_addr_, register_data.address, register_data.value);
|
||||
ESPHL_ERROR_CHECK(err, "Writing PHY Register failed");
|
||||
|
||||
|
||||
@@ -150,9 +150,9 @@ void EzoPMP::read_command_result_() {
|
||||
if (current_char == '\0') {
|
||||
ESP_LOGV(TAG,
|
||||
"Read Response from device: %s\n"
|
||||
"First Component: %s\n"
|
||||
"Second Component: %s\n"
|
||||
"Third Component: %s",
|
||||
" First Component: %s\n"
|
||||
" Second Component: %s\n"
|
||||
" Third Component: %s",
|
||||
(char *) response_buffer, (char *) first_parameter_buffer, (char *) second_parameter_buffer,
|
||||
(char *) third_parameter_buffer);
|
||||
|
||||
|
||||
@@ -97,10 +97,10 @@ void GCJA5Component::parse_data_() {
|
||||
|
||||
ESP_LOGI(TAG,
|
||||
"GCJA5 Status\n"
|
||||
"Overall Status : %i\n"
|
||||
"PD Status : %i\n"
|
||||
"LD Status : %i\n"
|
||||
"Fan Status : %i",
|
||||
" Overall Status : %i\n"
|
||||
" PD Status : %i\n"
|
||||
" LD Status : %i\n"
|
||||
" Fan Status : %i",
|
||||
(status >> 6) & 0x03, (status >> 4) & 0x03, (status >> 2) & 0x03, (status >> 0) & 0x03);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,13 +38,13 @@ void GraphicalDisplayMenu::setup() {
|
||||
void GraphicalDisplayMenu::dump_config() {
|
||||
ESP_LOGCONFIG(TAG,
|
||||
"Graphical Display Menu\n"
|
||||
"Has Display: %s\n"
|
||||
"Popup Mode: %s\n"
|
||||
"Advanced Drawing Mode: %s\n"
|
||||
"Has Font: %s\n"
|
||||
"Mode: %s\n"
|
||||
"Active: %s\n"
|
||||
"Menu items:",
|
||||
" Has Display: %s\n"
|
||||
" Popup Mode: %s\n"
|
||||
" Advanced Drawing Mode: %s\n"
|
||||
" Has Font: %s\n"
|
||||
" Mode: %s\n"
|
||||
" Active: %s\n"
|
||||
" Menu items:",
|
||||
YESNO(this->display_ != nullptr), YESNO(this->display_ != nullptr), YESNO(this->display_ == nullptr),
|
||||
YESNO(this->font_ != nullptr),
|
||||
this->mode_ == display_menu_base::MENU_MODE_ROTARY ? "Rotary" : "Joystick", YESNO(this->active_));
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <queue>
|
||||
#ifdef USE_SENSOR
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#endif
|
||||
|
||||
1
esphome/components/hdc302x/__init__.py
Normal file
1
esphome/components/hdc302x/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
CODEOWNERS = ["@joshuasing"]
|
||||
171
esphome/components/hdc302x/hdc302x.cpp
Normal file
171
esphome/components/hdc302x/hdc302x.cpp
Normal file
@@ -0,0 +1,171 @@
|
||||
#include "hdc302x.h"
|
||||
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome::hdc302x {
|
||||
|
||||
static const char *const TAG = "hdc302x.sensor";
|
||||
|
||||
// Commands (per datasheet Table 7-4)
|
||||
static const uint8_t HDC302X_CMD_SOFT_RESET[2] = {0x30, 0xa2};
|
||||
static const uint8_t HDC302X_CMD_CLEAR_STATUS_REGISTER[2] = {0x30, 0x41};
|
||||
|
||||
static const uint8_t HDC302X_CMD_TRIGGER_MSB = 0x24;
|
||||
|
||||
static const uint8_t HDC302X_CMD_HEATER_ENABLE[2] = {0x30, 0x6d};
|
||||
static const uint8_t HDC302X_CMD_HEATER_DISABLE[2] = {0x30, 0x66};
|
||||
static const uint8_t HDC302X_CMD_HEATER_CONFIGURE[2] = {0x30, 0x6e};
|
||||
|
||||
void HDC302XComponent::setup() {
|
||||
// Soft reset the device
|
||||
if (this->write(HDC302X_CMD_SOFT_RESET, 2) != i2c::ERROR_OK) {
|
||||
this->mark_failed(LOG_STR("Soft reset failed"));
|
||||
return;
|
||||
}
|
||||
// Delay SensorRR (reset ready), per datasheet, 6.5.
|
||||
delay(3);
|
||||
|
||||
// Clear status register
|
||||
if (this->write(HDC302X_CMD_CLEAR_STATUS_REGISTER, 2) != i2c::ERROR_OK) {
|
||||
this->mark_failed(LOG_STR("Clear status failed"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void HDC302XComponent::dump_config() {
|
||||
ESP_LOGCONFIG(TAG,
|
||||
"HDC302x:\n"
|
||||
" Heater: %s",
|
||||
this->heater_active_ ? "active" : "inactive");
|
||||
LOG_I2C_DEVICE(this);
|
||||
LOG_UPDATE_INTERVAL(this);
|
||||
LOG_SENSOR(" ", "Temperature", this->temp_sensor_);
|
||||
LOG_SENSOR(" ", "Humidity", this->humidity_sensor_);
|
||||
}
|
||||
|
||||
void HDC302XComponent::update() {
|
||||
uint8_t cmd[] = {
|
||||
HDC302X_CMD_TRIGGER_MSB,
|
||||
this->power_mode_,
|
||||
};
|
||||
if (this->write(cmd, 2) != i2c::ERROR_OK) {
|
||||
this->status_set_warning(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
|
||||
return;
|
||||
}
|
||||
|
||||
// Read data after ADC conversion has completed
|
||||
this->set_timeout(this->conversion_delay_ms_(), [this]() { this->read_data_(); });
|
||||
}
|
||||
|
||||
void HDC302XComponent::start_heater(uint16_t power, uint32_t duration_ms) {
|
||||
if (!this->disable_heater_()) {
|
||||
ESP_LOGD(TAG, "Heater disable before start failed");
|
||||
}
|
||||
if (!this->configure_heater_(power) || !this->enable_heater_()) {
|
||||
ESP_LOGW(TAG, "Heater start failed");
|
||||
return;
|
||||
}
|
||||
this->heater_active_ = true;
|
||||
this->cancel_timeout("heater_off");
|
||||
if (duration_ms > 0) {
|
||||
this->set_timeout("heater_off", duration_ms, [this]() { this->stop_heater(); });
|
||||
}
|
||||
}
|
||||
|
||||
void HDC302XComponent::stop_heater() {
|
||||
this->cancel_timeout("heater_off");
|
||||
if (!this->disable_heater_()) {
|
||||
ESP_LOGW(TAG, "Heater stop failed");
|
||||
}
|
||||
this->heater_active_ = false;
|
||||
}
|
||||
|
||||
bool HDC302XComponent::enable_heater_() {
|
||||
if (this->write(HDC302X_CMD_HEATER_ENABLE, 2) != i2c::ERROR_OK) {
|
||||
ESP_LOGE(TAG, "Enable heater failed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HDC302XComponent::configure_heater_(uint16_t power_level) {
|
||||
if (power_level > 0x3fff) {
|
||||
ESP_LOGW(TAG, "Heater power 0x%04x exceeds max 0x3fff", power_level);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Heater current level config.
|
||||
uint8_t config[] = {
|
||||
static_cast<uint8_t>((power_level >> 8) & 0xff), // MSB
|
||||
static_cast<uint8_t>(power_level & 0xff) // LSB
|
||||
};
|
||||
|
||||
// Configure level of heater current (per datasheet 7.5.7.8).
|
||||
uint8_t cmd[] = {
|
||||
HDC302X_CMD_HEATER_CONFIGURE[0], HDC302X_CMD_HEATER_CONFIGURE[1], config[0], config[1],
|
||||
crc8(config, 2, 0xff, 0x31, true),
|
||||
};
|
||||
if (this->write(cmd, sizeof(cmd)) != i2c::ERROR_OK) {
|
||||
ESP_LOGE(TAG, "Configure heater failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HDC302XComponent::disable_heater_() {
|
||||
if (this->write(HDC302X_CMD_HEATER_DISABLE, 2) != i2c::ERROR_OK) {
|
||||
ESP_LOGE(TAG, "Disable heater failed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void HDC302XComponent::read_data_() {
|
||||
uint8_t buf[6];
|
||||
if (this->read(buf, 6) != i2c::ERROR_OK) {
|
||||
this->status_set_warning(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check checksums
|
||||
if (crc8(buf, 2, 0xff, 0x31, true) != buf[2] || crc8(buf + 3, 2, 0xff, 0x31, true) != buf[5]) {
|
||||
this->status_set_warning(LOG_STR("Read data: invalid CRC"));
|
||||
return;
|
||||
}
|
||||
|
||||
this->status_clear_warning();
|
||||
|
||||
if (this->temp_sensor_ != nullptr) {
|
||||
uint16_t raw_t = encode_uint16(buf[0], buf[1]);
|
||||
// Calculate temperature in Celsius per datasheet section 7.3.3.
|
||||
float temp = -45 + 175 * (float(raw_t) / 65535.0f);
|
||||
this->temp_sensor_->publish_state(temp);
|
||||
}
|
||||
|
||||
if (this->humidity_sensor_ != nullptr) {
|
||||
uint16_t raw_rh = encode_uint16(buf[3], buf[4]);
|
||||
// Calculate RH% per datasheet section 7.3.3.
|
||||
float humidity = 100 * (float(raw_rh) / 65535.0f);
|
||||
this->humidity_sensor_->publish_state(humidity);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t HDC302XComponent::conversion_delay_ms_() {
|
||||
// ADC conversion delay per datasheet, Table 7-5. - Trigger on Demand
|
||||
switch (this->power_mode_) {
|
||||
case HDC302XPowerMode::BALANCED:
|
||||
return 8;
|
||||
case HDC302XPowerMode::LOW_POWER:
|
||||
return 5;
|
||||
case HDC302XPowerMode::ULTRA_LOW_POWER:
|
||||
return 4;
|
||||
case HDC302XPowerMode::HIGH_ACCURACY:
|
||||
default:
|
||||
return 13;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace esphome::hdc302x
|
||||
68
esphome/components/hdc302x/hdc302x.h
Normal file
68
esphome/components/hdc302x/hdc302x.h
Normal file
@@ -0,0 +1,68 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/automation.h"
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
|
||||
namespace esphome::hdc302x {
|
||||
|
||||
enum HDC302XPowerMode : uint8_t {
|
||||
HIGH_ACCURACY = 0x00,
|
||||
BALANCED = 0x0b,
|
||||
LOW_POWER = 0x16,
|
||||
ULTRA_LOW_POWER = 0xff,
|
||||
};
|
||||
|
||||
/**
|
||||
HDC302x Temperature and humidity sensor.
|
||||
|
||||
Datasheet:
|
||||
https://www.ti.com/lit/ds/symlink/hdc3020.pdf
|
||||
*/
|
||||
class HDC302XComponent : public PollingComponent, public i2c::I2CDevice {
|
||||
public:
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
void update() override;
|
||||
|
||||
void start_heater(uint16_t power, uint32_t duration_ms);
|
||||
void stop_heater();
|
||||
|
||||
void set_temp_sensor(sensor::Sensor *temp_sensor) { this->temp_sensor_ = temp_sensor; }
|
||||
void set_humidity_sensor(sensor::Sensor *humidity_sensor) { this->humidity_sensor_ = humidity_sensor; }
|
||||
|
||||
void set_power_mode(HDC302XPowerMode power_mode) { this->power_mode_ = power_mode; }
|
||||
|
||||
protected:
|
||||
sensor::Sensor *temp_sensor_{nullptr};
|
||||
sensor::Sensor *humidity_sensor_{nullptr};
|
||||
|
||||
HDC302XPowerMode power_mode_{HDC302XPowerMode::HIGH_ACCURACY};
|
||||
bool heater_active_{false};
|
||||
|
||||
bool enable_heater_();
|
||||
bool configure_heater_(uint16_t power_level);
|
||||
bool disable_heater_();
|
||||
void read_data_();
|
||||
uint32_t conversion_delay_ms_();
|
||||
};
|
||||
|
||||
template<typename... Ts> class HeaterOnAction : public Action<Ts...>, public Parented<HDC302XComponent> {
|
||||
public:
|
||||
TEMPLATABLE_VALUE(uint16_t, power)
|
||||
TEMPLATABLE_VALUE(uint32_t, duration)
|
||||
|
||||
void play(const Ts &...x) override {
|
||||
auto power_val = this->power_.value(x...);
|
||||
auto duration_val = this->duration_.value(x...);
|
||||
this->parent_->start_heater(power_val, duration_val);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... Ts> class HeaterOffAction : public Action<Ts...>, public Parented<HDC302XComponent> {
|
||||
public:
|
||||
void play(const Ts &...x) override { this->parent_->stop_heater(); }
|
||||
};
|
||||
|
||||
} // namespace esphome::hdc302x
|
||||
135
esphome/components/hdc302x/sensor.py
Normal file
135
esphome/components/hdc302x/sensor.py
Normal file
@@ -0,0 +1,135 @@
|
||||
from esphome import automation
|
||||
from esphome.automation import maybe_simple_id
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import i2c, sensor
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
CONF_DURATION,
|
||||
CONF_HUMIDITY,
|
||||
CONF_ID,
|
||||
CONF_POWER,
|
||||
CONF_POWER_MODE,
|
||||
CONF_TEMPERATURE,
|
||||
DEVICE_CLASS_HUMIDITY,
|
||||
DEVICE_CLASS_TEMPERATURE,
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
UNIT_CELSIUS,
|
||||
UNIT_PERCENT,
|
||||
)
|
||||
|
||||
DEPENDENCIES = ["i2c"]
|
||||
|
||||
hdc302x_ns = cg.esphome_ns.namespace("hdc302x")
|
||||
HDC302XComponent = hdc302x_ns.class_(
|
||||
"HDC302XComponent", cg.PollingComponent, i2c.I2CDevice
|
||||
)
|
||||
|
||||
HDC302XPowerMode = hdc302x_ns.enum("HDC302XPowerMode")
|
||||
POWER_MODE_OPTIONS = {
|
||||
"HIGH_ACCURACY": HDC302XPowerMode.HIGH_ACCURACY,
|
||||
"BALANCED": HDC302XPowerMode.BALANCED,
|
||||
"LOW_POWER": HDC302XPowerMode.LOW_POWER,
|
||||
"ULTRA_LOW_POWER": HDC302XPowerMode.ULTRA_LOW_POWER,
|
||||
}
|
||||
|
||||
# Actions
|
||||
HeaterOnAction = hdc302x_ns.class_("HeaterOnAction", automation.Action)
|
||||
HeaterOffAction = hdc302x_ns.class_("HeaterOffAction", automation.Action)
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(HDC302XComponent),
|
||||
cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
accuracy_decimals=2,
|
||||
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
),
|
||||
cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(
|
||||
unit_of_measurement=UNIT_PERCENT,
|
||||
accuracy_decimals=2,
|
||||
device_class=DEVICE_CLASS_HUMIDITY,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
),
|
||||
cv.Optional(CONF_POWER_MODE, default="HIGH_ACCURACY"): cv.enum(
|
||||
POWER_MODE_OPTIONS, upper=True
|
||||
),
|
||||
}
|
||||
)
|
||||
.extend(cv.polling_component_schema("60s"))
|
||||
.extend(i2c.i2c_device_schema(0x44)) # Default address per datasheet, Table 7-2.
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
await i2c.register_i2c_device(var, config)
|
||||
|
||||
if temp_config := config.get(CONF_TEMPERATURE):
|
||||
sens = await sensor.new_sensor(temp_config)
|
||||
cg.add(var.set_temp_sensor(sens))
|
||||
|
||||
if humidity_config := config.get(CONF_HUMIDITY):
|
||||
sens = await sensor.new_sensor(humidity_config)
|
||||
cg.add(var.set_humidity_sensor(sens))
|
||||
|
||||
cg.add(var.set_power_mode(config[CONF_POWER_MODE]))
|
||||
|
||||
|
||||
# HDC302x heater power configs, per datasheet Table 7-15.
|
||||
HDC302X_HEATER_POWER_MAP = {
|
||||
"QUARTER": 0x009F,
|
||||
"HALF": 0x03FF,
|
||||
"FULL": 0x3FFF,
|
||||
}
|
||||
|
||||
|
||||
def heater_power_value(value):
|
||||
"""Accept enum names or raw uint16 values"""
|
||||
if isinstance(value, cv.Lambda):
|
||||
return value
|
||||
if isinstance(value, str):
|
||||
upper = value.upper()
|
||||
if upper in HDC302X_HEATER_POWER_MAP:
|
||||
return HDC302X_HEATER_POWER_MAP[upper]
|
||||
raise cv.Invalid(
|
||||
f"Unknown heater power preset: {value}. Use QUARTER, HALF, FULL, or a raw value 0-16383"
|
||||
)
|
||||
return cv.int_range(min=0, max=0x3FFF)(value)
|
||||
|
||||
|
||||
HDC302X_ACTION_SCHEMA = maybe_simple_id({cv.GenerateID(): cv.use_id(HDC302XComponent)})
|
||||
|
||||
HDC302X_HEATER_ON_ACTION_SCHEMA = maybe_simple_id(
|
||||
{
|
||||
cv.GenerateID(): cv.use_id(HDC302XComponent),
|
||||
cv.Optional(CONF_POWER, default="QUARTER"): cv.templatable(heater_power_value),
|
||||
cv.Optional(CONF_DURATION, default="5s"): cv.templatable(
|
||||
cv.positive_time_period_milliseconds
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"hdc302x.heater_on", HeaterOnAction, HDC302X_HEATER_ON_ACTION_SCHEMA
|
||||
)
|
||||
async def hdc302x_heater_on_to_code(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
template_ = await cg.templatable(config[CONF_POWER], args, cg.uint16)
|
||||
cg.add(var.set_power(template_))
|
||||
template_ = await cg.templatable(config[CONF_DURATION], args, cg.uint32)
|
||||
cg.add(var.set_duration(template_))
|
||||
return var
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"hdc302x.heater_off", HeaterOffAction, HDC302X_ACTION_SCHEMA
|
||||
)
|
||||
async def hdc302x_heater_off_to_code(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
@@ -35,10 +35,7 @@ uint8_t HONEYWELLABPSensor::readsensor_() {
|
||||
pressure_count_ = ((uint16_t) (buf_[0]) << 8 & 0x3F00) | ((uint16_t) (buf_[1]) & 0xFF);
|
||||
// 11 - bit temperature is all of byte 2 (lowest 8 bits) and the first three bits of byte 3
|
||||
temperature_count_ = (((uint16_t) (buf_[2]) << 3) & 0x7F8) | (((uint16_t) (buf_[3]) >> 5) & 0x7);
|
||||
ESP_LOGV(TAG,
|
||||
"Sensor pressure_count_ %d\n"
|
||||
"Sensor temperature_count_ %d",
|
||||
pressure_count_, temperature_count_);
|
||||
ESP_LOGV(TAG, "Sensor pressure_count_ %d, temperature_count_ %d", pressure_count_, temperature_count_);
|
||||
}
|
||||
return status_;
|
||||
}
|
||||
|
||||
@@ -330,38 +330,72 @@ class HttpRequestComponent : public Component {
|
||||
void set_follow_redirects(bool follow_redirects) { this->follow_redirects_ = follow_redirects; }
|
||||
void set_redirect_limit(uint16_t limit) { this->redirect_limit_ = limit; }
|
||||
|
||||
std::shared_ptr<HttpContainer> get(const std::string &url) { return this->start(url, "GET", "", {}); }
|
||||
std::shared_ptr<HttpContainer> get(const std::string &url, const std::list<Header> &request_headers) {
|
||||
std::shared_ptr<HttpContainer> get(const std::string &url) {
|
||||
return this->start(url, "GET", "", std::vector<Header>{});
|
||||
}
|
||||
std::shared_ptr<HttpContainer> get(const std::string &url, const std::vector<Header> &request_headers) {
|
||||
return this->start(url, "GET", "", request_headers);
|
||||
}
|
||||
std::shared_ptr<HttpContainer> get(const std::string &url, const std::list<Header> &request_headers,
|
||||
std::shared_ptr<HttpContainer> get(const std::string &url, const std::vector<Header> &request_headers,
|
||||
const std::vector<std::string> &lower_case_collect_headers) {
|
||||
return this->start(url, "GET", "", request_headers, lower_case_collect_headers);
|
||||
}
|
||||
std::shared_ptr<HttpContainer> post(const std::string &url, const std::string &body) {
|
||||
return this->start(url, "POST", body, {});
|
||||
return this->start(url, "POST", body, std::vector<Header>{});
|
||||
}
|
||||
std::shared_ptr<HttpContainer> post(const std::string &url, const std::string &body,
|
||||
const std::list<Header> &request_headers) {
|
||||
const std::vector<Header> &request_headers) {
|
||||
return this->start(url, "POST", body, request_headers);
|
||||
}
|
||||
std::shared_ptr<HttpContainer> post(const std::string &url, const std::string &body,
|
||||
const std::list<Header> &request_headers,
|
||||
const std::vector<Header> &request_headers,
|
||||
const std::vector<std::string> &lower_case_collect_headers) {
|
||||
return this->start(url, "POST", body, request_headers, lower_case_collect_headers);
|
||||
}
|
||||
|
||||
// Remove before 2027.1.0
|
||||
ESPDEPRECATED("Pass request_headers as std::vector<Header> instead of std::list. Removed in 2027.1.0.", "2026.7.0")
|
||||
std::shared_ptr<HttpContainer> get(const std::string &url, const std::list<Header> &request_headers) {
|
||||
return this->get(url, std::vector<Header>(request_headers.begin(), request_headers.end()));
|
||||
}
|
||||
// Remove before 2027.1.0
|
||||
ESPDEPRECATED("Pass request_headers as std::vector<Header> instead of std::list. Removed in 2027.1.0.", "2026.7.0")
|
||||
std::shared_ptr<HttpContainer> get(const std::string &url, const std::list<Header> &request_headers,
|
||||
const std::vector<std::string> &collect_headers) {
|
||||
return this->get(url, std::vector<Header>(request_headers.begin(), request_headers.end()), collect_headers);
|
||||
}
|
||||
// Remove before 2027.1.0
|
||||
ESPDEPRECATED("Pass request_headers as std::vector<Header> instead of std::list. Removed in 2027.1.0.", "2026.7.0")
|
||||
std::shared_ptr<HttpContainer> post(const std::string &url, const std::string &body,
|
||||
const std::list<Header> &request_headers) {
|
||||
return this->post(url, body, std::vector<Header>(request_headers.begin(), request_headers.end()));
|
||||
}
|
||||
// Remove before 2027.1.0
|
||||
ESPDEPRECATED("Pass request_headers as std::vector<Header> instead of std::list. Removed in 2027.1.0.", "2026.7.0")
|
||||
std::shared_ptr<HttpContainer> post(const std::string &url, const std::string &body,
|
||||
const std::list<Header> &request_headers,
|
||||
const std::vector<std::string> &collect_headers) {
|
||||
return this->post(url, body, std::vector<Header>(request_headers.begin(), request_headers.end()), collect_headers);
|
||||
}
|
||||
|
||||
std::shared_ptr<HttpContainer> start(const std::string &url, const std::string &method, const std::string &body,
|
||||
const std::vector<Header> &request_headers) {
|
||||
// Call perform() directly to avoid ambiguity with the deprecated overloads
|
||||
return this->perform(url, method, body, request_headers, {});
|
||||
}
|
||||
|
||||
// Remove before 2027.1.0
|
||||
ESPDEPRECATED("Pass request_headers as std::vector<Header> instead of std::list. Removed in 2027.1.0.", "2026.7.0")
|
||||
std::shared_ptr<HttpContainer> start(const std::string &url, const std::string &method, const std::string &body,
|
||||
const std::list<Header> &request_headers) {
|
||||
// Call perform() directly to avoid ambiguity with the std::set overload
|
||||
return this->perform(url, method, body, request_headers, {});
|
||||
return this->start(url, method, body, std::vector<Header>(request_headers.begin(), request_headers.end()));
|
||||
}
|
||||
|
||||
// Remove before 2027.1.0
|
||||
ESPDEPRECATED("Pass collect_headers as std::vector<std::string> instead of std::set. Removed in 2027.1.0.",
|
||||
"2026.7.0")
|
||||
std::shared_ptr<HttpContainer> start(const std::string &url, const std::string &method, const std::string &body,
|
||||
const std::list<Header> &request_headers,
|
||||
const std::vector<Header> &request_headers,
|
||||
const std::set<std::string> &collect_headers) {
|
||||
std::vector<std::string> lower;
|
||||
lower.reserve(collect_headers.size());
|
||||
@@ -371,15 +405,39 @@ class HttpRequestComponent : public Component {
|
||||
return this->perform(url, method, body, request_headers, lower);
|
||||
}
|
||||
|
||||
// Remove before 2027.1.0
|
||||
ESPDEPRECATED("Pass request_headers as std::vector<Header> instead of std::list, and collect_headers as "
|
||||
"std::vector<std::string> instead of std::set. Removed in 2027.1.0.",
|
||||
"2026.7.0")
|
||||
std::shared_ptr<HttpContainer> start(const std::string &url, const std::string &method, const std::string &body,
|
||||
const std::list<Header> &request_headers,
|
||||
const std::set<std::string> &collect_headers) {
|
||||
std::vector<std::string> lower;
|
||||
lower.reserve(collect_headers.size());
|
||||
for (const auto &h : collect_headers) {
|
||||
lower.push_back(str_lower_case(h));
|
||||
}
|
||||
return this->perform(url, method, body, std::vector<Header>(request_headers.begin(), request_headers.end()), lower);
|
||||
}
|
||||
|
||||
// Remove before 2027.1.0
|
||||
ESPDEPRECATED("Pass request_headers as std::vector<Header> instead of std::list. Removed in 2027.1.0.", "2026.7.0")
|
||||
std::shared_ptr<HttpContainer> start(const std::string &url, const std::string &method, const std::string &body,
|
||||
const std::list<Header> &request_headers,
|
||||
const std::vector<std::string> &lower_case_collect_headers) {
|
||||
return this->perform(url, method, body, std::vector<Header>(request_headers.begin(), request_headers.end()),
|
||||
lower_case_collect_headers);
|
||||
}
|
||||
|
||||
std::shared_ptr<HttpContainer> start(const std::string &url, const std::string &method, const std::string &body,
|
||||
const std::vector<Header> &request_headers,
|
||||
const std::vector<std::string> &lower_case_collect_headers) {
|
||||
return this->perform(url, method, body, request_headers, lower_case_collect_headers);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual std::shared_ptr<HttpContainer> perform(const std::string &url, const std::string &method,
|
||||
const std::string &body, const std::list<Header> &request_headers,
|
||||
const std::string &body, const std::vector<Header> &request_headers,
|
||||
const std::vector<std::string> &lower_case_collect_headers) = 0;
|
||||
const char *useragent_{nullptr};
|
||||
bool follow_redirects_{};
|
||||
@@ -436,13 +494,10 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> {
|
||||
auto f = std::bind(&HttpRequestSendAction<Ts...>::encode_json_func_, this, x..., std::placeholders::_1);
|
||||
body = json::build_json(f);
|
||||
}
|
||||
std::list<Header> request_headers;
|
||||
for (const auto &item : this->request_headers_) {
|
||||
auto val = item.second;
|
||||
Header header;
|
||||
header.name = item.first;
|
||||
header.value = val.value(x...);
|
||||
request_headers.push_back(header);
|
||||
std::vector<Header> request_headers;
|
||||
request_headers.reserve(this->request_headers_.size());
|
||||
for (const auto &[key, val] : this->request_headers_) {
|
||||
request_headers.push_back({key, val.value(x...)});
|
||||
}
|
||||
|
||||
auto container = this->parent_->start(this->url_.value(x...), this->method_.value(x...), body, request_headers,
|
||||
|
||||
@@ -26,7 +26,7 @@ static constexpr int ESP8266_SSL_ERR_OOM = -1000;
|
||||
|
||||
std::shared_ptr<HttpContainer> HttpRequestArduino::perform(const std::string &url, const std::string &method,
|
||||
const std::string &body,
|
||||
const std::list<Header> &request_headers,
|
||||
const std::vector<Header> &request_headers,
|
||||
const std::vector<std::string> &lower_case_collect_headers) {
|
||||
if (!network::is_connected()) {
|
||||
this->status_momentary_error("failed", 1000);
|
||||
|
||||
@@ -49,7 +49,7 @@ class HttpContainerArduino : public HttpContainer {
|
||||
class HttpRequestArduino : public HttpRequestComponent {
|
||||
protected:
|
||||
std::shared_ptr<HttpContainer> perform(const std::string &url, const std::string &method, const std::string &body,
|
||||
const std::list<Header> &request_headers,
|
||||
const std::vector<Header> &request_headers,
|
||||
const std::vector<std::string> &lower_case_collect_headers) override;
|
||||
};
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ static const char *const TAG = "http_request.host";
|
||||
|
||||
std::shared_ptr<HttpContainer> HttpRequestHost::perform(const std::string &url, const std::string &method,
|
||||
const std::string &body,
|
||||
const std::list<Header> &request_headers,
|
||||
const std::vector<Header> &request_headers,
|
||||
const std::vector<std::string> &lower_case_collect_headers) {
|
||||
if (!network::is_connected()) {
|
||||
this->status_momentary_error("failed", 1000);
|
||||
|
||||
@@ -19,7 +19,7 @@ class HttpContainerHost : public HttpContainer {
|
||||
class HttpRequestHost : public HttpRequestComponent {
|
||||
public:
|
||||
std::shared_ptr<HttpContainer> perform(const std::string &url, const std::string &method, const std::string &body,
|
||||
const std::list<Header> &request_headers,
|
||||
const std::vector<Header> &request_headers,
|
||||
const std::vector<std::string> &lower_case_collect_headers) override;
|
||||
void set_ca_path(const char *ca_path) { this->ca_path_ = ca_path; }
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ esp_err_t HttpRequestIDF::http_event_handler(esp_http_client_event_t *evt) {
|
||||
|
||||
std::shared_ptr<HttpContainer> HttpRequestIDF::perform(const std::string &url, const std::string &method,
|
||||
const std::string &body,
|
||||
const std::list<Header> &request_headers,
|
||||
const std::vector<Header> &request_headers,
|
||||
const std::vector<std::string> &lower_case_collect_headers) {
|
||||
if (!network::is_connected()) {
|
||||
this->status_momentary_error("failed", 1000);
|
||||
|
||||
@@ -37,7 +37,7 @@ class HttpRequestIDF : public HttpRequestComponent {
|
||||
|
||||
protected:
|
||||
std::shared_ptr<HttpContainer> perform(const std::string &url, const std::string &method, const std::string &body,
|
||||
const std::list<Header> &request_headers,
|
||||
const std::vector<Header> &request_headers,
|
||||
const std::vector<std::string> &lower_case_collect_headers) override;
|
||||
// if zero ESP-IDF will use DEFAULT_HTTP_BUF_SIZE
|
||||
uint16_t buffer_size_rx_{};
|
||||
|
||||
@@ -105,8 +105,7 @@ uint8_t OtaHttpRequestComponent::do_ota_() {
|
||||
|
||||
// we will compute MD5 on the fly for verification -- Arduino OTA seems to ignore it
|
||||
md5_receive.init();
|
||||
ESP_LOGV(TAG, "MD5Digest initialized\n"
|
||||
"OTA backend begin");
|
||||
ESP_LOGV(TAG, "MD5Digest initialized, OTA backend begin");
|
||||
auto backend = ota::make_ota_backend();
|
||||
auto error_code = backend->begin(container->content_length);
|
||||
if (error_code != ota::OTA_RESPONSE_OK) {
|
||||
|
||||
@@ -362,10 +362,8 @@ bool INA2XX::configure_shunt_() {
|
||||
ESP_LOGW(TAG, "Shunt value too high");
|
||||
}
|
||||
this->shunt_cal_ &= 0x7FFF;
|
||||
ESP_LOGV(TAG,
|
||||
"Given Rshunt=%f Ohm and Max_current=%.3f\n"
|
||||
"New CURRENT_LSB=%f, SHUNT_CAL=%u",
|
||||
this->shunt_resistance_ohm_, this->max_current_a_, this->current_lsb_, this->shunt_cal_);
|
||||
ESP_LOGV(TAG, "Rshunt=%f Ohm, max current=%.3f A, current LSB=%f, shunt cal=%u", this->shunt_resistance_ohm_,
|
||||
this->max_current_a_, this->current_lsb_, this->shunt_cal_);
|
||||
return this->write_unsigned_16_(RegisterMap::REG_SHUNT_CAL, this->shunt_cal_);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <queue>
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#include "esphome/components/uart/uart.h"
|
||||
#include "esphome/core/component.h"
|
||||
|
||||
@@ -489,11 +489,8 @@ bool LD2410Component::handle_ack_data_() {
|
||||
this->out_pin_level_ = this->buffer_data_[12];
|
||||
const auto *light_function_str = find_str(LIGHT_FUNCTIONS_BY_UINT, this->light_function_);
|
||||
const auto *out_pin_level_str = find_str(OUT_PIN_LEVELS_BY_UINT, this->out_pin_level_);
|
||||
ESP_LOGV(TAG,
|
||||
"Light function: %s\n"
|
||||
"Light threshold: %u\n"
|
||||
"Out pin level: %s",
|
||||
light_function_str, this->light_threshold_, out_pin_level_str);
|
||||
ESP_LOGV(TAG, "Light function: %s, threshold: %u, out pin level: %s", light_function_str, this->light_threshold_,
|
||||
out_pin_level_str);
|
||||
#ifdef USE_SELECT
|
||||
if (this->light_function_select_ != nullptr) {
|
||||
this->light_function_select_->publish_state(light_function_str);
|
||||
|
||||
@@ -530,10 +530,7 @@ bool LD2412Component::handle_ack_data_() {
|
||||
this->light_function_ = this->buffer_data_[10];
|
||||
this->light_threshold_ = this->buffer_data_[11];
|
||||
const auto *light_function_str = find_str(LIGHT_FUNCTIONS_BY_UINT, this->light_function_);
|
||||
ESP_LOGV(TAG,
|
||||
"Light function: %s\n"
|
||||
"Light threshold: %u",
|
||||
light_function_str, this->light_threshold_);
|
||||
ESP_LOGV(TAG, "Light function: %s, threshold: %u", light_function_str, this->light_threshold_);
|
||||
#ifdef USE_SELECT
|
||||
if (this->light_function_select_ != nullptr) {
|
||||
this->light_function_select_->publish_state(light_function_str);
|
||||
|
||||
@@ -130,10 +130,8 @@ void LEDCOutput::setup() {
|
||||
}
|
||||
int hpoint = ledc_angle_to_htop(this->phase_angle_, this->bit_depth_);
|
||||
|
||||
ESP_LOGV(TAG,
|
||||
"Configured frequency %f with a bit depth of %u bits\n"
|
||||
"Angle of %.1f° results in hpoint %u",
|
||||
this->frequency_, this->bit_depth_, this->phase_angle_, hpoint);
|
||||
ESP_LOGV(TAG, "Configured frequency %f with bit depth %u, angle %.1f° hpoint %u", this->frequency_, this->bit_depth_,
|
||||
this->phase_angle_, hpoint);
|
||||
|
||||
ledc_channel_config_t chan_conf{};
|
||||
chan_conf.gpio_num = this->pin_->get_pin();
|
||||
|
||||
@@ -275,6 +275,146 @@ BASE_SCHEMA.add_extra(_detect_variant)
|
||||
BASE_SCHEMA.add_extra(_update_core_data)
|
||||
|
||||
|
||||
def _configure_lwip(config: dict) -> None:
|
||||
"""Configure lwIP options for LibreTiny platforms.
|
||||
|
||||
The BK/RTL/LN SDKs each ship different lwIP defaults. BK72XX defaults are
|
||||
wildly oversized for ESPHome's IoT use case, causing OOM on BK7231N.
|
||||
RTL87XX and LN882H have more conservative defaults but still need tuning
|
||||
for ESPHome's socket usage patterns.
|
||||
|
||||
See https://github.com/esphome/esphome/issues/14095
|
||||
|
||||
Comparison of SDK defaults vs ESPHome targets (TCP_MSS=1460 on all LT):
|
||||
|
||||
Setting ESP8266 ESP32 BK SDK RTL SDK LN SDK New
|
||||
────────────────────────────────────────────────────────────────────────────
|
||||
TCP_SND_BUF 2×MSS 4×MSS 10×MSS 5×MSS 7×MSS 4×MSS
|
||||
TCP_WND 4×MSS 4×MSS 3/10×MSS 2×MSS 3×MSS 4×MSS
|
||||
MEM_LIBC_MALLOC 1 1 0 0 1 1
|
||||
MEMP_MEM_MALLOC 1 1 0 0 0 1
|
||||
MEM_SIZE N/A* N/A* 16/32KB 5KB N/A* N/A* BK
|
||||
PBUF_POOL_SIZE 10 16 3/10 20 20 10 BK
|
||||
MAX_SOCKETS_TCP 5 16 12 —** —** dynamic
|
||||
MAX_SOCKETS_UDP 4 16 22 —** —** dynamic
|
||||
TCP_SND_QUEUELEN ~8 17 20 20 35 17
|
||||
MEMP_NUM_TCP_SEG 10 16 40 20 =qlen 17
|
||||
MEMP_NUM_TCP_PCB 5 16 12 10 8 =TCP
|
||||
MEMP_NUM_TCP_PCB_LISTEN 4 16 4 5 3 dynamic
|
||||
MEMP_NUM_UDP_PCB 4 16 25*** 7**** 7**** =UDP
|
||||
MEMP_NUM_NETCONN 0 10 38 4***** =sum =sum
|
||||
MEMP_NUM_NETBUF 0 2 16 2***** 8 4
|
||||
MEMP_NUM_TCPIP_MSG_INPKT 4 8 16 8***** 12 8
|
||||
|
||||
* ESP8266/ESP32/LN882H use MEM_LIBC_MALLOC=1 (system heap, no dedicated pool).
|
||||
ESP8266/ESP32 also use MEMP_MEM_MALLOC=1 (MEMP pools from heap, not static).
|
||||
** RTL/LN SDKs don't define MAX_SOCKETS_TCP/UDP (LibreTiny-specific).
|
||||
*** BK LT overlay: MAX_SOCKETS_UDP+2+1 = 25.
|
||||
**** RTL/LN LT overlay overrides to flat 7.
|
||||
***** Not defined in RTL SDK — lwIP opt.h defaults shown.
|
||||
"dynamic" = auto-calculated from component socket registrations via
|
||||
socket.get_socket_counts() with minimums of 8 TCP / 6 UDP.
|
||||
"""
|
||||
from esphome.components.socket import (
|
||||
MIN_TCP_LISTEN_SOCKETS,
|
||||
MIN_TCP_SOCKETS,
|
||||
MIN_UDP_SOCKETS,
|
||||
get_socket_counts,
|
||||
)
|
||||
|
||||
sc = get_socket_counts()
|
||||
# Apply platform minimums — ensure headroom for ESPHome's needs
|
||||
tcp_sockets = max(MIN_TCP_SOCKETS, sc.tcp)
|
||||
udp_sockets = max(MIN_UDP_SOCKETS, sc.udp)
|
||||
# Listening sockets — registered by components (api, ota, web_server_base, etc.)
|
||||
# Not all components register yet, so ensure a minimum for baseline operation.
|
||||
listening_tcp = max(MIN_TCP_LISTEN_SOCKETS, sc.tcp_listen)
|
||||
|
||||
# TCP_SND_BUF: ESPAsyncWebServer allocates malloc(tcp_sndbuf()) per
|
||||
# response chunk. At 10×MSS=14.6KB (BK default) this causes OOM (#14095).
|
||||
# 4×MSS=5,840 matches ESP32. RTL(5×) and LN(7×) are close already.
|
||||
tcp_snd_buf = "(4*TCP_MSS)" # BK: 10×MSS, RTL: 5×MSS, LN: 7×MSS
|
||||
|
||||
# TCP_WND: receive window. 4×MSS matches ESP32.
|
||||
# RTL SDK uses only 2×MSS; increasing to 4× is safe and improves throughput.
|
||||
tcp_wnd = "(4*TCP_MSS)" # BK: 10×MSS, RTL: 2×MSS, LN: 3×MSS
|
||||
|
||||
# TCP_SND_QUEUELEN: max pbufs queued for send buffer
|
||||
# ESP-IDF formula: (4 * TCP_SND_BUF + (TCP_MSS - 1)) / TCP_MSS
|
||||
# With 4×MSS: (4*5840 + 1459) / 1460 = 17 — match ESP32
|
||||
tcp_snd_queuelen = 17 # BK: 20, RTL: 20, LN: 35
|
||||
# MEMP_NUM_TCP_SEG: segment pool, must be >= TCP_SND_QUEUELEN (lwIP sanity check)
|
||||
memp_num_tcp_seg = tcp_snd_queuelen # BK: 40, RTL: 20, LN: =qlen
|
||||
|
||||
lwip_opts: list[str] = [
|
||||
# Disable statistics — not needed for production, saves RAM
|
||||
"LWIP_STATS=0", # BK: 1, RTL: 0 already, LN: 0 already
|
||||
"MEM_STATS=0",
|
||||
"MEMP_STATS=0",
|
||||
# TCP send buffer — 4×MSS matches ESP32
|
||||
f"TCP_SND_BUF={tcp_snd_buf}",
|
||||
# TCP receive window — 4×MSS matches ESP32
|
||||
f"TCP_WND={tcp_wnd}",
|
||||
# Socket counts — auto-calculated from component registrations
|
||||
f"MAX_SOCKETS_TCP={tcp_sockets}",
|
||||
f"MAX_SOCKETS_UDP={udp_sockets}",
|
||||
# Listening sockets — BK SDK uses this to derive MEMP_NUM_TCP_PCB_LISTEN;
|
||||
# RTL/LN don't use it, but we set MEMP_NUM_TCP_PCB_LISTEN explicitly below.
|
||||
f"MAX_LISTENING_SOCKETS_TCP={listening_tcp}",
|
||||
# Queued segment limits — derived from 4×MSS buffer size
|
||||
f"TCP_SND_QUEUELEN={tcp_snd_queuelen}",
|
||||
f"MEMP_NUM_TCP_SEG={memp_num_tcp_seg}", # must be >= queuelen
|
||||
# PCB pools — active connections + listening sockets
|
||||
f"MEMP_NUM_TCP_PCB={tcp_sockets}", # BK: 12, RTL: 10, LN: 8
|
||||
f"MEMP_NUM_TCP_PCB_LISTEN={listening_tcp}", # BK: =MAX_LISTENING, RTL: 5, LN: 3
|
||||
# UDP PCB pool — includes wifi.lwip_internal (DHCP + DNS)
|
||||
f"MEMP_NUM_UDP_PCB={udp_sockets}", # BK: 25, RTL/LN: 7 via LT
|
||||
# Netconn pool — each socket (active + listening) needs a netconn
|
||||
f"MEMP_NUM_NETCONN={tcp_sockets + udp_sockets + listening_tcp}",
|
||||
# Netbuf pool
|
||||
"MEMP_NUM_NETBUF=4", # BK: 16, RTL: 2 (opt.h), LN: 8
|
||||
# Inbound message pool
|
||||
"MEMP_NUM_TCPIP_MSG_INPKT=8", # BK: 16, RTL: 8 (opt.h), LN: 12
|
||||
]
|
||||
|
||||
# Use system heap for all lwIP allocations on all LibreTiny platforms.
|
||||
# - MEM_LIBC_MALLOC=1: Use system heap instead of dedicated lwIP heap.
|
||||
# LN882H already ships with this. BK SDK defaults to a 16/32KB dedicated
|
||||
# pool that fragments during OTA. RTL SDK defaults to a 5KB pool.
|
||||
# All three SDKs wire malloc → pvPortMalloc (FreeRTOS thread-safe heap).
|
||||
# - MEMP_MEM_MALLOC=1: Allocate MEMP pools from heap on demand instead
|
||||
# of static arrays. Saves ~20KB RAM on BK72XX. Safe because WiFi
|
||||
# receive paths run in task context, not ISR context. ESP32 and ESP8266
|
||||
# both ship with MEMP_MEM_MALLOC=1.
|
||||
lwip_opts.append("MEM_LIBC_MALLOC=1")
|
||||
lwip_opts.append("MEMP_MEM_MALLOC=1")
|
||||
|
||||
# BK72XX-specific: PBUF_POOL_SIZE override
|
||||
# BK SDK "reduced plan" sets this to only 3 — too few for multiple
|
||||
# concurrent connections (API + web_server + OTA). BK default plan
|
||||
# uses 10; match that. RTL(20) and LN(20) need no override.
|
||||
# With MEMP_MEM_MALLOC=1, this is a max count (allocated on demand).
|
||||
if CORE.is_bk72xx:
|
||||
lwip_opts.append("PBUF_POOL_SIZE=10")
|
||||
|
||||
tcp_min = " (min)" if tcp_sockets > sc.tcp else ""
|
||||
udp_min = " (min)" if udp_sockets > sc.udp else ""
|
||||
listen_min = " (min)" if listening_tcp > sc.tcp_listen else ""
|
||||
_LOGGER.info(
|
||||
"Configuring lwIP: TCP=%d%s [%s], UDP=%d%s [%s], TCP_LISTEN=%d%s [%s]",
|
||||
tcp_sockets,
|
||||
tcp_min,
|
||||
sc.tcp_details,
|
||||
udp_sockets,
|
||||
udp_min,
|
||||
sc.udp_details,
|
||||
listening_tcp,
|
||||
listen_min,
|
||||
sc.tcp_listen_details,
|
||||
)
|
||||
cg.add_platformio_option("custom_options.lwip", lwip_opts)
|
||||
|
||||
|
||||
# pylint: disable=use-dict-literal
|
||||
async def component_to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
@@ -389,11 +529,12 @@ async def component_to_code(config):
|
||||
"custom_options.sys_config#h", _BK7231N_SYS_CONFIG_OPTIONS
|
||||
)
|
||||
|
||||
# Disable LWIP statistics to save RAM - not needed in production
|
||||
# Must explicitly disable all sub-stats to avoid redefinition warnings
|
||||
cg.add_platformio_option(
|
||||
"custom_options.lwip",
|
||||
["LWIP_STATS=0", "MEM_STATS=0", "MEMP_STATS=0"],
|
||||
)
|
||||
# Tune lwIP for ESPHome's actual needs.
|
||||
# The SDK defaults (TCP_SND_BUF=10*MSS, MAX_SOCKETS_TCP=12, MEM_SIZE=32KB)
|
||||
# are wildly oversized for an IoT device. ESPAsyncWebServer allocates
|
||||
# malloc(tcp_sndbuf()) per response chunk — at 14.6KB this causes silent
|
||||
# OOM on memory-constrained chips like BK7231N.
|
||||
# See https://github.com/esphome/esphome/issues/14095
|
||||
_configure_lwip(config)
|
||||
|
||||
await cg.register_component(var, config)
|
||||
|
||||
@@ -329,10 +329,11 @@ async def to_code(config):
|
||||
level = config[CONF_LEVEL]
|
||||
CORE.data.setdefault(CONF_LOGGER, {})[CONF_LEVEL] = level
|
||||
initial_level = LOG_LEVELS[config.get(CONF_INITIAL_LEVEL, level)]
|
||||
tx_buffer_size = config[CONF_TX_BUFFER_SIZE]
|
||||
cg.add_define("ESPHOME_LOGGER_TX_BUFFER_SIZE", tx_buffer_size)
|
||||
log = cg.new_Pvariable(
|
||||
config[CONF_ID],
|
||||
baud_rate,
|
||||
config[CONF_TX_BUFFER_SIZE],
|
||||
)
|
||||
if CORE.is_esp32:
|
||||
cg.add(log.create_pthread_key())
|
||||
|
||||
@@ -75,18 +75,13 @@ struct LogBuffer {
|
||||
|
||||
*p++ = ':';
|
||||
|
||||
// Format line number without modulo operations
|
||||
// Format line number using subtraction loops (no division - important for ESP8266 which lacks hardware divider)
|
||||
if (line > 999) [[unlikely]] {
|
||||
int thousands = line / 1000;
|
||||
*p++ = '0' + thousands;
|
||||
line -= thousands * 1000;
|
||||
write_digit(p, line, 1000);
|
||||
}
|
||||
int hundreds = line / 100;
|
||||
int remainder = line - hundreds * 100;
|
||||
int tens = remainder / 10;
|
||||
*p++ = '0' + hundreds;
|
||||
*p++ = '0' + tens;
|
||||
*p++ = '0' + (remainder - tens * 10);
|
||||
write_digit(p, line, 100);
|
||||
write_digit(p, line, 10);
|
||||
*p++ = '0' + line;
|
||||
*p++ = ']';
|
||||
|
||||
#if defined(USE_ESP32) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR) || defined(USE_HOST)
|
||||
@@ -162,6 +157,15 @@ struct LogBuffer {
|
||||
this->process_vsnprintf_result_(vsnprintf_P(this->current_(), this->remaining_(), format, args));
|
||||
}
|
||||
#endif
|
||||
// Extract one decimal digit via subtraction (no division - important for ESP8266)
|
||||
static inline void ESPHOME_ALWAYS_INLINE write_digit(char *&p, int &value, int divisor) {
|
||||
char d = '0';
|
||||
while (value >= divisor) {
|
||||
d++;
|
||||
value -= divisor;
|
||||
}
|
||||
*p++ = d;
|
||||
}
|
||||
// Write ANSI color escape sequence to buffer, updates pointer in place
|
||||
// Caller is responsible for ensuring buffer has sufficient space
|
||||
void write_ansi_color_(char *&p, uint8_t level) {
|
||||
|
||||
@@ -152,10 +152,7 @@ inline uint8_t Logger::level_for(const char *tag) {
|
||||
return this->current_level_;
|
||||
}
|
||||
|
||||
Logger::Logger(uint32_t baud_rate, size_t tx_buffer_size) : baud_rate_(baud_rate), tx_buffer_size_(tx_buffer_size) {
|
||||
// add 1 to buffer size for null terminator
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - allocated once, never freed
|
||||
this->tx_buffer_ = new char[this->tx_buffer_size_ + 1];
|
||||
Logger::Logger(uint32_t baud_rate) : baud_rate_(baud_rate) {
|
||||
#if defined(USE_ESP32) || defined(USE_LIBRETINY)
|
||||
this->main_task_ = xTaskGetCurrentTaskHandle();
|
||||
#elif defined(USE_ZEPHYR)
|
||||
@@ -196,7 +193,7 @@ void Logger::process_messages_() {
|
||||
uint16_t text_length;
|
||||
while (this->log_buffer_->borrow_message_main_loop(message, text_length)) {
|
||||
const char *thread_name = message->thread_name[0] != '\0' ? message->thread_name : nullptr;
|
||||
LogBuffer buf{this->tx_buffer_, this->tx_buffer_size_};
|
||||
LogBuffer buf{this->tx_buffer_, ESPHOME_LOGGER_TX_BUFFER_SIZE};
|
||||
this->format_buffered_message_and_notify_(message->level, message->tag, message->line, thread_name,
|
||||
message->text_data(), text_length, buf);
|
||||
// Release the message to allow other tasks to use it as soon as possible
|
||||
|
||||
@@ -143,7 +143,7 @@ enum UARTSelection : uint8_t {
|
||||
*/
|
||||
class Logger : public Component {
|
||||
public:
|
||||
explicit Logger(uint32_t baud_rate, size_t tx_buffer_size);
|
||||
explicit Logger(uint32_t baud_rate);
|
||||
#ifdef USE_ESPHOME_TASK_LOG_BUFFER
|
||||
void init_log_buffer(size_t total_buffer_size);
|
||||
#endif
|
||||
@@ -281,7 +281,7 @@ class Logger : public Component {
|
||||
inline void HOT log_message_to_buffer_and_send_(bool &recursion_guard, uint8_t level, const char *tag, int line,
|
||||
FormatType format, va_list args, const char *thread_name) {
|
||||
RecursionGuard guard(recursion_guard);
|
||||
LogBuffer buf{this->tx_buffer_, this->tx_buffer_size_};
|
||||
LogBuffer buf{this->tx_buffer_, ESPHOME_LOGGER_TX_BUFFER_SIZE};
|
||||
#ifdef USE_STORE_LOG_STR_IN_FLASH
|
||||
if constexpr (std::is_same_v<FormatType, const __FlashStringHelper *>) {
|
||||
this->format_log_to_buffer_with_terminator_P_(level, tag, line, format, args, buf);
|
||||
@@ -312,7 +312,6 @@ class Logger : public Component {
|
||||
|
||||
// Group 4-byte aligned members first
|
||||
uint32_t baud_rate_;
|
||||
char *tx_buffer_{nullptr};
|
||||
#if defined(USE_ARDUINO) && !defined(USE_ESP32)
|
||||
Stream *hw_serial_{nullptr};
|
||||
#endif
|
||||
@@ -354,7 +353,6 @@ class Logger : public Component {
|
||||
#endif
|
||||
|
||||
// Group smaller types together at the end
|
||||
uint16_t tx_buffer_size_{0};
|
||||
uint8_t current_level_{ESPHOME_LOG_LEVEL_VERY_VERBOSE};
|
||||
#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_ZEPHYR)
|
||||
UARTSelection uart_{UART_SELECTION_UART0};
|
||||
@@ -371,6 +369,9 @@ class Logger : public Component {
|
||||
bool global_recursion_guard_{false}; // Simple global recursion guard for single-task platforms
|
||||
#endif
|
||||
|
||||
// Large buffer placed last to keep frequently-accessed member offsets small
|
||||
char tx_buffer_[ESPHOME_LOGGER_TX_BUFFER_SIZE + 1]; // +1 for null terminator
|
||||
|
||||
// --- get_thread_name_ overloads (per-platform) ---
|
||||
|
||||
#if defined(USE_ESP32) || defined(USE_LIBRETINY)
|
||||
|
||||
@@ -89,16 +89,16 @@ void Logger::pre_setup() {
|
||||
switch (this->uart_) {
|
||||
case UART_SELECTION_UART0:
|
||||
this->uart_num_ = UART_NUM_0;
|
||||
init_uart(this->uart_num_, baud_rate_, tx_buffer_size_);
|
||||
init_uart(this->uart_num_, baud_rate_, ESPHOME_LOGGER_TX_BUFFER_SIZE);
|
||||
break;
|
||||
case UART_SELECTION_UART1:
|
||||
this->uart_num_ = UART_NUM_1;
|
||||
init_uart(this->uart_num_, baud_rate_, tx_buffer_size_);
|
||||
init_uart(this->uart_num_, baud_rate_, ESPHOME_LOGGER_TX_BUFFER_SIZE);
|
||||
break;
|
||||
#ifdef USE_ESP32_VARIANT_ESP32
|
||||
case UART_SELECTION_UART2:
|
||||
this->uart_num_ = UART_NUM_2;
|
||||
init_uart(this->uart_num_, baud_rate_, tx_buffer_size_);
|
||||
init_uart(this->uart_num_, baud_rate_, ESPHOME_LOGGER_TX_BUFFER_SIZE);
|
||||
break;
|
||||
#endif
|
||||
#ifdef USE_LOGGER_USB_CDC
|
||||
|
||||
@@ -5,8 +5,8 @@ namespace esphome::logger {
|
||||
|
||||
void HOT Logger::write_msg_(const char *msg, uint16_t len) {
|
||||
static constexpr size_t TIMESTAMP_LEN = 10; // "[HH:MM:SS]"
|
||||
// tx_buffer_size_ defaults to 512, so 768 covers default + headroom
|
||||
char buffer[TIMESTAMP_LEN + 768];
|
||||
static constexpr size_t HEADROOM = 128; // Extra space for ANSI codes, newline, etc.
|
||||
char buffer[TIMESTAMP_LEN + ESPHOME_LOGGER_TX_BUFFER_SIZE + HEADROOM];
|
||||
|
||||
time_t rawtime;
|
||||
time(&rawtime);
|
||||
|
||||
@@ -146,11 +146,11 @@ void MAX6956::dump_config() {
|
||||
|
||||
if (brightness_mode_ == MAX6956CURRENTMODE::GLOBAL) {
|
||||
ESP_LOGCONFIG(TAG,
|
||||
"current mode: global\n"
|
||||
"global brightness: %u",
|
||||
" Current mode: global\n"
|
||||
" Brightness: %u",
|
||||
global_brightness_);
|
||||
} else {
|
||||
ESP_LOGCONFIG(TAG, "current mode: segment");
|
||||
ESP_LOGCONFIG(TAG, " Current mode: segment");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ def _consume_mdns_sockets(config: ConfigType) -> ConfigType:
|
||||
from esphome.components import socket
|
||||
|
||||
# mDNS needs 2 sockets (IPv4 + IPv6 multicast)
|
||||
socket.consume_sockets(2, "mdns")(config)
|
||||
socket.consume_sockets(2, "mdns", socket.SocketType.UDP)(config)
|
||||
return config
|
||||
|
||||
|
||||
|
||||
@@ -165,10 +165,7 @@ void MQTTBackendESP32::mqtt_event_handler_(const Event &event) {
|
||||
case MQTT_EVENT_ERROR:
|
||||
ESP_LOGE(TAG, "MQTT_EVENT_ERROR");
|
||||
if (event.error_handle.error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
|
||||
ESP_LOGE(TAG,
|
||||
"Last error code reported from esp-tls: 0x%x\n"
|
||||
"Last tls stack error number: 0x%x\n"
|
||||
"Last captured errno : %d (%s)",
|
||||
ESP_LOGE(TAG, "Last esp-tls error: 0x%x, tls stack error: 0x%x, socket errno: %d (%s)",
|
||||
event.error_handle.esp_tls_last_esp_err, event.error_handle.esp_tls_stack_err,
|
||||
event.error_handle.esp_transport_sock_errno, strerror(event.error_handle.esp_transport_sock_errno));
|
||||
} else if (event.error_handle.error_type == MQTT_ERROR_TYPE_CONNECTION_REFUSED) {
|
||||
|
||||
@@ -61,7 +61,9 @@ struct IPAddress {
|
||||
IPAddress(const std::string &in_address) { inet_aton(in_address.c_str(), &ip_addr_); }
|
||||
IPAddress(const ip_addr_t *other_ip) { ip_addr_ = *other_ip; }
|
||||
// Remove before 2026.8.0
|
||||
ESPDEPRECATED("Use str_to() instead. Removed in 2026.8.0", "2026.2.0")
|
||||
ESPDEPRECATED(
|
||||
"str() is deprecated: use 'char buf[IP_ADDRESS_BUFFER_SIZE]; ip.str_to(buf);' instead. Removed in 2026.8.0",
|
||||
"2026.2.0")
|
||||
std::string str() const {
|
||||
char buf[IP_ADDRESS_BUFFER_SIZE];
|
||||
this->str_to(buf);
|
||||
@@ -150,7 +152,9 @@ struct IPAddress {
|
||||
bool is_ip6() const { return IP_IS_V6(&ip_addr_); }
|
||||
bool is_multicast() const { return ip_addr_ismulticast(&ip_addr_); }
|
||||
// Remove before 2026.8.0
|
||||
ESPDEPRECATED("Use str_to() instead. Removed in 2026.8.0", "2026.2.0")
|
||||
ESPDEPRECATED(
|
||||
"str() is deprecated: use 'char buf[IP_ADDRESS_BUFFER_SIZE]; ip.str_to(buf);' instead. Removed in 2026.8.0",
|
||||
"2026.2.0")
|
||||
std::string str() const {
|
||||
char buf[IP_ADDRESS_BUFFER_SIZE];
|
||||
this->str_to(buf);
|
||||
|
||||
@@ -25,11 +25,7 @@ int Nextion::upload_by_chunks_(HTTPClient &http_client, uint32_t &range_start) {
|
||||
uint32_t range_end = ((upload_first_chunk_sent_ or this->tft_size_ < 4096) ? this->tft_size_ : 4096) - 1;
|
||||
ESP_LOGD(TAG, "Range start: %" PRIu32, range_start);
|
||||
if (range_size <= 0 or range_end <= range_start) {
|
||||
ESP_LOGE(TAG, "Invalid range");
|
||||
ESP_LOGD(TAG,
|
||||
"Range end: %" PRIu32 "\n"
|
||||
"Range size: %" PRIu32,
|
||||
range_end, range_size);
|
||||
ESP_LOGE(TAG, "Invalid range end: %" PRIu32 ", size: %" PRIu32, range_end, range_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -138,11 +134,7 @@ int Nextion::upload_by_chunks_(HTTPClient &http_client, uint32_t &range_start) {
|
||||
}
|
||||
|
||||
bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
||||
ESP_LOGD(TAG,
|
||||
"TFT upload requested\n"
|
||||
"Exit reparse: %s\n"
|
||||
"URL: %s",
|
||||
YESNO(exit_reparse), this->tft_url_.c_str());
|
||||
ESP_LOGD(TAG, "TFT upload requested, exit reparse: %s, URL: %s", YESNO(exit_reparse), this->tft_url_.c_str());
|
||||
|
||||
if (this->connection_state_.is_updating_) {
|
||||
ESP_LOGW(TAG, "Upload in progress");
|
||||
@@ -172,10 +164,7 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
||||
ESP_LOGD(TAG, "Baud rate: %" PRIu32, baud_rate);
|
||||
|
||||
// Define the configuration for the HTTP client
|
||||
ESP_LOGV(TAG,
|
||||
"Init HTTP client\n"
|
||||
"Heap: %" PRIu32,
|
||||
EspClass::getFreeHeap());
|
||||
ESP_LOGV(TAG, "Init HTTP client, heap: %" PRIu32, EspClass::getFreeHeap());
|
||||
HTTPClient http_client;
|
||||
http_client.setTimeout(15000); // Yes 15 seconds.... Helps 8266s along
|
||||
|
||||
@@ -262,10 +251,7 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
||||
this->reset_(false);
|
||||
delay(250); // NOLINT
|
||||
|
||||
ESP_LOGV(TAG,
|
||||
"Heap: %" PRIu32 "\n"
|
||||
"Upload cmd: %s",
|
||||
EspClass::getFreeHeap(), command);
|
||||
ESP_LOGV(TAG, "Heap: %" PRIu32 ", upload cmd: %s", EspClass::getFreeHeap(), command);
|
||||
this->send_command_(command);
|
||||
|
||||
if (baud_rate != this->original_baud_rate_) {
|
||||
|
||||
@@ -27,11 +27,7 @@ int Nextion::upload_by_chunks_(esp_http_client_handle_t http_client, uint32_t &r
|
||||
uint32_t range_end = ((upload_first_chunk_sent_ or this->tft_size_ < 4096) ? this->tft_size_ : 4096) - 1;
|
||||
ESP_LOGD(TAG, "Range start: %" PRIu32, range_start);
|
||||
if (range_size <= 0 or range_end <= range_start) {
|
||||
ESP_LOGD(TAG,
|
||||
"Range end: %" PRIu32 "\n"
|
||||
"Range size: %" PRIu32,
|
||||
range_end, range_size);
|
||||
ESP_LOGE(TAG, "Invalid range");
|
||||
ESP_LOGE(TAG, "Invalid range end: %" PRIu32 ", size: %" PRIu32, range_end, range_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -159,11 +155,7 @@ int Nextion::upload_by_chunks_(esp_http_client_handle_t http_client, uint32_t &r
|
||||
}
|
||||
|
||||
bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
||||
ESP_LOGD(TAG,
|
||||
"TFT upload requested\n"
|
||||
"Exit reparse: %s\n"
|
||||
"URL: %s",
|
||||
YESNO(exit_reparse), this->tft_url_.c_str());
|
||||
ESP_LOGD(TAG, "TFT upload requested, exit reparse: %s, URL: %s", YESNO(exit_reparse), this->tft_url_.c_str());
|
||||
|
||||
if (this->connection_state_.is_updating_) {
|
||||
ESP_LOGW(TAG, "Upload in progress");
|
||||
@@ -193,10 +185,7 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
||||
ESP_LOGD(TAG, "Baud rate: %" PRIu32, baud_rate);
|
||||
|
||||
// Define the configuration for the HTTP client
|
||||
ESP_LOGV(TAG,
|
||||
"Init HTTP client\n"
|
||||
"Heap: %" PRIu32,
|
||||
esp_get_free_heap_size());
|
||||
ESP_LOGV(TAG, "Init HTTP client, heap: %" PRIu32, esp_get_free_heap_size());
|
||||
esp_http_client_config_t config = {
|
||||
.url = this->tft_url_.c_str(),
|
||||
.cert_pem = nullptr,
|
||||
@@ -220,10 +209,7 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
||||
}
|
||||
|
||||
// Perform the HTTP request
|
||||
ESP_LOGV(TAG,
|
||||
"Check connection\n"
|
||||
"Heap: %" PRIu32,
|
||||
esp_get_free_heap_size());
|
||||
ESP_LOGV(TAG, "Check connection, heap: %" PRIu32, esp_get_free_heap_size());
|
||||
err = esp_http_client_perform(http_client);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "HTTP failed: %s", esp_err_to_name(err));
|
||||
@@ -232,10 +218,7 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
||||
}
|
||||
|
||||
// Check the HTTP Status Code
|
||||
ESP_LOGV(TAG,
|
||||
"Check status\n"
|
||||
"Heap: %" PRIu32,
|
||||
esp_get_free_heap_size());
|
||||
ESP_LOGV(TAG, "Check status, heap: %" PRIu32, esp_get_free_heap_size());
|
||||
int status_code = esp_http_client_get_status_code(http_client);
|
||||
if (status_code != 200 && status_code != 206) {
|
||||
ESP_LOGE(TAG, "HTTP request failed with status %d", status_code);
|
||||
@@ -344,8 +327,7 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
||||
ESP_LOGV(TAG, "Heap: %" PRIu32 " left: %" PRIu32, esp_get_free_heap_size(), this->content_length_);
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "TFT upload complete\n"
|
||||
"Close HTTP");
|
||||
ESP_LOGD(TAG, "TFT upload complete, closing HTTP");
|
||||
esp_http_client_close(http_client);
|
||||
esp_http_client_cleanup(http_client);
|
||||
ESP_LOGV(TAG, "Connection closed");
|
||||
|
||||
@@ -49,7 +49,7 @@ void OnlineImage::update() {
|
||||
|
||||
ESP_LOGD(TAG, "Updating image from %s", this->url_.c_str());
|
||||
|
||||
std::list<http_request::Header> headers;
|
||||
std::vector<http_request::Header> headers;
|
||||
|
||||
// Add caching headers if we have them
|
||||
if (!this->etag_.empty()) {
|
||||
|
||||
@@ -35,9 +35,9 @@ void OpenThreadComponent::dump_config() {
|
||||
#elif CONFIG_OPENTHREAD_MTD
|
||||
ESP_LOGCONFIG(TAG, " Device Type: MTD");
|
||||
// TBD: Synchronized Sleepy End Device
|
||||
if (this->poll_period > 0) {
|
||||
if (this->poll_period_ > 0) {
|
||||
ESP_LOGCONFIG(TAG, " Device is configured as Sleepy End Device (SED)");
|
||||
uint32_t duration = this->poll_period / 1000;
|
||||
uint32_t duration = this->poll_period_ / 1000;
|
||||
ESP_LOGCONFIG(TAG, " Poll Period: %" PRIu32 "s", duration);
|
||||
} else {
|
||||
ESP_LOGCONFIG(TAG, " Device is configured as Minimal End Device (MED)");
|
||||
|
||||
@@ -36,22 +36,22 @@ class OpenThreadComponent : public Component {
|
||||
const char *get_use_address() const;
|
||||
void set_use_address(const char *use_address);
|
||||
#if CONFIG_OPENTHREAD_MTD
|
||||
void set_poll_period(uint32_t poll_period) { this->poll_period = poll_period; }
|
||||
void set_poll_period(uint32_t poll_period) { this->poll_period_ = poll_period; }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
std::optional<otIp6Address> get_omr_address_(InstanceLock &lock);
|
||||
std::function<void()> factory_reset_external_callback_;
|
||||
#if CONFIG_OPENTHREAD_MTD
|
||||
uint32_t poll_period_{0};
|
||||
#endif
|
||||
bool teardown_started_{false};
|
||||
bool teardown_complete_{false};
|
||||
std::function<void()> factory_reset_external_callback_;
|
||||
|
||||
private:
|
||||
// Stores a pointer to a string literal (static storage duration).
|
||||
// ONLY set from Python-generated code with string literals - never dynamic strings.
|
||||
const char *use_address_{""};
|
||||
#if CONFIG_OPENTHREAD_MTD
|
||||
uint32_t poll_period{0};
|
||||
#endif
|
||||
};
|
||||
|
||||
extern OpenThreadComponent *global_openthread_component; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
@@ -81,9 +81,11 @@ void OpenThreadComponent::ot_main() {
|
||||
// Initialize the OpenThread stack
|
||||
// otLoggingSetLevel(OT_LOG_LEVEL_DEBG);
|
||||
ESP_ERROR_CHECK(esp_openthread_init(&config));
|
||||
// Fetch OT instance once to avoid repeated call into OT stack
|
||||
otInstance *instance = esp_openthread_get_instance();
|
||||
|
||||
#if CONFIG_OPENTHREAD_STATE_INDICATOR_ENABLE
|
||||
ESP_ERROR_CHECK(esp_openthread_state_indicator_init(esp_openthread_get_instance()));
|
||||
ESP_ERROR_CHECK(esp_openthread_state_indicator_init(instance));
|
||||
#endif
|
||||
|
||||
#if CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC
|
||||
@@ -104,34 +106,34 @@ void OpenThreadComponent::ot_main() {
|
||||
esp_cli_custom_command_init();
|
||||
#endif // CONFIG_OPENTHREAD_CLI_ESP_EXTENSION
|
||||
|
||||
ESP_LOGD(TAG, "Thread Version: %" PRIu16, otThreadGetVersion());
|
||||
|
||||
otLinkModeConfig link_mode_config{};
|
||||
#if CONFIG_OPENTHREAD_FTD
|
||||
link_mode_config.mRxOnWhenIdle = true;
|
||||
link_mode_config.mDeviceType = true;
|
||||
link_mode_config.mNetworkData = true;
|
||||
#elif CONFIG_OPENTHREAD_MTD
|
||||
if (this->poll_period > 0) {
|
||||
if (otLinkSetPollPeriod(esp_openthread_get_instance(), this->poll_period) != OT_ERROR_NONE) {
|
||||
ESP_LOGE(TAG, "Failed to set OpenThread pollperiod.");
|
||||
if (this->poll_period_ > 0) {
|
||||
if (otLinkSetPollPeriod(instance, this->poll_period_) != OT_ERROR_NONE) {
|
||||
ESP_LOGE(TAG, "Failed to set pollperiod");
|
||||
}
|
||||
uint32_t link_polling_period = otLinkGetPollPeriod(esp_openthread_get_instance());
|
||||
ESP_LOGD(TAG, "Link Polling Period: %" PRIu32, link_polling_period);
|
||||
ESP_LOGD(TAG, "Link Polling Period: %" PRIu32, otLinkGetPollPeriod(instance));
|
||||
}
|
||||
link_mode_config.mRxOnWhenIdle = this->poll_period == 0;
|
||||
link_mode_config.mRxOnWhenIdle = this->poll_period_ == 0;
|
||||
link_mode_config.mDeviceType = false;
|
||||
link_mode_config.mNetworkData = false;
|
||||
#endif
|
||||
|
||||
if (otThreadSetLinkMode(esp_openthread_get_instance(), link_mode_config) != OT_ERROR_NONE) {
|
||||
ESP_LOGE(TAG, "Failed to set OpenThread linkmode.");
|
||||
if (otThreadSetLinkMode(instance, link_mode_config) != OT_ERROR_NONE) {
|
||||
ESP_LOGE(TAG, "Failed to set linkmode");
|
||||
}
|
||||
link_mode_config = otThreadGetLinkMode(esp_openthread_get_instance());
|
||||
ESP_LOGD(TAG,
|
||||
"Link Mode Device Type: %s\n"
|
||||
"Link Mode Network Data: %s\n"
|
||||
"Link Mode RX On When Idle: %s",
|
||||
link_mode_config.mDeviceType ? "true" : "false", link_mode_config.mNetworkData ? "true" : "false",
|
||||
link_mode_config.mRxOnWhenIdle ? "true" : "false");
|
||||
#ifdef ESPHOME_LOG_HAS_DEBUG // Fetch link mode from OT only when DEBUG
|
||||
link_mode_config = otThreadGetLinkMode(instance);
|
||||
ESP_LOGD(TAG, "Link Mode Device Type: %s, Network Data: %s, RX On When Idle: %s",
|
||||
TRUEFALSE(link_mode_config.mDeviceType), TRUEFALSE(link_mode_config.mNetworkData),
|
||||
TRUEFALSE(link_mode_config.mRxOnWhenIdle));
|
||||
#endif
|
||||
|
||||
// Run the main loop
|
||||
#if CONFIG_OPENTHREAD_CLI
|
||||
@@ -142,13 +144,12 @@ void OpenThreadComponent::ot_main() {
|
||||
|
||||
#ifndef USE_OPENTHREAD_FORCE_DATASET
|
||||
// Check if openthread has a valid dataset from a previous execution
|
||||
otError error = otDatasetGetActiveTlvs(esp_openthread_get_instance(), &dataset);
|
||||
otError error = otDatasetGetActiveTlvs(instance, &dataset);
|
||||
if (error != OT_ERROR_NONE) {
|
||||
// Make sure the length is 0 so we fallback to the configuration
|
||||
dataset.mLength = 0;
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Found OpenThread-managed dataset, ignoring esphome configuration\n"
|
||||
"(set force_dataset: true to override)");
|
||||
ESP_LOGI(TAG, "Found existing dataset, ignoring config (force_dataset: true to override)");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ class OpenThreadInstancePollingComponent : public PollingComponent {
|
||||
virtual void update_instance(otInstance *instance) = 0;
|
||||
};
|
||||
|
||||
class IPAddressOpenThreadInfo : public PollingComponent, public text_sensor::TextSensor {
|
||||
class IPAddressOpenThreadInfo final : public PollingComponent, public text_sensor::TextSensor {
|
||||
public:
|
||||
void update() override {
|
||||
std::optional<otIp6Address> address = openthread::global_openthread_component->get_omr_address();
|
||||
@@ -48,7 +48,7 @@ class IPAddressOpenThreadInfo : public PollingComponent, public text_sensor::Tex
|
||||
std::string last_ip_;
|
||||
};
|
||||
|
||||
class RoleOpenThreadInfo : public OpenThreadInstancePollingComponent, public text_sensor::TextSensor {
|
||||
class RoleOpenThreadInfo final : public OpenThreadInstancePollingComponent, public text_sensor::TextSensor {
|
||||
public:
|
||||
void update_instance(otInstance *instance) override {
|
||||
otDeviceRole role = otThreadGetDeviceRole(instance);
|
||||
@@ -64,7 +64,7 @@ class RoleOpenThreadInfo : public OpenThreadInstancePollingComponent, public tex
|
||||
otDeviceRole last_role_;
|
||||
};
|
||||
|
||||
class Rloc16OpenThreadInfo : public OpenThreadInstancePollingComponent, public text_sensor::TextSensor {
|
||||
class Rloc16OpenThreadInfo final : public OpenThreadInstancePollingComponent, public text_sensor::TextSensor {
|
||||
public:
|
||||
void update_instance(otInstance *instance) override {
|
||||
uint16_t rloc16 = otThreadGetRloc16(instance);
|
||||
@@ -75,14 +75,13 @@ class Rloc16OpenThreadInfo : public OpenThreadInstancePollingComponent, public t
|
||||
this->publish_state(buf);
|
||||
}
|
||||
}
|
||||
float get_setup_priority() const override { return setup_priority::AFTER_WIFI; }
|
||||
void dump_config() override;
|
||||
|
||||
protected:
|
||||
uint16_t last_rloc16_;
|
||||
};
|
||||
|
||||
class ExtAddrOpenThreadInfo : public OpenThreadInstancePollingComponent, public text_sensor::TextSensor {
|
||||
class ExtAddrOpenThreadInfo final : public OpenThreadInstancePollingComponent, public text_sensor::TextSensor {
|
||||
public:
|
||||
void update_instance(otInstance *instance) override {
|
||||
const auto *extaddr = otLinkGetExtendedAddress(instance);
|
||||
@@ -93,14 +92,13 @@ class ExtAddrOpenThreadInfo : public OpenThreadInstancePollingComponent, public
|
||||
this->publish_state(buf);
|
||||
}
|
||||
}
|
||||
float get_setup_priority() const override { return setup_priority::AFTER_WIFI; }
|
||||
void dump_config() override;
|
||||
|
||||
protected:
|
||||
std::array<uint8_t, 8> last_extaddr_{};
|
||||
};
|
||||
|
||||
class Eui64OpenThreadInfo : public OpenThreadInstancePollingComponent, public text_sensor::TextSensor {
|
||||
class Eui64OpenThreadInfo final : public OpenThreadInstancePollingComponent, public text_sensor::TextSensor {
|
||||
public:
|
||||
void update_instance(otInstance *instance) override {
|
||||
otExtAddress addr;
|
||||
@@ -113,14 +111,13 @@ class Eui64OpenThreadInfo : public OpenThreadInstancePollingComponent, public te
|
||||
this->publish_state(buf);
|
||||
}
|
||||
}
|
||||
float get_setup_priority() const override { return setup_priority::AFTER_WIFI; }
|
||||
void dump_config() override;
|
||||
|
||||
protected:
|
||||
std::array<uint8_t, 8> last_eui64_{};
|
||||
};
|
||||
|
||||
class ChannelOpenThreadInfo : public OpenThreadInstancePollingComponent, public text_sensor::TextSensor {
|
||||
class ChannelOpenThreadInfo final : public OpenThreadInstancePollingComponent, public text_sensor::TextSensor {
|
||||
public:
|
||||
void update_instance(otInstance *instance) override {
|
||||
uint8_t channel = otLinkGetChannel(instance);
|
||||
@@ -131,7 +128,6 @@ class ChannelOpenThreadInfo : public OpenThreadInstancePollingComponent, public
|
||||
this->publish_state(buf);
|
||||
}
|
||||
}
|
||||
float get_setup_priority() const override { return setup_priority::AFTER_WIFI; }
|
||||
void dump_config() override;
|
||||
|
||||
protected:
|
||||
@@ -153,7 +149,7 @@ class DatasetOpenThreadInfo : public OpenThreadInstancePollingComponent {
|
||||
virtual void update_dataset(otOperationalDataset *dataset) = 0;
|
||||
};
|
||||
|
||||
class NetworkNameOpenThreadInfo : public DatasetOpenThreadInfo, public text_sensor::TextSensor {
|
||||
class NetworkNameOpenThreadInfo final : public DatasetOpenThreadInfo, public text_sensor::TextSensor {
|
||||
public:
|
||||
void update_dataset(otOperationalDataset *dataset) override {
|
||||
if (this->last_network_name_ != dataset->mNetworkName.m8) {
|
||||
@@ -161,14 +157,13 @@ class NetworkNameOpenThreadInfo : public DatasetOpenThreadInfo, public text_sens
|
||||
this->publish_state(this->last_network_name_);
|
||||
}
|
||||
}
|
||||
float get_setup_priority() const override { return setup_priority::AFTER_WIFI; }
|
||||
void dump_config() override;
|
||||
|
||||
protected:
|
||||
std::string last_network_name_;
|
||||
};
|
||||
|
||||
class NetworkKeyOpenThreadInfo : public DatasetOpenThreadInfo, public text_sensor::TextSensor {
|
||||
class NetworkKeyOpenThreadInfo final : public DatasetOpenThreadInfo, public text_sensor::TextSensor {
|
||||
public:
|
||||
void update_dataset(otOperationalDataset *dataset) override {
|
||||
if (!std::equal(this->last_key_.begin(), this->last_key_.end(), dataset->mNetworkKey.m8)) {
|
||||
@@ -178,14 +173,13 @@ class NetworkKeyOpenThreadInfo : public DatasetOpenThreadInfo, public text_senso
|
||||
this->publish_state(buf);
|
||||
}
|
||||
}
|
||||
float get_setup_priority() const override { return setup_priority::AFTER_WIFI; }
|
||||
void dump_config() override;
|
||||
|
||||
protected:
|
||||
std::array<uint8_t, 16> last_key_{};
|
||||
};
|
||||
|
||||
class PanIdOpenThreadInfo : public DatasetOpenThreadInfo, public text_sensor::TextSensor {
|
||||
class PanIdOpenThreadInfo final : public DatasetOpenThreadInfo, public text_sensor::TextSensor {
|
||||
public:
|
||||
void update_dataset(otOperationalDataset *dataset) override {
|
||||
uint16_t panid = dataset->mPanId;
|
||||
@@ -196,14 +190,13 @@ class PanIdOpenThreadInfo : public DatasetOpenThreadInfo, public text_sensor::Te
|
||||
this->publish_state(buf);
|
||||
}
|
||||
}
|
||||
float get_setup_priority() const override { return setup_priority::AFTER_WIFI; }
|
||||
void dump_config() override;
|
||||
|
||||
protected:
|
||||
uint16_t last_panid_;
|
||||
};
|
||||
|
||||
class ExtPanIdOpenThreadInfo : public DatasetOpenThreadInfo, public text_sensor::TextSensor {
|
||||
class ExtPanIdOpenThreadInfo final : public DatasetOpenThreadInfo, public text_sensor::TextSensor {
|
||||
public:
|
||||
void update_dataset(otOperationalDataset *dataset) override {
|
||||
if (!std::equal(this->last_extpanid_.begin(), this->last_extpanid_.end(), dataset->mExtendedPanId.m8)) {
|
||||
@@ -214,7 +207,6 @@ class ExtPanIdOpenThreadInfo : public DatasetOpenThreadInfo, public text_sensor:
|
||||
}
|
||||
}
|
||||
|
||||
float get_setup_priority() const override { return setup_priority::AFTER_WIFI; }
|
||||
void dump_config() override;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -122,8 +122,10 @@ bool PCA9554Component::write_register_(uint8_t reg, uint16_t value) {
|
||||
|
||||
float PCA9554Component::get_setup_priority() const { return setup_priority::IO; }
|
||||
|
||||
#ifdef USE_LOOP_PRIORITY
|
||||
// Run our loop() method early to invalidate cache before any other components access the pins
|
||||
float PCA9554Component::get_loop_priority() const { return 9.0f; } // Just after WIFI
|
||||
#endif
|
||||
|
||||
void PCA9554GPIOPin::setup() { pin_mode(flags_); }
|
||||
void PCA9554GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); }
|
||||
|
||||
@@ -23,7 +23,9 @@ class PCA9554Component : public Component,
|
||||
|
||||
float get_setup_priority() const override;
|
||||
|
||||
#ifdef USE_LOOP_PRIORITY
|
||||
float get_loop_priority() const override;
|
||||
#endif
|
||||
|
||||
void dump_config() override;
|
||||
|
||||
|
||||
@@ -99,8 +99,10 @@ bool PCF8574Component::write_gpio_() {
|
||||
}
|
||||
float PCF8574Component::get_setup_priority() const { return setup_priority::IO; }
|
||||
|
||||
#ifdef USE_LOOP_PRIORITY
|
||||
// Run our loop() method early to invalidate cache before any other components access the pins
|
||||
float PCF8574Component::get_loop_priority() const { return 9.0f; } // Just after WIFI
|
||||
#endif
|
||||
|
||||
void PCF8574GPIOPin::setup() { pin_mode(flags_); }
|
||||
void PCF8574GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); }
|
||||
|
||||
@@ -26,7 +26,9 @@ class PCF8574Component : public Component,
|
||||
void pin_mode(uint8_t pin, gpio::Flags flags);
|
||||
|
||||
float get_setup_priority() const override;
|
||||
#ifdef USE_LOOP_PRIORITY
|
||||
float get_loop_priority() const override;
|
||||
#endif
|
||||
|
||||
void dump_config() override;
|
||||
|
||||
|
||||
@@ -144,9 +144,10 @@ bool PI4IOE5V6408Component::write_gpio_modes_() {
|
||||
}
|
||||
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
|
||||
ESP_LOGV(TAG,
|
||||
"Wrote GPIO modes: 0b" BYTE_TO_BINARY_PATTERN "\n"
|
||||
"Wrote GPIO pullup/pulldown: 0b" BYTE_TO_BINARY_PATTERN "\n"
|
||||
"Wrote GPIO pull enable: 0b" BYTE_TO_BINARY_PATTERN,
|
||||
"Wrote GPIO config:\n"
|
||||
" modes: 0b" BYTE_TO_BINARY_PATTERN "\n"
|
||||
" pullup/pulldown: 0b" BYTE_TO_BINARY_PATTERN "\n"
|
||||
" pull enable: 0b" BYTE_TO_BINARY_PATTERN,
|
||||
BYTE_TO_BINARY(this->mode_mask_), BYTE_TO_BINARY(this->pull_up_down_mask_),
|
||||
BYTE_TO_BINARY(this->pull_enable_mask_));
|
||||
#endif
|
||||
|
||||
@@ -748,8 +748,7 @@ esphome::optional<bool> Pipsolar::get_bit_(std::string bits, uint8_t bit_pos) {
|
||||
}
|
||||
|
||||
void Pipsolar::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "Pipsolar:\n"
|
||||
"enabled polling commands:");
|
||||
ESP_LOGCONFIG(TAG, "Pipsolar enabled polling commands:");
|
||||
for (auto &enabled_polling_command : this->enabled_polling_commands_) {
|
||||
if (enabled_polling_command.length != 0) {
|
||||
ESP_LOGCONFIG(TAG, "%s", enabled_polling_command.command);
|
||||
|
||||
@@ -31,10 +31,7 @@ void PN532::setup() {
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
ESP_LOGD(TAG,
|
||||
"Found chip PN5%02X\n"
|
||||
"Firmware ver. %d.%d",
|
||||
version_data[0], version_data[1], version_data[2]);
|
||||
ESP_LOGD(TAG, "Found chip PN5%02X, Firmware v%d.%d", version_data[0], version_data[1], version_data[2]);
|
||||
|
||||
if (!this->write_command_({
|
||||
PN532_COMMAND_SAMCONFIGURATION,
|
||||
|
||||
@@ -243,9 +243,7 @@ uint8_t PN7150::reset_core_(const bool reset_config, const bool power) {
|
||||
return nfc::STATUS_FAILED;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG,
|
||||
"Configuration %s\n"
|
||||
"NCI version: %s",
|
||||
ESP_LOGD(TAG, "Configuration %s, NCI version: %s",
|
||||
rx.get_message()[nfc::NCI_PKT_PAYLOAD_OFFSET + 2] ? "reset" : "retained",
|
||||
rx.get_message()[nfc::NCI_PKT_PAYLOAD_OFFSET + 1] == 0x20 ? "2.0" : "1.0");
|
||||
|
||||
@@ -274,11 +272,12 @@ uint8_t PN7150::init_core_() {
|
||||
uint8_t flash_minor_version = rx.get_message()[19 + rx.get_message()[8]];
|
||||
|
||||
ESP_LOGD(TAG,
|
||||
"Manufacturer ID: 0x%02X\n"
|
||||
"Hardware version: 0x%02X\n"
|
||||
"ROM code version: 0x%02X\n"
|
||||
"FLASH major version: 0x%02X\n"
|
||||
"FLASH minor version: 0x%02X",
|
||||
"PN7150 chip info:\n"
|
||||
" Manufacturer ID: 0x%02X\n"
|
||||
" Hardware version: 0x%02X\n"
|
||||
" ROM code version: 0x%02X\n"
|
||||
" FLASH major version: 0x%02X\n"
|
||||
" FLASH minor version: 0x%02X",
|
||||
manf_id, hw_version, rom_code_version, flash_major_version, flash_minor_version);
|
||||
|
||||
return rx.get_simple_status_response();
|
||||
|
||||
@@ -265,10 +265,7 @@ uint8_t PN7160::reset_core_(const bool reset_config, const bool power) {
|
||||
return nfc::STATUS_FAILED;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG,
|
||||
"Configuration %s\n"
|
||||
"NCI version: %s\n"
|
||||
"Manufacturer ID: 0x%02X",
|
||||
ESP_LOGD(TAG, "Configuration %s, NCI version: %s, Manufacturer ID: 0x%02X",
|
||||
rx.get_message()[4] ? "reset" : "retained", rx.get_message()[5] == 0x20 ? "2.0" : "1.0",
|
||||
rx.get_message()[6]);
|
||||
rx.get_message().erase(rx.get_message().begin(), rx.get_message().begin() + 8);
|
||||
@@ -301,11 +298,12 @@ uint8_t PN7160::init_core_() {
|
||||
|
||||
char feat_buf[nfc::FORMAT_BYTES_BUFFER_SIZE];
|
||||
ESP_LOGD(TAG,
|
||||
"Hardware version: %u\n"
|
||||
"ROM code version: %u\n"
|
||||
"FLASH major version: %u\n"
|
||||
"FLASH minor version: %u\n"
|
||||
"Features: %s",
|
||||
"PN7160 chip info:\n"
|
||||
" Hardware version: %u\n"
|
||||
" ROM code version: %u\n"
|
||||
" FLASH major version: %u\n"
|
||||
" FLASH minor version: %u\n"
|
||||
" Features: %s",
|
||||
hw_version, rom_code_version, flash_major_version, flash_minor_version,
|
||||
nfc::format_bytes_to(feat_buf, features));
|
||||
|
||||
|
||||
@@ -128,15 +128,14 @@ bool QMP6988Component::get_calibration_data_() {
|
||||
qmp6988_data_.qmp6988_cali.COE_bp3 = (int16_t) encode_uint16(a_data_uint8_tr[16], a_data_uint8_tr[17]);
|
||||
|
||||
ESP_LOGV(TAG,
|
||||
"<-----------calibration data-------------->\n"
|
||||
"COE_a0[%d] COE_a1[%d] COE_a2[%d] COE_b00[%d]",
|
||||
"Calibration data:\n"
|
||||
" COE_a0[%d] COE_a1[%d] COE_a2[%d] COE_b00[%d]\n"
|
||||
" COE_bt1[%d] COE_bt2[%d] COE_bp1[%d] COE_b11[%d]\n"
|
||||
" COE_bp2[%d] COE_b12[%d] COE_b21[%d] COE_bp3[%d]",
|
||||
qmp6988_data_.qmp6988_cali.COE_a0, qmp6988_data_.qmp6988_cali.COE_a1, qmp6988_data_.qmp6988_cali.COE_a2,
|
||||
qmp6988_data_.qmp6988_cali.COE_b00);
|
||||
ESP_LOGV(TAG, "COE_bt1[%d] COE_bt2[%d] COE_bp1[%d] COE_b11[%d]\r\n", qmp6988_data_.qmp6988_cali.COE_bt1,
|
||||
qmp6988_data_.qmp6988_cali.COE_bt2, qmp6988_data_.qmp6988_cali.COE_bp1, qmp6988_data_.qmp6988_cali.COE_b11);
|
||||
ESP_LOGV(TAG, "COE_bp2[%d] COE_b12[%d] COE_b21[%d] COE_bp3[%d]\r\n", qmp6988_data_.qmp6988_cali.COE_bp2,
|
||||
qmp6988_data_.qmp6988_cali.COE_b00, qmp6988_data_.qmp6988_cali.COE_bt1, qmp6988_data_.qmp6988_cali.COE_bt2,
|
||||
qmp6988_data_.qmp6988_cali.COE_bp1, qmp6988_data_.qmp6988_cali.COE_b11, qmp6988_data_.qmp6988_cali.COE_bp2,
|
||||
qmp6988_data_.qmp6988_cali.COE_b12, qmp6988_data_.qmp6988_cali.COE_b21, qmp6988_data_.qmp6988_cali.COE_bp3);
|
||||
ESP_LOGV(TAG, "<-----------calibration data-------------->\r\n");
|
||||
|
||||
qmp6988_data_.ik.a0 = qmp6988_data_.qmp6988_cali.COE_a0; // 20Q4
|
||||
qmp6988_data_.ik.b00 = qmp6988_data_.qmp6988_cali.COE_b00; // 20Q4
|
||||
@@ -153,14 +152,13 @@ bool QMP6988Component::get_calibration_data_() {
|
||||
qmp6988_data_.ik.b21 = 13836L * (int64_t) qmp6988_data_.qmp6988_cali.COE_b21 + 79333336L; // 29Q60
|
||||
qmp6988_data_.ik.bp3 = 2915L * (int64_t) qmp6988_data_.qmp6988_cali.COE_bp3 + 157155561L; // 28Q65
|
||||
ESP_LOGV(TAG,
|
||||
"<----------- int calibration data -------------->\n"
|
||||
"a0[%d] a1[%d] a2[%d] b00[%d]",
|
||||
qmp6988_data_.ik.a0, qmp6988_data_.ik.a1, qmp6988_data_.ik.a2, qmp6988_data_.ik.b00);
|
||||
ESP_LOGV(TAG, "bt1[%lld] bt2[%lld] bp1[%lld] b11[%lld]\r\n", qmp6988_data_.ik.bt1, qmp6988_data_.ik.bt2,
|
||||
qmp6988_data_.ik.bp1, qmp6988_data_.ik.b11);
|
||||
ESP_LOGV(TAG, "bp2[%lld] b12[%lld] b21[%lld] bp3[%lld]\r\n", qmp6988_data_.ik.bp2, qmp6988_data_.ik.b12,
|
||||
"Int calibration data:\n"
|
||||
" a0[%d] a1[%d] a2[%d] b00[%d]\n"
|
||||
" bt1[%lld] bt2[%lld] bp1[%lld] b11[%lld]\n"
|
||||
" bp2[%lld] b12[%lld] b21[%lld] bp3[%lld]",
|
||||
qmp6988_data_.ik.a0, qmp6988_data_.ik.a1, qmp6988_data_.ik.a2, qmp6988_data_.ik.b00, qmp6988_data_.ik.bt1,
|
||||
qmp6988_data_.ik.bt2, qmp6988_data_.ik.bp1, qmp6988_data_.ik.b11, qmp6988_data_.ik.bp2, qmp6988_data_.ik.b12,
|
||||
qmp6988_data_.ik.b21, qmp6988_data_.ik.bp3);
|
||||
ESP_LOGV(TAG, "<----------- int calibration data -------------->\r\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -104,10 +104,7 @@ void ProntoProtocol::send_pronto_(RemoteTransmitData *dst, const std::vector<uin
|
||||
|
||||
uint16_t intros = 2 * data[2];
|
||||
uint16_t repeats = 2 * data[3];
|
||||
ESP_LOGD(TAG,
|
||||
"Send Pronto: intros=%d\n"
|
||||
"Send Pronto: repeats=%d",
|
||||
intros, repeats);
|
||||
ESP_LOGD(TAG, "Send Pronto: intros=%d, repeats=%d", intros, repeats);
|
||||
if (NUMBERS_IN_PREAMBLE + intros + repeats != data.size()) { // inconsistent sizes
|
||||
ESP_LOGE(TAG, "Inconsistent data, not sending");
|
||||
return;
|
||||
|
||||
@@ -51,13 +51,11 @@ void SafeModeComponent::dump_config() {
|
||||
#if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK)
|
||||
const esp_partition_t *last_invalid = esp_ota_get_last_invalid_partition();
|
||||
if (last_invalid != nullptr) {
|
||||
ESP_LOGW(TAG,
|
||||
"OTA rollback detected! Rolled back from partition '%s'\n"
|
||||
"The device reset before the boot was marked successful",
|
||||
last_invalid->label);
|
||||
ESP_LOGW(TAG, "OTA rollback detected! Rolled back from partition '%s'", last_invalid->label);
|
||||
ESP_LOGW(TAG, "The device reset before the boot was marked successful");
|
||||
if (esp_reset_reason() == ESP_RST_BROWNOUT) {
|
||||
ESP_LOGW(TAG, "Last reset was due to brownout - check your power supply!\n"
|
||||
"See https://esphome.io/guides/faq.html#brownout-detector-was-triggered");
|
||||
ESP_LOGW(TAG, "Last reset was due to brownout - check your power supply!");
|
||||
ESP_LOGW(TAG, "See https://esphome.io/guides/faq.html#brownout-detector-was-triggered");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -903,6 +903,7 @@ async def setup_sensor_core_(var, config):
|
||||
if config[CONF_FORCE_UPDATE]:
|
||||
cg.add(var.set_force_update(True))
|
||||
if config.get(CONF_FILTERS): # must exist and not be empty
|
||||
cg.add_define("USE_SENSOR_FILTER")
|
||||
filters = await build_filters(config[CONF_FILTERS])
|
||||
cg.add(var.set_filters(filters))
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#include "esphome/core/defines.h"
|
||||
#ifdef USE_SENSOR_FILTER
|
||||
|
||||
#include "filter.h"
|
||||
#include <cmath>
|
||||
#include "esphome/core/application.h"
|
||||
@@ -580,3 +583,5 @@ void StreamingMovingAverageFilter::reset_batch() {
|
||||
}
|
||||
|
||||
} // namespace esphome::sensor
|
||||
|
||||
#endif // USE_SENSOR_FILTER
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <queue>
|
||||
#include "esphome/core/defines.h"
|
||||
#ifdef USE_SENSOR_FILTER
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include "esphome/core/automation.h"
|
||||
@@ -638,3 +640,5 @@ class StreamingMovingAverageFilter : public StreamingFilter {
|
||||
};
|
||||
|
||||
} // namespace esphome::sensor
|
||||
|
||||
#endif // USE_SENSOR_FILTER
|
||||
|
||||
@@ -68,11 +68,15 @@ void Sensor::publish_state(float state) {
|
||||
|
||||
ESP_LOGV(TAG, "'%s': Received new state %f", this->name_.c_str(), state);
|
||||
|
||||
#ifdef USE_SENSOR_FILTER
|
||||
if (this->filter_list_ == nullptr) {
|
||||
#endif
|
||||
this->internal_send_state_to_frontend(state);
|
||||
#ifdef USE_SENSOR_FILTER
|
||||
} else {
|
||||
this->filter_list_->input(state);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Sensor::add_on_state_callback(std::function<void(float)> &&callback) { this->callback_.add(std::move(callback)); }
|
||||
@@ -80,6 +84,7 @@ void Sensor::add_on_raw_state_callback(std::function<void(float)> &&callback) {
|
||||
this->raw_callback_.add(std::move(callback));
|
||||
}
|
||||
|
||||
#ifdef USE_SENSOR_FILTER
|
||||
void Sensor::add_filter(Filter *filter) {
|
||||
// inefficient, but only happens once on every sensor setup and nobody's going to have massive amounts of
|
||||
// filters
|
||||
@@ -109,6 +114,7 @@ void Sensor::clear_filters() {
|
||||
}
|
||||
this->filter_list_ = nullptr;
|
||||
}
|
||||
#endif // USE_SENSOR_FILTER
|
||||
float Sensor::get_state() const { return this->state; }
|
||||
float Sensor::get_raw_state() const { return this->raw_state; }
|
||||
|
||||
|
||||
@@ -4,13 +4,17 @@
|
||||
#include "esphome/core/entity_base.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
#ifdef USE_SENSOR_FILTER
|
||||
#include "esphome/components/sensor/filter.h"
|
||||
#endif
|
||||
|
||||
#include <initializer_list>
|
||||
#include <memory>
|
||||
|
||||
namespace esphome::sensor {
|
||||
|
||||
class Sensor;
|
||||
|
||||
void log_sensor(const char *tag, const char *prefix, const char *type, Sensor *obj);
|
||||
|
||||
#define LOG_SENSOR(prefix, type, obj) log_sensor(TAG, prefix, LOG_STR_LITERAL(type), obj)
|
||||
@@ -67,6 +71,7 @@ class Sensor : public EntityBase, public EntityBase_DeviceClass, public EntityBa
|
||||
/// Set force update mode.
|
||||
void set_force_update(bool force_update) { sensor_flags_.force_update = force_update; }
|
||||
|
||||
#ifdef USE_SENSOR_FILTER
|
||||
/// Add a filter to the filter chain. Will be appended to the back.
|
||||
void add_filter(Filter *filter);
|
||||
|
||||
@@ -87,6 +92,7 @@ class Sensor : public EntityBase, public EntityBase_DeviceClass, public EntityBa
|
||||
|
||||
/// Clear the entire filter chain.
|
||||
void clear_filters();
|
||||
#endif
|
||||
|
||||
/// Getter-syntax for .state.
|
||||
float get_state() const;
|
||||
@@ -130,7 +136,9 @@ class Sensor : public EntityBase, public EntityBase_DeviceClass, public EntityBa
|
||||
LazyCallbackManager<void(float)> raw_callback_; ///< Storage for raw state callbacks.
|
||||
LazyCallbackManager<void(float)> callback_; ///< Storage for filtered state callbacks.
|
||||
|
||||
#ifdef USE_SENSOR_FILTER
|
||||
Filter *filter_list_{nullptr}; ///< Store all active filters.
|
||||
#endif
|
||||
|
||||
// Group small members together to avoid padding
|
||||
int8_t accuracy_decimals_{-1}; ///< Accuracy in decimals (-1 = not set)
|
||||
|
||||
@@ -326,7 +326,7 @@ void Sim800LComponent::parse_cmd_(std::string message) {
|
||||
if (ok || message.compare(0, 6, "+CMGL:") == 0) {
|
||||
ESP_LOGD(TAG,
|
||||
"Received SMS from: %s\n"
|
||||
"%s",
|
||||
" %s",
|
||||
this->sender_.c_str(), this->message_.c_str());
|
||||
this->sms_received_callback_.call(this->message_, this->sender_);
|
||||
this->state_ = STATE_RECEIVED_SMS;
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
from collections.abc import Callable, MutableMapping
|
||||
from dataclasses import dataclass
|
||||
from enum import StrEnum
|
||||
import logging
|
||||
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.core import CORE
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
CODEOWNERS = ["@esphome/core"]
|
||||
|
||||
CONF_IMPLEMENTATION = "implementation"
|
||||
@@ -13,33 +18,110 @@ IMPLEMENTATION_BSD_SOCKETS = "bsd_sockets"
|
||||
|
||||
# Socket tracking infrastructure
|
||||
# Components register their socket needs and platforms read this to configure appropriately
|
||||
KEY_SOCKET_CONSUMERS = "socket_consumers"
|
||||
KEY_SOCKET_CONSUMERS_TCP = "socket_consumers_tcp"
|
||||
KEY_SOCKET_CONSUMERS_UDP = "socket_consumers_udp"
|
||||
KEY_SOCKET_CONSUMERS_TCP_LISTEN = "socket_consumers_tcp_listen"
|
||||
|
||||
# Recommended minimum socket counts.
|
||||
# Platforms should apply these (or their own) on top of get_socket_counts().
|
||||
# These cover minimal configs (e.g. api-only without web_server).
|
||||
# When web_server is present, its 5 registered sockets push past the TCP minimum.
|
||||
MIN_TCP_SOCKETS = 8
|
||||
MIN_UDP_SOCKETS = 6
|
||||
# Minimum listening sockets — at least api + ota baseline.
|
||||
MIN_TCP_LISTEN_SOCKETS = 2
|
||||
|
||||
# Wake loop threadsafe support tracking
|
||||
KEY_WAKE_LOOP_THREADSAFE_REQUIRED = "wake_loop_threadsafe_required"
|
||||
|
||||
|
||||
class SocketType(StrEnum):
|
||||
TCP = "tcp"
|
||||
UDP = "udp"
|
||||
TCP_LISTEN = "tcp_listen"
|
||||
|
||||
|
||||
_SOCKET_TYPE_KEYS = {
|
||||
SocketType.TCP: KEY_SOCKET_CONSUMERS_TCP,
|
||||
SocketType.UDP: KEY_SOCKET_CONSUMERS_UDP,
|
||||
SocketType.TCP_LISTEN: KEY_SOCKET_CONSUMERS_TCP_LISTEN,
|
||||
}
|
||||
|
||||
|
||||
def consume_sockets(
|
||||
value: int, consumer: str
|
||||
value: int, consumer: str, socket_type: SocketType = SocketType.TCP
|
||||
) -> Callable[[MutableMapping], MutableMapping]:
|
||||
"""Register socket usage for a component.
|
||||
|
||||
Args:
|
||||
value: Number of sockets needed by the component
|
||||
consumer: Name of the component consuming the sockets
|
||||
socket_type: Type of socket (SocketType.TCP, SocketType.UDP, or SocketType.TCP_LISTEN)
|
||||
|
||||
Returns:
|
||||
A validator function that records the socket usage
|
||||
"""
|
||||
typed_key = _SOCKET_TYPE_KEYS[socket_type]
|
||||
|
||||
def _consume_sockets(config: MutableMapping) -> MutableMapping:
|
||||
consumers: dict[str, int] = CORE.data.setdefault(KEY_SOCKET_CONSUMERS, {})
|
||||
consumers: dict[str, int] = CORE.data.setdefault(typed_key, {})
|
||||
consumers[consumer] = consumers.get(consumer, 0) + value
|
||||
return config
|
||||
|
||||
return _consume_sockets
|
||||
|
||||
|
||||
def _format_consumers(consumers: dict[str, int]) -> str:
|
||||
"""Format consumer dict as 'name=count, ...' or 'none'."""
|
||||
if not consumers:
|
||||
return "none"
|
||||
return ", ".join(f"{name}={count}" for name, count in sorted(consumers.items()))
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class SocketCounts:
|
||||
"""Socket counts and component details for platform configuration."""
|
||||
|
||||
tcp: int
|
||||
udp: int
|
||||
tcp_listen: int
|
||||
tcp_details: str
|
||||
udp_details: str
|
||||
tcp_listen_details: str
|
||||
|
||||
|
||||
def get_socket_counts() -> SocketCounts:
|
||||
"""Return socket counts and component details for platform configuration.
|
||||
|
||||
Platforms call this during code generation to configure lwIP socket limits.
|
||||
All components will have registered their needs by then.
|
||||
|
||||
Platforms should apply their own minimums on top of these values.
|
||||
"""
|
||||
tcp_consumers = CORE.data.get(KEY_SOCKET_CONSUMERS_TCP, {})
|
||||
udp_consumers = CORE.data.get(KEY_SOCKET_CONSUMERS_UDP, {})
|
||||
tcp_listen_consumers = CORE.data.get(KEY_SOCKET_CONSUMERS_TCP_LISTEN, {})
|
||||
tcp = sum(tcp_consumers.values())
|
||||
udp = sum(udp_consumers.values())
|
||||
tcp_listen = sum(tcp_listen_consumers.values())
|
||||
|
||||
tcp_details = _format_consumers(tcp_consumers)
|
||||
udp_details = _format_consumers(udp_consumers)
|
||||
tcp_listen_details = _format_consumers(tcp_listen_consumers)
|
||||
_LOGGER.debug(
|
||||
"Socket counts: TCP=%d (%s), UDP=%d (%s), TCP_LISTEN=%d (%s)",
|
||||
tcp,
|
||||
tcp_details,
|
||||
udp,
|
||||
udp_details,
|
||||
tcp_listen,
|
||||
tcp_listen_details,
|
||||
)
|
||||
return SocketCounts(
|
||||
tcp, udp, tcp_listen, tcp_details, udp_details, tcp_listen_details
|
||||
)
|
||||
|
||||
|
||||
def require_wake_loop_threadsafe() -> None:
|
||||
"""Mark that wake_loop_threadsafe support is required by a component.
|
||||
|
||||
@@ -66,7 +148,7 @@ def require_wake_loop_threadsafe() -> None:
|
||||
CORE.data[KEY_WAKE_LOOP_THREADSAFE_REQUIRED] = True
|
||||
cg.add_define("USE_WAKE_LOOP_THREADSAFE")
|
||||
# Consume 1 socket for the shared wake notification socket
|
||||
consume_sockets(1, "socket.wake_loop_threadsafe")({})
|
||||
consume_sockets(1, "socket.wake_loop_threadsafe", SocketType.UDP)({})
|
||||
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
|
||||
@@ -93,10 +93,7 @@ bool SonoffD1Output::read_command_(uint8_t *cmd, size_t &len) {
|
||||
if (this->read_array(cmd, 6)) {
|
||||
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
|
||||
char hex_buf[format_hex_pretty_size(6)];
|
||||
ESP_LOGV(TAG,
|
||||
"[%04d] Reading from dimmer:\n"
|
||||
"[%04d] %s",
|
||||
this->write_count_, this->write_count_, format_hex_pretty_to(hex_buf, cmd, 6));
|
||||
ESP_LOGV(TAG, "[%04d] Reading from dimmer: %s", this->write_count_, format_hex_pretty_to(hex_buf, cmd, 6));
|
||||
#endif
|
||||
|
||||
if (cmd[0] != 0xAA || cmd[1] != 0x55) {
|
||||
@@ -190,10 +187,7 @@ bool SonoffD1Output::write_command_(uint8_t *cmd, const size_t len, bool needs_a
|
||||
do {
|
||||
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
|
||||
char hex_buf[format_hex_pretty_size(SONOFF_D1_MAX_CMD_SIZE)];
|
||||
ESP_LOGV(TAG,
|
||||
"[%04d] Writing to the dimmer:\n"
|
||||
"[%04d] %s",
|
||||
this->write_count_, this->write_count_, format_hex_pretty_to(hex_buf, cmd, len));
|
||||
ESP_LOGV(TAG, "[%04d] Writing to the dimmer: %s", this->write_count_, format_hex_pretty_to(hex_buf, cmd, len));
|
||||
#endif
|
||||
this->write_array(cmd, len);
|
||||
this->write_count_++;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "esphome/components/microphone/microphone_source.h"
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
|
||||
#include "esphome/core/automation.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/ring_buffer.h"
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user