diff --git a/esphome/components/bedjet/bedjet_codec.h b/esphome/components/bedjet/bedjet_codec.h index 07aee32d54..3936ba2315 100644 --- a/esphome/components/bedjet/bedjet_codec.h +++ b/esphome/components/bedjet/bedjet_codec.h @@ -183,7 +183,7 @@ class BedjetCodec { BedjetPacket packet_; - BedjetStatusPacket *status_packet_; + BedjetStatusPacket *status_packet_{nullptr}; BedjetStatusPacket buf_; }; diff --git a/esphome/components/ble_client/sensor/ble_sensor.cpp b/esphome/components/ble_client/sensor/ble_sensor.cpp index fe5f11bbc2..4bd871dc81 100644 --- a/esphome/components/ble_client/sensor/ble_sensor.cpp +++ b/esphome/components/ble_client/sensor/ble_sensor.cpp @@ -102,6 +102,10 @@ void BLESensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t ga break; } case ESP_GATTC_NOTIFY_EVT: { + if (param->notify.value_len == 0) { + ESP_LOGW(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: empty value", this->get_name().c_str()); + break; + } ESP_LOGD(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: handle=0x%x, value=0x%x", this->get_name().c_str(), param->notify.handle, param->notify.value[0]); if (param->notify.handle != this->handle) @@ -131,8 +135,10 @@ float BLESensor::parse_data_(uint8_t *value, uint16_t value_len) { if (this->has_data_to_value_) { std::vector data(value, value + value_len); return this->data_to_value_func_(data); - } else { + } else if (value_len > 0) { return value[0]; + } else { + return NAN; } } diff --git a/esphome/components/ble_client/text_sensor/ble_text_sensor.cpp b/esphome/components/ble_client/text_sensor/ble_text_sensor.cpp index cacf1b4835..7eaa6af076 100644 --- a/esphome/components/ble_client/text_sensor/ble_text_sensor.cpp +++ b/esphome/components/ble_client/text_sensor/ble_text_sensor.cpp @@ -104,6 +104,10 @@ void BLETextSensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ case ESP_GATTC_NOTIFY_EVT: { if (param->notify.handle != this->handle) break; + if (param->notify.value_len == 0) { + ESP_LOGW(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: empty value", this->get_name().c_str()); + break; + } ESP_LOGV(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: handle=0x%x, value=0x%x", this->get_name().c_str(), param->notify.handle, param->notify.value[0]); this->publish_state(reinterpret_cast(param->notify.value), param->notify.value_len); diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h index 1d03a4c495..93ec754178 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h @@ -110,7 +110,7 @@ class I2SAudioSpeaker : public I2SAudioOut, public speaker::Speaker, public Comp TaskHandle_t speaker_task_handle_{nullptr}; EventGroupHandle_t event_group_{nullptr}; - QueueHandle_t i2s_event_queue_; + QueueHandle_t i2s_event_queue_{nullptr}; std::weak_ptr audio_ring_buffer_; diff --git a/esphome/components/inkplate/inkplate.cpp b/esphome/components/inkplate/inkplate.cpp index 7551c6fc77..326bdff774 100644 --- a/esphome/components/inkplate/inkplate.cpp +++ b/esphome/components/inkplate/inkplate.cpp @@ -229,7 +229,7 @@ void Inkplate::eink_off_() { this->oe_pin_->digital_write(false); this->gmod_pin_->digital_write(false); - GPIO.out &= ~(this->get_data_pin_mask_() | (1 << this->cl_pin_->get_pin()) | (1 << this->le_pin_->get_pin())); + GPIO.out &= ~(this->get_data_pin_mask_() | (1UL << this->cl_pin_->get_pin()) | (1UL << this->le_pin_->get_pin())); this->ckv_pin_->digital_write(false); this->sph_pin_->digital_write(false); this->spv_pin_->digital_write(false); diff --git a/esphome/components/inkplate/inkplate.h b/esphome/components/inkplate/inkplate.h index fb4674b522..bcd56b829a 100644 --- a/esphome/components/inkplate/inkplate.h +++ b/esphome/components/inkplate/inkplate.h @@ -152,16 +152,16 @@ class Inkplate : public display::DisplayBuffer, public i2c::I2CDevice { size_t get_buffer_length_(); - int get_data_pin_mask_() { - int data = 0; - data |= (1 << this->display_data_0_pin_->get_pin()); - data |= (1 << this->display_data_1_pin_->get_pin()); - data |= (1 << this->display_data_2_pin_->get_pin()); - data |= (1 << this->display_data_3_pin_->get_pin()); - data |= (1 << this->display_data_4_pin_->get_pin()); - data |= (1 << this->display_data_5_pin_->get_pin()); - data |= (1 << this->display_data_6_pin_->get_pin()); - data |= (1 << this->display_data_7_pin_->get_pin()); + uint32_t get_data_pin_mask_() { + uint32_t data = 0; + data |= (1UL << this->display_data_0_pin_->get_pin()); + data |= (1UL << this->display_data_1_pin_->get_pin()); + data |= (1UL << this->display_data_2_pin_->get_pin()); + data |= (1UL << this->display_data_3_pin_->get_pin()); + data |= (1UL << this->display_data_4_pin_->get_pin()); + data |= (1UL << this->display_data_5_pin_->get_pin()); + data |= (1UL << this->display_data_6_pin_->get_pin()); + data |= (1UL << this->display_data_7_pin_->get_pin()); return data; } diff --git a/esphome/components/ld2412/ld2412.cpp b/esphome/components/ld2412/ld2412.cpp index 37578dd8da..6ff6963e9f 100644 --- a/esphome/components/ld2412/ld2412.cpp +++ b/esphome/components/ld2412/ld2412.cpp @@ -455,12 +455,10 @@ void LD2412Component::handle_periodic_data_() { } #ifdef USE_NUMBER -std::function set_number_value(number::Number *n, float value) { +void set_number_value(number::Number *n, float value) { if (n != nullptr && (!n->has_state() || n->state != value)) { - n->state = value; - return [n, value]() { n->publish_state(value); }; + n->publish_state(value); } - return []() {}; } #endif @@ -504,6 +502,9 @@ bool LD2412Component::handle_ack_data_() { break; case CMD_QUERY_VERSION: { + if (this->buffer_pos_ < 12 + sizeof(this->version_)) { + return false; + } std::memcpy(this->version_, &this->buffer_data_[12], sizeof(this->version_)); char version_s[20]; ld24xx::format_version_str(this->version_, version_s); @@ -596,13 +597,8 @@ bool LD2412Component::handle_ack_data_() { case CMD_QUERY_MOTION_GATE_SENS: { #ifdef USE_NUMBER - std::vector> updates; - updates.reserve(this->gate_still_threshold_numbers_.size()); - for (size_t i = 0; i < this->gate_still_threshold_numbers_.size(); i++) { - updates.push_back(set_number_value(this->gate_move_threshold_numbers_[i], this->buffer_data_[10 + i])); - } - for (auto &update : updates) { - update(); + for (size_t i = 0; i < this->gate_move_threshold_numbers_.size() && (10 + i) < this->buffer_pos_; i++) { + set_number_value(this->gate_move_threshold_numbers_[i], this->buffer_data_[10 + i]); } #endif break; @@ -610,13 +606,8 @@ bool LD2412Component::handle_ack_data_() { case CMD_QUERY_STATIC_GATE_SENS: { #ifdef USE_NUMBER - std::vector> updates; - updates.reserve(this->gate_still_threshold_numbers_.size()); - for (size_t i = 0; i < this->gate_still_threshold_numbers_.size(); i++) { - updates.push_back(set_number_value(this->gate_still_threshold_numbers_[i], this->buffer_data_[10 + i])); - } - for (auto &update : updates) { - update(); + for (size_t i = 0; i < this->gate_still_threshold_numbers_.size() && (10 + i) < this->buffer_pos_; i++) { + set_number_value(this->gate_still_threshold_numbers_[i], this->buffer_data_[10 + i]); } #endif break; @@ -625,20 +616,21 @@ bool LD2412Component::handle_ack_data_() { case CMD_QUERY_BASIC_CONF: // Query parameters response { #ifdef USE_NUMBER + if (this->buffer_pos_ < 15) { + return false; + } /* Moving distance range: 9th byte Still distance range: 10th byte */ - std::vector> updates; - updates.push_back(set_number_value(this->min_distance_gate_number_, this->buffer_data_[10])); - updates.push_back(set_number_value(this->max_distance_gate_number_, this->buffer_data_[11] - 1)); + set_number_value(this->min_distance_gate_number_, this->buffer_data_[10]); + set_number_value(this->max_distance_gate_number_, this->buffer_data_[11] - 1); ESP_LOGV(TAG, "min_distance_gate_number_: %u, max_distance_gate_number_ %u", this->buffer_data_[10], this->buffer_data_[11]); /* None Duration: 11~12th bytes */ - updates.push_back( - set_number_value(this->timeout_number_, encode_uint16(this->buffer_data_[13], this->buffer_data_[12]))); + set_number_value(this->timeout_number_, encode_uint16(this->buffer_data_[13], this->buffer_data_[12])); ESP_LOGV(TAG, "timeout_number_: %u", encode_uint16(this->buffer_data_[13], this->buffer_data_[12])); /* Output pin configuration: 13th bytes @@ -650,9 +642,6 @@ bool LD2412Component::handle_ack_data_() { this->out_pin_level_select_->publish_state(out_pin_level_str); } #endif - for (auto &update : updates) { - update(); - } #endif } break; default: diff --git a/esphome/components/ld2420/ld2420.cpp b/esphome/components/ld2420/ld2420.cpp index 1e671363c9..ae622cda28 100644 --- a/esphome/components/ld2420/ld2420.cpp +++ b/esphome/components/ld2420/ld2420.cpp @@ -170,14 +170,18 @@ static uint8_t calc_checksum(void *data, size_t size) { return checksum; } -static int get_firmware_int(const char *version_string) { - std::string version_str = version_string; - if (version_str[0] == 'v') { - version_str.erase(0, 1); +static int32_t get_firmware_int(const char *version_string) { + // Convert "v1.5.4" -> 154 by skipping 'v' and '.', accumulating digits + const char *p = (*version_string == 'v') ? version_string + 1 : version_string; + int32_t result = 0; + for (; *p != '\0'; p++) { + if (*p == '.') + continue; + if (*p < '0' || *p > '9') + return 0; + result = result * 10 + (*p - '0'); } - version_str.erase(remove(version_str.begin(), version_str.end(), '.'), version_str.end()); - int version_integer = stoi(version_str); - return version_integer; + return result; } float LD2420Component::get_setup_priority() const { return setup_priority::BUS; } @@ -683,7 +687,7 @@ int LD2420Component::send_cmd_from_array(CmdFrameT frame) { retry = 0; } if (this->cmd_reply_.error > 0) { - this->handle_cmd_error(error); + this->handle_cmd_error(this->cmd_reply_.error); } } return error; diff --git a/esphome/components/light/effects.py b/esphome/components/light/effects.py index 15d9272d1a..4088a78e0d 100644 --- a/esphome/components/light/effects.py +++ b/esphome/components/light/effects.py @@ -392,7 +392,7 @@ async def addressable_lambda_effect_to_code(config, effect_id): "Rainbow", { cv.Optional(CONF_SPEED, default=10): cv.uint32_t, - cv.Optional(CONF_WIDTH, default=50): cv.uint32_t, + cv.Optional(CONF_WIDTH, default=50): cv.int_range(min=1, max=65535), }, ) async def addressable_rainbow_effect_to_code(config, effect_id): diff --git a/esphome/components/modbus_controller/modbus_controller.h b/esphome/components/modbus_controller/modbus_controller.h index bdb626be16..78c3b95965 100644 --- a/esphome/components/modbus_controller/modbus_controller.h +++ b/esphome/components/modbus_controller/modbus_controller.h @@ -178,7 +178,7 @@ template N mask_and_shift_by_rightbit(N data, uint32_t mask) { return result; } for (size_t pos = 0; pos < sizeof(N) << 3; pos++) { - if ((mask & (1 << pos)) != 0) + if ((mask & (1UL << pos)) != 0) return result >> pos; } return 0; diff --git a/esphome/components/ota/ota_backend.cpp b/esphome/components/ota/ota_backend.cpp index 8fb9f67214..01a18a58ef 100644 --- a/esphome/components/ota/ota_backend.cpp +++ b/esphome/components/ota/ota_backend.cpp @@ -13,6 +13,19 @@ OTAGlobalCallback *get_global_ota_callback() { return global_ota_callback; } +void OTAComponent::notify_state_deferred_(OTAState state, float progress, uint8_t error) { + // Pack state, error, and progress into a single uint32_t so the lambda + // captures only [this, packed] (8 bytes) — fits in std::function SBO. + // Layout: [state:8][error:8][progress_fixed:16] where progress is 0–10000 (0.01% resolution) + static_assert(OTA_ERROR <= 0xFF, "OTAState must fit in 8 bits for packing"); + uint32_t packed = (static_cast(state) << 24) | (static_cast(error) << 16) | + static_cast(progress * 100.0f); + this->defer([this, packed]() { + this->notify_state_(static_cast(packed >> 24), static_cast(packed & 0xFFFF) / 100.0f, + static_cast(packed >> 16)); + }); +} + void OTAComponent::notify_state_(OTAState state, float progress, uint8_t error) { for (auto *listener : this->state_listeners_) { listener->on_ota_state(state, progress, error); diff --git a/esphome/components/ota/ota_backend.h b/esphome/components/ota/ota_backend.h index bc603a6e9e..ab0ec58e8a 100644 --- a/esphome/components/ota/ota_backend.h +++ b/esphome/components/ota/ota_backend.h @@ -73,9 +73,7 @@ class OTAComponent : public Component { * This should be used by OTA implementations that run in separate tasks * (like web_server OTA) to ensure listeners execute in the main loop. */ - void notify_state_deferred_(OTAState state, float progress, uint8_t error) { - this->defer([this, state, progress, error]() { this->notify_state_(state, progress, error); }); - } + void notify_state_deferred_(OTAState state, float progress, uint8_t error); std::vector state_listeners_; #endif diff --git a/esphome/components/shelly_dimmer/shelly_dimmer.cpp b/esphome/components/shelly_dimmer/shelly_dimmer.cpp index 88fcbcbfe1..230fb963b1 100644 --- a/esphome/components/shelly_dimmer/shelly_dimmer.cpp +++ b/esphome/components/shelly_dimmer/shelly_dimmer.cpp @@ -402,7 +402,7 @@ bool ShellyDimmer::handle_frame_() { // Handle response. switch (cmd) { case SHELLY_DIMMER_PROTO_CMD_POLL: { - if (payload_len < 16) { + if (payload_len < 17) { return false; } diff --git a/esphome/components/st7789v/st7789v.cpp b/esphome/components/st7789v/st7789v.cpp index 6e4360ae74..dc03fb04ca 100644 --- a/esphome/components/st7789v/st7789v.cpp +++ b/esphome/components/st7789v/st7789v.cpp @@ -156,9 +156,9 @@ void ST7789V::update() { void ST7789V::set_model_str(const char *model_str) { this->model_str_ = model_str; } void ST7789V::write_display_data() { - uint16_t x1 = this->offset_height_; + uint16_t x1 = this->offset_width_; uint16_t x2 = x1 + get_width_internal() - 1; - uint16_t y1 = this->offset_width_; + uint16_t y1 = this->offset_height_; uint16_t y2 = y1 + get_height_internal() - 1; this->enable(); diff --git a/esphome/components/vbus/sensor/vbus_sensor.cpp b/esphome/components/vbus/sensor/vbus_sensor.cpp index 1cabb49703..407a81c83b 100644 --- a/esphome/components/vbus/sensor/vbus_sensor.cpp +++ b/esphome/components/vbus/sensor/vbus_sensor.cpp @@ -48,8 +48,8 @@ void DeltaSolBSPlusSensor::handle_message(std::vector &message) { if (this->operating_hours2_sensor_ != nullptr) this->operating_hours2_sensor_->publish_state(get_u16(message, 18)); if (this->heat_quantity_sensor_ != nullptr) { - this->heat_quantity_sensor_->publish_state(get_u16(message, 20) + get_u16(message, 22) * 1000 + - get_u16(message, 24) * 1000000); + this->heat_quantity_sensor_->publish_state(get_u16(message, 20) + get_u16(message, 22) * 1000.0f + + get_u16(message, 24) * 1000000.0f); } if (this->time_sensor_ != nullptr) this->time_sensor_->publish_state(get_u16(message, 12)); @@ -130,8 +130,8 @@ void DeltaSolCSensor::handle_message(std::vector &message) { if (this->operating_hours2_sensor_ != nullptr) this->operating_hours2_sensor_->publish_state(get_u16(message, 14)); if (this->heat_quantity_sensor_ != nullptr) { - this->heat_quantity_sensor_->publish_state(get_u16(message, 16) + get_u16(message, 18) * 1000 + - get_u16(message, 20) * 1000000); + this->heat_quantity_sensor_->publish_state(get_u16(message, 16) + get_u16(message, 18) * 1000.0f + + get_u16(message, 20) * 1000000.0f); } if (this->time_sensor_ != nullptr) this->time_sensor_->publish_state(get_u16(message, 22)); @@ -162,8 +162,10 @@ void DeltaSolCS2Sensor::handle_message(std::vector &message) { this->pump_speed_sensor_->publish_state(message[12]); if (this->operating_hours_sensor_ != nullptr) this->operating_hours_sensor_->publish_state(get_u16(message, 14)); - if (this->heat_quantity_sensor_ != nullptr) - this->heat_quantity_sensor_->publish_state((get_u16(message, 26) << 16) + get_u16(message, 24)); + if (this->heat_quantity_sensor_ != nullptr) { + this->heat_quantity_sensor_->publish_state((static_cast(get_u16(message, 26)) << 16) | + get_u16(message, 24)); + } if (this->version_sensor_ != nullptr) this->version_sensor_->publish_state(get_u16(message, 28) * 0.01f); } @@ -204,8 +206,10 @@ void DeltaSolCS4Sensor::handle_message(std::vector &message) { this->operating_hours1_sensor_->publish_state(get_u16(message, 10)); if (this->operating_hours2_sensor_ != nullptr) this->operating_hours2_sensor_->publish_state(get_u16(message, 14)); - if (this->heat_quantity_sensor_ != nullptr) - this->heat_quantity_sensor_->publish_state((get_u16(message, 30) << 16) + get_u16(message, 28)); + if (this->heat_quantity_sensor_ != nullptr) { + this->heat_quantity_sensor_->publish_state((static_cast(get_u16(message, 30)) << 16) | + get_u16(message, 28)); + } if (this->time_sensor_ != nullptr) this->time_sensor_->publish_state(get_u16(message, 22)); if (this->version_sensor_ != nullptr) @@ -250,8 +254,10 @@ void DeltaSolCSPlusSensor::handle_message(std::vector &message) { this->operating_hours1_sensor_->publish_state(get_u16(message, 10)); if (this->operating_hours2_sensor_ != nullptr) this->operating_hours2_sensor_->publish_state(get_u16(message, 14)); - if (this->heat_quantity_sensor_ != nullptr) - this->heat_quantity_sensor_->publish_state((get_u16(message, 30) << 16) + get_u16(message, 28)); + if (this->heat_quantity_sensor_ != nullptr) { + this->heat_quantity_sensor_->publish_state((static_cast(get_u16(message, 30)) << 16) | + get_u16(message, 28)); + } if (this->time_sensor_ != nullptr) this->time_sensor_->publish_state(get_u16(message, 22)); if (this->version_sensor_ != nullptr) diff --git a/esphome/components/vbus/vbus.cpp b/esphome/components/vbus/vbus.cpp index c6786ee31e..195d6ed568 100644 --- a/esphome/components/vbus/vbus.cpp +++ b/esphome/components/vbus/vbus.cpp @@ -67,8 +67,7 @@ void VBus::loop() { } septet_spread(this->buffer_.data(), 7, 6, this->buffer_[13]); uint16_t id = (this->buffer_[8] << 8) + this->buffer_[7]; - uint32_t value = - (this->buffer_[12] << 24) + (this->buffer_[11] << 16) + (this->buffer_[10] << 8) + this->buffer_[9]; + uint32_t value = encode_uint32(this->buffer_[12], this->buffer_[11], this->buffer_[10], this->buffer_[9]); ESP_LOGV(TAG, "P1 C%04x %04x->%04x: %04x %04" PRIx32 " (%" PRIu32 ")", this->command_, this->source_, this->dest_, id, value, value); } else if ((this->protocol_ == 0x10) && (this->buffer_.size() == 9)) { diff --git a/esphome/components/vl53l0x/vl53l0x_sensor.cpp b/esphome/components/vl53l0x/vl53l0x_sensor.cpp index 0b2b40d723..8a76ed7760 100644 --- a/esphome/components/vl53l0x/vl53l0x_sensor.cpp +++ b/esphome/components/vl53l0x/vl53l0x_sensor.cpp @@ -266,6 +266,7 @@ void VL53L0XSensor::update() { this->status_momentary_warning("update", 5000); ESP_LOGW(TAG, "%s - update called before prior reading complete - initiated:%d waiting_for_interrupt:%d", this->name_.c_str(), this->initiated_read_, this->waiting_for_interrupt_); + return; } // initiate single shot measurement