diff --git a/.clang-tidy.hash b/.clang-tidy.hash index a6222ebd64..f2b148342f 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -bc4001761441a1f0d32971287398739b2b1c45435440425f5ed5aacf1c1f8c2b +499db61c1aa55b98b6629df603a56a1ba7aff5a9a7c781a5c1552a9dcd186c08 diff --git a/CODEOWNERS b/CODEOWNERS index 0b9935faf7..d5b81d548e 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -256,6 +256,7 @@ esphome/components/libretiny_pwm/* @kuba2k2 esphome/components/light/* @esphome/core esphome/components/lightwaverf/* @max246 esphome/components/lilygo_t5_47/touchscreen/* @jesserockz +esphome/components/lm75b/* @beormund esphome/components/ln882x/* @lamauny esphome/components/lock/* @esphome/core esphome/components/logger/* @esphome/core diff --git a/esphome/components/animation/animation.cpp b/esphome/components/animation/animation.cpp index 6db6f1a7bd..c2ae3b2f76 100644 --- a/esphome/components/animation/animation.cpp +++ b/esphome/components/animation/animation.cpp @@ -26,12 +26,12 @@ uint32_t Animation::get_animation_frame_count() const { return this->animation_f int Animation::get_current_frame() const { return this->current_frame_; } void Animation::next_frame() { this->current_frame_++; - if (loop_count_ && this->current_frame_ == loop_end_frame_ && + if (loop_count_ && static_cast(this->current_frame_) == loop_end_frame_ && (this->loop_current_iteration_ < loop_count_ || loop_count_ < 0)) { this->current_frame_ = loop_start_frame_; this->loop_current_iteration_++; } - if (this->current_frame_ >= animation_frame_count_) { + if (static_cast(this->current_frame_) >= animation_frame_count_) { this->loop_current_iteration_ = 1; this->current_frame_ = 0; } diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 4f32112fa6..615b7f5764 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1389,6 +1389,11 @@ void APIConnection::complete_authentication_() { this->send_time_request(); } #endif +#ifdef USE_ZWAVE_PROXY + if (zwave_proxy::global_zwave_proxy != nullptr) { + zwave_proxy::global_zwave_proxy->api_connection_authenticated(this); + } +#endif } bool APIConnection::send_hello_response(const HelloRequest &msg) { diff --git a/esphome/components/audio/audio.cpp b/esphome/components/audio/audio.cpp index 2a58c38ac7..9cc9b7d0da 100644 --- a/esphome/components/audio/audio.cpp +++ b/esphome/components/audio/audio.cpp @@ -57,7 +57,7 @@ const char *audio_file_type_to_string(AudioFileType file_type) { void scale_audio_samples(const int16_t *audio_samples, int16_t *output_buffer, int16_t scale_factor, size_t samples_to_scale) { // Note the assembly dsps_mulc function has audio glitches if the input and output buffers are the same. - for (int i = 0; i < samples_to_scale; i++) { + for (size_t i = 0; i < samples_to_scale; i++) { int32_t acc = (int32_t) audio_samples[i] * (int32_t) scale_factor; output_buffer[i] = (int16_t) (acc >> 15); } diff --git a/esphome/components/bl0906/bl0906.cpp b/esphome/components/bl0906/bl0906.cpp index e48715010c..c1cd48a1ac 100644 --- a/esphome/components/bl0906/bl0906.cpp +++ b/esphome/components/bl0906/bl0906.cpp @@ -97,10 +97,10 @@ void BL0906::handle_actions_() { return; } ActionCallbackFuncPtr ptr_func = nullptr; - for (int i = 0; i < this->action_queue_.size(); i++) { + for (size_t i = 0; i < this->action_queue_.size(); i++) { ptr_func = this->action_queue_[i]; if (ptr_func) { - ESP_LOGI(TAG, "HandleActionCallback[%d]", i); + ESP_LOGI(TAG, "HandleActionCallback[%zu]", i); (this->*ptr_func)(); } } diff --git a/esphome/components/bl0942/bl0942.cpp b/esphome/components/bl0942/bl0942.cpp index 894fcbfbb7..95dd689b07 100644 --- a/esphome/components/bl0942/bl0942.cpp +++ b/esphome/components/bl0942/bl0942.cpp @@ -51,7 +51,7 @@ void BL0942::loop() { if (!avail) { return; } - if (avail < sizeof(buffer)) { + if (static_cast(avail) < sizeof(buffer)) { if (!this->rx_start_) { this->rx_start_ = millis(); } else if (millis() > this->rx_start_ + PKT_TIMEOUT_MS) { @@ -148,7 +148,7 @@ void BL0942::setup() { this->write_reg_(BL0942_REG_USR_WRPROT, 0); - if (this->read_reg_(BL0942_REG_MODE) != mode) + if (static_cast(this->read_reg_(BL0942_REG_MODE)) != mode) this->status_set_warning(LOG_STR("BL0942 setup failed!")); this->flush(); diff --git a/esphome/components/cm1106/cm1106.cpp b/esphome/components/cm1106/cm1106.cpp index 339a1659ac..d88ea2e1da 100644 --- a/esphome/components/cm1106/cm1106.cpp +++ b/esphome/components/cm1106/cm1106.cpp @@ -13,7 +13,7 @@ static const uint8_t C_M1106_CMD_SET_CO2_CALIB_RESPONSE[4] = {0x16, 0x01, 0x03, uint8_t cm1106_checksum(const uint8_t *response, size_t len) { uint8_t crc = 0; - for (int i = 0; i < len - 1; i++) { + for (size_t i = 0; i < len - 1; i++) { crc -= response[i]; } return crc; diff --git a/esphome/components/daikin_arc/daikin_arc.cpp b/esphome/components/daikin_arc/daikin_arc.cpp index f806463d00..068819ecd1 100644 --- a/esphome/components/daikin_arc/daikin_arc.cpp +++ b/esphome/components/daikin_arc/daikin_arc.cpp @@ -26,7 +26,7 @@ void DaikinArcClimate::transmit_query_() { uint8_t remote_header[8] = {0x11, 0xDA, 0x27, 0x00, 0x84, 0x87, 0x20, 0x00}; // Calculate checksum - for (int i = 0; i < sizeof(remote_header) - 1; i++) { + for (size_t i = 0; i < sizeof(remote_header) - 1; i++) { remote_header[sizeof(remote_header) - 1] += remote_header[i]; } @@ -102,7 +102,7 @@ void DaikinArcClimate::transmit_state() { remote_state[9] = fan_speed & 0xff; // Calculate checksum - for (int i = 0; i < sizeof(remote_header) - 1; i++) { + for (size_t i = 0; i < sizeof(remote_header) - 1; i++) { remote_header[sizeof(remote_header) - 1] += remote_header[i]; } @@ -350,7 +350,7 @@ bool DaikinArcClimate::on_receive(remote_base::RemoteReceiveData data) { bool valid_daikin_frame = false; if (data.expect_item(DAIKIN_HEADER_MARK, DAIKIN_HEADER_SPACE)) { valid_daikin_frame = true; - int bytes_count = data.size() / 2 / 8; + size_t bytes_count = data.size() / 2 / 8; std::unique_ptr buf(new char[bytes_count * 3 + 1]); buf[0] = '\0'; for (size_t i = 0; i < bytes_count; i++) { @@ -370,7 +370,7 @@ bool DaikinArcClimate::on_receive(remote_base::RemoteReceiveData data) { if (!valid_daikin_frame) { char sbuf[16 * 10 + 1]; sbuf[0] = '\0'; - for (size_t j = 0; j < data.size(); j++) { + for (size_t j = 0; j < static_cast(data.size()); j++) { if ((j - 2) % 16 == 0) { if (j > 0) { ESP_LOGD(TAG, "DATA %04x: %s", (j - 16 > 0xffff ? 0 : j - 16), sbuf); @@ -380,19 +380,26 @@ bool DaikinArcClimate::on_receive(remote_base::RemoteReceiveData data) { char type_ch = ' '; // debug_tolerance = 25% - if (DAIKIN_DBG_LOWER(DAIKIN_ARC_PRE_MARK) <= data[j] && data[j] <= DAIKIN_DBG_UPPER(DAIKIN_ARC_PRE_MARK)) + if (static_cast(DAIKIN_DBG_LOWER(DAIKIN_ARC_PRE_MARK)) <= data[j] && + data[j] <= static_cast(DAIKIN_DBG_UPPER(DAIKIN_ARC_PRE_MARK))) type_ch = 'P'; - if (DAIKIN_DBG_LOWER(DAIKIN_ARC_PRE_SPACE) <= -data[j] && -data[j] <= DAIKIN_DBG_UPPER(DAIKIN_ARC_PRE_SPACE)) + if (static_cast(DAIKIN_DBG_LOWER(DAIKIN_ARC_PRE_SPACE)) <= -data[j] && + -data[j] <= static_cast(DAIKIN_DBG_UPPER(DAIKIN_ARC_PRE_SPACE))) type_ch = 'a'; - if (DAIKIN_DBG_LOWER(DAIKIN_HEADER_MARK) <= data[j] && data[j] <= DAIKIN_DBG_UPPER(DAIKIN_HEADER_MARK)) + if (static_cast(DAIKIN_DBG_LOWER(DAIKIN_HEADER_MARK)) <= data[j] && + data[j] <= static_cast(DAIKIN_DBG_UPPER(DAIKIN_HEADER_MARK))) type_ch = 'H'; - if (DAIKIN_DBG_LOWER(DAIKIN_HEADER_SPACE) <= -data[j] && -data[j] <= DAIKIN_DBG_UPPER(DAIKIN_HEADER_SPACE)) + if (static_cast(DAIKIN_DBG_LOWER(DAIKIN_HEADER_SPACE)) <= -data[j] && + -data[j] <= static_cast(DAIKIN_DBG_UPPER(DAIKIN_HEADER_SPACE))) type_ch = 'h'; - if (DAIKIN_DBG_LOWER(DAIKIN_BIT_MARK) <= data[j] && data[j] <= DAIKIN_DBG_UPPER(DAIKIN_BIT_MARK)) + if (static_cast(DAIKIN_DBG_LOWER(DAIKIN_BIT_MARK)) <= data[j] && + data[j] <= static_cast(DAIKIN_DBG_UPPER(DAIKIN_BIT_MARK))) type_ch = 'B'; - if (DAIKIN_DBG_LOWER(DAIKIN_ONE_SPACE) <= -data[j] && -data[j] <= DAIKIN_DBG_UPPER(DAIKIN_ONE_SPACE)) + if (static_cast(DAIKIN_DBG_LOWER(DAIKIN_ONE_SPACE)) <= -data[j] && + -data[j] <= static_cast(DAIKIN_DBG_UPPER(DAIKIN_ONE_SPACE))) type_ch = '1'; - if (DAIKIN_DBG_LOWER(DAIKIN_ZERO_SPACE) <= -data[j] && -data[j] <= DAIKIN_DBG_UPPER(DAIKIN_ZERO_SPACE)) + if (static_cast(DAIKIN_DBG_LOWER(DAIKIN_ZERO_SPACE)) <= -data[j] && + -data[j] <= static_cast(DAIKIN_DBG_UPPER(DAIKIN_ZERO_SPACE))) type_ch = '0'; if (abs(data[j]) > 100000) { @@ -400,7 +407,7 @@ bool DaikinArcClimate::on_receive(remote_base::RemoteReceiveData data) { } else { sprintf(sbuf, "%s%-5d[%c] ", sbuf, (int) (round(data[j] / 10.) * 10), type_ch); } - if (j == data.size() - 1) { + if (j + 1 == static_cast(data.size())) { ESP_LOGD(TAG, "DATA %04x: %s", (j - 8 > 0xffff ? 0 : j - 8), sbuf); } } diff --git a/esphome/components/es7210/es7210.cpp b/esphome/components/es7210/es7210.cpp index e5729703ed..1358121c1b 100644 --- a/esphome/components/es7210/es7210.cpp +++ b/esphome/components/es7210/es7210.cpp @@ -97,12 +97,12 @@ bool ES7210::set_mic_gain(float mic_gain) { } bool ES7210::configure_sample_rate_() { - int mclk_fre = this->sample_rate_ * MCLK_DIV_FRE; + uint32_t mclk_fre = this->sample_rate_ * MCLK_DIV_FRE; int coeff = -1; - for (int i = 0; i < (sizeof(ES7210_COEFFICIENTS) / sizeof(ES7210_COEFFICIENTS[0])); ++i) { + for (size_t i = 0; i < (sizeof(ES7210_COEFFICIENTS) / sizeof(ES7210_COEFFICIENTS[0])); ++i) { if (ES7210_COEFFICIENTS[i].lrclk == this->sample_rate_ && ES7210_COEFFICIENTS[i].mclk == mclk_fre) - coeff = i; + coeff = static_cast(i); } if (coeff >= 0) { diff --git a/esphome/components/esp32_ble/ble_advertising.cpp b/esphome/components/esp32_ble/ble_advertising.cpp index 3bc0fabe7e..da105051eb 100644 --- a/esphome/components/esp32_ble/ble_advertising.cpp +++ b/esphome/components/esp32_ble/ble_advertising.cpp @@ -156,7 +156,7 @@ void BLEAdvertising::loop() { if (now - this->last_advertisement_time_ > this->advertising_cycle_time_) { this->stop(); this->current_adv_index_ += 1; - if (this->current_adv_index_ >= this->raw_advertisements_callbacks_.size()) { + if (static_cast(this->current_adv_index_) >= this->raw_advertisements_callbacks_.size()) { this->current_adv_index_ = -1; } this->start(); diff --git a/esphome/components/esp32_can/esp32_can.cpp b/esphome/components/esp32_can/esp32_can.cpp index 252482dc5e..cdef7b1930 100644 --- a/esphome/components/esp32_can/esp32_can.cpp +++ b/esphome/components/esp32_can/esp32_can.cpp @@ -68,7 +68,7 @@ static bool get_bitrate(canbus::CanSpeed bitrate, twai_timing_config_t *t_config bool ESP32Can::setup_internal() { static int next_twai_ctrl_num = 0; - if (next_twai_ctrl_num >= SOC_TWAI_CONTROLLER_NUM) { + if (static_cast(next_twai_ctrl_num) >= SOC_TWAI_CONTROLLER_NUM) { ESP_LOGW(TAG, "Maximum number of esp32_can components created already"); this->mark_failed(); return false; diff --git a/esphome/components/esp32_rmt_led_strip/led_strip.cpp b/esphome/components/esp32_rmt_led_strip/led_strip.cpp index 344ea35e81..fa43aa5950 100644 --- a/esphome/components/esp32_rmt_led_strip/led_strip.cpp +++ b/esphome/components/esp32_rmt_led_strip/led_strip.cpp @@ -35,7 +35,7 @@ static size_t IRAM_ATTR HOT encoder_callback(const void *data, size_t size, size if (symbols_free < RMT_SYMBOLS_PER_BYTE) { return 0; } - for (int32_t i = 0; i < RMT_SYMBOLS_PER_BYTE; i++) { + for (size_t i = 0; i < RMT_SYMBOLS_PER_BYTE; i++) { if (bytes[index] & (1 << (7 - i))) { symbols[i] = params->bit1; } else { diff --git a/esphome/components/fingerprint_grow/fingerprint_grow.cpp b/esphome/components/fingerprint_grow/fingerprint_grow.cpp index 54a267a404..eb7ede8fe9 100644 --- a/esphome/components/fingerprint_grow/fingerprint_grow.cpp +++ b/esphome/components/fingerprint_grow/fingerprint_grow.cpp @@ -80,7 +80,7 @@ void FingerprintGrowComponent::setup() { delay(20); // This delay guarantees the sensor will in fact be powered power. if (this->check_password_()) { - if (this->new_password_ != -1) { + if (this->new_password_ != std::numeric_limits::max()) { if (this->set_password_()) return; } else { diff --git a/esphome/components/fingerprint_grow/fingerprint_grow.h b/esphome/components/fingerprint_grow/fingerprint_grow.h index 1c3098ef14..590c709c22 100644 --- a/esphome/components/fingerprint_grow/fingerprint_grow.h +++ b/esphome/components/fingerprint_grow/fingerprint_grow.h @@ -6,6 +6,7 @@ #include "esphome/components/binary_sensor/binary_sensor.h" #include "esphome/components/uart/uart.h" +#include #include namespace esphome { @@ -177,7 +178,7 @@ class FingerprintGrowComponent : public PollingComponent, public uart::UARTDevic uint8_t address_[4] = {0xFF, 0xFF, 0xFF, 0xFF}; uint16_t capacity_ = 64; uint32_t password_ = 0x0; - uint32_t new_password_ = -1; + uint32_t new_password_ = std::numeric_limits::max(); GPIOPin *sensing_pin_{nullptr}; GPIOPin *sensor_power_pin_{nullptr}; uint8_t enrollment_image_ = 0; diff --git a/esphome/components/graphical_display_menu/graphical_display_menu.cpp b/esphome/components/graphical_display_menu/graphical_display_menu.cpp index 1a29536b46..2b120a746f 100644 --- a/esphome/components/graphical_display_menu/graphical_display_menu.cpp +++ b/esphome/components/graphical_display_menu/graphical_display_menu.cpp @@ -116,7 +116,7 @@ void GraphicalDisplayMenu::draw_menu_internal_(display::Display *display, const int number_items_fit_to_screen = 0; const int max_item_index = this->displayed_item_->items_size() - 1; - for (size_t i = 0; i <= max_item_index; i++) { + for (size_t i = 0; max_item_index >= 0 && i <= static_cast(max_item_index); i++) { const auto *item = this->displayed_item_->get_item(i); const bool selected = i == this->cursor_index_; const display::Rect item_dimensions = this->measure_item(display, item, bounds, selected); @@ -174,7 +174,8 @@ void GraphicalDisplayMenu::draw_menu_internal_(display::Display *display, const display->filled_rectangle(bounds->x, bounds->y, max_width, total_height, this->background_color_); auto y_offset = bounds->y; - for (size_t i = first_item_index; i <= last_item_index; i++) { + for (size_t i = static_cast(first_item_index); + last_item_index >= 0 && i <= static_cast(last_item_index); i++) { const auto *item = this->displayed_item_->get_item(i); const bool selected = i == this->cursor_index_; display::Rect dimensions = menu_dimensions[i]; diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp index 7ae3ec8b3b..53e378c41e 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp @@ -377,7 +377,7 @@ void I2SAudioSpeaker::speaker_task(void *params) { this_speaker->current_stream_info_.get_bits_per_sample() <= 16) { size_t len = bytes_read / sizeof(int16_t); int16_t *tmp_buf = (int16_t *) new_data; - for (int i = 0; i < len; i += 2) { + for (size_t i = 0; i < len; i += 2) { int16_t tmp = tmp_buf[i]; tmp_buf[i] = tmp_buf[i + 1]; tmp_buf[i + 1] = tmp; diff --git a/esphome/components/ili9xxx/ili9xxx_display.cpp b/esphome/components/ili9xxx/ili9xxx_display.cpp index ec0a860aa8..2a3d0edca7 100644 --- a/esphome/components/ili9xxx/ili9xxx_display.cpp +++ b/esphome/components/ili9xxx/ili9xxx_display.cpp @@ -325,7 +325,7 @@ void ILI9XXXDisplay::draw_pixels_at(int x_start, int y_start, int w, int h, cons // we could deal here with a non-zero y_offset, but if x_offset is zero, y_offset probably will be so don't bother this->write_array(ptr, w * h * 2); } else { - for (size_t y = 0; y != h; y++) { + for (size_t y = 0; y != static_cast(h); y++) { this->write_array(ptr + (y + y_offset) * stride + x_offset, w * 2); } } @@ -349,7 +349,7 @@ void ILI9XXXDisplay::draw_pixels_at(int x_start, int y_start, int w, int h, cons App.feed_wdt(); } // end of line? Skip to the next. - if (++pixel == w) { + if (++pixel == static_cast(w)) { pixel = 0; ptr += (x_pad + x_offset) * 2; } diff --git a/esphome/components/json/json_util.cpp b/esphome/components/json/json_util.cpp index 643f23f499..dbdf6e3486 100644 --- a/esphome/components/json/json_util.cpp +++ b/esphome/components/json/json_util.cpp @@ -19,15 +19,19 @@ std::string build_json(const json_build_t &f) { bool parse_json(const std::string &data, const json_parse_t &f) { // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson - JsonDocument doc = parse_json(data); + JsonDocument doc = parse_json(reinterpret_cast(data.c_str()), data.size()); if (doc.overflowed() || doc.isNull()) return false; return f(doc.as()); // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks) } -JsonDocument parse_json(const std::string &data) { +JsonDocument parse_json(const uint8_t *data, size_t len) { // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson + if (data == nullptr || len == 0) { + ESP_LOGE(TAG, "No data to parse"); + return JsonObject(); // return unbound object + } #ifdef USE_PSRAM auto doc_allocator = SpiRamAllocator(); JsonDocument json_document(&doc_allocator); @@ -38,7 +42,7 @@ JsonDocument parse_json(const std::string &data) { ESP_LOGE(TAG, "Could not allocate memory for JSON document!"); return JsonObject(); // return unbound object } - DeserializationError err = deserializeJson(json_document, data); + DeserializationError err = deserializeJson(json_document, data, len); if (err == DeserializationError::Ok) { return json_document; diff --git a/esphome/components/json/json_util.h b/esphome/components/json/json_util.h index a8f452d7d0..91cc84dc14 100644 --- a/esphome/components/json/json_util.h +++ b/esphome/components/json/json_util.h @@ -50,8 +50,13 @@ std::string build_json(const json_build_t &f); /// Parse a JSON string and run the provided json parse function if it's valid. bool parse_json(const std::string &data, const json_parse_t &f); + /// Parse a JSON string and return the root JsonDocument (or an unbound object on error) -JsonDocument parse_json(const std::string &data); +JsonDocument parse_json(const uint8_t *data, size_t len); +/// Parse a JSON string and return the root JsonDocument (or an unbound object on error) +inline JsonDocument parse_json(const std::string &data) { + return parse_json(reinterpret_cast(data.c_str()), data.size()); +} /// Builder class for creating JSON documents without lambdas class JsonBuilder { diff --git a/esphome/components/kamstrup_kmp/kamstrup_kmp.cpp b/esphome/components/kamstrup_kmp/kamstrup_kmp.cpp index c058c7b3aa..e5fa035682 100644 --- a/esphome/components/kamstrup_kmp/kamstrup_kmp.cpp +++ b/esphome/components/kamstrup_kmp/kamstrup_kmp.cpp @@ -22,7 +22,7 @@ void KamstrupKMPComponent::dump_config() { LOG_SENSOR(" ", "Flow", this->flow_sensor_); LOG_SENSOR(" ", "Volume", this->volume_sensor_); - for (int i = 0; i < this->custom_sensors_.size(); i++) { + for (size_t i = 0; i < this->custom_sensors_.size(); i++) { LOG_SENSOR(" ", "Custom Sensor", this->custom_sensors_[i]); ESP_LOGCONFIG(TAG, " Command: 0x%04X", this->custom_commands_[i]); } @@ -268,7 +268,7 @@ void KamstrupKMPComponent::set_sensor_value_(uint16_t command, float value, uint } // Custom sensors - for (int i = 0; i < this->custom_commands_.size(); i++) { + for (size_t i = 0; i < this->custom_commands_.size(); i++) { if (command == this->custom_commands_[i]) { this->custom_sensors_[i]->publish_state(value); } diff --git a/esphome/components/key_collector/key_collector.h b/esphome/components/key_collector/key_collector.h index 6e585ddd8e..35e8141ce5 100644 --- a/esphome/components/key_collector/key_collector.h +++ b/esphome/components/key_collector/key_collector.h @@ -13,8 +13,8 @@ class KeyCollector : public Component { void loop() override; void dump_config() override; void set_provider(key_provider::KeyProvider *provider); - void set_min_length(int min_length) { this->min_length_ = min_length; }; - void set_max_length(int max_length) { this->max_length_ = max_length; }; + void set_min_length(uint32_t min_length) { this->min_length_ = min_length; }; + void set_max_length(uint32_t max_length) { this->max_length_ = max_length; }; void set_start_keys(std::string start_keys) { this->start_keys_ = std::move(start_keys); }; void set_end_keys(std::string end_keys) { this->end_keys_ = std::move(end_keys); }; void set_end_key_required(bool end_key_required) { this->end_key_required_ = end_key_required; }; @@ -33,8 +33,8 @@ class KeyCollector : public Component { protected: void key_pressed_(uint8_t key); - int min_length_{0}; - int max_length_{0}; + uint32_t min_length_{0}; + uint32_t max_length_{0}; std::string start_keys_; std::string end_keys_; bool end_key_required_{false}; diff --git a/esphome/components/lm75b/__init__.py b/esphome/components/lm75b/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/lm75b/lm75b.cpp b/esphome/components/lm75b/lm75b.cpp new file mode 100644 index 0000000000..19398eda85 --- /dev/null +++ b/esphome/components/lm75b/lm75b.cpp @@ -0,0 +1,39 @@ +#include "lm75b.h" +#include "esphome/core/log.h" +#include "esphome/core/hal.h" + +namespace esphome { +namespace lm75b { + +static const char *const TAG = "lm75b"; + +void LM75BComponent::dump_config() { + ESP_LOGCONFIG(TAG, "LM75B:"); + LOG_I2C_DEVICE(this); + if (this->is_failed()) { + ESP_LOGE(TAG, "Setting up LM75B failed!"); + } + LOG_UPDATE_INTERVAL(this); + LOG_SENSOR(" ", "Temperature", this); +} + +void LM75BComponent::update() { + // Create a temporary buffer + uint8_t buff[2]; + if (this->read_register(LM75B_REG_TEMPERATURE, buff, 2) != i2c::ERROR_OK) { + this->status_set_warning(); + return; + } + // Obtain combined 16-bit value + int16_t raw_temperature = (buff[0] << 8) | buff[1]; + // Read the 11-bit raw temperature value + raw_temperature >>= 5; + // Publish the temperature in °C + this->publish_state(raw_temperature * 0.125); + if (this->status_has_warning()) { + this->status_clear_warning(); + } +} + +} // namespace lm75b +} // namespace esphome diff --git a/esphome/components/lm75b/lm75b.h b/esphome/components/lm75b/lm75b.h new file mode 100644 index 0000000000..79d9fa3f32 --- /dev/null +++ b/esphome/components/lm75b/lm75b.h @@ -0,0 +1,19 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/i2c/i2c.h" + +namespace esphome { +namespace lm75b { + +static const uint8_t LM75B_REG_TEMPERATURE = 0x00; + +class LM75BComponent : public PollingComponent, public i2c::I2CDevice, public sensor::Sensor { + public: + void dump_config() override; + void update() override; +}; + +} // namespace lm75b +} // namespace esphome diff --git a/esphome/components/lm75b/sensor.py b/esphome/components/lm75b/sensor.py new file mode 100644 index 0000000000..335446b62f --- /dev/null +++ b/esphome/components/lm75b/sensor.py @@ -0,0 +1,34 @@ +import esphome.codegen as cg +from esphome.components import i2c, sensor +import esphome.config_validation as cv +from esphome.const import ( + DEVICE_CLASS_TEMPERATURE, + STATE_CLASS_MEASUREMENT, + UNIT_CELSIUS, +) + +CODEOWNERS = ["@beormund"] +DEPENDENCIES = ["i2c"] + +lm75b_ns = cg.esphome_ns.namespace("lm75b") +LM75BComponent = lm75b_ns.class_( + "LM75BComponent", cg.PollingComponent, i2c.I2CDevice, sensor.Sensor +) + +CONFIG_SCHEMA = ( + sensor.sensor_schema( + LM75BComponent, + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=3, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x48)) +) + + +async def to_code(config): + var = await sensor.new_sensor(config) + await cg.register_component(var, config) + await i2c.register_i2c_device(var, config) diff --git a/esphome/components/ltr501/ltr501.cpp b/esphome/components/ltr501/ltr501.cpp index b249d23666..be5a4ddccf 100644 --- a/esphome/components/ltr501/ltr501.cpp +++ b/esphome/components/ltr501/ltr501.cpp @@ -2,6 +2,7 @@ #include "esphome/core/application.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" +#include using esphome::i2c::ErrorCode; @@ -28,30 +29,30 @@ bool operator!=(const GainTimePair &lhs, const GainTimePair &rhs) { template T get_next(const T (&array)[size], const T val) { size_t i = 0; - size_t idx = -1; - while (idx == -1 && i < size) { + size_t idx = std::numeric_limits::max(); + while (idx == std::numeric_limits::max() && i < size) { if (array[i] == val) { idx = i; break; } i++; } - if (idx == -1 || i + 1 >= size) + if (idx == std::numeric_limits::max() || i + 1 >= size) return val; return array[i + 1]; } template T get_prev(const T (&array)[size], const T val) { size_t i = size - 1; - size_t idx = -1; - while (idx == -1 && i > 0) { + size_t idx = std::numeric_limits::max(); + while (idx == std::numeric_limits::max() && i > 0) { if (array[i] == val) { idx = i; break; } i--; } - if (idx == -1 || i == 0) + if (idx == std::numeric_limits::max() || i == 0) return val; return array[i - 1]; } diff --git a/esphome/components/ltr_als_ps/ltr_als_ps.cpp b/esphome/components/ltr_als_ps/ltr_als_ps.cpp index bf27c01e26..c3ea5848c8 100644 --- a/esphome/components/ltr_als_ps/ltr_als_ps.cpp +++ b/esphome/components/ltr_als_ps/ltr_als_ps.cpp @@ -2,6 +2,7 @@ #include "esphome/core/application.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" +#include using esphome::i2c::ErrorCode; @@ -14,30 +15,30 @@ static const uint8_t MAX_TRIES = 5; template T get_next(const T (&array)[size], const T val) { size_t i = 0; - size_t idx = -1; - while (idx == -1 && i < size) { + size_t idx = std::numeric_limits::max(); + while (idx == std::numeric_limits::max() && i < size) { if (array[i] == val) { idx = i; break; } i++; } - if (idx == -1 || i + 1 >= size) + if (idx == std::numeric_limits::max() || i + 1 >= size) return val; return array[i + 1]; } template T get_prev(const T (&array)[size], const T val) { size_t i = size - 1; - size_t idx = -1; - while (idx == -1 && i > 0) { + size_t idx = std::numeric_limits::max(); + while (idx == std::numeric_limits::max() && i > 0) { if (array[i] == val) { idx = i; break; } i--; } - if (idx == -1 || i == 0) + if (idx == std::numeric_limits::max() || i == 0) return val; return array[i - 1]; } diff --git a/esphome/components/matrix_keypad/matrix_keypad.h b/esphome/components/matrix_keypad/matrix_keypad.h index 8b309b42c2..258ab4fadc 100644 --- a/esphome/components/matrix_keypad/matrix_keypad.h +++ b/esphome/components/matrix_keypad/matrix_keypad.h @@ -29,9 +29,9 @@ class MatrixKeypad : public key_provider::KeyProvider, public Component { void set_columns(std::vector pins) { columns_ = std::move(pins); }; void set_rows(std::vector pins) { rows_ = std::move(pins); }; void set_keys(std::string keys) { keys_ = std::move(keys); }; - void set_debounce_time(int debounce_time) { debounce_time_ = debounce_time; }; - void set_has_diodes(int has_diodes) { has_diodes_ = has_diodes; }; - void set_has_pulldowns(int has_pulldowns) { has_pulldowns_ = has_pulldowns; }; + void set_debounce_time(uint32_t debounce_time) { debounce_time_ = debounce_time; }; + void set_has_diodes(bool has_diodes) { has_diodes_ = has_diodes; }; + void set_has_pulldowns(bool has_pulldowns) { has_pulldowns_ = has_pulldowns; }; void register_listener(MatrixKeypadListener *listener); void register_key_trigger(MatrixKeyTrigger *trig); @@ -40,7 +40,7 @@ class MatrixKeypad : public key_provider::KeyProvider, public Component { std::vector rows_; std::vector columns_; std::string keys_; - int debounce_time_ = 0; + uint32_t debounce_time_ = 0; bool has_diodes_{false}; bool has_pulldowns_{false}; int pressed_key_ = -1; diff --git a/esphome/components/max7219digit/max7219digit.cpp b/esphome/components/max7219digit/max7219digit.cpp index 9b9921d2f0..6df3c4d7c8 100644 --- a/esphome/components/max7219digit/max7219digit.cpp +++ b/esphome/components/max7219digit/max7219digit.cpp @@ -90,7 +90,7 @@ void MAX7219Component::loop() { } if (this->scroll_mode_ == ScrollMode::STOP) { - if (this->stepsleft_ + get_width_internal() == first_line_size + 1) { + if (static_cast(this->stepsleft_ + get_width_internal()) == first_line_size + 1) { if (millis_since_last_scroll < this->scroll_dwell_) { ESP_LOGVV(TAG, "Dwell time at end of string in case of stop at end. Step %d, since last scroll %d, dwell %d.", this->stepsleft_, millis_since_last_scroll, this->scroll_dwell_); diff --git a/esphome/components/mipi/__init__.py b/esphome/components/mipi/__init__.py index f670a5913d..7e687cabaa 100644 --- a/esphome/components/mipi/__init__.py +++ b/esphome/components/mipi/__init__.py @@ -343,11 +343,7 @@ class DriverChip: ) offset_height = native_height - height - offset_height # Swap default dimensions if swap_xy is set, or if rotation is 90/270 and we are not using a buffer - rotated = not requires_buffer(config) and config.get(CONF_ROTATION, 0) in ( - 90, - 270, - ) - if transform.get(CONF_SWAP_XY) is True or rotated: + if transform.get(CONF_SWAP_XY) is True: width, height = height, width offset_height, offset_width = offset_width, offset_height return width, height, offset_width, offset_height diff --git a/esphome/components/mipi_spi/display.py b/esphome/components/mipi_spi/display.py index e891e2daad..52b5b86fba 100644 --- a/esphome/components/mipi_spi/display.py +++ b/esphome/components/mipi_spi/display.py @@ -380,25 +380,41 @@ def get_instance(config): bus_type = BusTypes[bus_type] buffer_type = cg.uint8 if color_depth == 8 else cg.uint16 frac = denominator(config) - rotation = DISPLAY_ROTATIONS[ + rotation = ( 0 if model.rotation_as_transform(config) else config.get(CONF_ROTATION, 0) - ] + ) templateargs = [ buffer_type, bufferpixels, config[CONF_BYTE_ORDER] == "big_endian", display_pixel_mode, bus_type, - width, - height, - offset_width, - offset_height, ] # If a buffer is required, use MipiSpiBuffer, otherwise use MipiSpi if requires_buffer(config): - templateargs.append(rotation) - templateargs.append(frac) + templateargs.extend( + [ + width, + height, + offset_width, + offset_height, + DISPLAY_ROTATIONS[rotation], + frac, + ] + ) return MipiSpiBuffer, templateargs + # Swap height and width if the display is rotated 90 or 270 degrees in software + if rotation in (90, 270): + width, height = height, width + offset_width, offset_height = offset_height, offset_width + templateargs.extend( + [ + width, + height, + offset_width, + offset_height, + ] + ) return MipiSpi, templateargs diff --git a/esphome/components/mixer/speaker/mixer_speaker.cpp b/esphome/components/mixer/speaker/mixer_speaker.cpp index fc0517c7be..b0b64f5709 100644 --- a/esphome/components/mixer/speaker/mixer_speaker.cpp +++ b/esphome/components/mixer/speaker/mixer_speaker.cpp @@ -572,7 +572,7 @@ void MixerSpeaker::audio_mixer_task(void *params) { } } else { // Determine how many frames to mix - for (int i = 0; i < transfer_buffers_with_data.size(); ++i) { + for (size_t i = 0; i < transfer_buffers_with_data.size(); ++i) { const uint32_t frames_available_in_buffer = speakers_with_data[i]->get_audio_stream_info().bytes_to_frames(transfer_buffers_with_data[i]->available()); frames_to_mix = std::min(frames_to_mix, frames_available_in_buffer); @@ -581,7 +581,7 @@ void MixerSpeaker::audio_mixer_task(void *params) { audio::AudioStreamInfo primary_stream_info = speakers_with_data[0]->get_audio_stream_info(); // Mix two streams together - for (int i = 1; i < transfer_buffers_with_data.size(); ++i) { + for (size_t i = 1; i < transfer_buffers_with_data.size(); ++i) { mix_audio_samples(primary_buffer, primary_stream_info, reinterpret_cast(transfer_buffers_with_data[i]->get_buffer_start()), speakers_with_data[i]->get_audio_stream_info(), @@ -596,7 +596,7 @@ void MixerSpeaker::audio_mixer_task(void *params) { } // Update source transfer buffer lengths and add new audio durations to the source speaker pending playbacks - for (int i = 0; i < transfer_buffers_with_data.size(); ++i) { + for (size_t i = 0; i < transfer_buffers_with_data.size(); ++i) { transfer_buffers_with_data[i]->decrease_buffer_length( speakers_with_data[i]->get_audio_stream_info().frames_to_bytes(frames_to_mix)); speakers_with_data[i]->pending_playback_frames_ += frames_to_mix; diff --git a/esphome/components/nau7802/nau7802.cpp b/esphome/components/nau7802/nau7802.cpp index acdca03fdb..6a31b754f7 100644 --- a/esphome/components/nau7802/nau7802.cpp +++ b/esphome/components/nau7802/nau7802.cpp @@ -218,7 +218,7 @@ void NAU7802Sensor::dump_config() { void NAU7802Sensor::write_value_(uint8_t start_reg, size_t size, int32_t value) { uint8_t data[4]; - for (int i = 0; i < size; i++) { + for (size_t i = 0; i < size; i++) { data[i] = 0xFF & (value >> (size - 1 - i) * 8); } this->write_register(start_reg, data, size); @@ -228,7 +228,7 @@ int32_t NAU7802Sensor::read_value_(uint8_t start_reg, size_t size) { uint8_t data[4]; this->read_register(start_reg, data, size); int32_t result = 0; - for (int i = 0; i < size; i++) { + for (size_t i = 0; i < size; i++) { result |= data[i] << (size - 1 - i) * 8; } // extend sign bit diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index b348bc9920..0ce9d02e97 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -77,7 +77,7 @@ bool Nextion::check_connect_() { this->recv_ret_string_(response, 0, false); if (!response.empty() && response[0] == 0x1A) { // Swallow invalid variable name responses that may be caused by the above commands - ESP_LOGD(TAG, "0x1A error ignored (setup)"); + ESP_LOGV(TAG, "0x1A error ignored (setup)"); return false; } if (response.empty() || response.find("comok") == std::string::npos) { @@ -334,7 +334,7 @@ void Nextion::loop() { this->started_ms_ = App.get_loop_component_start_time(); if (this->started_ms_ + this->startup_override_ms_ < App.get_loop_component_start_time()) { - ESP_LOGD(TAG, "Manual ready set"); + ESP_LOGV(TAG, "Manual ready set"); this->connection_state_.nextion_reports_is_setup_ = true; } } @@ -544,7 +544,7 @@ void Nextion::process_nextion_commands_() { uint8_t page_id = to_process[0]; uint8_t component_id = to_process[1]; uint8_t touch_event = to_process[2]; // 0 -> release, 1 -> press - ESP_LOGD(TAG, "Touch %s: page %u comp %u", touch_event ? "PRESS" : "RELEASE", page_id, component_id); + ESP_LOGV(TAG, "Touch %s: page %u comp %u", touch_event ? "PRESS" : "RELEASE", page_id, component_id); for (auto *touch : this->touch_) { touch->process_touch(page_id, component_id, touch_event != 0); } @@ -559,7 +559,7 @@ void Nextion::process_nextion_commands_() { } uint8_t page_id = to_process[0]; - ESP_LOGD(TAG, "New page: %u", page_id); + ESP_LOGV(TAG, "New page: %u", page_id); this->page_callback_.call(page_id); break; } @@ -577,7 +577,7 @@ void Nextion::process_nextion_commands_() { const uint16_t x = (uint16_t(to_process[0]) << 8) | to_process[1]; const uint16_t y = (uint16_t(to_process[2]) << 8) | to_process[3]; const uint8_t touch_event = to_process[4]; // 0 -> release, 1 -> press - ESP_LOGD(TAG, "Touch %s at %u,%u", touch_event ? "PRESS" : "RELEASE", x, y); + ESP_LOGV(TAG, "Touch %s at %u,%u", touch_event ? "PRESS" : "RELEASE", x, y); break; } @@ -676,7 +676,7 @@ void Nextion::process_nextion_commands_() { } case 0x88: // system successful start up { - ESP_LOGD(TAG, "System start: %zu", to_process_length); + ESP_LOGV(TAG, "System start: %zu", to_process_length); this->connection_state_.nextion_reports_is_setup_ = true; break; } @@ -922,7 +922,7 @@ void Nextion::set_nextion_sensor_state(NextionQueueType queue_type, const std::s } void Nextion::set_nextion_text_state(const std::string &name, const std::string &state) { - ESP_LOGD(TAG, "State: %s='%s'", name.c_str(), state.c_str()); + ESP_LOGV(TAG, "State: %s='%s'", name.c_str(), state.c_str()); for (auto *sensor : this->textsensortype_) { if (name == sensor->get_variable_name()) { @@ -933,7 +933,7 @@ void Nextion::set_nextion_text_state(const std::string &name, const std::string } void Nextion::all_components_send_state_(bool force_update) { - ESP_LOGD(TAG, "Send states"); + ESP_LOGV(TAG, "Send states"); for (auto *binarysensortype : this->binarysensortype_) { if (force_update || binarysensortype->get_needs_to_send_update()) binarysensortype->send_state_to_nextion(); diff --git a/esphome/components/online_image/bmp_image.cpp b/esphome/components/online_image/bmp_image.cpp index f55c9f1813..676a2efca9 100644 --- a/esphome/components/online_image/bmp_image.cpp +++ b/esphome/components/online_image/bmp_image.cpp @@ -117,7 +117,8 @@ int HOT BmpDecoder::decode(uint8_t *buffer, size_t size) { this->paint_index_++; this->current_index_ += 3; index += 3; - if (x == this->width_ - 1 && this->padding_bytes_ > 0) { + size_t last_col = static_cast(this->width_) - 1; + if (x == last_col && this->padding_bytes_ > 0) { index += this->padding_bytes_; this->current_index_ += this->padding_bytes_; } diff --git a/esphome/components/online_image/jpeg_image.cpp b/esphome/components/online_image/jpeg_image.cpp index e5ee3dd8bf..10586091d5 100644 --- a/esphome/components/online_image/jpeg_image.cpp +++ b/esphome/components/online_image/jpeg_image.cpp @@ -25,8 +25,10 @@ static int draw_callback(JPEGDRAW *jpeg) { // to avoid crashing. App.feed_wdt(); size_t position = 0; - for (size_t y = 0; y < jpeg->iHeight; y++) { - for (size_t x = 0; x < jpeg->iWidth; x++) { + size_t height = static_cast(jpeg->iHeight); + size_t width = static_cast(jpeg->iWidth); + for (size_t y = 0; y < height; y++) { + for (size_t x = 0; x < width; x++) { auto rg = decode_value(jpeg->pPixels[position++]); auto ba = decode_value(jpeg->pPixels[position++]); Color color(rg[1], rg[0], ba[1], ba[0]); diff --git a/esphome/components/pid/pid_controller.cpp b/esphome/components/pid/pid_controller.cpp index 1a16f14542..5d7aecdb05 100644 --- a/esphome/components/pid/pid_controller.cpp +++ b/esphome/components/pid/pid_controller.cpp @@ -104,7 +104,7 @@ float PIDController::weighted_average_(std::deque &list, float new_value, list.push_front(new_value); // keep only 'samples' readings, by popping off the back of the list - while (list.size() > samples) + while (samples > 0 && list.size() > static_cast(samples)) list.pop_back(); // calculate and return the average of all values in the list diff --git a/esphome/components/qmc5883l/qmc5883l.cpp b/esphome/components/qmc5883l/qmc5883l.cpp index c9196f2469..d2041a2d52 100644 --- a/esphome/components/qmc5883l/qmc5883l.cpp +++ b/esphome/components/qmc5883l/qmc5883l.cpp @@ -8,6 +8,7 @@ namespace esphome { namespace qmc5883l { static const char *const TAG = "qmc5883l"; + static const uint8_t QMC5883L_ADDRESS = 0x0D; static const uint8_t QMC5883L_REGISTER_DATA_X_LSB = 0x00; @@ -32,6 +33,10 @@ void QMC5883LComponent::setup() { } delay(10); + if (this->drdy_pin_) { + this->drdy_pin_->setup(); + } + uint8_t control_1 = 0; control_1 |= 0b01 << 0; // MODE (Mode) -> 0b00=standby, 0b01=continuous control_1 |= this->datarate_ << 2; @@ -64,6 +69,7 @@ void QMC5883LComponent::setup() { high_freq_.start(); } } + void QMC5883LComponent::dump_config() { ESP_LOGCONFIG(TAG, "QMC5883L:"); LOG_I2C_DEVICE(this); @@ -77,11 +83,20 @@ void QMC5883LComponent::dump_config() { LOG_SENSOR(" ", "Z Axis", this->z_sensor_); LOG_SENSOR(" ", "Heading", this->heading_sensor_); LOG_SENSOR(" ", "Temperature", this->temperature_sensor_); + LOG_PIN(" DRDY Pin: ", this->drdy_pin_); } + float QMC5883LComponent::get_setup_priority() const { return setup_priority::DATA; } + void QMC5883LComponent::update() { i2c::ErrorCode err; uint8_t status = false; + + // If DRDY pin is configured and the data is not ready return. + if (this->drdy_pin_ && !this->drdy_pin_->digital_read()) { + return; + } + // Status byte gets cleared when data is read, so we have to read this first. // If status and two axes are desired, it's possible to save one byte of traffic by enabling // ROL_PNT in setup and reading 7 bytes starting at the status register. diff --git a/esphome/components/qmc5883l/qmc5883l.h b/esphome/components/qmc5883l/qmc5883l.h index 3202e37780..5ba7180e23 100644 --- a/esphome/components/qmc5883l/qmc5883l.h +++ b/esphome/components/qmc5883l/qmc5883l.h @@ -3,6 +3,7 @@ #include "esphome/core/component.h" #include "esphome/components/sensor/sensor.h" #include "esphome/components/i2c/i2c.h" +#include "esphome/core/hal.h" namespace esphome { namespace qmc5883l { @@ -33,6 +34,7 @@ class QMC5883LComponent : public PollingComponent, public i2c::I2CDevice { float get_setup_priority() const override; void update() override; + void set_drdy_pin(GPIOPin *pin) { drdy_pin_ = pin; } void set_datarate(QMC5883LDatarate datarate) { datarate_ = datarate; } void set_range(QMC5883LRange range) { range_ = range; } void set_oversampling(QMC5883LOversampling oversampling) { oversampling_ = oversampling; } @@ -51,6 +53,7 @@ class QMC5883LComponent : public PollingComponent, public i2c::I2CDevice { sensor::Sensor *z_sensor_{nullptr}; sensor::Sensor *heading_sensor_{nullptr}; sensor::Sensor *temperature_sensor_{nullptr}; + GPIOPin *drdy_pin_{nullptr}; enum ErrorCode { NONE = 0, COMMUNICATION_FAILED, diff --git a/esphome/components/qmc5883l/sensor.py b/esphome/components/qmc5883l/sensor.py index ade286cb9e..b79e370a05 100644 --- a/esphome/components/qmc5883l/sensor.py +++ b/esphome/components/qmc5883l/sensor.py @@ -1,8 +1,12 @@ +import logging + +from esphome import pins import esphome.codegen as cg from esphome.components import i2c, sensor import esphome.config_validation as cv from esphome.const import ( CONF_ADDRESS, + CONF_DATA_RATE, CONF_FIELD_STRENGTH_X, CONF_FIELD_STRENGTH_Y, CONF_FIELD_STRENGTH_Z, @@ -21,6 +25,10 @@ from esphome.const import ( UNIT_MICROTESLA, ) +_LOGGER = logging.getLogger(__name__) + +CONF_DRDY_PIN = "drdy_pin" + DEPENDENCIES = ["i2c"] qmc5883l_ns = cg.esphome_ns.namespace("qmc5883l") @@ -52,6 +60,18 @@ QMC5883LOversamplings = { } +def validate_config(config): + if ( + config[CONF_UPDATE_INTERVAL].total_milliseconds < 15 + and CONF_DRDY_PIN not in config + ): + _LOGGER.warning( + "[qmc5883l] 'update_interval' is less than 15ms and 'drdy_pin' is " + "not configured, this may result in I2C errors" + ) + return config + + def validate_enum(enum_values, units=None, int=True): _units = [] if units is not None: @@ -88,7 +108,7 @@ temperature_schema = sensor.sensor_schema( state_class=STATE_CLASS_MEASUREMENT, ) -CONFIG_SCHEMA = ( +CONFIG_SCHEMA = cv.All( cv.Schema( { cv.GenerateID(): cv.declare_id(QMC5883LComponent), @@ -104,29 +124,25 @@ CONFIG_SCHEMA = ( cv.Optional(CONF_FIELD_STRENGTH_Z): field_strength_schema, cv.Optional(CONF_HEADING): heading_schema, cv.Optional(CONF_TEMPERATURE): temperature_schema, + cv.Optional(CONF_DRDY_PIN): pins.gpio_input_pin_schema, + cv.Optional(CONF_DATA_RATE, default="200hz"): validate_enum( + QMC5883LDatarates, units=["hz", "Hz"] + ), } ) .extend(cv.polling_component_schema("60s")) - .extend(i2c.i2c_device_schema(0x0D)) + .extend(i2c.i2c_device_schema(0x0D)), + validate_config, ) -def auto_data_rate(config): - interval_sec = config[CONF_UPDATE_INTERVAL].total_milliseconds / 1000 - interval_hz = 1.0 / interval_sec - for datarate in sorted(QMC5883LDatarates.keys()): - if float(datarate) >= interval_hz: - return QMC5883LDatarates[datarate] - return QMC5883LDatarates[200] - - async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) await i2c.register_i2c_device(var, config) cg.add(var.set_oversampling(config[CONF_OVERSAMPLING])) - cg.add(var.set_datarate(auto_data_rate(config))) + cg.add(var.set_datarate(config[CONF_DATA_RATE])) cg.add(var.set_range(config[CONF_RANGE])) if CONF_FIELD_STRENGTH_X in config: sens = await sensor.new_sensor(config[CONF_FIELD_STRENGTH_X]) @@ -143,3 +159,6 @@ async def to_code(config): if CONF_TEMPERATURE in config: sens = await sensor.new_sensor(config[CONF_TEMPERATURE]) cg.add(var.set_temperature_sensor(sens)) + if CONF_DRDY_PIN in config: + pin = await cg.gpio_pin_expression(config[CONF_DRDY_PIN]) + cg.add(var.set_drdy_pin(pin)) diff --git a/esphome/components/remote_base/gobox_protocol.cpp b/esphome/components/remote_base/gobox_protocol.cpp index 54e0dff663..4f6de5e59e 100644 --- a/esphome/components/remote_base/gobox_protocol.cpp +++ b/esphome/components/remote_base/gobox_protocol.cpp @@ -10,8 +10,8 @@ constexpr uint32_t BIT_MARK_US = 580; // 70us seems like a safe time delta for constexpr uint32_t BIT_ONE_SPACE_US = 1640; constexpr uint32_t BIT_ZERO_SPACE_US = 545; constexpr uint64_t HEADER = 0b011001001100010uL; // 15 bits -constexpr uint64_t HEADER_SIZE = 15; -constexpr uint64_t CODE_SIZE = 17; +constexpr size_t HEADER_SIZE = 15; +constexpr size_t CODE_SIZE = 17; void GoboxProtocol::dump_timings_(const RawTimings &timings) const { ESP_LOGD(TAG, "Gobox: size=%u", timings.size()); @@ -39,7 +39,7 @@ void GoboxProtocol::encode(RemoteTransmitData *dst, const GoboxData &data) { } optional GoboxProtocol::decode(RemoteReceiveData src) { - if (src.size() < ((HEADER_SIZE + CODE_SIZE) * 2 + 1)) { + if (static_cast(src.size()) < ((HEADER_SIZE + CODE_SIZE) * 2 + 1)) { return {}; } diff --git a/esphome/components/sonoff_d1/sonoff_d1.cpp b/esphome/components/sonoff_d1/sonoff_d1.cpp index e3d55681c5..cd09f31dd7 100644 --- a/esphome/components/sonoff_d1/sonoff_d1.cpp +++ b/esphome/components/sonoff_d1/sonoff_d1.cpp @@ -50,7 +50,7 @@ static const char *const TAG = "sonoff_d1"; uint8_t SonoffD1Output::calc_checksum_(const uint8_t *cmd, const size_t len) { uint8_t crc = 0; - for (int i = 2; i < len - 1; i++) { + for (size_t i = 2; i < len - 1; i++) { crc += cmd[i]; } return crc; diff --git a/esphome/components/st7567_i2c/st7567_i2c.cpp b/esphome/components/st7567_i2c/st7567_i2c.cpp index 710e473b11..14c21d5148 100644 --- a/esphome/components/st7567_i2c/st7567_i2c.cpp +++ b/esphome/components/st7567_i2c/st7567_i2c.cpp @@ -50,8 +50,10 @@ void HOT I2CST7567::write_display_data() { static const size_t BLOCK_SIZE = 64; for (uint8_t x = 0; x < (uint8_t) this->get_width_internal(); x += BLOCK_SIZE) { + size_t remaining = static_cast(this->get_width_internal()) - x; + size_t chunk = remaining > BLOCK_SIZE ? BLOCK_SIZE : remaining; this->write_register(esphome::st7567_base::ST7567_SET_START_LINE, &buffer_[y * this->get_width_internal() + x], - this->get_width_internal() - x > BLOCK_SIZE ? BLOCK_SIZE : this->get_width_internal() - x); + chunk); } } } diff --git a/esphome/components/st7789v/st7789v.cpp b/esphome/components/st7789v/st7789v.cpp index 44f2293ac4..ade9c1126f 100644 --- a/esphome/components/st7789v/st7789v.cpp +++ b/esphome/components/st7789v/st7789v.cpp @@ -176,8 +176,9 @@ void ST7789V::write_display_data() { if (this->eightbitcolor_) { uint8_t temp_buffer[TEMP_BUFFER_SIZE]; size_t temp_index = 0; - for (int line = 0; line < this->get_buffer_length_(); line = line + this->get_width_internal()) { - for (int index = 0; index < this->get_width_internal(); ++index) { + size_t width = static_cast(this->get_width_internal()); + for (size_t line = 0; line < this->get_buffer_length_(); line += width) { + for (size_t index = 0; index < width; ++index) { auto color = display::ColorUtil::color_to_565( display::ColorUtil::to_color(this->buffer_[index + line], display::ColorOrder::COLOR_ORDER_RGB, display::ColorBitness::COLOR_BITNESS_332, true)); diff --git a/esphome/components/statsd/statsd.cpp b/esphome/components/statsd/statsd.cpp index 05f71c7b24..7729f36858 100644 --- a/esphome/components/statsd/statsd.cpp +++ b/esphome/components/statsd/statsd.cpp @@ -151,7 +151,7 @@ void StatsdComponent::send_(std::string *out) { int n_bytes = this->sock_->sendto(out->c_str(), out->length(), 0, reinterpret_cast(&this->destination_), sizeof(this->destination_)); - if (n_bytes != out->length()) { + if (n_bytes != static_cast(out->length())) { ESP_LOGE(TAG, "Failed to send UDP packed (%d of %d)", n_bytes, out->length()); } #endif diff --git a/esphome/components/tuya/select/tuya_select.cpp b/esphome/components/tuya/select/tuya_select.cpp index 07b0ff2815..91ddbc77ec 100644 --- a/esphome/components/tuya/select/tuya_select.cpp +++ b/esphome/components/tuya/select/tuya_select.cpp @@ -50,7 +50,7 @@ void TuyaSelect::dump_config() { " Options are:", this->select_id_, this->is_int_ ? "int" : "enum"); auto options = this->traits.get_options(); - for (auto i = 0; i < this->mappings_.size(); i++) { + for (size_t i = 0; i < this->mappings_.size(); i++) { ESP_LOGCONFIG(TAG, " %i: %s", this->mappings_.at(i), options.at(i).c_str()); } } diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 621f626569..2e083d4c68 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -334,9 +334,9 @@ void WiFiComponent::set_sta(const WiFiAP &ap) { } void WiFiComponent::clear_sta() { this->sta_.clear(); } void WiFiComponent::save_wifi_sta(const std::string &ssid, const std::string &password) { - SavedWifiSettings save{}; // zero-initialized - strncpy(save.ssid, ssid.c_str(), sizeof(save.ssid) - 1); - strncpy(save.password, password.c_str(), sizeof(save.password) - 1); + SavedWifiSettings save{}; // zero-initialized - all bytes set to \0, guaranteeing null termination + strncpy(save.ssid, ssid.c_str(), sizeof(save.ssid) - 1); // max 32 chars, byte 32 remains \0 + strncpy(save.password, password.c_str(), sizeof(save.password) - 1); // max 64 chars, byte 64 remains \0 this->pref_.save(&save); // ensure it's written immediately global_preferences->sync(); diff --git a/esphome/components/zwave_proxy/zwave_proxy.cpp b/esphome/components/zwave_proxy/zwave_proxy.cpp index 70932da87c..a26a9b2335 100644 --- a/esphome/components/zwave_proxy/zwave_proxy.cpp +++ b/esphome/components/zwave_proxy/zwave_proxy.cpp @@ -101,15 +101,7 @@ void ZWaveProxy::process_uart_() { // Store the 4-byte Home ID, which starts at offset 4, and notify connected clients if it changed // The frame parser has already validated the checksum and ensured all bytes are present if (this->set_home_id(&this->buffer_[4])) { - api::ZWaveProxyRequest msg; - msg.type = api::enums::ZWAVE_PROXY_REQUEST_TYPE_HOME_ID_CHANGE; - msg.data = this->home_id_.data(); - msg.data_len = this->home_id_.size(); - if (api::global_api_server != nullptr) { - // We could add code to manage a second subscription type, but, since this message is - // very infrequent and small, we simply send it to all clients - api::global_api_server->on_zwave_proxy_request(msg); - } + this->send_homeid_changed_msg_(); } } ESP_LOGV(TAG, "Sending to client: %s", YESNO(this->api_connection_ != nullptr)); @@ -135,6 +127,13 @@ void ZWaveProxy::dump_config() { format_hex_pretty(this->home_id_.data(), this->home_id_.size(), ':', false).c_str()); } +void ZWaveProxy::api_connection_authenticated(api::APIConnection *conn) { + if (this->home_id_ready_) { + // If a client just authenticated & HomeID is ready, send the current HomeID + this->send_homeid_changed_msg_(conn); + } +} + void ZWaveProxy::zwave_proxy_request(api::APIConnection *api_connection, api::enums::ZWaveProxyRequestType type) { switch (type) { case api::enums::ZWAVE_PROXY_REQUEST_TYPE_SUBSCRIBE: @@ -178,6 +177,21 @@ void ZWaveProxy::send_frame(const uint8_t *data, size_t length) { this->write_array(data, length); } +void ZWaveProxy::send_homeid_changed_msg_(api::APIConnection *conn) { + api::ZWaveProxyRequest msg; + msg.type = api::enums::ZWAVE_PROXY_REQUEST_TYPE_HOME_ID_CHANGE; + msg.data = this->home_id_.data(); + msg.data_len = this->home_id_.size(); + if (conn != nullptr) { + // Send to specific connection + conn->send_message(msg, api::ZWaveProxyRequest::MESSAGE_TYPE); + } else if (api::global_api_server != nullptr) { + // We could add code to manage a second subscription type, but, since this message is + // very infrequent and small, we simply send it to all clients + api::global_api_server->on_zwave_proxy_request(msg); + } +} + void ZWaveProxy::send_simple_command_(const uint8_t command_id) { // Send a simple Z-Wave command with no parameters // Frame format: [SOF][LENGTH][TYPE][CMD][CHECKSUM] diff --git a/esphome/components/zwave_proxy/zwave_proxy.h b/esphome/components/zwave_proxy/zwave_proxy.h index a9123a81ca..20d9090d98 100644 --- a/esphome/components/zwave_proxy/zwave_proxy.h +++ b/esphome/components/zwave_proxy/zwave_proxy.h @@ -49,6 +49,7 @@ class ZWaveProxy : public uart::UARTDevice, public Component { float get_setup_priority() const override; bool can_proceed() override; + void api_connection_authenticated(api::APIConnection *conn); void zwave_proxy_request(api::APIConnection *api_connection, api::enums::ZWaveProxyRequestType type); api::APIConnection *get_api_connection() { return this->api_connection_; } @@ -61,6 +62,7 @@ class ZWaveProxy : public uart::UARTDevice, public Component { void send_frame(const uint8_t *data, size_t length); protected: + void send_homeid_changed_msg_(api::APIConnection *conn = nullptr); void send_simple_command_(uint8_t command_id); bool parse_byte_(uint8_t byte); // Returns true if frame parsing was completed (a frame is ready in the buffer) void parse_start_(uint8_t byte); diff --git a/script/setup b/script/setup index 1bd7c44575..8cad7017ff 100755 --- a/script/setup +++ b/script/setup @@ -22,8 +22,6 @@ uv pip install -e ".[dev,test]" --config-settings editable_mode=compat pre-commit install -script/platformio_install_deps.py platformio.ini --libraries --tools --platforms - mkdir -p .temp echo diff --git a/script/setup.bat b/script/setup.bat index f89d5aea1a..003ea31b36 100644 --- a/script/setup.bat +++ b/script/setup.bat @@ -19,8 +19,6 @@ pip3 install -e ".[dev,test]" --config-settings editable_mode=compat pre-commit install -python script/platformio_install_deps.py platformio.ini --libraries --tools --platforms - echo . echo . echo Virtual environment created. Run 'venv/Scripts/activate' to use it. diff --git a/tests/components/lm75b/common.yaml b/tests/components/lm75b/common.yaml new file mode 100644 index 0000000000..e451c2f679 --- /dev/null +++ b/tests/components/lm75b/common.yaml @@ -0,0 +1,9 @@ +i2c: + - id: i2c_lm75b + scl: ${scl_pin} + sda: ${sda_pin} + +sensor: + - platform: lm75b + name: LM75B Temperature + update_interval: 30s diff --git a/tests/components/lm75b/test.esp32-ard.yaml b/tests/components/lm75b/test.esp32-ard.yaml new file mode 100644 index 0000000000..43264df633 --- /dev/null +++ b/tests/components/lm75b/test.esp32-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO15 + sda_pin: GPIO13 + +<<: !include common.yaml diff --git a/tests/components/lm75b/test.esp32-c3-ard.yaml b/tests/components/lm75b/test.esp32-c3-ard.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/lm75b/test.esp32-c3-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/lm75b/test.esp32-c3-idf.yaml b/tests/components/lm75b/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/lm75b/test.esp32-c3-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/lm75b/test.esp32-idf.yaml b/tests/components/lm75b/test.esp32-idf.yaml new file mode 100644 index 0000000000..43264df633 --- /dev/null +++ b/tests/components/lm75b/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO15 + sda_pin: GPIO13 + +<<: !include common.yaml diff --git a/tests/components/lm75b/test.esp8266-ard.yaml b/tests/components/lm75b/test.esp8266-ard.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/lm75b/test.esp8266-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/lm75b/test.rp2040-ard.yaml b/tests/components/lm75b/test.rp2040-ard.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/lm75b/test.rp2040-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/qmc5883l/common.yaml b/tests/components/qmc5883l/common.yaml index 5d8ac73b4f..c8ad4ba006 100644 --- a/tests/components/qmc5883l/common.yaml +++ b/tests/components/qmc5883l/common.yaml @@ -17,5 +17,7 @@ sensor: temperature: name: QMC5883L Temperature range: 800uT + data_rate: 200Hz oversampling: 256x update_interval: 15s + drdy_pin: ${drdy_pin} diff --git a/tests/components/qmc5883l/test.esp32-ard.yaml b/tests/components/qmc5883l/test.esp32-ard.yaml index 63c3bd6afd..2cf2041501 100644 --- a/tests/components/qmc5883l/test.esp32-ard.yaml +++ b/tests/components/qmc5883l/test.esp32-ard.yaml @@ -1,5 +1,6 @@ substitutions: scl_pin: GPIO16 sda_pin: GPIO17 + drdy_pin: GPIO18 <<: !include common.yaml diff --git a/tests/components/qmc5883l/test.esp32-c3-ard.yaml b/tests/components/qmc5883l/test.esp32-c3-ard.yaml index ee2c29ca4e..677501d15a 100644 --- a/tests/components/qmc5883l/test.esp32-c3-ard.yaml +++ b/tests/components/qmc5883l/test.esp32-c3-ard.yaml @@ -1,5 +1,6 @@ substitutions: scl_pin: GPIO5 sda_pin: GPIO4 + drdy_pin: GPIO6 <<: !include common.yaml diff --git a/tests/components/qmc5883l/test.esp32-c3-idf.yaml b/tests/components/qmc5883l/test.esp32-c3-idf.yaml index ee2c29ca4e..677501d15a 100644 --- a/tests/components/qmc5883l/test.esp32-c3-idf.yaml +++ b/tests/components/qmc5883l/test.esp32-c3-idf.yaml @@ -1,5 +1,6 @@ substitutions: scl_pin: GPIO5 sda_pin: GPIO4 + drdy_pin: GPIO6 <<: !include common.yaml diff --git a/tests/components/qmc5883l/test.esp32-idf.yaml b/tests/components/qmc5883l/test.esp32-idf.yaml index 63c3bd6afd..2cf2041501 100644 --- a/tests/components/qmc5883l/test.esp32-idf.yaml +++ b/tests/components/qmc5883l/test.esp32-idf.yaml @@ -1,5 +1,6 @@ substitutions: scl_pin: GPIO16 sda_pin: GPIO17 + drdy_pin: GPIO18 <<: !include common.yaml diff --git a/tests/components/qmc5883l/test.esp8266-ard.yaml b/tests/components/qmc5883l/test.esp8266-ard.yaml index ee2c29ca4e..65b0fd75d9 100644 --- a/tests/components/qmc5883l/test.esp8266-ard.yaml +++ b/tests/components/qmc5883l/test.esp8266-ard.yaml @@ -1,5 +1,6 @@ substitutions: scl_pin: GPIO5 sda_pin: GPIO4 + drdy_pin: GPIO2 <<: !include common.yaml diff --git a/tests/components/qmc5883l/test.rp2040-ard.yaml b/tests/components/qmc5883l/test.rp2040-ard.yaml index ee2c29ca4e..65b0fd75d9 100644 --- a/tests/components/qmc5883l/test.rp2040-ard.yaml +++ b/tests/components/qmc5883l/test.rp2040-ard.yaml @@ -1,5 +1,6 @@ substitutions: scl_pin: GPIO5 sda_pin: GPIO4 + drdy_pin: GPIO2 <<: !include common.yaml