diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index e6b6da4177..b2a3394563 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.11.0 + uses: docker/build-push-action@v6.12.0 env: DOCKER_BUILD_SUMMARY: false DOCKER_BUILD_RECORD_UPLOAD: false @@ -72,7 +72,7 @@ runs: - name: Build and push to dockerhub by digest id: build-dockerhub - uses: docker/build-push-action@v6.11.0 + uses: docker/build-push-action@v6.12.0 env: DOCKER_BUILD_SUMMARY: false DOCKER_BUILD_RECORD_UPLOAD: false diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 95f275e5a4..b79939fc8e 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -17,7 +17,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v9.0.0 + - uses: actions/stale@v9.1.0 with: days-before-pr-stale: 90 days-before-pr-close: 7 @@ -37,7 +37,7 @@ jobs: close-issues: runs-on: ubuntu-latest steps: - - uses: actions/stale@v9.0.0 + - uses: actions/stale@v9.1.0 with: days-before-pr-stale: -1 days-before-pr-close: -1 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index aeb434167a..adf0ac6fc2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,14 +11,6 @@ repos: args: [--fix] # Run the formatter. - id: ruff-format - - repo: https://github.com/psf/black-pre-commit-mirror - rev: 24.4.2 - hooks: - - id: black - args: - - --safe - - --quiet - files: ^((esphome|script|tests)/.+)?[^/]+\.py$ - repo: https://github.com/PyCQA/flake8 rev: 6.1.0 hooks: @@ -53,6 +45,6 @@ repos: hooks: - id: pylint name: pylint - entry: script/run-in-env.sh pylint - language: script + entry: python script/run-in-env pylint + language: system types: [python] diff --git a/CODEOWNERS b/CODEOWNERS index ba7106e6a3..aa24b6cb82 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -49,6 +49,7 @@ esphome/components/atc_mithermometer/* @ahpohl esphome/components/atm90e26/* @danieltwagner esphome/components/atm90e32/* @circuitsetup @descipher esphome/components/audio/* @kahrendt +esphome/components/audio_adc/* @kbx81 esphome/components/audio_dac/* @kbx81 esphome/components/axs15231/* @clydebarrow esphome/components/b_parasite/* @rbaron @@ -132,6 +133,8 @@ esphome/components/ens160_i2c/* @latonita esphome/components/ens160_spi/* @latonita esphome/components/ens210/* @itn3rd77 esphome/components/es7210/* @kahrendt +esphome/components/es7243e/* @kbx81 +esphome/components/es8156/* @kbx81 esphome/components/es8311/* @kahrendt @kroimon esphome/components/esp32/* @esphome/core esphome/components/esp32_ble/* @Rapsssito @jesserockz @@ -339,7 +342,6 @@ esphome/components/radon_eye_rd200/* @jeffeb3 esphome/components/rc522/* @glmnet esphome/components/rc522_i2c/* @glmnet esphome/components/rc522_spi/* @glmnet -esphome/components/resistance_sampler/* @jesserockz esphome/components/restart/* @esphome/core esphome/components/rf_bridge/* @jesserockz esphome/components/rgbct/* @jesserockz diff --git a/esphome/components/ads1115/ads1115.cpp b/esphome/components/ads1115/ads1115.cpp index 218edc4c81..c05064383c 100644 --- a/esphome/components/ads1115/ads1115.cpp +++ b/esphome/components/ads1115/ads1115.cpp @@ -9,8 +9,6 @@ static const char *const TAG = "ads1115"; static const uint8_t ADS1115_REGISTER_CONVERSION = 0x00; static const uint8_t ADS1115_REGISTER_CONFIG = 0x01; -static const uint8_t ADS1115_DATA_RATE_860_SPS = 0b111; // 3300_SPS for ADS1015 - void ADS1115Component::setup() { ESP_LOGCONFIG(TAG, "Setting up ADS1115..."); uint16_t value; @@ -43,9 +41,9 @@ void ADS1115Component::setup() { config |= 0b0000000100000000; } - // Set data rate - 860 samples per second (we're in singleshot mode) + // Set data rate - 860 samples per second // 0bxxxxxxxx100xxxxx - config |= ADS1115_DATA_RATE_860_SPS << 5; + config |= ADS1115_860SPS << 5; // Set comparator mode - hysteresis // 0bxxxxxxxxxxx0xxxx @@ -77,7 +75,7 @@ void ADS1115Component::dump_config() { } } float ADS1115Component::request_measurement(ADS1115Multiplexer multiplexer, ADS1115Gain gain, - ADS1115Resolution resolution) { + ADS1115Resolution resolution, ADS1115Samplerate samplerate) { uint16_t config = this->prev_config_; // Multiplexer // 0bxBBBxxxxxxxxxxxx @@ -89,6 +87,11 @@ float ADS1115Component::request_measurement(ADS1115Multiplexer multiplexer, ADS1 config &= 0b1111000111111111; config |= (gain & 0b111) << 9; + // Sample rate + // 0bxxxxxxxxBBBxxxxx + config &= 0b1111111100011111; + config |= (samplerate & 0b111) << 5; + if (!this->continuous_mode_) { // Start conversion config |= 0b1000000000000000; @@ -101,8 +104,54 @@ float ADS1115Component::request_measurement(ADS1115Multiplexer multiplexer, ADS1 } this->prev_config_ = config; - // about 1.2 ms with 860 samples per second - delay(2); + // Delay calculated as: ceil((1000/SPS)+.5) + if (resolution == ADS1015_12_BITS) { + switch (samplerate) { + case ADS1115_8SPS: + delay(9); + break; + case ADS1115_16SPS: + delay(5); + break; + case ADS1115_32SPS: + delay(3); + break; + case ADS1115_64SPS: + case ADS1115_128SPS: + delay(2); + break; + default: + delay(1); + break; + } + } else { + switch (samplerate) { + case ADS1115_8SPS: + delay(126); // NOLINT + break; + case ADS1115_16SPS: + delay(63); // NOLINT + break; + case ADS1115_32SPS: + delay(32); + break; + case ADS1115_64SPS: + delay(17); + break; + case ADS1115_128SPS: + delay(9); + break; + case ADS1115_250SPS: + delay(5); + break; + case ADS1115_475SPS: + delay(3); + break; + case ADS1115_860SPS: + delay(2); + break; + } + } // in continuous mode, conversion will always be running, rely on the delay // to ensure conversion is taking place with the correct settings diff --git a/esphome/components/ads1115/ads1115.h b/esphome/components/ads1115/ads1115.h index 509333d2c8..e65835a386 100644 --- a/esphome/components/ads1115/ads1115.h +++ b/esphome/components/ads1115/ads1115.h @@ -33,6 +33,17 @@ enum ADS1115Resolution { ADS1015_12_BITS = 12, }; +enum ADS1115Samplerate { + ADS1115_8SPS = 0b000, + ADS1115_16SPS = 0b001, + ADS1115_32SPS = 0b010, + ADS1115_64SPS = 0b011, + ADS1115_128SPS = 0b100, + ADS1115_250SPS = 0b101, + ADS1115_475SPS = 0b110, + ADS1115_860SPS = 0b111 +}; + class ADS1115Component : public Component, public i2c::I2CDevice { public: void setup() override; @@ -42,7 +53,8 @@ class ADS1115Component : public Component, public i2c::I2CDevice { void set_continuous_mode(bool continuous_mode) { continuous_mode_ = continuous_mode; } /// Helper method to request a measurement from a sensor. - float request_measurement(ADS1115Multiplexer multiplexer, ADS1115Gain gain, ADS1115Resolution resolution); + float request_measurement(ADS1115Multiplexer multiplexer, ADS1115Gain gain, ADS1115Resolution resolution, + ADS1115Samplerate samplerate); protected: uint16_t prev_config_{0}; diff --git a/esphome/components/ads1115/sensor/__init__.py b/esphome/components/ads1115/sensor/__init__.py index baec31d35c..f346a71198 100644 --- a/esphome/components/ads1115/sensor/__init__.py +++ b/esphome/components/ads1115/sensor/__init__.py @@ -5,6 +5,7 @@ from esphome.const import ( CONF_GAIN, CONF_MULTIPLEXER, CONF_RESOLUTION, + CONF_SAMPLE_RATE, DEVICE_CLASS_VOLTAGE, STATE_CLASS_MEASUREMENT, UNIT_VOLT, @@ -43,6 +44,17 @@ RESOLUTION = { "12_BITS": ADS1115Resolution.ADS1015_12_BITS, } +ADS1115Samplerate = ads1115_ns.enum("ADS1115Samplerate") +SAMPLERATE = { + "8": ADS1115Samplerate.ADS1115_8SPS, + "16": ADS1115Samplerate.ADS1115_16SPS, + "32": ADS1115Samplerate.ADS1115_32SPS, + "64": ADS1115Samplerate.ADS1115_64SPS, + "128": ADS1115Samplerate.ADS1115_128SPS, + "250": ADS1115Samplerate.ADS1115_250SPS, + "475": ADS1115Samplerate.ADS1115_475SPS, + "860": ADS1115Samplerate.ADS1115_860SPS, +} ADS1115Sensor = ads1115_ns.class_( "ADS1115Sensor", sensor.Sensor, cg.PollingComponent, voltage_sampler.VoltageSampler @@ -64,6 +76,9 @@ CONFIG_SCHEMA = ( cv.Optional(CONF_RESOLUTION, default="16_BITS"): cv.enum( RESOLUTION, upper=True, space="_" ), + cv.Optional(CONF_SAMPLE_RATE, default="860"): cv.enum( + SAMPLERATE, string=True + ), } ) .extend(cv.polling_component_schema("60s")) @@ -79,3 +94,4 @@ async def to_code(config): cg.add(var.set_multiplexer(config[CONF_MULTIPLEXER])) cg.add(var.set_gain(config[CONF_GAIN])) cg.add(var.set_resolution(config[CONF_RESOLUTION])) + cg.add(var.set_samplerate(config[CONF_SAMPLE_RATE])) diff --git a/esphome/components/ads1115/sensor/ads1115_sensor.cpp b/esphome/components/ads1115/sensor/ads1115_sensor.cpp index 335fca4845..6de95f1d12 100644 --- a/esphome/components/ads1115/sensor/ads1115_sensor.cpp +++ b/esphome/components/ads1115/sensor/ads1115_sensor.cpp @@ -8,7 +8,7 @@ namespace ads1115 { static const char *const TAG = "ads1115.sensor"; float ADS1115Sensor::sample() { - return this->parent_->request_measurement(this->multiplexer_, this->gain_, this->resolution_); + return this->parent_->request_measurement(this->multiplexer_, this->gain_, this->resolution_, this->samplerate_); } void ADS1115Sensor::update() { @@ -24,6 +24,7 @@ void ADS1115Sensor::dump_config() { ESP_LOGCONFIG(TAG, " Multiplexer: %u", this->multiplexer_); ESP_LOGCONFIG(TAG, " Gain: %u", this->gain_); ESP_LOGCONFIG(TAG, " Resolution: %u", this->resolution_); + ESP_LOGCONFIG(TAG, " Sample rate: %u", this->samplerate_); } } // namespace ads1115 diff --git a/esphome/components/ads1115/sensor/ads1115_sensor.h b/esphome/components/ads1115/sensor/ads1115_sensor.h index 191afc3de6..5ca25c13ad 100644 --- a/esphome/components/ads1115/sensor/ads1115_sensor.h +++ b/esphome/components/ads1115/sensor/ads1115_sensor.h @@ -21,6 +21,7 @@ class ADS1115Sensor : public sensor::Sensor, void set_multiplexer(ADS1115Multiplexer multiplexer) { this->multiplexer_ = multiplexer; } void set_gain(ADS1115Gain gain) { this->gain_ = gain; } void set_resolution(ADS1115Resolution resolution) { this->resolution_ = resolution; } + void set_samplerate(ADS1115Samplerate samplerate) { this->samplerate_ = samplerate; } float sample() override; void dump_config() override; @@ -29,6 +30,7 @@ class ADS1115Sensor : public sensor::Sensor, ADS1115Multiplexer multiplexer_; ADS1115Gain gain_; ADS1115Resolution resolution_; + ADS1115Samplerate samplerate_; }; } // namespace ads1115 diff --git a/esphome/components/audio_adc/__init__.py b/esphome/components/audio_adc/__init__.py new file mode 100644 index 0000000000..dd3c958821 --- /dev/null +++ b/esphome/components/audio_adc/__init__.py @@ -0,0 +1,41 @@ +from esphome import automation +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.const import CONF_ID, CONF_MIC_GAIN +from esphome.core import coroutine_with_priority + +CODEOWNERS = ["@kbx81"] +IS_PLATFORM_COMPONENT = True + +audio_adc_ns = cg.esphome_ns.namespace("audio_adc") +AudioAdc = audio_adc_ns.class_("AudioAdc") + +SetMicGainAction = audio_adc_ns.class_("SetMicGainAction", automation.Action) + + +SET_MIC_GAIN_ACTION_SCHEMA = cv.maybe_simple_value( + { + cv.GenerateID(): cv.use_id(AudioAdc), + cv.Required(CONF_MIC_GAIN): cv.templatable(cv.decibel), + }, + key=CONF_MIC_GAIN, +) + + +@automation.register_action( + "audio_adc.set_mic_gain", SetMicGainAction, SET_MIC_GAIN_ACTION_SCHEMA +) +async def audio_adc_set_mic_gain_to_code(config, action_id, template_arg, args): + paren = await cg.get_variable(config[CONF_ID]) + var = cg.new_Pvariable(action_id, template_arg, paren) + + template_ = await cg.templatable(config.get(CONF_MIC_GAIN), args, float) + cg.add(var.set_mic_gain(template_)) + + return var + + +@coroutine_with_priority(100.0) +async def to_code(config): + cg.add_define("USE_AUDIO_ADC") + cg.add_global(audio_adc_ns.using) diff --git a/esphome/components/audio_adc/audio_adc.h b/esphome/components/audio_adc/audio_adc.h new file mode 100644 index 0000000000..94bfb57db5 --- /dev/null +++ b/esphome/components/audio_adc/audio_adc.h @@ -0,0 +1,17 @@ +#pragma once + +#include "esphome/core/defines.h" +#include "esphome/core/hal.h" + +namespace esphome { +namespace audio_adc { + +class AudioAdc { + public: + virtual bool set_mic_gain(float mic_gain) = 0; + + virtual float mic_gain() = 0; +}; + +} // namespace audio_adc +} // namespace esphome diff --git a/esphome/components/audio_adc/automation.h b/esphome/components/audio_adc/automation.h new file mode 100644 index 0000000000..1b0bc2a6ad --- /dev/null +++ b/esphome/components/audio_adc/automation.h @@ -0,0 +1,23 @@ +#pragma once + +#include "esphome/core/automation.h" +#include "esphome/core/component.h" +#include "audio_adc.h" + +namespace esphome { +namespace audio_adc { + +template class SetMicGainAction : public Action { + public: + explicit SetMicGainAction(AudioAdc *audio_adc) : audio_adc_(audio_adc) {} + + TEMPLATABLE_VALUE(float, mic_gain) + + void play(Ts... x) override { this->audio_adc_->set_mic_gain(this->mic_gain_.value(x...)); } + + protected: + AudioAdc *audio_adc_; +}; + +} // namespace audio_adc +} // namespace esphome diff --git a/esphome/components/bk72xx/__init__.py b/esphome/components/bk72xx/__init__.py index b5122de956..5b14d0529d 100644 --- a/esphome/components/bk72xx/__init__.py +++ b/esphome/components/bk72xx/__init__.py @@ -19,6 +19,7 @@ from .boards import BK72XX_BOARD_PINS, BK72XX_BOARDS CODEOWNERS = ["@kuba2k2"] AUTO_LOAD = ["libretiny"] +IS_TARGET_PLATFORM = True COMPONENT_DATA = LibreTinyComponent( name=COMPONENT_BK72XX, diff --git a/esphome/components/custom/__init__.py b/esphome/components/custom/__init__.py index 74450300f3..e69de29bb2 100644 --- a/esphome/components/custom/__init__.py +++ b/esphome/components/custom/__init__.py @@ -1,3 +0,0 @@ -import esphome.codegen as cg - -custom_ns = cg.esphome_ns.namespace("custom") diff --git a/esphome/components/custom/binary_sensor/__init__.py b/esphome/components/custom/binary_sensor/__init__.py index 8d6d621b3a..ca9747ea3e 100644 --- a/esphome/components/custom/binary_sensor/__init__.py +++ b/esphome/components/custom/binary_sensor/__init__.py @@ -1,31 +1,5 @@ -import esphome.codegen as cg import esphome.config_validation as cv -from esphome.components import binary_sensor -from esphome.const import CONF_BINARY_SENSORS, CONF_ID, CONF_LAMBDA -from .. import custom_ns -CustomBinarySensorConstructor = custom_ns.class_("CustomBinarySensorConstructor") - -CONFIG_SCHEMA = cv.Schema( - { - cv.GenerateID(): cv.declare_id(CustomBinarySensorConstructor), - cv.Required(CONF_LAMBDA): cv.returning_lambda, - cv.Required(CONF_BINARY_SENSORS): cv.ensure_list( - binary_sensor.binary_sensor_schema() - ), - } +CONFIG_SCHEMA = cv.invalid( + 'The "custom" component has been removed. Consider conversion to an external component.\nhttps://esphome.io/guides/contributing#a-note-about-custom-components' ) - - -async def to_code(config): - template_ = await cg.process_lambda( - config[CONF_LAMBDA], - [], - return_type=cg.std_vector.template(binary_sensor.BinarySensorPtr), - ) - - rhs = CustomBinarySensorConstructor(template_) - custom = cg.variable(config[CONF_ID], rhs) - for i, conf in enumerate(config[CONF_BINARY_SENSORS]): - rhs = custom.Pget_binary_sensor(i) - await binary_sensor.register_binary_sensor(rhs, conf) diff --git a/esphome/components/custom/binary_sensor/custom_binary_sensor.cpp b/esphome/components/custom/binary_sensor/custom_binary_sensor.cpp deleted file mode 100644 index ea83198568..0000000000 --- a/esphome/components/custom/binary_sensor/custom_binary_sensor.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "custom_binary_sensor.h" -#include "esphome/core/log.h" - -namespace esphome { -namespace custom { - -static const char *const TAG = "custom.binary_sensor"; - -void CustomBinarySensorConstructor::dump_config() { - for (auto *child : this->binary_sensors_) { - LOG_BINARY_SENSOR("", "Custom Binary Sensor", child); - } -} - -} // namespace custom -} // namespace esphome diff --git a/esphome/components/custom/binary_sensor/custom_binary_sensor.h b/esphome/components/custom/binary_sensor/custom_binary_sensor.h deleted file mode 100644 index b7d5458d9e..0000000000 --- a/esphome/components/custom/binary_sensor/custom_binary_sensor.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "esphome/core/component.h" -#include "esphome/components/binary_sensor/binary_sensor.h" - -#include - -namespace esphome { -namespace custom { - -class CustomBinarySensorConstructor : public Component { - public: - CustomBinarySensorConstructor(const std::function()> &init) { - this->binary_sensors_ = init(); - } - - binary_sensor::BinarySensor *get_binary_sensor(int i) { return this->binary_sensors_[i]; } - - void dump_config() override; - - protected: - std::vector binary_sensors_; -}; - -} // namespace custom -} // namespace esphome diff --git a/esphome/components/custom/climate/__init__.py b/esphome/components/custom/climate/__init__.py index a95456133a..ca9747ea3e 100644 --- a/esphome/components/custom/climate/__init__.py +++ b/esphome/components/custom/climate/__init__.py @@ -1,30 +1,5 @@ -import esphome.codegen as cg import esphome.config_validation as cv -from esphome.components import climate -from esphome.const import CONF_ID, CONF_LAMBDA -from .. import custom_ns -CustomClimateConstructor = custom_ns.class_("CustomClimateConstructor") -CONF_CLIMATES = "climates" - -CONFIG_SCHEMA = cv.Schema( - { - cv.GenerateID(): cv.declare_id(CustomClimateConstructor), - cv.Required(CONF_LAMBDA): cv.returning_lambda, - cv.Required(CONF_CLIMATES): cv.ensure_list(climate.CLIMATE_SCHEMA), - } +CONFIG_SCHEMA = cv.invalid( + 'The "custom" component has been removed. Consider conversion to an external component.\nhttps://esphome.io/guides/contributing#a-note-about-custom-components' ) - - -async def to_code(config): - template_ = await cg.process_lambda( - config[CONF_LAMBDA], - [], - return_type=cg.std_vector.template(climate.Climate.operator("ptr")), - ) - - rhs = CustomClimateConstructor(template_) - custom = cg.variable(config[CONF_ID], rhs) - for i, conf in enumerate(config[CONF_CLIMATES]): - rhs = custom.Pget_climate(i) - await climate.register_climate(rhs, conf) diff --git a/esphome/components/custom/climate/custom_climate.h b/esphome/components/custom/climate/custom_climate.h deleted file mode 100644 index 37876f7115..0000000000 --- a/esphome/components/custom/climate/custom_climate.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include "esphome/core/component.h" -#include "esphome/components/climate/climate.h" - -#include - -namespace esphome { -namespace custom { - -class CustomClimateConstructor { - public: - CustomClimateConstructor(const std::function()> &init) { this->climates_ = init(); } - - climate::Climate *get_climate(int i) { return this->climates_[i]; } - - protected: - std::vector climates_; -}; - -} // namespace custom -} // namespace esphome diff --git a/esphome/components/custom/cover/__init__.py b/esphome/components/custom/cover/__init__.py index 37fd4cdbbc..ca9747ea3e 100644 --- a/esphome/components/custom/cover/__init__.py +++ b/esphome/components/custom/cover/__init__.py @@ -1,30 +1,5 @@ -import esphome.codegen as cg import esphome.config_validation as cv -from esphome.components import cover -from esphome.const import CONF_ID, CONF_LAMBDA -from .. import custom_ns -CustomCoverConstructor = custom_ns.class_("CustomCoverConstructor") -CONF_COVERS = "covers" - -CONFIG_SCHEMA = cv.Schema( - { - cv.GenerateID(): cv.declare_id(CustomCoverConstructor), - cv.Required(CONF_LAMBDA): cv.returning_lambda, - cv.Required(CONF_COVERS): cv.ensure_list(cover.COVER_SCHEMA), - } +CONFIG_SCHEMA = cv.invalid( + 'The "custom" component has been removed. Consider conversion to an external component.\nhttps://esphome.io/guides/contributing#a-note-about-custom-components' ) - - -async def to_code(config): - template_ = await cg.process_lambda( - config[CONF_LAMBDA], - [], - return_type=cg.std_vector.template(cover.Cover.operator("ptr")), - ) - - rhs = CustomCoverConstructor(template_) - custom = cg.variable(config[CONF_ID], rhs) - for i, conf in enumerate(config[CONF_COVERS]): - rhs = custom.Pget_cover(i) - await cover.register_cover(rhs, conf) diff --git a/esphome/components/custom/cover/custom_cover.h b/esphome/components/custom/cover/custom_cover.h deleted file mode 100644 index 58330b9d54..0000000000 --- a/esphome/components/custom/cover/custom_cover.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "esphome/components/cover/cover.h" - -#include - -namespace esphome { -namespace custom { - -class CustomCoverConstructor { - public: - CustomCoverConstructor(const std::function()> &init) { this->covers_ = init(); } - - cover::Cover *get_cover(int i) { return this->covers_[i]; } - - protected: - std::vector covers_; -}; - -} // namespace custom -} // namespace esphome diff --git a/esphome/components/custom/light/__init__.py b/esphome/components/custom/light/__init__.py index b6ebe13ab2..ca9747ea3e 100644 --- a/esphome/components/custom/light/__init__.py +++ b/esphome/components/custom/light/__init__.py @@ -1,30 +1,5 @@ -import esphome.codegen as cg import esphome.config_validation as cv -from esphome.components import light -from esphome.const import CONF_ID, CONF_LAMBDA -from .. import custom_ns -CustomLightOutputConstructor = custom_ns.class_("CustomLightOutputConstructor") -CONF_LIGHTS = "lights" - -CONFIG_SCHEMA = cv.Schema( - { - cv.GenerateID(): cv.declare_id(CustomLightOutputConstructor), - cv.Required(CONF_LAMBDA): cv.returning_lambda, - cv.Required(CONF_LIGHTS): cv.ensure_list(light.ADDRESSABLE_LIGHT_SCHEMA), - } +CONFIG_SCHEMA = cv.invalid( + 'The "custom" component has been removed. Consider conversion to an external component.\nhttps://esphome.io/guides/contributing#a-note-about-custom-components' ) - - -async def to_code(config): - template_ = await cg.process_lambda( - config[CONF_LAMBDA], - [], - return_type=cg.std_vector.template(light.LightOutput.operator("ptr")), - ) - - rhs = CustomLightOutputConstructor(template_) - custom = cg.variable(config[CONF_ID], rhs) - for i, conf in enumerate(config[CONF_LIGHTS]): - rhs = custom.Pget_light(i) - await light.register_light(rhs, conf) diff --git a/esphome/components/custom/light/custom_light_output.h b/esphome/components/custom/light/custom_light_output.h deleted file mode 100644 index c2c83ebe97..0000000000 --- a/esphome/components/custom/light/custom_light_output.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "esphome/core/component.h" -#include "esphome/components/light/light_output.h" - -#include - -namespace esphome { -namespace custom { - -class CustomLightOutputConstructor { - public: - CustomLightOutputConstructor(const std::function()> &init) { - this->outputs_ = init(); - } - - light::LightOutput *get_light(int i) { return this->outputs_[i]; } - - protected: - std::vector outputs_; -}; - -} // namespace custom -} // namespace esphome diff --git a/esphome/components/custom/output/__init__.py b/esphome/components/custom/output/__init__.py index 97ef070fc3..ca9747ea3e 100644 --- a/esphome/components/custom/output/__init__.py +++ b/esphome/components/custom/output/__init__.py @@ -1,61 +1,5 @@ -import esphome.codegen as cg import esphome.config_validation as cv -from esphome.components import output -from esphome.const import CONF_ID, CONF_LAMBDA, CONF_OUTPUTS, CONF_TYPE, CONF_BINARY -from .. import custom_ns -CustomBinaryOutputConstructor = custom_ns.class_("CustomBinaryOutputConstructor") -CustomFloatOutputConstructor = custom_ns.class_("CustomFloatOutputConstructor") - -CONF_FLOAT = "float" - -CONFIG_SCHEMA = cv.typed_schema( - { - CONF_BINARY: cv.Schema( - { - cv.GenerateID(): cv.declare_id(CustomBinaryOutputConstructor), - cv.Required(CONF_LAMBDA): cv.returning_lambda, - cv.Required(CONF_OUTPUTS): cv.ensure_list( - output.BINARY_OUTPUT_SCHEMA.extend( - { - cv.GenerateID(): cv.declare_id(output.BinaryOutput), - } - ) - ), - } - ), - CONF_FLOAT: cv.Schema( - { - cv.GenerateID(): cv.declare_id(CustomFloatOutputConstructor), - cv.Required(CONF_LAMBDA): cv.returning_lambda, - cv.Required(CONF_OUTPUTS): cv.ensure_list( - output.FLOAT_OUTPUT_SCHEMA.extend( - { - cv.GenerateID(): cv.declare_id(output.FloatOutput), - } - ) - ), - } - ), - }, - lower=True, +CONFIG_SCHEMA = cv.invalid( + 'The "custom" component has been removed. Consider conversion to an external component.\nhttps://esphome.io/guides/contributing#a-note-about-custom-components' ) - - -async def to_code(config): - type = config[CONF_TYPE] - if type == "binary": - ret_type = output.BinaryOutputPtr - klass = CustomBinaryOutputConstructor - else: - ret_type = output.FloatOutputPtr - klass = CustomFloatOutputConstructor - template_ = await cg.process_lambda( - config[CONF_LAMBDA], [], return_type=cg.std_vector.template(ret_type) - ) - - rhs = klass(template_) - custom = cg.variable(config[CONF_ID], rhs) - for i, conf in enumerate(config[CONF_OUTPUTS]): - out = cg.Pvariable(conf[CONF_ID], custom.get_output(i)) - await output.register_output(out, conf) diff --git a/esphome/components/custom/output/custom_output.h b/esphome/components/custom/output/custom_output.h deleted file mode 100644 index 4624642420..0000000000 --- a/esphome/components/custom/output/custom_output.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include "esphome/core/component.h" -#include "esphome/components/output/binary_output.h" -#include "esphome/components/output/float_output.h" - -#include - -namespace esphome { -namespace custom { - -class CustomBinaryOutputConstructor { - public: - CustomBinaryOutputConstructor(const std::function()> &init) { - this->outputs_ = init(); - } - - output::BinaryOutput *get_output(int i) { return this->outputs_[i]; } - - protected: - std::vector outputs_; -}; - -class CustomFloatOutputConstructor { - public: - CustomFloatOutputConstructor(const std::function()> &init) { - this->outputs_ = init(); - } - - output::FloatOutput *get_output(int i) { return this->outputs_[i]; } - - protected: - std::vector outputs_; -}; - -} // namespace custom -} // namespace esphome diff --git a/esphome/components/custom/sensor/__init__.py b/esphome/components/custom/sensor/__init__.py index be17d9a334..ca9747ea3e 100644 --- a/esphome/components/custom/sensor/__init__.py +++ b/esphome/components/custom/sensor/__init__.py @@ -1,27 +1,5 @@ -import esphome.codegen as cg import esphome.config_validation as cv -from esphome.components import sensor -from esphome.const import CONF_ID, CONF_LAMBDA, CONF_SENSORS -from .. import custom_ns -CustomSensorConstructor = custom_ns.class_("CustomSensorConstructor") - -CONFIG_SCHEMA = cv.Schema( - { - cv.GenerateID(): cv.declare_id(CustomSensorConstructor), - cv.Required(CONF_LAMBDA): cv.returning_lambda, - cv.Required(CONF_SENSORS): cv.ensure_list(sensor.sensor_schema()), - } +CONFIG_SCHEMA = cv.invalid( + 'The "custom" component has been removed. Consider conversion to an external component.\nhttps://esphome.io/guides/contributing#a-note-about-custom-components' ) - - -async def to_code(config): - template_ = await cg.process_lambda( - config[CONF_LAMBDA], [], return_type=cg.std_vector.template(sensor.SensorPtr) - ) - - rhs = CustomSensorConstructor(template_) - var = cg.variable(config[CONF_ID], rhs) - for i, conf in enumerate(config[CONF_SENSORS]): - sens = cg.Pvariable(conf[CONF_ID], var.get_sensor(i)) - await sensor.register_sensor(sens, conf) diff --git a/esphome/components/custom/sensor/custom_sensor.cpp b/esphome/components/custom/sensor/custom_sensor.cpp deleted file mode 100644 index e670f09530..0000000000 --- a/esphome/components/custom/sensor/custom_sensor.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "custom_sensor.h" -#include "esphome/core/log.h" - -namespace esphome { -namespace custom { - -static const char *const TAG = "custom.sensor"; - -void CustomSensorConstructor::dump_config() { - for (auto *child : this->sensors_) { - LOG_SENSOR("", "Custom Sensor", child); - } -} - -} // namespace custom -} // namespace esphome diff --git a/esphome/components/custom/sensor/custom_sensor.h b/esphome/components/custom/sensor/custom_sensor.h deleted file mode 100644 index d8f4fbc109..0000000000 --- a/esphome/components/custom/sensor/custom_sensor.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "esphome/core/component.h" -#include "esphome/components/sensor/sensor.h" - -#include - -namespace esphome { -namespace custom { - -class CustomSensorConstructor : public Component { - public: - CustomSensorConstructor(const std::function()> &init) { this->sensors_ = init(); } - - sensor::Sensor *get_sensor(int i) { return this->sensors_[i]; } - - void dump_config() override; - - protected: - std::vector sensors_; -}; - -} // namespace custom -} // namespace esphome diff --git a/esphome/components/custom/switch/__init__.py b/esphome/components/custom/switch/__init__.py index 5538ae6aa0..ca9747ea3e 100644 --- a/esphome/components/custom/switch/__init__.py +++ b/esphome/components/custom/switch/__init__.py @@ -1,27 +1,5 @@ -import esphome.codegen as cg import esphome.config_validation as cv -from esphome.components import switch -from esphome.const import CONF_ID, CONF_LAMBDA, CONF_SWITCHES -from .. import custom_ns -CustomSwitchConstructor = custom_ns.class_("CustomSwitchConstructor") - -CONFIG_SCHEMA = cv.Schema( - { - cv.GenerateID(): cv.declare_id(CustomSwitchConstructor), - cv.Required(CONF_LAMBDA): cv.returning_lambda, - cv.Required(CONF_SWITCHES): cv.ensure_list(switch.switch_schema(switch.Switch)), - } +CONFIG_SCHEMA = cv.invalid( + 'The "custom" component has been removed. Consider conversion to an external component.\nhttps://esphome.io/guides/contributing#a-note-about-custom-components' ) - - -async def to_code(config): - template_ = await cg.process_lambda( - config[CONF_LAMBDA], [], return_type=cg.std_vector.template(switch.SwitchPtr) - ) - - rhs = CustomSwitchConstructor(template_) - var = cg.variable(config[CONF_ID], rhs) - for i, conf in enumerate(config[CONF_SWITCHES]): - switch_ = cg.Pvariable(conf[CONF_ID], var.get_switch(i)) - await switch.register_switch(switch_, conf) diff --git a/esphome/components/custom/switch/custom_switch.cpp b/esphome/components/custom/switch/custom_switch.cpp deleted file mode 100644 index 6d0a8fa621..0000000000 --- a/esphome/components/custom/switch/custom_switch.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "custom_switch.h" -#include "esphome/core/log.h" - -namespace esphome { -namespace custom { - -static const char *const TAG = "custom.switch"; - -void CustomSwitchConstructor::dump_config() { - for (auto *child : this->switches_) { - LOG_SWITCH("", "Custom Switch", child); - } -} - -} // namespace custom -} // namespace esphome diff --git a/esphome/components/custom/switch/custom_switch.h b/esphome/components/custom/switch/custom_switch.h deleted file mode 100644 index 9657e4b44d..0000000000 --- a/esphome/components/custom/switch/custom_switch.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "esphome/core/component.h" -#include "esphome/components/switch/switch.h" - -#include - -namespace esphome { -namespace custom { - -class CustomSwitchConstructor : public Component { - public: - CustomSwitchConstructor(const std::function()> &init) { this->switches_ = init(); } - - switch_::Switch *get_switch(int i) { return this->switches_[i]; } - - void dump_config() override; - - protected: - std::vector switches_; -}; - -} // namespace custom -} // namespace esphome diff --git a/esphome/components/custom/text_sensor/__init__.py b/esphome/components/custom/text_sensor/__init__.py index 70728af604..ca9747ea3e 100644 --- a/esphome/components/custom/text_sensor/__init__.py +++ b/esphome/components/custom/text_sensor/__init__.py @@ -1,32 +1,5 @@ -import esphome.codegen as cg import esphome.config_validation as cv -from esphome.components import text_sensor -from esphome.const import CONF_ID, CONF_LAMBDA, CONF_TEXT_SENSORS -from .. import custom_ns -CustomTextSensorConstructor = custom_ns.class_("CustomTextSensorConstructor") - -CONFIG_SCHEMA = cv.Schema( - { - cv.GenerateID(): cv.declare_id(CustomTextSensorConstructor), - cv.Required(CONF_LAMBDA): cv.returning_lambda, - cv.Required(CONF_TEXT_SENSORS): cv.ensure_list( - text_sensor.text_sensor_schema() - ), - } +CONFIG_SCHEMA = cv.invalid( + 'The "custom" component has been removed. Consider conversion to an external component.\nhttps://esphome.io/guides/contributing#a-note-about-custom-components' ) - - -async def to_code(config): - template_ = await cg.process_lambda( - config[CONF_LAMBDA], - [], - return_type=cg.std_vector.template(text_sensor.TextSensorPtr), - ) - - rhs = CustomTextSensorConstructor(template_) - var = cg.variable(config[CONF_ID], rhs) - - for i, conf in enumerate(config[CONF_TEXT_SENSORS]): - text = cg.Pvariable(conf[CONF_ID], var.get_text_sensor(i)) - await text_sensor.register_text_sensor(text, conf) diff --git a/esphome/components/custom/text_sensor/custom_text_sensor.cpp b/esphome/components/custom/text_sensor/custom_text_sensor.cpp deleted file mode 100644 index 618ba832a5..0000000000 --- a/esphome/components/custom/text_sensor/custom_text_sensor.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "custom_text_sensor.h" -#include "esphome/core/log.h" - -namespace esphome { -namespace custom { - -static const char *const TAG = "custom.text_sensor"; - -void CustomTextSensorConstructor::dump_config() { - for (auto *child : this->text_sensors_) { - LOG_TEXT_SENSOR("", "Custom Text Sensor", child); - } -} - -} // namespace custom -} // namespace esphome diff --git a/esphome/components/custom/text_sensor/custom_text_sensor.h b/esphome/components/custom/text_sensor/custom_text_sensor.h deleted file mode 100644 index 13732c00b6..0000000000 --- a/esphome/components/custom/text_sensor/custom_text_sensor.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "esphome/core/component.h" -#include "esphome/components/text_sensor/text_sensor.h" - -#include - -namespace esphome { -namespace custom { - -class CustomTextSensorConstructor : public Component { - public: - CustomTextSensorConstructor(const std::function()> &init) { - this->text_sensors_ = init(); - } - - text_sensor::TextSensor *get_text_sensor(int i) { return this->text_sensors_[i]; } - - void dump_config() override; - - protected: - std::vector text_sensors_; -}; - -} // namespace custom -} // namespace esphome diff --git a/esphome/components/custom_component/__init__.py b/esphome/components/custom_component/__init__.py index d41dd7ea59..982153414d 100644 --- a/esphome/components/custom_component/__init__.py +++ b/esphome/components/custom_component/__init__.py @@ -1,31 +1,7 @@ -import esphome.codegen as cg import esphome.config_validation as cv -from esphome.const import CONF_COMPONENTS, CONF_ID, CONF_LAMBDA - -custom_component_ns = cg.esphome_ns.namespace("custom_component") -CustomComponentConstructor = custom_component_ns.class_("CustomComponentConstructor") MULTI_CONF = True -CONFIG_SCHEMA = cv.Schema( - { - cv.GenerateID(): cv.declare_id(CustomComponentConstructor), - cv.Required(CONF_LAMBDA): cv.returning_lambda, - cv.Optional(CONF_COMPONENTS): cv.ensure_list( - cv.Schema({cv.GenerateID(): cv.declare_id(cg.Component)}).extend( - cv.COMPONENT_SCHEMA - ) - ), - } + +CONFIG_SCHEMA = cv.invalid( + 'The "custom" component has been removed. Consider conversion to an external component.\nhttps://esphome.io/guides/contributing#a-note-about-custom-components' ) - - -async def to_code(config): - template_ = await cg.process_lambda( - config[CONF_LAMBDA], [], return_type=cg.std_vector.template(cg.ComponentPtr) - ) - - rhs = CustomComponentConstructor(template_) - var = cg.variable(config[CONF_ID], rhs) - for i, conf in enumerate(config.get(CONF_COMPONENTS, [])): - comp = cg.Pvariable(conf[CONF_ID], var.get_component(i)) - await cg.register_component(comp, conf) diff --git a/esphome/components/custom_component/custom_component.h b/esphome/components/custom_component/custom_component.h deleted file mode 100644 index 3b34019a7a..0000000000 --- a/esphome/components/custom_component/custom_component.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include "esphome/core/component.h" -#include "esphome/core/application.h" - -#include - -namespace esphome { -namespace custom_component { - -class CustomComponentConstructor { - public: - CustomComponentConstructor(const std::function()> &init) { - this->components_ = init(); - - for (auto *comp : this->components_) { - App.register_component(comp); - } - } - - Component *get_component(int i) const { return this->components_[i]; } - - protected: - std::vector components_; -}; - -} // namespace custom_component -} // namespace esphome diff --git a/esphome/components/daly_bms/daly_bms.cpp b/esphome/components/daly_bms/daly_bms.cpp index 8f6fc0fb57..929f31e008 100644 --- a/esphome/components/daly_bms/daly_bms.cpp +++ b/esphome/components/daly_bms/daly_bms.cpp @@ -298,6 +298,12 @@ void DalyBmsComponent::decode_data_(std::vector data) { if (this->cell_16_voltage_sensor_) { this->cell_16_voltage_sensor_->publish_state((float) encode_uint16(it[5], it[6]) / 1000); } + if (this->cell_17_voltage_sensor_) { + this->cell_17_voltage_sensor_->publish_state((float) encode_uint16(it[7], it[8]) / 1000); + } + if (this->cell_18_voltage_sensor_) { + this->cell_18_voltage_sensor_->publish_state((float) encode_uint16(it[9], it[10]) / 1000); + } break; } break; diff --git a/esphome/components/daly_bms/daly_bms.h b/esphome/components/daly_bms/daly_bms.h index 52ea30ecde..e6d476bcdd 100644 --- a/esphome/components/daly_bms/daly_bms.h +++ b/esphome/components/daly_bms/daly_bms.h @@ -54,6 +54,8 @@ class DalyBmsComponent : public PollingComponent, public uart::UARTDevice { SUB_SENSOR(cell_14_voltage) SUB_SENSOR(cell_15_voltage) SUB_SENSOR(cell_16_voltage) + SUB_SENSOR(cell_17_voltage) + SUB_SENSOR(cell_18_voltage) #endif #ifdef USE_TEXT_SENSOR diff --git a/esphome/components/daly_bms/sensor.py b/esphome/components/daly_bms/sensor.py index c447fbd8a2..6d78946a02 100644 --- a/esphome/components/daly_bms/sensor.py +++ b/esphome/components/daly_bms/sensor.py @@ -52,6 +52,8 @@ CONF_CELL_13_VOLTAGE = "cell_13_voltage" CONF_CELL_14_VOLTAGE = "cell_14_voltage" CONF_CELL_15_VOLTAGE = "cell_15_voltage" CONF_CELL_16_VOLTAGE = "cell_16_voltage" +CONF_CELL_17_VOLTAGE = "cell_17_voltage" +CONF_CELL_18_VOLTAGE = "cell_18_voltage" ICON_CURRENT_DC = "mdi:current-dc" ICON_BATTERY_OUTLINE = "mdi:battery-outline" ICON_THERMOMETER_CHEVRON_UP = "mdi:thermometer-chevron-up" @@ -92,6 +94,8 @@ TYPES = [ CONF_CELL_14_VOLTAGE, CONF_CELL_15_VOLTAGE, CONF_CELL_16_VOLTAGE, + CONF_CELL_17_VOLTAGE, + CONF_CELL_18_VOLTAGE, ] CELL_VOLTAGE_SCHEMA = sensor.sensor_schema( @@ -212,6 +216,8 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_CELL_14_VOLTAGE): CELL_VOLTAGE_SCHEMA, cv.Optional(CONF_CELL_15_VOLTAGE): CELL_VOLTAGE_SCHEMA, cv.Optional(CONF_CELL_16_VOLTAGE): CELL_VOLTAGE_SCHEMA, + cv.Optional(CONF_CELL_17_VOLTAGE): CELL_VOLTAGE_SCHEMA, + cv.Optional(CONF_CELL_18_VOLTAGE): CELL_VOLTAGE_SCHEMA, } ).extend(cv.COMPONENT_SCHEMA) ) diff --git a/esphome/components/debug/debug_esp32.cpp b/esphome/components/debug/debug_esp32.cpp index 69ae7e3678..caa9f8d743 100644 --- a/esphome/components/debug/debug_esp32.cpp +++ b/esphome/components/debug/debug_esp32.cpp @@ -35,8 +35,8 @@ void DebugComponent::log_partition_info_() { esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_ANY, NULL); while (it != NULL) { const esp_partition_t *partition = esp_partition_get(it); - ESP_LOGCONFIG(TAG, " %-12s %-4d %-8d 0x%08X 0x%08X", partition->label, partition->type, partition->subtype, - partition->address, partition->size); + ESP_LOGCONFIG(TAG, " %-12s %-4d %-8d 0x%08" PRIX32 " 0x%08" PRIX32, partition->label, partition->type, + partition->subtype, partition->address, partition->size); it = esp_partition_next(it); } esp_partition_iterator_release(it); diff --git a/esphome/components/es7210/__init__.py b/esphome/components/es7210/__init__.py index 8e63d7f04f..e69de29bb2 100644 --- a/esphome/components/es7210/__init__.py +++ b/esphome/components/es7210/__init__.py @@ -1,67 +0,0 @@ -import esphome.codegen as cg -from esphome.components import i2c -import esphome.config_validation as cv -from esphome.const import CONF_BITS_PER_SAMPLE, CONF_ID, CONF_MIC_GAIN, CONF_SAMPLE_RATE - -CODEOWNERS = ["@kahrendt"] -DEPENDENCIES = ["i2c"] - -es7210_ns = cg.esphome_ns.namespace("es7210") -ES7210 = es7210_ns.class_("ES7210", cg.Component, i2c.I2CDevice) - - -es7210_bits_per_sample = es7210_ns.enum("ES7210BitsPerSample") -ES7210_BITS_PER_SAMPLE_ENUM = { - 16: es7210_bits_per_sample.ES7210_BITS_PER_SAMPLE_16, - 24: es7210_bits_per_sample.ES7210_BITS_PER_SAMPLE_24, - 32: es7210_bits_per_sample.ES7210_BITS_PER_SAMPLE_32, -} - - -es7210_mic_gain = es7210_ns.enum("ES7210MicGain") -ES7210_MIC_GAIN_ENUM = { - "0DB": es7210_mic_gain.ES7210_MIC_GAIN_0DB, - "3DB": es7210_mic_gain.ES7210_MIC_GAIN_3DB, - "6DB": es7210_mic_gain.ES7210_MIC_GAIN_6DB, - "9DB": es7210_mic_gain.ES7210_MIC_GAIN_9DB, - "12DB": es7210_mic_gain.ES7210_MIC_GAIN_12DB, - "15DB": es7210_mic_gain.ES7210_MIC_GAIN_15DB, - "18DB": es7210_mic_gain.ES7210_MIC_GAIN_18DB, - "21DB": es7210_mic_gain.ES7210_MIC_GAIN_21DB, - "24DB": es7210_mic_gain.ES7210_MIC_GAIN_24DB, - "27DB": es7210_mic_gain.ES7210_MIC_GAIN_27DB, - "30DB": es7210_mic_gain.ES7210_MIC_GAIN_30DB, - "33DB": es7210_mic_gain.ES7210_MIC_GAIN_33DB, - "34.5DB": es7210_mic_gain.ES7210_MIC_GAIN_34_5DB, - "36DB": es7210_mic_gain.ES7210_MIC_GAIN_36DB, - "37.5DB": es7210_mic_gain.ES7210_MIC_GAIN_37_5DB, -} - -_validate_bits = cv.float_with_unit("bits", "bit") - -CONFIG_SCHEMA = ( - cv.Schema( - { - cv.GenerateID(): cv.declare_id(ES7210), - cv.Optional(CONF_BITS_PER_SAMPLE, default="16bit"): cv.All( - _validate_bits, cv.enum(ES7210_BITS_PER_SAMPLE_ENUM) - ), - cv.Optional(CONF_MIC_GAIN, default="24DB"): cv.enum( - ES7210_MIC_GAIN_ENUM, upper=True - ), - cv.Optional(CONF_SAMPLE_RATE, default=16000): cv.int_range(min=1), - } - ) - .extend(cv.COMPONENT_SCHEMA) - .extend(i2c.i2c_device_schema(0x40)) -) - - -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_bits_per_sample(config[CONF_BITS_PER_SAMPLE])) - cg.add(var.set_mic_gain(config[CONF_MIC_GAIN])) - cg.add(var.set_sample_rate(config[CONF_SAMPLE_RATE])) diff --git a/esphome/components/es7210/audio_adc.py b/esphome/components/es7210/audio_adc.py new file mode 100644 index 0000000000..f0bd8bc25a --- /dev/null +++ b/esphome/components/es7210/audio_adc.py @@ -0,0 +1,51 @@ +import esphome.codegen as cg +from esphome.components import i2c +from esphome.components.audio_adc import AudioAdc +import esphome.config_validation as cv +from esphome.const import CONF_BITS_PER_SAMPLE, CONF_ID, CONF_MIC_GAIN, CONF_SAMPLE_RATE + +CODEOWNERS = ["@kahrendt"] +DEPENDENCIES = ["i2c"] + +es7210_ns = cg.esphome_ns.namespace("es7210") +ES7210 = es7210_ns.class_("ES7210", AudioAdc, cg.Component, i2c.I2CDevice) + + +es7210_bits_per_sample = es7210_ns.enum("ES7210BitsPerSample") +ES7210_BITS_PER_SAMPLE_ENUM = { + 16: es7210_bits_per_sample.ES7210_BITS_PER_SAMPLE_16, + 24: es7210_bits_per_sample.ES7210_BITS_PER_SAMPLE_24, + 32: es7210_bits_per_sample.ES7210_BITS_PER_SAMPLE_32, +} + + +ES7210_MIC_GAINS = [0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 34.5, 36, 37.5] + +_validate_bits = cv.float_with_unit("bits", "bit") + +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(ES7210), + cv.Optional(CONF_BITS_PER_SAMPLE, default="16bit"): cv.All( + _validate_bits, cv.enum(ES7210_BITS_PER_SAMPLE_ENUM) + ), + cv.Optional(CONF_MIC_GAIN, default="24db"): cv.All( + cv.decibel, cv.one_of(*ES7210_MIC_GAINS) + ), + cv.Optional(CONF_SAMPLE_RATE, default=16000): cv.int_range(min=1), + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(i2c.i2c_device_schema(0x40)) +) + + +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_bits_per_sample(config[CONF_BITS_PER_SAMPLE])) + cg.add(var.set_mic_gain(config[CONF_MIC_GAIN])) + cg.add(var.set_sample_rate(config[CONF_SAMPLE_RATE])) diff --git a/esphome/components/es7210/es7210.cpp b/esphome/components/es7210/es7210.cpp index d2f2c3c1ff..9a99e60995 100644 --- a/esphome/components/es7210/es7210.cpp +++ b/esphome/components/es7210/es7210.cpp @@ -25,12 +25,12 @@ static const size_t MCLK_DIV_FRE = 256; } void ES7210::dump_config() { - ESP_LOGCONFIG(TAG, "ES7210 ADC:"); + ESP_LOGCONFIG(TAG, "ES7210 audio ADC:"); ESP_LOGCONFIG(TAG, " Bits Per Sample: %" PRIu8, this->bits_per_sample_); ESP_LOGCONFIG(TAG, " Sample Rate: %" PRIu32, this->sample_rate_); if (this->is_failed()) { - ESP_LOGCONFIG(TAG, " Failed to initialize!"); + ESP_LOGE(TAG, " Failed to initialize"); return; } } @@ -84,6 +84,16 @@ void ES7210::setup() { // Enable device ES7210_ERROR_FAILED(this->write_byte(ES7210_RESET_REG00, 0x71)); ES7210_ERROR_FAILED(this->write_byte(ES7210_RESET_REG00, 0x41)); + + this->setup_complete_ = true; +} + +bool ES7210::set_mic_gain(float mic_gain) { + this->mic_gain_ = clamp(mic_gain, ES7210_MIC_GAIN_MIN, ES7210_MIC_GAIN_MAX); + if (this->setup_complete_) { + return this->configure_mic_gain_(); + } + return true; } bool ES7210::configure_sample_rate_() { @@ -122,9 +132,11 @@ bool ES7210::configure_sample_rate_() { return true; } + bool ES7210::configure_mic_gain_() { - for (int i = 0; i < 4; ++i) { - this->es7210_update_reg_bit_(ES7210_MIC1_GAIN_REG43 + i, 0x10, 0x00); + auto regv = this->es7210_gain_reg_value_(this->mic_gain_); + for (uint8_t i = 0; i < 4; ++i) { + ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC1_GAIN_REG43 + i, 0x10, 0x00)); } ES7210_ERROR_CHECK(this->write_byte(ES7210_MIC12_POWER_REG4B, 0xff)); ES7210_ERROR_CHECK(this->write_byte(ES7210_MIC34_POWER_REG4C, 0xff)); @@ -133,29 +145,44 @@ bool ES7210::configure_mic_gain_() { ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_CLOCK_OFF_REG01, 0x0b, 0x00)); ES7210_ERROR_CHECK(this->write_byte(ES7210_MIC12_POWER_REG4B, 0x00)); ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC1_GAIN_REG43, 0x10, 0x10)); - ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC1_GAIN_REG43, 0x0f, this->mic_gain_)); + ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC1_GAIN_REG43, 0x0f, regv)); // Configure mic 2 ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_CLOCK_OFF_REG01, 0x0b, 0x00)); ES7210_ERROR_CHECK(this->write_byte(ES7210_MIC12_POWER_REG4B, 0x00)); ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC2_GAIN_REG44, 0x10, 0x10)); - ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC2_GAIN_REG44, 0x0f, this->mic_gain_)); + ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC2_GAIN_REG44, 0x0f, regv)); // Configure mic 3 ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_CLOCK_OFF_REG01, 0x0b, 0x00)); ES7210_ERROR_CHECK(this->write_byte(ES7210_MIC34_POWER_REG4C, 0x00)); ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC3_GAIN_REG45, 0x10, 0x10)); - ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC3_GAIN_REG45, 0x0f, this->mic_gain_)); + ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC3_GAIN_REG45, 0x0f, regv)); // Configure mic 4 ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_CLOCK_OFF_REG01, 0x0b, 0x00)); ES7210_ERROR_CHECK(this->write_byte(ES7210_MIC34_POWER_REG4C, 0x00)); ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC4_GAIN_REG46, 0x10, 0x10)); - ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC4_GAIN_REG46, 0x0f, this->mic_gain_)); + ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC4_GAIN_REG46, 0x0f, regv)); return true; } +uint8_t ES7210::es7210_gain_reg_value_(float mic_gain) { + // reg: 12 - 34.5dB, 13 - 36dB, 14 - 37.5dB + mic_gain += 0.5; + if (mic_gain <= 33.0) { + return (uint8_t) mic_gain / 3; + } + if (mic_gain < 36.0) { + return 12; + } + if (mic_gain < 37.0) { + return 13; + } + return 14; +} + bool ES7210::configure_i2s_format_() { // Configure bits per sample uint8_t reg_val = 0; diff --git a/esphome/components/es7210/es7210.h b/esphome/components/es7210/es7210.h index a40dde5aa5..8f6d9d8136 100644 --- a/esphome/components/es7210/es7210.h +++ b/esphome/components/es7210/es7210.h @@ -1,8 +1,11 @@ #pragma once +#include "esphome/components/audio_adc/audio_adc.h" #include "esphome/components/i2c/i2c.h" #include "esphome/core/component.h" +#include "es7210_const.h" + namespace esphome { namespace es7210 { @@ -14,25 +17,7 @@ enum ES7210BitsPerSample : uint8_t { ES7210_BITS_PER_SAMPLE_32 = 32, }; -enum ES7210MicGain : uint8_t { - ES7210_MIC_GAIN_0DB = 0, - ES7210_MIC_GAIN_3DB, - ES7210_MIC_GAIN_6DB, - ES7210_MIC_GAIN_9DB, - ES7210_MIC_GAIN_12DB, - ES7210_MIC_GAIN_15DB, - ES7210_MIC_GAIN_18DB, - ES7210_MIC_GAIN_21DB, - ES7210_MIC_GAIN_24DB, - ES7210_MIC_GAIN_27DB, - ES7210_MIC_GAIN_30DB, - ES7210_MIC_GAIN_33DB, - ES7210_MIC_GAIN_34_5DB, - ES7210_MIC_GAIN_36DB, - ES7210_MIC_GAIN_37_5DB, -}; - -class ES7210 : public Component, public i2c::I2CDevice { +class ES7210 : public audio_adc::AudioAdc, public Component, public i2c::I2CDevice { /* Class for configuring an ES7210 ADC for microphone input. * Based on code from: * - https://github.com/espressif/esp-bsp/ (accessed 20241219) @@ -44,9 +29,11 @@ class ES7210 : public Component, public i2c::I2CDevice { void dump_config() override; void set_bits_per_sample(ES7210BitsPerSample bits_per_sample) { this->bits_per_sample_ = bits_per_sample; } - void set_mic_gain(ES7210MicGain mic_gain) { this->mic_gain_ = mic_gain; } + bool set_mic_gain(float mic_gain) override; void set_sample_rate(uint32_t sample_rate) { this->sample_rate_ = sample_rate; } + float mic_gain() override { return this->mic_gain_; }; + protected: /// @brief Updates an I2C registry address by modifying the current state /// @param reg_addr I2C register address @@ -55,14 +42,20 @@ class ES7210 : public Component, public i2c::I2CDevice { /// @return True if successful, false otherwise bool es7210_update_reg_bit_(uint8_t reg_addr, uint8_t update_bits, uint8_t data); + /// @brief Convert floating point mic gain value to register value + /// @param mic_gain Gain value to convert + /// @return Corresponding register value for specified gain + uint8_t es7210_gain_reg_value_(float mic_gain); + bool configure_i2s_format_(); bool configure_mic_gain_(); bool configure_sample_rate_(); + bool setup_complete_{false}; bool enable_tdm_{false}; // TDM is unsupported in ESPHome as of version 2024.12 - ES7210MicGain mic_gain_; - ES7210BitsPerSample bits_per_sample_; - uint32_t sample_rate_; + float mic_gain_{0}; + ES7210BitsPerSample bits_per_sample_{ES7210_BITS_PER_SAMPLE_16}; + uint32_t sample_rate_{0}; }; } // namespace es7210 diff --git a/esphome/components/es7210/es7210_const.h b/esphome/components/es7210/es7210_const.h index 87fd6d86d2..e5ffea5743 100644 --- a/esphome/components/es7210/es7210_const.h +++ b/esphome/components/es7210/es7210_const.h @@ -1,6 +1,6 @@ #pragma once -#include "es7210.h" +#include namespace esphome { namespace es7210 { @@ -42,7 +42,7 @@ static const uint8_t ES7210_MIC12_POWER_REG4B = 0x4B; /* MICBias & ADC & PGA Pow static const uint8_t ES7210_MIC34_POWER_REG4C = 0x4C; /* - * Clock coefficient structer + * Clock coefficient structure */ struct ES7210Coefficient { uint32_t mclk; // mclk frequency @@ -122,5 +122,8 @@ static const ES7210Coefficient ES7210_COEFFICIENTS[] = { {19200000, 96000, 0x01, 0x05, 0x00, 0x01, 0x28, 0x00, 0x00, 0xc8}, }; +static const float ES7210_MIC_GAIN_MIN = 0.0; +static const float ES7210_MIC_GAIN_MAX = 37.5; + } // namespace es7210 } // namespace esphome diff --git a/esphome/components/es7243e/__init__.py b/esphome/components/es7243e/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/es7243e/audio_adc.py b/esphome/components/es7243e/audio_adc.py new file mode 100644 index 0000000000..c305d60172 --- /dev/null +++ b/esphome/components/es7243e/audio_adc.py @@ -0,0 +1,34 @@ +import esphome.codegen as cg +from esphome.components import i2c +from esphome.components.audio_adc import AudioAdc +import esphome.config_validation as cv +from esphome.const import CONF_ID, CONF_MIC_GAIN + +CODEOWNERS = ["@kbx81"] +DEPENDENCIES = ["i2c"] + +es7243e_ns = cg.esphome_ns.namespace("es7243e") +ES7243E = es7243e_ns.class_("ES7243E", AudioAdc, cg.Component, i2c.I2CDevice) + +ES7243E_MIC_GAINS = [0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 34.5, 36, 37.5] + +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(ES7243E), + cv.Optional(CONF_MIC_GAIN, default="24db"): cv.All( + cv.decibel, cv.one_of(*ES7243E_MIC_GAINS) + ), + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(i2c.i2c_device_schema(0x10)) +) + + +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_mic_gain(config[CONF_MIC_GAIN])) diff --git a/esphome/components/es7243e/es7243e.cpp b/esphome/components/es7243e/es7243e.cpp new file mode 100644 index 0000000000..ce65ce973e --- /dev/null +++ b/esphome/components/es7243e/es7243e.cpp @@ -0,0 +1,125 @@ +#include "es7243e.h" +#include "es7243e_const.h" + +#include "esphome/core/hal.h" +#include "esphome/core/log.h" + +#include + +namespace esphome { +namespace es7243e { + +static const char *const TAG = "es7243e"; + +// Mark the component as failed; use only in setup +#define ES7243E_ERROR_FAILED(func) \ + if (!(func)) { \ + this->mark_failed(); \ + return; \ + } + +// Return false; use outside of setup +#define ES7243E_ERROR_CHECK(func) \ + if (!(func)) { \ + return false; \ + } + +void ES7243E::dump_config() { + ESP_LOGCONFIG(TAG, "ES7243E audio ADC:"); + + if (this->is_failed()) { + ESP_LOGE(TAG, " Failed to initialize"); + return; + } +} + +void ES7243E::setup() { + ESP_LOGCONFIG(TAG, "Setting up ES7243E..."); + + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG01, 0x3A)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_RESET_REG00, 0x80)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_TEST_MODE_REGF9, 0x00)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG04, 0x02)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG04, 0x01)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_TEST_MODE_REGF9, 0x01)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_RESET_REG00, 0x1E)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG01, 0x00)); + + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG02, 0x00)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG03, 0x20)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG04, 0x01)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ADC_CTRL_REG0D, 0x00)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG05, 0x00)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG06, 0x03)); // SCLK=MCLK/4 + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG07, 0x00)); // LRCK=MCLK/256 + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG08, 0xFF)); // LRCK=MCLK/256 + + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG09, 0xCA)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_SDP_REG0A, 0x85)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_SDP_REG0B, 0x00)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ADC_CTRL_REG0E, 0xBF)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ADC_CTRL_REG0F, 0x80)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ADC_CTRL_REG14, 0x0C)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ADC_CTRL_REG15, 0x0C)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG17, 0x02)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG18, 0x26)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG19, 0x77)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG1A, 0xF4)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG1B, 0x66)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG1C, 0x44)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG1E, 0x00)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG1F, 0x0C)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG20, 0x1A)); // PGA gain +30dB + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG21, 0x1A)); + + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_RESET_REG00, 0x80)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG01, 0x3A)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG16, 0x3F)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG16, 0x00)); + + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_TEST_MODE_REGF9, 0x00)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG04, 0x01)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG17, 0x01)); + ES7243E_ERROR_FAILED(this->configure_mic_gain_()); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_RESET_REG00, 0x80)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG01, 0x3A)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG16, 0x3F)); + ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG16, 0x00)); + + this->setup_complete_ = true; +} + +bool ES7243E::set_mic_gain(float mic_gain) { + this->mic_gain_ = clamp(mic_gain, 0, 37.5); + if (this->setup_complete_) { + return this->configure_mic_gain_(); + } + return true; +} + +bool ES7243E::configure_mic_gain_() { + auto regv = this->es7243e_gain_reg_value_(this->mic_gain_); + + ES7243E_ERROR_CHECK(this->write_byte(ES7243E_ANALOG_REG20, 0x10 | regv)); + ES7243E_ERROR_CHECK(this->write_byte(ES7243E_ANALOG_REG21, 0x10 | regv)); + + return true; +} + +uint8_t ES7243E::es7243e_gain_reg_value_(float mic_gain) { + // reg: 12 - 34.5dB, 13 - 36dB, 14 - 37.5dB + mic_gain += 0.5; + if (mic_gain <= 33.0) { + return (uint8_t) mic_gain / 3; + } + if (mic_gain < 36.0) { + return 12; + } + if (mic_gain < 37.0) { + return 13; + } + return 14; +} + +} // namespace es7243e +} // namespace esphome diff --git a/esphome/components/es7243e/es7243e.h b/esphome/components/es7243e/es7243e.h new file mode 100644 index 0000000000..41a8acac8d --- /dev/null +++ b/esphome/components/es7243e/es7243e.h @@ -0,0 +1,37 @@ +#pragma once + +#include "esphome/components/audio_adc/audio_adc.h" +#include "esphome/components/i2c/i2c.h" +#include "esphome/core/component.h" + +namespace esphome { +namespace es7243e { + +class ES7243E : public audio_adc::AudioAdc, public Component, public i2c::I2CDevice { + /* Class for configuring an ES7243E ADC for microphone input. + * Based on code from: + * - https://github.com/espressif/esp-adf/ (accessed 20250116) + */ + public: + void setup() override; + float get_setup_priority() const override { return setup_priority::DATA; } + void dump_config() override; + + bool set_mic_gain(float mic_gain) override; + + float mic_gain() override { return this->mic_gain_; }; + + protected: + /// @brief Convert floating point mic gain value to register value + /// @param mic_gain Gain value to convert + /// @return Corresponding register value for specified gain + uint8_t es7243e_gain_reg_value_(float mic_gain); + + bool configure_mic_gain_(); + + bool setup_complete_{false}; + float mic_gain_{0}; +}; + +} // namespace es7243e +} // namespace esphome diff --git a/esphome/components/es7243e/es7243e_const.h b/esphome/components/es7243e/es7243e_const.h new file mode 100644 index 0000000000..daae53a108 --- /dev/null +++ b/esphome/components/es7243e/es7243e_const.h @@ -0,0 +1,54 @@ +#pragma once + +#include + +namespace esphome { +namespace es7243e { + +// ES7243E register addresses +static const uint8_t ES7243E_RESET_REG00 = 0x00; // Reset control +static const uint8_t ES7243E_CLOCK_MGR_REG01 = 0x01; // MCLK/BCLK/ADCCLK/Analog clocks on/off +static const uint8_t ES7243E_CLOCK_MGR_REG02 = 0x02; // MCLK & BCLK configuration, source selection + +static const uint8_t ES7243E_CLOCK_MGR_REG03 = 0x03; // ADC Over-sample rate control +static const uint8_t ES7243E_CLOCK_MGR_REG04 = 0x04; // Pre-divide/Pre-multiplication +static const uint8_t ES7243E_CLOCK_MGR_REG05 = 0x05; // CF/DSP clock divider +static const uint8_t ES7243E_CLOCK_MGR_REG06 = 0x06; // BCLK divider at master mode +static const uint8_t ES7243E_CLOCK_MGR_REG07 = 0x07; // BCLK/LRCK/SDOUT tri-state control/LRCK divider bit 11->8 +static const uint8_t ES7243E_CLOCK_MGR_REG08 = 0x08; // Master LRCK divider bit 7 to bit 0 +static const uint8_t ES7243E_CLOCK_MGR_REG09 = 0x09; // SEL S1/Timer for S1 +static const uint8_t ES7243E_SDP_REG0A = 0x0A; // SEL S3/Timer for S3 +static const uint8_t ES7243E_SDP_REG0B = 0x0B; // SDP out mute control/I2S/left-justify case/word length/format +static const uint8_t ES7243E_SDP_REG0C = 0x0C; // NFS flag at slot0/LSB/TDM mode selection +static const uint8_t ES7243E_ADC_CTRL_REG0D = 0x0D; // data mux/pol. inv./ram clear on lrck/mclk active/gain scale up +static const uint8_t ES7243E_ADC_CTRL_REG0E = 0x0E; // volume control +static const uint8_t ES7243E_ADC_CTRL_REG0F = 0x0F; // offset freeze/auto level control/automute control/VC ramp rate +static const uint8_t ES7243E_ADC_CTRL_REG10 = 0x10; // automute noise gate/detection +static const uint8_t ES7243E_ADC_CTRL_REG11 = 0x11; // automute SDP control/out gain select +static const uint8_t ES7243E_ADC_CTRL_REG12 = 0x12; // controls for automute PDN_PGA/MOD/reset/digital circuit +static const uint8_t ES7243E_ADC_CTRL_REG13 = 0x13; // ALC rate selection/ALC target level +static const uint8_t ES7243E_ADC_CTRL_REG14 = 0x14; // ADCHPF stage1 coeff +static const uint8_t ES7243E_ADC_CTRL_REG15 = 0x15; // ADCHPF stage2 coeff +static const uint8_t ES7243E_ANALOG_REG16 = 0x16; // power-down/reset +static const uint8_t ES7243E_ANALOG_REG17 = 0x17; // VMIDSEL +static const uint8_t ES7243E_ANALOG_REG18 = 0x18; // ADC/ADCFL bias +static const uint8_t ES7243E_ANALOG_REG19 = 0x19; // PGA1/PGA2 bias +static const uint8_t ES7243E_ANALOG_REG1A = 0x1A; // ADCI1/ADCI23 bias +static const uint8_t ES7243E_ANALOG_REG1B = 0x1B; // ADCSM/ADCCM bias +static const uint8_t ES7243E_ANALOG_REG1C = 0x1C; // ADCVRP/ADCCPP bias +static const uint8_t ES7243E_ANALOG_REG1D = 0x1D; // low power bits +static const uint8_t ES7243E_ANALOG_REG1E = 0x1E; // low power bits +static const uint8_t ES7243E_ANALOG_REG1F = 0x1F; // ADC_DMIC_ON/REFSEL/VX2OFF/VX1SEL/VMIDLVL +static const uint8_t ES7243E_ANALOG_REG20 = 0x20; // select MIC1 as PGA1 input/PGA1 gain +static const uint8_t ES7243E_ANALOG_REG21 = 0x21; // select MIC2 as PGA1 input/PGA2 gain +static const uint8_t ES7243E_TEST_MODE_REGF7 = 0xF7; +static const uint8_t ES7243E_TEST_MODE_REGF8 = 0xF8; +static const uint8_t ES7243E_TEST_MODE_REGF9 = 0xF9; +static const uint8_t ES7243E_I2C_CONF_REGFA = 0xFA; // I2C signals retime/reset registers to default +static const uint8_t ES7243E_FLAG_REGFC = 0xFC; // CSM flag/ADC automute flag (RO) +static const uint8_t ES7243E_CHIP_ID1_REGFD = 0xFD; // chip ID 1, reads 0x7A (RO) +static const uint8_t ES7243E_CHIP_ID2_REGFE = 0xFE; // chip ID 2, reads 0x43 (RO) +static const uint8_t ES7243E_CHIP_VERSION_REGFF = 0xFF; // chip version, reads 0x00 (RO) + +} // namespace es7243e +} // namespace esphome diff --git a/esphome/components/es8156/__init__.py b/esphome/components/es8156/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/es8156/audio_dac.py b/esphome/components/es8156/audio_dac.py new file mode 100644 index 0000000000..b9d8eae6b0 --- /dev/null +++ b/esphome/components/es8156/audio_dac.py @@ -0,0 +1,27 @@ +import esphome.codegen as cg +from esphome.components import i2c +from esphome.components.audio_dac import AudioDac +import esphome.config_validation as cv +from esphome.const import CONF_ID + +CODEOWNERS = ["@kbx81"] +DEPENDENCIES = ["i2c"] + +es8156_ns = cg.esphome_ns.namespace("es8156") +ES8156 = es8156_ns.class_("ES8156", AudioDac, cg.Component, i2c.I2CDevice) + +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(ES8156), + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(i2c.i2c_device_schema(0x08)) +) + + +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) diff --git a/esphome/components/es8156/es8156.cpp b/esphome/components/es8156/es8156.cpp new file mode 100644 index 0000000000..62d35aa2d2 --- /dev/null +++ b/esphome/components/es8156/es8156.cpp @@ -0,0 +1,87 @@ +#include "es8156.h" +#include "es8156_const.h" +#include "esphome/core/hal.h" +#include "esphome/core/log.h" +#include + +namespace esphome { +namespace es8156 { + +static const char *const TAG = "es8156"; + +// Mark the component as failed; use only in setup +#define ES8156_ERROR_FAILED(func) \ + if (!(func)) { \ + this->mark_failed(); \ + return; \ + } + +void ES8156::setup() { + ESP_LOGCONFIG(TAG, "Setting up ES8156..."); + + ES8156_ERROR_FAILED(this->write_byte(ES8156_REG02_SCLK_MODE, 0x04)); + ES8156_ERROR_FAILED(this->write_byte(ES8156_REG20_ANALOG_SYS1, 0x2A)); + ES8156_ERROR_FAILED(this->write_byte(ES8156_REG21_ANALOG_SYS2, 0x3C)); + ES8156_ERROR_FAILED(this->write_byte(ES8156_REG22_ANALOG_SYS3, 0x00)); + ES8156_ERROR_FAILED(this->write_byte(ES8156_REG24_ANALOG_LP, 0x07)); + ES8156_ERROR_FAILED(this->write_byte(ES8156_REG23_ANALOG_SYS4, 0x00)); + + ES8156_ERROR_FAILED(this->write_byte(ES8156_REG0A_TIME_CONTROL1, 0x01)); + ES8156_ERROR_FAILED(this->write_byte(ES8156_REG0B_TIME_CONTROL2, 0x01)); + ES8156_ERROR_FAILED(this->write_byte(ES8156_REG11_DAC_SDP, 0x00)); + ES8156_ERROR_FAILED(this->write_byte(ES8156_REG19_EQ_CONTROL1, 0x20)); + + ES8156_ERROR_FAILED(this->write_byte(ES8156_REG0D_P2S_CONTROL, 0x14)); + ES8156_ERROR_FAILED(this->write_byte(ES8156_REG09_MISC_CONTROL2, 0x00)); + ES8156_ERROR_FAILED(this->write_byte(ES8156_REG18_MISC_CONTROL3, 0x00)); + ES8156_ERROR_FAILED(this->write_byte(ES8156_REG08_CLOCK_ON_OFF, 0x3F)); + ES8156_ERROR_FAILED(this->write_byte(ES8156_REG00_RESET, 0x02)); + ES8156_ERROR_FAILED(this->write_byte(ES8156_REG00_RESET, 0x03)); + ES8156_ERROR_FAILED(this->write_byte(ES8156_REG25_ANALOG_SYS5, 0x20)); +} + +void ES8156::dump_config() { + ESP_LOGCONFIG(TAG, "ES8156 Audio Codec:"); + + if (this->is_failed()) { + ESP_LOGCONFIG(TAG, " Failed to initialize"); + return; + } +} + +bool ES8156::set_volume(float volume) { + volume = clamp(volume, 0.0f, 1.0f); + uint8_t reg = remap(volume, 0.0f, 1.0f, 0, 255); + ESP_LOGV(TAG, "Setting ES8156_REG14_VOLUME_CONTROL to %u (volume: %f)", reg, volume); + return this->write_byte(ES8156_REG14_VOLUME_CONTROL, reg); +} + +float ES8156::volume() { + uint8_t reg; + this->read_byte(ES8156_REG14_VOLUME_CONTROL, ®); + return remap(reg, 0, 255, 0.0f, 1.0f); +} + +bool ES8156::set_mute_state_(bool mute_state) { + uint8_t reg13; + + this->is_muted_ = mute_state; + + if (!this->read_byte(ES8156_REG13_DAC_MUTE, ®13)) { + return false; + } + + ESP_LOGV(TAG, "Read ES8156_REG13_DAC_MUTE: %u", reg13); + + if (mute_state) { + reg13 |= BIT(1) | BIT(2); + } else { + reg13 &= ~(BIT(1) | BIT(2)); + } + + ESP_LOGV(TAG, "Setting ES8156_REG13_DAC_MUTE to %u (muted: %s)", reg13, YESNO(mute_state)); + return this->write_byte(ES8156_REG13_DAC_MUTE, reg13); +} + +} // namespace es8156 +} // namespace esphome diff --git a/esphome/components/es8156/es8156.h b/esphome/components/es8156/es8156.h new file mode 100644 index 0000000000..e973599a7a --- /dev/null +++ b/esphome/components/es8156/es8156.h @@ -0,0 +1,51 @@ +#pragma once + +#include "esphome/components/audio_dac/audio_dac.h" +#include "esphome/components/i2c/i2c.h" +#include "esphome/core/component.h" + +namespace esphome { +namespace es8156 { + +class ES8156 : public audio_dac::AudioDac, public Component, public i2c::I2CDevice { + public: + ///////////////////////// + // Component overrides // + ///////////////////////// + + void setup() override; + float get_setup_priority() const override { return setup_priority::DATA; } + void dump_config() override; + + //////////////////////// + // AudioDac overrides // + //////////////////////// + + /// @brief Writes the volume out to the DAC + /// @param volume floating point between 0.0 and 1.0 + /// @return True if successful and false otherwise + bool set_volume(float volume) override; + + /// @brief Gets the current volume out from the DAC + /// @return floating point between 0.0 and 1.0 + float volume() override; + + /// @brief Disables mute for audio out + /// @return True if successful and false otherwise + bool set_mute_off() override { return this->set_mute_state_(false); } + + /// @brief Enables mute for audio out + /// @return True if successful and false otherwise + bool set_mute_on() override { return this->set_mute_state_(true); } + + bool is_muted() override { return this->is_muted_; } + + protected: + /// @brief Mutes or unmutes the DAC audio out + /// @param mute_state True to mute, false to unmute + /// @return True if successful and false otherwise + bool set_mute_state_(bool mute_state); +}; + +} // namespace es8156 +} // namespace esphome diff --git a/esphome/components/es8156/es8156_const.h b/esphome/components/es8156/es8156_const.h new file mode 100644 index 0000000000..0bc8f89dd4 --- /dev/null +++ b/esphome/components/es8156/es8156_const.h @@ -0,0 +1,68 @@ +#pragma once + +#include "es8156.h" + +namespace esphome { +namespace es8156 { + +/* ES8156 register addresses */ +/* + * RESET Control + */ +static const uint8_t ES8156_REG00_RESET = 0x00; +/* + * Clock Managerment + */ +static const uint8_t ES8156_REG01_MAINCLOCK_CTL = 0x01; +static const uint8_t ES8156_REG02_SCLK_MODE = 0x02; +static const uint8_t ES8156_REG03_LRCLK_DIV_H = 0x03; +static const uint8_t ES8156_REG04_LRCLK_DIV_L = 0x04; +static const uint8_t ES8156_REG05_SCLK_DIV = 0x05; +static const uint8_t ES8156_REG06_NFS_CONFIG = 0x06; +static const uint8_t ES8156_REG07_MISC_CONTROL1 = 0x07; +static const uint8_t ES8156_REG08_CLOCK_ON_OFF = 0x08; +static const uint8_t ES8156_REG09_MISC_CONTROL2 = 0x09; +static const uint8_t ES8156_REG0A_TIME_CONTROL1 = 0x0a; +static const uint8_t ES8156_REG0B_TIME_CONTROL2 = 0x0b; +/* + * System Control + */ +static const uint8_t ES8156_REG0C_CHIP_STATUS = 0x0c; +static const uint8_t ES8156_REG0D_P2S_CONTROL = 0x0d; +static const uint8_t ES8156_REG10_DAC_OSR_COUNTER = 0x10; +/* + * SDP Control + */ +static const uint8_t ES8156_REG11_DAC_SDP = 0x11; +static const uint8_t ES8156_REG12_AUTOMUTE_SET = 0x12; +static const uint8_t ES8156_REG13_DAC_MUTE = 0x13; +static const uint8_t ES8156_REG14_VOLUME_CONTROL = 0x14; + +/* + * ALC Control + */ +static const uint8_t ES8156_REG15_ALC_CONFIG1 = 0x15; +static const uint8_t ES8156_REG16_ALC_CONFIG2 = 0x16; +static const uint8_t ES8156_REG17_ALC_CONFIG3 = 0x17; +static const uint8_t ES8156_REG18_MISC_CONTROL3 = 0x18; +static const uint8_t ES8156_REG19_EQ_CONTROL1 = 0x19; +static const uint8_t ES8156_REG1A_EQ_CONTROL2 = 0x1a; +/* + * Analog System Control + */ +static const uint8_t ES8156_REG20_ANALOG_SYS1 = 0x20; +static const uint8_t ES8156_REG21_ANALOG_SYS2 = 0x21; +static const uint8_t ES8156_REG22_ANALOG_SYS3 = 0x22; +static const uint8_t ES8156_REG23_ANALOG_SYS4 = 0x23; +static const uint8_t ES8156_REG24_ANALOG_LP = 0x24; +static const uint8_t ES8156_REG25_ANALOG_SYS5 = 0x25; +/* + * Chip Information + */ +static const uint8_t ES8156_REGFC_I2C_PAGESEL = 0xFC; +static const uint8_t ES8156_REGFD_CHIPID1 = 0xFD; +static const uint8_t ES8156_REGFE_CHIPID0 = 0xFE; +static const uint8_t ES8156_REGFF_CHIP_VERSION = 0xFF; + +} // namespace es8156 +} // namespace esphome diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 98db45831a..23b84f3d13 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -64,6 +64,7 @@ from .gpio import esp32_pin_to_code # noqa _LOGGER = logging.getLogger(__name__) CODEOWNERS = ["@esphome/core"] AUTO_LOAD = ["preferences"] +IS_TARGET_PLATFORM = True CONF_RELEASE = "release" diff --git a/esphome/components/esp32_touch/esp32_touch.cpp b/esphome/components/esp32_touch/esp32_touch.cpp index e43c3b844c..0ae414fa12 100644 --- a/esphome/components/esp32_touch/esp32_touch.cpp +++ b/esphome/components/esp32_touch/esp32_touch.cpp @@ -52,7 +52,12 @@ void ESP32TouchComponent::setup() { } #endif +#if ESP_IDF_VERSION_MAJOR >= 5 + touch_pad_set_measurement_clock_cycles(this->meas_cycle_); + touch_pad_set_measurement_interval(this->sleep_cycle_); +#else touch_pad_set_meas_time(this->sleep_cycle_, this->meas_cycle_); +#endif touch_pad_set_voltage(this->high_voltage_reference_, this->low_voltage_reference_, this->voltage_attenuation_); for (auto *child : this->children_) { diff --git a/esphome/components/esp8266/__init__.py b/esphome/components/esp8266/__init__.py index c73027fe1b..c949e53aa6 100644 --- a/esphome/components/esp8266/__init__.py +++ b/esphome/components/esp8266/__init__.py @@ -34,6 +34,7 @@ from .gpio import PinInitialState, add_pin_initial_states_array CODEOWNERS = ["@esphome/core"] _LOGGER = logging.getLogger(__name__) AUTO_LOAD = ["preferences"] +IS_TARGET_PLATFORM = True def set_core_data(config): diff --git a/esphome/components/host/__init__.py b/esphome/components/host/__init__.py index eb8cfbd984..e275adafa9 100644 --- a/esphome/components/host/__init__.py +++ b/esphome/components/host/__init__.py @@ -17,6 +17,7 @@ from .gpio import host_pin_to_code # noqa CODEOWNERS = ["@esphome/core", "@clydebarrow"] AUTO_LOAD = ["network", "preferences"] +IS_TARGET_PLATFORM = True def set_core_data(config): diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp index b449f046ee..66f064c2ce 100644 --- a/esphome/components/http_request/http_request_idf.cpp +++ b/esphome/components/http_request/http_request_idf.cpp @@ -12,6 +12,8 @@ #include "esp_crt_bundle.h" #endif +#include "esp_task_wdt.h" + namespace esphome { namespace http_request { @@ -117,11 +119,11 @@ std::shared_ptr HttpRequestIDF::start(std::string url, std::strin return nullptr; } - App.feed_wdt(); + container->feed_wdt(); container->content_length = esp_http_client_fetch_headers(client); - App.feed_wdt(); + container->feed_wdt(); container->status_code = esp_http_client_get_status_code(client); - App.feed_wdt(); + container->feed_wdt(); if (is_success(container->status_code)) { container->duration_ms = millis() - start; return container; @@ -151,11 +153,11 @@ std::shared_ptr HttpRequestIDF::start(std::string url, std::strin return nullptr; } - App.feed_wdt(); + container->feed_wdt(); container->content_length = esp_http_client_fetch_headers(client); - App.feed_wdt(); + container->feed_wdt(); container->status_code = esp_http_client_get_status_code(client); - App.feed_wdt(); + container->feed_wdt(); if (is_success(container->status_code)) { container->duration_ms = millis() - start; return container; @@ -185,8 +187,9 @@ int HttpContainerIDF::read(uint8_t *buf, size_t max_len) { return 0; } - App.feed_wdt(); + this->feed_wdt(); int read_len = esp_http_client_read(this->client_, (char *) buf, bufsize); + this->feed_wdt(); this->bytes_read_ += read_len; this->duration_ms += (millis() - start); @@ -201,6 +204,13 @@ void HttpContainerIDF::end() { esp_http_client_cleanup(this->client_); } +void HttpContainerIDF::feed_wdt() { + // Tests to see if the executing task has a watchdog timer attached + if (esp_task_wdt_status(nullptr) == ESP_OK) { + App.feed_wdt(); + } +} + } // namespace http_request } // namespace esphome diff --git a/esphome/components/http_request/http_request_idf.h b/esphome/components/http_request/http_request_idf.h index 431794924b..2ed50698b9 100644 --- a/esphome/components/http_request/http_request_idf.h +++ b/esphome/components/http_request/http_request_idf.h @@ -18,6 +18,9 @@ class HttpContainerIDF : public HttpContainer { int read(uint8_t *buf, size_t max_len) override; void end() override; + /// @brief Feeds the watchdog timer if the executing task has one attached + void feed_wdt(); + protected: esp_http_client_handle_t client_; }; diff --git a/esphome/components/http_request/update/http_request_update.cpp b/esphome/components/http_request/update/http_request_update.cpp index 0e0966c22b..d683495ac6 100644 --- a/esphome/components/http_request/update/http_request_update.cpp +++ b/esphome/components/http_request/update/http_request_update.cpp @@ -9,6 +9,13 @@ namespace esphome { namespace http_request { +// The update function runs in a task only on ESP32s. +#ifdef USE_ESP32 +#define UPDATE_RETURN vTaskDelete(nullptr) // Delete the current update task +#else +#define UPDATE_RETURN return +#endif + static const char *const TAG = "http_request.update"; static const size_t MAX_READ_SIZE = 256; @@ -29,113 +36,131 @@ void HttpRequestUpdate::setup() { } void HttpRequestUpdate::update() { - auto container = this->request_parent_->get(this->source_url_); +#ifdef USE_ESP32 + xTaskCreate(HttpRequestUpdate::update_task, "update_task", 8192, (void *) this, 1, &this->update_task_handle_); +#else + this->update_task(this); +#endif +} + +void HttpRequestUpdate::update_task(void *params) { + HttpRequestUpdate *this_update = (HttpRequestUpdate *) params; + + auto container = this_update->request_parent_->get(this_update->source_url_); if (container == nullptr || container->status_code != HTTP_STATUS_OK) { - std::string msg = str_sprintf("Failed to fetch manifest from %s", this->source_url_.c_str()); - this->status_set_error(msg.c_str()); - return; + std::string msg = str_sprintf("Failed to fetch manifest from %s", this_update->source_url_.c_str()); + this_update->status_set_error(msg.c_str()); + UPDATE_RETURN; } ExternalRAMAllocator allocator(ExternalRAMAllocator::ALLOW_FAILURE); uint8_t *data = allocator.allocate(container->content_length); if (data == nullptr) { std::string msg = str_sprintf("Failed to allocate %d bytes for manifest", container->content_length); - this->status_set_error(msg.c_str()); + this_update->status_set_error(msg.c_str()); container->end(); - return; + UPDATE_RETURN; } size_t read_index = 0; while (container->get_bytes_read() < container->content_length) { int read_bytes = container->read(data + read_index, MAX_READ_SIZE); - App.feed_wdt(); yield(); read_index += read_bytes; } - std::string response((char *) data, read_index); - allocator.deallocate(data, container->content_length); + bool valid = false; + { // Ensures the response string falls out of scope and deallocates before the task ends + std::string response((char *) data, read_index); + allocator.deallocate(data, container->content_length); - container->end(); + container->end(); + container.reset(); // Release ownership of the container's shared_ptr - bool valid = json::parse_json(response, [this](JsonObject root) -> bool { - if (!root.containsKey("name") || !root.containsKey("version") || !root.containsKey("builds")) { - ESP_LOGE(TAG, "Manifest does not contain required fields"); - return false; - } - this->update_info_.title = root["name"].as(); - this->update_info_.latest_version = root["version"].as(); - - for (auto build : root["builds"].as()) { - if (!build.containsKey("chipFamily")) { + valid = json::parse_json(response, [this_update](JsonObject root) -> bool { + if (!root.containsKey("name") || !root.containsKey("version") || !root.containsKey("builds")) { ESP_LOGE(TAG, "Manifest does not contain required fields"); return false; } - if (build["chipFamily"] == ESPHOME_VARIANT) { - if (!build.containsKey("ota")) { + this_update->update_info_.title = root["name"].as(); + this_update->update_info_.latest_version = root["version"].as(); + + for (auto build : root["builds"].as()) { + if (!build.containsKey("chipFamily")) { ESP_LOGE(TAG, "Manifest does not contain required fields"); return false; } - auto ota = build["ota"]; - if (!ota.containsKey("path") || !ota.containsKey("md5")) { - ESP_LOGE(TAG, "Manifest does not contain required fields"); - return false; + if (build["chipFamily"] == ESPHOME_VARIANT) { + if (!build.containsKey("ota")) { + ESP_LOGE(TAG, "Manifest does not contain required fields"); + return false; + } + auto ota = build["ota"]; + if (!ota.containsKey("path") || !ota.containsKey("md5")) { + ESP_LOGE(TAG, "Manifest does not contain required fields"); + return false; + } + this_update->update_info_.firmware_url = ota["path"].as(); + this_update->update_info_.md5 = ota["md5"].as(); + + if (ota.containsKey("summary")) + this_update->update_info_.summary = ota["summary"].as(); + if (ota.containsKey("release_url")) + this_update->update_info_.release_url = ota["release_url"].as(); + + return true; } - this->update_info_.firmware_url = ota["path"].as(); - this->update_info_.md5 = ota["md5"].as(); - - if (ota.containsKey("summary")) - this->update_info_.summary = ota["summary"].as(); - if (ota.containsKey("release_url")) - this->update_info_.release_url = ota["release_url"].as(); - - return true; } - } - return false; - }); + return false; + }); + } if (!valid) { - std::string msg = str_sprintf("Failed to parse JSON from %s", this->source_url_.c_str()); - this->status_set_error(msg.c_str()); - return; + std::string msg = str_sprintf("Failed to parse JSON from %s", this_update->source_url_.c_str()); + this_update->status_set_error(msg.c_str()); + UPDATE_RETURN; } - // Merge source_url_ and this->update_info_.firmware_url - if (this->update_info_.firmware_url.find("http") == std::string::npos) { - std::string path = this->update_info_.firmware_url; + // Merge source_url_ and this_update->update_info_.firmware_url + if (this_update->update_info_.firmware_url.find("http") == std::string::npos) { + std::string path = this_update->update_info_.firmware_url; if (path[0] == '/') { - std::string domain = this->source_url_.substr(0, this->source_url_.find('/', 8)); - this->update_info_.firmware_url = domain + path; + std::string domain = this_update->source_url_.substr(0, this_update->source_url_.find('/', 8)); + this_update->update_info_.firmware_url = domain + path; } else { - std::string domain = this->source_url_.substr(0, this->source_url_.rfind('/') + 1); - this->update_info_.firmware_url = domain + path; + std::string domain = this_update->source_url_.substr(0, this_update->source_url_.rfind('/') + 1); + this_update->update_info_.firmware_url = domain + path; } } - std::string current_version; + { // Ensures the current version string falls out of scope and deallocates before the task ends + std::string current_version; #ifdef ESPHOME_PROJECT_VERSION - current_version = ESPHOME_PROJECT_VERSION; + current_version = ESPHOME_PROJECT_VERSION; #else - current_version = ESPHOME_VERSION; + current_version = ESPHOME_VERSION; #endif - this->update_info_.current_version = current_version; - - if (this->update_info_.latest_version.empty() || this->update_info_.latest_version == update_info_.current_version) { - this->state_ = update::UPDATE_STATE_NO_UPDATE; - } else { - this->state_ = update::UPDATE_STATE_AVAILABLE; + this_update->update_info_.current_version = current_version; } - this->update_info_.has_progress = false; - this->update_info_.progress = 0.0f; + if (this_update->update_info_.latest_version.empty() || + this_update->update_info_.latest_version == this_update->update_info_.current_version) { + this_update->state_ = update::UPDATE_STATE_NO_UPDATE; + } else { + this_update->state_ = update::UPDATE_STATE_AVAILABLE; + } - this->status_clear_error(); - this->publish_state(); + this_update->update_info_.has_progress = false; + this_update->update_info_.progress = 0.0f; + + this_update->status_clear_error(); + this_update->publish_state(); + + UPDATE_RETURN; } void HttpRequestUpdate::perform(bool force) { diff --git a/esphome/components/http_request/update/http_request_update.h b/esphome/components/http_request/update/http_request_update.h index 45c7e6a447..e05fdb0cc2 100644 --- a/esphome/components/http_request/update/http_request_update.h +++ b/esphome/components/http_request/update/http_request_update.h @@ -7,6 +7,10 @@ #include "esphome/components/http_request/ota/ota_http_request.h" #include "esphome/components/update/update_entity.h" +#ifdef USE_ESP32 +#include +#endif + namespace esphome { namespace http_request { @@ -29,6 +33,11 @@ class HttpRequestUpdate : public update::UpdateEntity, public PollingComponent { HttpRequestComponent *request_parent_; OtaHttpRequestComponent *ota_parent_; std::string source_url_; + + static void update_task(void *params); +#ifdef USE_ESP32 + TaskHandle_t update_task_handle_{nullptr}; +#endif }; } // namespace http_request diff --git a/esphome/components/image/__init__.py b/esphome/components/image/__init__.py index a503e8f471..7cdce757be 100644 --- a/esphome/components/image/__init__.py +++ b/esphome/components/image/__init__.py @@ -282,7 +282,7 @@ IMAGE_TYPE = { TransparencyType = image_ns.enum("TransparencyType") -CONF_USE_TRANSPARENCY = "use_transparency" +CONF_TRANSPARENCY = "transparency" # If the MDI file cannot be downloaded within this time, abort. IMAGE_DOWNLOAD_TIMEOUT = 30 # seconds @@ -417,7 +417,7 @@ def validate_type(image_types): def validate_settings(value): type = value[CONF_TYPE] - transparency = value[CONF_USE_TRANSPARENCY].lower() + transparency = value[CONF_TRANSPARENCY].lower() allow_config = IMAGE_TYPE[type].allow_config if transparency not in allow_config: raise cv.Invalid( @@ -458,9 +458,7 @@ BASE_SCHEMA = cv.Schema( IMAGE_SCHEMA = BASE_SCHEMA.extend( { cv.Required(CONF_TYPE): validate_type(IMAGE_TYPE), - cv.Optional( - CONF_USE_TRANSPARENCY, default=CONF_OPAQUE - ): validate_transparency(), + cv.Optional(CONF_TRANSPARENCY, default=CONF_OPAQUE): validate_transparency(), } ) @@ -476,7 +474,7 @@ def typed_image_schema(image_type): BASE_SCHEMA.extend( { cv.Optional( - CONF_USE_TRANSPARENCY, default=t + CONF_TRANSPARENCY, default=t ): validate_transparency((t,)), cv.Optional(CONF_TYPE, default=image_type): validate_type( (image_type,) @@ -494,7 +492,7 @@ def typed_image_schema(image_type): BASE_SCHEMA.extend( { cv.Optional( - CONF_USE_TRANSPARENCY, default=CONF_OPAQUE + CONF_TRANSPARENCY, default=CONF_OPAQUE ): validate_transparency(), cv.Optional(CONF_TYPE, default=image_type): validate_type( (image_type,) @@ -556,7 +554,7 @@ async def write_image(config, all_frames=False): else Image.Dither.FLOYDSTEINBERG ) type = config[CONF_TYPE] - transparency = config[CONF_USE_TRANSPARENCY] + transparency = config[CONF_TRANSPARENCY] invert_alpha = config[CONF_INVERT_ALPHA] frame_count = 1 if all_frames: diff --git a/esphome/components/libretiny/__init__.py b/esphome/components/libretiny/__init__.py index b29d2e309c..5bdfb15e19 100644 --- a/esphome/components/libretiny/__init__.py +++ b/esphome/components/libretiny/__init__.py @@ -47,6 +47,7 @@ from .const import ( _LOGGER = logging.getLogger(__name__) CODEOWNERS = ["@kuba2k2"] AUTO_LOAD = ["preferences"] +IS_TARGET_PLATFORM = True def _detect_variant(value): diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index f30bc23e38..6e92777058 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -186,6 +186,8 @@ CONFIG_SCHEMA = cv.All( esp32_s3_idf=USB_SERIAL_JTAG, esp32_c3_arduino=USB_CDC, esp32_c3_idf=USB_SERIAL_JTAG, + esp32_c6_arduino=USB_CDC, + esp32_c6_idf=USB_SERIAL_JTAG, rp2040=USB_CDC, bk72xx=DEFAULT, rtl87xx=DEFAULT, diff --git a/esphome/components/mqtt/mqtt_climate.cpp b/esphome/components/mqtt/mqtt_climate.cpp index f06574fa26..a8768114a4 100644 --- a/esphome/components/mqtt/mqtt_climate.cpp +++ b/esphome/components/mqtt/mqtt_climate.cpp @@ -72,9 +72,9 @@ void MQTTClimateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCo // max_temp root[MQTT_MAX_TEMP] = traits.get_visual_max_temperature(); // target_temp_step - root[MQTT_TARGET_TEMPERATURE_STEP] = traits.get_visual_target_temperature_step(); + root[MQTT_TARGET_TEMPERATURE_STEP] = roundf(traits.get_visual_target_temperature_step() * 10) * 0.1; // current_temp_step - root[MQTT_CURRENT_TEMPERATURE_STEP] = traits.get_visual_current_temperature_step(); + root[MQTT_CURRENT_TEMPERATURE_STEP] = roundf(traits.get_visual_current_temperature_step() * 10) * 0.1; // temperature units are always coerced to Celsius internally root[MQTT_TEMPERATURE_UNIT] = "C"; diff --git a/esphome/components/ntc/sensor.py b/esphome/components/ntc/sensor.py index 961511fe00..bd5f4a1841 100644 --- a/esphome/components/ntc/sensor.py +++ b/esphome/components/ntc/sensor.py @@ -2,7 +2,7 @@ from math import log import esphome.config_validation as cv import esphome.codegen as cg -from esphome.components import sensor, resistance_sampler +from esphome.components import sensor from esphome.const import ( CONF_CALIBRATION, CONF_REFERENCE_RESISTANCE, @@ -15,8 +15,6 @@ from esphome.const import ( UNIT_CELSIUS, ) -AUTO_LOAD = ["resistance_sampler"] - ntc_ns = cg.esphome_ns.namespace("ntc") NTC = ntc_ns.class_("NTC", cg.Component, sensor.Sensor) @@ -126,7 +124,7 @@ CONFIG_SCHEMA = ( ) .extend( { - cv.Required(CONF_SENSOR): cv.use_id(resistance_sampler.ResistanceSampler), + cv.Required(CONF_SENSOR): cv.use_id(sensor.Sensor), cv.Required(CONF_CALIBRATION): process_calibration, } ) diff --git a/esphome/components/online_image/__init__.py b/esphome/components/online_image/__init__.py index d1915c7364..ca4eefea6f 100644 --- a/esphome/components/online_image/__init__.py +++ b/esphome/components/online_image/__init__.py @@ -5,7 +5,7 @@ import esphome.codegen as cg from esphome.components.http_request import CONF_HTTP_REQUEST_ID, HttpRequestComponent from esphome.components.image import ( CONF_INVERT_ALPHA, - CONF_USE_TRANSPARENCY, + CONF_TRANSPARENCY, IMAGE_SCHEMA, Image_, get_image_type_enum, @@ -168,7 +168,7 @@ async def to_code(config): url = config[CONF_URL] width, height = config.get(CONF_RESIZE, (0, 0)) - transparent = get_transparency_enum(config[CONF_USE_TRANSPARENCY]) + transparent = get_transparency_enum(config[CONF_TRANSPARENCY]) var = cg.new_Pvariable( config[CONF_ID], diff --git a/esphome/components/online_image/image_decoder.h b/esphome/components/online_image/image_decoder.h index cde7f572e3..7c5175d72d 100644 --- a/esphome/components/online_image/image_decoder.h +++ b/esphome/components/online_image/image_decoder.h @@ -100,7 +100,7 @@ class DownloadBuffer { void reset() { this->unread_ = 0; } protected: - ExternalRAMAllocator allocator_; + RAMAllocator allocator_{}; uint8_t *buffer_; size_t size_; /** Total number of downloaded bytes not yet read. */ diff --git a/esphome/components/online_image/online_image.h b/esphome/components/online_image/online_image.h index e044b4f390..bafd8ba67e 100644 --- a/esphome/components/online_image/online_image.h +++ b/esphome/components/online_image/online_image.h @@ -83,8 +83,7 @@ class OnlineImage : public PollingComponent, protected: bool validate_url_(const std::string &url); - using Allocator = ExternalRAMAllocator; - Allocator allocator_{Allocator::Flags::ALLOW_FAILURE}; + RAMAllocator allocator_{}; uint32_t get_buffer_size_() const { return get_buffer_size_(this->buffer_width_, this->buffer_height_); } int get_buffer_size_(int width, int height) const { return (this->get_bpp() * width + 7u) / 8u * height; } diff --git a/esphome/components/pulse_meter/pulse_meter_sensor.cpp b/esphome/components/pulse_meter/pulse_meter_sensor.cpp index 530425563c..836a84b391 100644 --- a/esphome/components/pulse_meter/pulse_meter_sensor.cpp +++ b/esphome/components/pulse_meter/pulse_meter_sensor.cpp @@ -75,6 +75,8 @@ void PulseMeterSensor::loop() { case MeterState::RUNNING: { uint32_t delta_us = this->get_->last_detected_edge_us_ - this->last_processed_edge_us_; float pulse_width_us = delta_us / float(this->get_->count_); + ESP_LOGV(TAG, "New pulse, delta: %" PRIu32 " µs, count: %" PRIu32 ", width: %.5f µs", delta_us, + this->get_->count_, pulse_width_us); this->publish_state((60.0f * 1000000.0f) / pulse_width_us); } break; } diff --git a/esphome/components/resistance/resistance_sensor.h b/esphome/components/resistance/resistance_sensor.h index 8fa1f8b570..b57f90b59c 100644 --- a/esphome/components/resistance/resistance_sensor.h +++ b/esphome/components/resistance/resistance_sensor.h @@ -1,8 +1,7 @@ #pragma once -#include "esphome/components/resistance_sampler/resistance_sampler.h" -#include "esphome/components/sensor/sensor.h" #include "esphome/core/component.h" +#include "esphome/components/sensor/sensor.h" namespace esphome { namespace resistance { @@ -12,7 +11,7 @@ enum ResistanceConfiguration { DOWNSTREAM, }; -class ResistanceSensor : public Component, public sensor::Sensor, resistance_sampler::ResistanceSampler { +class ResistanceSensor : public Component, public sensor::Sensor { public: void set_sensor(Sensor *sensor) { sensor_ = sensor; } void set_configuration(ResistanceConfiguration configuration) { configuration_ = configuration; } diff --git a/esphome/components/resistance/sensor.py b/esphome/components/resistance/sensor.py index ce4459fc6d..3622799a07 100644 --- a/esphome/components/resistance/sensor.py +++ b/esphome/components/resistance/sensor.py @@ -1,6 +1,6 @@ import esphome.codegen as cg import esphome.config_validation as cv -from esphome.components import sensor, resistance_sampler +from esphome.components import sensor from esphome.const import ( CONF_REFERENCE_VOLTAGE, CONF_SENSOR, @@ -9,15 +9,8 @@ from esphome.const import ( ICON_FLASH, ) -AUTO_LOAD = ["resistance_sampler"] - resistance_ns = cg.esphome_ns.namespace("resistance") -ResistanceSensor = resistance_ns.class_( - "ResistanceSensor", - cg.Component, - sensor.Sensor, - resistance_sampler.ResistanceSampler, -) +ResistanceSensor = resistance_ns.class_("ResistanceSensor", cg.Component, sensor.Sensor) CONF_CONFIGURATION = "configuration" CONF_RESISTOR = "resistor" diff --git a/esphome/components/resistance_sampler/__init__.py b/esphome/components/resistance_sampler/__init__.py deleted file mode 100644 index d2032848aa..0000000000 --- a/esphome/components/resistance_sampler/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -import esphome.codegen as cg - -resistance_sampler_ns = cg.esphome_ns.namespace("resistance_sampler") -ResistanceSampler = resistance_sampler_ns.class_("ResistanceSampler") - -CODEOWNERS = ["@jesserockz"] diff --git a/esphome/components/resistance_sampler/resistance_sampler.h b/esphome/components/resistance_sampler/resistance_sampler.h deleted file mode 100644 index 9e300bebcc..0000000000 --- a/esphome/components/resistance_sampler/resistance_sampler.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -namespace esphome { -namespace resistance_sampler { - -/// Abstract interface to mark components that provide resistance values. -class ResistanceSampler {}; - -} // namespace resistance_sampler -} // namespace esphome diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index b04e539182..3d73cad195 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -27,6 +27,7 @@ from .gpio import rp2040_pin_to_code # noqa _LOGGER = logging.getLogger(__name__) CODEOWNERS = ["@jesserockz"] AUTO_LOAD = ["preferences"] +IS_TARGET_PLATFORM = True def set_core_data(config): diff --git a/esphome/components/rtl87xx/__init__.py b/esphome/components/rtl87xx/__init__.py index 4c1956f0f4..109c986f75 100644 --- a/esphome/components/rtl87xx/__init__.py +++ b/esphome/components/rtl87xx/__init__.py @@ -19,6 +19,8 @@ from .boards import RTL87XX_BOARD_PINS, RTL87XX_BOARDS CODEOWNERS = ["@kuba2k2"] AUTO_LOAD = ["libretiny"] +IS_TARGET_PLATFORM = True + COMPONENT_DATA = LibreTinyComponent( name=COMPONENT_RTL87XX, diff --git a/esphome/components/seeed_mr60bha2/binary_sensor.py b/esphome/components/seeed_mr60bha2/binary_sensor.py new file mode 100644 index 0000000000..ae9e1c23e6 --- /dev/null +++ b/esphome/components/seeed_mr60bha2/binary_sensor.py @@ -0,0 +1,25 @@ +import esphome.codegen as cg +from esphome.components import binary_sensor +import esphome.config_validation as cv +from esphome.const import ( + DEVICE_CLASS_OCCUPANCY, + CONF_HAS_TARGET, +) +from . import CONF_MR60BHA2_ID, MR60BHA2Component + +DEPENDENCIES = ["seeed_mr60bha2"] + +CONFIG_SCHEMA = { + cv.GenerateID(CONF_MR60BHA2_ID): cv.use_id(MR60BHA2Component), + cv.Optional(CONF_HAS_TARGET): binary_sensor.binary_sensor_schema( + device_class=DEVICE_CLASS_OCCUPANCY, icon="mdi:motion-sensor" + ), +} + + +async def to_code(config): + mr60bha2_component = await cg.get_variable(config[CONF_MR60BHA2_ID]) + + if has_target_config := config.get(CONF_HAS_TARGET): + sens = await binary_sensor.new_binary_sensor(has_target_config) + cg.add(mr60bha2_component.set_has_target_binary_sensor(sens)) diff --git a/esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp b/esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp index 50d709c3b0..75f3f092a6 100644 --- a/esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp +++ b/esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp @@ -1,6 +1,7 @@ #include "seeed_mr60bha2.h" #include "esphome/core/log.h" +#include #include namespace esphome { @@ -12,10 +13,14 @@ static const char *const TAG = "seeed_mr60bha2"; // items in an easy-to-read format, including the configuration key-value pairs. void MR60BHA2Component::dump_config() { ESP_LOGCONFIG(TAG, "MR60BHA2:"); +#ifdef USE_BINARY_SENSOR + LOG_BINARY_SENSOR(" ", "People Exist Binary Sensor", this->has_target_binary_sensor_); +#endif #ifdef USE_SENSOR LOG_SENSOR(" ", "Breath Rate Sensor", this->breath_rate_sensor_); LOG_SENSOR(" ", "Heart Rate Sensor", this->heart_rate_sensor_); LOG_SENSOR(" ", "Distance Sensor", this->distance_sensor_); + LOG_SENSOR(" ", "Target Number Sensor", this->num_targets_sensor_); #endif } @@ -94,7 +99,8 @@ bool MR60BHA2Component::validate_message_() { uint16_t frame_type = encode_uint16(data[5], data[6]); if (frame_type != BREATH_RATE_TYPE_BUFFER && frame_type != HEART_RATE_TYPE_BUFFER && - frame_type != DISTANCE_TYPE_BUFFER) { + frame_type != DISTANCE_TYPE_BUFFER && frame_type != PEOPLE_EXIST_TYPE_BUFFER && + frame_type != PRINT_CLOUD_BUFFER) { return false; } @@ -144,6 +150,18 @@ void MR60BHA2Component::process_frame_(uint16_t frame_id, uint16_t frame_type, c } } break; + case PEOPLE_EXIST_TYPE_BUFFER: + if (this->has_target_binary_sensor_ != nullptr && length >= 2) { + uint16_t has_target_int = encode_uint16(data[1], data[0]); + this->has_target_binary_sensor_->publish_state(has_target_int); + if (has_target_int == 0) { + this->breath_rate_sensor_->publish_state(0.0); + this->heart_rate_sensor_->publish_state(0.0); + this->distance_sensor_->publish_state(0.0); + this->num_targets_sensor_->publish_state(0); + } + } + break; case HEART_RATE_TYPE_BUFFER: if (this->heart_rate_sensor_ != nullptr && length >= 4) { uint32_t current_heart_rate_int = encode_uint32(data[3], data[2], data[1], data[0]); @@ -155,7 +173,7 @@ void MR60BHA2Component::process_frame_(uint16_t frame_id, uint16_t frame_type, c } break; case DISTANCE_TYPE_BUFFER: - if (!data[0]) { + if (data[0] != 0) { if (this->distance_sensor_ != nullptr && length >= 8) { uint32_t current_distance_int = encode_uint32(data[7], data[6], data[5], data[4]); float distance_float; @@ -164,6 +182,12 @@ void MR60BHA2Component::process_frame_(uint16_t frame_id, uint16_t frame_type, c } } break; + case PRINT_CLOUD_BUFFER: + if (this->num_targets_sensor_ != nullptr && length >= 4) { + uint32_t current_num_targets_int = encode_uint32(data[3], data[2], data[1], data[0]); + this->num_targets_sensor_->publish_state(current_num_targets_int); + } + break; default: break; } diff --git a/esphome/components/seeed_mr60bha2/seeed_mr60bha2.h b/esphome/components/seeed_mr60bha2/seeed_mr60bha2.h index 0a4f21f1ad..d20c8e50cc 100644 --- a/esphome/components/seeed_mr60bha2/seeed_mr60bha2.h +++ b/esphome/components/seeed_mr60bha2/seeed_mr60bha2.h @@ -1,6 +1,9 @@ #pragma once #include "esphome/core/component.h" #include "esphome/core/defines.h" +#ifdef USE_BINARY_SENSOR +#include "esphome/components/binary_sensor/binary_sensor.h" +#endif #ifdef USE_SENSOR #include "esphome/components/sensor/sensor.h" #endif @@ -12,37 +15,23 @@ namespace esphome { namespace seeed_mr60bha2 { - -static const uint8_t DATA_BUF_MAX_SIZE = 12; -static const uint8_t FRAME_BUF_MAX_SIZE = 21; -static const uint8_t LEN_TO_HEAD_CKSUM = 8; -static const uint8_t LEN_TO_DATA_FRAME = 9; - static const uint8_t FRAME_HEADER_BUFFER = 0x01; static const uint16_t BREATH_RATE_TYPE_BUFFER = 0x0A14; +static const uint16_t PEOPLE_EXIST_TYPE_BUFFER = 0x0F09; static const uint16_t HEART_RATE_TYPE_BUFFER = 0x0A15; static const uint16_t DISTANCE_TYPE_BUFFER = 0x0A16; - -enum FrameLocation { - LOCATE_FRAME_HEADER, - LOCATE_ID_FRAME1, - LOCATE_ID_FRAME2, - LOCATE_LENGTH_FRAME_H, - LOCATE_LENGTH_FRAME_L, - LOCATE_TYPE_FRAME1, - LOCATE_TYPE_FRAME2, - LOCATE_HEAD_CKSUM_FRAME, // Header checksum: [from the first byte to the previous byte of the HEAD_CKSUM bit] - LOCATE_DATA_FRAME, - LOCATE_DATA_CKSUM_FRAME, // Data checksum: [from the first to the previous byte of the DATA_CKSUM bit] - LOCATE_PROCESS_FRAME, -}; +static const uint16_t PRINT_CLOUD_BUFFER = 0x0A04; class MR60BHA2Component : public Component, public uart::UARTDevice { // The class name must be the name defined by text_sensor.py +#ifdef USE_BINARY_SENSOR + SUB_BINARY_SENSOR(has_target); +#endif #ifdef USE_SENSOR SUB_SENSOR(breath_rate); SUB_SENSOR(heart_rate); SUB_SENSOR(distance); + SUB_SENSOR(num_targets); #endif public: diff --git a/esphome/components/seeed_mr60bha2/sensor.py b/esphome/components/seeed_mr60bha2/sensor.py index 5f30b363bf..916d4b4ba2 100644 --- a/esphome/components/seeed_mr60bha2/sensor.py +++ b/esphome/components/seeed_mr60bha2/sensor.py @@ -7,6 +7,7 @@ from esphome.const import ( ICON_HEART_PULSE, ICON_PULSE, ICON_SIGNAL, + ICON_COUNTER, STATE_CLASS_MEASUREMENT, UNIT_BEATS_PER_MINUTE, UNIT_CENTIMETER, @@ -18,12 +19,13 @@ DEPENDENCIES = ["seeed_mr60bha2"] CONF_BREATH_RATE = "breath_rate" CONF_HEART_RATE = "heart_rate" +CONF_NUM_TARGETS = "num_targets" CONFIG_SCHEMA = cv.Schema( { cv.GenerateID(CONF_MR60BHA2_ID): cv.use_id(MR60BHA2Component), cv.Optional(CONF_BREATH_RATE): sensor.sensor_schema( - accuracy_decimals=2, + accuracy_decimals=0, state_class=STATE_CLASS_MEASUREMENT, icon=ICON_PULSE, ), @@ -40,6 +42,9 @@ CONFIG_SCHEMA = cv.Schema( accuracy_decimals=2, icon=ICON_SIGNAL, ), + cv.Optional(CONF_NUM_TARGETS): sensor.sensor_schema( + icon=ICON_COUNTER, + ), } ) @@ -55,3 +60,6 @@ async def to_code(config): if distance_config := config.get(CONF_DISTANCE): sens = await sensor.new_sensor(distance_config) cg.add(mr60bha2_component.set_distance_sensor(sens)) + if num_targets_config := config.get(CONF_NUM_TARGETS): + sens = await sensor.new_sensor(num_targets_config) + cg.add(mr60bha2_component.set_num_targets_sensor(sens)) diff --git a/esphome/components/spi/spi.cpp b/esphome/components/spi/spi.cpp index b13826c443..18f7852757 100644 --- a/esphome/components/spi/spi.cpp +++ b/esphome/components/spi/spi.cpp @@ -88,7 +88,7 @@ void SPIDelegateBitBash::write(uint16_t data, size_t num_bits) { this->transfer_ uint16_t SPIDelegateBitBash::transfer_(uint16_t data, size_t num_bits) { // Clock starts out at idle level this->clk_pin_->digital_write(clock_polarity_); - uint8_t out_data = 0; + uint16_t out_data = 0; for (uint8_t i = 0; i != num_bits; i++) { uint8_t shift; diff --git a/esphome/components/uptime/text_sensor/__init__.py b/esphome/components/uptime/text_sensor/__init__.py index 996d983e71..e4a7ac6517 100644 --- a/esphome/components/uptime/text_sensor/__init__.py +++ b/esphome/components/uptime/text_sensor/__init__.py @@ -11,7 +11,7 @@ CONFIG_SCHEMA = text_sensor.text_sensor_schema( UptimeTextSensor, icon=ICON_TIMER, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, -).extend(cv.polling_component_schema("60s")) +).extend(cv.polling_component_schema("30s")) async def to_code(config): diff --git a/esphome/components/uptime/text_sensor/uptime_text_sensor.cpp b/esphome/components/uptime/text_sensor/uptime_text_sensor.cpp index 0fa5e199f3..409af6e4ff 100644 --- a/esphome/components/uptime/text_sensor/uptime_text_sensor.cpp +++ b/esphome/components/uptime/text_sensor/uptime_text_sensor.cpp @@ -9,34 +9,51 @@ namespace uptime { static const char *const TAG = "uptime.sensor"; -void UptimeTextSensor::setup() { this->last_ms_ = millis(); } +void UptimeTextSensor::setup() { + this->last_ms_ = millis(); + if (this->last_ms_ < 60 * 1000) + this->last_ms_ = 0; + this->update(); +} void UptimeTextSensor::update() { - const auto now = millis(); + auto now = millis(); // get whole seconds since last update. Note that even if the millis count has overflowed between updates, // the difference will still be correct due to the way twos-complement arithmetic works. - const uint32_t delta = (now - this->last_ms_) / 1000; - if (delta == 0) - return; - // set last_ms_ to the last second boundary - this->last_ms_ = now - (now % 1000); + uint32_t delta = now - this->last_ms_; + this->last_ms_ = now - delta % 1000; // save remainder for next update + delta /= 1000; this->uptime_ += delta; auto uptime = this->uptime_; - unsigned days = uptime / (24 * 3600); - unsigned seconds = uptime % (24 * 3600); - unsigned hours = seconds / 3600; - seconds %= 3600; - unsigned minutes = seconds / 60; - seconds %= 60; - if (days != 0) { - this->publish_state(str_sprintf("%dd%dh%dm%ds", days, hours, minutes, seconds)); - } else if (hours != 0) { - this->publish_state(str_sprintf("%dh%dm%ds", hours, minutes, seconds)); - } else if (minutes != 0) { - this->publish_state(str_sprintf("%dm%ds", minutes, seconds)); - } else { - this->publish_state(str_sprintf("%ds", seconds)); + unsigned interval = this->get_update_interval() / 1000; + std::string buffer{}; + // display from the largest unit that corresponds to the update interval, drop larger units that are zero. + while (true) { // enable use of break for early exit + unsigned remainder = uptime % 60; + uptime /= 60; + if (interval < 30) { + buffer.insert(0, str_sprintf("%us", remainder)); + if (uptime == 0) + break; + } + remainder = uptime % 60; + uptime /= 60; + if (interval < 1800) { + buffer.insert(0, str_sprintf("%um", remainder)); + if (uptime == 0) + break; + } + remainder = uptime % 24; + uptime /= 24; + if (interval < 12 * 3600) { + buffer.insert(0, str_sprintf("%uh", remainder)); + if (uptime == 0) + break; + } + buffer.insert(0, str_sprintf("%ud", (unsigned) uptime)); + break; } + this->publish_state(buffer); } float UptimeTextSensor::get_setup_priority() const { return setup_priority::HARDWARE; } diff --git a/esphome/components/uptime/text_sensor/uptime_text_sensor.h b/esphome/components/uptime/text_sensor/uptime_text_sensor.h index 4baf1039b6..5719ef38a2 100644 --- a/esphome/components/uptime/text_sensor/uptime_text_sensor.h +++ b/esphome/components/uptime/text_sensor/uptime_text_sensor.h @@ -17,8 +17,8 @@ class UptimeTextSensor : public text_sensor::TextSensor, public PollingComponent float get_setup_priority() const override; protected: - uint64_t uptime_{0}; - uint64_t last_ms_{0}; + uint32_t uptime_{0}; // uptime in seconds, will overflow after 136 years + uint32_t last_ms_{0}; }; } // namespace uptime diff --git a/esphome/components/waveshare_epaper/waveshare_213v3.cpp b/esphome/components/waveshare_epaper/waveshare_213v3.cpp index 196aeed3f7..85d7033d4b 100644 --- a/esphome/components/waveshare_epaper/waveshare_213v3.cpp +++ b/esphome/components/waveshare_epaper/waveshare_213v3.cpp @@ -72,7 +72,8 @@ void WaveshareEPaper2P13InV3::write_buffer_(uint8_t cmd, int top, int bottom) { this->set_window_(top, bottom); this->command(cmd); this->start_data_(); - auto width_bytes = this->get_width_internal() / 8; + + auto width_bytes = this->get_width_controller() / 8; this->write_array(this->buffer_ + top * width_bytes, (bottom - top) * width_bytes); this->end_data_(); } @@ -162,7 +163,8 @@ void WaveshareEPaper2P13InV3::display() { } } -int WaveshareEPaper2P13InV3::get_width_internal() { return 128; } +int WaveshareEPaper2P13InV3::get_width_controller() { return 128; } +int WaveshareEPaper2P13InV3::get_width_internal() { return 122; } int WaveshareEPaper2P13InV3::get_height_internal() { return 250; } diff --git a/esphome/components/waveshare_epaper/waveshare_epaper.h b/esphome/components/waveshare_epaper/waveshare_epaper.h index 4544f7df59..0fc1051268 100644 --- a/esphome/components/waveshare_epaper/waveshare_epaper.h +++ b/esphome/components/waveshare_epaper/waveshare_epaper.h @@ -811,6 +811,7 @@ class WaveshareEPaper2P13InV3 : public WaveshareEPaper { void initialize() override; protected: + int get_width_controller() override; int get_width_internal() override; int get_height_internal() override; uint32_t idle_timeout_() override; diff --git a/esphome/config.py b/esphome/config.py index 65e9ac29bc..09ee2a8f9b 100644 --- a/esphome/config.py +++ b/esphome/config.py @@ -22,7 +22,6 @@ from esphome.const import ( CONF_PACKAGES, CONF_PLATFORM, CONF_SUBSTITUTIONS, - TARGET_PLATFORMS, ) from esphome.core import CORE, DocumentRange, EsphomeError import esphome.core.config as core_config @@ -833,7 +832,7 @@ def validate_config( result[CONF_ESPHOME] = config[CONF_ESPHOME] result.add_output_path([CONF_ESPHOME], CONF_ESPHOME) try: - core_config.preload_core_config(config, result) + target_platform = core_config.preload_core_config(config, result) except vol.Invalid as err: result.add_error(err) return result @@ -845,9 +844,9 @@ def validate_config( cv.All(cv.version_number, cv.validate_esphome_version)(min_version) # First run platform validation steps - for key in TARGET_PLATFORMS: - if key in config: - result.add_validation_step(LoadValidationStep(key, config[key])) + result.add_validation_step( + LoadValidationStep(target_platform, config[target_platform]) + ) result.run_validation_steps() if result.errors: diff --git a/esphome/const.py b/esphome/const.py index 284f8d5f78..95bf6afc02 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -15,15 +15,6 @@ PLATFORM_LIBRETINY_OLDSTYLE = "libretiny" PLATFORM_RP2040 = "rp2040" PLATFORM_RTL87XX = "rtl87xx" -TARGET_PLATFORMS = [ - PLATFORM_BK72XX, - PLATFORM_ESP32, - PLATFORM_ESP8266, - PLATFORM_HOST, - PLATFORM_LIBRETINY_OLDSTYLE, - PLATFORM_RP2040, - PLATFORM_RTL87XX, -] SOURCE_FILE_EXTENSIONS = {".cpp", ".hpp", ".h", ".c", ".tcc", ".ino"} HEADER_FILE_EXTENSIONS = {".h", ".hpp", ".tcc"} diff --git a/esphome/core/config.py b/esphome/core/config.py index eee8b73934..06ae1d7747 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -1,21 +1,17 @@ import logging import multiprocessing import os -import re +from pathlib import Path from esphome import automation import esphome.codegen as cg import esphome.config_validation as cv from esphome.const import ( - CONF_ARDUINO_VERSION, CONF_AREA, - CONF_BOARD, - CONF_BOARD_FLASH_MODE, CONF_BUILD_PATH, CONF_COMMENT, CONF_COMPILE_PROCESS_LIMIT, CONF_ESPHOME, - CONF_FRAMEWORK, CONF_FRIENDLY_NAME, CONF_INCLUDES, CONF_LIBRARIES, @@ -30,13 +26,9 @@ from esphome.const import ( CONF_PLATFORMIO_OPTIONS, CONF_PRIORITY, CONF_PROJECT, - CONF_SOURCE, CONF_TRIGGER_ID, - CONF_TYPE, CONF_VERSION, KEY_CORE, - PLATFORM_ESP8266, - TARGET_PLATFORMS, __version__ as ESPHOME_VERSION, ) from esphome.core import CORE, coroutine_with_priority @@ -44,7 +36,6 @@ from esphome.helpers import copy_file_if_changed, get_str_env, walk_files _LOGGER = logging.getLogger(__name__) -BUILD_FLASH_MODES = ["qio", "qout", "dio", "dout"] StartupTrigger = cg.esphome_ns.class_( "StartupTrigger", cg.Component, automation.Trigger.template() ) @@ -58,8 +49,6 @@ ProjectUpdateTrigger = cg.esphome_ns.class_( "ProjectUpdateTrigger", cg.Component, automation.Trigger.template(cg.std_string) ) -VERSION_REGEX = re.compile(r"^[0-9]+\.[0-9]+\.[0-9]+(?:[ab]\d+)?$") - VALID_INCLUDE_EXTS = {".h", ".hpp", ".tcc", ".ino", ".cpp", ".c"} @@ -111,7 +100,6 @@ else: _compile_process_limit_default = cv.UNDEFINED -CONF_ESP8266_RESTORE_FROM_FLASH = "esp8266_restore_from_flash" CONFIG_SCHEMA = cv.All( cv.Schema( { @@ -175,14 +163,9 @@ PRELOAD_CONFIG_SCHEMA = cv.Schema( { cv.Required(CONF_NAME): cv.valid_name, cv.Optional(CONF_BUILD_PATH): cv.string, - # Compat options, these were moved to target-platform specific sections - # but we'll keep these around for a long time because every config would - # be impacted - cv.Optional(CONF_PLATFORM): cv.one_of(*TARGET_PLATFORMS, lower=True), - cv.Optional(CONF_BOARD): cv.string_strict, - cv.Optional(CONF_ESP8266_RESTORE_FROM_FLASH): cv.valid, - cv.Optional(CONF_BOARD_FLASH_MODE): cv.valid, - cv.Optional(CONF_ARDUINO_VERSION): cv.valid, + cv.Optional(CONF_PLATFORM): cv.invalid( + "Please remove the `platform` key from the [esphome] block and use the correct platform component. This style of configuration has now been removed." + ), cv.Optional(CONF_MIN_VERSION, default=ESPHOME_VERSION): cv.All( cv.version_number, cv.validate_esphome_version ), @@ -191,7 +174,31 @@ PRELOAD_CONFIG_SCHEMA = cv.Schema( ) -def preload_core_config(config, result): +def _is_target_platform(name): + from esphome.loader import get_component + + try: + if get_component(name, True).is_target_platform: + return True + except KeyError: + pass + return False + + +def _list_target_platforms(): + target_platforms = [] + root = Path(__file__).parents[1] + for path in (root / "components").iterdir(): + if not path.is_dir(): + continue + if not (path / "__init__.py").is_file(): + continue + if _is_target_platform(path.name): + target_platforms += [path.name] + return target_platforms + + +def preload_core_config(config, result) -> str: with cv.prepend_path(CONF_ESPHOME): conf = PRELOAD_CONFIG_SCHEMA(config[CONF_ESPHOME]) @@ -204,63 +211,26 @@ def preload_core_config(config, result): conf[CONF_BUILD_PATH] = os.path.join(build_path, CORE.name) CORE.build_path = CORE.relative_internal_path(conf[CONF_BUILD_PATH]) - has_oldstyle = CONF_PLATFORM in conf - newstyle_found = [key for key in TARGET_PLATFORMS if key in config] - oldstyle_opts = [ - CONF_ESP8266_RESTORE_FROM_FLASH, - CONF_BOARD_FLASH_MODE, - CONF_ARDUINO_VERSION, - CONF_BOARD, - ] + target_platforms = [] - if not has_oldstyle and not newstyle_found: + for domain, _ in config.items(): + if _is_target_platform(domain): + target_platforms += [domain] + + if not target_platforms: raise cv.Invalid( "Platform missing. You must include one of the available platform keys: " - + ", ".join(TARGET_PLATFORMS), + + ", ".join(_list_target_platforms()), [CONF_ESPHOME], ) - if has_oldstyle and newstyle_found: + if len(target_platforms) > 1: raise cv.Invalid( - f"Please remove the `platform` key from the [esphome] block. You're already using the new style with the [{conf[CONF_PLATFORM]}] block", - [CONF_ESPHOME, CONF_PLATFORM], + f"Found multiple target platform blocks: {', '.join(target_platforms)}. Only one is allowed.", + [target_platforms[0]], ) - if len(newstyle_found) > 1: - raise cv.Invalid( - f"Found multiple target platform blocks: {', '.join(newstyle_found)}. Only one is allowed.", - [newstyle_found[0]], - ) - if newstyle_found: - # Convert to newstyle - for key in oldstyle_opts: - if key in conf: - raise cv.Invalid( - f"Please move {key} to the [{newstyle_found[0]}] block.", - [CONF_ESPHOME, key], - ) - if has_oldstyle: - plat = conf.pop(CONF_PLATFORM) - plat_conf = {} - if CONF_ESP8266_RESTORE_FROM_FLASH in conf: - plat_conf["restore_from_flash"] = conf.pop(CONF_ESP8266_RESTORE_FROM_FLASH) - if CONF_BOARD_FLASH_MODE in conf: - plat_conf[CONF_BOARD_FLASH_MODE] = conf.pop(CONF_BOARD_FLASH_MODE) - if CONF_ARDUINO_VERSION in conf: - plat_conf[CONF_FRAMEWORK] = {} - if plat != PLATFORM_ESP8266: - plat_conf[CONF_FRAMEWORK][CONF_TYPE] = "arduino" - - try: - if conf[CONF_ARDUINO_VERSION] not in ("recommended", "latest", "dev"): - cv.Version.parse(conf[CONF_ARDUINO_VERSION]) - plat_conf[CONF_FRAMEWORK][CONF_VERSION] = conf.pop(CONF_ARDUINO_VERSION) - except ValueError: - plat_conf[CONF_FRAMEWORK][CONF_SOURCE] = conf.pop(CONF_ARDUINO_VERSION) - if CONF_BOARD in conf: - plat_conf[CONF_BOARD] = conf.pop(CONF_BOARD) - # Insert generated target platform config to main config - config[plat] = plat_conf config[CONF_ESPHOME] = conf + return target_platforms[0] def include_file(path, basename): diff --git a/esphome/core/defines.h b/esphome/core/defines.h index c38a26c6a8..96a05435ed 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -120,7 +120,7 @@ #endif #ifdef USE_ESP_IDF -#define USE_ESP_IDF_VERSION_CODE VERSION_CODE(4, 4, 2) +#define USE_ESP_IDF_VERSION_CODE VERSION_CODE(5, 1, 5) #endif #if defined(USE_ESP32_VARIANT_ESP32S2) diff --git a/esphome/loader.py b/esphome/loader.py index d808805119..0fb4187b04 100644 --- a/esphome/loader.py +++ b/esphome/loader.py @@ -52,6 +52,10 @@ class ComponentManifest: def is_platform_component(self) -> bool: return getattr(self.module, "IS_PLATFORM_COMPONENT", False) + @property + def is_target_platform(self) -> bool: + return getattr(self.module, "IS_TARGET_PLATFORM", False) + @property def config_schema(self) -> Optional[Any]: return getattr(self.module, "CONFIG_SCHEMA", None) @@ -169,13 +173,15 @@ def install_custom_components_meta_finder(): install_meta_finder(custom_components_dir) -def _lookup_module(domain): +def _lookup_module(domain, exception): if domain in _COMPONENT_CACHE: return _COMPONENT_CACHE[domain] try: module = importlib.import_module(f"esphome.components.{domain}") except ImportError as e: + if exception: + raise if "No module named" in str(e): _LOGGER.info( "Unable to import component %s: %s", domain, str(e), exc_info=False @@ -184,6 +190,8 @@ def _lookup_module(domain): _LOGGER.error("Unable to import component %s:", domain, exc_info=True) return None except Exception: # pylint: disable=broad-except + if exception: + raise _LOGGER.error("Unable to load component %s:", domain, exc_info=True) return None @@ -192,14 +200,14 @@ def _lookup_module(domain): return manif -def get_component(domain): +def get_component(domain, exception=False): assert "." not in domain - return _lookup_module(domain) + return _lookup_module(domain, exception) def get_platform(domain, platform): full = f"{platform}.{domain}" - return _lookup_module(full) + return _lookup_module(full, False) _COMPONENT_CACHE = {} diff --git a/script/run-in-env b/script/run-in-env new file mode 100644 index 0000000000..57bfddccf7 --- /dev/null +++ b/script/run-in-env @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 + +import os +from pathlib import Path +import subprocess +import sys + + +def find_and_activate_virtualenv(): + try: + # Get the top-level directory of the git repository + my_path = subprocess.check_output( + ["git", "rev-parse", "--show-toplevel"], text=True + ).strip() + except subprocess.CalledProcessError: + print( + "Error: Not a git repository or unable to determine the top-level directory.", + file=sys.stderr, + ) + sys.exit(1) + + # Check for virtual environments + for venv in ["venv", ".venv", "."]: + activate_path = ( + Path(my_path) + / venv + / ("Scripts" if os.name == "nt" else "bin") + / "activate" + ) + if activate_path.exists(): + # Activate the virtual environment by updating PATH + env = os.environ.copy() + venv_bin_dir = activate_path.parent + env["PATH"] = f"{venv_bin_dir}{os.pathsep}{env['PATH']}" + env["VIRTUAL_ENV"] = str(venv_bin_dir.parent) + print(f"Activated virtual environment: {venv_bin_dir.parent}") + + # Execute the remaining arguments in the new environment + if len(sys.argv) > 1: + subprocess.run(sys.argv[1:], env=env, check=False) + else: + print( + "No command provided to run in the virtual environment.", + file=sys.stderr, + ) + return + + print("No virtual environment found.", file=sys.stderr) + sys.exit(1) + + +if __name__ == "__main__": + find_and_activate_virtualenv() diff --git a/script/run-in-env.sh b/script/run-in-env.sh deleted file mode 100755 index 2e05fe1d17..0000000000 --- a/script/run-in-env.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env sh -set -eu - -my_path=$(git rev-parse --show-toplevel) - -for venv in venv .venv .; do - if [ -f "${my_path}/${venv}/bin/activate" ]; then - . "${my_path}/${venv}/bin/activate" - break - fi -done - -exec "$@" diff --git a/tests/component_tests/binary_sensor/test_binary_sensor.yaml b/tests/component_tests/binary_sensor/test_binary_sensor.yaml index f98ce693f7..8842dda837 100644 --- a/tests/component_tests/binary_sensor/test_binary_sensor.yaml +++ b/tests/component_tests/binary_sensor/test_binary_sensor.yaml @@ -1,7 +1,8 @@ --- esphome: name: test - platform: ESP8266 + +esp8266: board: d1_mini_lite binary_sensor: diff --git a/tests/component_tests/button/test_button.yaml b/tests/component_tests/button/test_button.yaml index 48e13f0353..916c85cb8b 100644 --- a/tests/component_tests/button/test_button.yaml +++ b/tests/component_tests/button/test_button.yaml @@ -1,7 +1,8 @@ --- esphome: name: test - platform: ESP8266 + +esp8266: board: d1_mini_lite wifi: diff --git a/tests/component_tests/deep_sleep/test_deep_sleep1.yaml b/tests/component_tests/deep_sleep/test_deep_sleep1.yaml index 96514a677f..03145290a9 100644 --- a/tests/component_tests/deep_sleep/test_deep_sleep1.yaml +++ b/tests/component_tests/deep_sleep/test_deep_sleep1.yaml @@ -1,7 +1,8 @@ --- esphome: name: test - platform: ESP32 + +esp32: board: nodemcu-32s deep_sleep: diff --git a/tests/component_tests/deep_sleep/test_deep_sleep2.yaml b/tests/component_tests/deep_sleep/test_deep_sleep2.yaml index 0e8e598402..88ebb31728 100644 --- a/tests/component_tests/deep_sleep/test_deep_sleep2.yaml +++ b/tests/component_tests/deep_sleep/test_deep_sleep2.yaml @@ -1,7 +1,8 @@ --- esphome: name: test - platform: ESP32 + +esp32: board: nodemcu-32s deep_sleep: diff --git a/tests/component_tests/sensor/test_sensor.yaml b/tests/component_tests/sensor/test_sensor.yaml index 8c0fd85b17..612b8e5e56 100644 --- a/tests/component_tests/sensor/test_sensor.yaml +++ b/tests/component_tests/sensor/test_sensor.yaml @@ -1,7 +1,8 @@ --- esphome: name: test - platform: ESP8266 + +esp8266: board: d1_mini_lite sensor: diff --git a/tests/component_tests/text_sensor/test_text_sensor.yaml b/tests/component_tests/text_sensor/test_text_sensor.yaml index b426cb102c..9cc75082ac 100644 --- a/tests/component_tests/text_sensor/test_text_sensor.yaml +++ b/tests/component_tests/text_sensor/test_text_sensor.yaml @@ -1,7 +1,8 @@ --- esphome: name: test - platform: ESP8266 + +esp8266: board: d1_mini_lite text_sensor: diff --git a/tests/components/ads1115/test.esp32-ard.yaml b/tests/components/ads1115/test.esp32-ard.yaml index a869f2379b..0fdaeff275 100644 --- a/tests/components/ads1115/test.esp32-ard.yaml +++ b/tests/components/ads1115/test.esp32-ard.yaml @@ -10,4 +10,5 @@ sensor: - platform: ads1115 multiplexer: A0_A1 gain: 1.024 + sample_rate: 128 id: ads1115_sensor diff --git a/tests/components/ads1115/test.esp32-c3-ard.yaml b/tests/components/ads1115/test.esp32-c3-ard.yaml index 7ac5a09f3f..265d2cad2c 100644 --- a/tests/components/ads1115/test.esp32-c3-ard.yaml +++ b/tests/components/ads1115/test.esp32-c3-ard.yaml @@ -10,4 +10,5 @@ sensor: - platform: ads1115 multiplexer: A0_A1 gain: 1.024 + sample_rate: 128 id: ads1115_sensor diff --git a/tests/components/ads1115/test.esp32-c3-idf.yaml b/tests/components/ads1115/test.esp32-c3-idf.yaml index 7ac5a09f3f..265d2cad2c 100644 --- a/tests/components/ads1115/test.esp32-c3-idf.yaml +++ b/tests/components/ads1115/test.esp32-c3-idf.yaml @@ -10,4 +10,5 @@ sensor: - platform: ads1115 multiplexer: A0_A1 gain: 1.024 + sample_rate: 128 id: ads1115_sensor diff --git a/tests/components/ads1115/test.esp32-idf.yaml b/tests/components/ads1115/test.esp32-idf.yaml index a869f2379b..0fdaeff275 100644 --- a/tests/components/ads1115/test.esp32-idf.yaml +++ b/tests/components/ads1115/test.esp32-idf.yaml @@ -10,4 +10,5 @@ sensor: - platform: ads1115 multiplexer: A0_A1 gain: 1.024 + sample_rate: 128 id: ads1115_sensor diff --git a/tests/components/ads1115/test.esp8266-ard.yaml b/tests/components/ads1115/test.esp8266-ard.yaml index 7ac5a09f3f..265d2cad2c 100644 --- a/tests/components/ads1115/test.esp8266-ard.yaml +++ b/tests/components/ads1115/test.esp8266-ard.yaml @@ -10,4 +10,5 @@ sensor: - platform: ads1115 multiplexer: A0_A1 gain: 1.024 + sample_rate: 128 id: ads1115_sensor diff --git a/tests/components/ads1115/test.rp2040-ard.yaml b/tests/components/ads1115/test.rp2040-ard.yaml index 7ac5a09f3f..265d2cad2c 100644 --- a/tests/components/ads1115/test.rp2040-ard.yaml +++ b/tests/components/ads1115/test.rp2040-ard.yaml @@ -10,4 +10,5 @@ sensor: - platform: ads1115 multiplexer: A0_A1 gain: 1.024 + sample_rate: 128 id: ads1115_sensor diff --git a/tests/components/animation/common.yaml b/tests/components/animation/common.yaml index c0f04fe768..8bb2a2f4d8 100644 --- a/tests/components/animation/common.yaml +++ b/tests/components/animation/common.yaml @@ -2,12 +2,12 @@ animation: - id: rgb565_animation file: $component_dir/anim.gif type: RGB565 - use_transparency: opaque + transparency: opaque resize: 50x50 - id: rgb_animation file: $component_dir/anim.apng type: RGB - use_transparency: chroma_key + transparency: chroma_key resize: 50x50 - id: grayscale_animation file: $component_dir/anim.apng diff --git a/tests/components/es7210/common.yaml b/tests/components/es7210/common.yaml index 5c30f7e883..3fab177cb3 100644 --- a/tests/components/es7210/common.yaml +++ b/tests/components/es7210/common.yaml @@ -1,6 +1,16 @@ +esphome: + on_boot: + then: + - audio_adc.set_mic_gain: 0db + - audio_adc.set_mic_gain: !lambda 'return 4;' + i2c: - id: i2c_aic3204 scl: ${scl_pin} sda: ${sda_pin} -es7210: +audio_adc: + - platform: es7210 + id: es7210_adc + bits_per_sample: 16bit + sample_rate: 16000 diff --git a/tests/components/es7243e/common.yaml b/tests/components/es7243e/common.yaml new file mode 100644 index 0000000000..3de76909e9 --- /dev/null +++ b/tests/components/es7243e/common.yaml @@ -0,0 +1,14 @@ +esphome: + on_boot: + then: + - audio_adc.set_mic_gain: 0db + - audio_adc.set_mic_gain: !lambda 'return 4;' + +i2c: + - id: i2c_es7243e + scl: ${scl_pin} + sda: ${sda_pin} + +audio_adc: + - platform: es7243e + id: es7243e_adc diff --git a/tests/components/es7243e/test.esp32-ard.yaml b/tests/components/es7243e/test.esp32-ard.yaml new file mode 100644 index 0000000000..63c3bd6afd --- /dev/null +++ b/tests/components/es7243e/test.esp32-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO16 + sda_pin: GPIO17 + +<<: !include common.yaml diff --git a/tests/components/es7243e/test.esp32-c3-ard.yaml b/tests/components/es7243e/test.esp32-c3-ard.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/es7243e/test.esp32-c3-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/es7243e/test.esp32-c3-idf.yaml b/tests/components/es7243e/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/es7243e/test.esp32-c3-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/es7243e/test.esp32-idf.yaml b/tests/components/es7243e/test.esp32-idf.yaml new file mode 100644 index 0000000000..63c3bd6afd --- /dev/null +++ b/tests/components/es7243e/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO16 + sda_pin: GPIO17 + +<<: !include common.yaml diff --git a/tests/components/es8156/common.yaml b/tests/components/es8156/common.yaml new file mode 100644 index 0000000000..addaa0b70a --- /dev/null +++ b/tests/components/es8156/common.yaml @@ -0,0 +1,15 @@ +esphome: + on_boot: + then: + - audio_dac.mute_off: + - audio_dac.mute_on: + - audio_dac.set_volume: + volume: 50% + +i2c: + - id: i2c_es8156 + scl: ${scl_pin} + sda: ${sda_pin} + +audio_dac: + - platform: es8156 diff --git a/tests/components/es8156/test.esp32-ard.yaml b/tests/components/es8156/test.esp32-ard.yaml new file mode 100644 index 0000000000..63c3bd6afd --- /dev/null +++ b/tests/components/es8156/test.esp32-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO16 + sda_pin: GPIO17 + +<<: !include common.yaml diff --git a/tests/components/es8156/test.esp32-c3-ard.yaml b/tests/components/es8156/test.esp32-c3-ard.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/es8156/test.esp32-c3-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/es8156/test.esp32-c3-idf.yaml b/tests/components/es8156/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/es8156/test.esp32-c3-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/es8156/test.esp32-idf.yaml b/tests/components/es8156/test.esp32-idf.yaml new file mode 100644 index 0000000000..63c3bd6afd --- /dev/null +++ b/tests/components/es8156/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO16 + sda_pin: GPIO17 + +<<: !include common.yaml diff --git a/tests/components/es8156/test.esp8266-ard.yaml b/tests/components/es8156/test.esp8266-ard.yaml new file mode 100644 index 0000000000..ee2c29ca4e --- /dev/null +++ b/tests/components/es8156/test.esp8266-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + scl_pin: GPIO5 + sda_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/components/image/common.yaml b/tests/components/image/common.yaml index fdb0493d2a..4c9b9ed670 100644 --- a/tests/components/image/common.yaml +++ b/tests/components/image/common.yaml @@ -6,54 +6,54 @@ image: - id: transparent_transparent_image file: ../../pnglogo.png type: BINARY - use_transparency: chroma_key + transparency: chroma_key - id: rgba_image file: ../../pnglogo.png type: RGB - use_transparency: alpha_channel + transparency: alpha_channel resize: 50x50 - id: rgb24_image file: ../../pnglogo.png type: RGB - use_transparency: chroma_key + transparency: chroma_key - id: rgb_image file: ../../pnglogo.png type: RGB - use_transparency: opaque + transparency: opaque - id: rgb565_image file: ../../pnglogo.png type: RGB565 - use_transparency: opaque + transparency: opaque - id: rgb565_ck_image file: ../../pnglogo.png type: RGB565 - use_transparency: chroma_key + transparency: chroma_key - id: rgb565_alpha_image file: ../../pnglogo.png type: RGB565 - use_transparency: alpha_channel + transparency: alpha_channel - id: grayscale_alpha_image file: ../../pnglogo.png type: grayscale - use_transparency: alpha_channel + transparency: alpha_channel resize: 50x50 - id: grayscale_ck_image file: ../../pnglogo.png type: grayscale - use_transparency: chroma_key + transparency: chroma_key - id: grayscale_image file: ../../pnglogo.png type: grayscale - use_transparency: opaque + transparency: opaque - id: web_svg_image file: https://raw.githubusercontent.com/esphome/esphome-docs/a62d7ab193c1a464ed791670170c7d518189109b/images/logo.svg resize: 256x48 type: BINARY - use_transparency: chroma_key + transparency: chroma_key - id: web_tiff_image file: https://upload.wikimedia.org/wikipedia/commons/b/b6/SIPI_Jelly_Beans_4.1.07.tiff type: RGB diff --git a/tests/components/image/test.host.yaml b/tests/components/image/test.host.yaml index 61ecd5e374..0411195e2a 100644 --- a/tests/components/image/test.host.yaml +++ b/tests/components/image/test.host.yaml @@ -12,7 +12,7 @@ image: dither: FloydSteinberg - id: transparent_transparent_image file: ../../pnglogo.png - use_transparency: chroma_key + transparency: chroma_key rgb: alpha_channel: - id: rgba_image @@ -28,21 +28,21 @@ image: rgb565: - id: rgb565_image file: ../../pnglogo.png - use_transparency: opaque + transparency: opaque - id: rgb565_ck_image file: ../../pnglogo.png - use_transparency: chroma_key + transparency: chroma_key - id: rgb565_alpha_image file: ../../pnglogo.png - use_transparency: alpha_channel + transparency: alpha_channel grayscale: - id: grayscale_alpha_image file: ../../pnglogo.png - use_transparency: alpha_channel + transparency: alpha_channel resize: 50x50 - id: grayscale_ck_image file: ../../pnglogo.png - use_transparency: chroma_key + transparency: chroma_key - id: grayscale_image file: ../../pnglogo.png - use_transparency: opaque + transparency: opaque diff --git a/tests/components/online_image/common.yaml b/tests/components/online_image/common.yaml index 81f43e9fdc..6c161e4f20 100644 --- a/tests/components/online_image/common.yaml +++ b/tests/components/online_image/common.yaml @@ -14,18 +14,18 @@ online_image: - id: online_binary_transparent_image url: http://www.libpng.org/pub/png/img_png/pnglogo-blk-tiny.png type: BINARY - use_transparency: chroma_key + transparency: chroma_key format: png - id: online_rgba_image url: http://www.libpng.org/pub/png/img_png/pnglogo-blk-tiny.png format: PNG type: RGB - use_transparency: alpha_channel + transparency: alpha_channel - id: online_rgb24_image url: http://www.libpng.org/pub/png/img_png/pnglogo-blk-tiny.png format: PNG type: RGB - use_transparency: chroma_key + transparency: chroma_key # Check the set_url action esphome: diff --git a/tests/components/seeed_mr60bha2/common.yaml b/tests/components/seeed_mr60bha2/common.yaml index e9d0c735af..9eb0c8d527 100644 --- a/tests/components/seeed_mr60bha2/common.yaml +++ b/tests/components/seeed_mr60bha2/common.yaml @@ -9,6 +9,11 @@ uart: seeed_mr60bha2: id: my_seeed_mr60bha2 +binary_sensor: + - platform: seeed_mr60bha2 + has_target: + name: "Person Information" + sensor: - platform: seeed_mr60bha2 breath_rate: @@ -17,3 +22,5 @@ sensor: name: "Real-time heart rate" distance: name: "Distance to detection object" + num_targets: + name: "Target Number" diff --git a/tests/unit_tests/fixtures/yaml_util/broken_includetest.yaml b/tests/unit_tests/fixtures/yaml_util/broken_includetest.yaml index aaca55b807..a49ae706a4 100644 --- a/tests/unit_tests/fixtures/yaml_util/broken_includetest.yaml +++ b/tests/unit_tests/fixtures/yaml_util/broken_includetest.yaml @@ -12,7 +12,7 @@ esphome: # not overwritten by vars in the !include above name: ${name} name_add_mac_suffix: true - platform: esp8266 - board: !include {file: includes/scalar.yaml, vars: {var1: nodemcu}} - libraries: !include {file: includes/list.yaml, vars: {var1: Wire}} + +esp8266: + board: !include {file: includes/scalar.yaml, vars: {var1: nodemcu}} diff --git a/tests/unit_tests/fixtures/yaml_util/includetest.yaml b/tests/unit_tests/fixtures/yaml_util/includetest.yaml index af0a4e2030..7b01da6a17 100644 --- a/tests/unit_tests/fixtures/yaml_util/includetest.yaml +++ b/tests/unit_tests/fixtures/yaml_util/includetest.yaml @@ -12,7 +12,7 @@ esphome: # not overwritten by vars in the !include above name: ${name} name_add_mac_suffix: true - platform: esp8266 - board: !include {file: includes/scalar.yaml, vars: {var1: nodemcu}} - libraries: !include {file: includes/list.yaml, vars: {var1: Wire}} + +esp8266: + board: !include {file: includes/scalar.yaml, vars: {var1: nodemcu}} diff --git a/tests/unit_tests/test_yaml_util.py b/tests/unit_tests/test_yaml_util.py index 9178726247..828b2bf14b 100644 --- a/tests/unit_tests/test_yaml_util.py +++ b/tests/unit_tests/test_yaml_util.py @@ -10,7 +10,7 @@ def test_include_with_vars(fixture_path): substitutions.do_substitution_pass(actual, None) assert actual["esphome"]["name"] == "original" assert actual["esphome"]["libraries"][0] == "Wire" - assert actual["esphome"]["board"] == "nodemcu" + assert actual["esp8266"]["board"] == "nodemcu" assert actual["wifi"]["ssid"] == "my_custom_ssid"