diff --git a/CODEOWNERS b/CODEOWNERS index 429c9d2ab7..693d2dc30f 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -63,7 +63,10 @@ esphome/components/bme280_base/* @esphome/core esphome/components/bme280_spi/* @apbodrov esphome/components/bme680_bsec/* @trvrnrth esphome/components/bmi160/* @flaviut -esphome/components/bmp3xx/* @martgras +esphome/components/bmp3xx/* @latonita +esphome/components/bmp3xx_base/* @latonita @martgras +esphome/components/bmp3xx_i2c/* @latonita +esphome/components/bmp3xx_spi/* @latonita esphome/components/bmp581/* @kahrendt esphome/components/bp1658cj/* @Cossid esphome/components/bp5758d/* @Cossid @@ -242,7 +245,7 @@ esphome/components/mpl3115a2/* @kbickar esphome/components/mpu6886/* @fabaff esphome/components/ms8607/* @e28eta esphome/components/network/* @esphome/core -esphome/components/nextion/* @senexcrenshaw +esphome/components/nextion/* @edwardtfn @senexcrenshaw esphome/components/nextion/binary_sensor/* @senexcrenshaw esphome/components/nextion/sensor/* @senexcrenshaw esphome/components/nextion/switch/* @senexcrenshaw diff --git a/esphome/components/bmp3xx/sensor.py b/esphome/components/bmp3xx/sensor.py index 6f90173c7b..89753768c3 100644 --- a/esphome/components/bmp3xx/sensor.py +++ b/esphome/components/bmp3xx/sensor.py @@ -1,102 +1,7 @@ -import esphome.codegen as cg import esphome.config_validation as cv -from esphome.components import i2c, sensor -from esphome.const import ( - CONF_ID, - CONF_IIR_FILTER, - CONF_OVERSAMPLING, - CONF_PRESSURE, - CONF_TEMPERATURE, - DEVICE_CLASS_PRESSURE, - DEVICE_CLASS_TEMPERATURE, - STATE_CLASS_MEASUREMENT, - UNIT_CELSIUS, - UNIT_HECTOPASCAL, + +CODEOWNERS = ["@latonita"] + +CONFIG_SCHEMA = CONFIG_SCHEMA = cv.invalid( + "The bmp3xx sensor component has been renamed to bmp3xx_i2c." ) - -CODEOWNERS = ["@martgras"] -DEPENDENCIES = ["i2c"] - -bmp3xx_ns = cg.esphome_ns.namespace("bmp3xx") -Oversampling = bmp3xx_ns.enum("Oversampling") -OVERSAMPLING_OPTIONS = { - "NONE": Oversampling.OVERSAMPLING_NONE, - "2X": Oversampling.OVERSAMPLING_X2, - "4X": Oversampling.OVERSAMPLING_X4, - "8X": Oversampling.OVERSAMPLING_X8, - "16X": Oversampling.OVERSAMPLING_X16, - "32X": Oversampling.OVERSAMPLING_X32, -} - -IIRFilter = bmp3xx_ns.enum("IIRFilter") -IIR_FILTER_OPTIONS = { - "OFF": IIRFilter.IIR_FILTER_OFF, - "2X": IIRFilter.IIR_FILTER_2, - "4X": IIRFilter.IIR_FILTER_4, - "8X": IIRFilter.IIR_FILTER_8, - "16X": IIRFilter.IIR_FILTER_16, - "32X": IIRFilter.IIR_FILTER_32, - "64X": IIRFilter.IIR_FILTER_64, - "128X": IIRFilter.IIR_FILTER_128, -} - -BMP3XXComponent = bmp3xx_ns.class_( - "BMP3XXComponent", cg.PollingComponent, i2c.I2CDevice -) - -CONFIG_SCHEMA = ( - cv.Schema( - { - cv.GenerateID(): cv.declare_id(BMP3XXComponent), - cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( - unit_of_measurement=UNIT_CELSIUS, - accuracy_decimals=1, - device_class=DEVICE_CLASS_TEMPERATURE, - state_class=STATE_CLASS_MEASUREMENT, - ).extend( - { - cv.Optional(CONF_OVERSAMPLING, default="2X"): cv.enum( - OVERSAMPLING_OPTIONS, upper=True - ), - } - ), - cv.Optional(CONF_PRESSURE): sensor.sensor_schema( - unit_of_measurement=UNIT_HECTOPASCAL, - accuracy_decimals=1, - device_class=DEVICE_CLASS_PRESSURE, - state_class=STATE_CLASS_MEASUREMENT, - ).extend( - { - cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum( - OVERSAMPLING_OPTIONS, upper=True - ), - } - ), - cv.Optional(CONF_IIR_FILTER, default="OFF"): cv.enum( - IIR_FILTER_OPTIONS, upper=True - ), - } - ) - .extend(cv.polling_component_schema("60s")) - .extend(i2c.i2c_device_schema(0x77)) -) - - -async def to_code(config): - var = cg.new_Pvariable(config[CONF_ID]) - await cg.register_component(var, config) - await i2c.register_i2c_device(var, config) - cg.add(var.set_iir_filter_config(config[CONF_IIR_FILTER])) - if temperature_config := config.get(CONF_TEMPERATURE): - sens = await sensor.new_sensor(temperature_config) - cg.add(var.set_temperature_sensor(sens)) - cg.add( - var.set_temperature_oversampling_config( - temperature_config[CONF_OVERSAMPLING] - ) - ) - - if pressure_config := config.get(CONF_PRESSURE): - sens = await sensor.new_sensor(pressure_config) - cg.add(var.set_pressure_sensor(sens)) - cg.add(var.set_pressure_oversampling_config(pressure_config[CONF_OVERSAMPLING])) diff --git a/esphome/components/bmp3xx_base/__init__.py b/esphome/components/bmp3xx_base/__init__.py new file mode 100644 index 0000000000..589d170907 --- /dev/null +++ b/esphome/components/bmp3xx_base/__init__.py @@ -0,0 +1,95 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import sensor +from esphome.const import ( + CONF_ID, + CONF_IIR_FILTER, + CONF_OVERSAMPLING, + CONF_PRESSURE, + CONF_TEMPERATURE, + DEVICE_CLASS_PRESSURE, + DEVICE_CLASS_TEMPERATURE, + STATE_CLASS_MEASUREMENT, + UNIT_CELSIUS, + UNIT_HECTOPASCAL, +) + +CODEOWNERS = ["@martgras", "@latonita"] + +bmp3xx_ns = cg.esphome_ns.namespace("bmp3xx_base") +Oversampling = bmp3xx_ns.enum("Oversampling") +OVERSAMPLING_OPTIONS = { + "NONE": Oversampling.OVERSAMPLING_NONE, + "2X": Oversampling.OVERSAMPLING_X2, + "4X": Oversampling.OVERSAMPLING_X4, + "8X": Oversampling.OVERSAMPLING_X8, + "16X": Oversampling.OVERSAMPLING_X16, + "32X": Oversampling.OVERSAMPLING_X32, +} + +IIRFilter = bmp3xx_ns.enum("IIRFilter") +IIR_FILTER_OPTIONS = { + "OFF": IIRFilter.IIR_FILTER_OFF, + "2X": IIRFilter.IIR_FILTER_2, + "4X": IIRFilter.IIR_FILTER_4, + "8X": IIRFilter.IIR_FILTER_8, + "16X": IIRFilter.IIR_FILTER_16, + "32X": IIRFilter.IIR_FILTER_32, + "64X": IIRFilter.IIR_FILTER_64, + "128X": IIRFilter.IIR_FILTER_128, +} + + +CONFIG_SCHEMA_BASE = cv.Schema( + { + cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=1, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + ).extend( + { + cv.Optional(CONF_OVERSAMPLING, default="2X"): cv.enum( + OVERSAMPLING_OPTIONS, upper=True + ), + } + ), + cv.Optional(CONF_PRESSURE): sensor.sensor_schema( + unit_of_measurement=UNIT_HECTOPASCAL, + accuracy_decimals=1, + device_class=DEVICE_CLASS_PRESSURE, + state_class=STATE_CLASS_MEASUREMENT, + ).extend( + { + cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum( + OVERSAMPLING_OPTIONS, upper=True + ), + } + ), + cv.Optional(CONF_IIR_FILTER, default="OFF"): cv.enum( + IIR_FILTER_OPTIONS, upper=True + ), + } +).extend(cv.polling_component_schema("60s")) + + +async def to_code_base(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + + cg.add(var.set_iir_filter_config(config[CONF_IIR_FILTER])) + if temperature_config := config.get(CONF_TEMPERATURE): + sens = await sensor.new_sensor(temperature_config) + cg.add(var.set_temperature_sensor(sens)) + cg.add( + var.set_temperature_oversampling_config( + temperature_config[CONF_OVERSAMPLING] + ) + ) + + if pressure_config := config.get(CONF_PRESSURE): + sens = await sensor.new_sensor(pressure_config) + cg.add(var.set_pressure_sensor(sens)) + cg.add(var.set_pressure_oversampling_config(pressure_config[CONF_OVERSAMPLING])) + + return var diff --git a/esphome/components/bmp3xx/bmp3xx.cpp b/esphome/components/bmp3xx_base/bmp3xx_base.cpp similarity index 99% rename from esphome/components/bmp3xx/bmp3xx.cpp rename to esphome/components/bmp3xx_base/bmp3xx_base.cpp index de28fd76ff..75b6812f81 100644 --- a/esphome/components/bmp3xx/bmp3xx.cpp +++ b/esphome/components/bmp3xx_base/bmp3xx_base.cpp @@ -5,13 +5,13 @@ http://github.com/MartinL1/BMP388_DEV */ -#include "bmp3xx.h" +#include "bmp3xx_base.h" #include "esphome/core/log.h" #include "esphome/core/hal.h" #include namespace esphome { -namespace bmp3xx { +namespace bmp3xx_base { static const char *const TAG = "bmp3xx.sensor"; @@ -150,7 +150,6 @@ void BMP3XXComponent::setup() { void BMP3XXComponent::dump_config() { ESP_LOGCONFIG(TAG, "BMP3XX:"); ESP_LOGCONFIG(TAG, " Type: %s (0x%X)", LOG_STR_ARG(chip_type_to_str(this->chip_id_.reg)), this->chip_id_.reg); - LOG_I2C_DEVICE(this); switch (this->error_code_) { case NONE: break; @@ -386,5 +385,5 @@ float BMP3XXComponent::bmp388_compensate_pressure_(float uncomp_press, float t_l return partial_out1 + partial_out2 + partial_data4; } -} // namespace bmp3xx +} // namespace bmp3xx_base } // namespace esphome diff --git a/esphome/components/bmp3xx/bmp3xx.h b/esphome/components/bmp3xx_base/bmp3xx_base.h similarity index 94% rename from esphome/components/bmp3xx/bmp3xx.h rename to esphome/components/bmp3xx_base/bmp3xx_base.h index d3b15f601d..50f92e04c1 100644 --- a/esphome/components/bmp3xx/bmp3xx.h +++ b/esphome/components/bmp3xx_base/bmp3xx_base.h @@ -9,10 +9,9 @@ #include "esphome/core/component.h" #include "esphome/components/sensor/sensor.h" -#include "esphome/components/i2c/i2c.h" namespace esphome { -namespace bmp3xx { +namespace bmp3xx_base { static const uint8_t BMP388_ID = 0x50; // The BMP388 device ID static const uint8_t BMP390_ID = 0x60; // The BMP390 device ID @@ -69,8 +68,8 @@ enum IIRFilter { IIR_FILTER_128 = 0x07 }; -/// This class implements support for the BMP3XX Temperature+Pressure i2c sensor. -class BMP3XXComponent : public PollingComponent, public i2c::I2CDevice { +/// This class implements support for the BMP3XX Temperature+Pressure sensor. +class BMP3XXComponent : public PollingComponent { public: void setup() override; void dump_config() override; @@ -231,7 +230,13 @@ class BMP3XXComponent : public PollingComponent, public i2c::I2CDevice { float bmp388_compensate_temperature_(float uncomp_temp); // Bosch pressure compensation function float bmp388_compensate_pressure_(float uncomp_press, float t_lin); + + // interface specific functions + virtual bool read_byte(uint8_t a_register, uint8_t *data) = 0; + virtual bool write_byte(uint8_t a_register, uint8_t data) = 0; + virtual bool read_bytes(uint8_t a_register, uint8_t *data, size_t len) = 0; + virtual bool write_bytes(uint8_t a_register, uint8_t *data, size_t len) = 0; }; -} // namespace bmp3xx +} // namespace bmp3xx_base } // namespace esphome diff --git a/esphome/components/bmp3xx_i2c/__init__.py b/esphome/components/bmp3xx_i2c/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/bmp3xx_i2c/bmp3xx_i2c.cpp b/esphome/components/bmp3xx_i2c/bmp3xx_i2c.cpp new file mode 100644 index 0000000000..7531090185 --- /dev/null +++ b/esphome/components/bmp3xx_i2c/bmp3xx_i2c.cpp @@ -0,0 +1,29 @@ +#include "esphome/components/i2c/i2c.h" +#include "bmp3xx_i2c.h" +#include + +namespace esphome { +namespace bmp3xx_i2c { + +static const char *const TAG = "bmp3xx_i2c.sensor"; + +bool BMP3XXI2CComponent::read_byte(uint8_t a_register, uint8_t *data) { + return I2CDevice::read_byte(a_register, data); +}; +bool BMP3XXI2CComponent::write_byte(uint8_t a_register, uint8_t data) { + return I2CDevice::write_byte(a_register, data); +}; +bool BMP3XXI2CComponent::read_bytes(uint8_t a_register, uint8_t *data, size_t len) { + return I2CDevice::read_bytes(a_register, data, len); +}; +bool BMP3XXI2CComponent::write_bytes(uint8_t a_register, uint8_t *data, size_t len) { + return I2CDevice::write_bytes(a_register, data, len); +}; + +void BMP3XXI2CComponent::dump_config() { + LOG_I2C_DEVICE(this); + BMP3XXComponent::dump_config(); +} + +} // namespace bmp3xx_i2c +} // namespace esphome diff --git a/esphome/components/bmp3xx_i2c/bmp3xx_i2c.h b/esphome/components/bmp3xx_i2c/bmp3xx_i2c.h new file mode 100644 index 0000000000..d8b95cf843 --- /dev/null +++ b/esphome/components/bmp3xx_i2c/bmp3xx_i2c.h @@ -0,0 +1,17 @@ +#pragma once +#include "esphome/components/i2c/i2c.h" +#include "esphome/components/bmp3xx_base/bmp3xx_base.h" + +namespace esphome { +namespace bmp3xx_i2c { + +class BMP3XXI2CComponent : public bmp3xx_base::BMP3XXComponent, public i2c::I2CDevice { + bool read_byte(uint8_t a_register, uint8_t *data) override; + bool write_byte(uint8_t a_register, uint8_t data) override; + bool read_bytes(uint8_t a_register, uint8_t *data, size_t len) override; + bool write_bytes(uint8_t a_register, uint8_t *data, size_t len) override; + void dump_config() override; +}; + +} // namespace bmp3xx_i2c +} // namespace esphome diff --git a/esphome/components/bmp3xx_i2c/sensor.py b/esphome/components/bmp3xx_i2c/sensor.py new file mode 100644 index 0000000000..ae59d29e89 --- /dev/null +++ b/esphome/components/bmp3xx_i2c/sensor.py @@ -0,0 +1,22 @@ +import esphome.codegen as cg +from esphome.components import i2c +from ..bmp3xx_base import to_code_base, cv, CONFIG_SCHEMA_BASE + +AUTO_LOAD = ["bmp3xx_base"] +CODEOWNERS = ["@latonita"] +DEPENDENCIES = ["i2c"] + +bmp3xx_ns = cg.esphome_ns.namespace("bmp3xx_i2c") + +BMP3XXI2CComponent = bmp3xx_ns.class_( + "BMP3XXI2CComponent", cg.PollingComponent, i2c.I2CDevice +) + +CONFIG_SCHEMA = CONFIG_SCHEMA_BASE.extend( + i2c.i2c_device_schema(default_address=0x77) +).extend({cv.GenerateID(): cv.declare_id(BMP3XXI2CComponent)}) + + +async def to_code(config): + var = await to_code_base(config) + await i2c.register_i2c_device(var, config) diff --git a/esphome/components/bmp3xx_spi/__init__.py b/esphome/components/bmp3xx_spi/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/bmp3xx_spi/bmp3xx_spi.cpp b/esphome/components/bmp3xx_spi/bmp3xx_spi.cpp new file mode 100644 index 0000000000..2084530125 --- /dev/null +++ b/esphome/components/bmp3xx_spi/bmp3xx_spi.cpp @@ -0,0 +1,57 @@ +#include "bmp3xx_spi.h" +#include + +namespace esphome { +namespace bmp3xx_spi { + +static const char *const TAG = "bmp3xx_spi.sensor"; + +uint8_t set_bit(uint8_t num, int position) { + int mask = 1 << position; + return num | mask; +} + +uint8_t clear_bit(uint8_t num, int position) { + int mask = 1 << position; + return num & ~mask; +} + +void BMP3XXSPIComponent::setup() { + this->spi_setup(); + BMP3XXComponent::setup(); +} + +bool BMP3XXSPIComponent::read_byte(uint8_t a_register, uint8_t *data) { + this->enable(); + this->transfer_byte(set_bit(a_register, 7)); + *data = this->transfer_byte(0); + this->disable(); + return true; +} + +bool BMP3XXSPIComponent::write_byte(uint8_t a_register, uint8_t data) { + this->enable(); + this->transfer_byte(clear_bit(a_register, 7)); + this->transfer_byte(data); + this->disable(); + return true; +} + +bool BMP3XXSPIComponent::read_bytes(uint8_t a_register, uint8_t *data, size_t len) { + this->enable(); + this->transfer_byte(set_bit(a_register, 7)); + this->read_array(data, len); + this->disable(); + return true; +} + +bool BMP3XXSPIComponent::write_bytes(uint8_t a_register, uint8_t *data, size_t len) { + this->enable(); + this->transfer_byte(clear_bit(a_register, 7)); + this->transfer_array(data, len); + this->disable(); + return true; +} + +} // namespace bmp3xx_spi +} // namespace esphome diff --git a/esphome/components/bmp3xx_spi/bmp3xx_spi.h b/esphome/components/bmp3xx_spi/bmp3xx_spi.h new file mode 100644 index 0000000000..2183994abe --- /dev/null +++ b/esphome/components/bmp3xx_spi/bmp3xx_spi.h @@ -0,0 +1,19 @@ +#pragma once +#include "esphome/components/bmp3xx_base/bmp3xx_base.h" +#include "esphome/components/spi/spi.h" + +namespace esphome { +namespace bmp3xx_spi { + +class BMP3XXSPIComponent : public bmp3xx_base::BMP3XXComponent, + public spi::SPIDevice { + void setup() override; + bool read_byte(uint8_t a_register, uint8_t *data) override; + bool write_byte(uint8_t a_register, uint8_t data) override; + bool read_bytes(uint8_t a_register, uint8_t *data, size_t len) override; + bool write_bytes(uint8_t a_register, uint8_t *data, size_t len) override; +}; + +} // namespace bmp3xx_spi +} // namespace esphome diff --git a/esphome/components/bmp3xx_spi/sensor.py b/esphome/components/bmp3xx_spi/sensor.py new file mode 100644 index 0000000000..3d1acd3c1b --- /dev/null +++ b/esphome/components/bmp3xx_spi/sensor.py @@ -0,0 +1,22 @@ +import esphome.codegen as cg +from esphome.components import spi +from ..bmp3xx_base import to_code_base, cv, CONFIG_SCHEMA_BASE + +AUTO_LOAD = ["bmp3xx_base"] +CODEOWNERS = ["@latonita"] +DEPENDENCIES = ["spi"] + +bmp3xx_ns = cg.esphome_ns.namespace("bmp3xx_spi") + +BMP3XXSPIComponent = bmp3xx_ns.class_( + "BMP3XXSPIComponent", cg.PollingComponent, spi.SPIDevice +) + +CONFIG_SCHEMA = CONFIG_SCHEMA_BASE.extend(spi.spi_device_schema()).extend( + {cv.GenerateID(): cv.declare_id(BMP3XXSPIComponent)} +) + + +async def to_code(config): + var = await to_code_base(config) + await spi.register_spi_device(var, config) diff --git a/esphome/components/nextion/display.py b/esphome/components/nextion/display.py index 6487c12f36..ce45d25e7b 100644 --- a/esphome/components/nextion/display.py +++ b/esphome/components/nextion/display.py @@ -25,7 +25,7 @@ from .base_component import ( CONF_EXIT_REPARSE_ON_START, ) -CODEOWNERS = ["@senexcrenshaw"] +CODEOWNERS = ["@senexcrenshaw", "@edwardtfn"] DEPENDENCIES = ["uart"] AUTO_LOAD = ["binary_sensor", "switch", "sensor", "text_sensor"] diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index 7938af0ea5..6435e2b4e2 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -1013,7 +1013,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe */ bool upload_tft(uint32_t baud_rate = 0, bool exit_reparse = true); -#endif +#endif // USE_NEXTION_TFT_UPLOAD void dump_config() override; @@ -1142,6 +1142,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * Sends commands ignoring of the Nextion has been setup. */ bool ignore_is_setup_ = false; + bool nextion_reports_is_setup_ = false; uint8_t nextion_event_; @@ -1182,7 +1183,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe WiFiClient *wifi_client_{nullptr}; BearSSL::WiFiClientSecure *wifi_client_secure_{nullptr}; WiFiClient *get_wifi_client_(); -#endif +#endif // USE_ESP8266 std::string tft_url_; uint32_t content_length_ = 0; int tft_size_ = 0; @@ -1193,11 +1194,21 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe /** * will request chunk_size chunks from the web server * and send each to the nextion - * @param HTTPClient http HTTP client handler. + * @param HTTPClient http_client HTTP client handler. * @param int range_start Position of next byte to transfer. * @return position of last byte transferred, -1 for failure. */ int upload_by_chunks_(HTTPClient &http_client, uint32_t &range_start); +#elif defined(USE_ESP_IDF) + /** + * will request 4096 bytes chunks from the web server + * and send each to Nextion + * @param esp_http_client_handle_t http_client HTTP client handler. + * @param int range_start Position of next byte to transfer. + * @return position of last byte transferred, -1 for failure. + */ + int upload_by_chunks_(esp_http_client_handle_t http_client, uint32_t &range_start); +#endif // ARDUINO vs USE_ESP_IDF /** * Ends the upload process, restart Nextion and, if successful, @@ -1207,24 +1218,6 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe */ bool upload_end_(bool successful); -#elif defined(USE_ESP_IDF) - /** - * will request 4096 bytes chunks from the web server - * and send each to Nextion - * @param std::string url Full url for download. - * @param int range_start Position of next byte to transfer. - * @return position of last byte transferred, -1 for failure. - */ - int upload_range(const std::string &url, int range_start); - - /** - * Ends the upload process, restart Nextion and, if successful, - * restarts ESP - * @param bool url successful True: Transfer completed successfuly, False: Transfer failed. - * @return bool True: Transfer completed successfuly, False: Transfer failed. - */ - bool upload_end(bool successful); -#endif // ARDUINO vs USE_ESP_IDF /** * Returns the ESP Free Heap memory. This is framework independent. * @return Free Heap in bytes. @@ -1260,7 +1253,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe #ifdef NEXTION_PROTOCOL_LOG void print_queue_members_(); -#endif +#endif // NEXTION_PROTOCOL_LOG void reset_(bool reset_nextion = true); std::string command_data_; diff --git a/esphome/components/nextion/nextion_upload_idf.cpp b/esphome/components/nextion/nextion_upload_idf.cpp index 163b497d3b..448b6fc0ff 100644 --- a/esphome/components/nextion/nextion_upload_idf.cpp +++ b/esphome/components/nextion/nextion_upload_idf.cpp @@ -1,17 +1,16 @@ #include "nextion.h" -#ifdef USE_ESP_IDF #ifdef USE_NEXTION_TFT_UPLOAD +#ifdef USE_ESP_IDF #include "esphome/core/application.h" #include "esphome/core/defines.h" #include "esphome/core/util.h" #include "esphome/core/log.h" #include "esphome/components/network/util.h" - +#include #include #include -#include namespace esphome { namespace nextion { @@ -20,153 +19,147 @@ static const char *const TAG = "nextion.upload.idf"; // Followed guide // https://unofficialnextion.com/t/nextion-upload-protocol-v1-2-the-fast-one/1044/2 -int Nextion::upload_range(const std::string &url, int range_start) { - ESP_LOGVV(TAG, "url: %s", url.c_str()); - uint range_size = this->tft_size_ - range_start; - ESP_LOGVV(TAG, "tft_size_: %i", this->tft_size_); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - int range_end = (range_start == 0) ? std::min(this->tft_size_, 16383) : this->tft_size_; +int Nextion::upload_by_chunks_(esp_http_client_handle_t http_client, uint32_t &range_start) { + uint32_t range_size = this->tft_size_ - range_start; + ESP_LOGV(TAG, "Free heap: %" PRIu32, esp_get_free_heap_size()); + uint32_t range_end = ((upload_first_chunk_sent_ or this->tft_size_ < 4096) ? this->tft_size_ : 4096) - 1; + ESP_LOGD(TAG, "Range start: %" PRIu32, range_start); if (range_size <= 0 or range_end <= range_start) { + ESP_LOGD(TAG, "Range end: %" PRIu32, range_end); + ESP_LOGD(TAG, "Range size: %" PRIu32, range_size); ESP_LOGE(TAG, "Invalid range"); - ESP_LOGD(TAG, "Range start: %i", range_start); - ESP_LOGD(TAG, "Range end: %i", range_end); - ESP_LOGD(TAG, "Range size: %i", range_size); return -1; } - esp_http_client_config_t config = { - .url = url.c_str(), - .cert_pem = nullptr, - .disable_auto_redirect = false, - .max_redirection_count = 10, - }; - esp_http_client_handle_t client = esp_http_client_init(&config); - - char range_header[64]; - sprintf(range_header, "bytes=%d-%d", range_start, range_end); + char range_header[32]; + sprintf(range_header, "bytes=%" PRIu32 "-%" PRIu32, range_start, range_end); ESP_LOGV(TAG, "Requesting range: %s", range_header); - esp_http_client_set_header(client, "Range", range_header); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - - ESP_LOGV(TAG, "Opening http connetion"); + esp_http_client_set_header(http_client, "Range", range_header); + ESP_LOGV(TAG, "Opening HTTP connetion"); esp_err_t err; - if ((err = esp_http_client_open(client, 0)) != ESP_OK) { + if ((err = esp_http_client_open(http_client, 0)) != ESP_OK) { ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err)); - esp_http_client_cleanup(client); return -1; } ESP_LOGV(TAG, "Fetch content length"); - int content_length = esp_http_client_fetch_headers(client); - ESP_LOGV(TAG, "content_length = %d", content_length); - if (content_length <= 0) { - ESP_LOGE(TAG, "Failed to get content length: %d", content_length); - esp_http_client_cleanup(client); + const int chunk_size = esp_http_client_fetch_headers(http_client); + ESP_LOGV(TAG, "content_length = %d", chunk_size); + if (chunk_size <= 0) { + ESP_LOGE(TAG, "Failed to get chunk's content length: %d", chunk_size); return -1; } - int total_read_len = 0, read_len; - - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - ESP_LOGV(TAG, "Allocate buffer"); - uint8_t *buffer = new uint8_t[4096]; - std::string recv_string; - if (buffer == nullptr) { - ESP_LOGE(TAG, "Failed to allocate memory for buffer"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - } else { - ESP_LOGV(TAG, "Memory for buffer allocated successfully"); - - while (true) { - App.feed_wdt(); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - int read_len = esp_http_client_read(client, reinterpret_cast(buffer), 4096); - ESP_LOGVV(TAG, "Read %d bytes from HTTP client, writing to UART", read_len); - if (read_len > 0) { - this->write_array(buffer, read_len); - ESP_LOGVV(TAG, "Write to UART successful"); - this->recv_ret_string_(recv_string, 5000, true); - this->content_length_ -= read_len; - ESP_LOGD(TAG, "Uploaded %0.2f %%, remaining %d bytes, heap is %" PRIu32 " bytes", - 100.0 * (this->tft_size_ - this->content_length_) / this->tft_size_, this->content_length_, - esp_get_free_heap_size()); - - if (recv_string[0] == 0x08 && recv_string.size() == 5) { // handle partial upload request - ESP_LOGD( - TAG, "recv_string [%s]", - format_hex_pretty(reinterpret_cast(recv_string.data()), recv_string.size()).c_str()); - uint32_t result = 0; - for (int j = 0; j < 4; ++j) { - result += static_cast(recv_string[j + 1]) << (8 * j); - } - if (result > 0) { - ESP_LOGI(TAG, "Nextion reported new range %" PRIu32, result); - this->content_length_ = this->tft_size_ - result; - // Deallocate the buffer when done - ESP_LOGV(TAG, "Deallocate buffer"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - delete[] buffer; - ESP_LOGVV(TAG, "Memory for buffer deallocated"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - ESP_LOGV(TAG, "Close http client"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - esp_http_client_close(client); - esp_http_client_cleanup(client); - ESP_LOGVV(TAG, "Client closed"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - return result; - } - } else if (recv_string[0] != 0x05) { // 0x05 == "ok" - ESP_LOGE( - TAG, "Invalid response from Nextion: [%s]", - format_hex_pretty(reinterpret_cast(recv_string.data()), recv_string.size()).c_str()); - ESP_LOGV(TAG, "Deallocate buffer"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - delete[] buffer; - ESP_LOGVV(TAG, "Memory for buffer deallocated"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - ESP_LOGV(TAG, "Close http client"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - esp_http_client_close(client); - esp_http_client_cleanup(client); - ESP_LOGVV(TAG, "Client closed"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - return -1; - } - - recv_string.clear(); - } else if (read_len == 0) { - ESP_LOGV(TAG, "End of HTTP response reached"); - break; // Exit the loop if there is no more data to read - } else { - ESP_LOGE(TAG, "Failed to read from HTTP client, error code: %d", read_len); - break; // Exit the loop on error - } - } - - // Deallocate the buffer when done - ESP_LOGV(TAG, "Deallocate buffer"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - delete[] buffer; - ESP_LOGVV(TAG, "Memory for buffer deallocated"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); + // Allocate the buffer dynamically + ExternalRAMAllocator allocator(ExternalRAMAllocator::ALLOW_FAILURE); + uint8_t *buffer = allocator.allocate(4096); + if (!buffer) { + ESP_LOGE(TAG, "Failed to allocate upload buffer"); + return -1; } - ESP_LOGV(TAG, "Close http client"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - esp_http_client_close(client); - esp_http_client_cleanup(client); - ESP_LOGVV(TAG, "Client closed"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); + + std::string recv_string; + while (true) { + App.feed_wdt(); + const uint16_t buffer_size = + this->content_length_ < 4096 ? this->content_length_ : 4096; // Limits buffer to the remaining data + ESP_LOGV(TAG, "Fetching %" PRIu16 " bytes from HTTP", buffer_size); + uint16_t read_len = 0; + int partial_read_len = 0; + uint8_t retries = 0; + // Attempt to read the chunk with retries. + while (retries < 5 && read_len < buffer_size) { + partial_read_len = + esp_http_client_read(http_client, reinterpret_cast(buffer) + read_len, buffer_size - read_len); + if (partial_read_len > 0) { + read_len += partial_read_len; // Accumulate the total read length. + // Reset retries on successful read. + retries = 0; + } else { + // If no data was read, increment retries. + retries++; + vTaskDelay(pdMS_TO_TICKS(2)); // NOLINT + } + App.feed_wdt(); // Feed the watchdog timer. + } + if (read_len != buffer_size) { + // Did not receive the full package within the timeout period + ESP_LOGE(TAG, "Failed to read full package, received only %" PRIu16 " of %" PRIu16 " bytes", read_len, + buffer_size); + // Deallocate buffer + allocator.deallocate(buffer, 4096); + buffer = nullptr; + return -1; + } + ESP_LOGV(TAG, "%d bytes fetched, writing it to UART", read_len); + if (read_len > 0) { + recv_string.clear(); + this->write_array(buffer, buffer_size); + App.feed_wdt(); + this->recv_ret_string_(recv_string, upload_first_chunk_sent_ ? 500 : 5000, true); + this->content_length_ -= read_len; + const float upload_percentage = 100.0f * (this->tft_size_ - this->content_length_) / this->tft_size_; +#ifdef USE_PSRAM + ESP_LOGD( + TAG, + "Uploaded %0.2f%%, remaining %" PRIu32 " bytes, free heap: %" PRIu32 " (DRAM) + %" PRIu32 " (PSRAM) bytes", + upload_percentage, this->content_length_, static_cast(heap_caps_get_free_size(MALLOC_CAP_INTERNAL)), + static_cast(heap_caps_get_free_size(MALLOC_CAP_SPIRAM))); +#else + ESP_LOGD(TAG, "Uploaded %0.2f%%, remaining %" PRIu32 " bytes, free heap: %" PRIu32 " bytes", upload_percentage, + this->content_length_, static_cast(esp_get_free_heap_size())); +#endif + upload_first_chunk_sent_ = true; + if (recv_string[0] == 0x08 && recv_string.size() == 5) { // handle partial upload request + ESP_LOGD(TAG, "recv_string [%s]", + format_hex_pretty(reinterpret_cast(recv_string.data()), recv_string.size()).c_str()); + uint32_t result = 0; + for (int j = 0; j < 4; ++j) { + result += static_cast(recv_string[j + 1]) << (8 * j); + } + if (result > 0) { + ESP_LOGI(TAG, "Nextion reported new range %" PRIu32, result); + this->content_length_ = this->tft_size_ - result; + range_start = result; + } else { + range_start = range_end + 1; + } + // Deallocate buffer + allocator.deallocate(buffer, 4096); + buffer = nullptr; + return range_end + 1; + } else if (recv_string[0] != 0x05 and recv_string[0] != 0x08) { // 0x05 == "ok" + ESP_LOGE(TAG, "Invalid response from Nextion: [%s]", + format_hex_pretty(reinterpret_cast(recv_string.data()), recv_string.size()).c_str()); + // Deallocate buffer + allocator.deallocate(buffer, 4096); + buffer = nullptr; + return -1; + } + + recv_string.clear(); + } else if (read_len == 0) { + ESP_LOGV(TAG, "End of HTTP response reached"); + break; // Exit the loop if there is no more data to read + } else { + ESP_LOGE(TAG, "Failed to read from HTTP client, error code: %" PRIu16, read_len); + break; // Exit the loop on error + } + } + range_start = range_end + 1; + // Deallocate buffer + allocator.deallocate(buffer, 4096); + buffer = nullptr; return range_end + 1; } bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { ESP_LOGD(TAG, "Nextion TFT upload requested"); ESP_LOGD(TAG, "Exit reparse: %s", YESNO(exit_reparse)); - ESP_LOGD(TAG, "url: %s", this->tft_url_.c_str()); + ESP_LOGD(TAG, "URL: %s", this->tft_url_.c_str()); if (this->is_updating_) { - ESP_LOGW(TAG, "Currently updating"); + ESP_LOGW(TAG, "Currently uploading"); return false; } @@ -195,8 +188,8 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { ESP_LOGD(TAG, "Baud rate: %" PRIu32, baud_rate); // Define the configuration for the HTTP client - ESP_LOGV(TAG, "Establishing connection to HTTP server"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); + ESP_LOGV(TAG, "Initializing HTTP client"); + ESP_LOGV(TAG, "Free heap: %" PRIu32, esp_get_free_heap_size()); esp_http_client_config_t config = { .url = this->tft_url_.c_str(), .cert_pem = nullptr, @@ -205,58 +198,62 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { .disable_auto_redirect = false, .max_redirection_count = 10, }; - // Initialize the HTTP client with the configuration - ESP_LOGV(TAG, "Initializing HTTP client"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - esp_http_client_handle_t http = esp_http_client_init(&config); - if (!http) { + esp_http_client_handle_t http_client = esp_http_client_init(&config); + if (!http_client) { ESP_LOGE(TAG, "Failed to initialize HTTP client."); - return this->upload_end(false); + return this->upload_end_(false); + } + + esp_err_t err = esp_http_client_set_header(http_client, "Connection", "keep-alive"); + if (err != ESP_OK) { + ESP_LOGE(TAG, "HTTP set header failed: %s", esp_err_to_name(err)); + esp_http_client_cleanup(http_client); + return this->upload_end_(false); } // Perform the HTTP request ESP_LOGV(TAG, "Check if the client could connect"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - esp_err_t err = esp_http_client_perform(http); + ESP_LOGV(TAG, "Free heap: %" PRIu32, esp_get_free_heap_size()); + err = esp_http_client_perform(http_client); if (err != ESP_OK) { ESP_LOGE(TAG, "HTTP request failed: %s", esp_err_to_name(err)); - esp_http_client_cleanup(http); - return this->upload_end(false); + esp_http_client_cleanup(http_client); + return this->upload_end_(false); } // Check the HTTP Status Code ESP_LOGV(TAG, "Check the HTTP Status Code"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - int status_code = esp_http_client_get_status_code(http); - ESP_LOGV(TAG, "HTTP Status Code: %d", status_code); - size_t tft_file_size = esp_http_client_get_content_length(http); - ESP_LOGD(TAG, "TFT file size: %zu", tft_file_size); + ESP_LOGV(TAG, "Free heap: %" PRIu32, esp_get_free_heap_size()); + int status_code = esp_http_client_get_status_code(http_client); + if (status_code != 200 && status_code != 206) { + return this->upload_end_(false); + } - ESP_LOGD(TAG, "Close HTTP connection"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - esp_http_client_close(http); - esp_http_client_cleanup(http); - ESP_LOGVV(TAG, "Connection closed"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); + this->tft_size_ = esp_http_client_get_content_length(http_client); - if (tft_file_size < 4096) { - ESP_LOGE(TAG, "File size check failed. Size: %zu", tft_file_size); - return this->upload_end(false); + ESP_LOGD(TAG, "TFT file size: %zu bytes", this->tft_size_); + if (this->tft_size_ < 4096 || this->tft_size_ > 134217728) { + ESP_LOGE(TAG, "File size check failed."); + ESP_LOGD(TAG, "Close HTTP connection"); + esp_http_client_close(http_client); + esp_http_client_cleanup(http_client); + ESP_LOGV(TAG, "Connection closed"); + return this->upload_end_(false); } else { ESP_LOGV(TAG, "File size check passed. Proceeding..."); } - this->content_length_ = tft_file_size; - this->tft_size_ = tft_file_size; + this->content_length_ = this->tft_size_; - ESP_LOGD(TAG, "Updating Nextion"); + ESP_LOGD(TAG, "Uploading Nextion"); - // The Nextion will ignore the update command if it is sleeping + // The Nextion will ignore the upload command if it is sleeping ESP_LOGV(TAG, "Wake-up Nextion"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); + this->ignore_is_setup_ = true; this->send_command_("sleep=0"); - this->set_backlight_brightness(1.0); + this->send_command_("dim=100"); vTaskDelay(pdMS_TO_TICKS(250)); // NOLINT + ESP_LOGV(TAG, "Free heap: %" PRIu32, esp_get_free_heap_size()); App.feed_wdt(); char command[128]; @@ -267,14 +264,11 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { // Clear serial receive buffer ESP_LOGV(TAG, "Clear serial receive buffer"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - uint8_t d; - while (this->available()) { - this->read_byte(&d); - }; + this->reset_(false); + vTaskDelay(pdMS_TO_TICKS(250)); // NOLINT + ESP_LOGV(TAG, "Free heap: %" PRIu32, esp_get_free_heap_size()); - ESP_LOGV(TAG, "Send update instruction: %s", command); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); + ESP_LOGV(TAG, "Send upload instruction: %s", command); this->send_command_(command); if (baud_rate != this->original_baud_rate_) { @@ -288,41 +282,66 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { this->recv_ret_string_(response, 5000, true); // This can take some time to return // The Nextion display will, if it's ready to accept data, send a 0x05 byte. - ESP_LOGD(TAG, "Upgrade response is [%s] - %zu bytes", + ESP_LOGD(TAG, "Upgrade response is [%s] - %zu byte(s)", format_hex_pretty(reinterpret_cast(response.data()), response.size()).c_str(), response.length()); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); + ESP_LOGV(TAG, "Free heap: %" PRIu32, esp_get_free_heap_size()); if (response.find(0x05) != std::string::npos) { - ESP_LOGV(TAG, "Preparation for tft update done"); + ESP_LOGV(TAG, "Preparation for TFT upload done"); } else { - ESP_LOGE(TAG, "Preparation for tft update failed %d \"%s\"", response[0], response.c_str()); - return this->upload_end(false); + ESP_LOGE(TAG, "Preparation for TFT upload failed %d \"%s\"", response[0], response.c_str()); + ESP_LOGD(TAG, "Close HTTP connection"); + esp_http_client_close(http_client); + esp_http_client_cleanup(http_client); + ESP_LOGV(TAG, "Connection closed"); + return this->upload_end_(false); } - ESP_LOGD(TAG, "Updating tft from \"%s\" with a file size of %d, Heap Size %" PRIu32, this->tft_url_.c_str(), - content_length_, esp_get_free_heap_size()); + ESP_LOGV(TAG, "Change the method to GET before starting the download"); + esp_err_t set_method_result = esp_http_client_set_method(http_client, HTTP_METHOD_GET); + if (set_method_result != ESP_OK) { + ESP_LOGE(TAG, "Failed to set HTTP method to GET: %s", esp_err_to_name(set_method_result)); + return this->upload_end_(false); + } + + ESP_LOGD(TAG, "Uploading TFT to Nextion:"); + ESP_LOGD(TAG, " URL: %s", this->tft_url_.c_str()); + ESP_LOGD(TAG, " File size: %" PRIu32 " bytes", this->content_length_); + ESP_LOGD(TAG, " Free heap: %" PRIu32, esp_get_free_heap_size()); + + // Proceed with the content download as before ESP_LOGV(TAG, "Starting transfer by chunks loop"); - ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size()); - int result = 0; - while (content_length_ > 0) { - result = upload_range(this->tft_url_.c_str(), result); - if (result < 0) { - ESP_LOGE(TAG, "Error updating Nextion!"); - return this->upload_end(false); + + uint32_t position = 0; + while (this->content_length_ > 0) { + int upload_result = upload_by_chunks_(http_client, position); + if (upload_result < 0) { + ESP_LOGE(TAG, "Error uploading TFT to Nextion!"); + ESP_LOGD(TAG, "Close HTTP connection"); + esp_http_client_close(http_client); + esp_http_client_cleanup(http_client); + ESP_LOGV(TAG, "Connection closed"); + return this->upload_end_(false); } App.feed_wdt(); - ESP_LOGV(TAG, "Heap Size %" PRIu32 ", Bytes left %d", esp_get_free_heap_size(), content_length_); + ESP_LOGV(TAG, "Free heap: %" PRIu32 ", Bytes left: %" PRIu32, esp_get_free_heap_size(), this->content_length_); } - ESP_LOGD(TAG, "Successfully updated Nextion!"); + ESP_LOGD(TAG, "Successfully uploaded TFT to Nextion!"); - return upload_end(true); + ESP_LOGD(TAG, "Close HTTP connection"); + esp_http_client_close(http_client); + esp_http_client_cleanup(http_client); + ESP_LOGV(TAG, "Connection closed"); + return this->upload_end_(true); } -bool Nextion::upload_end(bool successful) { +bool Nextion::upload_end_(bool successful) { + ESP_LOGD(TAG, "Nextion TFT upload finished: %s", YESNO(successful)); this->is_updating_ = false; + this->ignore_is_setup_ = false; uint32_t baud_rate = this->parent_->get_baud_rate(); if (baud_rate != this->original_baud_rate_) { @@ -331,12 +350,12 @@ bool Nextion::upload_end(bool successful) { this->parent_->load_settings(); } - ESP_LOGD(TAG, "Restarting Nextion"); - this->soft_reset(); - vTaskDelay(pdMS_TO_TICKS(1500)); // NOLINT if (successful) { ESP_LOGD(TAG, "Restarting ESPHome"); - esp_restart(); // NOLINT(readability-static-accessed-through-instance) + delay(1500); // NOLINT + arch_restart(); + } else { + ESP_LOGE(TAG, "Nextion TFT upload failed"); } return successful; } @@ -344,5 +363,5 @@ bool Nextion::upload_end(bool successful) { } // namespace nextion } // namespace esphome -#endif // USE_NEXTION_TFT_UPLOAD #endif // USE_ESP_IDF +#endif // USE_NEXTION_TFT_UPLOAD diff --git a/esphome/components/qmc5883l/qmc5883l.cpp b/esphome/components/qmc5883l/qmc5883l.cpp index 8541b41ff7..49a67d4e09 100644 --- a/esphome/components/qmc5883l/qmc5883l.cpp +++ b/esphome/components/qmc5883l/qmc5883l.cpp @@ -1,4 +1,5 @@ #include "qmc5883l.h" +#include "esphome/core/application.h" #include "esphome/core/log.h" #include "esphome/core/hal.h" #include @@ -59,6 +60,10 @@ void QMC5883LComponent::setup() { this->mark_failed(); return; } + + if (this->get_update_interval() < App.get_loop_interval()) { + high_freq_.start(); + } } void QMC5883LComponent::dump_config() { ESP_LOGCONFIG(TAG, "QMC5883L:"); diff --git a/esphome/components/qmc5883l/qmc5883l.h b/esphome/components/qmc5883l/qmc5883l.h index b0c0af40d2..dd2008d453 100644 --- a/esphome/components/qmc5883l/qmc5883l.h +++ b/esphome/components/qmc5883l/qmc5883l.h @@ -56,6 +56,7 @@ class QMC5883LComponent : public PollingComponent, public i2c::I2CDevice { COMMUNICATION_FAILED, } error_code_; bool read_byte_16_(uint8_t a_register, uint16_t *data); + HighFrequencyLoopRequester high_freq_; }; } // namespace qmc5883l diff --git a/esphome/components/remote_base/remote_base.cpp b/esphome/components/remote_base/remote_base.cpp index 0e9cef8cca..fdfd0b43cc 100644 --- a/esphome/components/remote_base/remote_base.cpp +++ b/esphome/components/remote_base/remote_base.cpp @@ -108,18 +108,18 @@ void RemoteReceiverBase::register_dumper(RemoteReceiverDumperBase *dumper) { void RemoteReceiverBase::call_listeners_() { for (auto *listener : this->listeners_) - listener->on_receive(RemoteReceiveData(this->temp_, this->tolerance_)); + listener->on_receive(RemoteReceiveData(this->temp_, this->tolerance_, this->tolerance_mode_)); } void RemoteReceiverBase::call_dumpers_() { bool success = false; for (auto *dumper : this->dumpers_) { - if (dumper->dump(RemoteReceiveData(this->temp_, this->tolerance_))) + if (dumper->dump(RemoteReceiveData(this->temp_, this->tolerance_, this->tolerance_mode_))) success = true; } if (!success) { for (auto *dumper : this->secondary_dumpers_) - dumper->dump(RemoteReceiveData(this->temp_, this->tolerance_)); + dumper->dump(RemoteReceiveData(this->temp_, this->tolerance_, this->tolerance_mode_)); } } diff --git a/esphome/components/remote_base/remote_base.h b/esphome/components/remote_base/remote_base.h index b2a4b543ea..c31127735a 100644 --- a/esphome/components/remote_base/remote_base.h +++ b/esphome/components/remote_base/remote_base.h @@ -15,6 +15,11 @@ namespace esphome { namespace remote_base { +enum ToleranceMode : uint8_t { + TOLERANCE_MODE_PERCENTAGE = 0, + TOLERANCE_MODE_TIME = 1, +}; + using RawTimings = std::vector; class RemoteTransmitData { @@ -42,8 +47,8 @@ class RemoteTransmitData { class RemoteReceiveData { public: - explicit RemoteReceiveData(const RawTimings &data, uint8_t tolerance) - : data_(data), index_(0), tolerance_(tolerance) {} + explicit RemoteReceiveData(const RawTimings &data, uint32_t tolerance, ToleranceMode tolerance_mode) + : data_(data), index_(0), tolerance_(tolerance), tolerance_mode_(tolerance_mode) {} const RawTimings &get_raw_data() const { return this->data_; } uint32_t get_index() const { return index_; } @@ -65,13 +70,35 @@ class RemoteReceiveData { void advance(uint32_t amount = 1) { this->index_ += amount; } void reset() { this->index_ = 0; } + void set_tolerance(uint32_t tolerance, ToleranceMode tolerance_mode) { + this->tolerance_ = tolerance; + this->tolerance_mode_ = tolerance_mode; + } + uint32_t get_tolerance() { return tolerance_; } + ToleranceMode get_tolerance_mode() { return this->tolerance_mode_; } + protected: - int32_t lower_bound_(uint32_t length) const { return int32_t(100 - this->tolerance_) * length / 100U; } - int32_t upper_bound_(uint32_t length) const { return int32_t(100 + this->tolerance_) * length / 100U; } + int32_t lower_bound_(uint32_t length) const { + if (this->tolerance_mode_ == TOLERANCE_MODE_TIME) { + return int32_t(length - this->tolerance_); + } else if (this->tolerance_mode_ == TOLERANCE_MODE_PERCENTAGE) { + return int32_t(100 - this->tolerance_) * length / 100U; + } + return 0; + } + int32_t upper_bound_(uint32_t length) const { + if (this->tolerance_mode_ == TOLERANCE_MODE_TIME) { + return int32_t(length + this->tolerance_); + } else if (this->tolerance_mode_ == TOLERANCE_MODE_PERCENTAGE) { + return int32_t(100 + this->tolerance_) * length / 100U; + } + return 0; + } const RawTimings &data_; uint32_t index_; - uint8_t tolerance_; + uint32_t tolerance_; + ToleranceMode tolerance_mode_; }; class RemoteComponentBase { @@ -162,7 +189,10 @@ class RemoteReceiverBase : public RemoteComponentBase { RemoteReceiverBase(InternalGPIOPin *pin) : RemoteComponentBase(pin) {} void register_listener(RemoteReceiverListener *listener) { this->listeners_.push_back(listener); } void register_dumper(RemoteReceiverDumperBase *dumper); - void set_tolerance(uint8_t tolerance) { tolerance_ = tolerance; } + void set_tolerance(uint32_t tolerance, ToleranceMode tolerance_mode) { + this->tolerance_ = tolerance; + this->tolerance_mode_ = tolerance_mode; + } protected: void call_listeners_(); @@ -176,7 +206,8 @@ class RemoteReceiverBase : public RemoteComponentBase { std::vector dumpers_; std::vector secondary_dumpers_; RawTimings temp_; - uint8_t tolerance_; + uint32_t tolerance_{25}; + ToleranceMode tolerance_mode_{TOLERANCE_MODE_PERCENTAGE}; }; class RemoteReceiverBinarySensorBase : public binary_sensor::BinarySensorInitiallyOff, diff --git a/esphome/components/remote_receiver/__init__.py b/esphome/components/remote_receiver/__init__.py index 6a68c8b254..6fe20153f4 100644 --- a/esphome/components/remote_receiver/__init__.py +++ b/esphome/components/remote_receiver/__init__.py @@ -10,17 +10,69 @@ from esphome.const import ( CONF_IDLE, CONF_PIN, CONF_TOLERANCE, + CONF_TYPE, CONF_MEMORY_BLOCKS, CONF_RMT_CHANNEL, + CONF_VALUE, ) from esphome.core import CORE, TimePeriod +CONF_CLOCK_DIVIDER = "clock_divider" + AUTO_LOAD = ["remote_base"] remote_receiver_ns = cg.esphome_ns.namespace("remote_receiver") +remote_base_ns = cg.esphome_ns.namespace("remote_base") + +ToleranceMode = remote_base_ns.enum("ToleranceMode") + +TYPE_PERCENTAGE = "percentage" +TYPE_TIME = "time" + +TOLERANCE_MODE = { + TYPE_PERCENTAGE: ToleranceMode.TOLERANCE_MODE_PERCENTAGE, + TYPE_TIME: ToleranceMode.TOLERANCE_MODE_TIME, +} + +TOLERANCE_SCHEMA = cv.typed_schema( + { + TYPE_PERCENTAGE: cv.Schema( + {cv.Required(CONF_VALUE): cv.All(cv.percentage_int, cv.uint32_t)} + ), + TYPE_TIME: cv.Schema( + { + cv.Required(CONF_VALUE): cv.All( + cv.positive_time_period_microseconds, + cv.Range(max=TimePeriod(microseconds=4294967295)), + ) + } + ), + }, + lower=True, + enum=TOLERANCE_MODE, +) + RemoteReceiverComponent = remote_receiver_ns.class_( "RemoteReceiverComponent", remote_base.RemoteReceiverBase, cg.Component ) + +def validate_tolerance(value): + if isinstance(value, dict): + return TOLERANCE_SCHEMA(value) + + if "%" in str(value): + type_ = TYPE_PERCENTAGE + else: + type_ = TYPE_TIME + + return TOLERANCE_SCHEMA( + { + CONF_VALUE: value, + CONF_TYPE: type_, + } + ) + + MULTI_CONF = True CONFIG_SCHEMA = remote_base.validate_triggers( cv.Schema( @@ -28,9 +80,7 @@ CONFIG_SCHEMA = remote_base.validate_triggers( cv.GenerateID(): cv.declare_id(RemoteReceiverComponent), cv.Required(CONF_PIN): cv.All(pins.internal_gpio_input_pin_schema), cv.Optional(CONF_DUMP, default=[]): remote_base.validate_dumpers, - cv.Optional(CONF_TOLERANCE, default=25): cv.All( - cv.percentage_int, cv.Range(min=0) - ), + cv.Optional(CONF_TOLERANCE, default="25%"): validate_tolerance, cv.SplitDefault( CONF_BUFFER_SIZE, esp32="10000b", @@ -40,11 +90,15 @@ CONFIG_SCHEMA = remote_base.validate_triggers( ): cv.validate_bytes, cv.Optional(CONF_FILTER, default="50us"): cv.All( cv.positive_time_period_microseconds, - cv.Range(max=TimePeriod(microseconds=255)), + cv.Range(max=TimePeriod(microseconds=4294967295)), + ), + cv.SplitDefault(CONF_CLOCK_DIVIDER, esp32=80): cv.All( + cv.only_on_esp32, cv.Range(min=1, max=255) + ), + cv.Optional(CONF_IDLE, default="10ms"): cv.All( + cv.positive_time_period_microseconds, + cv.Range(max=TimePeriod(microseconds=4294967295)), ), - cv.Optional( - CONF_IDLE, default="10ms" - ): cv.positive_time_period_microseconds, cv.Optional(CONF_MEMORY_BLOCKS, default=3): cv.Range(min=1, max=8), cv.Optional(CONF_RMT_CHANNEL): esp32_rmt.validate_rmt_channel(tx=False), } @@ -61,6 +115,7 @@ async def to_code(config): ) else: var = cg.new_Pvariable(config[CONF_ID], pin, config[CONF_MEMORY_BLOCKS]) + cg.add(var.set_clock_divider(config[CONF_CLOCK_DIVIDER])) else: var = cg.new_Pvariable(config[CONF_ID], pin) @@ -73,7 +128,11 @@ async def to_code(config): cg.add(var.register_listener(trigger)) await cg.register_component(var, config) - cg.add(var.set_tolerance(config[CONF_TOLERANCE])) + cg.add( + var.set_tolerance( + config[CONF_TOLERANCE][CONF_VALUE], config[CONF_TOLERANCE][CONF_TYPE] + ) + ) cg.add(var.set_buffer_size(config[CONF_BUFFER_SIZE])) cg.add(var.set_filter_us(config[CONF_FILTER])) cg.add(var.set_idle_us(config[CONF_IDLE])) diff --git a/esphome/components/remote_receiver/remote_receiver.h b/esphome/components/remote_receiver/remote_receiver.h index f29145a59e..a1db671e5c 100644 --- a/esphome/components/remote_receiver/remote_receiver.h +++ b/esphome/components/remote_receiver/remote_receiver.h @@ -22,7 +22,7 @@ struct RemoteReceiverComponentStore { uint32_t buffer_read_at{0}; bool overflow{false}; uint32_t buffer_size{1000}; - uint8_t filter_us{10}; + uint32_t filter_us{10}; ISRInternalGPIOPin pin; }; #endif @@ -50,7 +50,7 @@ class RemoteReceiverComponent : public remote_base::RemoteReceiverBase, float get_setup_priority() const override { return setup_priority::DATA; } void set_buffer_size(uint32_t buffer_size) { this->buffer_size_ = buffer_size; } - void set_filter_us(uint8_t filter_us) { this->filter_us_ = filter_us; } + void set_filter_us(uint32_t filter_us) { this->filter_us_ = filter_us; } void set_idle_us(uint32_t idle_us) { this->idle_us_ = idle_us; } protected: @@ -66,7 +66,7 @@ class RemoteReceiverComponent : public remote_base::RemoteReceiverBase, #endif uint32_t buffer_size_{}; - uint8_t filter_us_{10}; + uint32_t filter_us_{10}; uint32_t idle_us_{10000}; }; diff --git a/esphome/components/remote_receiver/remote_receiver_esp32.cpp b/esphome/components/remote_receiver/remote_receiver_esp32.cpp index d19ab695e1..c0bfb0222f 100644 --- a/esphome/components/remote_receiver/remote_receiver_esp32.cpp +++ b/esphome/components/remote_receiver/remote_receiver_esp32.cpp @@ -20,9 +20,11 @@ void RemoteReceiverComponent::setup() { rmt.rx_config.filter_en = false; } else { rmt.rx_config.filter_en = true; - rmt.rx_config.filter_ticks_thresh = this->from_microseconds_(this->filter_us_); + rmt.rx_config.filter_ticks_thresh = static_cast( + std::min(this->from_microseconds_(this->filter_us_) * this->clock_divider_, (uint32_t) 255)); } - rmt.rx_config.idle_threshold = this->from_microseconds_(this->idle_us_); + rmt.rx_config.idle_threshold = + static_cast(std::min(this->from_microseconds_(this->idle_us_), (uint32_t) 65535)); esp_err_t error = rmt_config(&rmt); if (error != ESP_OK) { @@ -60,8 +62,9 @@ void RemoteReceiverComponent::dump_config() { ESP_LOGCONFIG(TAG, " Channel: %d", this->channel_); ESP_LOGCONFIG(TAG, " RMT memory blocks: %d", this->mem_block_num_); ESP_LOGCONFIG(TAG, " Clock divider: %u", this->clock_divider_); - ESP_LOGCONFIG(TAG, " Tolerance: %u%%", this->tolerance_); - ESP_LOGCONFIG(TAG, " Filter out pulses shorter than: %u us", this->filter_us_); + ESP_LOGCONFIG(TAG, " Tolerance: %" PRIu32 "%s", this->tolerance_, + (this->tolerance_mode_ == remote_base::TOLERANCE_MODE_TIME) ? " us" : "%"); + ESP_LOGCONFIG(TAG, " Filter out pulses shorter than: %" PRIu32 " us", this->filter_us_); ESP_LOGCONFIG(TAG, " Signal is done after %" PRIu32 " us of no changes", this->idle_us_); if (this->is_failed()) { ESP_LOGE(TAG, "Configuring RMT driver failed: %s", esp_err_to_name(this->error_code_)); @@ -88,6 +91,7 @@ void RemoteReceiverComponent::decode_rmt_(rmt_item32_t *item, size_t len) { this->temp_.clear(); int32_t multiplier = this->pin_->is_inverted() ? -1 : 1; size_t item_count = len / sizeof(rmt_item32_t); + uint32_t filter_ticks = this->from_microseconds_(this->filter_us_); ESP_LOGVV(TAG, "START:"); for (size_t i = 0; i < item_count; i++) { @@ -112,7 +116,7 @@ void RemoteReceiverComponent::decode_rmt_(rmt_item32_t *item, size_t len) { for (size_t i = 0; i < item_count; i++) { if (item[i].duration0 == 0u) { // Do nothing - } else if (bool(item[i].level0) == prev_level) { + } else if ((bool(item[i].level0) == prev_level) || (item[i].duration0 < filter_ticks)) { prev_length += item[i].duration0; } else { if (prev_length > 0) { @@ -128,7 +132,7 @@ void RemoteReceiverComponent::decode_rmt_(rmt_item32_t *item, size_t len) { if (item[i].duration1 == 0u) { // Do nothing - } else if (bool(item[i].level1) == prev_level) { + } else if ((bool(item[i].level1) == prev_level) || (item[i].duration1 < filter_ticks)) { prev_length += item[i].duration1; } else { if (prev_length > 0) { diff --git a/esphome/components/remote_receiver/remote_receiver_esp8266.cpp b/esphome/components/remote_receiver/remote_receiver_esp8266.cpp index 8700fcf0bb..c92a134bd8 100644 --- a/esphome/components/remote_receiver/remote_receiver_esp8266.cpp +++ b/esphome/components/remote_receiver/remote_receiver_esp8266.cpp @@ -64,7 +64,8 @@ void RemoteReceiverComponent::dump_config() { "invert the signal using 'inverted: True' in the pin schema!"); } ESP_LOGCONFIG(TAG, " Buffer Size: %u", this->buffer_size_); - ESP_LOGCONFIG(TAG, " Tolerance: %u%%", this->tolerance_); + ESP_LOGCONFIG(TAG, " Tolerance: %u%s", this->tolerance_, + (this->tolerance_mode_ == remote_base::TOLERANCE_MODE_TIME) ? " us" : "%"); ESP_LOGCONFIG(TAG, " Filter out pulses shorter than: %u us", this->filter_us_); ESP_LOGCONFIG(TAG, " Signal is done after %u us of no changes", this->idle_us_); } diff --git a/esphome/components/remote_receiver/remote_receiver_libretiny.cpp b/esphome/components/remote_receiver/remote_receiver_libretiny.cpp index ac85b6b520..bfc29b4211 100644 --- a/esphome/components/remote_receiver/remote_receiver_libretiny.cpp +++ b/esphome/components/remote_receiver/remote_receiver_libretiny.cpp @@ -64,7 +64,8 @@ void RemoteReceiverComponent::dump_config() { "invert the signal using 'inverted: True' in the pin schema!"); } ESP_LOGCONFIG(TAG, " Buffer Size: %u", this->buffer_size_); - ESP_LOGCONFIG(TAG, " Tolerance: %u%%", this->tolerance_); + ESP_LOGCONFIG(TAG, " Tolerance: %u%s", this->tolerance_, + (this->tolerance_mode_ == remote_base::TOLERANCE_MODE_TIME) ? " us" : "%"); ESP_LOGCONFIG(TAG, " Filter out pulses shorter than: %u us", this->filter_us_); ESP_LOGCONFIG(TAG, " Signal is done after %u us of no changes", this->idle_us_); } diff --git a/esphome/core/application.h b/esphome/core/application.h index 7487780412..c4c745b687 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -222,6 +222,8 @@ class Application { */ void set_loop_interval(uint32_t loop_interval) { this->loop_interval_ = loop_interval; } + uint32_t get_loop_interval() const { return this->loop_interval_; } + void schedule_dump_config() { this->dump_config_at_ = 0; } void feed_wdt(); diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 619a956071..b09373bcde 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -35,6 +35,7 @@ #define USE_MDNS #define USE_MEDIA_PLAYER #define USE_MQTT +#define USE_NEXTION_TFT_UPLOAD #define USE_NUMBER #define USE_DATETIME #define USE_DATETIME_DATE @@ -64,7 +65,6 @@ // Arduino-specific feature flags #ifdef USE_ARDUINO #define USE_CAPTIVE_PORTAL -#define USE_NEXTION_TFT_UPLOAD #define USE_PROMETHEUS #define USE_WEBSERVER #define USE_WEBSERVER_PORT 80 // NOLINT diff --git a/tests/components/bmp3xx/test.esp32-c3-idf.yaml b/tests/components/bmp3xx/test.esp32-c3-idf.yaml deleted file mode 100644 index 3b244eccf9..0000000000 --- a/tests/components/bmp3xx/test.esp32-c3-idf.yaml +++ /dev/null @@ -1,14 +0,0 @@ -i2c: - - id: i2c_bmp3xx - scl: 5 - sda: 4 - -sensor: - - platform: bmp3xx - address: 0x77 - temperature: - name: BMP Temperature - oversampling: 16x - pressure: - name: BMP Pressure - iir_filter: 2X diff --git a/tests/components/bmp3xx/test.esp32-c3.yaml b/tests/components/bmp3xx/test.esp32-c3.yaml deleted file mode 100644 index 3b244eccf9..0000000000 --- a/tests/components/bmp3xx/test.esp32-c3.yaml +++ /dev/null @@ -1,14 +0,0 @@ -i2c: - - id: i2c_bmp3xx - scl: 5 - sda: 4 - -sensor: - - platform: bmp3xx - address: 0x77 - temperature: - name: BMP Temperature - oversampling: 16x - pressure: - name: BMP Pressure - iir_filter: 2X diff --git a/tests/components/bmp3xx/test.esp32.yaml b/tests/components/bmp3xx/test.esp32.yaml deleted file mode 100644 index 677ed8a22d..0000000000 --- a/tests/components/bmp3xx/test.esp32.yaml +++ /dev/null @@ -1,14 +0,0 @@ -i2c: - - id: i2c_bmp3xx - scl: 16 - sda: 17 - -sensor: - - platform: bmp3xx - address: 0x77 - temperature: - name: BMP Temperature - oversampling: 16x - pressure: - name: BMP Pressure - iir_filter: 2X diff --git a/tests/components/bmp3xx/test.esp8266.yaml b/tests/components/bmp3xx/test.esp8266.yaml deleted file mode 100644 index 3b244eccf9..0000000000 --- a/tests/components/bmp3xx/test.esp8266.yaml +++ /dev/null @@ -1,14 +0,0 @@ -i2c: - - id: i2c_bmp3xx - scl: 5 - sda: 4 - -sensor: - - platform: bmp3xx - address: 0x77 - temperature: - name: BMP Temperature - oversampling: 16x - pressure: - name: BMP Pressure - iir_filter: 2X diff --git a/tests/components/bmp3xx/test.rp2040.yaml b/tests/components/bmp3xx/test.rp2040.yaml deleted file mode 100644 index 3b244eccf9..0000000000 --- a/tests/components/bmp3xx/test.rp2040.yaml +++ /dev/null @@ -1,14 +0,0 @@ -i2c: - - id: i2c_bmp3xx - scl: 5 - sda: 4 - -sensor: - - platform: bmp3xx - address: 0x77 - temperature: - name: BMP Temperature - oversampling: 16x - pressure: - name: BMP Pressure - iir_filter: 2X diff --git a/tests/components/bmp3xx/test.esp32-idf.yaml b/tests/components/bmp3xx_i2c/common.yaml similarity index 66% rename from tests/components/bmp3xx/test.esp32-idf.yaml rename to tests/components/bmp3xx_i2c/common.yaml index 677ed8a22d..6641b7a1b8 100644 --- a/tests/components/bmp3xx/test.esp32-idf.yaml +++ b/tests/components/bmp3xx_i2c/common.yaml @@ -1,10 +1,11 @@ i2c: - id: i2c_bmp3xx - scl: 16 - sda: 17 + scl: ${scl_pin} + sda: ${sda_pin} sensor: - - platform: bmp3xx + - platform: bmp3xx_i2c + i2c_id: i2c_bmp3xx address: 0x77 temperature: name: BMP Temperature diff --git a/tests/components/bmp3xx_i2c/test.esp32-c3-idf.yaml b/tests/components/bmp3xx_i2c/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/bmp3xx_i2c/test.esp32-c3-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/bmp3xx_i2c/test.esp32-c3.yaml b/tests/components/bmp3xx_i2c/test.esp32-c3.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/bmp3xx_i2c/test.esp32-c3.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/bmp3xx_i2c/test.esp32-idf.yaml b/tests/components/bmp3xx_i2c/test.esp32-idf.yaml new file mode 100644 index 0000000000..63c3bd6afd --- /dev/null +++ b/tests/components/bmp3xx_i2c/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO16 + sda_pin: GPIO17 + +<<: !include common.yaml diff --git a/tests/components/bmp3xx_i2c/test.esp32.yaml b/tests/components/bmp3xx_i2c/test.esp32.yaml new file mode 100644 index 0000000000..63c3bd6afd --- /dev/null +++ b/tests/components/bmp3xx_i2c/test.esp32.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO16 + sda_pin: GPIO17 + +<<: !include common.yaml diff --git a/tests/components/bmp3xx_i2c/test.esp8266.yaml b/tests/components/bmp3xx_i2c/test.esp8266.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/bmp3xx_i2c/test.esp8266.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/bmp3xx_i2c/test.rp2040.yaml b/tests/components/bmp3xx_i2c/test.rp2040.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/bmp3xx_i2c/test.rp2040.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/bmp3xx_spi/common.yaml b/tests/components/bmp3xx_spi/common.yaml new file mode 100644 index 0000000000..8d5f897661 --- /dev/null +++ b/tests/components/bmp3xx_spi/common.yaml @@ -0,0 +1,16 @@ +spi: + - id: spi_bmp3xx + clk_pin: ${clk_pin} + mosi_pin: ${mosi_pin} + miso_pin: ${miso_pin} + +sensor: + - platform: bmp3xx_spi + spi_id: spi_bmp3xx + cs_pin: ${cs_pin} + temperature: + name: BMP Temperature + oversampling: 16x + pressure: + name: BMP Pressure + iir_filter: 2X diff --git a/tests/components/bmp3xx_spi/test.esp32-c3-idf.yaml b/tests/components/bmp3xx_spi/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..2415ba5dc6 --- /dev/null +++ b/tests/components/bmp3xx_spi/test.esp32-c3-idf.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO6 + mosi_pin: GPIO7 + miso_pin: GPIO5 + cs_pin: GPIO8 + +<<: !include common.yaml diff --git a/tests/components/bmp3xx_spi/test.esp32-c3.yaml b/tests/components/bmp3xx_spi/test.esp32-c3.yaml new file mode 100644 index 0000000000..2415ba5dc6 --- /dev/null +++ b/tests/components/bmp3xx_spi/test.esp32-c3.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO6 + mosi_pin: GPIO7 + miso_pin: GPIO5 + cs_pin: GPIO8 + +<<: !include common.yaml diff --git a/tests/components/bmp3xx_spi/test.esp32-idf.yaml b/tests/components/bmp3xx_spi/test.esp32-idf.yaml new file mode 100644 index 0000000000..54e027a614 --- /dev/null +++ b/tests/components/bmp3xx_spi/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO16 + mosi_pin: GPIO17 + miso_pin: GPIO15 + cs_pin: GPIO5 + +<<: !include common.yaml diff --git a/tests/components/bmp3xx_spi/test.esp32.yaml b/tests/components/bmp3xx_spi/test.esp32.yaml new file mode 100644 index 0000000000..54e027a614 --- /dev/null +++ b/tests/components/bmp3xx_spi/test.esp32.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO16 + mosi_pin: GPIO17 + miso_pin: GPIO15 + cs_pin: GPIO5 + +<<: !include common.yaml diff --git a/tests/components/bmp3xx_spi/test.esp8266.yaml b/tests/components/bmp3xx_spi/test.esp8266.yaml new file mode 100644 index 0000000000..dbd158d030 --- /dev/null +++ b/tests/components/bmp3xx_spi/test.esp8266.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO14 + mosi_pin: GPIO13 + miso_pin: GPIO12 + cs_pin: GPIO15 + +<<: !include common.yaml diff --git a/tests/components/bmp3xx_spi/test.rp2040.yaml b/tests/components/bmp3xx_spi/test.rp2040.yaml new file mode 100644 index 0000000000..f6c3f1eeca --- /dev/null +++ b/tests/components/bmp3xx_spi/test.rp2040.yaml @@ -0,0 +1,7 @@ +substitutions: + clk_pin: GPIO2 + mosi_pin: GPIO3 + miso_pin: GPIO4 + cs_pin: GPIO5 + +<<: !include common.yaml diff --git a/tests/components/script/common.yaml b/tests/components/script/common.yaml new file mode 100644 index 0000000000..bfd5d0e7ff --- /dev/null +++ b/tests/components/script/common.yaml @@ -0,0 +1,55 @@ +esphome: + on_boot: + then: + - script.execute: my_script + - script.execute: + id: my_script_with_params + prefix: "Test" + param2: 0 + param3: true + - script.wait: my_script + - script.stop: my_script + - if: + condition: + - script.is_running: my_script + then: + - logger.log: my_script is running + +script: + - id: my_script + mode: single + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_queued + mode: queued + max_runs: 2 + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_parallel + mode: parallel + max_runs: 2 + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_restart + mode: restart + then: + - lambda: 'ESP_LOGD("main", "Hello World!");' + - id: my_script_with_params + parameters: + prefix: string + param2: uint8_t + param3: bool + then: + - lambda: 'ESP_LOGD(prefix.c_str(), "Hello World! %u %u", param2, param3);' + - if: + condition: + for: + time: !lambda "return param2;" + condition: + script.is_running: my_script + then: + - lambda: 'ESP_LOGD("main", "API has stayed connected for at least %u minutes", param2);' + - repeat: + count: 5 + then: + - logger.log: looping! diff --git a/tests/components/script/test.bk72xx.yaml b/tests/components/script/test.bk72xx.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/script/test.bk72xx.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/script/test.esp32-c3-idf.yaml b/tests/components/script/test.esp32-c3-idf.yaml index 3872c690ff..dade44d145 100644 --- a/tests/components/script/test.esp32-c3-idf.yaml +++ b/tests/components/script/test.esp32-c3-idf.yaml @@ -1,26 +1 @@ -script: - - id: my_script - mode: single - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_queued - mode: queued - max_runs: 2 - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_parallel - mode: parallel - max_runs: 2 - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_restart - mode: restart - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_with_params - parameters: - prefix: string - param2: int - param3: bool - then: - - lambda: 'ESP_LOGD("main", (prefix + " Hello World!" + to_string(param2) + " " + to_string(param3)).c_str());' +<<: !include common.yaml diff --git a/tests/components/script/test.esp32-c3.yaml b/tests/components/script/test.esp32-c3.yaml index 3872c690ff..dade44d145 100644 --- a/tests/components/script/test.esp32-c3.yaml +++ b/tests/components/script/test.esp32-c3.yaml @@ -1,26 +1 @@ -script: - - id: my_script - mode: single - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_queued - mode: queued - max_runs: 2 - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_parallel - mode: parallel - max_runs: 2 - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_restart - mode: restart - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_with_params - parameters: - prefix: string - param2: int - param3: bool - then: - - lambda: 'ESP_LOGD("main", (prefix + " Hello World!" + to_string(param2) + " " + to_string(param3)).c_str());' +<<: !include common.yaml diff --git a/tests/components/script/test.esp32-idf.yaml b/tests/components/script/test.esp32-idf.yaml index 3872c690ff..dade44d145 100644 --- a/tests/components/script/test.esp32-idf.yaml +++ b/tests/components/script/test.esp32-idf.yaml @@ -1,26 +1 @@ -script: - - id: my_script - mode: single - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_queued - mode: queued - max_runs: 2 - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_parallel - mode: parallel - max_runs: 2 - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_restart - mode: restart - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_with_params - parameters: - prefix: string - param2: int - param3: bool - then: - - lambda: 'ESP_LOGD("main", (prefix + " Hello World!" + to_string(param2) + " " + to_string(param3)).c_str());' +<<: !include common.yaml diff --git a/tests/components/script/test.esp32.yaml b/tests/components/script/test.esp32.yaml index 3872c690ff..dade44d145 100644 --- a/tests/components/script/test.esp32.yaml +++ b/tests/components/script/test.esp32.yaml @@ -1,26 +1 @@ -script: - - id: my_script - mode: single - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_queued - mode: queued - max_runs: 2 - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_parallel - mode: parallel - max_runs: 2 - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_restart - mode: restart - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_with_params - parameters: - prefix: string - param2: int - param3: bool - then: - - lambda: 'ESP_LOGD("main", (prefix + " Hello World!" + to_string(param2) + " " + to_string(param3)).c_str());' +<<: !include common.yaml diff --git a/tests/components/script/test.esp8266.yaml b/tests/components/script/test.esp8266.yaml index ce0e40e7ee..dade44d145 100644 --- a/tests/components/script/test.esp8266.yaml +++ b/tests/components/script/test.esp8266.yaml @@ -1,26 +1 @@ -script: - - id: my_script - mode: single - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_queued - mode: queued - max_runs: 2 - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_parallel - mode: parallel - max_runs: 2 - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_restart - mode: restart - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_with_params - parameters: - prefix: string - param2: int - param3: bool - then: - - lambda: 'ESP_LOGD(prefix.c_str(), "Hello World! %i %i", param2, param3);' +<<: !include common.yaml diff --git a/tests/components/script/test.rp2040.yaml b/tests/components/script/test.rp2040.yaml index 3872c690ff..dade44d145 100644 --- a/tests/components/script/test.rp2040.yaml +++ b/tests/components/script/test.rp2040.yaml @@ -1,26 +1 @@ -script: - - id: my_script - mode: single - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_queued - mode: queued - max_runs: 2 - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_parallel - mode: parallel - max_runs: 2 - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_restart - mode: restart - then: - - lambda: 'ESP_LOGD("main", "Hello World!");' - - id: my_script_with_params - parameters: - prefix: string - param2: int - param3: bool - then: - - lambda: 'ESP_LOGD("main", (prefix + " Hello World!" + to_string(param2) + " " + to_string(param3)).c_str());' +<<: !include common.yaml diff --git a/tests/test11.5.yaml b/tests/test11.5.yaml index 936fdc29fc..bba4ec5405 100644 --- a/tests/test11.5.yaml +++ b/tests/test11.5.yaml @@ -510,15 +510,6 @@ sensor: co2: name: CO2 Sensor - - platform: bmp3xx - temperature: - name: BMP Temperature - oversampling: 16x - pressure: - name: BMP Pressure - address: 0x77 - iir_filter: 2X - - platform: sen5x id: sen54 temperature: diff --git a/tests/test5.yaml b/tests/test5.yaml index 81615b24b0..afd3359098 100644 --- a/tests/test5.yaml +++ b/tests/test5.yaml @@ -474,15 +474,6 @@ sensor: co2: name: CO2 Sensor - - platform: bmp3xx - temperature: - name: BMP Temperature - oversampling: 16x - pressure: - name: BMP Pressure - address: 0x77 - iir_filter: 2X - - platform: ms8607 temperature: name: Temperature