mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	Merge branch 'dev' into vornado-ir
This commit is contained in:
		| @@ -122,7 +122,8 @@ void APDS9306::update() { | |||||||
|  |  | ||||||
|   this->status_clear_warning(); |   this->status_clear_warning(); | ||||||
|  |  | ||||||
|   if (!(status &= 0b00001000)) {  // No new data |   status &= 0b00001000; | ||||||
|  |   if (!status) {  // No new data | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -52,11 +52,11 @@ void DeepSleepComponent::dump_config_platform_() { | |||||||
|  |  | ||||||
| bool DeepSleepComponent::prepare_to_sleep_() { | bool DeepSleepComponent::prepare_to_sleep_() { | ||||||
|   if (this->wakeup_pin_mode_ == WAKEUP_PIN_MODE_KEEP_AWAKE && this->wakeup_pin_ != nullptr && |   if (this->wakeup_pin_mode_ == WAKEUP_PIN_MODE_KEEP_AWAKE && this->wakeup_pin_ != nullptr && | ||||||
|       !this->sleep_duration_.has_value() && this->wakeup_pin_->digital_read()) { |       this->wakeup_pin_->digital_read()) { | ||||||
|     // Defer deep sleep until inactive |     // Defer deep sleep until inactive | ||||||
|     if (!this->next_enter_deep_sleep_) { |     if (!this->next_enter_deep_sleep_) { | ||||||
|       this->status_set_warning(); |       this->status_set_warning(); | ||||||
|       ESP_LOGW(TAG, "Waiting for pin_ to switch state to enter deep sleep..."); |       ESP_LOGW(TAG, "Waiting wakeup pin state change to enter deep sleep..."); | ||||||
|     } |     } | ||||||
|     this->next_enter_deep_sleep_ = true; |     this->next_enter_deep_sleep_ = true; | ||||||
|     return false; |     return false; | ||||||
|   | |||||||
| @@ -135,7 +135,8 @@ bool HOT IRAM_ATTR DHT::read_sensor_(float *temperature, float *humidity, bool r | |||||||
|  |  | ||||||
|       // Wait for falling edge |       // Wait for falling edge | ||||||
|       while (this->pin_->digital_read()) { |       while (this->pin_->digital_read()) { | ||||||
|         if ((end_time = micros()) - start_time > 90) { |         end_time = micros(); | ||||||
|  |         if (end_time - start_time > 90) { | ||||||
|           if (i < 0) { |           if (i < 0) { | ||||||
|             error_code = 3; |             error_code = 3; | ||||||
|           } else { |           } else { | ||||||
|   | |||||||
| @@ -34,7 +34,7 @@ ESPBTUUID ESPBTUUID::from_raw(const uint8_t *data) { | |||||||
| ESPBTUUID ESPBTUUID::from_raw_reversed(const uint8_t *data) { | ESPBTUUID ESPBTUUID::from_raw_reversed(const uint8_t *data) { | ||||||
|   ESPBTUUID ret; |   ESPBTUUID ret; | ||||||
|   ret.uuid_.len = ESP_UUID_LEN_128; |   ret.uuid_.len = ESP_UUID_LEN_128; | ||||||
|   for (int i = 0; i < ESP_UUID_LEN_128; i++) |   for (uint8_t i = 0; i < ESP_UUID_LEN_128; i++) | ||||||
|     ret.uuid_.uuid.uuid128[ESP_UUID_LEN_128 - 1 - i] = data[i]; |     ret.uuid_.uuid.uuid128[ESP_UUID_LEN_128 - 1 - i] = data[i]; | ||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
| @@ -43,30 +43,30 @@ ESPBTUUID ESPBTUUID::from_raw(const std::string &data) { | |||||||
|   if (data.length() == 4) { |   if (data.length() == 4) { | ||||||
|     ret.uuid_.len = ESP_UUID_LEN_16; |     ret.uuid_.len = ESP_UUID_LEN_16; | ||||||
|     ret.uuid_.uuid.uuid16 = 0; |     ret.uuid_.uuid.uuid16 = 0; | ||||||
|     for (int i = 0; i < data.length();) { |     for (uint i = 0; i < data.length(); i += 2) { | ||||||
|       uint8_t msb = data.c_str()[i]; |       uint8_t msb = data.c_str()[i]; | ||||||
|       uint8_t lsb = data.c_str()[i + 1]; |       uint8_t lsb = data.c_str()[i + 1]; | ||||||
|  |       uint8_t lsb_shift = i <= 2 ? (2 - i) * 4 : 0; | ||||||
|  |  | ||||||
|       if (msb > '9') |       if (msb > '9') | ||||||
|         msb -= 7; |         msb -= 7; | ||||||
|       if (lsb > '9') |       if (lsb > '9') | ||||||
|         lsb -= 7; |         lsb -= 7; | ||||||
|       ret.uuid_.uuid.uuid16 += (((msb & 0x0F) << 4) | (lsb & 0x0F)) << (2 - i) * 4; |       ret.uuid_.uuid.uuid16 += (((msb & 0x0F) << 4) | (lsb & 0x0F)) << lsb_shift; | ||||||
|       i += 2; |  | ||||||
|     } |     } | ||||||
|   } else if (data.length() == 8) { |   } else if (data.length() == 8) { | ||||||
|     ret.uuid_.len = ESP_UUID_LEN_32; |     ret.uuid_.len = ESP_UUID_LEN_32; | ||||||
|     ret.uuid_.uuid.uuid32 = 0; |     ret.uuid_.uuid.uuid32 = 0; | ||||||
|     for (int i = 0; i < data.length();) { |     for (uint i = 0; i < data.length(); i += 2) { | ||||||
|       uint8_t msb = data.c_str()[i]; |       uint8_t msb = data.c_str()[i]; | ||||||
|       uint8_t lsb = data.c_str()[i + 1]; |       uint8_t lsb = data.c_str()[i + 1]; | ||||||
|  |       uint8_t lsb_shift = i <= 6 ? (6 - i) * 4 : 0; | ||||||
|  |  | ||||||
|       if (msb > '9') |       if (msb > '9') | ||||||
|         msb -= 7; |         msb -= 7; | ||||||
|       if (lsb > '9') |       if (lsb > '9') | ||||||
|         lsb -= 7; |         lsb -= 7; | ||||||
|       ret.uuid_.uuid.uuid32 += (((msb & 0x0F) << 4) | (lsb & 0x0F)) << (6 - i) * 4; |       ret.uuid_.uuid.uuid32 += (((msb & 0x0F) << 4) | (lsb & 0x0F)) << lsb_shift; | ||||||
|       i += 2; |  | ||||||
|     } |     } | ||||||
|   } else if (data.length() == 16) {  // how we can have 16 byte length string reprezenting 128 bit uuid??? needs to be |   } else if (data.length() == 16) {  // how we can have 16 byte length string reprezenting 128 bit uuid??? needs to be | ||||||
|                                      // investigated (lack of time) |                                      // investigated (lack of time) | ||||||
| @@ -77,7 +77,7 @@ ESPBTUUID ESPBTUUID::from_raw(const std::string &data) { | |||||||
|     // UUID format. |     // UUID format. | ||||||
|     ret.uuid_.len = ESP_UUID_LEN_128; |     ret.uuid_.len = ESP_UUID_LEN_128; | ||||||
|     int n = 0; |     int n = 0; | ||||||
|     for (int i = 0; i < data.length();) { |     for (uint i = 0; i < data.length(); i += 2) { | ||||||
|       if (data.c_str()[i] == '-') |       if (data.c_str()[i] == '-') | ||||||
|         i++; |         i++; | ||||||
|       uint8_t msb = data.c_str()[i]; |       uint8_t msb = data.c_str()[i]; | ||||||
| @@ -88,7 +88,6 @@ ESPBTUUID ESPBTUUID::from_raw(const std::string &data) { | |||||||
|       if (lsb > '9') |       if (lsb > '9') | ||||||
|         lsb -= 7; |         lsb -= 7; | ||||||
|       ret.uuid_.uuid.uuid128[15 - n++] = ((msb & 0x0F) << 4) | (lsb & 0x0F); |       ret.uuid_.uuid.uuid128[15 - n++] = ((msb & 0x0F) << 4) | (lsb & 0x0F); | ||||||
|       i += 2; |  | ||||||
|     } |     } | ||||||
|   } else { |   } else { | ||||||
|     ESP_LOGE(TAG, "ERROR: UUID value not 2, 4, 16 or 36 bytes - %s", data.c_str()); |     ESP_LOGE(TAG, "ERROR: UUID value not 2, 4, 16 or 36 bytes - %s", data.c_str()); | ||||||
| @@ -155,7 +154,7 @@ bool ESPBTUUID::operator==(const ESPBTUUID &uuid) const { | |||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
|       case ESP_UUID_LEN_128: |       case ESP_UUID_LEN_128: | ||||||
|         for (int i = 0; i < ESP_UUID_LEN_128; i++) { |         for (uint8_t i = 0; i < ESP_UUID_LEN_128; i++) { | ||||||
|           if (uuid.uuid_.uuid.uuid128[i] != this->uuid_.uuid.uuid128[i]) { |           if (uuid.uuid_.uuid.uuid128[i] != this->uuid_.uuid.uuid128[i]) { | ||||||
|             return false; |             return false; | ||||||
|           } |           } | ||||||
|   | |||||||
| @@ -432,7 +432,7 @@ void ESPBTDevice::parse_scan_rst(const esp_ble_gap_cb_param_t::ble_scan_result_e | |||||||
|  |  | ||||||
| #ifdef ESPHOME_LOG_HAS_VERY_VERBOSE | #ifdef ESPHOME_LOG_HAS_VERY_VERBOSE | ||||||
|   ESP_LOGVV(TAG, "Parse Result:"); |   ESP_LOGVV(TAG, "Parse Result:"); | ||||||
|   const char *address_type = ""; |   const char *address_type; | ||||||
|   switch (this->address_type_) { |   switch (this->address_type_) { | ||||||
|     case BLE_ADDR_TYPE_PUBLIC: |     case BLE_ADDR_TYPE_PUBLIC: | ||||||
|       address_type = "PUBLIC"; |       address_type = "PUBLIC"; | ||||||
| @@ -446,6 +446,9 @@ void ESPBTDevice::parse_scan_rst(const esp_ble_gap_cb_param_t::ble_scan_result_e | |||||||
|     case BLE_ADDR_TYPE_RPA_RANDOM: |     case BLE_ADDR_TYPE_RPA_RANDOM: | ||||||
|       address_type = "RPA_RANDOM"; |       address_type = "RPA_RANDOM"; | ||||||
|       break; |       break; | ||||||
|  |     default: | ||||||
|  |       address_type = "UNKNOWN"; | ||||||
|  |       break; | ||||||
|   } |   } | ||||||
|   ESP_LOGVV(TAG, "  Address: %02X:%02X:%02X:%02X:%02X:%02X (%s)", this->address_[0], this->address_[1], |   ESP_LOGVV(TAG, "  Address: %02X:%02X:%02X:%02X:%02X:%02X (%s)", this->address_[0], this->address_[1], | ||||||
|             this->address_[2], this->address_[3], this->address_[4], this->address_[5], address_type); |             this->address_[2], this->address_[3], this->address_[4], this->address_[5], address_type); | ||||||
|   | |||||||
| @@ -111,11 +111,11 @@ void EZOSensor::loop() { | |||||||
|   if (buf[0] == 1) { |   if (buf[0] == 1) { | ||||||
|     std::string payload = reinterpret_cast<char *>(&buf[1]); |     std::string payload = reinterpret_cast<char *>(&buf[1]); | ||||||
|     if (!payload.empty()) { |     if (!payload.empty()) { | ||||||
|  |       auto start_location = payload.find(','); | ||||||
|       switch (to_run->command_type) { |       switch (to_run->command_type) { | ||||||
|         case EzoCommandType::EZO_READ: { |         case EzoCommandType::EZO_READ: { | ||||||
|           // some sensors return multiple comma-separated values, terminate string after first one |           // some sensors return multiple comma-separated values, terminate string after first one | ||||||
|           int start_location = 0; |           if (start_location != std::string::npos) { | ||||||
|           if ((start_location = payload.find(',')) != std::string::npos) { |  | ||||||
|             payload.erase(start_location); |             payload.erase(start_location); | ||||||
|           } |           } | ||||||
|           auto val = parse_number<float>(payload); |           auto val = parse_number<float>(payload); | ||||||
| @@ -126,49 +126,37 @@ void EZOSensor::loop() { | |||||||
|           } |           } | ||||||
|           break; |           break; | ||||||
|         } |         } | ||||||
|         case EzoCommandType::EZO_LED: { |         case EzoCommandType::EZO_LED: | ||||||
|           this->led_callback_.call(payload.back() == '1'); |           this->led_callback_.call(payload.back() == '1'); | ||||||
|           break; |           break; | ||||||
|         } |         case EzoCommandType::EZO_DEVICE_INFORMATION: | ||||||
|         case EzoCommandType::EZO_DEVICE_INFORMATION: { |           if (start_location != std::string::npos) { | ||||||
|           int start_location = 0; |  | ||||||
|           if ((start_location = payload.find(',')) != std::string::npos) { |  | ||||||
|             this->device_infomation_callback_.call(payload.substr(start_location + 1)); |             this->device_infomation_callback_.call(payload.substr(start_location + 1)); | ||||||
|           } |           } | ||||||
|           break; |           break; | ||||||
|         } |         case EzoCommandType::EZO_SLOPE: | ||||||
|         case EzoCommandType::EZO_SLOPE: { |           if (start_location != std::string::npos) { | ||||||
|           int start_location = 0; |  | ||||||
|           if ((start_location = payload.find(',')) != std::string::npos) { |  | ||||||
|             this->slope_callback_.call(payload.substr(start_location + 1)); |             this->slope_callback_.call(payload.substr(start_location + 1)); | ||||||
|           } |           } | ||||||
|           break; |           break; | ||||||
|         } |         case EzoCommandType::EZO_CALIBRATION: | ||||||
|         case EzoCommandType::EZO_CALIBRATION: { |           if (start_location != std::string::npos) { | ||||||
|           int start_location = 0; |  | ||||||
|           if ((start_location = payload.find(',')) != std::string::npos) { |  | ||||||
|             this->calibration_callback_.call(payload.substr(start_location + 1)); |             this->calibration_callback_.call(payload.substr(start_location + 1)); | ||||||
|           } |           } | ||||||
|           break; |           break; | ||||||
|         } |         case EzoCommandType::EZO_T: | ||||||
|         case EzoCommandType::EZO_T: { |           if (start_location != std::string::npos) { | ||||||
|           int start_location = 0; |  | ||||||
|           if ((start_location = payload.find(',')) != std::string::npos) { |  | ||||||
|             this->t_callback_.call(payload.substr(start_location + 1)); |             this->t_callback_.call(payload.substr(start_location + 1)); | ||||||
|           } |           } | ||||||
|           break; |           break; | ||||||
|         } |         case EzoCommandType::EZO_CUSTOM: | ||||||
|         case EzoCommandType::EZO_CUSTOM: { |  | ||||||
|           this->custom_callback_.call(payload); |           this->custom_callback_.call(payload); | ||||||
|           break; |           break; | ||||||
|         } |         default: | ||||||
|         default: { |  | ||||||
|           break; |           break; | ||||||
|         } |  | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   this->commands_.pop_front(); |   this->commands_.pop_front(); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -178,7 +166,7 @@ void EZOSensor::add_command_(const std::string &command, EzoCommandType command_ | |||||||
|   ezo_command->command_type = command_type; |   ezo_command->command_type = command_type; | ||||||
|   ezo_command->delay_ms = delay_ms; |   ezo_command->delay_ms = delay_ms; | ||||||
|   this->commands_.push_back(std::move(ezo_command)); |   this->commands_.push_back(std::move(ezo_command)); | ||||||
| }; | } | ||||||
|  |  | ||||||
| void EZOSensor::set_calibration_point_(EzoCalibrationType type, float value) { | void EZOSensor::set_calibration_point_(EzoCalibrationType type, float value) { | ||||||
|   std::string payload = str_sprintf("Cal,%s,%0.2f", EZO_CALIBRATION_TYPE_STRINGS[type], value); |   std::string payload = str_sprintf("Cal,%s,%0.2f", EZO_CALIBRATION_TYPE_STRINGS[type], value); | ||||||
|   | |||||||
| @@ -133,8 +133,10 @@ bool HitachiClimate::get_swing_v_() { | |||||||
| } | } | ||||||
|  |  | ||||||
| void HitachiClimate::set_swing_h_(uint8_t position) { | void HitachiClimate::set_swing_h_(uint8_t position) { | ||||||
|   if (position > HITACHI_AC344_SWINGH_LEFT_MAX) |   if (position > HITACHI_AC344_SWINGH_LEFT_MAX) { | ||||||
|     return set_swing_h_(HITACHI_AC344_SWINGH_MIDDLE); |     set_swing_h_(HITACHI_AC344_SWINGH_MIDDLE); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|   set_bits(&remote_state_[HITACHI_AC344_SWINGH_BYTE], HITACHI_AC344_SWINGH_OFFSET, HITACHI_AC344_SWINGH_SIZE, position); |   set_bits(&remote_state_[HITACHI_AC344_SWINGH_BYTE], HITACHI_AC344_SWINGH_OFFSET, HITACHI_AC344_SWINGH_SIZE, position); | ||||||
|   set_button_(HITACHI_AC344_BUTTON_SWINGH); |   set_button_(HITACHI_AC344_BUTTON_SWINGH); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -133,8 +133,10 @@ bool HitachiClimate::get_swing_v_() { | |||||||
| } | } | ||||||
|  |  | ||||||
| void HitachiClimate::set_swing_h_(uint8_t position) { | void HitachiClimate::set_swing_h_(uint8_t position) { | ||||||
|   if (position > HITACHI_AC424_SWINGH_LEFT_MAX) |   if (position > HITACHI_AC424_SWINGH_LEFT_MAX) { | ||||||
|     return set_swing_h_(HITACHI_AC424_SWINGH_MIDDLE); |     set_swing_h_(HITACHI_AC424_SWINGH_MIDDLE); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|   set_bits(&remote_state_[HITACHI_AC424_SWINGH_BYTE], HITACHI_AC424_SWINGH_OFFSET, HITACHI_AC424_SWINGH_SIZE, position); |   set_bits(&remote_state_[HITACHI_AC424_SWINGH_BYTE], HITACHI_AC424_SWINGH_OFFSET, HITACHI_AC424_SWINGH_SIZE, position); | ||||||
|   set_button_(HITACHI_AC424_BUTTON_SWINGH); |   set_button_(HITACHI_AC424_BUTTON_SWINGH); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -313,8 +313,9 @@ void ILI9XXXDisplay::draw_pixels_at(int x_start, int y_start, int w, int h, cons | |||||||
|   // do color conversion pixel-by-pixel into the buffer and draw it later. If this is happening the user has not |   // do color conversion pixel-by-pixel into the buffer and draw it later. If this is happening the user has not | ||||||
|   // configured the renderer well. |   // configured the renderer well. | ||||||
|   if (this->rotation_ != display::DISPLAY_ROTATION_0_DEGREES || bitness != display::COLOR_BITNESS_565 || !big_endian) { |   if (this->rotation_ != display::DISPLAY_ROTATION_0_DEGREES || bitness != display::COLOR_BITNESS_565 || !big_endian) { | ||||||
|     return display::Display::draw_pixels_at(x_start, y_start, w, h, ptr, order, bitness, big_endian, x_offset, y_offset, |     display::Display::draw_pixels_at(x_start, y_start, w, h, ptr, order, bitness, big_endian, x_offset, y_offset, | ||||||
|                                             x_pad); |                                      x_pad); | ||||||
|  |     return; | ||||||
|   } |   } | ||||||
|   this->set_addr_window_(x_start, y_start, x_start + w - 1, y_start + h - 1); |   this->set_addr_window_(x_start, y_start, x_start + w - 1, y_start + h - 1); | ||||||
|   // x_ and y_offset are offsets into the source buffer, unrelated to our own offsets into the display. |   // x_ and y_offset are offsets into the source buffer, unrelated to our own offsets into the display. | ||||||
|   | |||||||
| @@ -47,7 +47,7 @@ void Logger::write_header_(int level, const char *tag, int line) { | |||||||
|   if (current_task == main_task_) { |   if (current_task == main_task_) { | ||||||
|     this->printf_to_buffer_("%s[%s][%s:%03u]: ", color, letter, tag, line); |     this->printf_to_buffer_("%s[%s][%s:%03u]: ", color, letter, tag, line); | ||||||
|   } else { |   } else { | ||||||
|     const char *thread_name = ""; |     const char *thread_name = "";  // NOLINT(clang-analyzer-deadcode.DeadStores) | ||||||
| #if defined(USE_ESP32) | #if defined(USE_ESP32) | ||||||
|     thread_name = pcTaskGetName(current_task); |     thread_name = pcTaskGetName(current_task); | ||||||
| #elif defined(USE_LIBRETINY) | #elif defined(USE_LIBRETINY) | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ import logging | |||||||
|  |  | ||||||
| from esphome import codegen as cg, config_validation as cv | from esphome import codegen as cg, config_validation as cv | ||||||
| from esphome.const import CONF_ITEMS | from esphome.const import CONF_ITEMS | ||||||
| from esphome.core import Lambda | from esphome.core import ID, Lambda | ||||||
| from esphome.cpp_generator import LambdaExpression, MockObj | from esphome.cpp_generator import LambdaExpression, MockObj | ||||||
| from esphome.cpp_types import uint32 | from esphome.cpp_types import uint32 | ||||||
| from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor | from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor | ||||||
| @@ -72,6 +72,12 @@ class LValidator: | |||||||
|             ) |             ) | ||||||
|         if self.retmapper is not None: |         if self.retmapper is not None: | ||||||
|             return self.retmapper(value) |             return self.retmapper(value) | ||||||
|  |         if isinstance(value, ID): | ||||||
|  |             return await cg.get_variable(value) | ||||||
|  |         if isinstance(value, list): | ||||||
|  |             value = [ | ||||||
|  |                 await cg.get_variable(x) if isinstance(x, ID) else x for x in value | ||||||
|  |             ] | ||||||
|         return cg.safe_exp(value) |         return cg.safe_exp(value) | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| from typing import Union | from typing import Union | ||||||
|  |  | ||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
|  | from esphome.components import image | ||||||
| from esphome.components.color import CONF_HEX, ColorStruct, from_rgbw | from esphome.components.color import CONF_HEX, ColorStruct, from_rgbw | ||||||
| from esphome.components.font import Font | from esphome.components.font import Font | ||||||
| from esphome.components.image import Image_ | from esphome.components.image import Image_ | ||||||
| @@ -31,7 +32,7 @@ from .defines import ( | |||||||
|     literal, |     literal, | ||||||
| ) | ) | ||||||
| from .helpers import add_lv_use, esphome_fonts_used, lv_fonts_used, requires_component | from .helpers import add_lv_use, esphome_fonts_used, lv_fonts_used, requires_component | ||||||
| from .types import lv_font_t, lv_gradient_t, lv_img_t | from .types import lv_font_t, lv_gradient_t | ||||||
|  |  | ||||||
| opacity_consts = LvConstant("LV_OPA_", "TRANSP", "COVER") | opacity_consts = LvConstant("LV_OPA_", "TRANSP", "COVER") | ||||||
|  |  | ||||||
| @@ -332,8 +333,12 @@ def image_validator(value): | |||||||
|  |  | ||||||
| lv_image = LValidator( | lv_image = LValidator( | ||||||
|     image_validator, |     image_validator, | ||||||
|     lv_img_t, |     image.Image_.operator("ptr"), | ||||||
|     retmapper=lambda x: MockObj(x, "->").get_lv_img_dsc(), |     requires="image", | ||||||
|  | ) | ||||||
|  | lv_image_list = LValidator( | ||||||
|  |     cv.ensure_list(image_validator), | ||||||
|  |     cg.std_vector.template(image.Image_.operator("ptr")), | ||||||
|     requires="image", |     requires="image", | ||||||
| ) | ) | ||||||
| lv_bool = LValidator(cv.boolean, cg.bool_, retmapper=literal) | lv_bool = LValidator(cv.boolean, cg.bool_, retmapper=literal) | ||||||
|   | |||||||
| @@ -57,6 +57,22 @@ inline void lv_img_set_src(lv_obj_t *obj, esphome::image::Image *image) { | |||||||
|   lv_img_set_src(obj, image->get_lv_img_dsc()); |   lv_img_set_src(obj, image->get_lv_img_dsc()); | ||||||
| } | } | ||||||
| #endif  // USE_LVGL_IMAGE | #endif  // USE_LVGL_IMAGE | ||||||
|  | #ifdef USE_LVGL_ANIMIMG | ||||||
|  | inline void lv_animimg_set_src(lv_obj_t *img, std::vector<image::Image *> images) { | ||||||
|  |   auto *dsc = static_cast<std::vector<lv_img_dsc_t *> *>(lv_obj_get_user_data(img)); | ||||||
|  |   if (dsc == nullptr) { | ||||||
|  |     // object will be lazily allocated but never freed. | ||||||
|  |     dsc = new std::vector<lv_img_dsc_t *>(images.size());  // NOLINT | ||||||
|  |     lv_obj_set_user_data(img, dsc); | ||||||
|  |   } | ||||||
|  |   dsc->clear(); | ||||||
|  |   for (auto &image : images) { | ||||||
|  |     dsc->push_back(image->get_lv_img_dsc()); | ||||||
|  |   } | ||||||
|  |   lv_animimg_set_src(img, (const void **) dsc->data(), dsc->size()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #endif  // USE_LVGL_ANIMIMG | ||||||
|  |  | ||||||
| // Parent class for things that wrap an LVGL object | // Parent class for things that wrap an LVGL object | ||||||
| class LvCompound { | class LvCompound { | ||||||
|   | |||||||
| @@ -1,20 +1,18 @@ | |||||||
| from esphome import automation | from esphome import automation | ||||||
| import esphome.codegen as cg |  | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.const import CONF_DURATION, CONF_ID | from esphome.const import CONF_DURATION, CONF_ID | ||||||
|  |  | ||||||
| from ..automation import action_to_code | from ..automation import action_to_code | ||||||
| from ..defines import CONF_AUTO_START, CONF_MAIN, CONF_REPEAT_COUNT, CONF_SRC | from ..defines import CONF_AUTO_START, CONF_MAIN, CONF_REPEAT_COUNT, CONF_SRC | ||||||
| from ..helpers import lvgl_components_required | from ..helpers import lvgl_components_required | ||||||
| from ..lv_validation import lv_image, lv_milliseconds | from ..lv_validation import lv_image_list, lv_milliseconds | ||||||
| from ..lvcode import lv | from ..lvcode import lv | ||||||
| from ..types import LvType, ObjUpdateAction, void_ptr | from ..types import LvType, ObjUpdateAction | ||||||
| from . import Widget, WidgetType, get_widgets | from . import Widget, WidgetType, get_widgets | ||||||
| from .img import CONF_IMAGE | from .img import CONF_IMAGE | ||||||
| from .label import CONF_LABEL | from .label import CONF_LABEL | ||||||
|  |  | ||||||
| CONF_ANIMIMG = "animimg" | CONF_ANIMIMG = "animimg" | ||||||
| CONF_SRC_LIST_ID = "src_list_id" |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def lv_repeat_count(value): | def lv_repeat_count(value): | ||||||
| @@ -32,14 +30,14 @@ ANIMIMG_BASE_SCHEMA = cv.Schema( | |||||||
| ANIMIMG_SCHEMA = ANIMIMG_BASE_SCHEMA.extend( | ANIMIMG_SCHEMA = ANIMIMG_BASE_SCHEMA.extend( | ||||||
|     { |     { | ||||||
|         cv.Required(CONF_DURATION): lv_milliseconds, |         cv.Required(CONF_DURATION): lv_milliseconds, | ||||||
|         cv.Required(CONF_SRC): cv.ensure_list(lv_image), |         cv.Required(CONF_SRC): lv_image_list, | ||||||
|         cv.GenerateID(CONF_SRC_LIST_ID): cv.declare_id(void_ptr), |  | ||||||
|     } |     } | ||||||
| ) | ) | ||||||
|  |  | ||||||
| ANIMIMG_MODIFY_SCHEMA = ANIMIMG_BASE_SCHEMA.extend( | ANIMIMG_MODIFY_SCHEMA = ANIMIMG_BASE_SCHEMA.extend( | ||||||
|     { |     { | ||||||
|         cv.Optional(CONF_DURATION): lv_milliseconds, |         cv.Optional(CONF_DURATION): lv_milliseconds, | ||||||
|  |         cv.Optional(CONF_SRC): lv_image_list, | ||||||
|     } |     } | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -59,17 +57,14 @@ class AnimimgType(WidgetType): | |||||||
|     async def to_code(self, w: Widget, config): |     async def to_code(self, w: Widget, config): | ||||||
|         lvgl_components_required.add(CONF_IMAGE) |         lvgl_components_required.add(CONF_IMAGE) | ||||||
|         lvgl_components_required.add(CONF_ANIMIMG) |         lvgl_components_required.add(CONF_ANIMIMG) | ||||||
|         if CONF_SRC in config: |         if srcs := config.get(CONF_SRC): | ||||||
|             srcs = [ |             srcs = await lv_image_list.process(srcs) | ||||||
|                 await lv_image.process(await cg.get_variable(x)) |             lv.animimg_set_src(w.obj, srcs) | ||||||
|                 for x in config[CONF_SRC] |         if repeat_count := config.get(CONF_REPEAT_COUNT): | ||||||
|             ] |             lv.animimg_set_repeat_count(w.obj, repeat_count) | ||||||
|             src_id = cg.static_const_array(config[CONF_SRC_LIST_ID], srcs) |         if duration := config.get(CONF_DURATION): | ||||||
|             count = len(config[CONF_SRC]) |             lv.animimg_set_duration(w.obj, duration) | ||||||
|             lv.animimg_set_src(w.obj, src_id, count) |         if config[CONF_AUTO_START]: | ||||||
|         lv.animimg_set_repeat_count(w.obj, config[CONF_REPEAT_COUNT]) |  | ||||||
|         lv.animimg_set_duration(w.obj, config[CONF_DURATION]) |  | ||||||
|         if config.get(CONF_AUTO_START): |  | ||||||
|             lv.animimg_start(w.obj) |             lv.animimg_start(w.obj) | ||||||
|  |  | ||||||
|     def get_uses(self): |     def get_uses(self): | ||||||
|   | |||||||
| @@ -1,4 +1,3 @@ | |||||||
| import esphome.codegen as cg |  | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.const import CONF_ANGLE, CONF_MODE | from esphome.const import CONF_ANGLE, CONF_MODE | ||||||
|  |  | ||||||
| @@ -65,7 +64,6 @@ class ImgType(WidgetType): | |||||||
|  |  | ||||||
|     async def to_code(self, w: Widget, config): |     async def to_code(self, w: Widget, config): | ||||||
|         if src := config.get(CONF_SRC): |         if src := config.get(CONF_SRC): | ||||||
|             src = await cg.get_variable(src) |  | ||||||
|             lv.img_set_src(w.obj, await lv_image.process(src)) |             lv.img_set_src(w.obj, await lv_image.process(src)) | ||||||
|         if (cf_angle := config.get(CONF_ANGLE)) is not None: |         if (cf_angle := config.get(CONF_ANGLE)) is not None: | ||||||
|             pivot_x = config[CONF_PIVOT_X] |             pivot_x = config[CONF_PIVOT_X] | ||||||
|   | |||||||
| @@ -106,7 +106,8 @@ void MAX31865Sensor::read_data_() { | |||||||
|  |  | ||||||
|   // Check faults |   // Check faults | ||||||
|   const uint8_t faults = this->read_register_(FAULT_STATUS_REG); |   const uint8_t faults = this->read_register_(FAULT_STATUS_REG); | ||||||
|   if ((has_fault_ = faults & 0b00111100)) { |   has_fault_ = faults & 0b00111100; | ||||||
|  |   if (has_fault_) { | ||||||
|     if (faults & (1 << 2)) { |     if (faults & (1 << 2)) { | ||||||
|       ESP_LOGE(TAG, "Overvoltage/undervoltage fault"); |       ESP_LOGE(TAG, "Overvoltage/undervoltage fault"); | ||||||
|     } |     } | ||||||
| @@ -125,7 +126,8 @@ void MAX31865Sensor::read_data_() { | |||||||
|   } else { |   } else { | ||||||
|     this->status_clear_error(); |     this->status_clear_error(); | ||||||
|   } |   } | ||||||
|   if ((has_warn_ = faults & 0b11000000)) { |   has_warn_ = faults & 0b11000000; | ||||||
|  |   if (has_warn_) { | ||||||
|     if (faults & (1 << 6)) { |     if (faults & (1 << 6)) { | ||||||
|       ESP_LOGW(TAG, "RTD Low Threshold"); |       ESP_LOGW(TAG, "RTD Low Threshold"); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -80,8 +80,7 @@ const EntityBase *MQTTAlarmControlPanelComponent::get_entity() const { return th | |||||||
|  |  | ||||||
| bool MQTTAlarmControlPanelComponent::send_initial_state() { return this->publish_state(); } | bool MQTTAlarmControlPanelComponent::send_initial_state() { return this->publish_state(); } | ||||||
| bool MQTTAlarmControlPanelComponent::publish_state() { | bool MQTTAlarmControlPanelComponent::publish_state() { | ||||||
|   bool success = true; |   const char *state_s; | ||||||
|   const char *state_s = ""; |  | ||||||
|   switch (this->alarm_control_panel_->get_state()) { |   switch (this->alarm_control_panel_->get_state()) { | ||||||
|     case ACP_STATE_DISARMED: |     case ACP_STATE_DISARMED: | ||||||
|       state_s = "disarmed"; |       state_s = "disarmed"; | ||||||
| @@ -116,9 +115,7 @@ bool MQTTAlarmControlPanelComponent::publish_state() { | |||||||
|     default: |     default: | ||||||
|       state_s = "unknown"; |       state_s = "unknown"; | ||||||
|   } |   } | ||||||
|   if (!this->publish(this->get_state_topic_(), state_s)) |   return this->publish(this->get_state_topic_(), state_s); | ||||||
|     success = false; |  | ||||||
|   return success; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| }  // namespace mqtt | }  // namespace mqtt | ||||||
|   | |||||||
| @@ -257,7 +257,7 @@ const EntityBase *MQTTClimateComponent::get_entity() const { return this->device | |||||||
| bool MQTTClimateComponent::publish_state_() { | bool MQTTClimateComponent::publish_state_() { | ||||||
|   auto traits = this->device_->get_traits(); |   auto traits = this->device_->get_traits(); | ||||||
|   // mode |   // mode | ||||||
|   const char *mode_s = ""; |   const char *mode_s; | ||||||
|   switch (this->device_->mode) { |   switch (this->device_->mode) { | ||||||
|     case CLIMATE_MODE_OFF: |     case CLIMATE_MODE_OFF: | ||||||
|       mode_s = "off"; |       mode_s = "off"; | ||||||
| @@ -280,6 +280,8 @@ bool MQTTClimateComponent::publish_state_() { | |||||||
|     case CLIMATE_MODE_HEAT_COOL: |     case CLIMATE_MODE_HEAT_COOL: | ||||||
|       mode_s = "heat_cool"; |       mode_s = "heat_cool"; | ||||||
|       break; |       break; | ||||||
|  |     default: | ||||||
|  |       mode_s = "unknown"; | ||||||
|   } |   } | ||||||
|   bool success = true; |   bool success = true; | ||||||
|   if (!this->publish(this->get_mode_state_topic(), mode_s)) |   if (!this->publish(this->get_mode_state_topic(), mode_s)) | ||||||
| @@ -343,6 +345,8 @@ bool MQTTClimateComponent::publish_state_() { | |||||||
|         case CLIMATE_PRESET_ACTIVITY: |         case CLIMATE_PRESET_ACTIVITY: | ||||||
|           payload = "activity"; |           payload = "activity"; | ||||||
|           break; |           break; | ||||||
|  |         default: | ||||||
|  |           payload = "unknown"; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     if (this->device_->custom_preset.has_value()) |     if (this->device_->custom_preset.has_value()) | ||||||
| @@ -352,7 +356,7 @@ bool MQTTClimateComponent::publish_state_() { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (traits.get_supports_action()) { |   if (traits.get_supports_action()) { | ||||||
|     const char *payload = "unknown"; |     const char *payload; | ||||||
|     switch (this->device_->action) { |     switch (this->device_->action) { | ||||||
|       case CLIMATE_ACTION_OFF: |       case CLIMATE_ACTION_OFF: | ||||||
|         payload = "off"; |         payload = "off"; | ||||||
| @@ -372,6 +376,8 @@ bool MQTTClimateComponent::publish_state_() { | |||||||
|       case CLIMATE_ACTION_FAN: |       case CLIMATE_ACTION_FAN: | ||||||
|         payload = "fan"; |         payload = "fan"; | ||||||
|         break; |         break; | ||||||
|  |       default: | ||||||
|  |         payload = "unknown"; | ||||||
|     } |     } | ||||||
|     if (!this->publish(this->get_action_state_topic(), payload)) |     if (!this->publish(this->get_action_state_topic(), payload)) | ||||||
|       success = false; |       success = false; | ||||||
| @@ -411,6 +417,8 @@ bool MQTTClimateComponent::publish_state_() { | |||||||
|         case CLIMATE_FAN_QUIET: |         case CLIMATE_FAN_QUIET: | ||||||
|           payload = "quiet"; |           payload = "quiet"; | ||||||
|           break; |           break; | ||||||
|  |         default: | ||||||
|  |           payload = "unknown"; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     if (this->device_->custom_fan_mode.has_value()) |     if (this->device_->custom_fan_mode.has_value()) | ||||||
| @@ -420,7 +428,7 @@ bool MQTTClimateComponent::publish_state_() { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (traits.get_supports_swing_modes()) { |   if (traits.get_supports_swing_modes()) { | ||||||
|     const char *payload = ""; |     const char *payload; | ||||||
|     switch (this->device_->swing_mode) { |     switch (this->device_->swing_mode) { | ||||||
|       case CLIMATE_SWING_OFF: |       case CLIMATE_SWING_OFF: | ||||||
|         payload = "off"; |         payload = "off"; | ||||||
| @@ -434,6 +442,8 @@ bool MQTTClimateComponent::publish_state_() { | |||||||
|       case CLIMATE_SWING_HORIZONTAL: |       case CLIMATE_SWING_HORIZONTAL: | ||||||
|         payload = "horizontal"; |         payload = "horizontal"; | ||||||
|         break; |         break; | ||||||
|  |       default: | ||||||
|  |         payload = "unknown"; | ||||||
|     } |     } | ||||||
|     if (!this->publish(this->get_swing_mode_state_topic(), payload)) |     if (!this->publish(this->get_swing_mode_state_topic(), payload)) | ||||||
|       success = false; |       success = false; | ||||||
|   | |||||||
| @@ -116,7 +116,7 @@ struct IPAddress { | |||||||
|   operator arduino_ns::IPAddress() const { return ip_addr_get_ip4_u32(&ip_addr_); } |   operator arduino_ns::IPAddress() const { return ip_addr_get_ip4_u32(&ip_addr_); } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|   bool is_set() { return !ip_addr_isany(&ip_addr_); } |   bool is_set() { return !ip_addr_isany(&ip_addr_); }  // NOLINT(readability-simplify-boolean-expr) | ||||||
|   bool is_ip4() { return IP_IS_V4(&ip_addr_); } |   bool is_ip4() { return IP_IS_V4(&ip_addr_); } | ||||||
|   bool is_ip6() { return IP_IS_V6(&ip_addr_); } |   bool is_ip6() { return IP_IS_V6(&ip_addr_); } | ||||||
|   std::string str() const { return str_lower_case(ipaddr_ntoa(&ip_addr_)); } |   std::string str() const { return str_lower_case(ipaddr_ntoa(&ip_addr_)); } | ||||||
|   | |||||||
| @@ -563,13 +563,10 @@ void Nextion::process_nextion_commands_() { | |||||||
|           break; |           break; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         int dataindex = 0; |  | ||||||
|  |  | ||||||
|         int value = 0; |         int value = 0; | ||||||
|  |  | ||||||
|         for (int i = 0; i < 4; ++i) { |         for (int i = 0; i < 4; ++i) { | ||||||
|           value += to_process[i] << (8 * i); |           value += to_process[i] << (8 * i); | ||||||
|           ++dataindex; |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         NextionQueue *nb = this->nextion_queue_.front(); |         NextionQueue *nb = this->nextion_queue_.front(); | ||||||
|   | |||||||
| @@ -49,6 +49,10 @@ void PngDecoder::prepare(uint32_t download_size) { | |||||||
| } | } | ||||||
|  |  | ||||||
| int HOT PngDecoder::decode(uint8_t *buffer, size_t size) { | int HOT PngDecoder::decode(uint8_t *buffer, size_t size) { | ||||||
|  |   if (!this->pngle_) { | ||||||
|  |     ESP_LOGE(TAG, "PNG decoder engine not initialized!"); | ||||||
|  |     return -1; | ||||||
|  |   } | ||||||
|   if (size < 256 && size < this->download_size_ - this->decoded_bytes_) { |   if (size < 256 && size < this->download_size_ - this->decoded_bytes_) { | ||||||
|     ESP_LOGD(TAG, "Waiting for data"); |     ESP_LOGD(TAG, "Waiting for data"); | ||||||
|     return 0; |     return 0; | ||||||
|   | |||||||
| @@ -220,7 +220,7 @@ void IRAM_ATTR OpenTherm::bit_read_(uint8_t value) { | |||||||
|   this->bit_pos_++; |   this->bit_pos_++; | ||||||
| } | } | ||||||
|  |  | ||||||
| ProtocolErrorType OpenTherm::verify_stop_bit_(uint8_t value) { | ProtocolErrorType IRAM_ATTR OpenTherm::verify_stop_bit_(uint8_t value) { | ||||||
|   if (value) {  // stop bit detected |   if (value) {  // stop bit detected | ||||||
|     return check_parity_(this->data_) ? ProtocolErrorType::NO_ERROR : ProtocolErrorType::PARITY_ERROR; |     return check_parity_(this->data_) ? ProtocolErrorType::NO_ERROR : ProtocolErrorType::PARITY_ERROR; | ||||||
|   } else {  // no stop bit detected, error |   } else {  // no stop bit detected, error | ||||||
| @@ -365,7 +365,7 @@ void IRAM_ATTR OpenTherm::stop_timer_() { | |||||||
|  |  | ||||||
| #ifdef ESP8266 | #ifdef ESP8266 | ||||||
| // 5 kHz timer_ | // 5 kHz timer_ | ||||||
| void OpenTherm::start_read_timer_() { | void IRAM_ATTR OpenTherm::start_read_timer_() { | ||||||
|   InterruptLock const lock; |   InterruptLock const lock; | ||||||
|   timer1_attachInterrupt(OpenTherm::esp8266_timer_isr); |   timer1_attachInterrupt(OpenTherm::esp8266_timer_isr); | ||||||
|   timer1_enable(TIM_DIV16, TIM_EDGE, TIM_LOOP);  // 5MHz (5 ticks/us - 1677721.4 us max) |   timer1_enable(TIM_DIV16, TIM_EDGE, TIM_LOOP);  // 5MHz (5 ticks/us - 1677721.4 us max) | ||||||
| @@ -373,14 +373,14 @@ void OpenTherm::start_read_timer_() { | |||||||
| } | } | ||||||
|  |  | ||||||
| // 2 kHz timer_ | // 2 kHz timer_ | ||||||
| void OpenTherm::start_write_timer_() { | void IRAM_ATTR OpenTherm::start_write_timer_() { | ||||||
|   InterruptLock const lock; |   InterruptLock const lock; | ||||||
|   timer1_attachInterrupt(OpenTherm::esp8266_timer_isr); |   timer1_attachInterrupt(OpenTherm::esp8266_timer_isr); | ||||||
|   timer1_enable(TIM_DIV16, TIM_EDGE, TIM_LOOP);  // 5MHz (5 ticks/us - 1677721.4 us max) |   timer1_enable(TIM_DIV16, TIM_EDGE, TIM_LOOP);  // 5MHz (5 ticks/us - 1677721.4 us max) | ||||||
|   timer1_write(2500);                            // 2kHz |   timer1_write(2500);                            // 2kHz | ||||||
| } | } | ||||||
|  |  | ||||||
| void OpenTherm::stop_timer_() { | void IRAM_ATTR OpenTherm::stop_timer_() { | ||||||
|   InterruptLock const lock; |   InterruptLock const lock; | ||||||
|   timer1_disable(); |   timer1_disable(); | ||||||
|   timer1_detachInterrupt(); |   timer1_detachInterrupt(); | ||||||
| @@ -389,7 +389,7 @@ void OpenTherm::stop_timer_() { | |||||||
| #endif  // END ESP8266 | #endif  // END ESP8266 | ||||||
|  |  | ||||||
| // https://stackoverflow.com/questions/21617970/how-to-check-if-value-has-even-parity-of-bits-or-odd | // https://stackoverflow.com/questions/21617970/how-to-check-if-value-has-even-parity-of-bits-or-odd | ||||||
| bool OpenTherm::check_parity_(uint32_t val) { | bool IRAM_ATTR OpenTherm::check_parity_(uint32_t val) { | ||||||
|   val ^= val >> 16; |   val ^= val >> 16; | ||||||
|   val ^= val >> 8; |   val ^= val >> 8; | ||||||
|   val ^= val >> 4; |   val ^= val >> 4; | ||||||
|   | |||||||
| @@ -34,7 +34,7 @@ void PCA6416AComponent::setup() { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Test to see if the device supports pull-up resistors |   // Test to see if the device supports pull-up resistors | ||||||
|   if (this->read_register(PCAL6416A_PULL_EN0, &value, 1, true) == esphome::i2c::ERROR_OK) { |   if (this->read_register(PCAL6416A_PULL_EN0, &value, 1, true) == i2c::ERROR_OK) { | ||||||
|     this->has_pullup_ = true; |     this->has_pullup_ = true; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -106,7 +106,8 @@ bool PCA6416AComponent::read_register_(uint8_t reg, uint8_t *value) { | |||||||
|     return false; |     return false; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if ((this->last_error_ = this->read_register(reg, value, 1, true)) != esphome::i2c::ERROR_OK) { |   this->last_error_ = this->read_register(reg, value, 1, true); | ||||||
|  |   if (this->last_error_ != i2c::ERROR_OK) { | ||||||
|     this->status_set_warning(); |     this->status_set_warning(); | ||||||
|     ESP_LOGE(TAG, "read_register_(): I2C I/O error: %d", (int) this->last_error_); |     ESP_LOGE(TAG, "read_register_(): I2C I/O error: %d", (int) this->last_error_); | ||||||
|     return false; |     return false; | ||||||
| @@ -122,7 +123,8 @@ bool PCA6416AComponent::write_register_(uint8_t reg, uint8_t value) { | |||||||
|     return false; |     return false; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if ((this->last_error_ = this->write_register(reg, &value, 1, true)) != esphome::i2c::ERROR_OK) { |   this->last_error_ = this->write_register(reg, &value, 1, true); | ||||||
|  |   if (this->last_error_ != i2c::ERROR_OK) { | ||||||
|     this->status_set_warning(); |     this->status_set_warning(); | ||||||
|     ESP_LOGE(TAG, "write_register_(): I2C I/O error: %d", (int) this->last_error_); |     ESP_LOGE(TAG, "write_register_(): I2C I/O error: %d", (int) this->last_error_); | ||||||
|     return false; |     return false; | ||||||
|   | |||||||
| @@ -95,8 +95,8 @@ bool PCA9554Component::read_inputs_() { | |||||||
|     return false; |     return false; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if ((this->last_error_ = this->read_register(INPUT_REG * this->reg_width_, inputs, this->reg_width_, true)) != |   this->last_error_ = this->read_register(INPUT_REG * this->reg_width_, inputs, this->reg_width_, true); | ||||||
|       esphome::i2c::ERROR_OK) { |   if (this->last_error_ != i2c::ERROR_OK) { | ||||||
|     this->status_set_warning(); |     this->status_set_warning(); | ||||||
|     ESP_LOGE(TAG, "read_register_(): I2C I/O error: %d", (int) this->last_error_); |     ESP_LOGE(TAG, "read_register_(): I2C I/O error: %d", (int) this->last_error_); | ||||||
|     return false; |     return false; | ||||||
| @@ -113,8 +113,8 @@ bool PCA9554Component::write_register_(uint8_t reg, uint16_t value) { | |||||||
|   uint8_t outputs[2]; |   uint8_t outputs[2]; | ||||||
|   outputs[0] = (uint8_t) value; |   outputs[0] = (uint8_t) value; | ||||||
|   outputs[1] = (uint8_t) (value >> 8); |   outputs[1] = (uint8_t) (value >> 8); | ||||||
|   if ((this->last_error_ = this->write_register(reg * this->reg_width_, outputs, this->reg_width_, true)) != |   this->last_error_ = this->write_register(reg * this->reg_width_, outputs, this->reg_width_, true); | ||||||
|       esphome::i2c::ERROR_OK) { |   if (this->last_error_ != i2c::ERROR_OK) { | ||||||
|     this->status_set_warning(); |     this->status_set_warning(); | ||||||
|     ESP_LOGE(TAG, "write_register_(): I2C I/O error: %d", (int) this->last_error_); |     ESP_LOGE(TAG, "write_register_(): I2C I/O error: %d", (int) this->last_error_); | ||||||
|     return false; |     return false; | ||||||
|   | |||||||
| @@ -146,7 +146,8 @@ void QspiDbi::draw_pixels_at(int x_start, int y_start, int w, int h, const uint8 | |||||||
|     return; |     return; | ||||||
|   if (bitness != display::COLOR_BITNESS_565 || order != this->color_mode_ || |   if (bitness != display::COLOR_BITNESS_565 || order != this->color_mode_ || | ||||||
|       big_endian != (this->bit_order_ == spi::BIT_ORDER_MSB_FIRST)) { |       big_endian != (this->bit_order_ == spi::BIT_ORDER_MSB_FIRST)) { | ||||||
|     return Display::draw_pixels_at(x_start, y_start, w, h, ptr, order, bitness, big_endian, x_offset, y_offset, x_pad); |     Display::draw_pixels_at(x_start, y_start, w, h, ptr, order, bitness, big_endian, x_offset, y_offset, x_pad); | ||||||
|  |     return; | ||||||
|   } else if (this->draw_from_origin_) { |   } else if (this->draw_from_origin_) { | ||||||
|     auto stride = x_offset + w + x_pad; |     auto stride = x_offset + w + x_pad; | ||||||
|     for (int y = 0; y != h; y++) { |     for (int y = 0; y != h; y++) { | ||||||
|   | |||||||
| @@ -162,7 +162,7 @@ void RotaryEncoderSensor::dump_config() { | |||||||
|   LOG_PIN("  Pin B: ", this->pin_b_); |   LOG_PIN("  Pin B: ", this->pin_b_); | ||||||
|   LOG_PIN("  Pin I: ", this->pin_i_); |   LOG_PIN("  Pin I: ", this->pin_i_); | ||||||
|  |  | ||||||
|   const LogString *restore_mode = LOG_STR(""); |   const LogString *restore_mode; | ||||||
|   switch (this->restore_mode_) { |   switch (this->restore_mode_) { | ||||||
|     case ROTARY_ENCODER_RESTORE_DEFAULT_ZERO: |     case ROTARY_ENCODER_RESTORE_DEFAULT_ZERO: | ||||||
|       restore_mode = LOG_STR("Restore (Defaults to zero)"); |       restore_mode = LOG_STR("Restore (Defaults to zero)"); | ||||||
| @@ -170,6 +170,8 @@ void RotaryEncoderSensor::dump_config() { | |||||||
|     case ROTARY_ENCODER_ALWAYS_ZERO: |     case ROTARY_ENCODER_ALWAYS_ZERO: | ||||||
|       restore_mode = LOG_STR("Always zero"); |       restore_mode = LOG_STR("Always zero"); | ||||||
|       break; |       break; | ||||||
|  |     default: | ||||||
|  |       restore_mode = LOG_STR(""); | ||||||
|   } |   } | ||||||
|   ESP_LOGCONFIG(TAG, "  Restore Mode: %s", LOG_STR_ARG(restore_mode)); |   ESP_LOGCONFIG(TAG, "  Restore Mode: %s", LOG_STR_ARG(restore_mode)); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -483,7 +483,7 @@ void ST7735::spi_master_write_color_(uint16_t color, uint16_t size) { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   this->dc_pin_->digital_write(true); |   this->dc_pin_->digital_write(true); | ||||||
|   return write_array(byte, size * 2); |   write_array(byte, size * 2); | ||||||
| } | } | ||||||
|  |  | ||||||
| }  // namespace st7735 | }  // namespace st7735 | ||||||
|   | |||||||
| @@ -252,7 +252,7 @@ void ST7789V::write_color_(uint16_t color, uint16_t size) { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   this->dc_pin_->digital_write(true); |   this->dc_pin_->digital_write(true); | ||||||
|   return write_array(byte, size * 2); |   write_array(byte, size * 2); | ||||||
| } | } | ||||||
|  |  | ||||||
| size_t ST7789V::get_buffer_length_() { | size_t ST7789V::get_buffer_length_() { | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| #include "st7920.h" | #include "st7920.h" | ||||||
| #include "esphome/core/log.h" |  | ||||||
| #include "esphome/core/application.h" |  | ||||||
| #include "esphome/components/display/display_buffer.h" | #include "esphome/components/display/display_buffer.h" | ||||||
|  | #include "esphome/core/application.h" | ||||||
|  | #include "esphome/core/log.h" | ||||||
|  |  | ||||||
| namespace esphome { | namespace esphome { | ||||||
| namespace st7920 { | namespace st7920 { | ||||||
| @@ -118,7 +118,6 @@ size_t ST7920::get_buffer_length_() { | |||||||
|  |  | ||||||
| void HOT ST7920::draw_absolute_pixel_internal(int x, int y, Color color) { | void HOT ST7920::draw_absolute_pixel_internal(int x, int y, Color color) { | ||||||
|   if (x >= this->get_width_internal() || x < 0 || y >= this->get_height_internal() || y < 0) { |   if (x >= this->get_width_internal() || x < 0 || y >= this->get_height_internal() || y < 0) { | ||||||
|     ESP_LOGW(TAG, "Position out of area: %dx%d", x, y); |  | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|   int width = this->get_width_internal() / 8u; |   int width = this->get_width_internal() / 8u; | ||||||
|   | |||||||
| @@ -434,7 +434,8 @@ static bool process_rolling_code(Provider &provider, uint8_t *&buf, const uint8_ | |||||||
| void UDPComponent::process_(uint8_t *buf, const size_t len) { | void UDPComponent::process_(uint8_t *buf, const size_t len) { | ||||||
|   auto ping_key_seen = !this->ping_pong_enable_; |   auto ping_key_seen = !this->ping_pong_enable_; | ||||||
|   if (len < 8) { |   if (len < 8) { | ||||||
|     return ESP_LOGV(TAG, "Bad length %zu", len); |     ESP_LOGV(TAG, "Bad length %zu", len); | ||||||
|  |     return; | ||||||
|   } |   } | ||||||
|   char namebuf[256]{}; |   char namebuf[256]{}; | ||||||
|   uint8_t byte; |   uint8_t byte; | ||||||
| @@ -442,31 +443,40 @@ void UDPComponent::process_(uint8_t *buf, const size_t len) { | |||||||
|   const uint8_t *end = buf + len; |   const uint8_t *end = buf + len; | ||||||
|   FuData rdata{}; |   FuData rdata{}; | ||||||
|   auto magic = get_uint16(buf); |   auto magic = get_uint16(buf); | ||||||
|   if (magic != MAGIC_NUMBER && magic != MAGIC_PING) |   if (magic != MAGIC_NUMBER && magic != MAGIC_PING) { | ||||||
|     return ESP_LOGV(TAG, "Bad magic %X", magic); |     ESP_LOGV(TAG, "Bad magic %X", magic); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   auto hlen = *buf++; |   auto hlen = *buf++; | ||||||
|   if (hlen > len - 3) { |   if (hlen > len - 3) { | ||||||
|     return ESP_LOGV(TAG, "Bad hostname length %u > %zu", hlen, len - 3); |     ESP_LOGV(TAG, "Bad hostname length %u > %zu", hlen, len - 3); | ||||||
|  |     return; | ||||||
|   } |   } | ||||||
|   memcpy(namebuf, buf, hlen); |   memcpy(namebuf, buf, hlen); | ||||||
|   if (strcmp(this->name_, namebuf) == 0) { |   if (strcmp(this->name_, namebuf) == 0) { | ||||||
|     return ESP_LOGV(TAG, "Ignoring our own data"); |     ESP_LOGV(TAG, "Ignoring our own data"); | ||||||
|  |     return; | ||||||
|   } |   } | ||||||
|   buf += hlen; |   buf += hlen; | ||||||
|   if (magic == MAGIC_PING) |   if (magic == MAGIC_PING) { | ||||||
|     return this->process_ping_request_(namebuf, buf, end - buf); |     this->process_ping_request_(namebuf, buf, end - buf); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|   if (round4(len) != len) { |   if (round4(len) != len) { | ||||||
|     return ESP_LOGW(TAG, "Bad length %zu", len); |     ESP_LOGW(TAG, "Bad length %zu", len); | ||||||
|  |     return; | ||||||
|   } |   } | ||||||
|   hlen = round4(hlen + 3); |   hlen = round4(hlen + 3); | ||||||
|   buf = start_ptr + hlen; |   buf = start_ptr + hlen; | ||||||
|   if (buf == end) { |   if (buf == end) { | ||||||
|     return ESP_LOGV(TAG, "No data after header"); |     ESP_LOGV(TAG, "No data after header"); | ||||||
|  |     return; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (this->providers_.count(namebuf) == 0) { |   if (this->providers_.count(namebuf) == 0) { | ||||||
|     return ESP_LOGVV(TAG, "Unknown hostname %s", namebuf); |     ESP_LOGVV(TAG, "Unknown hostname %s", namebuf); | ||||||
|  |     return; | ||||||
|   } |   } | ||||||
|   auto &provider = this->providers_[namebuf]; |   auto &provider = this->providers_[namebuf]; | ||||||
|   // if encryption not used with this host, ping check is pointless since it would be easily spoofed. |   // if encryption not used with this host, ping check is pointless since it would be easily spoofed. | ||||||
| @@ -489,7 +499,8 @@ void UDPComponent::process_(uint8_t *buf, const size_t len) { | |||||||
|     if (!process_rolling_code(provider, buf, end)) |     if (!process_rolling_code(provider, buf, end)) | ||||||
|       return; |       return; | ||||||
|   } else if (byte != DATA_KEY) { |   } else if (byte != DATA_KEY) { | ||||||
|     return ESP_LOGV(TAG, "Expected rolling_key or data_key, got %X", byte); |     ESP_LOGV(TAG, "Expected rolling_key or data_key, got %X", byte); | ||||||
|  |     return; | ||||||
|   } |   } | ||||||
|   while (buf < end) { |   while (buf < end) { | ||||||
|     byte = *buf++; |     byte = *buf++; | ||||||
| @@ -497,7 +508,8 @@ void UDPComponent::process_(uint8_t *buf, const size_t len) { | |||||||
|       continue; |       continue; | ||||||
|     if (byte == PING_KEY) { |     if (byte == PING_KEY) { | ||||||
|       if (end - buf < 4) { |       if (end - buf < 4) { | ||||||
|         return ESP_LOGV(TAG, "PING_KEY requires 4 more bytes"); |         ESP_LOGV(TAG, "PING_KEY requires 4 more bytes"); | ||||||
|  |         return; | ||||||
|       } |       } | ||||||
|       auto key = get_uint32(buf); |       auto key = get_uint32(buf); | ||||||
|       if (key == this->ping_key_) { |       if (key == this->ping_key_) { | ||||||
| @@ -515,21 +527,25 @@ void UDPComponent::process_(uint8_t *buf, const size_t len) { | |||||||
|     } |     } | ||||||
|     if (byte == BINARY_SENSOR_KEY) { |     if (byte == BINARY_SENSOR_KEY) { | ||||||
|       if (end - buf < 3) { |       if (end - buf < 3) { | ||||||
|         return ESP_LOGV(TAG, "Binary sensor key requires at least 3 more bytes"); |         ESP_LOGV(TAG, "Binary sensor key requires at least 3 more bytes"); | ||||||
|  |         return; | ||||||
|       } |       } | ||||||
|       rdata.u32 = *buf++; |       rdata.u32 = *buf++; | ||||||
|     } else if (byte == SENSOR_KEY) { |     } else if (byte == SENSOR_KEY) { | ||||||
|       if (end - buf < 6) { |       if (end - buf < 6) { | ||||||
|         return ESP_LOGV(TAG, "Sensor key requires at least 6 more bytes"); |         ESP_LOGV(TAG, "Sensor key requires at least 6 more bytes"); | ||||||
|  |         return; | ||||||
|       } |       } | ||||||
|       rdata.u32 = get_uint32(buf); |       rdata.u32 = get_uint32(buf); | ||||||
|     } else { |     } else { | ||||||
|       return ESP_LOGW(TAG, "Unknown key byte %X", byte); |       ESP_LOGW(TAG, "Unknown key byte %X", byte); | ||||||
|  |       return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     hlen = *buf++; |     hlen = *buf++; | ||||||
|     if (end - buf < hlen) { |     if (end - buf < hlen) { | ||||||
|       return ESP_LOGV(TAG, "Name length of %u not available", hlen); |       ESP_LOGV(TAG, "Name length of %u not available", hlen); | ||||||
|  |       return; | ||||||
|     } |     } | ||||||
|     memset(namebuf, 0, sizeof namebuf); |     memset(namebuf, 0, sizeof namebuf); | ||||||
|     memcpy(namebuf, buf, hlen); |     memcpy(namebuf, buf, hlen); | ||||||
|   | |||||||
| @@ -40,7 +40,7 @@ void ULN2003::dump_config() { | |||||||
|   LOG_PIN("  Pin C: ", this->pin_c_); |   LOG_PIN("  Pin C: ", this->pin_c_); | ||||||
|   LOG_PIN("  Pin D: ", this->pin_d_); |   LOG_PIN("  Pin D: ", this->pin_d_); | ||||||
|   ESP_LOGCONFIG(TAG, "  Sleep when done: %s", YESNO(this->sleep_when_done_)); |   ESP_LOGCONFIG(TAG, "  Sleep when done: %s", YESNO(this->sleep_when_done_)); | ||||||
|   const char *step_mode_s = ""; |   const char *step_mode_s; | ||||||
|   switch (this->step_mode_) { |   switch (this->step_mode_) { | ||||||
|     case ULN2003_STEP_MODE_FULL_STEP: |     case ULN2003_STEP_MODE_FULL_STEP: | ||||||
|       step_mode_s = "FULL STEP"; |       step_mode_s = "FULL STEP"; | ||||||
| @@ -51,6 +51,9 @@ void ULN2003::dump_config() { | |||||||
|     case ULN2003_STEP_MODE_WAVE_DRIVE: |     case ULN2003_STEP_MODE_WAVE_DRIVE: | ||||||
|       step_mode_s = "WAVE DRIVE"; |       step_mode_s = "WAVE DRIVE"; | ||||||
|       break; |       break; | ||||||
|  |     default: | ||||||
|  |       step_mode_s = "UNKNOWN"; | ||||||
|  |       break; | ||||||
|   } |   } | ||||||
|   ESP_LOGCONFIG(TAG, "  Step Mode: %s", step_mode_s); |   ESP_LOGCONFIG(TAG, "  Step Mode: %s", step_mode_s); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -67,7 +67,7 @@ bool Component::cancel_retry(const std::string &name) {  // NOLINT | |||||||
| } | } | ||||||
|  |  | ||||||
| void Component::set_timeout(const std::string &name, uint32_t timeout, std::function<void()> &&f) {  // NOLINT | void Component::set_timeout(const std::string &name, uint32_t timeout, std::function<void()> &&f) {  // NOLINT | ||||||
|   return App.scheduler.set_timeout(this, name, timeout, std::move(f)); |   App.scheduler.set_timeout(this, name, timeout, std::move(f)); | ||||||
| } | } | ||||||
|  |  | ||||||
| bool Component::cancel_timeout(const std::string &name) {  // NOLINT | bool Component::cancel_timeout(const std::string &name) {  // NOLINT | ||||||
|   | |||||||
| @@ -171,9 +171,13 @@ lvgl: | |||||||
|             duration: 1s |             duration: 1s | ||||||
|             auto_start: true |             auto_start: true | ||||||
|             on_all_events: |             on_all_events: | ||||||
|               logger.log: |               - logger.log: | ||||||
|                 format: "Event %s" |                   format: "Event %s" | ||||||
|                 args: ['lv_event_code_name_for(event->code).c_str()'] |                   args: ['lv_event_code_name_for(event->code).c_str()'] | ||||||
|  |               - lvgl.animimg.update: | ||||||
|  |                   id: anim_img | ||||||
|  |                   src: !lambda "return {dog_image, cat_image};" | ||||||
|  |                   duration: 2s | ||||||
|         - label: |         - label: | ||||||
|             id: hello_label |             id: hello_label | ||||||
|             text: Hello world |             text: Hello world | ||||||
| @@ -635,7 +639,7 @@ lvgl: | |||||||
|                   - image: |                   - image: | ||||||
|                       grid_cell_row_pos: 0 |                       grid_cell_row_pos: 0 | ||||||
|                       grid_cell_column_pos: 0 |                       grid_cell_column_pos: 0 | ||||||
|                       src: dog_image |                       src: !lambda return dog_image; | ||||||
|                       on_click: |                       on_click: | ||||||
|                         then: |                         then: | ||||||
|                           - lvgl.tabview.select: |                           - lvgl.tabview.select: | ||||||
|   | |||||||
| @@ -55,5 +55,5 @@ lvgl: | |||||||
|  |  | ||||||
| packages: | packages: | ||||||
|   lvgl: !include lvgl-package.yaml |   lvgl: !include lvgl-package.yaml | ||||||
|  |   xvgl: !include common.yaml | ||||||
|  |  | ||||||
| <<: !include common.yaml |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user