1
0
mirror of https://github.com/esphome/esphome.git synced 2025-03-15 23:28:13 +00:00

Merge branch 'dev' into nrf52_core

This commit is contained in:
tomaszduda23 2025-01-21 16:10:29 +01:00 committed by GitHub
commit 5c4148c49c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
56 changed files with 770 additions and 335 deletions

View File

@ -11,14 +11,6 @@ repos:
args: [--fix] args: [--fix]
# Run the formatter. # Run the formatter.
- id: ruff-format - 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 - repo: https://github.com/PyCQA/flake8
rev: 6.1.0 rev: 6.1.0
hooks: hooks:
@ -53,6 +45,6 @@ repos:
hooks: hooks:
- id: pylint - id: pylint
name: pylint name: pylint
entry: script/run-in-env.sh pylint entry: python script/run-in-env pylint
language: script language: system
types: [python] types: [python]

View File

@ -49,6 +49,7 @@ esphome/components/atc_mithermometer/* @ahpohl
esphome/components/atm90e26/* @danieltwagner esphome/components/atm90e26/* @danieltwagner
esphome/components/atm90e32/* @circuitsetup @descipher esphome/components/atm90e32/* @circuitsetup @descipher
esphome/components/audio/* @kahrendt esphome/components/audio/* @kahrendt
esphome/components/audio_adc/* @kbx81
esphome/components/audio_dac/* @kbx81 esphome/components/audio_dac/* @kbx81
esphome/components/axs15231/* @clydebarrow esphome/components/axs15231/* @clydebarrow
esphome/components/b_parasite/* @rbaron esphome/components/b_parasite/* @rbaron
@ -132,6 +133,7 @@ esphome/components/ens160_i2c/* @latonita
esphome/components/ens160_spi/* @latonita esphome/components/ens160_spi/* @latonita
esphome/components/ens210/* @itn3rd77 esphome/components/ens210/* @itn3rd77
esphome/components/es7210/* @kahrendt esphome/components/es7210/* @kahrendt
esphome/components/es8156/* @kbx81
esphome/components/es8311/* @kahrendt @kroimon esphome/components/es8311/* @kahrendt @kroimon
esphome/components/esp32/* @esphome/core esphome/components/esp32/* @esphome/core
esphome/components/esp32_ble/* @Rapsssito @jesserockz esphome/components/esp32_ble/* @Rapsssito @jesserockz

View File

@ -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)

View File

@ -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

View File

@ -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<typename... Ts> class SetMicGainAction : public Action<Ts...> {
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

View File

@ -298,6 +298,12 @@ void DalyBmsComponent::decode_data_(std::vector<uint8_t> data) {
if (this->cell_16_voltage_sensor_) { if (this->cell_16_voltage_sensor_) {
this->cell_16_voltage_sensor_->publish_state((float) encode_uint16(it[5], it[6]) / 1000); 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;
} }
break; break;

View File

@ -54,6 +54,8 @@ class DalyBmsComponent : public PollingComponent, public uart::UARTDevice {
SUB_SENSOR(cell_14_voltage) SUB_SENSOR(cell_14_voltage)
SUB_SENSOR(cell_15_voltage) SUB_SENSOR(cell_15_voltage)
SUB_SENSOR(cell_16_voltage) SUB_SENSOR(cell_16_voltage)
SUB_SENSOR(cell_17_voltage)
SUB_SENSOR(cell_18_voltage)
#endif #endif
#ifdef USE_TEXT_SENSOR #ifdef USE_TEXT_SENSOR

View File

@ -52,6 +52,8 @@ CONF_CELL_13_VOLTAGE = "cell_13_voltage"
CONF_CELL_14_VOLTAGE = "cell_14_voltage" CONF_CELL_14_VOLTAGE = "cell_14_voltage"
CONF_CELL_15_VOLTAGE = "cell_15_voltage" CONF_CELL_15_VOLTAGE = "cell_15_voltage"
CONF_CELL_16_VOLTAGE = "cell_16_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_CURRENT_DC = "mdi:current-dc"
ICON_BATTERY_OUTLINE = "mdi:battery-outline" ICON_BATTERY_OUTLINE = "mdi:battery-outline"
ICON_THERMOMETER_CHEVRON_UP = "mdi:thermometer-chevron-up" ICON_THERMOMETER_CHEVRON_UP = "mdi:thermometer-chevron-up"
@ -92,6 +94,8 @@ TYPES = [
CONF_CELL_14_VOLTAGE, CONF_CELL_14_VOLTAGE,
CONF_CELL_15_VOLTAGE, CONF_CELL_15_VOLTAGE,
CONF_CELL_16_VOLTAGE, CONF_CELL_16_VOLTAGE,
CONF_CELL_17_VOLTAGE,
CONF_CELL_18_VOLTAGE,
] ]
CELL_VOLTAGE_SCHEMA = sensor.sensor_schema( 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_14_VOLTAGE): CELL_VOLTAGE_SCHEMA,
cv.Optional(CONF_CELL_15_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_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) ).extend(cv.COMPONENT_SCHEMA)
) )

View File

@ -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]))

View File

@ -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]))

View File

@ -25,12 +25,12 @@ static const size_t MCLK_DIV_FRE = 256;
} }
void ES7210::dump_config() { 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, " Bits Per Sample: %" PRIu8, this->bits_per_sample_);
ESP_LOGCONFIG(TAG, " Sample Rate: %" PRIu32, this->sample_rate_); ESP_LOGCONFIG(TAG, " Sample Rate: %" PRIu32, this->sample_rate_);
if (this->is_failed()) { if (this->is_failed()) {
ESP_LOGCONFIG(TAG, " Failed to initialize!"); ESP_LOGE(TAG, " Failed to initialize");
return; return;
} }
} }
@ -84,6 +84,16 @@ void ES7210::setup() {
// Enable device // Enable device
ES7210_ERROR_FAILED(this->write_byte(ES7210_RESET_REG00, 0x71)); ES7210_ERROR_FAILED(this->write_byte(ES7210_RESET_REG00, 0x71));
ES7210_ERROR_FAILED(this->write_byte(ES7210_RESET_REG00, 0x41)); 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<float>(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_() { bool ES7210::configure_sample_rate_() {
@ -122,9 +132,11 @@ bool ES7210::configure_sample_rate_() {
return true; return true;
} }
bool ES7210::configure_mic_gain_() { bool ES7210::configure_mic_gain_() {
for (int i = 0; i < 4; ++i) { auto regv = this->es7210_gain_reg_value_(this->mic_gain_);
this->es7210_update_reg_bit_(ES7210_MIC1_GAIN_REG43 + i, 0x10, 0x00); 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_MIC12_POWER_REG4B, 0xff));
ES7210_ERROR_CHECK(this->write_byte(ES7210_MIC34_POWER_REG4C, 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->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->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, 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 // Configure mic 2
ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_CLOCK_OFF_REG01, 0x0b, 0x00)); 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->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, 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 // Configure mic 3
ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_CLOCK_OFF_REG01, 0x0b, 0x00)); 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->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, 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 // Configure mic 4
ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_CLOCK_OFF_REG01, 0x0b, 0x00)); 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->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, 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; 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_() { bool ES7210::configure_i2s_format_() {
// Configure bits per sample // Configure bits per sample
uint8_t reg_val = 0; uint8_t reg_val = 0;

View File

@ -1,8 +1,11 @@
#pragma once #pragma once
#include "esphome/components/audio_adc/audio_adc.h"
#include "esphome/components/i2c/i2c.h" #include "esphome/components/i2c/i2c.h"
#include "esphome/core/component.h" #include "esphome/core/component.h"
#include "es7210_const.h"
namespace esphome { namespace esphome {
namespace es7210 { namespace es7210 {
@ -14,25 +17,7 @@ enum ES7210BitsPerSample : uint8_t {
ES7210_BITS_PER_SAMPLE_32 = 32, ES7210_BITS_PER_SAMPLE_32 = 32,
}; };
enum ES7210MicGain : uint8_t { class ES7210 : public audio_adc::AudioAdc, public Component, public i2c::I2CDevice {
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 for configuring an ES7210 ADC for microphone input. /* Class for configuring an ES7210 ADC for microphone input.
* Based on code from: * Based on code from:
* - https://github.com/espressif/esp-bsp/ (accessed 20241219) * - https://github.com/espressif/esp-bsp/ (accessed 20241219)
@ -44,9 +29,11 @@ class ES7210 : public Component, public i2c::I2CDevice {
void dump_config() override; void dump_config() override;
void set_bits_per_sample(ES7210BitsPerSample bits_per_sample) { this->bits_per_sample_ = bits_per_sample; } 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; } void set_sample_rate(uint32_t sample_rate) { this->sample_rate_ = sample_rate; }
float mic_gain() override { return this->mic_gain_; };
protected: protected:
/// @brief Updates an I2C registry address by modifying the current state /// @brief Updates an I2C registry address by modifying the current state
/// @param reg_addr I2C register address /// @param reg_addr I2C register address
@ -55,14 +42,20 @@ class ES7210 : public Component, public i2c::I2CDevice {
/// @return True if successful, false otherwise /// @return True if successful, false otherwise
bool es7210_update_reg_bit_(uint8_t reg_addr, uint8_t update_bits, uint8_t data); 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_i2s_format_();
bool configure_mic_gain_(); bool configure_mic_gain_();
bool configure_sample_rate_(); bool configure_sample_rate_();
bool setup_complete_{false};
bool enable_tdm_{false}; // TDM is unsupported in ESPHome as of version 2024.12 bool enable_tdm_{false}; // TDM is unsupported in ESPHome as of version 2024.12
ES7210MicGain mic_gain_; float mic_gain_{0};
ES7210BitsPerSample bits_per_sample_; ES7210BitsPerSample bits_per_sample_{ES7210_BITS_PER_SAMPLE_16};
uint32_t sample_rate_; uint32_t sample_rate_{0};
}; };
} // namespace es7210 } // namespace es7210

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "es7210.h" #include <cinttypes>
namespace esphome { namespace esphome {
namespace es7210 { 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; static const uint8_t ES7210_MIC34_POWER_REG4C = 0x4C;
/* /*
* Clock coefficient structer * Clock coefficient structure
*/ */
struct ES7210Coefficient { struct ES7210Coefficient {
uint32_t mclk; // mclk frequency uint32_t mclk; // mclk frequency
@ -122,5 +122,8 @@ static const ES7210Coefficient ES7210_COEFFICIENTS[] = {
{19200000, 96000, 0x01, 0x05, 0x00, 0x01, 0x28, 0x00, 0x00, 0xc8}, {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 es7210
} // namespace esphome } // namespace esphome

View File

View File

@ -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)

View File

@ -0,0 +1,87 @@
#include "es8156.h"
#include "es8156_const.h"
#include "esphome/core/hal.h"
#include "esphome/core/log.h"
#include <cinttypes>
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<uint8_t, float>(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, &reg);
return remap<float, uint8_t>(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, &reg13)) {
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

View File

@ -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

View File

@ -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

View File

@ -52,7 +52,12 @@ void ESP32TouchComponent::setup() {
} }
#endif #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_); 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_); touch_pad_set_voltage(this->high_voltage_reference_, this->low_voltage_reference_, this->voltage_attenuation_);
for (auto *child : this->children_) { for (auto *child : this->children_) {

View File

@ -12,6 +12,8 @@
#include "esp_crt_bundle.h" #include "esp_crt_bundle.h"
#endif #endif
#include "esp_task_wdt.h"
namespace esphome { namespace esphome {
namespace http_request { namespace http_request {
@ -117,11 +119,11 @@ std::shared_ptr<HttpContainer> HttpRequestIDF::start(std::string url, std::strin
return nullptr; return nullptr;
} }
App.feed_wdt(); container->feed_wdt();
container->content_length = esp_http_client_fetch_headers(client); 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); container->status_code = esp_http_client_get_status_code(client);
App.feed_wdt(); container->feed_wdt();
if (is_success(container->status_code)) { if (is_success(container->status_code)) {
container->duration_ms = millis() - start; container->duration_ms = millis() - start;
return container; return container;
@ -151,11 +153,11 @@ std::shared_ptr<HttpContainer> HttpRequestIDF::start(std::string url, std::strin
return nullptr; return nullptr;
} }
App.feed_wdt(); container->feed_wdt();
container->content_length = esp_http_client_fetch_headers(client); 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); container->status_code = esp_http_client_get_status_code(client);
App.feed_wdt(); container->feed_wdt();
if (is_success(container->status_code)) { if (is_success(container->status_code)) {
container->duration_ms = millis() - start; container->duration_ms = millis() - start;
return container; return container;
@ -185,8 +187,9 @@ int HttpContainerIDF::read(uint8_t *buf, size_t max_len) {
return 0; return 0;
} }
App.feed_wdt(); this->feed_wdt();
int read_len = esp_http_client_read(this->client_, (char *) buf, bufsize); int read_len = esp_http_client_read(this->client_, (char *) buf, bufsize);
this->feed_wdt();
this->bytes_read_ += read_len; this->bytes_read_ += read_len;
this->duration_ms += (millis() - start); this->duration_ms += (millis() - start);
@ -201,6 +204,13 @@ void HttpContainerIDF::end() {
esp_http_client_cleanup(this->client_); 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 http_request
} // namespace esphome } // namespace esphome

View File

@ -18,6 +18,9 @@ class HttpContainerIDF : public HttpContainer {
int read(uint8_t *buf, size_t max_len) override; int read(uint8_t *buf, size_t max_len) override;
void end() override; void end() override;
/// @brief Feeds the watchdog timer if the executing task has one attached
void feed_wdt();
protected: protected:
esp_http_client_handle_t client_; esp_http_client_handle_t client_;
}; };

View File

@ -9,6 +9,13 @@
namespace esphome { namespace esphome {
namespace http_request { 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 char *const TAG = "http_request.update";
static const size_t MAX_READ_SIZE = 256; static const size_t MAX_READ_SIZE = 256;
@ -29,45 +36,57 @@ void HttpRequestUpdate::setup() {
} }
void HttpRequestUpdate::update() { 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) { 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()); std::string msg = str_sprintf("Failed to fetch manifest from %s", this_update->source_url_.c_str());
this->status_set_error(msg.c_str()); this_update->status_set_error(msg.c_str());
return; UPDATE_RETURN;
} }
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE); ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
uint8_t *data = allocator.allocate(container->content_length); uint8_t *data = allocator.allocate(container->content_length);
if (data == nullptr) { if (data == nullptr) {
std::string msg = str_sprintf("Failed to allocate %d bytes for manifest", container->content_length); 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(); container->end();
return; UPDATE_RETURN;
} }
size_t read_index = 0; size_t read_index = 0;
while (container->get_bytes_read() < container->content_length) { while (container->get_bytes_read() < container->content_length) {
int read_bytes = container->read(data + read_index, MAX_READ_SIZE); int read_bytes = container->read(data + read_index, MAX_READ_SIZE);
App.feed_wdt();
yield(); yield();
read_index += read_bytes; read_index += read_bytes;
} }
bool valid = false;
{ // Ensures the response string falls out of scope and deallocates before the task ends
std::string response((char *) data, read_index); std::string response((char *) data, read_index);
allocator.deallocate(data, container->content_length); 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 { valid = json::parse_json(response, [this_update](JsonObject root) -> bool {
if (!root.containsKey("name") || !root.containsKey("version") || !root.containsKey("builds")) { if (!root.containsKey("name") || !root.containsKey("version") || !root.containsKey("builds")) {
ESP_LOGE(TAG, "Manifest does not contain required fields"); ESP_LOGE(TAG, "Manifest does not contain required fields");
return false; return false;
} }
this->update_info_.title = root["name"].as<std::string>(); this_update->update_info_.title = root["name"].as<std::string>();
this->update_info_.latest_version = root["version"].as<std::string>(); this_update->update_info_.latest_version = root["version"].as<std::string>();
for (auto build : root["builds"].as<JsonArray>()) { for (auto build : root["builds"].as<JsonArray>()) {
if (!build.containsKey("chipFamily")) { if (!build.containsKey("chipFamily")) {
@ -84,38 +103,40 @@ void HttpRequestUpdate::update() {
ESP_LOGE(TAG, "Manifest does not contain required fields"); ESP_LOGE(TAG, "Manifest does not contain required fields");
return false; return false;
} }
this->update_info_.firmware_url = ota["path"].as<std::string>(); this_update->update_info_.firmware_url = ota["path"].as<std::string>();
this->update_info_.md5 = ota["md5"].as<std::string>(); this_update->update_info_.md5 = ota["md5"].as<std::string>();
if (ota.containsKey("summary")) if (ota.containsKey("summary"))
this->update_info_.summary = ota["summary"].as<std::string>(); this_update->update_info_.summary = ota["summary"].as<std::string>();
if (ota.containsKey("release_url")) if (ota.containsKey("release_url"))
this->update_info_.release_url = ota["release_url"].as<std::string>(); this_update->update_info_.release_url = ota["release_url"].as<std::string>();
return true; return true;
} }
} }
return false; return false;
}); });
}
if (!valid) { if (!valid) {
std::string msg = str_sprintf("Failed to parse JSON from %s", this->source_url_.c_str()); std::string msg = str_sprintf("Failed to parse JSON from %s", this_update->source_url_.c_str());
this->status_set_error(msg.c_str()); this_update->status_set_error(msg.c_str());
return; UPDATE_RETURN;
} }
// Merge source_url_ and this->update_info_.firmware_url // Merge source_url_ and this_update->update_info_.firmware_url
if (this->update_info_.firmware_url.find("http") == std::string::npos) { if (this_update->update_info_.firmware_url.find("http") == std::string::npos) {
std::string path = this->update_info_.firmware_url; std::string path = this_update->update_info_.firmware_url;
if (path[0] == '/') { if (path[0] == '/') {
std::string domain = this->source_url_.substr(0, this->source_url_.find('/', 8)); std::string domain = this_update->source_url_.substr(0, this_update->source_url_.find('/', 8));
this->update_info_.firmware_url = domain + path; this_update->update_info_.firmware_url = domain + path;
} else { } else {
std::string domain = this->source_url_.substr(0, this->source_url_.rfind('/') + 1); std::string domain = this_update->source_url_.substr(0, this_update->source_url_.rfind('/') + 1);
this->update_info_.firmware_url = domain + path; this_update->update_info_.firmware_url = domain + path;
} }
} }
{ // Ensures the current version string falls out of scope and deallocates before the task ends
std::string current_version; std::string current_version;
#ifdef ESPHOME_PROJECT_VERSION #ifdef ESPHOME_PROJECT_VERSION
current_version = ESPHOME_PROJECT_VERSION; current_version = ESPHOME_PROJECT_VERSION;
@ -123,19 +144,23 @@ void HttpRequestUpdate::update() {
current_version = ESPHOME_VERSION; current_version = ESPHOME_VERSION;
#endif #endif
this->update_info_.current_version = current_version; this_update->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_info_.has_progress = false; if (this_update->update_info_.latest_version.empty() ||
this->update_info_.progress = 0.0f; 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_update->update_info_.has_progress = false;
this->publish_state(); this_update->update_info_.progress = 0.0f;
this_update->status_clear_error();
this_update->publish_state();
UPDATE_RETURN;
} }
void HttpRequestUpdate::perform(bool force) { void HttpRequestUpdate::perform(bool force) {

View File

@ -7,6 +7,10 @@
#include "esphome/components/http_request/ota/ota_http_request.h" #include "esphome/components/http_request/ota/ota_http_request.h"
#include "esphome/components/update/update_entity.h" #include "esphome/components/update/update_entity.h"
#ifdef USE_ESP32
#include <freertos/FreeRTOS.h>
#endif
namespace esphome { namespace esphome {
namespace http_request { namespace http_request {
@ -29,6 +33,11 @@ class HttpRequestUpdate : public update::UpdateEntity, public PollingComponent {
HttpRequestComponent *request_parent_; HttpRequestComponent *request_parent_;
OtaHttpRequestComponent *ota_parent_; OtaHttpRequestComponent *ota_parent_;
std::string source_url_; std::string source_url_;
static void update_task(void *params);
#ifdef USE_ESP32
TaskHandle_t update_task_handle_{nullptr};
#endif
}; };
} // namespace http_request } // namespace http_request

View File

@ -282,7 +282,7 @@ IMAGE_TYPE = {
TransparencyType = image_ns.enum("TransparencyType") TransparencyType = image_ns.enum("TransparencyType")
CONF_USE_TRANSPARENCY = "use_transparency" CONF_TRANSPARENCY = "transparency"
# If the MDI file cannot be downloaded within this time, abort. # If the MDI file cannot be downloaded within this time, abort.
IMAGE_DOWNLOAD_TIMEOUT = 30 # seconds IMAGE_DOWNLOAD_TIMEOUT = 30 # seconds
@ -417,7 +417,7 @@ def validate_type(image_types):
def validate_settings(value): def validate_settings(value):
type = value[CONF_TYPE] type = value[CONF_TYPE]
transparency = value[CONF_USE_TRANSPARENCY].lower() transparency = value[CONF_TRANSPARENCY].lower()
allow_config = IMAGE_TYPE[type].allow_config allow_config = IMAGE_TYPE[type].allow_config
if transparency not in allow_config: if transparency not in allow_config:
raise cv.Invalid( raise cv.Invalid(
@ -458,9 +458,7 @@ BASE_SCHEMA = cv.Schema(
IMAGE_SCHEMA = BASE_SCHEMA.extend( IMAGE_SCHEMA = BASE_SCHEMA.extend(
{ {
cv.Required(CONF_TYPE): validate_type(IMAGE_TYPE), cv.Required(CONF_TYPE): validate_type(IMAGE_TYPE),
cv.Optional( cv.Optional(CONF_TRANSPARENCY, default=CONF_OPAQUE): validate_transparency(),
CONF_USE_TRANSPARENCY, default=CONF_OPAQUE
): validate_transparency(),
} }
) )
@ -476,7 +474,7 @@ def typed_image_schema(image_type):
BASE_SCHEMA.extend( BASE_SCHEMA.extend(
{ {
cv.Optional( cv.Optional(
CONF_USE_TRANSPARENCY, default=t CONF_TRANSPARENCY, default=t
): validate_transparency((t,)), ): validate_transparency((t,)),
cv.Optional(CONF_TYPE, default=image_type): validate_type( cv.Optional(CONF_TYPE, default=image_type): validate_type(
(image_type,) (image_type,)
@ -494,7 +492,7 @@ def typed_image_schema(image_type):
BASE_SCHEMA.extend( BASE_SCHEMA.extend(
{ {
cv.Optional( cv.Optional(
CONF_USE_TRANSPARENCY, default=CONF_OPAQUE CONF_TRANSPARENCY, default=CONF_OPAQUE
): validate_transparency(), ): validate_transparency(),
cv.Optional(CONF_TYPE, default=image_type): validate_type( cv.Optional(CONF_TYPE, default=image_type): validate_type(
(image_type,) (image_type,)
@ -556,7 +554,7 @@ async def write_image(config, all_frames=False):
else Image.Dither.FLOYDSTEINBERG else Image.Dither.FLOYDSTEINBERG
) )
type = config[CONF_TYPE] type = config[CONF_TYPE]
transparency = config[CONF_USE_TRANSPARENCY] transparency = config[CONF_TRANSPARENCY]
invert_alpha = config[CONF_INVERT_ALPHA] invert_alpha = config[CONF_INVERT_ALPHA]
frame_count = 1 frame_count = 1
if all_frames: if all_frames:

View File

@ -5,7 +5,7 @@ import esphome.codegen as cg
from esphome.components.http_request import CONF_HTTP_REQUEST_ID, HttpRequestComponent from esphome.components.http_request import CONF_HTTP_REQUEST_ID, HttpRequestComponent
from esphome.components.image import ( from esphome.components.image import (
CONF_INVERT_ALPHA, CONF_INVERT_ALPHA,
CONF_USE_TRANSPARENCY, CONF_TRANSPARENCY,
IMAGE_SCHEMA, IMAGE_SCHEMA,
Image_, Image_,
get_image_type_enum, get_image_type_enum,
@ -168,7 +168,7 @@ async def to_code(config):
url = config[CONF_URL] url = config[CONF_URL]
width, height = config.get(CONF_RESIZE, (0, 0)) 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( var = cg.new_Pvariable(
config[CONF_ID], config[CONF_ID],

View File

@ -100,7 +100,7 @@ class DownloadBuffer {
void reset() { this->unread_ = 0; } void reset() { this->unread_ = 0; }
protected: protected:
ExternalRAMAllocator<uint8_t> allocator_; RAMAllocator<uint8_t> allocator_{};
uint8_t *buffer_; uint8_t *buffer_;
size_t size_; size_t size_;
/** Total number of downloaded bytes not yet read. */ /** Total number of downloaded bytes not yet read. */

View File

@ -83,8 +83,7 @@ class OnlineImage : public PollingComponent,
protected: protected:
bool validate_url_(const std::string &url); bool validate_url_(const std::string &url);
using Allocator = ExternalRAMAllocator<uint8_t>; RAMAllocator<uint8_t> allocator_{};
Allocator allocator_{Allocator::Flags::ALLOW_FAILURE};
uint32_t get_buffer_size_() const { return get_buffer_size_(this->buffer_width_, this->buffer_height_); } 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; } int get_buffer_size_(int width, int height) const { return (this->get_bpp() * width + 7u) / 8u * height; }

View File

@ -11,7 +11,7 @@ CONFIG_SCHEMA = text_sensor.text_sensor_schema(
UptimeTextSensor, UptimeTextSensor,
icon=ICON_TIMER, icon=ICON_TIMER,
entity_category=ENTITY_CATEGORY_DIAGNOSTIC, entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
).extend(cv.polling_component_schema("60s")) ).extend(cv.polling_component_schema("30s"))
async def to_code(config): async def to_code(config):

View File

@ -9,34 +9,51 @@ namespace uptime {
static const char *const TAG = "uptime.sensor"; 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() { 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, // 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. // the difference will still be correct due to the way twos-complement arithmetic works.
const uint32_t delta = (now - this->last_ms_) / 1000; uint32_t delta = now - this->last_ms_;
if (delta == 0) this->last_ms_ = now - delta % 1000; // save remainder for next update
return; delta /= 1000;
// set last_ms_ to the last second boundary
this->last_ms_ = now - (now % 1000);
this->uptime_ += delta; this->uptime_ += delta;
auto uptime = this->uptime_; auto uptime = this->uptime_;
unsigned days = uptime / (24 * 3600); unsigned interval = this->get_update_interval() / 1000;
unsigned seconds = uptime % (24 * 3600); std::string buffer{};
unsigned hours = seconds / 3600; // display from the largest unit that corresponds to the update interval, drop larger units that are zero.
seconds %= 3600; while (true) { // enable use of break for early exit
unsigned minutes = seconds / 60; unsigned remainder = uptime % 60;
seconds %= 60; uptime /= 60;
if (days != 0) { if (interval < 30) {
this->publish_state(str_sprintf("%dd%dh%dm%ds", days, hours, minutes, seconds)); buffer.insert(0, str_sprintf("%us", remainder));
} else if (hours != 0) { if (uptime == 0)
this->publish_state(str_sprintf("%dh%dm%ds", hours, minutes, seconds)); break;
} else if (minutes != 0) {
this->publish_state(str_sprintf("%dm%ds", minutes, seconds));
} else {
this->publish_state(str_sprintf("%ds", seconds));
} }
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; } float UptimeTextSensor::get_setup_priority() const { return setup_priority::HARDWARE; }

View File

@ -17,8 +17,8 @@ class UptimeTextSensor : public text_sensor::TextSensor, public PollingComponent
float get_setup_priority() const override; float get_setup_priority() const override;
protected: protected:
uint64_t uptime_{0}; uint32_t uptime_{0}; // uptime in seconds, will overflow after 136 years
uint64_t last_ms_{0}; uint32_t last_ms_{0};
}; };
} // namespace uptime } // namespace uptime

View File

@ -72,7 +72,8 @@ void WaveshareEPaper2P13InV3::write_buffer_(uint8_t cmd, int top, int bottom) {
this->set_window_(top, bottom); this->set_window_(top, bottom);
this->command(cmd); this->command(cmd);
this->start_data_(); 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->write_array(this->buffer_ + top * width_bytes, (bottom - top) * width_bytes);
this->end_data_(); 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; } int WaveshareEPaper2P13InV3::get_height_internal() { return 250; }

View File

@ -811,6 +811,7 @@ class WaveshareEPaper2P13InV3 : public WaveshareEPaper {
void initialize() override; void initialize() override;
protected: protected:
int get_width_controller() override;
int get_width_internal() override; int get_width_internal() override;
int get_height_internal() override; int get_height_internal() override;
uint32_t idle_timeout_() override; uint32_t idle_timeout_() override;

View File

@ -1,21 +1,16 @@
import logging import logging
import multiprocessing import multiprocessing
import os import os
import re
from esphome import automation from esphome import automation
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.const import ( from esphome.const import (
CONF_ARDUINO_VERSION,
CONF_AREA, CONF_AREA,
CONF_BOARD,
CONF_BOARD_FLASH_MODE,
CONF_BUILD_PATH, CONF_BUILD_PATH,
CONF_COMMENT, CONF_COMMENT,
CONF_COMPILE_PROCESS_LIMIT, CONF_COMPILE_PROCESS_LIMIT,
CONF_ESPHOME, CONF_ESPHOME,
CONF_FRAMEWORK,
CONF_FRIENDLY_NAME, CONF_FRIENDLY_NAME,
CONF_INCLUDES, CONF_INCLUDES,
CONF_LIBRARIES, CONF_LIBRARIES,
@ -30,12 +25,9 @@ from esphome.const import (
CONF_PLATFORMIO_OPTIONS, CONF_PLATFORMIO_OPTIONS,
CONF_PRIORITY, CONF_PRIORITY,
CONF_PROJECT, CONF_PROJECT,
CONF_SOURCE,
CONF_TRIGGER_ID, CONF_TRIGGER_ID,
CONF_TYPE,
CONF_VERSION, CONF_VERSION,
KEY_CORE, KEY_CORE,
PLATFORM_ESP8266,
TARGET_PLATFORMS, TARGET_PLATFORMS,
__version__ as ESPHOME_VERSION, __version__ as ESPHOME_VERSION,
) )
@ -44,7 +36,6 @@ from esphome.helpers import copy_file_if_changed, get_str_env, walk_files
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
BUILD_FLASH_MODES = ["qio", "qout", "dio", "dout"]
StartupTrigger = cg.esphome_ns.class_( StartupTrigger = cg.esphome_ns.class_(
"StartupTrigger", cg.Component, automation.Trigger.template() "StartupTrigger", cg.Component, automation.Trigger.template()
) )
@ -58,8 +49,6 @@ ProjectUpdateTrigger = cg.esphome_ns.class_(
"ProjectUpdateTrigger", cg.Component, automation.Trigger.template(cg.std_string) "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"} VALID_INCLUDE_EXTS = {".h", ".hpp", ".tcc", ".ino", ".cpp", ".c"}
@ -111,7 +100,6 @@ else:
_compile_process_limit_default = cv.UNDEFINED _compile_process_limit_default = cv.UNDEFINED
CONF_ESP8266_RESTORE_FROM_FLASH = "esp8266_restore_from_flash"
CONFIG_SCHEMA = cv.All( CONFIG_SCHEMA = cv.All(
cv.Schema( cv.Schema(
{ {
@ -175,14 +163,9 @@ PRELOAD_CONFIG_SCHEMA = cv.Schema(
{ {
cv.Required(CONF_NAME): cv.valid_name, cv.Required(CONF_NAME): cv.valid_name,
cv.Optional(CONF_BUILD_PATH): cv.string, cv.Optional(CONF_BUILD_PATH): cv.string,
# Compat options, these were moved to target-platform specific sections cv.Optional(CONF_PLATFORM): cv.invalid(
# but we'll keep these around for a long time because every config would "Please remove the `platform` key from the [esphome] block and use the correct platform component. This style of configuration has now been removed."
# 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_MIN_VERSION, default=ESPHOME_VERSION): cv.All( cv.Optional(CONF_MIN_VERSION, default=ESPHOME_VERSION): cv.All(
cv.version_number, cv.validate_esphome_version cv.version_number, cv.validate_esphome_version
), ),
@ -204,62 +187,20 @@ def preload_core_config(config, result):
conf[CONF_BUILD_PATH] = os.path.join(build_path, CORE.name) conf[CONF_BUILD_PATH] = os.path.join(build_path, CORE.name)
CORE.build_path = CORE.relative_internal_path(conf[CONF_BUILD_PATH]) CORE.build_path = CORE.relative_internal_path(conf[CONF_BUILD_PATH])
has_oldstyle = CONF_PLATFORM in conf target_platforms = [key for key in TARGET_PLATFORMS if key in config]
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,
]
if not has_oldstyle and not newstyle_found: if not target_platforms:
raise cv.Invalid( raise cv.Invalid(
"Platform missing. You must include one of the available platform keys: " "Platform missing. You must include one of the available platform keys: "
+ ", ".join(TARGET_PLATFORMS), + ", ".join(TARGET_PLATFORMS),
[CONF_ESPHOME], [CONF_ESPHOME],
) )
if has_oldstyle and newstyle_found: if len(target_platforms) > 1:
raise cv.Invalid( 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", f"Found multiple target platform blocks: {', '.join(target_platforms)}. Only one is allowed.",
[CONF_ESPHOME, CONF_PLATFORM], [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 config[CONF_ESPHOME] = conf

View File

@ -125,7 +125,7 @@
#endif #endif
#ifdef USE_ESP_IDF #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 #endif
#if defined(USE_ESP32_VARIANT_ESP32S2) #if defined(USE_ESP32_VARIANT_ESP32S2)

53
script/run-in-env Normal file
View File

@ -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()

View File

@ -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 "$@"

View File

@ -1,7 +1,8 @@
--- ---
esphome: esphome:
name: test name: test
platform: ESP8266
esp8266:
board: d1_mini_lite board: d1_mini_lite
binary_sensor: binary_sensor:

View File

@ -1,7 +1,8 @@
--- ---
esphome: esphome:
name: test name: test
platform: ESP8266
esp8266:
board: d1_mini_lite board: d1_mini_lite
wifi: wifi:

View File

@ -1,7 +1,8 @@
--- ---
esphome: esphome:
name: test name: test
platform: ESP32
esp32:
board: nodemcu-32s board: nodemcu-32s
deep_sleep: deep_sleep:

View File

@ -1,7 +1,8 @@
--- ---
esphome: esphome:
name: test name: test
platform: ESP32
esp32:
board: nodemcu-32s board: nodemcu-32s
deep_sleep: deep_sleep:

View File

@ -1,7 +1,8 @@
--- ---
esphome: esphome:
name: test name: test
platform: ESP8266
esp8266:
board: d1_mini_lite board: d1_mini_lite
sensor: sensor:

View File

@ -1,7 +1,8 @@
--- ---
esphome: esphome:
name: test name: test
platform: ESP8266
esp8266:
board: d1_mini_lite board: d1_mini_lite
text_sensor: text_sensor:

View File

@ -2,12 +2,12 @@ animation:
- id: rgb565_animation - id: rgb565_animation
file: $component_dir/anim.gif file: $component_dir/anim.gif
type: RGB565 type: RGB565
use_transparency: opaque transparency: opaque
resize: 50x50 resize: 50x50
- id: rgb_animation - id: rgb_animation
file: $component_dir/anim.apng file: $component_dir/anim.apng
type: RGB type: RGB
use_transparency: chroma_key transparency: chroma_key
resize: 50x50 resize: 50x50
- id: grayscale_animation - id: grayscale_animation
file: $component_dir/anim.apng file: $component_dir/anim.apng

View File

@ -1,6 +1,16 @@
esphome:
on_boot:
then:
- audio_adc.set_mic_gain: 0db
- audio_adc.set_mic_gain: !lambda 'return 4;'
i2c: i2c:
- id: i2c_aic3204 - id: i2c_aic3204
scl: ${scl_pin} scl: ${scl_pin}
sda: ${sda_pin} sda: ${sda_pin}
es7210: audio_adc:
- platform: es7210
id: es7210_adc
bits_per_sample: 16bit
sample_rate: 16000

View File

@ -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

View File

@ -0,0 +1,5 @@
substitutions:
scl_pin: GPIO16
sda_pin: GPIO17
<<: !include common.yaml

View File

@ -0,0 +1,5 @@
substitutions:
scl_pin: GPIO5
sda_pin: GPIO4
<<: !include common.yaml

View File

@ -0,0 +1,5 @@
substitutions:
scl_pin: GPIO5
sda_pin: GPIO4
<<: !include common.yaml

View File

@ -0,0 +1,5 @@
substitutions:
scl_pin: GPIO16
sda_pin: GPIO17
<<: !include common.yaml

View File

@ -0,0 +1,5 @@
substitutions:
scl_pin: GPIO5
sda_pin: GPIO4
<<: !include common.yaml

View File

@ -6,54 +6,54 @@ image:
- id: transparent_transparent_image - id: transparent_transparent_image
file: ../../pnglogo.png file: ../../pnglogo.png
type: BINARY type: BINARY
use_transparency: chroma_key transparency: chroma_key
- id: rgba_image - id: rgba_image
file: ../../pnglogo.png file: ../../pnglogo.png
type: RGB type: RGB
use_transparency: alpha_channel transparency: alpha_channel
resize: 50x50 resize: 50x50
- id: rgb24_image - id: rgb24_image
file: ../../pnglogo.png file: ../../pnglogo.png
type: RGB type: RGB
use_transparency: chroma_key transparency: chroma_key
- id: rgb_image - id: rgb_image
file: ../../pnglogo.png file: ../../pnglogo.png
type: RGB type: RGB
use_transparency: opaque transparency: opaque
- id: rgb565_image - id: rgb565_image
file: ../../pnglogo.png file: ../../pnglogo.png
type: RGB565 type: RGB565
use_transparency: opaque transparency: opaque
- id: rgb565_ck_image - id: rgb565_ck_image
file: ../../pnglogo.png file: ../../pnglogo.png
type: RGB565 type: RGB565
use_transparency: chroma_key transparency: chroma_key
- id: rgb565_alpha_image - id: rgb565_alpha_image
file: ../../pnglogo.png file: ../../pnglogo.png
type: RGB565 type: RGB565
use_transparency: alpha_channel transparency: alpha_channel
- id: grayscale_alpha_image - id: grayscale_alpha_image
file: ../../pnglogo.png file: ../../pnglogo.png
type: grayscale type: grayscale
use_transparency: alpha_channel transparency: alpha_channel
resize: 50x50 resize: 50x50
- id: grayscale_ck_image - id: grayscale_ck_image
file: ../../pnglogo.png file: ../../pnglogo.png
type: grayscale type: grayscale
use_transparency: chroma_key transparency: chroma_key
- id: grayscale_image - id: grayscale_image
file: ../../pnglogo.png file: ../../pnglogo.png
type: grayscale type: grayscale
use_transparency: opaque transparency: opaque
- id: web_svg_image - id: web_svg_image
file: https://raw.githubusercontent.com/esphome/esphome-docs/a62d7ab193c1a464ed791670170c7d518189109b/images/logo.svg file: https://raw.githubusercontent.com/esphome/esphome-docs/a62d7ab193c1a464ed791670170c7d518189109b/images/logo.svg
resize: 256x48 resize: 256x48
type: BINARY type: BINARY
use_transparency: chroma_key transparency: chroma_key
- id: web_tiff_image - id: web_tiff_image
file: https://upload.wikimedia.org/wikipedia/commons/b/b6/SIPI_Jelly_Beans_4.1.07.tiff file: https://upload.wikimedia.org/wikipedia/commons/b/b6/SIPI_Jelly_Beans_4.1.07.tiff
type: RGB type: RGB

View File

@ -12,7 +12,7 @@ image:
dither: FloydSteinberg dither: FloydSteinberg
- id: transparent_transparent_image - id: transparent_transparent_image
file: ../../pnglogo.png file: ../../pnglogo.png
use_transparency: chroma_key transparency: chroma_key
rgb: rgb:
alpha_channel: alpha_channel:
- id: rgba_image - id: rgba_image
@ -28,21 +28,21 @@ image:
rgb565: rgb565:
- id: rgb565_image - id: rgb565_image
file: ../../pnglogo.png file: ../../pnglogo.png
use_transparency: opaque transparency: opaque
- id: rgb565_ck_image - id: rgb565_ck_image
file: ../../pnglogo.png file: ../../pnglogo.png
use_transparency: chroma_key transparency: chroma_key
- id: rgb565_alpha_image - id: rgb565_alpha_image
file: ../../pnglogo.png file: ../../pnglogo.png
use_transparency: alpha_channel transparency: alpha_channel
grayscale: grayscale:
- id: grayscale_alpha_image - id: grayscale_alpha_image
file: ../../pnglogo.png file: ../../pnglogo.png
use_transparency: alpha_channel transparency: alpha_channel
resize: 50x50 resize: 50x50
- id: grayscale_ck_image - id: grayscale_ck_image
file: ../../pnglogo.png file: ../../pnglogo.png
use_transparency: chroma_key transparency: chroma_key
- id: grayscale_image - id: grayscale_image
file: ../../pnglogo.png file: ../../pnglogo.png
use_transparency: opaque transparency: opaque

View File

@ -14,18 +14,18 @@ online_image:
- id: online_binary_transparent_image - id: online_binary_transparent_image
url: http://www.libpng.org/pub/png/img_png/pnglogo-blk-tiny.png url: http://www.libpng.org/pub/png/img_png/pnglogo-blk-tiny.png
type: BINARY type: BINARY
use_transparency: chroma_key transparency: chroma_key
format: png format: png
- id: online_rgba_image - id: online_rgba_image
url: http://www.libpng.org/pub/png/img_png/pnglogo-blk-tiny.png url: http://www.libpng.org/pub/png/img_png/pnglogo-blk-tiny.png
format: PNG format: PNG
type: RGB type: RGB
use_transparency: alpha_channel transparency: alpha_channel
- id: online_rgb24_image - id: online_rgb24_image
url: http://www.libpng.org/pub/png/img_png/pnglogo-blk-tiny.png url: http://www.libpng.org/pub/png/img_png/pnglogo-blk-tiny.png
format: PNG format: PNG
type: RGB type: RGB
use_transparency: chroma_key transparency: chroma_key
# Check the set_url action # Check the set_url action
esphome: esphome:

View File

@ -12,7 +12,7 @@ esphome:
# not overwritten by vars in the !include above # not overwritten by vars in the !include above
name: ${name} name: ${name}
name_add_mac_suffix: true 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}} libraries: !include {file: includes/list.yaml, vars: {var1: Wire}}
esp8266:
board: !include {file: includes/scalar.yaml, vars: {var1: nodemcu}}

View File

@ -12,7 +12,7 @@ esphome:
# not overwritten by vars in the !include above # not overwritten by vars in the !include above
name: ${name} name: ${name}
name_add_mac_suffix: true 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}} libraries: !include {file: includes/list.yaml, vars: {var1: Wire}}
esp8266:
board: !include {file: includes/scalar.yaml, vars: {var1: nodemcu}}

View File

@ -10,7 +10,7 @@ def test_include_with_vars(fixture_path):
substitutions.do_substitution_pass(actual, None) substitutions.do_substitution_pass(actual, None)
assert actual["esphome"]["name"] == "original" assert actual["esphome"]["name"] == "original"
assert actual["esphome"]["libraries"][0] == "Wire" assert actual["esphome"]["libraries"][0] == "Wire"
assert actual["esphome"]["board"] == "nodemcu" assert actual["esp8266"]["board"] == "nodemcu"
assert actual["wifi"]["ssid"] == "my_custom_ssid" assert actual["wifi"]["ssid"] == "my_custom_ssid"