Merge branch 'dev' into ota-use-idf-backend-for-all-esp32

This commit is contained in:
J. Nick Koston
2025-12-01 21:05:33 -06:00
committed by GitHub
191 changed files with 1670 additions and 712 deletions
+1 -1
View File
@@ -11,7 +11,7 @@ ci:
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.14.5
rev: v0.14.7
hooks:
# Run the linter.
- id: ruff
+1
View File
@@ -21,6 +21,7 @@ esphome/components/adc128s102/* @DeerMaximum
esphome/components/addressable_light/* @justfalter
esphome/components/ade7880/* @kpfleming
esphome/components/ade7953/* @angelnu
esphome/components/ade7953_base/* @angelnu
esphome/components/ade7953_i2c/* @angelnu
esphome/components/ade7953_spi/* @angelnu
esphome/components/ads1118/* @solomondg1
@@ -24,6 +24,8 @@ from esphome.const import (
UNIT_WATT,
)
CODEOWNERS = ["@angelnu"]
CONF_CURRENT_A = "current_a"
CONF_CURRENT_B = "current_b"
CONF_ACTIVE_POWER_A = "active_power_a"
@@ -25,7 +25,8 @@ void ADE7953::setup() {
this->ade_write_8(PGA_V_8, pga_v_);
this->ade_write_8(PGA_IA_8, pga_ia_);
this->ade_write_8(PGA_IB_8, pga_ib_);
this->ade_write_32(AVGAIN_32, vgain_);
this->ade_write_32(AVGAIN_32, avgain_);
this->ade_write_32(BVGAIN_32, bvgain_);
this->ade_write_32(AIGAIN_32, aigain_);
this->ade_write_32(BIGAIN_32, bigain_);
this->ade_write_32(AWGAIN_32, awgain_);
@@ -34,7 +35,8 @@ void ADE7953::setup() {
this->ade_read_8(PGA_V_8, &pga_v_);
this->ade_read_8(PGA_IA_8, &pga_ia_);
this->ade_read_8(PGA_IB_8, &pga_ib_);
this->ade_read_32(AVGAIN_32, &vgain_);
this->ade_read_32(AVGAIN_32, &avgain_);
this->ade_read_32(BVGAIN_32, &bvgain_);
this->ade_read_32(AIGAIN_32, &aigain_);
this->ade_read_32(BIGAIN_32, &bigain_);
this->ade_read_32(AWGAIN_32, &awgain_);
@@ -63,13 +65,14 @@ void ADE7953::dump_config() {
" PGA_V_8: 0x%X\n"
" PGA_IA_8: 0x%X\n"
" PGA_IB_8: 0x%X\n"
" VGAIN_32: 0x%08jX\n"
" AVGAIN_32: 0x%08jX\n"
" BVGAIN_32: 0x%08jX\n"
" AIGAIN_32: 0x%08jX\n"
" BIGAIN_32: 0x%08jX\n"
" AWGAIN_32: 0x%08jX\n"
" BWGAIN_32: 0x%08jX",
this->use_acc_energy_regs_, pga_v_, pga_ia_, pga_ib_, (uintmax_t) vgain_, (uintmax_t) aigain_,
(uintmax_t) bigain_, (uintmax_t) awgain_, (uintmax_t) bwgain_);
this->use_acc_energy_regs_, pga_v_, pga_ia_, pga_ib_, (uintmax_t) avgain_, (uintmax_t) bvgain_,
(uintmax_t) aigain_, (uintmax_t) bigain_, (uintmax_t) awgain_, (uintmax_t) bwgain_);
}
#define ADE_PUBLISH_(name, val, factor) \
@@ -46,7 +46,12 @@ class ADE7953 : public PollingComponent, public sensor::Sensor {
void set_pga_ib(uint8_t pga_ib) { pga_ib_ = pga_ib; }
// Set input gains
void set_vgain(uint32_t vgain) { vgain_ = vgain; }
void set_vgain(uint32_t vgain) {
// Datasheet says: "to avoid discrepancies in other registers,
// if AVGAIN is set then BVGAIN should be set to the same value."
avgain_ = vgain;
bvgain_ = vgain;
}
void set_aigain(uint32_t aigain) { aigain_ = aigain; }
void set_bigain(uint32_t bigain) { bigain_ = bigain; }
void set_awgain(uint32_t awgain) { awgain_ = awgain; }
@@ -100,7 +105,8 @@ class ADE7953 : public PollingComponent, public sensor::Sensor {
uint8_t pga_v_;
uint8_t pga_ia_;
uint8_t pga_ib_;
uint32_t vgain_;
uint32_t avgain_;
uint32_t bvgain_;
uint32_t aigain_;
uint32_t bigain_;
uint32_t awgain_;
+1
View File
@@ -589,6 +589,7 @@ enum SensorStateClass {
STATE_CLASS_MEASUREMENT = 1;
STATE_CLASS_TOTAL_INCREASING = 2;
STATE_CLASS_TOTAL = 3;
STATE_CLASS_MEASUREMENT_ANGLE = 4;
}
// Deprecated in API version 1.5
+4 -2
View File
@@ -169,8 +169,7 @@ void APIConnection::loop() {
} else {
this->last_traffic_ = now;
// read a packet
this->read_message(buffer.data_len, buffer.type,
buffer.data_len > 0 ? &buffer.container[buffer.data_offset] : nullptr);
this->read_message(buffer.data_len, buffer.type, buffer.data);
if (this->flags_.remove)
return;
}
@@ -195,6 +194,9 @@ void APIConnection::loop() {
}
// Now that everything is sent, enable immediate sending for future state changes
this->flags_.should_try_send_immediately = true;
// Release excess memory from buffers that grew during initial sync
this->deferred_batch_.release_buffer();
this->helper_->release_buffers();
}
}
+11 -4
View File
@@ -554,10 +554,8 @@ class APIConnection final : public APIServerConnection {
std::vector<BatchItem> items;
uint32_t batch_start_time{0};
DeferredBatch() {
// Pre-allocate capacity for typical batch sizes to avoid reallocation
items.reserve(8);
}
// No pre-allocation - log connections never use batching, and for
// connections that do, buffers are released after initial sync anyway
// Add item to the batch
void add_item(EntityBase *entity, MessageCreator creator, uint8_t message_type, uint8_t estimated_size);
@@ -576,6 +574,15 @@ class APIConnection final : public APIServerConnection {
bool empty() const { return items.empty(); }
size_t size() const { return items.size(); }
const BatchItem &operator[](size_t index) const { return items[index]; }
// Release excess capacity - only releases if items already empty
void release_buffer() {
// Safe to call: batch is processed before release_buffer is called,
// and if any items remain (partial processing), we must not clear them.
// Use swap trick since shrink_to_fit() is non-binding and may be ignored.
if (items.empty()) {
std::vector<BatchItem>().swap(items);
}
}
};
// DeferredBatch here (16 bytes, 4-byte aligned)
+18 -3
View File
@@ -35,10 +35,9 @@ struct ClientInfo;
class ProtoWriteBuffer;
struct ReadPacketBuffer {
std::vector<uint8_t> container;
uint16_t type;
uint16_t data_offset;
const uint8_t *data; // Points directly into frame helper's rx_buf_ (valid until next read_packet call)
uint16_t data_len;
uint16_t type;
};
// Packed packet info structure to minimize memory usage
@@ -119,6 +118,22 @@ class APIFrameHelper {
uint8_t frame_footer_size() const { return frame_footer_size_; }
// Check if socket has data ready to read
bool is_socket_ready() const { return socket_ != nullptr && socket_->ready(); }
// Release excess memory from internal buffers after initial sync
void release_buffers() {
// rx_buf_: Safe to clear only if no partial read in progress.
// rx_buf_len_ tracks bytes read so far; if non-zero, we're mid-frame
// and clearing would lose partially received data.
if (this->rx_buf_len_ == 0) {
// Use swap trick since shrink_to_fit() is non-binding and may be ignored
std::vector<uint8_t>().swap(this->rx_buf_);
}
// reusable_iovs_: Safe to release unconditionally.
// Only used within write_protobuf_packets() calls - cleared at start,
// populated with pointers, used for writev(), then function returns.
// The iovecs contain stale pointers after the call (data was either sent
// or copied to tx_buf_), and are cleared on next write_protobuf_packets().
std::vector<struct iovec>().swap(this->reusable_iovs_);
}
protected:
// Buffer containing data to be sent
@@ -407,8 +407,7 @@ APIError APINoiseFrameHelper::read_packet(ReadPacketBuffer *buffer) {
return APIError::BAD_DATA_PACKET;
}
buffer->container = std::move(this->rx_buf_);
buffer->data_offset = 4;
buffer->data = msg_data + 4; // Skip 4-byte header (type + length)
buffer->data_len = data_len;
buffer->type = type;
return APIError::OK;
@@ -210,8 +210,7 @@ APIError APIPlaintextFrameHelper::read_packet(ReadPacketBuffer *buffer) {
return aerr;
}
buffer->container = std::move(this->rx_buf_);
buffer->data_offset = 0;
buffer->data = this->rx_buf_.data();
buffer->data_len = this->rx_header_parsed_len_;
buffer->type = this->rx_header_parsed_type_;
return APIError::OK;
+1
View File
@@ -51,6 +51,7 @@ enum SensorStateClass : uint32_t {
STATE_CLASS_MEASUREMENT = 1,
STATE_CLASS_TOTAL_INCREASING = 2,
STATE_CLASS_TOTAL = 3,
STATE_CLASS_MEASUREMENT_ANGLE = 4,
};
#endif
enum LogLevel : uint32_t {
+2
View File
@@ -179,6 +179,8 @@ template<> const char *proto_enum_to_string<enums::SensorStateClass>(enums::Sens
return "STATE_CLASS_TOTAL_INCREASING";
case enums::STATE_CLASS_TOTAL:
return "STATE_CLASS_TOTAL";
case enums::STATE_CLASS_MEASUREMENT_ANGLE:
return "STATE_CLASS_MEASUREMENT_ANGLE";
default:
return "UNKNOWN";
}
+2 -2
View File
@@ -13,7 +13,7 @@ void APIServerConnectionBase::log_send_message_(const char *name, const std::str
}
#endif
void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) {
void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) {
switch (msg_type) {
case HelloRequest::MESSAGE_TYPE: {
HelloRequest msg;
@@ -827,7 +827,7 @@ void APIServerConnection::on_z_wave_proxy_frame(const ZWaveProxyFrame &msg) { th
void APIServerConnection::on_z_wave_proxy_request(const ZWaveProxyRequest &msg) { this->zwave_proxy_request(msg); }
#endif
void APIServerConnection::read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) {
void APIServerConnection::read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) {
// Check authentication/connection requirements for messages
switch (msg_type) {
case HelloRequest::MESSAGE_TYPE: // No setup required
+2 -2
View File
@@ -218,7 +218,7 @@ class APIServerConnectionBase : public ProtoService {
virtual void on_z_wave_proxy_request(const ZWaveProxyRequest &value){};
#endif
protected:
void read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) override;
void read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) override;
};
class APIServerConnection : public APIServerConnectionBase {
@@ -480,7 +480,7 @@ class APIServerConnection : public APIServerConnectionBase {
#ifdef USE_ZWAVE_PROXY
void on_z_wave_proxy_request(const ZWaveProxyRequest &msg) override;
#endif
void read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) override;
void read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) override;
};
} // namespace esphome::api
+16 -13
View File
@@ -101,19 +101,7 @@ void APIServer::setup() {
#ifdef USE_LOGGER
if (logger::global_logger != nullptr) {
logger::global_logger->add_on_log_callback(
[this](int level, const char *tag, const char *message, size_t message_len) {
if (this->shutting_down_) {
// Don't try to send logs during shutdown
// as it could result in a recursion and
// we would be filling a buffer we are trying to clear
return;
}
for (auto &c : this->clients_) {
if (!c->flags_.remove && c->get_log_subscription_level() >= level)
c->try_send_log_message(level, tag, message, message_len);
}
});
logger::global_logger->add_log_listener(this);
}
#endif
@@ -541,6 +529,21 @@ bool APIServer::is_connected(bool state_subscription_only) const {
return false;
}
#ifdef USE_LOGGER
void APIServer::on_log(uint8_t level, const char *tag, const char *message, size_t message_len) {
if (this->shutting_down_) {
// Don't try to send logs during shutdown
// as it could result in a recursion and
// we would be filling a buffer we are trying to clear
return;
}
for (auto &c : this->clients_) {
if (!c->flags_.remove && c->get_log_subscription_level() >= level)
c->try_send_log_message(level, tag, message, message_len);
}
}
#endif
void APIServer::on_shutdown() {
this->shutting_down_ = true;
+13 -1
View File
@@ -15,6 +15,9 @@
#ifdef USE_API_USER_DEFINED_ACTIONS
#include "user_services.h"
#endif
#ifdef USE_LOGGER
#include "esphome/components/logger/logger.h"
#endif
#include <map>
#include <vector>
@@ -27,7 +30,13 @@ struct SavedNoisePsk {
} PACKED; // NOLINT
#endif
class APIServer : public Component, public Controller {
class APIServer : public Component,
public Controller
#ifdef USE_LOGGER
,
public logger::LogListener
#endif
{
public:
APIServer();
void setup() override;
@@ -37,6 +46,9 @@ class APIServer : public Component, public Controller {
void dump_config() override;
void on_shutdown() override;
bool teardown() override;
#ifdef USE_LOGGER
void on_log(uint8_t level, const char *tag, const char *message, size_t message_len) override;
#endif
#ifdef USE_API_PASSWORD
bool check_password(const uint8_t *password_data, size_t password_len) const;
void set_password(const std::string &password);
+1 -1
View File
@@ -846,7 +846,7 @@ class ProtoService {
*/
virtual ProtoWriteBuffer create_buffer(uint32_t reserve_size) = 0;
virtual bool send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) = 0;
virtual void read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) = 0;
virtual void read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) = 0;
// Optimized method that pre-allocates buffer based on message size
bool send_message_(const ProtoMessage &msg, uint8_t message_type) {
+2 -4
View File
@@ -2,12 +2,10 @@
#include "automation.h"
namespace esphome {
namespace ble_client {
namespace esphome::ble_client {
const char *const Automation::TAG = "ble_client.automation";
} // namespace ble_client
} // namespace esphome
} // namespace esphome::ble_client
#endif
+2 -4
View File
@@ -9,8 +9,7 @@
#include "esphome/components/ble_client/ble_client.h"
#include "esphome/core/log.h"
namespace esphome {
namespace ble_client {
namespace esphome::ble_client {
// placeholder class for static TAG .
class Automation {
@@ -391,7 +390,6 @@ template<typename... Ts> class BLEClientDisconnectAction : public Action<Ts...>,
BLEClient *ble_client_;
std::tuple<Ts...> var_{};
};
} // namespace ble_client
} // namespace esphome
} // namespace esphome::ble_client
#endif
+2 -4
View File
@@ -7,8 +7,7 @@
#ifdef USE_ESP32
namespace esphome {
namespace ble_client {
namespace esphome::ble_client {
static const char *const TAG = "ble_client";
@@ -82,7 +81,6 @@ bool BLEClient::all_nodes_established_() {
return true;
}
} // namespace ble_client
} // namespace esphome
} // namespace esphome::ble_client
#endif
+2 -4
View File
@@ -15,8 +15,7 @@
#include <string>
#include <vector>
namespace esphome {
namespace ble_client {
namespace esphome::ble_client {
namespace espbt = esphome::esp32_ble_tracker;
@@ -75,7 +74,6 @@ class BLEClient : public BLEClientBase {
std::vector<BLEClientNode *> nodes_;
};
} // namespace ble_client
} // namespace esphome
} // namespace esphome::ble_client
#endif
@@ -3,8 +3,7 @@
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
#ifdef USE_ESP32
namespace esphome {
namespace ble_client {
namespace esphome::ble_client {
static const char *const TAG = "ble_binary_output";
@@ -75,6 +74,5 @@ void BLEBinaryOutput::write_state(bool state) {
ESP_LOGW(TAG, "[%s] Write error, err=%d", this->char_uuid_.to_string().c_str(), err);
}
} // namespace ble_client
} // namespace esphome
} // namespace esphome::ble_client
#endif
@@ -7,8 +7,7 @@
#ifdef USE_ESP32
#include <esp_gattc_api.h>
namespace esphome {
namespace ble_client {
namespace esphome::ble_client {
namespace espbt = esphome::esp32_ble_tracker;
@@ -36,7 +35,6 @@ class BLEBinaryOutput : public output::BinaryOutput, public BLEClientNode, publi
esp_gatt_write_type_t write_type_{};
};
} // namespace ble_client
} // namespace esphome
} // namespace esphome::ble_client
#endif
@@ -5,8 +5,7 @@
#ifdef USE_ESP32
namespace esphome {
namespace ble_client {
namespace esphome::ble_client {
class BLESensorNotifyTrigger : public Trigger<float>, public BLESensor {
public:
@@ -35,7 +34,6 @@ class BLESensorNotifyTrigger : public Trigger<float>, public BLESensor {
BLESensor *sensor_;
};
} // namespace ble_client
} // namespace esphome
} // namespace esphome::ble_client
#endif
@@ -6,8 +6,7 @@
#ifdef USE_ESP32
namespace esphome {
namespace ble_client {
namespace esphome::ble_client {
static const char *const TAG = "ble_rssi_sensor";
@@ -78,6 +77,5 @@ void BLEClientRSSISensor::get_rssi_() {
}
}
} // namespace ble_client
} // namespace esphome
} // namespace esphome::ble_client
#endif
@@ -8,8 +8,7 @@
#ifdef USE_ESP32
#include <esp_gattc_api.h>
namespace esphome {
namespace ble_client {
namespace esphome::ble_client {
namespace espbt = esphome::esp32_ble_tracker;
@@ -29,6 +28,5 @@ class BLEClientRSSISensor : public sensor::Sensor, public PollingComponent, publ
bool should_update_{false};
};
} // namespace ble_client
} // namespace esphome
} // namespace esphome::ble_client
#endif
@@ -6,8 +6,7 @@
#ifdef USE_ESP32
namespace esphome {
namespace ble_client {
namespace esphome::ble_client {
static const char *const TAG = "ble_sensor";
@@ -147,6 +146,5 @@ void BLESensor::update() {
}
}
} // namespace ble_client
} // namespace esphome
} // namespace esphome::ble_client
#endif
@@ -10,8 +10,7 @@
#ifdef USE_ESP32
#include <esp_gattc_api.h>
namespace esphome {
namespace ble_client {
namespace esphome::ble_client {
namespace espbt = esphome::esp32_ble_tracker;
@@ -48,6 +47,5 @@ class BLESensor : public sensor::Sensor, public PollingComponent, public BLEClie
espbt::ESPBTUUID descr_uuid_;
};
} // namespace ble_client
} // namespace esphome
} // namespace esphome::ble_client
#endif
@@ -4,8 +4,7 @@
#ifdef USE_ESP32
namespace esphome {
namespace ble_client {
namespace esphome::ble_client {
static const char *const TAG = "ble_switch";
@@ -31,6 +30,5 @@ void BLEClientSwitch::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_i
void BLEClientSwitch::dump_config() { LOG_SWITCH("", "BLE Client Switch", this); }
} // namespace ble_client
} // namespace esphome
} // namespace esphome::ble_client
#endif
@@ -8,8 +8,7 @@
#ifdef USE_ESP32
#include <esp_gattc_api.h>
namespace esphome {
namespace ble_client {
namespace esphome::ble_client {
namespace espbt = esphome::esp32_ble_tracker;
@@ -24,6 +23,5 @@ class BLEClientSwitch : public switch_::Switch, public Component, public BLEClie
void write_state(bool state) override;
};
} // namespace ble_client
} // namespace esphome
} // namespace esphome::ble_client
#endif
@@ -5,8 +5,7 @@
#ifdef USE_ESP32
namespace esphome {
namespace ble_client {
namespace esphome::ble_client {
class BLETextSensorNotifyTrigger : public Trigger<std::string>, public BLETextSensor {
public:
@@ -33,7 +32,6 @@ class BLETextSensorNotifyTrigger : public Trigger<std::string>, public BLETextSe
BLETextSensor *sensor_;
};
} // namespace ble_client
} // namespace esphome
} // namespace esphome::ble_client
#endif
@@ -7,8 +7,7 @@
#ifdef USE_ESP32
namespace esphome {
namespace ble_client {
namespace esphome::ble_client {
static const char *const TAG = "ble_text_sensor";
@@ -138,6 +137,5 @@ void BLETextSensor::update() {
}
}
} // namespace ble_client
} // namespace esphome
} // namespace esphome::ble_client
#endif
@@ -8,8 +8,7 @@
#ifdef USE_ESP32
#include <esp_gattc_api.h>
namespace esphome {
namespace ble_client {
namespace esphome::ble_client {
namespace espbt = esphome::esp32_ble_tracker;
@@ -40,6 +39,5 @@ class BLETextSensor : public text_sensor::TextSensor, public PollingComponent, p
espbt::ESPBTUUID descr_uuid_;
};
} // namespace ble_client
} // namespace esphome
} // namespace esphome::ble_client
#endif
+11 -7
View File
@@ -87,17 +87,21 @@ void BLENUS::setup() {
global_ble_nus = this;
#ifdef USE_LOGGER
if (logger::global_logger != nullptr && this->expose_log_) {
logger::global_logger->add_on_log_callback(
[this](int level, const char *tag, const char *message, size_t message_len) {
this->write_array(reinterpret_cast<const uint8_t *>(message), message_len);
const char c = '\n';
this->write_array(reinterpret_cast<const uint8_t *>(&c), 1);
});
logger::global_logger->add_log_listener(this);
}
#endif
}
#ifdef USE_LOGGER
void BLENUS::on_log(uint8_t level, const char *tag, const char *message, size_t message_len) {
(void) level;
(void) tag;
this->write_array(reinterpret_cast<const uint8_t *>(message), message_len);
const char c = '\n';
this->write_array(reinterpret_cast<const uint8_t *>(&c), 1);
}
#endif
void BLENUS::dump_config() {
ESP_LOGCONFIG(TAG, "ble nus:");
ESP_LOGCONFIG(TAG, " log: %s", YESNO(this->expose_log_));
+12 -1
View File
@@ -2,12 +2,20 @@
#ifdef USE_ZEPHYR
#include "esphome/core/defines.h"
#include "esphome/core/component.h"
#ifdef USE_LOGGER
#include "esphome/components/logger/logger.h"
#endif
#include <shell/shell_bt_nus.h>
#include <atomic>
namespace esphome::ble_nus {
class BLENUS : public Component {
class BLENUS : public Component
#ifdef USE_LOGGER
,
public logger::LogListener
#endif
{
enum TxStatus {
TX_DISABLED,
TX_ENABLED,
@@ -20,6 +28,9 @@ class BLENUS : public Component {
void loop() override;
size_t write_array(const uint8_t *data, size_t len);
void set_expose_log(bool expose_log) { this->expose_log_ = expose_log; }
#ifdef USE_LOGGER
void on_log(uint8_t level, const char *tag, const char *message, size_t message_len) override;
#endif
protected:
static void send_enabled_callback(bt_nus_send_status status);
@@ -27,11 +27,13 @@ void BluetoothProxy::setup() {
// Capture the configured scan mode from YAML before any API changes
this->configured_scan_active_ = this->parent_->get_scan_active();
this->parent_->add_scanner_state_callback([this](esp32_ble_tracker::ScannerState state) {
if (this->api_connection_ != nullptr) {
this->send_bluetooth_scanner_state_(state);
}
});
this->parent_->add_scanner_state_listener(this);
}
void BluetoothProxy::on_scanner_state(esp32_ble_tracker::ScannerState state) {
if (this->api_connection_ != nullptr) {
this->send_bluetooth_scanner_state_(state);
}
}
void BluetoothProxy::send_bluetooth_scanner_state_(esp32_ble_tracker::ScannerState state) {
@@ -52,7 +52,9 @@ enum BluetoothProxySubscriptionFlag : uint32_t {
SUBSCRIPTION_RAW_ADVERTISEMENTS = 1 << 0,
};
class BluetoothProxy final : public esp32_ble_tracker::ESPBTDeviceListener, public Component {
class BluetoothProxy final : public esp32_ble_tracker::ESPBTDeviceListener,
public esp32_ble_tracker::BLEScannerStateListener,
public Component {
friend class BluetoothConnection; // Allow connection to update connections_free_response_
public:
BluetoothProxy();
@@ -108,6 +110,9 @@ class BluetoothProxy final : public esp32_ble_tracker::ESPBTDeviceListener, publ
void set_active(bool active) { this->active_ = active; }
bool has_active() { return this->active_; }
/// BLEScannerStateListener interface
void on_scanner_state(esp32_ble_tracker::ScannerState state) override;
uint32_t get_legacy_version() const {
if (this->active_) {
return LEGACY_ACTIVE_CONNECTIONS_VERSION;
+2 -4
View File
@@ -4,8 +4,7 @@
#include "esphome/core/automation.h"
#include "esphome/core/component.h"
namespace esphome {
namespace button {
namespace esphome::button {
template<typename... Ts> class PressAction : public Action<Ts...> {
public:
@@ -24,5 +23,4 @@ class ButtonPressTrigger : public Trigger<> {
}
};
} // namespace button
} // namespace esphome
} // namespace esphome::button
+2 -4
View File
@@ -1,8 +1,7 @@
#include "button.h"
#include "esphome/core/log.h"
namespace esphome {
namespace button {
namespace esphome::button {
static const char *const TAG = "button";
@@ -26,5 +25,4 @@ void Button::press() {
}
void Button::add_on_press_callback(std::function<void()> &&callback) { this->press_callback_.add(std::move(callback)); }
} // namespace button
} // namespace esphome
} // namespace esphome::button
+2 -4
View File
@@ -4,8 +4,7 @@
#include "esphome/core/entity_base.h"
#include "esphome/core/helpers.h"
namespace esphome {
namespace button {
namespace esphome::button {
class Button;
void log_button(const char *tag, const char *prefix, const char *type, Button *obj);
@@ -45,5 +44,4 @@ class Button : public EntityBase, public EntityBase_DeviceClass {
CallbackManager<void()> press_callback_{};
};
} // namespace button
} // namespace esphome
} // namespace esphome::button
+2 -4
View File
@@ -3,8 +3,7 @@
#include "esphome/core/automation.h"
#include "climate.h"
namespace esphome {
namespace climate {
namespace esphome::climate {
template<typename... Ts> class ControlAction : public Action<Ts...> {
public:
@@ -58,5 +57,4 @@ class StateTrigger : public Trigger<Climate &> {
}
};
} // namespace climate
} // namespace esphome
} // namespace esphome::climate
+2 -4
View File
@@ -3,8 +3,7 @@
#include "esphome/core/controller_registry.h"
#include "esphome/core/macros.h"
namespace esphome {
namespace climate {
namespace esphome::climate {
static const char *const TAG = "climate";
@@ -762,5 +761,4 @@ void Climate::dump_traits_(const char *tag) {
}
}
} // namespace climate
} // namespace esphome
} // namespace esphome::climate
+2 -4
View File
@@ -8,8 +8,7 @@
#include "climate_mode.h"
#include "climate_traits.h"
namespace esphome {
namespace climate {
namespace esphome::climate {
#define LOG_CLIMATE(prefix, type, obj) \
if ((obj) != nullptr) { \
@@ -345,5 +344,4 @@ class Climate : public EntityBase {
const char *custom_preset_{nullptr};
};
} // namespace climate
} // namespace esphome
} // namespace esphome::climate
+2 -4
View File
@@ -1,7 +1,6 @@
#include "climate_mode.h"
namespace esphome {
namespace climate {
namespace esphome::climate {
const LogString *climate_mode_to_string(ClimateMode mode) {
switch (mode) {
@@ -107,5 +106,4 @@ const LogString *climate_preset_to_string(ClimatePreset preset) {
}
}
} // namespace climate
} // namespace esphome
} // namespace esphome::climate
+2 -4
View File
@@ -3,8 +3,7 @@
#include <cstdint>
#include "esphome/core/log.h"
namespace esphome {
namespace climate {
namespace esphome::climate {
/// Enum for all modes a climate device can be in.
/// NOTE: If adding values, update ClimateModeMask in climate_traits.h to use the new last value
@@ -132,5 +131,4 @@ const LogString *climate_swing_mode_to_string(ClimateSwingMode mode);
/// Convert the given PresetMode to a human-readable string.
const LogString *climate_preset_to_string(ClimatePreset preset);
} // namespace climate
} // namespace esphome
} // namespace esphome::climate
@@ -1,7 +1,6 @@
#include "climate_traits.h"
namespace esphome {
namespace climate {
namespace esphome::climate {
int8_t ClimateTraits::get_target_temperature_accuracy_decimals() const {
return step_to_accuracy_decimals(this->visual_target_temperature_step_);
@@ -11,5 +10,4 @@ int8_t ClimateTraits::get_current_temperature_accuracy_decimals() const {
return step_to_accuracy_decimals(this->visual_current_temperature_step_);
}
} // namespace climate
} // namespace esphome
} // namespace esphome::climate
+2 -4
View File
@@ -6,8 +6,7 @@
#include "esphome/core/finite_set_mask.h"
#include "esphome/core/helpers.h"
namespace esphome {
namespace climate {
namespace esphome::climate {
// Type aliases for climate enum bitmasks
// These replace std::set<EnumType> to eliminate red-black tree overhead
@@ -292,5 +291,4 @@ class ClimateTraits {
std::vector<const char *> supported_custom_presets_;
};
} // namespace climate
} // namespace esphome
} // namespace esphome::climate
+2 -4
View File
@@ -5,8 +5,7 @@
#include "esphome/core/log.h"
namespace esphome {
namespace datetime {
namespace esphome::datetime {
static const char *const TAG = "datetime.date_entity";
@@ -129,7 +128,6 @@ void DateEntityRestoreState::apply(DateEntity *date) {
date->publish_state();
}
} // namespace datetime
} // namespace esphome
} // namespace esphome::datetime
#endif // USE_DATETIME_DATE
+2 -4
View File
@@ -10,8 +10,7 @@
#include "datetime_base.h"
namespace esphome {
namespace datetime {
namespace esphome::datetime {
#define LOG_DATETIME_DATE(prefix, type, obj) \
if ((obj) != nullptr) { \
@@ -111,7 +110,6 @@ template<typename... Ts> class DateSetAction : public Action<Ts...>, public Pare
}
};
} // namespace datetime
} // namespace esphome
} // namespace esphome::datetime
#endif // USE_DATETIME_DATE
+2 -4
View File
@@ -8,8 +8,7 @@
#include "esphome/components/time/real_time_clock.h"
#endif
namespace esphome {
namespace datetime {
namespace esphome::datetime {
class DateTimeBase : public EntityBase {
public:
@@ -37,5 +36,4 @@ class DateTimeStateTrigger : public Trigger<ESPTime> {
}
};
} // namespace datetime
} // namespace esphome
} // namespace esphome::datetime
@@ -5,8 +5,7 @@
#include "esphome/core/log.h"
namespace esphome {
namespace datetime {
namespace esphome::datetime {
static const char *const TAG = "datetime.datetime_entity";
@@ -250,7 +249,6 @@ bool OnDateTimeTrigger::matches_(const ESPTime &time) const {
}
#endif
} // namespace datetime
} // namespace esphome
} // namespace esphome::datetime
#endif // USE_DATETIME_TIME
@@ -10,8 +10,7 @@
#include "datetime_base.h"
namespace esphome {
namespace datetime {
namespace esphome::datetime {
#define LOG_DATETIME_DATETIME(prefix, type, obj) \
if ((obj) != nullptr) { \
@@ -146,7 +145,6 @@ class OnDateTimeTrigger : public Trigger<>, public Component, public Parented<Da
};
#endif
} // namespace datetime
} // namespace esphome
} // namespace esphome::datetime
#endif // USE_DATETIME_DATETIME
+2 -4
View File
@@ -5,8 +5,7 @@
#include "esphome/core/log.h"
namespace esphome {
namespace datetime {
namespace esphome::datetime {
static const char *const TAG = "datetime.time_entity";
@@ -152,7 +151,6 @@ bool OnTimeTrigger::matches_(const ESPTime &time) const {
}
#endif
} // namespace datetime
} // namespace esphome
} // namespace esphome::datetime
#endif // USE_DATETIME_TIME
+2 -4
View File
@@ -10,8 +10,7 @@
#include "datetime_base.h"
namespace esphome {
namespace datetime {
namespace esphome::datetime {
#define LOG_DATETIME_TIME(prefix, type, obj) \
if ((obj) != nullptr) { \
@@ -125,7 +124,6 @@ class OnTimeTrigger : public Trigger<>, public Component, public Parented<TimeEn
};
#endif
} // namespace datetime
} // namespace esphome
} // namespace esphome::datetime
#endif // USE_DATETIME_TIME
@@ -33,7 +33,7 @@ class DemoAlarmControlPanel : public AlarmControlPanel, public Component {
case ACP_STATE_ARMED_AWAY:
if (this->get_requires_code_to_arm() && call.get_code().has_value()) {
if (call.get_code().value() != "1234") {
this->status_momentary_error("Invalid code", 5000);
this->status_momentary_error("invalid_code", 5000);
return;
}
}
@@ -42,7 +42,7 @@ class DemoAlarmControlPanel : public AlarmControlPanel, public Component {
case ACP_STATE_DISARMED:
if (this->get_requires_code() && call.get_code().has_value()) {
if (call.get_code().value() != "1234") {
this->status_momentary_error("Invalid code", 5000);
this->status_momentary_error("invalid_code", 5000);
return;
}
}
+2 -2
View File
@@ -225,7 +225,7 @@ bool ES8388::set_dac_output(DacOutputLine line) {
optional<DacOutputLine> ES8388::get_dac_power() {
uint8_t dac_power;
if (!this->read_byte(ES8388_DACPOWER, &dac_power)) {
this->status_momentary_warning("Failed to read ES8388_DACPOWER");
this->status_momentary_warning("dacpower_read");
return {};
}
switch (dac_power) {
@@ -268,7 +268,7 @@ bool ES8388::set_adc_input_mic(AdcInputMicLine line) {
optional<AdcInputMicLine> ES8388::get_mic_input() {
uint8_t mic_input;
if (!this->read_byte(ES8388_ADCCONTROL2, &mic_input)) {
this->status_momentary_warning("Failed to read ES8388_ADCCONTROL2");
this->status_momentary_warning("adccontrol2_read");
return {};
}
switch (mic_input) {
@@ -373,7 +373,9 @@ void ESP32BLETracker::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_i
void ESP32BLETracker::set_scanner_state_(ScannerState state) {
this->scanner_state_ = state;
this->scanner_state_callbacks_.call(state);
for (auto *listener : this->scanner_state_listeners_) {
listener->on_scanner_state(state);
}
}
#ifdef USE_ESP32_BLE_DEVICE
@@ -180,6 +180,16 @@ enum class ScannerState {
STOPPING,
};
/** Listener interface for BLE scanner state changes.
*
* Components can implement this interface to receive scanner state updates
* without the overhead of std::function callbacks.
*/
class BLEScannerStateListener {
public:
virtual void on_scanner_state(ScannerState state) = 0;
};
// Helper function to convert ClientState to string
const char *client_state_to_string(ClientState state);
@@ -264,8 +274,9 @@ class ESP32BLETracker : public Component,
void gap_scan_event_handler(const BLEScanResult &scan_result) override;
void ble_before_disabled_event_handler() override;
void add_scanner_state_callback(std::function<void(ScannerState)> &&callback) {
this->scanner_state_callbacks_.add(std::move(callback));
/// Add a listener for scanner state changes
void add_scanner_state_listener(BLEScannerStateListener *listener) {
this->scanner_state_listeners_.push_back(listener);
}
ScannerState get_scanner_state() const { return this->scanner_state_; }
@@ -322,14 +333,14 @@ class ESP32BLETracker : public Component,
return counts;
}
// Group 1: Large objects (12+ bytes) - vectors and callback manager
// Group 1: Large objects (12+ bytes) - vectors
#ifdef ESPHOME_ESP32_BLE_TRACKER_LISTENER_COUNT
StaticVector<ESPBTDeviceListener *, ESPHOME_ESP32_BLE_TRACKER_LISTENER_COUNT> listeners_;
#endif
#ifdef ESPHOME_ESP32_BLE_TRACKER_CLIENT_COUNT
StaticVector<ESPBTClient *, ESPHOME_ESP32_BLE_TRACKER_CLIENT_COUNT> clients_;
#endif
CallbackManager<void(ScannerState)> scanner_state_callbacks_;
std::vector<BLEScannerStateListener *> scanner_state_listeners_;
#ifdef USE_ESP32_BLE_DEVICE
/// Vector of addresses that have already been printed in print_bt_device_info
std::vector<uint64_t> already_discovered_;
+3
View File
@@ -10,6 +10,7 @@ from esphome.components.esp32.const import (
VARIANT_ESP32C3,
VARIANT_ESP32C6,
VARIANT_ESP32H2,
VARIANT_ESP32P4,
VARIANT_ESP32S2,
VARIANT_ESP32S3,
)
@@ -59,6 +60,7 @@ CAN_SPEEDS_ESP32_S3 = {**CAN_SPEEDS_ESP32_S2}
CAN_SPEEDS_ESP32_C3 = {**CAN_SPEEDS_ESP32_S2}
CAN_SPEEDS_ESP32_C6 = {**CAN_SPEEDS_ESP32_S2}
CAN_SPEEDS_ESP32_H2 = {**CAN_SPEEDS_ESP32_S2}
CAN_SPEEDS_ESP32_P4 = {**CAN_SPEEDS_ESP32_S2}
CAN_SPEEDS = {
VARIANT_ESP32: CAN_SPEEDS_ESP32,
@@ -67,6 +69,7 @@ CAN_SPEEDS = {
VARIANT_ESP32C3: CAN_SPEEDS_ESP32_C3,
VARIANT_ESP32C6: CAN_SPEEDS_ESP32_C6,
VARIANT_ESP32H2: CAN_SPEEDS_ESP32_H2,
VARIANT_ESP32P4: CAN_SPEEDS_ESP32_P4,
}
+1 -1
View File
@@ -17,7 +17,7 @@ static const char *const TAG = "esp32_can";
static bool get_bitrate(canbus::CanSpeed bitrate, twai_timing_config_t *t_config) {
switch (bitrate) {
#if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32C3) || \
defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32H2)
defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32H2) || defined(USE_ESP32_VARIANT_ESP32P4)
case canbus::CAN_1KBPS:
*t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_1KBITS();
return true;
+13 -10
View File
@@ -8,11 +8,13 @@ namespace esphome::esp8266 {
static const char *const TAG = "esp8266";
static int flags_to_mode(gpio::Flags flags, uint8_t pin) {
if (flags == gpio::FLAG_INPUT) { // NOLINT(bugprone-branch-clone)
return INPUT;
} else if (flags == gpio::FLAG_OUTPUT) {
if (flags == gpio::FLAG_OUTPUT || flags == (gpio::FLAG_OUTPUT | gpio::FLAG_INPUT)) {
return OUTPUT;
} else if (flags == (gpio::FLAG_INPUT | gpio::FLAG_PULLUP)) {
}
if (flags == gpio::FLAG_INPUT) {
return INPUT;
}
if (flags == (gpio::FLAG_INPUT | gpio::FLAG_PULLUP)) {
if (pin == 16) {
// GPIO16 doesn't have a pullup, so pinMode would fail.
// However, sometimes this method is called with pullup mode anyway
@@ -21,13 +23,14 @@ static int flags_to_mode(gpio::Flags flags, uint8_t pin) {
return INPUT;
}
return INPUT_PULLUP;
} else if (flags == (gpio::FLAG_INPUT | gpio::FLAG_PULLDOWN)) {
return INPUT_PULLDOWN_16;
} else if (flags == (gpio::FLAG_OUTPUT | gpio::FLAG_OPEN_DRAIN)) {
return OUTPUT_OPEN_DRAIN;
} else {
return 0;
}
if (flags == (gpio::FLAG_INPUT | gpio::FLAG_PULLDOWN)) {
return INPUT_PULLDOWN_16;
}
if (flags == (gpio::FLAG_OUTPUT | gpio::FLAG_OPEN_DRAIN)) {
return OUTPUT_OPEN_DRAIN;
}
return INPUT;
}
struct ISRPinArg {
@@ -401,7 +401,7 @@ error:
this->backend_->abort();
}
this->status_momentary_error("onerror", 5000);
this->status_momentary_error("err", 5000);
#ifdef USE_OTA_STATE_CALLBACK
this->state_callback_.call(ota::OTA_ERROR, 0.0f, static_cast<uint8_t>(error_code));
#endif
@@ -10,6 +10,7 @@
#include <esp_event.h>
#include <esp_mac.h>
#include <esp_netif.h>
#include <esp_now.h>
#include <esp_random.h>
#include <esp_wifi.h>
@@ -157,6 +158,12 @@ bool ESPNowComponent::is_wifi_enabled() {
}
void ESPNowComponent::setup() {
#ifndef USE_WIFI
// Initialize LwIP stack for wake_loop_threadsafe() socket support
// When WiFi component is present, it handles esp_netif_init()
ESP_ERROR_CHECK(esp_netif_init());
#endif
if (this->enable_on_boot_) {
this->enable_();
} else {
+5 -5
View File
@@ -189,7 +189,7 @@ template<typename... Ts> class EnrollmentAction : public Action<Ts...>, public P
TEMPLATABLE_VALUE(std::string, name)
TEMPLATABLE_VALUE(uint8_t, direction)
void play(Ts... x) override {
void play(const Ts &...x) override {
auto name = this->name_.value(x...);
auto direction = (HlkFm22xFaceDirection) this->direction_.value(x...);
this->parent_->enroll_face(name, direction);
@@ -200,7 +200,7 @@ template<typename... Ts> class DeleteAction : public Action<Ts...>, public Paren
public:
TEMPLATABLE_VALUE(int16_t, face_id)
void play(Ts... x) override {
void play(const Ts &...x) override {
auto face_id = this->face_id_.value(x...);
this->parent_->delete_face(face_id);
}
@@ -208,17 +208,17 @@ template<typename... Ts> class DeleteAction : public Action<Ts...>, public Paren
template<typename... Ts> class DeleteAllAction : public Action<Ts...>, public Parented<HlkFm22xComponent> {
public:
void play(Ts... x) override { this->parent_->delete_all_faces(); }
void play(const Ts &...x) override { this->parent_->delete_all_faces(); }
};
template<typename... Ts> class ScanAction : public Action<Ts...>, public Parented<HlkFm22xComponent> {
public:
void play(Ts... x) override { this->parent_->scan_face(); }
void play(const Ts &...x) override { this->parent_->scan_face(); }
};
template<typename... Ts> class ResetAction : public Action<Ts...>, public Parented<HlkFm22xComponent> {
public:
void play(Ts... x) override { this->parent_->reset(); }
void play(const Ts &...x) override { this->parent_->reset(); }
};
} // namespace esphome::hlk_fm22x
+6 -6
View File
@@ -74,11 +74,11 @@ static const LogString *color_mode_to_human(ColorMode color_mode) {
// Helper to log percentage values
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_DEBUG
static void log_percent(const char *name, const char *param, float value) {
ESP_LOGD(TAG, " %s: %.0f%%", param, value * 100.0f);
static void log_percent(const LogString *param, float value) {
ESP_LOGD(TAG, " %s: %.0f%%", LOG_STR_ARG(param), value * 100.0f);
}
#else
#define log_percent(name, param, value)
#define log_percent(param, value)
#endif
void LightCall::perform() {
@@ -104,11 +104,11 @@ void LightCall::perform() {
}
if (this->has_brightness()) {
log_percent(name, "Brightness", v.get_brightness());
log_percent(LOG_STR("Brightness"), v.get_brightness());
}
if (this->has_color_brightness()) {
log_percent(name, "Color brightness", v.get_color_brightness());
log_percent(LOG_STR("Color brightness"), v.get_color_brightness());
}
if (this->has_red() || this->has_green() || this->has_blue()) {
ESP_LOGD(TAG, " Red: %.0f%%, Green: %.0f%%, Blue: %.0f%%", v.get_red() * 100.0f, v.get_green() * 100.0f,
@@ -116,7 +116,7 @@ void LightCall::perform() {
}
if (this->has_white()) {
log_percent(name, "White", v.get_white());
log_percent(LOG_STR("White"), v.get_white());
}
if (this->has_color_temperature()) {
ESP_LOGD(TAG, " Color temperature: %.1f mireds", v.get_color_temperature());
+22 -23
View File
@@ -7,30 +7,29 @@ namespace esphome::light {
// See https://www.home-assistant.io/integrations/light.mqtt/#json-schema for documentation on the schema
// Lookup table for color mode strings
static constexpr const char *get_color_mode_json_str(ColorMode mode) {
switch (mode) {
case ColorMode::ON_OFF:
return "onoff";
case ColorMode::BRIGHTNESS:
return "brightness";
case ColorMode::WHITE:
return "white"; // not supported by HA in MQTT
case ColorMode::COLOR_TEMPERATURE:
return "color_temp";
case ColorMode::COLD_WARM_WHITE:
return "cwww"; // not supported by HA
case ColorMode::RGB:
return "rgb";
case ColorMode::RGB_WHITE:
return "rgbw";
case ColorMode::RGB_COLOR_TEMPERATURE:
return "rgbct"; // not supported by HA
case ColorMode::RGB_COLD_WARM_WHITE:
return "rgbww";
default:
return nullptr;
// Get JSON string for color mode using linear search (avoids large switch jump table)
static const char *get_color_mode_json_str(ColorMode mode) {
// Parallel arrays: mode values and their corresponding strings
// Uses less RAM than a switch jump table on sparse enum values
static constexpr ColorMode MODES[] = {
ColorMode::ON_OFF,
ColorMode::BRIGHTNESS,
ColorMode::WHITE,
ColorMode::COLOR_TEMPERATURE,
ColorMode::COLD_WARM_WHITE,
ColorMode::RGB,
ColorMode::RGB_WHITE,
ColorMode::RGB_COLOR_TEMPERATURE,
ColorMode::RGB_COLD_WARM_WHITE,
};
static constexpr const char *STRINGS[] = {
"onoff", "brightness", "white", "color_temp", "cwww", "rgb", "rgbw", "rgbct", "rgbww",
};
for (size_t i = 0; i < sizeof(MODES) / sizeof(MODES[0]); i++) {
if (MODES[i] == mode)
return STRINGS[i];
}
return nullptr;
}
void LightJSONSchema::dump_json(LightState &state, JsonObject root) {
+5 -13
View File
@@ -49,26 +49,18 @@ template<typename... Ts> class LockCondition : public Condition<Ts...> {
bool state_;
};
class LockLockTrigger : public Trigger<> {
template<LockState State> class LockStateTrigger : public Trigger<> {
public:
LockLockTrigger(Lock *a_lock) {
explicit LockStateTrigger(Lock *a_lock) {
a_lock->add_on_state_callback([this, a_lock]() {
if (a_lock->state == LockState::LOCK_STATE_LOCKED) {
if (a_lock->state == State) {
this->trigger();
}
});
}
};
class LockUnlockTrigger : public Trigger<> {
public:
LockUnlockTrigger(Lock *a_lock) {
a_lock->add_on_state_callback([this, a_lock]() {
if (a_lock->state == LockState::LOCK_STATE_UNLOCKED) {
this->trigger();
}
});
}
};
using LockLockTrigger = LockStateTrigger<LockState::LOCK_STATE_LOCKED>;
using LockUnlockTrigger = LockStateTrigger<LockState::LOCK_STATE_UNLOCKED>;
} // namespace esphome::lock
+23
View File
@@ -406,6 +406,8 @@ async def to_code(config):
conf,
)
CORE.add_job(final_step)
def validate_printf(value):
# https://stackoverflow.com/questions/30011379/how-can-i-parse-a-c-format-string-in-python
@@ -506,3 +508,24 @@ FILTER_SOURCE_FILES = filter_source_files_from_platform(
},
}
)
# Keys for CORE.data storage
DOMAIN = "logger"
KEY_LEVEL_LISTENERS = "level_listeners"
def request_logger_level_listeners() -> None:
"""Request that logger level listeners be compiled in.
Components that need to be notified about log level changes should call this
function during their code generation. This enables the add_level_listener()
method and compiles in the listener vector.
"""
CORE.data.setdefault(DOMAIN, {})[KEY_LEVEL_LISTENERS] = True
@coroutine_with_priority(CoroPriority.FINAL)
async def final_step():
"""Final code generation step to configure optional logger features."""
if CORE.data.get(DOMAIN, {}).get(KEY_LEVEL_LISTENERS, False):
cg.add_define("USE_LOGGER_LEVEL_LISTENERS")
+9 -7
View File
@@ -140,8 +140,9 @@ void Logger::log_vprintf_(uint8_t level, const char *tag, int line, const __Flas
uint16_t msg_length =
this->tx_buffer_at_ - msg_start; // Don't subtract 1 - tx_buffer_at_ is already at the null terminator position
// Callbacks get message first (before console write)
this->log_callback_.call(level, tag, this->tx_buffer_ + msg_start, msg_length);
// Listeners get message first (before console write)
for (auto *listener : this->log_listeners_)
listener->on_log(level, tag, this->tx_buffer_ + msg_start, msg_length);
// Write to console starting at the msg_start
this->write_tx_buffer_to_console_(msg_start, &msg_length);
@@ -203,7 +204,8 @@ void Logger::process_messages_() {
this->write_footer_to_buffer_(this->tx_buffer_, &this->tx_buffer_at_, this->tx_buffer_size_);
this->tx_buffer_[this->tx_buffer_at_] = '\0';
size_t msg_len = this->tx_buffer_at_; // We already know the length from tx_buffer_at_
this->log_callback_.call(message->level, message->tag, this->tx_buffer_, msg_len);
for (auto *listener : this->log_listeners_)
listener->on_log(message->level, message->tag, this->tx_buffer_, msg_len);
// At this point all the data we need from message has been transferred to the tx_buffer
// so we can release the message to allow other tasks to use it as soon as possible.
this->log_buffer_->release_message_main_loop(received_token);
@@ -231,9 +233,6 @@ void Logger::set_log_level(const char *tag, uint8_t log_level) { this->log_level
UARTSelection Logger::get_uart() const { return this->uart_; }
#endif
void Logger::add_on_log_callback(std::function<void(uint8_t, const char *, const char *, size_t)> &&callback) {
this->log_callback_.add(std::move(callback));
}
float Logger::get_setup_priority() const { return setup_priority::BUS + 500.0f; }
#ifdef USE_STORE_LOG_STR_IN_FLASH
@@ -289,7 +288,10 @@ void Logger::set_log_level(uint8_t level) {
ESP_LOGW(TAG, "Cannot set log level higher than pre-compiled %s", LOG_STR_ARG(LOG_LEVELS[ESPHOME_LOG_LEVEL]));
}
this->current_level_ = level;
this->level_callback_.call(level);
#ifdef USE_LOGGER_LEVEL_LISTENERS
for (auto *listener : this->level_listeners_)
listener->on_log_level_change(level);
#endif
}
Logger *global_logger = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
+68 -17
View File
@@ -36,6 +36,52 @@ struct device;
namespace esphome::logger {
/** Interface for receiving log messages without std::function overhead.
*
* Components can implement this interface instead of using lambdas with std::function
* to reduce flash usage from std::function type erasure machinery.
*
* Usage:
* class MyComponent : public Component, public LogListener {
* public:
* void setup() override {
* if (logger::global_logger != nullptr)
* logger::global_logger->add_log_listener(this);
* }
* void on_log(uint8_t level, const char *tag, const char *message, size_t message_len) override {
* // Handle log message
* }
* };
*/
class LogListener {
public:
virtual void on_log(uint8_t level, const char *tag, const char *message, size_t message_len) = 0;
};
#ifdef USE_LOGGER_LEVEL_LISTENERS
/** Interface for receiving log level changes without std::function overhead.
*
* Components can implement this interface instead of using lambdas with std::function
* to reduce flash usage from std::function type erasure machinery.
*
* Usage:
* class MyComponent : public Component, public LoggerLevelListener {
* public:
* void setup() override {
* if (logger::global_logger != nullptr)
* logger::global_logger->add_logger_level_listener(this);
* }
* void on_log_level_change(uint8_t level) override {
* // Handle log level change
* }
* };
*/
class LoggerLevelListener {
public:
virtual void on_log_level_change(uint8_t level) = 0;
};
#endif
#ifdef USE_LOGGER_RUNTIME_TAG_LEVELS
// Comparison function for const char* keys in log_levels_ map
struct CStrCompare {
@@ -168,11 +214,13 @@ class Logger : public Component {
inline uint8_t level_for(const char *tag);
/// Register a callback that will be called for every log message sent
void add_on_log_callback(std::function<void(uint8_t, const char *, const char *, size_t)> &&callback);
/// Register a log listener to receive log messages
void add_log_listener(LogListener *listener) { this->log_listeners_.push_back(listener); }
// add a listener for log level changes
void add_listener(std::function<void(uint8_t)> &&callback) { this->level_callback_.add(std::move(callback)); }
#ifdef USE_LOGGER_LEVEL_LISTENERS
/// Register a listener for log level changes
void add_level_listener(LoggerLevelListener *listener) { this->level_listeners_.push_back(listener); }
#endif
float get_setup_priority() const override;
@@ -240,7 +288,7 @@ class Logger : public Component {
}
}
// Helper to format and send a log message to both console and callbacks
// Helper to format and send a log message to both console and listeners
inline void HOT log_message_to_buffer_and_send_(uint8_t level, const char *tag, int line, const char *format,
va_list args) {
// Format to tx_buffer and prepare for output
@@ -248,8 +296,9 @@ class Logger : public Component {
this->format_log_to_buffer_with_terminator_(level, tag, line, format, args, this->tx_buffer_, &this->tx_buffer_at_,
this->tx_buffer_size_);
// Callbacks get message WITHOUT newline (for API/MQTT/syslog)
this->log_callback_.call(level, tag, this->tx_buffer_, this->tx_buffer_at_);
// Listeners get message WITHOUT newline (for API/MQTT/syslog)
for (auto *listener : this->log_listeners_)
listener->on_log(level, tag, this->tx_buffer_, this->tx_buffer_at_);
// Console gets message WITH newline (if platform needs it)
this->write_tx_buffer_to_console_();
@@ -301,8 +350,10 @@ class Logger : public Component {
#ifdef USE_LOGGER_RUNTIME_TAG_LEVELS
std::map<const char *, uint8_t, CStrCompare> log_levels_{};
#endif
CallbackManager<void(uint8_t, const char *, const char *, size_t)> log_callback_{};
CallbackManager<void(uint8_t)> level_callback_{};
std::vector<LogListener *> log_listeners_; // Log message listeners (API, MQTT, syslog, etc.)
#ifdef USE_LOGGER_LEVEL_LISTENERS
std::vector<LoggerLevelListener *> level_listeners_; // Log level change listeners
#endif
#ifdef USE_ESPHOME_TASK_LOG_BUFFER
std::unique_ptr<logger::TaskLogBuffer> log_buffer_; // Will be initialized with init_log_buffer
#endif
@@ -496,15 +547,15 @@ class Logger : public Component {
};
extern Logger *global_logger; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
class LoggerMessageTrigger : public Trigger<uint8_t, const char *, const char *> {
class LoggerMessageTrigger : public Trigger<uint8_t, const char *, const char *>, public LogListener {
public:
explicit LoggerMessageTrigger(Logger *parent, uint8_t level) {
this->level_ = level;
parent->add_on_log_callback([this](uint8_t level, const char *tag, const char *message, size_t message_len) {
if (level <= this->level_) {
this->trigger(level, tag, message);
}
});
explicit LoggerMessageTrigger(Logger *parent, uint8_t level) : level_(level) { parent->add_log_listener(this); }
void on_log(uint8_t level, const char *tag, const char *message, size_t message_len) override {
(void) message_len;
if (level <= this->level_) {
this->trigger(level, tag, message);
}
}
protected:
+8 -1
View File
@@ -5,7 +5,13 @@ from esphome.const import CONF_LEVEL, CONF_LOGGER, ENTITY_CATEGORY_CONFIG, ICON_
from esphome.core import CORE
from esphome.cpp_helpers import register_component, register_parented
from .. import CONF_LOGGER_ID, LOG_LEVELS, Logger, logger_ns
from .. import (
CONF_LOGGER_ID,
LOG_LEVELS,
Logger,
logger_ns,
request_logger_level_listeners,
)
CODEOWNERS = ["@clydebarrow"]
@@ -21,6 +27,7 @@ CONFIG_SCHEMA = select.select_schema(
async def to_code(config):
request_logger_level_listeners()
parent = await cg.get_variable(config[CONF_LOGGER_ID])
levels = list(LOG_LEVELS)
index = levels.index(CORE.data[CONF_LOGGER][CONF_LEVEL])
@@ -2,7 +2,7 @@
namespace esphome::logger {
void LoggerLevelSelect::publish_state(int level) {
void LoggerLevelSelect::on_log_level_change(uint8_t level) {
auto index = level_to_index(level);
if (!this->has_index(index))
return;
@@ -10,8 +10,8 @@ void LoggerLevelSelect::publish_state(int level) {
}
void LoggerLevelSelect::setup() {
this->parent_->add_listener([this](int level) { this->publish_state(level); });
this->publish_state(this->parent_->get_log_level());
this->parent_->add_level_listener(this);
this->on_log_level_change(this->parent_->get_log_level());
}
void LoggerLevelSelect::control(size_t index) { this->parent_->set_log_level(index_to_level(index)); }
@@ -5,12 +5,17 @@
#include "esphome/components/logger/logger.h"
namespace esphome::logger {
class LoggerLevelSelect : public Component, public select::Select, public Parented<Logger> {
class LoggerLevelSelect final : public Component,
public select::Select,
public Parented<Logger>,
public LoggerLevelListener {
public:
void publish_state(int level);
void setup() override;
void control(size_t index) override;
// LoggerLevelListener interface
void on_log_level_change(uint8_t level) override;
protected:
// Convert log level to option index (skip CONFIG at level 4)
static uint8_t level_to_index(uint8_t level) { return (level > ESPHOME_LOG_LEVEL_CONFIG) ? level - 1 : level; }
+1 -1
View File
@@ -165,7 +165,7 @@ async def to_code(config):
cg.add_library("LEAmDNS", None)
if CORE.using_esp_idf:
add_idf_component(name="espressif/mdns", ref="1.8.2")
add_idf_component(name="espressif/mdns", ref="1.9.1")
cg.add_define("USE_MDNS")
@@ -298,8 +298,7 @@ void MicroWakeWord::loop() {
// uses floating point operations.
if (!FrontendPopulateState(&this->frontend_config_, &this->frontend_state_,
this->microphone_source_->get_audio_stream_info().get_sample_rate())) {
this->status_momentary_error(
"Failed to allocate buffers for spectrogram feature processor, attempting again in 1 second", 1000);
this->status_momentary_error("frontend_alloc", 1000);
return;
}
@@ -308,7 +307,7 @@ void MicroWakeWord::loop() {
if (this->inference_task_handle_ == nullptr) {
FrontendFreeStateContents(&this->frontend_state_); // Deallocate frontend state
this->status_momentary_error("Task failed to start, attempting again in 1 second", 1000);
this->status_momentary_error("task_start", 1000);
}
}
break;
@@ -1,7 +1,6 @@
#include "micronova_button.h"
namespace esphome {
namespace micronova {
namespace esphome::micronova {
void MicroNovaButton::press_action() {
switch (this->get_function()) {
@@ -14,5 +13,4 @@ void MicroNovaButton::press_action() {
this->micronova_->update();
}
} // namespace micronova
} // namespace esphome
} // namespace esphome::micronova
@@ -4,8 +4,7 @@
#include "esphome/core/component.h"
#include "esphome/components/button/button.h"
namespace esphome {
namespace micronova {
namespace esphome::micronova {
class MicroNovaButton : public Component, public button::Button, public MicroNovaButtonListener {
public:
@@ -19,5 +18,4 @@ class MicroNovaButton : public Component, public button::Button, public MicroNov
void press_action() override;
};
} // namespace micronova
} // namespace esphome
} // namespace esphome::micronova
+2 -4
View File
@@ -1,8 +1,7 @@
#include "micronova.h"
#include "esphome/core/log.h"
namespace esphome {
namespace micronova {
namespace esphome::micronova {
void MicroNova::setup() {
if (this->enable_rx_pin_ != nullptr) {
@@ -144,5 +143,4 @@ void MicroNova::write_address(uint8_t location, uint8_t address, uint8_t data) {
}
}
} // namespace micronova
} // namespace esphome
} // namespace esphome::micronova
+2 -4
View File
@@ -8,8 +8,7 @@
#include <vector>
namespace esphome {
namespace micronova {
namespace esphome::micronova {
static const char *const TAG = "micronova";
static const int STOVE_REPLY_DELAY = 60;
@@ -160,5 +159,4 @@ class MicroNova : public PollingComponent, public uart::UARTDevice {
MicroNovaSwitchListener *stove_switch_{nullptr};
};
} // namespace micronova
} // namespace esphome
} // namespace esphome::micronova
@@ -1,7 +1,6 @@
#include "micronova_number.h"
namespace esphome {
namespace micronova {
namespace esphome::micronova {
void MicroNovaNumber::process_value_from_stove(int value_from_stove) {
float new_sensor_value = 0;
@@ -41,5 +40,4 @@ void MicroNovaNumber::control(float value) {
this->micronova_->update();
}
} // namespace micronova
} // namespace esphome
} // namespace esphome::micronova
@@ -3,8 +3,7 @@
#include "esphome/components/micronova/micronova.h"
#include "esphome/components/number/number.h"
namespace esphome {
namespace micronova {
namespace esphome::micronova {
class MicroNovaNumber : public number::Number, public MicroNovaSensorListener {
public:
@@ -24,5 +23,4 @@ class MicroNovaNumber : public number::Number, public MicroNovaSensorListener {
uint8_t memory_write_location_ = 0;
};
} // namespace micronova
} // namespace esphome
} // namespace esphome::micronova
@@ -1,7 +1,6 @@
#include "micronova_sensor.h"
namespace esphome {
namespace micronova {
namespace esphome::micronova {
void MicroNovaSensor::process_value_from_stove(int value_from_stove) {
if (value_from_stove == -1) {
@@ -31,5 +30,4 @@ void MicroNovaSensor::process_value_from_stove(int value_from_stove) {
this->publish_state(new_sensor_value);
}
} // namespace micronova
} // namespace esphome
} // namespace esphome::micronova
@@ -3,8 +3,7 @@
#include "esphome/components/micronova/micronova.h"
#include "esphome/components/sensor/sensor.h"
namespace esphome {
namespace micronova {
namespace esphome::micronova {
class MicroNovaSensor : public sensor::Sensor, public MicroNovaSensorListener {
public:
@@ -23,5 +22,4 @@ class MicroNovaSensor : public sensor::Sensor, public MicroNovaSensorListener {
int fan_speed_offset_ = 0;
};
} // namespace micronova
} // namespace esphome
} // namespace esphome::micronova
@@ -1,7 +1,6 @@
#include "micronova_switch.h"
namespace esphome {
namespace micronova {
namespace esphome::micronova {
void MicroNovaSwitch::write_state(bool state) {
switch (this->get_function()) {
@@ -31,5 +30,4 @@ void MicroNovaSwitch::write_state(bool state) {
}
}
} // namespace micronova
} // namespace esphome
} // namespace esphome::micronova
@@ -4,8 +4,7 @@
#include "esphome/core/component.h"
#include "esphome/components/switch/switch.h"
namespace esphome {
namespace micronova {
namespace esphome::micronova {
class MicroNovaSwitch : public Component, public switch_::Switch, public MicroNovaSwitchListener {
public:
@@ -25,5 +24,4 @@ class MicroNovaSwitch : public Component, public switch_::Switch, public MicroNo
void write_state(bool state) override;
};
} // namespace micronova
} // namespace esphome
} // namespace esphome::micronova
@@ -1,7 +1,6 @@
#include "micronova_text_sensor.h"
namespace esphome {
namespace micronova {
namespace esphome::micronova {
void MicroNovaTextSensor::process_value_from_stove(int value_from_stove) {
if (value_from_stove == -1) {
@@ -27,5 +26,4 @@ void MicroNovaTextSensor::process_value_from_stove(int value_from_stove) {
}
}
} // namespace micronova
} // namespace esphome
} // namespace esphome::micronova
@@ -3,8 +3,7 @@
#include "esphome/components/micronova/micronova.h"
#include "esphome/components/text_sensor/text_sensor.h"
namespace esphome {
namespace micronova {
namespace esphome::micronova {
class MicroNovaTextSensor : public text_sensor::TextSensor, public MicroNovaSensorListener {
public:
@@ -16,5 +15,4 @@ class MicroNovaTextSensor : public text_sensor::TextSensor, public MicroNovaSens
void process_value_from_stove(int value_from_stove) override;
};
} // namespace micronova
} // namespace esphome
} // namespace esphome::micronova
+105
View File
@@ -484,4 +484,109 @@ DriverChip(
),
)
DriverChip(
"JC4827W543",
height=272,
width=480,
offset_height=0,
offset_width=0,
cs_pin={CONF_NUMBER: 45, CONF_IGNORE_STRAPPING_WARNING: True},
invert_colors=True,
color_order=MODE_RGB,
bus_mode=TYPE_QUAD,
data_rate="20MHz",
initsequence=(
(0xFF, 0xA5),
(0x41, 0x03),
(0x44, 0x15),
(0x45, 0x15),
(0x7D, 0x03),
(0xC1, 0xBB),
(0xC2, 0x05),
(0xC3, 0x10),
(0xC6, 0x3E),
(0xC7, 0x25),
(0xC8, 0x11),
(0x7A, 0x5F),
(0x6F, 0x44),
(0x78, 0x70),
(0xC9, 0x00),
(0x67, 0x21),
(0x51, 0x0A),
(0x52, 0x76),
(0x53, 0x0A),
(0x54, 0x76),
(0x46, 0x0A),
(0x47, 0x2A),
(0x48, 0x0A),
(0x49, 0x1A),
(0x56, 0x43),
(0x57, 0x42),
(0x58, 0x3C),
(0x59, 0x64),
(0x5A, 0x41),
(0x5B, 0x3C),
(0x5C, 0x02),
(0x5D, 0x3C),
(0x5E, 0x1F),
(0x60, 0x80),
(0x61, 0x3F),
(0x62, 0x21),
(0x63, 0x07),
(0x64, 0xE0),
(0x65, 0x02),
(0xCA, 0x20),
(0xCB, 0x52),
(0xCC, 0x10),
(0xCD, 0x42),
(0xD0, 0x20),
(0xD1, 0x52),
(0xD2, 0x10),
(0xD3, 0x42),
(0xD4, 0x0A),
(0xD5, 0x32),
(0x80, 0x00),
(0xA0, 0x00),
(0x81, 0x07),
(0xA1, 0x06),
(0x82, 0x02),
(0xA2, 0x01),
(0x86, 0x11),
(0xA6, 0x10),
(0x87, 0x27),
(0xA7, 0x27),
(0x83, 0x37),
(0xA3, 0x37),
(0x84, 0x35),
(0xA4, 0x35),
(0x85, 0x3F),
(0xA5, 0x3F),
(0x88, 0x0B),
(0xA8, 0x0B),
(0x89, 0x14),
(0xA9, 0x14),
(0x8A, 0x1A),
(0xAA, 0x1A),
(0x8B, 0x0A),
(0xAB, 0x0A),
(0x8C, 0x14),
(0xAC, 0x08),
(0x8D, 0x17),
(0xAD, 0x07),
(0x8E, 0x16),
(0xAE, 0x06),
(0x8F, 0x1B),
(0xAF, 0x07),
(0x90, 0x04),
(0xB0, 0x04),
(0x91, 0x0A),
(0xB1, 0x0A),
(0x92, 0x16),
(0xB2, 0x15),
(0xFF, 0x00),
(0x11, 0x00),
(0x29, 0x00),
),
)
models = {}
@@ -116,7 +116,7 @@ bool MopekaProCheck::parse_device(const esp32_ble_tracker::ESPBTDevice &device)
// Get temperature of sensor
if (this->temperature_ != nullptr) {
uint8_t temp_in_c = this->parse_temperature_(manu_data.data);
int8_t temp_in_c = this->parse_temperature_(manu_data.data);
this->temperature_->publish_state(temp_in_c);
}
@@ -145,7 +145,7 @@ uint32_t MopekaProCheck::parse_distance_(const std::vector<uint8_t> &message) {
(MOPEKA_LPG_COEF[0] + MOPEKA_LPG_COEF[1] * raw_t + MOPEKA_LPG_COEF[2] * raw_t * raw_t));
}
uint8_t MopekaProCheck::parse_temperature_(const std::vector<uint8_t> &message) { return (message[2] & 0x7F) - 40; }
int8_t MopekaProCheck::parse_temperature_(const std::vector<uint8_t> &message) { return (message[2] & 0x7F) - 40; }
SensorReadQuality MopekaProCheck::parse_read_quality_(const std::vector<uint8_t> &message) {
// Since a 8 bit value is being shifted and truncated to 2 bits all possible values are defined as enumeration
@@ -61,7 +61,7 @@ class MopekaProCheck : public Component, public esp32_ble_tracker::ESPBTDeviceLi
uint8_t parse_battery_level_(const std::vector<uint8_t> &message);
uint32_t parse_distance_(const std::vector<uint8_t> &message);
uint8_t parse_temperature_(const std::vector<uint8_t> &message);
int8_t parse_temperature_(const std::vector<uint8_t> &message);
SensorReadQuality parse_read_quality_(const std::vector<uint8_t> &message);
};
+2 -1
View File
@@ -55,6 +55,7 @@ from esphome.const import (
PLATFORM_BK72XX,
PLATFORM_ESP32,
PLATFORM_ESP8266,
PLATFORM_RTL87XX,
PlatformFramework,
)
from esphome.core import CORE, CoroPriority, coroutine_with_priority
@@ -316,7 +317,7 @@ CONFIG_SCHEMA = cv.All(
}
),
validate_config,
cv.only_on([PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_BK72XX]),
cv.only_on([PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_BK72XX, PLATFORM_RTL87XX]),
_consume_mqtt_sockets,
)
+13 -9
View File
@@ -57,15 +57,7 @@ void MQTTClientComponent::setup() {
});
#ifdef USE_LOGGER
if (this->is_log_message_enabled() && logger::global_logger != nullptr) {
logger::global_logger->add_on_log_callback(
[this](int level, const char *tag, const char *message, size_t message_len) {
if (level <= this->log_level_ && this->is_connected()) {
this->publish({.topic = this->log_message_.topic,
.payload = std::string(message, message_len),
.qos = this->log_message_.qos,
.retain = this->log_message_.retain});
}
});
logger::global_logger->add_log_listener(this);
}
#endif
@@ -148,6 +140,18 @@ void MQTTClientComponent::send_device_info_() {
// NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks)
}
#ifdef USE_LOGGER
void MQTTClientComponent::on_log(uint8_t level, const char *tag, const char *message, size_t message_len) {
(void) tag;
if (level <= this->log_level_ && this->is_connected()) {
this->publish({.topic = this->log_message_.topic,
.payload = std::string(message, message_len),
.qos = this->log_message_.qos,
.retain = this->log_message_.retain});
}
}
#endif
void MQTTClientComponent::dump_config() {
ESP_LOGCONFIG(TAG,
"MQTT:\n"
+13 -1
View File
@@ -10,6 +10,9 @@
#include "esphome/core/component.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#ifdef USE_LOGGER
#include "esphome/components/logger/logger.h"
#endif
#if defined(USE_ESP32)
#include "mqtt_backend_esp32.h"
#elif defined(USE_ESP8266)
@@ -97,7 +100,12 @@ enum MQTTClientState {
class MQTTComponent;
class MQTTClientComponent : public Component {
class MQTTClientComponent : public Component
#ifdef USE_LOGGER
,
public logger::LogListener
#endif
{
public:
MQTTClientComponent();
@@ -238,6 +246,10 @@ class MQTTClientComponent : public Component {
/// MQTT client setup priority
float get_setup_priority() const override;
#ifdef USE_LOGGER
void on_log(uint8_t level, const char *tag, const char *message, size_t message_len) override;
#endif
void on_message(const std::string &topic, const std::string &payload);
bool can_proceed() override;
+3 -3
View File
@@ -8,7 +8,7 @@ namespace esphome::number {
class Number;
enum NumberOperation {
enum NumberOperation : uint8_t {
NUMBER_OP_NONE,
NUMBER_OP_SET,
NUMBER_OP_INCREMENT,
@@ -38,9 +38,9 @@ class NumberCall {
float limit);
Number *const parent_;
NumberOperation operation_{NUMBER_OP_NONE};
optional<float> value_;
bool cycle_;
NumberOperation operation_{NUMBER_OP_NONE};
bool cycle_{false};
};
} // namespace esphome::number
+2 -1
View File
@@ -1,5 +1,6 @@
import esphome.codegen as cg
from esphome.components.esp32 import (
VARIANT_ESP32C5,
VARIANT_ESP32C6,
VARIANT_ESP32H2,
add_idf_sdkconfig_option,
@@ -152,7 +153,7 @@ CONFIG_SCHEMA = cv.All(
).extend(_CONNECTION_SCHEMA),
cv.has_exactly_one_key(CONF_NETWORK_KEY, CONF_TLV),
cv.only_with_esp_idf,
only_on_variant(supported=[VARIANT_ESP32C6, VARIANT_ESP32H2]),
only_on_variant(supported=[VARIANT_ESP32C5, VARIANT_ESP32C6, VARIANT_ESP32H2]),
_validate,
_require_vfs_select,
)
+9 -3
View File
@@ -2,7 +2,8 @@ import logging
from pathlib import Path
from esphome import git, yaml_util
from esphome.config_helpers import merge_config
from esphome.components.substitutions.jinja import has_jinja
from esphome.config_helpers import Remove, merge_config
import esphome.config_validation as cv
from esphome.const import (
CONF_ESPHOME,
@@ -39,10 +40,15 @@ def valid_package_contents(package_config: dict):
for k, v in package_config.items():
if not isinstance(k, str):
raise cv.Invalid("Package content keys must be strings")
if isinstance(v, (dict, list)):
continue # e.g. script: [] or logger: {level: debug}
if isinstance(v, (dict, list, Remove)):
continue # e.g. script: [], psram: !remove, logger: {level: debug}
if v is None:
continue # e.g. web_server:
if isinstance(v, str) and has_jinja(v):
# e.g: remote package shorthand:
# package_name: github://esphome/repo/file.yaml@${ branch }
continue
raise cv.Invalid("Invalid component content in package definition")
return package_config
+3
View File
@@ -11,6 +11,7 @@ from esphome.components.esp32 import (
get_esp32_variant,
)
from esphome.components.esp32.const import (
VARIANT_ESP32C5,
VARIANT_ESP32P4,
VARIANT_ESP32S2,
VARIANT_ESP32S3,
@@ -55,6 +56,7 @@ SPIRAM_MODES = {
VARIANT_ESP32: (TYPE_QUAD,),
VARIANT_ESP32S2: (TYPE_QUAD,),
VARIANT_ESP32S3: (TYPE_QUAD, TYPE_OCTAL),
VARIANT_ESP32C5: (TYPE_QUAD,),
VARIANT_ESP32P4: (TYPE_HEX,),
}
@@ -63,6 +65,7 @@ SPIRAM_SPEEDS = {
VARIANT_ESP32: (40, 80, 120),
VARIANT_ESP32S2: (40, 80, 120),
VARIANT_ESP32S3: (40, 80, 120),
VARIANT_ESP32C5: (40, 80, 120),
VARIANT_ESP32P4: (20, 100, 200),
}
@@ -114,6 +114,7 @@ CONFIG_SCHEMA = remote_base.validate_triggers(
bk72xx="1000b",
ln882x="1000b",
rtl87xx="1000b",
rp2040="1000b",
): cv.validate_bytes,
cv.Optional(CONF_FILTER, default="50us"): cv.All(
cv.positive_time_period_microseconds,
@@ -213,6 +214,7 @@ FILTER_SOURCE_FILES = filter_source_files_from_platform(
PlatformFramework.BK72XX_ARDUINO,
PlatformFramework.RTL87XX_ARDUINO,
PlatformFramework.LN882X_ARDUINO,
PlatformFramework.RP2040_ARDUINO,
},
}
)
@@ -3,7 +3,7 @@
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#if defined(USE_LIBRETINY) || defined(USE_ESP8266)
#if defined(USE_LIBRETINY) || defined(USE_ESP8266) || defined(USE_RP2040)
namespace esphome {
namespace remote_receiver {

Some files were not shown because too many files have changed in this diff Show More