mirror of
https://github.com/esphome/esphome.git
synced 2025-10-06 20:03:46 +01:00
Merge branch 'logger_runtime_tags' into integration
This commit is contained in:
2
.github/workflows/stale.yml
vendored
2
.github/workflows/stale.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Stale
|
||||
uses: actions/stale@3a9db7e6a41a89f618792c92c0e97cc736e1b13f # v10.0.0
|
||||
uses: actions/stale@5f858e3efba33a5ca4407a664cc011ad407f2008 # v10.1.0
|
||||
with:
|
||||
debug-only: ${{ github.ref != 'refs/heads/dev' }} # Dry-run when not run on dev branch
|
||||
remove-stale-when-updated: true
|
||||
|
@@ -11,7 +11,7 @@ ci:
|
||||
repos:
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: v0.13.2
|
||||
rev: v0.13.3
|
||||
hooks:
|
||||
# Run the linter.
|
||||
- id: ruff
|
||||
|
@@ -14,9 +14,11 @@ from typing import Protocol
|
||||
|
||||
import argcomplete
|
||||
|
||||
# Note: Do not import modules from esphome.components here, as this would
|
||||
# cause them to be loaded before external components are processed, resulting
|
||||
# in the built-in version being used instead of the external component one.
|
||||
from esphome import const, writer, yaml_util
|
||||
import esphome.codegen as cg
|
||||
from esphome.components.mqtt import CONF_DISCOVER_IP
|
||||
from esphome.config import iter_component_configs, read_config, strip_default_ids
|
||||
from esphome.const import (
|
||||
ALLOWED_NAME_CHARS,
|
||||
@@ -240,6 +242,8 @@ def has_ota() -> bool:
|
||||
|
||||
def has_mqtt_ip_lookup() -> bool:
|
||||
"""Check if MQTT is available and IP lookup is supported."""
|
||||
from esphome.components.mqtt import CONF_DISCOVER_IP
|
||||
|
||||
if CONF_MQTT not in CORE.config:
|
||||
return False
|
||||
# Default Enabled
|
||||
|
@@ -95,6 +95,7 @@ DEFAULT = "DEFAULT"
|
||||
|
||||
CONF_INITIAL_LEVEL = "initial_level"
|
||||
CONF_LOGGER_ID = "logger_id"
|
||||
CONF_RUNTIME_TAG_LEVELS = "runtime_tag_levels"
|
||||
CONF_TASK_LOG_BUFFER_SIZE = "task_log_buffer_size"
|
||||
|
||||
UART_SELECTION_ESP32 = {
|
||||
@@ -249,6 +250,7 @@ CONFIG_SCHEMA = cv.All(
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_INITIAL_LEVEL): is_log_level,
|
||||
cv.Optional(CONF_RUNTIME_TAG_LEVELS, default=False): cv.boolean,
|
||||
cv.Optional(CONF_ON_MESSAGE): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LoggerMessageTrigger),
|
||||
@@ -291,8 +293,12 @@ async def to_code(config):
|
||||
)
|
||||
cg.add(log.pre_setup())
|
||||
|
||||
for tag, log_level in config[CONF_LOGS].items():
|
||||
cg.add(log.set_log_level(tag, LOG_LEVELS[log_level]))
|
||||
# Enable runtime tag levels if logs are configured or explicitly enabled
|
||||
logs_config = config[CONF_LOGS]
|
||||
if logs_config or config[CONF_RUNTIME_TAG_LEVELS]:
|
||||
cg.add_define("USE_LOGGER_RUNTIME_TAG_LEVELS")
|
||||
for tag, log_level in logs_config.items():
|
||||
cg.add(log.set_log_level(tag, LOG_LEVELS[log_level]))
|
||||
|
||||
cg.add_define("USE_LOGGER")
|
||||
this_severity = LOG_LEVEL_SEVERITY.index(level)
|
||||
@@ -443,6 +449,7 @@ async def logger_set_level_to_code(config, action_id, template_arg, args):
|
||||
level = LOG_LEVELS[config[CONF_LEVEL]]
|
||||
logger = await cg.get_variable(config[CONF_LOGGER_ID])
|
||||
if tag := config.get(CONF_TAG):
|
||||
cg.add_define("USE_LOGGER_RUNTIME_TAG_LEVELS")
|
||||
text = str(cg.statement(logger.set_log_level(tag, level)))
|
||||
else:
|
||||
text = str(cg.statement(logger.set_log_level(level)))
|
||||
|
@@ -148,9 +148,11 @@ void Logger::log_vprintf_(uint8_t level, const char *tag, int line, const __Flas
|
||||
#endif // USE_STORE_LOG_STR_IN_FLASH
|
||||
|
||||
inline uint8_t Logger::level_for(const char *tag) {
|
||||
#ifdef USE_LOGGER_RUNTIME_TAG_LEVELS
|
||||
auto it = this->log_levels_.find(tag);
|
||||
if (it != this->log_levels_.end())
|
||||
return it->second;
|
||||
#endif
|
||||
return this->current_level_;
|
||||
}
|
||||
|
||||
@@ -220,7 +222,9 @@ void Logger::process_messages_() {
|
||||
}
|
||||
|
||||
void Logger::set_baud_rate(uint32_t baud_rate) { this->baud_rate_ = baud_rate; }
|
||||
void Logger::set_log_level(const std::string &tag, uint8_t log_level) { this->log_levels_[tag] = log_level; }
|
||||
#ifdef USE_LOGGER_RUNTIME_TAG_LEVELS
|
||||
void Logger::set_log_level(const char *tag, uint8_t log_level) { this->log_levels_[tag] = log_level; }
|
||||
#endif
|
||||
|
||||
#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR)
|
||||
UARTSelection Logger::get_uart() const { return this->uart_; }
|
||||
@@ -271,9 +275,11 @@ void Logger::dump_config() {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_LOGGER_RUNTIME_TAG_LEVELS
|
||||
for (auto &it : this->log_levels_) {
|
||||
ESP_LOGCONFIG(TAG, " Level for '%s': %s", it.first.c_str(), LOG_STR_ARG(LOG_LEVELS[it.second]));
|
||||
ESP_LOGCONFIG(TAG, " Level for '%s': %s", it.first, LOG_STR_ARG(LOG_LEVELS[it.second]));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Logger::set_log_level(uint8_t level) {
|
||||
|
@@ -36,6 +36,13 @@ struct device;
|
||||
|
||||
namespace esphome::logger {
|
||||
|
||||
#ifdef USE_LOGGER_RUNTIME_TAG_LEVELS
|
||||
// Comparison function for const char* keys in log_levels_ map
|
||||
struct CStrCompare {
|
||||
bool operator()(const char *a, const char *b) const { return strcmp(a, b) < 0; }
|
||||
};
|
||||
#endif
|
||||
|
||||
// ANSI color code last digit (30-38 range, store only last digit to save RAM)
|
||||
static constexpr char LOG_LEVEL_COLOR_DIGIT[] = {
|
||||
'\0', // NONE
|
||||
@@ -133,8 +140,10 @@ class Logger : public Component {
|
||||
|
||||
/// Set the default log level for this logger.
|
||||
void set_log_level(uint8_t level);
|
||||
#ifdef USE_LOGGER_RUNTIME_TAG_LEVELS
|
||||
/// Set the log level of the specified tag.
|
||||
void set_log_level(const std::string &tag, uint8_t log_level);
|
||||
void set_log_level(const char *tag, uint8_t log_level);
|
||||
#endif
|
||||
uint8_t get_log_level() { return this->current_level_; }
|
||||
|
||||
// ========== INTERNAL METHODS ==========
|
||||
@@ -242,7 +251,9 @@ class Logger : public Component {
|
||||
#endif
|
||||
|
||||
// Large objects (internally aligned)
|
||||
std::map<std::string, uint8_t> log_levels_{};
|
||||
#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_{};
|
||||
#ifdef USE_ESPHOME_TASK_LOG_BUFFER
|
||||
|
@@ -3,11 +3,10 @@
|
||||
namespace esphome::logger {
|
||||
|
||||
void LoggerLevelSelect::publish_state(int level) {
|
||||
auto value = this->at(level);
|
||||
if (!value) {
|
||||
const auto &option = this->at(level_to_index(level));
|
||||
if (!option)
|
||||
return;
|
||||
}
|
||||
Select::publish_state(value.value());
|
||||
Select::publish_state(option.value());
|
||||
}
|
||||
|
||||
void LoggerLevelSelect::setup() {
|
||||
@@ -16,10 +15,10 @@ void LoggerLevelSelect::setup() {
|
||||
}
|
||||
|
||||
void LoggerLevelSelect::control(const std::string &value) {
|
||||
auto level = this->index_of(value);
|
||||
if (!level)
|
||||
const auto index = this->index_of(value);
|
||||
if (!index)
|
||||
return;
|
||||
this->parent_->set_log_level(level.value());
|
||||
this->parent_->set_log_level(index_to_level(index.value()));
|
||||
}
|
||||
|
||||
} // namespace esphome::logger
|
||||
|
@@ -3,11 +3,18 @@
|
||||
#include "esphome/components/select/select.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/logger/logger.h"
|
||||
|
||||
namespace esphome::logger {
|
||||
class LoggerLevelSelect : public Component, public select::Select, public Parented<Logger> {
|
||||
public:
|
||||
void publish_state(int level);
|
||||
void setup() override;
|
||||
void control(const std::string &value) 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; }
|
||||
// Convert option index to log level (skip CONFIG at level 4)
|
||||
static uint8_t index_to_level(uint8_t index) { return (index >= ESPHOME_LOG_LEVEL_CONFIG) ? index + 1 : index; }
|
||||
};
|
||||
} // namespace esphome::logger
|
||||
|
@@ -13,45 +13,46 @@ static const char *const TAG = "mpr121";
|
||||
void MPR121Component::setup() {
|
||||
// soft reset device
|
||||
this->write_byte(MPR121_SOFTRESET, 0x63);
|
||||
delay(100); // NOLINT
|
||||
if (!this->write_byte(MPR121_ECR, 0x0)) {
|
||||
this->error_code_ = COMMUNICATION_FAILED;
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
this->set_timeout(100, [this]() {
|
||||
if (!this->write_byte(MPR121_ECR, 0x0)) {
|
||||
this->error_code_ = COMMUNICATION_FAILED;
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
// set touch sensitivity for all 12 channels
|
||||
for (auto *channel : this->channels_) {
|
||||
channel->setup();
|
||||
}
|
||||
this->write_byte(MPR121_MHDR, 0x01);
|
||||
this->write_byte(MPR121_NHDR, 0x01);
|
||||
this->write_byte(MPR121_NCLR, 0x0E);
|
||||
this->write_byte(MPR121_FDLR, 0x00);
|
||||
|
||||
// set touch sensitivity for all 12 channels
|
||||
for (auto *channel : this->channels_) {
|
||||
channel->setup();
|
||||
}
|
||||
this->write_byte(MPR121_MHDR, 0x01);
|
||||
this->write_byte(MPR121_NHDR, 0x01);
|
||||
this->write_byte(MPR121_NCLR, 0x0E);
|
||||
this->write_byte(MPR121_FDLR, 0x00);
|
||||
this->write_byte(MPR121_MHDF, 0x01);
|
||||
this->write_byte(MPR121_NHDF, 0x05);
|
||||
this->write_byte(MPR121_NCLF, 0x01);
|
||||
this->write_byte(MPR121_FDLF, 0x00);
|
||||
|
||||
this->write_byte(MPR121_MHDF, 0x01);
|
||||
this->write_byte(MPR121_NHDF, 0x05);
|
||||
this->write_byte(MPR121_NCLF, 0x01);
|
||||
this->write_byte(MPR121_FDLF, 0x00);
|
||||
this->write_byte(MPR121_NHDT, 0x00);
|
||||
this->write_byte(MPR121_NCLT, 0x00);
|
||||
this->write_byte(MPR121_FDLT, 0x00);
|
||||
|
||||
this->write_byte(MPR121_NHDT, 0x00);
|
||||
this->write_byte(MPR121_NCLT, 0x00);
|
||||
this->write_byte(MPR121_FDLT, 0x00);
|
||||
this->write_byte(MPR121_DEBOUNCE, 0);
|
||||
// default, 16uA charge current
|
||||
this->write_byte(MPR121_CONFIG1, 0x10);
|
||||
// 0.5uS encoding, 1ms period
|
||||
this->write_byte(MPR121_CONFIG2, 0x20);
|
||||
|
||||
this->write_byte(MPR121_DEBOUNCE, 0);
|
||||
// default, 16uA charge current
|
||||
this->write_byte(MPR121_CONFIG1, 0x10);
|
||||
// 0.5uS encoding, 1ms period
|
||||
this->write_byte(MPR121_CONFIG2, 0x20);
|
||||
// Write the Electrode Configuration Register
|
||||
// * Highest 2 bits is "Calibration Lock", which we set to a value corresponding to 5 bits.
|
||||
// * The 2 bits below is "Proximity Enable" and are left at 0.
|
||||
// * The 4 least significant bits control how many electrodes are enabled. Electrodes are enabled
|
||||
// as a range, starting at 0 up to the highest channel index used.
|
||||
this->write_byte(MPR121_ECR, 0x80 | (this->max_touch_channel_ + 1));
|
||||
|
||||
// Write the Electrode Configuration Register
|
||||
// * Highest 2 bits is "Calibration Lock", which we set to a value corresponding to 5 bits.
|
||||
// * The 2 bits below is "Proximity Enable" and are left at 0.
|
||||
// * The 4 least significant bits control how many electrodes are enabled. Electrodes are enabled
|
||||
// as a range, starting at 0 up to the highest channel index used.
|
||||
this->write_byte(MPR121_ECR, 0x80 | (this->max_touch_channel_ + 1));
|
||||
|
||||
this->flush_gpio_();
|
||||
this->flush_gpio_();
|
||||
this->setup_complete_ = true;
|
||||
});
|
||||
}
|
||||
|
||||
void MPR121Component::set_touch_debounce(uint8_t debounce) {
|
||||
@@ -73,15 +74,15 @@ void MPR121Component::dump_config() {
|
||||
case COMMUNICATION_FAILED:
|
||||
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
|
||||
break;
|
||||
case WRONG_CHIP_STATE:
|
||||
ESP_LOGE(TAG, "MPR121 has wrong default value for CONFIG2?");
|
||||
break;
|
||||
case NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
void MPR121Component::loop() {
|
||||
if (!this->setup_complete_)
|
||||
return;
|
||||
|
||||
uint16_t val = 0;
|
||||
this->read_byte_16(MPR121_TOUCHSTATUS_L, &val);
|
||||
|
||||
|
@@ -80,6 +80,7 @@ class MPR121Component : public Component, public i2c::I2CDevice {
|
||||
void pin_mode(uint8_t ionum, gpio::Flags flags);
|
||||
|
||||
protected:
|
||||
bool setup_complete_{false};
|
||||
std::vector<MPR121Channel *> channels_{};
|
||||
uint8_t debounce_{0};
|
||||
uint8_t touch_threshold_{};
|
||||
@@ -88,7 +89,6 @@ class MPR121Component : public Component, public i2c::I2CDevice {
|
||||
enum ErrorCode {
|
||||
NONE = 0,
|
||||
COMMUNICATION_FAILED,
|
||||
WRONG_CHIP_STATE,
|
||||
} error_code_{NONE};
|
||||
|
||||
bool flush_gpio_();
|
||||
|
@@ -45,24 +45,26 @@ void SPS30Component::setup() {
|
||||
}
|
||||
ESP_LOGV(TAG, " Serial number: %s", this->serial_number_);
|
||||
|
||||
bool result;
|
||||
if (this->fan_interval_.has_value()) {
|
||||
// override default value
|
||||
result = this->write_command(SPS30_CMD_SET_AUTOMATIC_CLEANING_INTERVAL_SECONDS, this->fan_interval_.value());
|
||||
this->result_ =
|
||||
this->write_command(SPS30_CMD_SET_AUTOMATIC_CLEANING_INTERVAL_SECONDS, this->fan_interval_.value());
|
||||
} else {
|
||||
result = this->write_command(SPS30_CMD_SET_AUTOMATIC_CLEANING_INTERVAL_SECONDS);
|
||||
}
|
||||
if (result) {
|
||||
delay(20);
|
||||
uint16_t secs[2];
|
||||
if (this->read_data(secs, 2)) {
|
||||
this->fan_interval_ = secs[0] << 16 | secs[1];
|
||||
}
|
||||
this->result_ = this->write_command(SPS30_CMD_SET_AUTOMATIC_CLEANING_INTERVAL_SECONDS);
|
||||
}
|
||||
|
||||
this->status_clear_warning();
|
||||
this->skipped_data_read_cycles_ = 0;
|
||||
this->start_continuous_measurement_();
|
||||
this->set_timeout(20, [this]() {
|
||||
if (this->result_) {
|
||||
uint16_t secs[2];
|
||||
if (this->read_data(secs, 2)) {
|
||||
this->fan_interval_ = secs[0] << 16 | secs[1];
|
||||
}
|
||||
}
|
||||
this->status_clear_warning();
|
||||
this->skipped_data_read_cycles_ = 0;
|
||||
this->start_continuous_measurement_();
|
||||
this->setup_complete_ = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -111,6 +113,8 @@ void SPS30Component::dump_config() {
|
||||
}
|
||||
|
||||
void SPS30Component::update() {
|
||||
if (!this->setup_complete_)
|
||||
return;
|
||||
/// Check if warning flag active (sensor reconnected?)
|
||||
if (this->status_has_warning()) {
|
||||
ESP_LOGD(TAG, "Reconnecting");
|
||||
|
@@ -30,9 +30,12 @@ class SPS30Component : public PollingComponent, public sensirion_common::Sensiri
|
||||
bool start_fan_cleaning();
|
||||
|
||||
protected:
|
||||
bool result_{false};
|
||||
bool setup_complete_{false};
|
||||
uint16_t raw_firmware_version_;
|
||||
char serial_number_[17] = {0}; /// Terminating NULL character
|
||||
uint8_t skipped_data_read_cycles_ = 0;
|
||||
|
||||
bool start_continuous_measurement_();
|
||||
|
||||
enum ErrorCode : uint8_t {
|
||||
|
@@ -48,6 +48,7 @@
|
||||
#define USE_LIGHT
|
||||
#define USE_LOCK
|
||||
#define USE_LOGGER
|
||||
#define USE_LOGGER_RUNTIME_TAG_LEVELS
|
||||
#define USE_LVGL
|
||||
#define USE_LVGL_ANIMIMG
|
||||
#define USE_LVGL_ARC
|
||||
|
@@ -1,6 +1,6 @@
|
||||
pylint==3.3.8
|
||||
flake8==7.3.0 # also change in .pre-commit-config.yaml when updating
|
||||
ruff==0.13.2 # also change in .pre-commit-config.yaml when updating
|
||||
ruff==0.13.3 # also change in .pre-commit-config.yaml when updating
|
||||
pyupgrade==3.20.0 # also change in .pre-commit-config.yaml when updating
|
||||
pre-commit
|
||||
|
||||
|
@@ -6,11 +6,16 @@ esphome:
|
||||
format: "Warning: Logger level is %d"
|
||||
args: [id(logger_id).get_log_level()]
|
||||
- logger.set_level: WARN
|
||||
- logger.set_level:
|
||||
level: ERROR
|
||||
tag: mqtt.client
|
||||
|
||||
logger:
|
||||
id: logger_id
|
||||
level: DEBUG
|
||||
initial_level: INFO
|
||||
logs:
|
||||
mqtt.component: WARN
|
||||
|
||||
select:
|
||||
- platform: logger
|
||||
|
Reference in New Issue
Block a user