Merge remote-tracking branch 'upstream/dev' into integration

This commit is contained in:
J. Nick Koston
2026-03-22 12:58:13 -10:00
20 changed files with 57 additions and 55 deletions
+1
View File
@@ -614,6 +614,7 @@ FILTER_SOURCE_FILES = filter_source_files_from_platform(
PlatformFramework.RTL87XX_ARDUINO,
PlatformFramework.LN882X_ARDUINO,
},
"task_log_buffer_zephyr.cpp": {PlatformFramework.NRF52_ZEPHYR},
}
)
+3 -1
View File
@@ -671,9 +671,10 @@ void LvglComponent::static_flush_cb(lv_display_t *disp_drv, const lv_area_t *are
* @param e The event data
* @param color_start The color to apply to the first tick
* @param color_end The color to apply to the last tick
* @param width
*/
void lv_scale_draw_event_cb(lv_event_t *e, uint16_t range_start, uint16_t range_end, lv_color_t color_start,
lv_color_t color_end, bool local) {
lv_color_t color_end, int width, bool local) {
auto *scale = static_cast<lv_obj_t *>(lv_event_get_target(e));
lv_draw_task_t *task = lv_event_get_draw_task(e);
@@ -691,6 +692,7 @@ void lv_scale_draw_event_cb(lv_event_t *e, uint16_t range_start, uint16_t range_
range = 1;
auto ratio = (tick * 255) / range;
line_dsc->color = lv_color_mix(color_end, color_start, ratio);
line_dsc->width += width;
}
}
}
+1 -1
View File
@@ -53,7 +53,7 @@ extern std::string lv_event_code_name_for(lv_event_t *event);
lv_obj_t *lv_container_create(lv_obj_t *parent);
#ifdef USE_LVGL_SCALE
void lv_scale_draw_event_cb(lv_event_t *e, uint16_t range_start, uint16_t range_end, lv_color_t color_start,
lv_color_t color_end, bool local);
lv_color_t color_end, int width, bool local);
#endif
#if LV_COLOR_DEPTH == 16
static const display::ColorBitness LV_BITNESS = display::ColorBitness::COLOR_BITNESS_565;
+11 -10
View File
@@ -177,7 +177,7 @@ INDICATOR_ARC_SCHEMA = cv.Schema(
cv.Optional(CONF_VALUE): lv_float,
cv.Optional(CONF_START_VALUE): lv_float,
cv.Optional(CONF_END_VALUE): lv_float,
cv.Optional(CONF_OPA): opacity,
cv.Optional(CONF_OPA, default=1.0): opacity,
}
).add_extra(cv.has_at_most_one_key(CONF_VALUE, CONF_START_VALUE))
@@ -247,7 +247,7 @@ SCALE_SCHEMA = cv.Schema(
cv.Optional(CONF_RANGE_FROM, default=0.0): lv_int,
cv.Optional(CONF_RANGE_TO, default=100.0): lv_int,
cv.Optional(CONF_ANGLE_RANGE, default=270): lv_angle_degrees,
cv.Optional(CONF_ROTATION, default=0): lv_angle_degrees,
cv.Optional(CONF_ROTATION): lv_angle_degrees,
cv.Optional(CONF_INDICATORS): cv.ensure_list(INDICATOR_SCHEMA),
cv.Optional(CONF_DRAW_TICKS_ON_TOP, default=True): bool,
}
@@ -329,7 +329,7 @@ class MeterType(WidgetType):
)
def get_uses(self):
return CONF_SCALE, CONF_LINE
return CONF_SCALE, CONF_LINE, CONF_IMAGE
def validate(self, value):
return cv.has_at_most_one_key(CONF_INDICATOR, CONF_PIVOT)(value)
@@ -366,16 +366,17 @@ class MeterType(WidgetType):
lv.scale_set_range(scale_var, range_from, range_to)
angle_range = await lv_angle_degrees.process(scale_conf[CONF_ANGLE_RANGE])
rotation = await lv_angle_degrees.process(scale_conf[CONF_ROTATION])
if (rotation := scale_conf.get(CONF_ROTATION)) is not None:
rotation = await lv_angle_degrees.process(rotation)
else:
rotation = 90 + (360 - angle_range) // 2
# Set angle range
lv.scale_set_angle_range(
scale_var,
angle_range,
)
# Set rotation if specified
if rotation:
lv.scale_set_rotation(scale_var, rotation)
lv.scale_set_rotation(scale_var, rotation)
# Handle indicators as sections
for indicator in scale_conf.get(CONF_INDICATORS, ()):
@@ -393,10 +394,9 @@ class MeterType(WidgetType):
props = {
"arc_width": v[CONF_WIDTH],
"arc_color": v[CONF_COLOR],
"arc_opa": v[CONF_OPA],
"arc_rounded": v.get("arc_rounded", False),
}
if (opa := v.get(CONF_OPA)) is not None:
props["arc_opa"] = opa
if CONF_R_MOD in v:
get_warnings().add(
"The 'r_mod' indicator property is not supported in LVGL 9.x and will be ignored."
@@ -424,6 +424,7 @@ class MeterType(WidgetType):
end_value,
color_start,
color_end,
v[CONF_WIDTH],
local,
)
lv_obj.add_event_cb(
+5 -8
View File
@@ -95,10 +95,6 @@ void PMSX003Component::loop() {
// Just go ahead and read stuff
break;
}
} else if (now - this->last_update_ < this->update_interval_) {
// Otherwise just leave the sensor powered up and come back when we hit the update
// time
return;
}
if (now - this->last_transmission_ >= 500) {
@@ -114,10 +110,11 @@ void PMSX003Component::loop() {
this->read_byte(&this->data_[this->data_index_]);
auto check = this->check_byte_();
if (!check.has_value()) {
// finished
this->parse_data_();
if (this->update_interval_ > STABILISING_MS || now - this->last_update_ >= this->update_interval_) {
this->parse_data_();
this->last_update_ = now;
}
this->data_index_ = 0;
this->last_update_ = now;
} else if (!*check) {
// wrong data
this->data_index_ = 0;
@@ -138,7 +135,7 @@ optional<bool> PMSX003Component::check_byte_() {
return true;
}
ESP_LOGW(TAG, "Start character %u mismatch: 0x%02X != 0x%02X", index + 1, byte, START_CHARACTER_1);
ESP_LOGW(TAG, "Start character %u mismatch: 0x%02X != 0x%02X", index + 1, byte, start_char);
return false;
}
+1
View File
@@ -1,4 +1,5 @@
#include "sht4x.h"
#include "esphome/core/hal.h"
#include "esphome/core/log.h"
namespace esphome {
@@ -6,11 +6,17 @@ namespace esphome::ultrasonic {
static const char *const TAG = "ultrasonic.sensor";
static constexpr uint32_t DEBOUNCE_US = 50; // Ignore edges within 50us of each other (noise filtering)
static constexpr uint32_t START_DELAY_US = 100; // Ignore edges within 100us of trigger (filters bleed-through)
static constexpr uint32_t START_TIMEOUT_US = 40000; // Maximum time to wait for echo pulse to start
void IRAM_ATTR UltrasonicSensorStore::gpio_intr(UltrasonicSensorStore *arg) {
uint32_t now = micros();
if (arg->echo_pin_isr.digital_read()) {
// Ignore edges after measurement complete or too soon after trigger pulse
if (arg->echo_end || (now - arg->measurement_start_us) <= START_DELAY_US) {
return;
}
if (!arg->echo_start || (now - arg->echo_start_us) <= DEBOUNCE_US) {
arg->echo_start_us = now;
arg->echo_start = true;
} else {
@@ -21,15 +27,14 @@ void IRAM_ATTR UltrasonicSensorStore::gpio_intr(UltrasonicSensorStore *arg) {
void IRAM_ATTR UltrasonicSensorComponent::send_trigger_pulse_() {
InterruptLock lock;
this->store_.echo_start_us = 0;
this->store_.echo_end_us = 0;
this->store_.echo_start = false;
this->store_.echo_end = false;
this->store_.measurement_start_us = micros();
this->trigger_pin_isr_.digital_write(true);
delayMicroseconds(this->pulse_time_us_);
this->trigger_pin_isr_.digital_write(false);
this->measurement_pending_ = true;
this->measurement_start_us_ = micros();
this->measurement_start_us_ = this->store_.measurement_start_us;
}
void UltrasonicSensorComponent::setup() {
@@ -37,7 +42,6 @@ void UltrasonicSensorComponent::setup() {
this->trigger_pin_->digital_write(false);
this->trigger_pin_isr_ = this->trigger_pin_->to_isr();
this->echo_pin_->setup();
this->store_.echo_pin_isr = this->echo_pin_->to_isr();
this->echo_pin_->attach_interrupt(UltrasonicSensorStore::gpio_intr, &this->store_, gpio::INTERRUPT_ANY_EDGE);
}
@@ -77,17 +81,10 @@ void UltrasonicSensorComponent::loop() {
}
if (this->store_.echo_end) {
float result;
if (this->store_.echo_start) {
uint32_t pulse_duration = this->store_.echo_end_us - this->store_.echo_start_us;
ESP_LOGV(TAG, "pulse start took %" PRIu32 "us, echo took %" PRIu32 "us",
this->store_.echo_start_us - this->measurement_start_us_, pulse_duration);
result = UltrasonicSensorComponent::us_to_m(pulse_duration);
ESP_LOGD(TAG, "'%s' - Got distance: %.3f m", this->name_.c_str(), result);
} else {
ESP_LOGW(TAG, "'%s' - pulse end before pulse start, does the echo pin need to be inverted?", this->name_.c_str());
result = NAN;
}
uint32_t pulse_duration = this->store_.echo_end_us - this->store_.echo_start_us;
ESP_LOGV(TAG, "Echo took %" PRIu32 "us", pulse_duration);
float result = UltrasonicSensorComponent::us_to_m(pulse_duration);
ESP_LOGD(TAG, "'%s' - Got distance: %.3f m", this->name_.c_str(), result);
this->publish_state(result);
this->measurement_pending_ = false;
return;
@@ -11,8 +11,7 @@ namespace esphome::ultrasonic {
struct UltrasonicSensorStore {
static void gpio_intr(UltrasonicSensorStore *arg);
ISRInternalGPIOPin echo_pin_isr;
volatile uint32_t wait_start_us{0};
volatile uint32_t measurement_start_us{0};
volatile uint32_t echo_start_us{0};
volatile uint32_t echo_end_us{0};
volatile bool echo_start{false};
@@ -262,19 +262,6 @@ StringRef AsyncWebServerRequest::url_to(std::span<char, URL_BUF_SIZE> buffer) co
return StringRef(buffer.data(), decoded_len);
}
void AsyncWebServerRequest::send(AsyncWebServerResponse *response) {
httpd_resp_send(*this, response->get_content_data(), response->get_content_size());
}
void AsyncWebServerRequest::send(int code, const char *content_type, const char *content) {
this->init_response_(nullptr, code, content_type);
if (content) {
httpd_resp_send(*this, content, HTTPD_RESP_USE_STRLEN);
} else {
httpd_resp_send(*this, nullptr, 0);
}
}
void AsyncWebServerRequest::redirect(const std::string &url) {
httpd_resp_set_status(*this, "302 Found");
httpd_resp_set_hdr(*this, "Location", url.c_str());
@@ -134,8 +134,17 @@ class AsyncWebServerRequest {
void redirect(const std::string &url);
void send(AsyncWebServerResponse *response);
void send(int code, const char *content_type = nullptr, const char *content = nullptr);
inline void ESPHOME_ALWAYS_INLINE send(AsyncWebServerResponse *response) {
httpd_resp_send(*this, response->get_content_data(), response->get_content_size());
}
inline void ESPHOME_ALWAYS_INLINE send(int code, const char *content_type = nullptr, const char *content = nullptr) {
this->init_response_(nullptr, code, content_type);
if (content) {
httpd_resp_send(*this, content, HTTPD_RESP_USE_STRLEN);
} else {
httpd_resp_send(*this, nullptr, 0);
}
}
// NOLINTNEXTLINE(readability-identifier-naming)
AsyncWebServerResponse *beginResponse(int code, const char *content_type) {
auto *res = new AsyncWebServerResponseEmpty(this); // NOLINT(cppcoreguidelines-owning-memory)
+1 -1
View File
@@ -26,7 +26,7 @@ void setup() {
// Log functions call global_logger->log_vprintf_() without a null check,
// so we must set up a Logger before any test that triggers logging.
static esphome::logger::Logger test_logger(0);
static esphome::logger::Logger test_logger(0, 64);
test_logger.set_log_level(ESPHOME_LOG_LEVEL);
test_logger.pre_setup();
+1 -1
View File
@@ -22,7 +22,7 @@ void original_setup() {
void setup() {
// Log functions call global_logger->log_vprintf_() without a null check,
// so we must set up a Logger before any test that triggers logging.
static esphome::logger::Logger test_logger(0);
static esphome::logger::Logger test_logger(0, 64);
test_logger.set_log_level(ESPHOME_LOG_LEVEL);
test_logger.pre_setup();
@@ -3,6 +3,7 @@ esphome:
host:
api:
batch_delay: 0ms # Disable batching to receive all state updates
logger:
level: VERBOSE
@@ -3,6 +3,7 @@ esphome:
host:
api:
batch_delay: 0ms # Disable batching to receive all state updates
logger:
level: VERBOSE
@@ -3,6 +3,7 @@ esphome:
host:
api:
batch_delay: 0ms # Disable batching to receive all state updates
logger:
level: VERBOSE
@@ -3,6 +3,7 @@ esphome:
host:
api:
batch_delay: 0ms # Disable batching to receive all state updates
logger:
level: VERBOSE
@@ -3,6 +3,7 @@ esphome:
host:
api:
batch_delay: 0ms # Disable batching to receive all state updates
logger:
level: VERBOSE
@@ -3,6 +3,7 @@ esphome:
host:
api:
batch_delay: 0ms # Disable batching to receive all state updates
logger:
level: VERBOSE
@@ -3,6 +3,7 @@ esphome:
host:
api:
batch_delay: 0ms # Disable batching to receive all state updates
logger:
level: VERBOSE
@@ -3,6 +3,7 @@ esphome:
host:
api:
batch_delay: 0ms # Disable batching to receive all state updates
logger:
level: VERBOSE