diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index d5baf339aa..e2febdad1b 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -46,7 +46,7 @@ runs: - name: Build and push to ghcr by digest id: build-ghcr - uses: docker/build-push-action@v6.3.0 + uses: docker/build-push-action@v6.4.1 with: context: . file: ./docker/Dockerfile @@ -69,7 +69,7 @@ runs: - name: Build and push to dockerhub by digest id: build-dockerhub - uses: docker/build-push-action@v6.3.0 + uses: docker/build-push-action@v6.4.1 with: context: . file: ./docker/Dockerfile diff --git a/CODEOWNERS b/CODEOWNERS index 4198c8c95c..50730a53ae 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -214,7 +214,7 @@ esphome/components/lightwaverf/* @max246 esphome/components/lilygo_t5_47/touchscreen/* @jesserockz esphome/components/lock/* @esphome/core esphome/components/logger/* @esphome/core -esphome/components/ltr390/* @sjtrny +esphome/components/ltr390/* @latonita @sjtrny esphome/components/ltr_als_ps/* @latonita esphome/components/matrix_keypad/* @ssieb esphome/components/max31865/* @DAVe3283 diff --git a/esphome/__main__.py b/esphome/__main__.py index bee5a73542..25b8fce66f 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -703,7 +703,8 @@ def command_rename(args, config): os.remove(new_path) return 1 - os.remove(CORE.config_path) + if CORE.config_path != new_path: + os.remove(CORE.config_path) print(color(Fore.BOLD_GREEN, "SUCCESS")) print() diff --git a/esphome/components/heatpumpir/climate.py b/esphome/components/heatpumpir/climate.py index b86d405b7e..80900d7db9 100644 --- a/esphome/components/heatpumpir/climate.py +++ b/esphome/components/heatpumpir/climate.py @@ -8,7 +8,6 @@ from esphome.const import ( CONF_PROTOCOL, CONF_VISUAL, ) -from esphome.core import CORE CODEOWNERS = ["@rob-deutsch"] @@ -67,6 +66,11 @@ PROTOCOLS = { "carrier_qlima_2": Protocol.PROTOCOL_QLIMA_2, "samsung_aqv12msan": Protocol.PROTOCOL_SAMSUNG_AQV12MSAN, "zhjg01": Protocol.PROTOCOL_ZHJG01, + "airway": Protocol.PROTOCOL_AIRWAY, + "bgh_aud": Protocol.PROTOCOL_BGH_AUD, + "panasonic_altdke": Protocol.PROTOCOL_PANASONIC_ALTDKE, + "vaillantvai8": Protocol.PROTOCOL_VAILLANTVAI8, + "r51m": Protocol.PROTOCOL_R51M, } CONF_HORIZONTAL_DEFAULT = "horizontal_default" @@ -122,7 +126,4 @@ def to_code(config): cg.add(var.set_max_temperature(config[CONF_MAX_TEMPERATURE])) cg.add(var.set_min_temperature(config[CONF_MIN_TEMPERATURE])) - cg.add_library("tonia/HeatpumpIR", "1.0.26") - - if CORE.is_esp8266 or CORE.is_esp32: - cg.add_library("crankyoldgit/IRremoteESP8266", "2.8.6") + cg.add_library("tonia/HeatpumpIR", "1.0.27") diff --git a/esphome/components/heatpumpir/heatpumpir.cpp b/esphome/components/heatpumpir/heatpumpir.cpp index 22a5779c8d..144dcc9bfa 100644 --- a/esphome/components/heatpumpir/heatpumpir.cpp +++ b/esphome/components/heatpumpir/heatpumpir.cpp @@ -61,6 +61,11 @@ const std::map> PROTOCOL_CONSTRUCTOR_MAP {PROTOCOL_QLIMA_2, []() { return new Qlima2HeatpumpIR(); }}, // NOLINT {PROTOCOL_SAMSUNG_AQV12MSAN, []() { return new SamsungAQV12MSANHeatpumpIR(); }}, // NOLINT {PROTOCOL_ZHJG01, []() { return new ZHJG01HeatpumpIR(); }}, // NOLINT + {PROTOCOL_AIRWAY, []() { return new AIRWAYHeatpumpIR(); }}, // NOLINT + {PROTOCOL_BGH_AUD, []() { return new BGHHeatpumpIR(); }}, // NOLINT + {PROTOCOL_PANASONIC_ALTDKE, []() { return new PanasonicAltDKEHeatpumpIR(); }}, // NOLINT + {PROTOCOL_VAILLANTVAI8, []() { return new VaillantHeatpumpIR(); }}, // NOLINT + {PROTOCOL_R51M, []() { return new R51MHeatpumpIR(); }}, // NOLINT }; void HeatpumpIRClimate::setup() { diff --git a/esphome/components/heatpumpir/heatpumpir.h b/esphome/components/heatpumpir/heatpumpir.h index 0e6ea2218f..f6e7ff3cd6 100644 --- a/esphome/components/heatpumpir/heatpumpir.h +++ b/esphome/components/heatpumpir/heatpumpir.h @@ -61,6 +61,11 @@ enum Protocol { PROTOCOL_QLIMA_2, PROTOCOL_SAMSUNG_AQV12MSAN, PROTOCOL_ZHJG01, + PROTOCOL_AIRWAY, + PROTOCOL_BGH_AUD, + PROTOCOL_PANASONIC_ALTDKE, + PROTOCOL_VAILLANTVAI8, + PROTOCOL_R51M, }; // Simple enum to represent horizontal directios diff --git a/esphome/components/i2s_audio/__init__.py b/esphome/components/i2s_audio/__init__.py index d72e13630f..05e44696d8 100644 --- a/esphome/components/i2s_audio/__init__.py +++ b/esphome/components/i2s_audio/__init__.py @@ -25,6 +25,10 @@ CONF_I2S_LRCLK_PIN = "i2s_lrclk_pin" CONF_I2S_AUDIO = "i2s_audio" CONF_I2S_AUDIO_ID = "i2s_audio_id" +CONF_I2S_MODE = "i2s_mode" +CONF_PRIMARY = "primary" +CONF_SECONDARY = "secondary" + i2s_audio_ns = cg.esphome_ns.namespace("i2s_audio") I2SAudioComponent = i2s_audio_ns.class_("I2SAudioComponent", cg.Component) I2SAudioIn = i2s_audio_ns.class_("I2SAudioIn", cg.Parented.template(I2SAudioComponent)) @@ -32,6 +36,12 @@ I2SAudioOut = i2s_audio_ns.class_( "I2SAudioOut", cg.Parented.template(I2SAudioComponent) ) +i2s_mode_t = cg.global_ns.enum("i2s_mode_t") +I2S_MODE_OPTIONS = { + CONF_PRIMARY: i2s_mode_t.I2S_MODE_MASTER, # NOLINT + CONF_SECONDARY: i2s_mode_t.I2S_MODE_SLAVE, # NOLINT +} + # https://github.com/espressif/esp-idf/blob/master/components/soc/{variant}/include/soc/soc_caps.h I2S_PORTS = { VARIANT_ESP32: 2, diff --git a/esphome/components/i2s_audio/microphone/__init__.py b/esphome/components/i2s_audio/microphone/__init__.py index d9c31e8e7b..844f176bea 100644 --- a/esphome/components/i2s_audio/microphone/__init__.py +++ b/esphome/components/i2s_audio/microphone/__init__.py @@ -7,6 +7,9 @@ from esphome.components import microphone, esp32 from esphome.components.adc import ESP32_VARIANT_ADC1_PIN_TO_CHANNEL, validate_adc_pin from .. import ( + CONF_I2S_MODE, + CONF_PRIMARY, + I2S_MODE_OPTIONS, i2s_audio_ns, I2SAudioComponent, I2SAudioIn, @@ -68,6 +71,9 @@ BASE_SCHEMA = microphone.MICROPHONE_SCHEMA.extend( _validate_bits, cv.enum(BITS_PER_SAMPLE) ), cv.Optional(CONF_USE_APLL, default=False): cv.boolean, + cv.Optional(CONF_I2S_MODE, default=CONF_PRIMARY): cv.enum( + I2S_MODE_OPTIONS, lower=True + ), } ).extend(cv.COMPONENT_SCHEMA) @@ -107,6 +113,7 @@ async def to_code(config): cg.add(var.set_din_pin(config[CONF_I2S_DIN_PIN])) cg.add(var.set_pdm(config[CONF_PDM])) + cg.add(var.set_i2s_mode(config[CONF_I2S_MODE])) cg.add(var.set_channel(config[CONF_CHANNEL])) cg.add(var.set_sample_rate(config[CONF_SAMPLE_RATE])) cg.add(var.set_bits_per_sample(config[CONF_BITS_PER_SAMPLE])) diff --git a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp index a672348d85..009fecdf90 100644 --- a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +++ b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp @@ -46,7 +46,7 @@ void I2SAudioMicrophone::start_() { return; // Waiting for another i2s to return lock } i2s_driver_config_t config = { - .mode = (i2s_mode_t) (I2S_MODE_MASTER | I2S_MODE_RX), + .mode = (i2s_mode_t) (this->i2s_mode_ | I2S_MODE_RX), .sample_rate = this->sample_rate_, .bits_per_sample = this->bits_per_sample_, .channel_format = this->channel_, @@ -174,8 +174,7 @@ size_t I2SAudioMicrophone::read(int16_t *buf, size_t len) { size_t samples_read = bytes_read / sizeof(int32_t); samples.resize(samples_read); for (size_t i = 0; i < samples_read; i++) { - int32_t temp = reinterpret_cast(buf)[i] >> 14; - samples[i] = clamp(temp, INT16_MIN, INT16_MAX); + samples[i] = reinterpret_cast(buf)[i] >> 16; } memcpy(buf, samples.data(), samples_read * sizeof(int16_t)); return samples_read * sizeof(int16_t); diff --git a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h index 68b9a94fbd..07ca0528aa 100644 --- a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +++ b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h @@ -30,6 +30,8 @@ class I2SAudioMicrophone : public I2SAudioIn, public microphone::Microphone, pub } #endif + void set_i2s_mode(i2s_mode_t mode) { this->i2s_mode_ = mode; } + void set_channel(i2s_channel_fmt_t channel) { this->channel_ = channel; } void set_sample_rate(uint32_t sample_rate) { this->sample_rate_ = sample_rate; } void set_bits_per_sample(i2s_bits_per_sample_t bits_per_sample) { this->bits_per_sample_ = bits_per_sample; } @@ -46,6 +48,7 @@ class I2SAudioMicrophone : public I2SAudioIn, public microphone::Microphone, pub bool adc_{false}; #endif bool pdm_{false}; + i2s_mode_t i2s_mode_{}; i2s_channel_fmt_t channel_; uint32_t sample_rate_; i2s_bits_per_sample_t bits_per_sample_; diff --git a/esphome/components/improv_serial/improv_serial_component.cpp b/esphome/components/improv_serial/improv_serial_component.cpp index 02ffa9f31c..12809e38cb 100644 --- a/esphome/components/improv_serial/improv_serial_component.cpp +++ b/esphome/components/improv_serial/improv_serial_component.cpp @@ -57,7 +57,7 @@ optional ImprovSerialComponent::read_byte_() { } } break; -#ifdef USE_LOGGER_USB_CDC +#if defined(USE_LOGGER_USB_CDC) && defined(CONFIG_ESP_CONSOLE_USB_CDC) case logger::UART_SELECTION_USB_CDC: #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) if (esp_usb_console_available_for_read()) { @@ -99,7 +99,7 @@ void ImprovSerialComponent::write_data_(std::vector &data) { #endif // !USE_ESP32_VARIANT_ESP32C3 && !USE_ESP32_VARIANT_ESP32S2 && !USE_ESP32_VARIANT_ESP32S3 uart_write_bytes(this->uart_num_, data.data(), data.size()); break; -#ifdef USE_LOGGER_USB_CDC +#if defined(USE_LOGGER_USB_CDC) && defined(CONFIG_ESP_CONSOLE_USB_CDC) case logger::UART_SELECTION_USB_CDC: { const char *msg = (char *) data.data(); esp_usb_console_write_buf(msg, data.size()); @@ -109,6 +109,7 @@ void ImprovSerialComponent::write_data_(std::vector &data) { #ifdef USE_LOGGER_USB_SERIAL_JTAG case logger::UART_SELECTION_USB_SERIAL_JTAG: usb_serial_jtag_write_bytes((char *) data.data(), data.size(), 20 / portTICK_PERIOD_MS); + delay(10); usb_serial_jtag_ll_txfifo_flush(); // fixes for issue in IDF 4.4.7 break; #endif // USE_LOGGER_USB_SERIAL_JTAG diff --git a/esphome/components/ltr390/ltr390.cpp b/esphome/components/ltr390/ltr390.cpp index 4eb1ff2c46..198d15ebd8 100644 --- a/esphome/components/ltr390/ltr390.cpp +++ b/esphome/components/ltr390/ltr390.cpp @@ -19,6 +19,7 @@ static const uint8_t LTR390_MAIN_STATUS = 0x07; static const float GAINVALUES[5] = {1.0, 3.0, 6.0, 9.0, 18.0}; static const float RESOLUTIONVALUE[6] = {4.0, 2.0, 1.0, 0.5, 0.25, 0.125}; +static const uint8_t RESOLUTION_BITS[6] = {20, 19, 18, 17, 16, 13}; // Request fastest measurement rate - will be slowed by device if conversion rate is slower. static const float RESOLUTION_SETTING[6] = {0x00, 0x10, 0x20, 0x30, 0x40, 0x50}; @@ -74,7 +75,7 @@ void LTR390Component::read_als_() { uint32_t als = *val; if (this->light_sensor_ != nullptr) { - float lux = ((0.6 * als) / (GAINVALUES[this->gain_] * RESOLUTIONVALUE[this->res_])) * this->wfac_; + float lux = ((0.6 * als) / (GAINVALUES[this->gain_als_] * RESOLUTIONVALUE[this->res_als_])) * this->wfac_; this->light_sensor_->publish_state(lux); } @@ -90,7 +91,7 @@ void LTR390Component::read_uvs_() { uint32_t uv = *val; if (this->uvi_sensor_ != nullptr) { - this->uvi_sensor_->publish_state((uv / this->sensitivity_) * this->wfac_); + this->uvi_sensor_->publish_state((uv / this->sensitivity_uv_) * this->wfac_); } if (this->uv_sensor_ != nullptr) { @@ -107,24 +108,38 @@ void LTR390Component::read_mode_(int mode_index) { ctrl[LTR390_CTRL_EN] = true; this->reg(LTR390_MAIN_CTRL) = ctrl.to_ulong(); - // After the sensor integration time do the following - this->set_timeout(((uint32_t) RESOLUTIONVALUE[this->res_]) * 100 + LTR390_WAKEUP_TIME + LTR390_SETTLE_TIME, - [this, mode_index]() { - // Read from the sensor - std::get<1>(this->mode_funcs_[mode_index])(); + uint32_t int_time{0}; + // Set gain, resolution and measurement rate + switch (mode) { + case LTR390_MODE_ALS: + this->reg(LTR390_GAIN) = this->gain_als_; + this->reg(LTR390_MEAS_RATE) = RESOLUTION_SETTING[this->res_als_]; + int_time = ((uint32_t) RESOLUTIONVALUE[this->res_als_]) * 100; + break; + case LTR390_MODE_UVS: + this->reg(LTR390_GAIN) = this->gain_uv_; + this->reg(LTR390_MEAS_RATE) = RESOLUTION_SETTING[this->res_uv_]; + int_time = ((uint32_t) RESOLUTIONVALUE[this->res_uv_]) * 100; + break; + } - // If there are more modes to read then begin the next - // otherwise stop - if (mode_index + 1 < (int) this->mode_funcs_.size()) { - this->read_mode_(mode_index + 1); - } else { - // put sensor in standby - std::bitset<8> ctrl = this->reg(LTR390_MAIN_CTRL).get(); - ctrl[LTR390_CTRL_EN] = false; - this->reg(LTR390_MAIN_CTRL) = ctrl.to_ulong(); - this->reading_ = false; - } - }); + // After the sensor integration time do the following + this->set_timeout(int_time + LTR390_WAKEUP_TIME + LTR390_SETTLE_TIME, [this, mode_index]() { + // Read from the sensor + std::get<1>(this->mode_funcs_[mode_index])(); + + // If there are more modes to read then begin the next + // otherwise stop + if (mode_index + 1 < (int) this->mode_funcs_.size()) { + this->read_mode_(mode_index + 1); + } else { + // put sensor in standby + std::bitset<8> ctrl = this->reg(LTR390_MAIN_CTRL).get(); + ctrl[LTR390_CTRL_EN] = false; + this->reg(LTR390_MAIN_CTRL) = ctrl.to_ulong(); + this->reading_ = false; + } + }); } void LTR390Component::setup() { @@ -151,16 +166,10 @@ void LTR390Component::setup() { return; } - // Set gain - this->reg(LTR390_GAIN) = gain_; - - // Set resolution and measurement rate - this->reg(LTR390_MEAS_RATE) = RESOLUTION_SETTING[this->res_]; - // Set sensitivity by linearly scaling against known value in the datasheet - float gain_scale = GAINVALUES[this->gain_] / GAIN_MAX; - float intg_scale = (RESOLUTIONVALUE[this->res_] * 100) / INTG_MAX; - this->sensitivity_ = SENSITIVITY_MAX * gain_scale * intg_scale; + float gain_scale_uv = GAINVALUES[this->gain_uv_] / GAIN_MAX; + float intg_scale_uv = (RESOLUTIONVALUE[this->res_uv_] * 100) / INTG_MAX; + this->sensitivity_uv_ = SENSITIVITY_MAX * gain_scale_uv * intg_scale_uv; // Set sensor read state this->reading_ = false; @@ -176,7 +185,13 @@ void LTR390Component::setup() { } } -void LTR390Component::dump_config() { LOG_I2C_DEVICE(this); } +void LTR390Component::dump_config() { + LOG_I2C_DEVICE(this); + ESP_LOGCONFIG(TAG, " ALS Gain: X%.0f", GAINVALUES[this->gain_als_]); + ESP_LOGCONFIG(TAG, " ALS Resolution: %u-bit", RESOLUTION_BITS[this->res_als_]); + ESP_LOGCONFIG(TAG, " UV Gain: X%.0f", GAINVALUES[this->gain_uv_]); + ESP_LOGCONFIG(TAG, " UV Resolution: %u-bit", RESOLUTION_BITS[this->res_uv_]); +} void LTR390Component::update() { if (!this->reading_ && !mode_funcs_.empty()) { diff --git a/esphome/components/ltr390/ltr390.h b/esphome/components/ltr390/ltr390.h index bc98518fe9..24afd3c411 100644 --- a/esphome/components/ltr390/ltr390.h +++ b/esphome/components/ltr390/ltr390.h @@ -49,8 +49,10 @@ class LTR390Component : public PollingComponent, public i2c::I2CDevice { void dump_config() override; void update() override; - void set_gain_value(LTR390GAIN gain) { this->gain_ = gain; } - void set_res_value(LTR390RESOLUTION res) { this->res_ = res; } + void set_als_gain_value(LTR390GAIN gain) { this->gain_als_ = gain; } + void set_uv_gain_value(LTR390GAIN gain) { this->gain_uv_ = gain; } + void set_als_res_value(LTR390RESOLUTION res) { this->res_als_ = res; } + void set_uv_res_value(LTR390RESOLUTION res) { this->res_uv_ = res; } void set_wfac_value(float wfac) { this->wfac_ = wfac; } void set_light_sensor(sensor::Sensor *light_sensor) { this->light_sensor_ = light_sensor; } @@ -71,9 +73,11 @@ class LTR390Component : public PollingComponent, public i2c::I2CDevice { // a list of modes and corresponding read functions std::vector>> mode_funcs_; - LTR390GAIN gain_; - LTR390RESOLUTION res_; - float sensitivity_; + LTR390GAIN gain_als_; + LTR390GAIN gain_uv_; + LTR390RESOLUTION res_als_; + LTR390RESOLUTION res_uv_; + float sensitivity_uv_; float wfac_; sensor::Sensor *light_sensor_{nullptr}; diff --git a/esphome/components/ltr390/sensor.py b/esphome/components/ltr390/sensor.py index 8b2676599c..62c3edf8cb 100644 --- a/esphome/components/ltr390/sensor.py +++ b/esphome/components/ltr390/sensor.py @@ -13,7 +13,7 @@ from esphome.const import ( UNIT_LUX, ) -CODEOWNERS = ["@sjtrny"] +CODEOWNERS = ["@sjtrny", "@latonita"] DEPENDENCIES = ["i2c"] ltr390_ns = cg.esphome_ns.namespace("ltr390") @@ -76,8 +76,24 @@ CONFIG_SCHEMA = cv.All( accuracy_decimals=1, device_class=DEVICE_CLASS_EMPTY, ), - cv.Optional(CONF_GAIN, default="X18"): cv.enum(GAIN_OPTIONS), - cv.Optional(CONF_RESOLUTION, default=20): cv.enum(RES_OPTIONS), + cv.Optional(CONF_GAIN, default="X18"): cv.Any( + cv.enum(GAIN_OPTIONS), + cv.Schema( + { + cv.Required(CONF_AMBIENT_LIGHT): cv.enum(GAIN_OPTIONS), + cv.Required(CONF_UV): cv.enum(GAIN_OPTIONS), + } + ), + ), + cv.Optional(CONF_RESOLUTION, default=20): cv.Any( + cv.enum(RES_OPTIONS), + cv.Schema( + { + cv.Required(CONF_AMBIENT_LIGHT): cv.enum(RES_OPTIONS), + cv.Required(CONF_UV): cv.enum(RES_OPTIONS), + } + ), + ), cv.Optional(CONF_WINDOW_CORRECTION_FACTOR, default=1.0): cv.float_range( min=1.0 ), @@ -101,11 +117,25 @@ async def to_code(config): await cg.register_component(var, config) await i2c.register_i2c_device(var, config) - cg.add(var.set_gain_value(config[CONF_GAIN])) - cg.add(var.set_res_value(config[CONF_RESOLUTION])) cg.add(var.set_wfac_value(config[CONF_WINDOW_CORRECTION_FACTOR])) for key, funcName in TYPES.items(): if key in config: sens = await sensor.new_sensor(config[key]) cg.add(getattr(var, funcName)(sens)) + + gain_value = config[CONF_GAIN] + if isinstance(gain_value, dict): + cg.add(var.set_als_gain_value(gain_value[CONF_AMBIENT_LIGHT])) + cg.add(var.set_uv_gain_value(gain_value[CONF_UV])) + else: + cg.add(var.set_als_gain_value(gain_value)) + cg.add(var.set_uv_gain_value(gain_value)) + + res_value = config[CONF_RESOLUTION] + if isinstance(res_value, dict): + cg.add(var.set_als_res_value(res_value[CONF_AMBIENT_LIGHT])) + cg.add(var.set_uv_res_value(res_value[CONF_UV])) + else: + cg.add(var.set_als_res_value(res_value)) + cg.add(var.set_uv_res_value(res_value)) diff --git a/esphome/components/micro_wake_word/__init__.py b/esphome/components/micro_wake_word/__init__.py index 3d3459ccab..c2faca25f4 100644 --- a/esphome/components/micro_wake_word/__init__.py +++ b/esphome/components/micro_wake_word/__init__.py @@ -357,7 +357,9 @@ CONFIG_SCHEMA = cv.All( { cv.GenerateID(): cv.declare_id(MicroWakeWord), cv.GenerateID(CONF_MICROPHONE): cv.use_id(microphone.Microphone), - cv.Required(CONF_MODELS): cv.ensure_list(MODEL_SCHEMA), + cv.Required(CONF_MODELS): cv.ensure_list( + cv.maybe_simple_value(MODEL_SCHEMA, key=CONF_MODEL) + ), cv.Optional(CONF_ON_WAKE_WORD_DETECTED): automation.validate_automation( single=True ), diff --git a/esphome/components/ota/ota_backend_arduino_esp32.cpp b/esphome/components/ota/ota_backend_arduino_esp32.cpp index 62c6a72388..15dfc98a6c 100644 --- a/esphome/components/ota/ota_backend_arduino_esp32.cpp +++ b/esphome/components/ota/ota_backend_arduino_esp32.cpp @@ -1,14 +1,17 @@ #ifdef USE_ESP32_FRAMEWORK_ARDUINO #include "esphome/core/defines.h" +#include "esphome/core/log.h" -#include "ota_backend_arduino_esp32.h" #include "ota_backend.h" +#include "ota_backend_arduino_esp32.h" #include namespace esphome { namespace ota { +static const char *const TAG = "ota.arduino_esp32"; + std::unique_ptr make_ota_backend() { return make_unique(); } OTAResponseTypes ArduinoESP32OTABackend::begin(size_t image_size) { @@ -20,6 +23,9 @@ OTAResponseTypes ArduinoESP32OTABackend::begin(size_t image_size) { uint8_t error = Update.getError(); if (error == UPDATE_ERROR_SIZE) return OTA_RESPONSE_ERROR_ESP32_NOT_ENOUGH_SPACE; + + ESP_LOGE(TAG, "Begin error: %d", error); + return OTA_RESPONSE_ERROR_UNKNOWN; } @@ -27,16 +33,25 @@ void ArduinoESP32OTABackend::set_update_md5(const char *md5) { Update.setMD5(md5 OTAResponseTypes ArduinoESP32OTABackend::write(uint8_t *data, size_t len) { size_t written = Update.write(data, len); - if (written != len) { - return OTA_RESPONSE_ERROR_WRITING_FLASH; + if (written == len) { + return OTA_RESPONSE_OK; } - return OTA_RESPONSE_OK; + + uint8_t error = Update.getError(); + ESP_LOGE(TAG, "Write error: %d", error); + + return OTA_RESPONSE_ERROR_WRITING_FLASH; } OTAResponseTypes ArduinoESP32OTABackend::end() { - if (!Update.end()) - return OTA_RESPONSE_ERROR_UPDATE_END; - return OTA_RESPONSE_OK; + if (Update.end()) { + return OTA_RESPONSE_OK; + } + + uint8_t error = Update.getError(); + ESP_LOGE(TAG, "End error: %d", error); + + return OTA_RESPONSE_ERROR_UPDATE_END; } void ArduinoESP32OTABackend::abort() { Update.abort(); } diff --git a/esphome/components/ota/ota_backend_arduino_esp8266.cpp b/esphome/components/ota/ota_backend_arduino_esp8266.cpp index b317075bd0..42edbf5d2b 100644 --- a/esphome/components/ota/ota_backend_arduino_esp8266.cpp +++ b/esphome/components/ota/ota_backend_arduino_esp8266.cpp @@ -1,16 +1,19 @@ #ifdef USE_ARDUINO #ifdef USE_ESP8266 -#include "ota_backend.h" #include "ota_backend_arduino_esp8266.h" +#include "ota_backend.h" -#include "esphome/core/defines.h" #include "esphome/components/esp8266/preferences.h" +#include "esphome/core/defines.h" +#include "esphome/core/log.h" #include namespace esphome { namespace ota { +static const char *const TAG = "ota.arduino_esp8266"; + std::unique_ptr make_ota_backend() { return make_unique(); } OTAResponseTypes ArduinoESP8266OTABackend::begin(size_t image_size) { @@ -29,6 +32,9 @@ OTAResponseTypes ArduinoESP8266OTABackend::begin(size_t image_size) { return OTA_RESPONSE_ERROR_WRONG_CURRENT_FLASH_CONFIG; if (error == UPDATE_ERROR_SPACE) return OTA_RESPONSE_ERROR_ESP8266_NOT_ENOUGH_SPACE; + + ESP_LOGE(TAG, "Begin error: %d", error); + return OTA_RESPONSE_ERROR_UNKNOWN; } @@ -36,16 +42,25 @@ void ArduinoESP8266OTABackend::set_update_md5(const char *md5) { Update.setMD5(m OTAResponseTypes ArduinoESP8266OTABackend::write(uint8_t *data, size_t len) { size_t written = Update.write(data, len); - if (written != len) { - return OTA_RESPONSE_ERROR_WRITING_FLASH; + if (written == len) { + return OTA_RESPONSE_OK; } - return OTA_RESPONSE_OK; + + uint8_t error = Update.getError(); + ESP_LOGE(TAG, "Write error: %d", error); + + return OTA_RESPONSE_ERROR_WRITING_FLASH; } OTAResponseTypes ArduinoESP8266OTABackend::end() { - if (!Update.end()) - return OTA_RESPONSE_ERROR_UPDATE_END; - return OTA_RESPONSE_OK; + if (Update.end()) { + return OTA_RESPONSE_OK; + } + + uint8_t error = Update.getError(); + ESP_LOGE(TAG, "End error: %d", error); + + return OTA_RESPONSE_ERROR_UPDATE_END; } void ArduinoESP8266OTABackend::abort() { diff --git a/esphome/components/ota/ota_backend_arduino_libretiny.cpp b/esphome/components/ota/ota_backend_arduino_libretiny.cpp index df4e774ebc..6b2cf80684 100644 --- a/esphome/components/ota/ota_backend_arduino_libretiny.cpp +++ b/esphome/components/ota/ota_backend_arduino_libretiny.cpp @@ -1,14 +1,17 @@ #ifdef USE_LIBRETINY -#include "ota_backend.h" #include "ota_backend_arduino_libretiny.h" +#include "ota_backend.h" #include "esphome/core/defines.h" +#include "esphome/core/log.h" #include namespace esphome { namespace ota { +static const char *const TAG = "ota.arduino_libretiny"; + std::unique_ptr make_ota_backend() { return make_unique(); } OTAResponseTypes ArduinoLibreTinyOTABackend::begin(size_t image_size) { @@ -20,6 +23,9 @@ OTAResponseTypes ArduinoLibreTinyOTABackend::begin(size_t image_size) { uint8_t error = Update.getError(); if (error == UPDATE_ERROR_SIZE) return OTA_RESPONSE_ERROR_ESP32_NOT_ENOUGH_SPACE; + + ESP_LOGE(TAG, "Begin error: %d", error); + return OTA_RESPONSE_ERROR_UNKNOWN; } @@ -27,16 +33,25 @@ void ArduinoLibreTinyOTABackend::set_update_md5(const char *md5) { Update.setMD5 OTAResponseTypes ArduinoLibreTinyOTABackend::write(uint8_t *data, size_t len) { size_t written = Update.write(data, len); - if (written != len) { - return OTA_RESPONSE_ERROR_WRITING_FLASH; + if (written == len) { + return OTA_RESPONSE_OK; } - return OTA_RESPONSE_OK; + + uint8_t error = Update.getError(); + ESP_LOGE(TAG, "Write error: %d", error); + + return OTA_RESPONSE_ERROR_WRITING_FLASH; } OTAResponseTypes ArduinoLibreTinyOTABackend::end() { - if (!Update.end()) - return OTA_RESPONSE_ERROR_UPDATE_END; - return OTA_RESPONSE_OK; + if (Update.end()) { + return OTA_RESPONSE_OK; + } + + uint8_t error = Update.getError(); + ESP_LOGE(TAG, "End error: %d", error); + + return OTA_RESPONSE_ERROR_UPDATE_END; } void ArduinoLibreTinyOTABackend::abort() { Update.abort(); } diff --git a/esphome/components/ota/ota_backend_arduino_rp2040.cpp b/esphome/components/ota/ota_backend_arduino_rp2040.cpp index 4448b0c95e..ffeab2e93f 100644 --- a/esphome/components/ota/ota_backend_arduino_rp2040.cpp +++ b/esphome/components/ota/ota_backend_arduino_rp2040.cpp @@ -1,16 +1,19 @@ #ifdef USE_ARDUINO #ifdef USE_RP2040 -#include "ota_backend.h" #include "ota_backend_arduino_rp2040.h" +#include "ota_backend.h" #include "esphome/components/rp2040/preferences.h" #include "esphome/core/defines.h" +#include "esphome/core/log.h" #include namespace esphome { namespace ota { +static const char *const TAG = "ota.arduino_rp2040"; + std::unique_ptr make_ota_backend() { return make_unique(); } OTAResponseTypes ArduinoRP2040OTABackend::begin(size_t image_size) { @@ -29,6 +32,9 @@ OTAResponseTypes ArduinoRP2040OTABackend::begin(size_t image_size) { return OTA_RESPONSE_ERROR_WRONG_CURRENT_FLASH_CONFIG; if (error == UPDATE_ERROR_SPACE) return OTA_RESPONSE_ERROR_RP2040_NOT_ENOUGH_SPACE; + + ESP_LOGE(TAG, "Begin error: %d", error); + return OTA_RESPONSE_ERROR_UNKNOWN; } @@ -36,16 +42,25 @@ void ArduinoRP2040OTABackend::set_update_md5(const char *md5) { Update.setMD5(md OTAResponseTypes ArduinoRP2040OTABackend::write(uint8_t *data, size_t len) { size_t written = Update.write(data, len); - if (written != len) { - return OTA_RESPONSE_ERROR_WRITING_FLASH; + if (written == len) { + return OTA_RESPONSE_OK; } - return OTA_RESPONSE_OK; + + uint8_t error = Update.getError(); + ESP_LOGE(TAG, "Write error: %d", error); + + return OTA_RESPONSE_ERROR_WRITING_FLASH; } OTAResponseTypes ArduinoRP2040OTABackend::end() { - if (!Update.end()) - return OTA_RESPONSE_ERROR_UPDATE_END; - return OTA_RESPONSE_OK; + if (Update.end()) { + return OTA_RESPONSE_OK; + } + + uint8_t error = Update.getError(); + ESP_LOGE(TAG, "End error: %d", error); + + return OTA_RESPONSE_ERROR_UPDATE_END; } void ArduinoRP2040OTABackend::abort() { diff --git a/esphome/components/uart/uart_component_host.cpp b/esphome/components/uart/uart_component_host.cpp index d8d2fd75b8..40d3e91ab2 100644 --- a/esphome/components/uart/uart_component_host.cpp +++ b/esphome/components/uart/uart_component_host.cpp @@ -5,8 +5,8 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" -#ifndef __linux__ -#error This HostUartComponent implementation is only for Linux +#if !(defined(__linux__) || defined(__APPLE__)) +#error This HostUartComponent implementation is not supported on this host OS #endif #include @@ -24,6 +24,9 @@ namespace { speed_t get_baud(int baud) { +#ifdef __APPLE__ + return baud; +#else switch (baud) { case 50: return B50; @@ -88,6 +91,7 @@ speed_t get_baud(int baud) { default: return B0; } +#endif } } // namespace diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 9a1641e86f..6fb04f558a 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -46,29 +46,6 @@ static const char *const HEADER_CORS_REQ_PNA = "Access-Control-Request-Private-N static const char *const HEADER_CORS_ALLOW_PNA = "Access-Control-Allow-Private-Network"; #endif -#if USE_WEBSERVER_VERSION == 1 -void write_row(AsyncResponseStream *stream, EntityBase *obj, const std::string &klass, const std::string &action, - const std::function &action_func = nullptr) { - stream->print("print(klass.c_str()); - if (obj->is_internal()) - stream->print(" internal"); - stream->print("\" id=\""); - stream->print(klass.c_str()); - stream->print("-"); - stream->print(obj->get_object_id().c_str()); - stream->print("\">"); - stream->print(obj->get_name().c_str()); - stream->print(""); - stream->print(action.c_str()); - if (action_func) { - action_func(*stream, obj); - } - stream->print(""); - stream->print(""); -} -#endif - UrlMatch match_url(const std::string &url, bool only_domain = false) { UrlMatch match; match.valid = false; @@ -102,11 +79,6 @@ WebServer::WebServer(web_server_base::WebServerBase *base) #endif } -#if USE_WEBSERVER_VERSION == 1 -void WebServer::set_css_url(const char *css_url) { this->css_url_ = css_url; } -void WebServer::set_js_url(const char *js_url) { this->js_url_ = js_url; } -#endif - #ifdef USE_WEBSERVER_CSS_INCLUDE void WebServer::set_css_include(const char *css_include) { this->css_include_ = css_include; } #endif @@ -181,187 +153,6 @@ void WebServer::handle_index_request(AsyncWebServerRequest *request) { response->addHeader("Content-Encoding", "gzip"); request->send(response); } -#elif USE_WEBSERVER_VERSION == 1 -void WebServer::handle_index_request(AsyncWebServerRequest *request) { - AsyncResponseStream *stream = request->beginResponseStream("text/html"); - const std::string &title = App.get_name(); - stream->print(F("")); - stream->print(title.c_str()); - stream->print(F("")); -#ifdef USE_WEBSERVER_CSS_INCLUDE - stream->print(F("")); -#endif - if (strlen(this->css_url_) > 0) { - stream->print(F(R"(print(this->css_url_); - stream->print(F("\">")); - } - stream->print(F("")); - stream->print(F("

")); - stream->print(title.c_str()); - stream->print(F("

")); - stream->print(F("

States

")); - -#ifdef USE_SENSOR - for (auto *obj : App.get_sensors()) { - if (this->include_internal_ || !obj->is_internal()) - write_row(stream, obj, "sensor", ""); - } -#endif - -#ifdef USE_SWITCH - for (auto *obj : App.get_switches()) { - if (this->include_internal_ || !obj->is_internal()) - write_row(stream, obj, "switch", ""); - } -#endif - -#ifdef USE_BUTTON - for (auto *obj : App.get_buttons()) - write_row(stream, obj, "button", ""); -#endif - -#ifdef USE_BINARY_SENSOR - for (auto *obj : App.get_binary_sensors()) { - if (this->include_internal_ || !obj->is_internal()) - write_row(stream, obj, "binary_sensor", ""); - } -#endif - -#ifdef USE_FAN - for (auto *obj : App.get_fans()) { - if (this->include_internal_ || !obj->is_internal()) - write_row(stream, obj, "fan", ""); - } -#endif - -#ifdef USE_LIGHT - for (auto *obj : App.get_lights()) { - if (this->include_internal_ || !obj->is_internal()) - write_row(stream, obj, "light", ""); - } -#endif - -#ifdef USE_TEXT_SENSOR - for (auto *obj : App.get_text_sensors()) { - if (this->include_internal_ || !obj->is_internal()) - write_row(stream, obj, "text_sensor", ""); - } -#endif - -#ifdef USE_COVER - for (auto *obj : App.get_covers()) { - if (this->include_internal_ || !obj->is_internal()) - write_row(stream, obj, "cover", ""); - } -#endif - -#ifdef USE_NUMBER - for (auto *obj : App.get_numbers()) { - if (this->include_internal_ || !obj->is_internal()) { - write_row(stream, obj, "number", "", [](AsyncResponseStream &stream, EntityBase *obj) { - number::Number *number = (number::Number *) obj; - stream.print(R"(traits.get_min_value()); - stream.print(R"(" max=")"); - stream.print(number->traits.get_max_value()); - stream.print(R"(" step=")"); - stream.print(number->traits.get_step()); - stream.print(R"(" value=")"); - stream.print(number->state); - stream.print(R"("/>)"); - }); - } - } -#endif - -#ifdef USE_TEXT - for (auto *obj : App.get_texts()) { - if (this->include_internal_ || !obj->is_internal()) { - write_row(stream, obj, "text", "", [](AsyncResponseStream &stream, EntityBase *obj) { - text::Text *text = (text::Text *) obj; - auto mode = (int) text->traits.get_mode(); - stream.print(R"(traits.get_min_length()); - stream.print(R"(" maxlength=")"); - stream.print(text->traits.get_max_length()); - stream.print(R"(" pattern=")"); - stream.print(text->traits.get_pattern().c_str()); - stream.print(R"(" value=")"); - stream.print(text->state.c_str()); - stream.print(R"("/>)"); - }); - } - } -#endif - -#ifdef USE_SELECT - for (auto *obj : App.get_selects()) { - if (this->include_internal_ || !obj->is_internal()) { - write_row(stream, obj, "select", "", [](AsyncResponseStream &stream, EntityBase *obj) { - select::Select *select = (select::Select *) obj; - stream.print(""); - }); - } - } -#endif - -#ifdef USE_LOCK - for (auto *obj : App.get_locks()) { - if (this->include_internal_ || !obj->is_internal()) { - write_row(stream, obj, "lock", "", [](AsyncResponseStream &stream, EntityBase *obj) { - lock::Lock *lock = (lock::Lock *) obj; - stream.print(""); - if (lock->traits.get_supports_open()) { - stream.print(""); - } - }); - } - } -#endif - -#ifdef USE_CLIMATE - for (auto *obj : App.get_climates()) { - if (this->include_internal_ || !obj->is_internal()) - write_row(stream, obj, "climate", ""); - } -#endif - - stream->print(F("
NameStateActions

See ESPHome Web API for " - "REST API documentation.

")); - if (this->allow_ota_) { - stream->print( - F("

OTA Update

")); - } - stream->print(F("

Debug Log

"));
-#ifdef USE_WEBSERVER_JS_INCLUDE
-  if (this->js_include_ != nullptr) {
-    stream->print(F(""));
-  }
-#endif
-  if (strlen(this->js_url_) > 0) {
-    stream->print(F(""));
-  }
-  stream->print(F("
")); - request->send(stream); -} #elif USE_WEBSERVER_VERSION >= 2 void WebServer::handle_index_request(AsyncWebServerRequest *request) { AsyncWebServerResponse *response = diff --git a/esphome/components/web_server/web_server_v1.cpp b/esphome/components/web_server/web_server_v1.cpp new file mode 100644 index 0000000000..c9b38a2dc4 --- /dev/null +++ b/esphome/components/web_server/web_server_v1.cpp @@ -0,0 +1,217 @@ +#include "web_server.h" +#include "esphome/core/application.h" + +#if USE_WEBSERVER_VERSION == 1 + +namespace esphome { +namespace web_server { + +void write_row(AsyncResponseStream *stream, EntityBase *obj, const std::string &klass, const std::string &action, + const std::function &action_func = nullptr) { + stream->print("print(klass.c_str()); + if (obj->is_internal()) + stream->print(" internal"); + stream->print("\" id=\""); + stream->print(klass.c_str()); + stream->print("-"); + stream->print(obj->get_object_id().c_str()); + stream->print("\">"); + stream->print(obj->get_name().c_str()); + stream->print(""); + stream->print(action.c_str()); + if (action_func) { + action_func(*stream, obj); + } + stream->print(""); + stream->print(""); +} + +void WebServer::set_css_url(const char *css_url) { this->css_url_ = css_url; } + +void WebServer::set_js_url(const char *js_url) { this->js_url_ = js_url; } + +void WebServer::handle_index_request(AsyncWebServerRequest *request) { + AsyncResponseStream *stream = request->beginResponseStream("text/html"); + const std::string &title = App.get_name(); + stream->print(F("")); + stream->print(title.c_str()); + stream->print(F("")); +#ifdef USE_WEBSERVER_CSS_INCLUDE + stream->print(F("")); +#endif + if (strlen(this->css_url_) > 0) { + stream->print(F(R"(print(this->css_url_); + stream->print(F("\">")); + } + stream->print(F("")); + stream->print(F("

")); + stream->print(title.c_str()); + stream->print(F("

")); + stream->print(F("

States

")); + +#ifdef USE_SENSOR + for (auto *obj : App.get_sensors()) { + if (this->include_internal_ || !obj->is_internal()) + write_row(stream, obj, "sensor", ""); + } +#endif + +#ifdef USE_SWITCH + for (auto *obj : App.get_switches()) { + if (this->include_internal_ || !obj->is_internal()) + write_row(stream, obj, "switch", ""); + } +#endif + +#ifdef USE_BUTTON + for (auto *obj : App.get_buttons()) + write_row(stream, obj, "button", ""); +#endif + +#ifdef USE_BINARY_SENSOR + for (auto *obj : App.get_binary_sensors()) { + if (this->include_internal_ || !obj->is_internal()) + write_row(stream, obj, "binary_sensor", ""); + } +#endif + +#ifdef USE_FAN + for (auto *obj : App.get_fans()) { + if (this->include_internal_ || !obj->is_internal()) + write_row(stream, obj, "fan", ""); + } +#endif + +#ifdef USE_LIGHT + for (auto *obj : App.get_lights()) { + if (this->include_internal_ || !obj->is_internal()) + write_row(stream, obj, "light", ""); + } +#endif + +#ifdef USE_TEXT_SENSOR + for (auto *obj : App.get_text_sensors()) { + if (this->include_internal_ || !obj->is_internal()) + write_row(stream, obj, "text_sensor", ""); + } +#endif + +#ifdef USE_COVER + for (auto *obj : App.get_covers()) { + if (this->include_internal_ || !obj->is_internal()) + write_row(stream, obj, "cover", ""); + } +#endif + +#ifdef USE_NUMBER + for (auto *obj : App.get_numbers()) { + if (this->include_internal_ || !obj->is_internal()) { + write_row(stream, obj, "number", "", [](AsyncResponseStream &stream, EntityBase *obj) { + number::Number *number = (number::Number *) obj; + stream.print(R"(traits.get_min_value()); + stream.print(R"(" max=")"); + stream.print(number->traits.get_max_value()); + stream.print(R"(" step=")"); + stream.print(number->traits.get_step()); + stream.print(R"(" value=")"); + stream.print(number->state); + stream.print(R"("/>)"); + }); + } + } +#endif + +#ifdef USE_TEXT + for (auto *obj : App.get_texts()) { + if (this->include_internal_ || !obj->is_internal()) { + write_row(stream, obj, "text", "", [](AsyncResponseStream &stream, EntityBase *obj) { + text::Text *text = (text::Text *) obj; + auto mode = (int) text->traits.get_mode(); + stream.print(R"(traits.get_min_length()); + stream.print(R"(" maxlength=")"); + stream.print(text->traits.get_max_length()); + stream.print(R"(" pattern=")"); + stream.print(text->traits.get_pattern().c_str()); + stream.print(R"(" value=")"); + stream.print(text->state.c_str()); + stream.print(R"("/>)"); + }); + } + } +#endif + +#ifdef USE_SELECT + for (auto *obj : App.get_selects()) { + if (this->include_internal_ || !obj->is_internal()) { + write_row(stream, obj, "select", "", [](AsyncResponseStream &stream, EntityBase *obj) { + select::Select *select = (select::Select *) obj; + stream.print(""); + }); + } + } +#endif + +#ifdef USE_LOCK + for (auto *obj : App.get_locks()) { + if (this->include_internal_ || !obj->is_internal()) { + write_row(stream, obj, "lock", "", [](AsyncResponseStream &stream, EntityBase *obj) { + lock::Lock *lock = (lock::Lock *) obj; + stream.print(""); + if (lock->traits.get_supports_open()) { + stream.print(""); + } + }); + } + } +#endif + +#ifdef USE_CLIMATE + for (auto *obj : App.get_climates()) { + if (this->include_internal_ || !obj->is_internal()) + write_row(stream, obj, "climate", ""); + } +#endif + + stream->print(F("
NameStateActions

See ESPHome Web API for " + "REST API documentation.

")); + if (this->allow_ota_) { + stream->print( + F("

OTA Update

")); + } + stream->print(F("

Debug Log

"));
+#ifdef USE_WEBSERVER_JS_INCLUDE
+  if (this->js_include_ != nullptr) {
+    stream->print(F(""));
+  }
+#endif
+  if (strlen(this->js_url_) > 0) {
+    stream->print(F(""));
+  }
+  stream->print(F("
")); + request->send(stream); +} + +} // namespace web_server +} // namespace esphome +#endif diff --git a/esphome/components/wifi/wifi_component_esp32_arduino.cpp b/esphome/components/wifi/wifi_component_esp32_arduino.cpp index fc954a2333..71548b7a3e 100644 --- a/esphome/components/wifi/wifi_component_esp32_arduino.cpp +++ b/esphome/components/wifi/wifi_component_esp32_arduino.cpp @@ -82,8 +82,8 @@ bool WiFiComponent::wifi_mode_(optional sta, optional ap) { // WiFiClass::mode above calls esp_netif_create_default_wifi_sta() and // esp_netif_create_default_wifi_ap(), which creates the interfaces. - if (set_sta) - s_sta_netif = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"); + // s_sta_netif handle is set during ESPHOME_EVENT_ID_WIFI_STA_START event + #ifdef USE_WIFI_AP if (set_ap) s_ap_netif = esp_netif_get_handle_from_ifkey("WIFI_AP_DEF"); @@ -495,6 +495,7 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ case ESPHOME_EVENT_ID_WIFI_STA_START: { ESP_LOGV(TAG, "Event: WiFi STA start"); // apply hostname + s_sta_netif = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"); esp_err_t err = esp_netif_set_hostname(s_sta_netif, App.get_name().c_str()); if (err != ERR_OK) { ESP_LOGW(TAG, "esp_netif_set_hostname failed: %s", esp_err_to_name(err)); diff --git a/platformio.ini b/platformio.ini index f07889526f..fc7f35b6c3 100644 --- a/platformio.ini +++ b/platformio.ini @@ -65,7 +65,7 @@ lib_deps = glmnet/Dsmr@0.7 ; dsmr rweather/Crypto@0.4.0 ; dsmr dudanov/MideaUART@1.1.9 ; midea - tonia/HeatpumpIR@1.0.26 ; heatpumpir + tonia/HeatpumpIR@1.0.27 ; heatpumpir build_flags = ${common.build_flags} -DUSE_ARDUINO @@ -93,8 +93,8 @@ lib_deps = ESP8266HTTPClient ; http_request (Arduino built-in) ESP8266mDNS ; mdns (Arduino built-in) DNSServer ; captive_portal (Arduino built-in) - crankyoldgit/IRremoteESP8266@2.8.6 ; heatpumpir droscy/esp_wireguard@0.4.2 ; wireguard + build_flags = ${common:arduino.build_flags} -Wno-nonnull-compare @@ -123,8 +123,8 @@ lib_deps = ESPmDNS ; mdns (Arduino built-in) DNSServer ; captive_portal (Arduino built-in) esphome/ESP32-audioI2S@2.0.7 ; i2s_audio - crankyoldgit/IRremoteESP8266@2.8.6 ; heatpumpir droscy/esp_wireguard@0.4.2 ; wireguard + build_flags = ${common:arduino.build_flags} -DUSE_ESP32 diff --git a/pyproject.toml b/pyproject.toml index fe558f695f..cfc279845f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -105,3 +105,33 @@ disable = [ [tool.pylint.FORMAT] expected-line-ending-format = "LF" + +[tool.ruff] +required-version = ">=0.5.0" + +[tool.ruff.lint] +select = [ + "E", # pycodestyle + "F", # pyflakes/autoflake + "I", # isort + "PL", # pylint + "UP", # pyupgrade +] + +ignore = [ + "E501", # line too long + "PLR0911", # Too many return statements ({returns} > {max_returns}) + "PLR0912", # Too many branches ({branches} > {max_branches}) + "PLR0913", # Too many arguments to function call ({c_args} > {max_args}) + "PLR0915", # Too many statements ({statements} > {max_statements}) + "PLR2004", # Magic value used in comparison, consider replacing {value} with a constant variable + "PLW2901", # Outer {outer_kind} variable {name} overwritten by inner {inner_kind} target +] + +[tool.ruff.lint.isort] +force-sort-within-sections = true +known-first-party = [ + "esphome", +] +combine-as-imports = true +split-on-trailing-comma = false diff --git a/tests/components/heatpumpir/test.bk72xx-ard.yaml b/tests/components/heatpumpir/test.bk72xx-ard.yaml new file mode 100644 index 0000000000..90259f1244 --- /dev/null +++ b/tests/components/heatpumpir/test.bk72xx-ard.yaml @@ -0,0 +1,19 @@ +remote_transmitter: + pin: 6 + carrier_duty_percent: 50% + +climate: + - platform: heatpumpir + protocol: daikin + horizontal_default: mleft + vertical_default: mup + name: HeatpumpIR Climate + min_temperature: 18 + max_temperature: 30 + - platform: heatpumpir + protocol: panasonic_altdke + horizontal_default: mright + vertical_default: mdown + name: HeatpumpIR Climate + min_temperature: 18 + max_temperature: 30 diff --git a/tests/components/improv_serial/common.yaml b/tests/components/improv_serial/common-uart0.yaml similarity index 64% rename from tests/components/improv_serial/common.yaml rename to tests/components/improv_serial/common-uart0.yaml index b36fe5a4a7..7b7730fd46 100644 --- a/tests/components/improv_serial/common.yaml +++ b/tests/components/improv_serial/common-uart0.yaml @@ -2,4 +2,7 @@ wifi: ssid: MySSID password: password1 +logger: + hardware_uart: UART0 + improv_serial: diff --git a/tests/components/improv_serial/common-usb_cdc.yaml b/tests/components/improv_serial/common-usb_cdc.yaml new file mode 100644 index 0000000000..fc72b6aa7e --- /dev/null +++ b/tests/components/improv_serial/common-usb_cdc.yaml @@ -0,0 +1,8 @@ +wifi: + ssid: MySSID + password: password1 + +logger: + hardware_uart: USB_CDC + +improv_serial: diff --git a/tests/components/improv_serial/common-usb_serial_jtag.yaml b/tests/components/improv_serial/common-usb_serial_jtag.yaml new file mode 100644 index 0000000000..0abcc07168 --- /dev/null +++ b/tests/components/improv_serial/common-usb_serial_jtag.yaml @@ -0,0 +1,8 @@ +wifi: + ssid: MySSID + password: password1 + +logger: + hardware_uart: USB_SERIAL_JTAG + +improv_serial: diff --git a/tests/components/improv_serial/test-uart0.esp32-ard.yaml b/tests/components/improv_serial/test-uart0.esp32-ard.yaml new file mode 100644 index 0000000000..ef8c799241 --- /dev/null +++ b/tests/components/improv_serial/test-uart0.esp32-ard.yaml @@ -0,0 +1 @@ +<<: !include common-uart0.yaml diff --git a/tests/components/improv_serial/test-uart0.esp32-c3-ard.yaml b/tests/components/improv_serial/test-uart0.esp32-c3-ard.yaml new file mode 100644 index 0000000000..ef8c799241 --- /dev/null +++ b/tests/components/improv_serial/test-uart0.esp32-c3-ard.yaml @@ -0,0 +1 @@ +<<: !include common-uart0.yaml diff --git a/tests/components/improv_serial/test-uart0.esp32-c3-idf.yaml b/tests/components/improv_serial/test-uart0.esp32-c3-idf.yaml new file mode 100644 index 0000000000..ef8c799241 --- /dev/null +++ b/tests/components/improv_serial/test-uart0.esp32-c3-idf.yaml @@ -0,0 +1 @@ +<<: !include common-uart0.yaml diff --git a/tests/components/improv_serial/test-uart0.esp32-idf.yaml b/tests/components/improv_serial/test-uart0.esp32-idf.yaml new file mode 100644 index 0000000000..ef8c799241 --- /dev/null +++ b/tests/components/improv_serial/test-uart0.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common-uart0.yaml diff --git a/tests/components/improv_serial/test-uart0.esp32-s2-ard.yaml b/tests/components/improv_serial/test-uart0.esp32-s2-ard.yaml new file mode 100644 index 0000000000..ef8c799241 --- /dev/null +++ b/tests/components/improv_serial/test-uart0.esp32-s2-ard.yaml @@ -0,0 +1 @@ +<<: !include common-uart0.yaml diff --git a/tests/components/improv_serial/test-uart0.esp32-s2-idf.yaml b/tests/components/improv_serial/test-uart0.esp32-s2-idf.yaml new file mode 100644 index 0000000000..ef8c799241 --- /dev/null +++ b/tests/components/improv_serial/test-uart0.esp32-s2-idf.yaml @@ -0,0 +1 @@ +<<: !include common-uart0.yaml diff --git a/tests/components/improv_serial/test-uart0.esp32-s3-ard.yaml b/tests/components/improv_serial/test-uart0.esp32-s3-ard.yaml new file mode 100644 index 0000000000..ef8c799241 --- /dev/null +++ b/tests/components/improv_serial/test-uart0.esp32-s3-ard.yaml @@ -0,0 +1 @@ +<<: !include common-uart0.yaml diff --git a/tests/components/improv_serial/test-uart0.esp32-s3-idf.yaml b/tests/components/improv_serial/test-uart0.esp32-s3-idf.yaml new file mode 100644 index 0000000000..ef8c799241 --- /dev/null +++ b/tests/components/improv_serial/test-uart0.esp32-s3-idf.yaml @@ -0,0 +1 @@ +<<: !include common-uart0.yaml diff --git a/tests/components/improv_serial/test-uart0.esp8266-ard.yaml b/tests/components/improv_serial/test-uart0.esp8266-ard.yaml new file mode 100644 index 0000000000..ef8c799241 --- /dev/null +++ b/tests/components/improv_serial/test-uart0.esp8266-ard.yaml @@ -0,0 +1 @@ +<<: !include common-uart0.yaml diff --git a/tests/components/improv_serial/test-uart0.rp2040-ard.yaml b/tests/components/improv_serial/test-uart0.rp2040-ard.yaml new file mode 100644 index 0000000000..ef8c799241 --- /dev/null +++ b/tests/components/improv_serial/test-uart0.rp2040-ard.yaml @@ -0,0 +1 @@ +<<: !include common-uart0.yaml diff --git a/tests/components/improv_serial/test-usb_cdc.esp32-c3-ard.yaml b/tests/components/improv_serial/test-usb_cdc.esp32-c3-ard.yaml new file mode 100644 index 0000000000..cfdaec9771 --- /dev/null +++ b/tests/components/improv_serial/test-usb_cdc.esp32-c3-ard.yaml @@ -0,0 +1 @@ +<<: !include common-usb_cdc.yaml diff --git a/tests/components/improv_serial/test-usb_cdc.esp32-s2-ard.yaml b/tests/components/improv_serial/test-usb_cdc.esp32-s2-ard.yaml new file mode 100644 index 0000000000..cfdaec9771 --- /dev/null +++ b/tests/components/improv_serial/test-usb_cdc.esp32-s2-ard.yaml @@ -0,0 +1 @@ +<<: !include common-usb_cdc.yaml diff --git a/tests/components/improv_serial/test-usb_cdc.esp32-s2-idf.yaml b/tests/components/improv_serial/test-usb_cdc.esp32-s2-idf.yaml new file mode 100644 index 0000000000..cfdaec9771 --- /dev/null +++ b/tests/components/improv_serial/test-usb_cdc.esp32-s2-idf.yaml @@ -0,0 +1 @@ +<<: !include common-usb_cdc.yaml diff --git a/tests/components/improv_serial/test-usb_cdc.esp32-s3-ard.yaml b/tests/components/improv_serial/test-usb_cdc.esp32-s3-ard.yaml new file mode 100644 index 0000000000..cfdaec9771 --- /dev/null +++ b/tests/components/improv_serial/test-usb_cdc.esp32-s3-ard.yaml @@ -0,0 +1 @@ +<<: !include common-usb_cdc.yaml diff --git a/tests/components/improv_serial/test-usb_cdc.rp2040-ard.yaml b/tests/components/improv_serial/test-usb_cdc.rp2040-ard.yaml new file mode 100644 index 0000000000..cfdaec9771 --- /dev/null +++ b/tests/components/improv_serial/test-usb_cdc.rp2040-ard.yaml @@ -0,0 +1 @@ +<<: !include common-usb_cdc.yaml diff --git a/tests/components/improv_serial/test-usb_serial_jtag.esp32-c3-idf.yaml b/tests/components/improv_serial/test-usb_serial_jtag.esp32-c3-idf.yaml new file mode 100644 index 0000000000..46a927ff10 --- /dev/null +++ b/tests/components/improv_serial/test-usb_serial_jtag.esp32-c3-idf.yaml @@ -0,0 +1 @@ +<<: !include common-usb_serial_jtag.yaml diff --git a/tests/components/improv_serial/test-usb_serial_jtag.esp32-s3-idf.yaml b/tests/components/improv_serial/test-usb_serial_jtag.esp32-s3-idf.yaml new file mode 100644 index 0000000000..46a927ff10 --- /dev/null +++ b/tests/components/improv_serial/test-usb_serial_jtag.esp32-s3-idf.yaml @@ -0,0 +1 @@ +<<: !include common-usb_serial_jtag.yaml diff --git a/tests/components/improv_serial/test.esp32-ard.yaml b/tests/components/improv_serial/test.esp32-ard.yaml deleted file mode 100644 index dade44d145..0000000000 --- a/tests/components/improv_serial/test.esp32-ard.yaml +++ /dev/null @@ -1 +0,0 @@ -<<: !include common.yaml diff --git a/tests/components/improv_serial/test.esp32-c3-ard.yaml b/tests/components/improv_serial/test.esp32-c3-ard.yaml deleted file mode 100644 index dade44d145..0000000000 --- a/tests/components/improv_serial/test.esp32-c3-ard.yaml +++ /dev/null @@ -1 +0,0 @@ -<<: !include common.yaml diff --git a/tests/components/improv_serial/test.esp32-c3-idf.yaml b/tests/components/improv_serial/test.esp32-c3-idf.yaml deleted file mode 100644 index dade44d145..0000000000 --- a/tests/components/improv_serial/test.esp32-c3-idf.yaml +++ /dev/null @@ -1 +0,0 @@ -<<: !include common.yaml diff --git a/tests/components/improv_serial/test.esp32-idf.yaml b/tests/components/improv_serial/test.esp32-idf.yaml deleted file mode 100644 index dade44d145..0000000000 --- a/tests/components/improv_serial/test.esp32-idf.yaml +++ /dev/null @@ -1 +0,0 @@ -<<: !include common.yaml diff --git a/tests/components/improv_serial/test.esp8266-ard.yaml b/tests/components/improv_serial/test.esp8266-ard.yaml deleted file mode 100644 index dade44d145..0000000000 --- a/tests/components/improv_serial/test.esp8266-ard.yaml +++ /dev/null @@ -1 +0,0 @@ -<<: !include common.yaml diff --git a/tests/components/improv_serial/test.rp2040-ard.yaml b/tests/components/improv_serial/test.rp2040-ard.yaml deleted file mode 100644 index dade44d145..0000000000 --- a/tests/components/improv_serial/test.rp2040-ard.yaml +++ /dev/null @@ -1 +0,0 @@ -<<: !include common.yaml diff --git a/tests/components/ltr390/test.esp32-ard.yaml b/tests/components/ltr390/test.esp32-ard.yaml index 9786c7dac3..bdfe349b77 100644 --- a/tests/components/ltr390/test.esp32-ard.yaml +++ b/tests/components/ltr390/test.esp32-ard.yaml @@ -18,3 +18,21 @@ sensor: window_correction_factor: 1.0 address: 0x53 update_interval: 60s + - platform: ltr390 + uv: + name: LTR390 UV + uv_index: + name: LTR390 UVI + light: + name: LTR390 Light + ambient_light: + name: LTR390 ALS + gain: + ambient_light: X9 + uv: X3 + resolution: + ambient_light: 18 + uv: 13 + window_correction_factor: 1.0 + address: 0x53 + update_interval: 60s diff --git a/tests/components/ltr390/test.esp8266-ard.yaml b/tests/components/ltr390/test.esp8266-ard.yaml index fee0f37ce1..149f46f9c8 100644 --- a/tests/components/ltr390/test.esp8266-ard.yaml +++ b/tests/components/ltr390/test.esp8266-ard.yaml @@ -13,7 +13,9 @@ sensor: name: LTR390 Light ambient_light: name: LTR390 ALS - gain: X3 + gain: + ambient_light: X9 + uv: X3 resolution: 18 window_correction_factor: 1.0 address: 0x53 diff --git a/tests/components/web_server/common.yaml b/tests/components/web_server/common.yaml index 94388726c3..eb768eeb91 100644 --- a/tests/components/web_server/common.yaml +++ b/tests/components/web_server/common.yaml @@ -2,6 +2,37 @@ wifi: ssid: MySSID password: password1 -web_server: - port: 8080 - version: 2 +binary_sensor: +cover: +fan: +light: +sensor: +switch: +button: +text_sensor: +climate: +number: +text: +select: +lock: +valve: +alarm_control_panel: +api: +time: + - platform: homeassistant + id: homeassistant_time +datetime: + - platform: template + id: my_datetime_date + type: date + optimistic: yes + - platform: template + id: my_datetime_time + type: time + optimistic: yes + - platform: template + id: my_datetime + type: datetime + optimistic: yes +event: +update: diff --git a/tests/components/web_server/common_v1.yaml b/tests/components/web_server/common_v1.yaml new file mode 100644 index 0000000000..bf5aab4ce6 --- /dev/null +++ b/tests/components/web_server/common_v1.yaml @@ -0,0 +1,5 @@ +<<: !include common.yaml + +web_server: + port: 8080 + version: 1 diff --git a/tests/components/web_server/common_v2.yaml b/tests/components/web_server/common_v2.yaml new file mode 100644 index 0000000000..564c43e553 --- /dev/null +++ b/tests/components/web_server/common_v2.yaml @@ -0,0 +1,5 @@ +<<: !include common.yaml + +web_server: + port: 8080 + version: 2 diff --git a/tests/components/web_server/test.esp32-ard.yaml b/tests/components/web_server/test.esp32-ard.yaml index dade44d145..7e6658e20e 100644 --- a/tests/components/web_server/test.esp32-ard.yaml +++ b/tests/components/web_server/test.esp32-ard.yaml @@ -1 +1 @@ -<<: !include common.yaml +<<: !include common_v2.yaml diff --git a/tests/components/web_server/test.esp32-c3-ard.yaml b/tests/components/web_server/test.esp32-c3-ard.yaml index dade44d145..7e6658e20e 100644 --- a/tests/components/web_server/test.esp32-c3-ard.yaml +++ b/tests/components/web_server/test.esp32-c3-ard.yaml @@ -1 +1 @@ -<<: !include common.yaml +<<: !include common_v2.yaml diff --git a/tests/components/web_server/test.esp32-c3-idf.yaml b/tests/components/web_server/test.esp32-c3-idf.yaml index dade44d145..7e6658e20e 100644 --- a/tests/components/web_server/test.esp32-c3-idf.yaml +++ b/tests/components/web_server/test.esp32-c3-idf.yaml @@ -1 +1 @@ -<<: !include common.yaml +<<: !include common_v2.yaml diff --git a/tests/components/web_server/test.esp32-idf.yaml b/tests/components/web_server/test.esp32-idf.yaml index dade44d145..7e6658e20e 100644 --- a/tests/components/web_server/test.esp32-idf.yaml +++ b/tests/components/web_server/test.esp32-idf.yaml @@ -1 +1 @@ -<<: !include common.yaml +<<: !include common_v2.yaml diff --git a/tests/components/web_server/test.esp8266-ard.yaml b/tests/components/web_server/test.esp8266-ard.yaml index dade44d145..7e6658e20e 100644 --- a/tests/components/web_server/test.esp8266-ard.yaml +++ b/tests/components/web_server/test.esp8266-ard.yaml @@ -1 +1 @@ -<<: !include common.yaml +<<: !include common_v2.yaml diff --git a/tests/components/web_server/test_v1.esp32-ard.yaml b/tests/components/web_server/test_v1.esp32-ard.yaml new file mode 100644 index 0000000000..389a930284 --- /dev/null +++ b/tests/components/web_server/test_v1.esp32-ard.yaml @@ -0,0 +1 @@ +<<: !include common_v1.yaml