mirror of
https://github.com/esphome/esphome.git
synced 2025-01-30 23:02:14 +01:00
Merge branch 'dev' into gpio-pin-validation-override
This commit is contained in:
commit
93cc1fafc0
@ -131,6 +131,7 @@ esphome/components/ens160_base/* @latonita @vincentscode
|
||||
esphome/components/ens160_i2c/* @latonita
|
||||
esphome/components/ens160_spi/* @latonita
|
||||
esphome/components/ens210/* @itn3rd77
|
||||
esphome/components/es7210/* @kahrendt
|
||||
esphome/components/es8311/* @kahrendt @kroimon
|
||||
esphome/components/esp32/* @esphome/core
|
||||
esphome/components/esp32_ble/* @Rapsssito @jesserockz
|
||||
|
67
esphome/components/es7210/__init__.py
Normal file
67
esphome/components/es7210/__init__.py
Normal file
@ -0,0 +1,67 @@
|
||||
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]))
|
201
esphome/components/es7210/es7210.cpp
Normal file
201
esphome/components/es7210/es7210.cpp
Normal file
@ -0,0 +1,201 @@
|
||||
#include "es7210.h"
|
||||
#include "es7210_const.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include <cinttypes>
|
||||
|
||||
namespace esphome {
|
||||
namespace es7210 {
|
||||
|
||||
static const char *const TAG = "es7210";
|
||||
|
||||
static const size_t MCLK_DIV_FRE = 256;
|
||||
|
||||
// Mark the component as failed; use only in setup
|
||||
#define ES7210_ERROR_FAILED(func) \
|
||||
if (!(func)) { \
|
||||
this->mark_failed(); \
|
||||
return; \
|
||||
}
|
||||
|
||||
// Return false; use outside of setup
|
||||
#define ES7210_ERROR_CHECK(func) \
|
||||
if (!(func)) { \
|
||||
return false; \
|
||||
}
|
||||
|
||||
void ES7210::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "ES7210 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!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ES7210::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Setting up ES7210...");
|
||||
|
||||
// Software reset
|
||||
ES7210_ERROR_FAILED(this->write_byte(ES7210_RESET_REG00, 0xff));
|
||||
ES7210_ERROR_FAILED(this->write_byte(ES7210_RESET_REG00, 0x32));
|
||||
ES7210_ERROR_FAILED(this->write_byte(ES7210_CLOCK_OFF_REG01, 0x3f));
|
||||
|
||||
// Set initialization time when device powers up
|
||||
ES7210_ERROR_FAILED(this->write_byte(ES7210_TIME_CONTROL0_REG09, 0x30));
|
||||
ES7210_ERROR_FAILED(this->write_byte(ES7210_TIME_CONTROL1_REG0A, 0x30));
|
||||
|
||||
// Configure HFP for all ADC channels
|
||||
ES7210_ERROR_FAILED(this->write_byte(ES7210_ADC12_HPF2_REG23, 0x2a));
|
||||
ES7210_ERROR_FAILED(this->write_byte(ES7210_ADC12_HPF1_REG22, 0x0a));
|
||||
ES7210_ERROR_FAILED(this->write_byte(ES7210_ADC34_HPF2_REG20, 0x0a));
|
||||
ES7210_ERROR_FAILED(this->write_byte(ES7210_ADC34_HPF1_REG21, 0x2a));
|
||||
|
||||
// Secondary I2S mode settings
|
||||
ES7210_ERROR_FAILED(this->es7210_update_reg_bit_(ES7210_MODE_CONFIG_REG08, 0x01, 0x00));
|
||||
|
||||
// Configure analog power
|
||||
ES7210_ERROR_FAILED(this->write_byte(ES7210_ANALOG_REG40, 0xC3));
|
||||
|
||||
// Set mic bias
|
||||
ES7210_ERROR_FAILED(this->write_byte(ES7210_MIC12_BIAS_REG41, 0x70));
|
||||
ES7210_ERROR_FAILED(this->write_byte(ES7210_MIC34_BIAS_REG42, 0x70));
|
||||
|
||||
// Configure I2S settings, sample rate, and microphone gains
|
||||
ES7210_ERROR_FAILED(this->configure_i2s_format_());
|
||||
ES7210_ERROR_FAILED(this->configure_sample_rate_());
|
||||
ES7210_ERROR_FAILED(this->configure_mic_gain_());
|
||||
|
||||
// Power on mics 1 through 4
|
||||
ES7210_ERROR_FAILED(this->write_byte(ES7210_MIC1_POWER_REG47, 0x08));
|
||||
ES7210_ERROR_FAILED(this->write_byte(ES7210_MIC2_POWER_REG48, 0x08));
|
||||
ES7210_ERROR_FAILED(this->write_byte(ES7210_MIC3_POWER_REG49, 0x08));
|
||||
ES7210_ERROR_FAILED(this->write_byte(ES7210_MIC4_POWER_REG4A, 0x08));
|
||||
|
||||
// Power down DLL
|
||||
ES7210_ERROR_FAILED(this->write_byte(ES7210_POWER_DOWN_REG06, 0x04));
|
||||
|
||||
// Power on MIC1-4 bias & ADC1-4 & PGA1-4 Power
|
||||
ES7210_ERROR_FAILED(this->write_byte(ES7210_MIC12_POWER_REG4B, 0x0F));
|
||||
ES7210_ERROR_FAILED(this->write_byte(ES7210_MIC34_POWER_REG4C, 0x0F));
|
||||
|
||||
// Enable device
|
||||
ES7210_ERROR_FAILED(this->write_byte(ES7210_RESET_REG00, 0x71));
|
||||
ES7210_ERROR_FAILED(this->write_byte(ES7210_RESET_REG00, 0x41));
|
||||
}
|
||||
|
||||
bool ES7210::configure_sample_rate_() {
|
||||
int mclk_fre = this->sample_rate_ * MCLK_DIV_FRE;
|
||||
int coeff = -1;
|
||||
|
||||
for (int i = 0; i < (sizeof(ES7210_COEFFICIENTS) / sizeof(ES7210_COEFFICIENTS[0])); ++i) {
|
||||
if (ES7210_COEFFICIENTS[i].lrclk == this->sample_rate_ && ES7210_COEFFICIENTS[i].mclk == mclk_fre)
|
||||
coeff = i;
|
||||
}
|
||||
|
||||
if (coeff >= 0) {
|
||||
// Set adc_div & doubler & dll
|
||||
uint8_t regv;
|
||||
ES7210_ERROR_CHECK(this->read_byte(ES7210_MAINCLK_REG02, ®v));
|
||||
regv = regv & 0x00;
|
||||
regv |= ES7210_COEFFICIENTS[coeff].adc_div;
|
||||
regv |= ES7210_COEFFICIENTS[coeff].doubler << 6;
|
||||
regv |= ES7210_COEFFICIENTS[coeff].dll << 7;
|
||||
|
||||
ES7210_ERROR_CHECK(this->write_byte(ES7210_MAINCLK_REG02, regv));
|
||||
|
||||
// Set osr
|
||||
regv = ES7210_COEFFICIENTS[coeff].osr;
|
||||
ES7210_ERROR_CHECK(this->write_byte(ES7210_OSR_REG07, regv));
|
||||
// Set lrck
|
||||
regv = ES7210_COEFFICIENTS[coeff].lrck_h;
|
||||
ES7210_ERROR_CHECK(this->write_byte(ES7210_LRCK_DIVH_REG04, regv));
|
||||
regv = ES7210_COEFFICIENTS[coeff].lrck_l;
|
||||
ES7210_ERROR_CHECK(this->write_byte(ES7210_LRCK_DIVL_REG05, regv));
|
||||
} else {
|
||||
// Invalid sample frequency
|
||||
ESP_LOGE(TAG, "Invalid sample rate");
|
||||
return false;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
ES7210_ERROR_CHECK(this->write_byte(ES7210_MIC12_POWER_REG4B, 0xff));
|
||||
ES7210_ERROR_CHECK(this->write_byte(ES7210_MIC34_POWER_REG4C, 0xff));
|
||||
|
||||
// Configure mic 1
|
||||
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_));
|
||||
|
||||
// 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_));
|
||||
|
||||
// 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_));
|
||||
|
||||
// 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_));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ES7210::configure_i2s_format_() {
|
||||
// Configure bits per sample
|
||||
uint8_t reg_val = 0;
|
||||
switch (this->bits_per_sample_) {
|
||||
case ES7210_BITS_PER_SAMPLE_16:
|
||||
reg_val = 0x60;
|
||||
break;
|
||||
case ES7210_BITS_PER_SAMPLE_18:
|
||||
reg_val = 0x40;
|
||||
break;
|
||||
case ES7210_BITS_PER_SAMPLE_20:
|
||||
reg_val = 0x20;
|
||||
break;
|
||||
case ES7210_BITS_PER_SAMPLE_24:
|
||||
reg_val = 0x00;
|
||||
break;
|
||||
case ES7210_BITS_PER_SAMPLE_32:
|
||||
reg_val = 0x80;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
ES7210_ERROR_CHECK(this->write_byte(ES7210_SDP_INTERFACE1_REG11, reg_val));
|
||||
|
||||
if (this->enable_tdm_) {
|
||||
ES7210_ERROR_CHECK(this->write_byte(ES7210_SDP_INTERFACE2_REG12, 0x02));
|
||||
} else {
|
||||
// Microphones 1 and 2 output on SDOUT1, microphones 3 and 4 output on SDOUT2
|
||||
ES7210_ERROR_CHECK(this->write_byte(ES7210_SDP_INTERFACE2_REG12, 0x00));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ES7210::es7210_update_reg_bit_(uint8_t reg_addr, uint8_t update_bits, uint8_t data) {
|
||||
uint8_t regv;
|
||||
ES7210_ERROR_CHECK(this->read_byte(reg_addr, ®v));
|
||||
regv = (regv & (~update_bits)) | (update_bits & data);
|
||||
return this->write_byte(reg_addr, regv);
|
||||
}
|
||||
|
||||
} // namespace es7210
|
||||
} // namespace esphome
|
69
esphome/components/es7210/es7210.h
Normal file
69
esphome/components/es7210/es7210.h
Normal file
@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
#include "esphome/core/component.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace es7210 {
|
||||
|
||||
enum ES7210BitsPerSample : uint8_t {
|
||||
ES7210_BITS_PER_SAMPLE_16 = 16,
|
||||
ES7210_BITS_PER_SAMPLE_18 = 18,
|
||||
ES7210_BITS_PER_SAMPLE_20 = 20,
|
||||
ES7210_BITS_PER_SAMPLE_24 = 24,
|
||||
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 for configuring an ES7210 ADC for microphone input.
|
||||
* Based on code from:
|
||||
* - https://github.com/espressif/esp-bsp/ (accessed 20241219)
|
||||
* - https://github.com/espressif/esp-adf/ (accessed 20241219)
|
||||
*/
|
||||
public:
|
||||
void setup() override;
|
||||
float get_setup_priority() const override { return setup_priority::DATA; }
|
||||
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; }
|
||||
void set_sample_rate(uint32_t sample_rate) { this->sample_rate_ = sample_rate; }
|
||||
|
||||
protected:
|
||||
/// @brief Updates an I2C registry address by modifying the current state
|
||||
/// @param reg_addr I2C register address
|
||||
/// @param update_bits Mask of allowed bits to be modified
|
||||
/// @param data Bit values to be written
|
||||
/// @return True if successful, false otherwise
|
||||
bool es7210_update_reg_bit_(uint8_t reg_addr, uint8_t update_bits, uint8_t data);
|
||||
|
||||
bool configure_i2s_format_();
|
||||
bool configure_mic_gain_();
|
||||
bool configure_sample_rate_();
|
||||
|
||||
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_;
|
||||
};
|
||||
|
||||
} // namespace es7210
|
||||
} // namespace esphome
|
126
esphome/components/es7210/es7210_const.h
Normal file
126
esphome/components/es7210/es7210_const.h
Normal file
@ -0,0 +1,126 @@
|
||||
#pragma once
|
||||
|
||||
#include "es7210.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace es7210 {
|
||||
|
||||
// ES7210 register addresses
|
||||
static const uint8_t ES7210_RESET_REG00 = 0x00; /* Reset control */
|
||||
static const uint8_t ES7210_CLOCK_OFF_REG01 = 0x01; /* Used to turn off the ADC clock */
|
||||
static const uint8_t ES7210_MAINCLK_REG02 = 0x02; /* Set ADC clock frequency division */
|
||||
|
||||
static const uint8_t ES7210_MASTER_CLK_REG03 = 0x03; /* MCLK source $ SCLK division */
|
||||
static const uint8_t ES7210_LRCK_DIVH_REG04 = 0x04; /* lrck_divh */
|
||||
static const uint8_t ES7210_LRCK_DIVL_REG05 = 0x05; /* lrck_divl */
|
||||
static const uint8_t ES7210_POWER_DOWN_REG06 = 0x06; /* power down */
|
||||
static const uint8_t ES7210_OSR_REG07 = 0x07;
|
||||
static const uint8_t ES7210_MODE_CONFIG_REG08 = 0x08; /* Set primary/secondary & channels */
|
||||
static const uint8_t ES7210_TIME_CONTROL0_REG09 = 0x09; /* Set Chip intial state period*/
|
||||
static const uint8_t ES7210_TIME_CONTROL1_REG0A = 0x0A; /* Set Power up state period */
|
||||
static const uint8_t ES7210_SDP_INTERFACE1_REG11 = 0x11; /* Set sample & fmt */
|
||||
static const uint8_t ES7210_SDP_INTERFACE2_REG12 = 0x12; /* Pins state */
|
||||
static const uint8_t ES7210_ADC_AUTOMUTE_REG13 = 0x13; /* Set mute */
|
||||
static const uint8_t ES7210_ADC34_MUTERANGE_REG14 = 0x14; /* Set mute range */
|
||||
static const uint8_t ES7210_ADC12_MUTERANGE_REG15 = 0x15; /* Set mute range */
|
||||
static const uint8_t ES7210_ADC34_HPF2_REG20 = 0x20; /* HPF */
|
||||
static const uint8_t ES7210_ADC34_HPF1_REG21 = 0x21; /* HPF */
|
||||
static const uint8_t ES7210_ADC12_HPF1_REG22 = 0x22; /* HPF */
|
||||
static const uint8_t ES7210_ADC12_HPF2_REG23 = 0x23; /* HPF */
|
||||
static const uint8_t ES7210_ANALOG_REG40 = 0x40; /* ANALOG Power */
|
||||
static const uint8_t ES7210_MIC12_BIAS_REG41 = 0x41;
|
||||
static const uint8_t ES7210_MIC34_BIAS_REG42 = 0x42;
|
||||
static const uint8_t ES7210_MIC1_GAIN_REG43 = 0x43;
|
||||
static const uint8_t ES7210_MIC2_GAIN_REG44 = 0x44;
|
||||
static const uint8_t ES7210_MIC3_GAIN_REG45 = 0x45;
|
||||
static const uint8_t ES7210_MIC4_GAIN_REG46 = 0x46;
|
||||
static const uint8_t ES7210_MIC1_POWER_REG47 = 0x47;
|
||||
static const uint8_t ES7210_MIC2_POWER_REG48 = 0x48;
|
||||
static const uint8_t ES7210_MIC3_POWER_REG49 = 0x49;
|
||||
static const uint8_t ES7210_MIC4_POWER_REG4A = 0x4A;
|
||||
static const uint8_t ES7210_MIC12_POWER_REG4B = 0x4B; /* MICBias & ADC & PGA Power */
|
||||
static const uint8_t ES7210_MIC34_POWER_REG4C = 0x4C;
|
||||
|
||||
/*
|
||||
* Clock coefficient structer
|
||||
*/
|
||||
struct ES7210Coefficient {
|
||||
uint32_t mclk; // mclk frequency
|
||||
uint32_t lrclk;
|
||||
uint8_t ss_ds;
|
||||
uint8_t adc_div;
|
||||
uint8_t dll; // dll_bypass
|
||||
uint8_t doubler; // doubler_enable
|
||||
uint8_t osr; // adc osr
|
||||
uint8_t mclk_src; // sselect mclk source
|
||||
uint8_t lrck_h; // High 4 bits of lrck
|
||||
uint8_t lrck_l; // Low 8 bits of lrck
|
||||
};
|
||||
|
||||
/* Codec hifi mclk clock divider coefficients
|
||||
* MEMBER REG
|
||||
* mclk: 0x03
|
||||
* lrck: standard
|
||||
* ss_ds: --
|
||||
* adc_div: 0x02
|
||||
* dll: 0x06
|
||||
* doubler: 0x02
|
||||
* osr: 0x07
|
||||
* mclk_src: 0x03
|
||||
* lrckh: 0x04
|
||||
* lrckl: 0x05
|
||||
*/
|
||||
static const ES7210Coefficient ES7210_COEFFICIENTS[] = {
|
||||
// mclk lrck ss_ds adc_div dll doubler osr mclk_src lrckh lrckl
|
||||
/* 8k */
|
||||
{12288000, 8000, 0x00, 0x03, 0x01, 0x00, 0x20, 0x00, 0x06, 0x00},
|
||||
{16384000, 8000, 0x00, 0x04, 0x01, 0x00, 0x20, 0x00, 0x08, 0x00},
|
||||
{19200000, 8000, 0x00, 0x1e, 0x00, 0x01, 0x28, 0x00, 0x09, 0x60},
|
||||
{4096000, 8000, 0x00, 0x01, 0x01, 0x00, 0x20, 0x00, 0x02, 0x00},
|
||||
|
||||
/* 11.025k */
|
||||
{11289600, 11025, 0x00, 0x02, 0x01, 0x00, 0x20, 0x00, 0x01, 0x00},
|
||||
|
||||
/* 12k */
|
||||
{12288000, 12000, 0x00, 0x02, 0x01, 0x00, 0x20, 0x00, 0x04, 0x00},
|
||||
{19200000, 12000, 0x00, 0x14, 0x00, 0x01, 0x28, 0x00, 0x06, 0x40},
|
||||
|
||||
/* 16k */
|
||||
{4096000, 16000, 0x00, 0x01, 0x01, 0x01, 0x20, 0x00, 0x01, 0x00},
|
||||
{19200000, 16000, 0x00, 0x0a, 0x00, 0x00, 0x1e, 0x00, 0x04, 0x80},
|
||||
{16384000, 16000, 0x00, 0x02, 0x01, 0x00, 0x20, 0x00, 0x04, 0x00},
|
||||
{12288000, 16000, 0x00, 0x03, 0x01, 0x01, 0x20, 0x00, 0x03, 0x00},
|
||||
|
||||
/* 22.05k */
|
||||
{11289600, 22050, 0x00, 0x01, 0x01, 0x00, 0x20, 0x00, 0x02, 0x00},
|
||||
|
||||
/* 24k */
|
||||
{12288000, 24000, 0x00, 0x01, 0x01, 0x00, 0x20, 0x00, 0x02, 0x00},
|
||||
{19200000, 24000, 0x00, 0x0a, 0x00, 0x01, 0x28, 0x00, 0x03, 0x20},
|
||||
|
||||
/* 32k */
|
||||
{12288000, 32000, 0x00, 0x03, 0x00, 0x00, 0x20, 0x00, 0x01, 0x80},
|
||||
{16384000, 32000, 0x00, 0x01, 0x01, 0x00, 0x20, 0x00, 0x02, 0x00},
|
||||
{19200000, 32000, 0x00, 0x05, 0x00, 0x00, 0x1e, 0x00, 0x02, 0x58},
|
||||
|
||||
/* 44.1k */
|
||||
{11289600, 44100, 0x00, 0x01, 0x01, 0x01, 0x20, 0x00, 0x01, 0x00},
|
||||
|
||||
/* 48k */
|
||||
{12288000, 48000, 0x00, 0x01, 0x01, 0x01, 0x20, 0x00, 0x01, 0x00},
|
||||
{19200000, 48000, 0x00, 0x05, 0x00, 0x01, 0x28, 0x00, 0x01, 0x90},
|
||||
|
||||
/* 64k */
|
||||
{16384000, 64000, 0x01, 0x01, 0x01, 0x00, 0x20, 0x00, 0x01, 0x00},
|
||||
{19200000, 64000, 0x00, 0x05, 0x00, 0x01, 0x1e, 0x00, 0x01, 0x2c},
|
||||
|
||||
/* 88.2k */
|
||||
{11289600, 88200, 0x01, 0x01, 0x01, 0x01, 0x20, 0x00, 0x00, 0x80},
|
||||
|
||||
/* 96k */
|
||||
{12288000, 96000, 0x01, 0x01, 0x01, 0x01, 0x20, 0x00, 0x00, 0x80},
|
||||
{19200000, 96000, 0x01, 0x05, 0x00, 0x01, 0x28, 0x00, 0x00, 0xc8},
|
||||
};
|
||||
|
||||
} // namespace es7210
|
||||
} // namespace esphome
|
@ -2,7 +2,7 @@ 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_BITS_PER_SAMPLE, CONF_ID, CONF_SAMPLE_RATE
|
||||
from esphome.const import CONF_BITS_PER_SAMPLE, CONF_ID, CONF_MIC_GAIN, CONF_SAMPLE_RATE
|
||||
|
||||
CODEOWNERS = ["@kroimon", "@kahrendt"]
|
||||
DEPENDENCIES = ["i2c"]
|
||||
@ -10,7 +10,6 @@ DEPENDENCIES = ["i2c"]
|
||||
es8311_ns = cg.esphome_ns.namespace("es8311")
|
||||
ES8311 = es8311_ns.class_("ES8311", AudioDac, cg.Component, i2c.I2CDevice)
|
||||
|
||||
CONF_MIC_GAIN = "mic_gain"
|
||||
CONF_USE_MCLK = "use_mclk"
|
||||
CONF_USE_MICROPHONE = "use_microphone"
|
||||
|
||||
|
@ -8,11 +8,13 @@ namespace event {
|
||||
static const char *const TAG = "event";
|
||||
|
||||
void Event::trigger(const std::string &event_type) {
|
||||
if (types_.find(event_type) == types_.end()) {
|
||||
auto found = types_.find(event_type);
|
||||
if (found == types_.end()) {
|
||||
ESP_LOGE(TAG, "'%s': invalid event type for trigger(): %s", this->get_name().c_str(), event_type.c_str());
|
||||
return;
|
||||
}
|
||||
ESP_LOGD(TAG, "'%s' Triggered event '%s'", this->get_name().c_str(), event_type.c_str());
|
||||
last_event_type = &(*found);
|
||||
ESP_LOGD(TAG, "'%s' Triggered event '%s'", this->get_name().c_str(), last_event_type->c_str());
|
||||
this->event_callback_.call(event_type);
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,8 @@ namespace event {
|
||||
|
||||
class Event : public EntityBase, public EntityBase_DeviceClass {
|
||||
public:
|
||||
const std::string *last_event_type;
|
||||
|
||||
void trigger(const std::string &event_type);
|
||||
void set_event_types(const std::set<std::string> &event_types) { this->types_ = event_types; }
|
||||
std::set<std::string> get_event_types() const { return this->types_; }
|
||||
|
@ -15,6 +15,7 @@ from .defines import (
|
||||
CONF_FREEZE,
|
||||
CONF_LVGL_ID,
|
||||
CONF_SHOW_SNOW,
|
||||
PARTS,
|
||||
literal,
|
||||
)
|
||||
from .lv_validation import lv_bool, lv_color, lv_image, opacity
|
||||
@ -33,7 +34,7 @@ from .lvcode import (
|
||||
lvgl_comp,
|
||||
static_cast,
|
||||
)
|
||||
from .schemas import DISP_BG_SCHEMA, LIST_ACTION_SCHEMA, LVGL_SCHEMA
|
||||
from .schemas import DISP_BG_SCHEMA, LIST_ACTION_SCHEMA, LVGL_SCHEMA, base_update_schema
|
||||
from .types import (
|
||||
LV_STATE,
|
||||
LvglAction,
|
||||
@ -41,6 +42,7 @@ from .types import (
|
||||
ObjUpdateAction,
|
||||
lv_disp_t,
|
||||
lv_group_t,
|
||||
lv_obj_base_t,
|
||||
lv_obj_t,
|
||||
lv_pseudo_button_t,
|
||||
)
|
||||
@ -336,3 +338,14 @@ async def widget_focus(config, action_id, template_arg, args):
|
||||
lv.group_focus_freeze(group, True)
|
||||
var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda())
|
||||
return var
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"lvgl.widget.update", ObjUpdateAction, base_update_schema(lv_obj_base_t, PARTS)
|
||||
)
|
||||
async def obj_update_to_code(config, action_id, template_arg, args):
|
||||
async def do_update(widget: Widget):
|
||||
await set_obj_properties(widget, config)
|
||||
|
||||
widgets = await get_widgets(config[CONF_ID])
|
||||
return await action_to_code(widgets, do_update, action_id, template_arg, args)
|
||||
|
@ -199,13 +199,12 @@ FLAG_SCHEMA = cv.Schema({cv.Optional(flag): lvalid.lv_bool for flag in df.OBJ_FL
|
||||
FLAG_LIST = cv.ensure_list(df.LvConstant("LV_OBJ_FLAG_", *df.OBJ_FLAGS).one_of)
|
||||
|
||||
|
||||
def part_schema(widget_type: WidgetType):
|
||||
def part_schema(parts):
|
||||
"""
|
||||
Generate a schema for the various parts (e.g. main:, indicator:) of a widget type
|
||||
:param widget_type: The type of widget to generate for
|
||||
:return:
|
||||
:param parts: The parts to include in the schema
|
||||
:return: The schema
|
||||
"""
|
||||
parts = widget_type.parts
|
||||
return cv.Schema({cv.Optional(part): STATE_SCHEMA for part in parts}).extend(
|
||||
STATE_SCHEMA
|
||||
)
|
||||
@ -228,9 +227,15 @@ def automation_schema(typ: LvType):
|
||||
}
|
||||
|
||||
|
||||
def create_modify_schema(widget_type):
|
||||
def base_update_schema(widget_type, parts):
|
||||
"""
|
||||
Create a schema for updating a widgets style properties, states and flags
|
||||
:param widget_type: The type of the ID
|
||||
:param parts: The allowable parts to specify
|
||||
:return:
|
||||
"""
|
||||
return (
|
||||
part_schema(widget_type)
|
||||
part_schema(parts)
|
||||
.extend(
|
||||
{
|
||||
cv.Required(CONF_ID): cv.ensure_list(
|
||||
@ -245,7 +250,12 @@ def create_modify_schema(widget_type):
|
||||
}
|
||||
)
|
||||
.extend(FLAG_SCHEMA)
|
||||
.extend(widget_type.modify_schema)
|
||||
)
|
||||
|
||||
|
||||
def create_modify_schema(widget_type):
|
||||
return base_update_schema(widget_type.w_type, widget_type.parts).extend(
|
||||
widget_type.modify_schema
|
||||
)
|
||||
|
||||
|
||||
@ -256,7 +266,7 @@ def obj_schema(widget_type: WidgetType):
|
||||
:return:
|
||||
"""
|
||||
return (
|
||||
part_schema(widget_type)
|
||||
part_schema(widget_type.parts)
|
||||
.extend(FLAG_SCHEMA)
|
||||
.extend(LAYOUT_SCHEMA)
|
||||
.extend(ALIGN_TO_SCHEMA)
|
||||
@ -341,7 +351,6 @@ FLEX_OBJ_SCHEMA = {
|
||||
cv.Optional(df.CONF_FLEX_GROW): cv.int_,
|
||||
}
|
||||
|
||||
|
||||
DISP_BG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.Optional(df.CONF_DISP_BG_IMAGE): cv.Any(
|
||||
|
@ -37,7 +37,7 @@ DROPDOWN_BASE_SCHEMA = cv.Schema(
|
||||
cv.Exclusive(CONF_SELECTED_INDEX, CONF_SELECTED_TEXT): lv_int,
|
||||
cv.Exclusive(CONF_SELECTED_TEXT, CONF_SELECTED_TEXT): lv_text,
|
||||
cv.Optional(CONF_DIR, default="BOTTOM"): DIRECTIONS.one_of,
|
||||
cv.Optional(CONF_DROPDOWN_LIST): part_schema(dropdown_list_spec),
|
||||
cv.Optional(CONF_DROPDOWN_LIST): part_schema(dropdown_list_spec.parts),
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -16,6 +16,11 @@ KEYBOARD_SCHEMA = {
|
||||
cv.Optional(CONF_TEXTAREA): cv.use_id(lv_textarea_t),
|
||||
}
|
||||
|
||||
KEYBOARD_MODIFY_SCHEMA = {
|
||||
cv.Optional(CONF_MODE): KEYBOARD_MODES.one_of,
|
||||
cv.Optional(CONF_TEXTAREA): cv.use_id(lv_textarea_t),
|
||||
}
|
||||
|
||||
lv_keyboard_t = LvType(
|
||||
"LvKeyboardType",
|
||||
parents=(KeyProvider, LvCompound),
|
||||
@ -32,6 +37,7 @@ class KeyboardType(WidgetType):
|
||||
lv_keyboard_t,
|
||||
(CONF_MAIN, CONF_ITEMS),
|
||||
KEYBOARD_SCHEMA,
|
||||
modify_schema=KEYBOARD_MODIFY_SCHEMA,
|
||||
)
|
||||
|
||||
def get_uses(self):
|
||||
@ -41,7 +47,8 @@ class KeyboardType(WidgetType):
|
||||
lvgl_components_required.add("KEY_LISTENER")
|
||||
lvgl_components_required.add(CONF_KEYBOARD)
|
||||
add_lv_use("btnmatrix")
|
||||
await w.set_property(CONF_MODE, await KEYBOARD_MODES.process(config[CONF_MODE]))
|
||||
if mode := config.get(CONF_MODE):
|
||||
await w.set_property(CONF_MODE, await KEYBOARD_MODES.process(mode))
|
||||
if ta := await get_widgets(config, CONF_TEXTAREA):
|
||||
await w.set_property(CONF_TEXTAREA, ta[0].obj)
|
||||
|
||||
|
@ -51,7 +51,7 @@ MSGBOX_SCHEMA = container_schema(
|
||||
cv.Required(CONF_TITLE): STYLED_TEXT_SCHEMA,
|
||||
cv.Optional(CONF_BODY, default=""): STYLED_TEXT_SCHEMA,
|
||||
cv.Optional(CONF_BUTTONS): cv.ensure_list(BUTTONMATRIX_BUTTON_SCHEMA),
|
||||
cv.Optional(CONF_BUTTON_STYLE): part_schema(buttonmatrix_spec),
|
||||
cv.Optional(CONF_BUTTON_STYLE): part_schema(buttonmatrix_spec.parts),
|
||||
cv.Optional(CONF_CLOSE_BUTTON, default=True): lv_bool,
|
||||
cv.GenerateID(CONF_BUTTON_TEXT_LIST_ID): cv.declare_id(char_ptr),
|
||||
}
|
||||
|
@ -1,9 +1,5 @@
|
||||
from esphome import automation
|
||||
|
||||
from ..automation import update_to_code
|
||||
from ..defines import CONF_MAIN, CONF_OBJ, CONF_SCROLLBAR
|
||||
from ..schemas import create_modify_schema
|
||||
from ..types import ObjUpdateAction, WidgetType, lv_obj_t
|
||||
from ..types import WidgetType, lv_obj_t
|
||||
|
||||
|
||||
class ObjType(WidgetType):
|
||||
@ -21,10 +17,3 @@ class ObjType(WidgetType):
|
||||
|
||||
|
||||
obj_spec = ObjType()
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"lvgl.widget.update", ObjUpdateAction, create_modify_schema(obj_spec)
|
||||
)
|
||||
async def obj_update_to_code(config, action_id, template_arg, args):
|
||||
return await update_to_code(config, action_id, template_arg, args)
|
||||
|
@ -38,7 +38,7 @@ TABVIEW_SCHEMA = cv.Schema(
|
||||
},
|
||||
)
|
||||
),
|
||||
cv.Optional(CONF_TAB_STYLE): part_schema(buttonmatrix_spec),
|
||||
cv.Optional(CONF_TAB_STYLE): part_schema(buttonmatrix_spec.parts),
|
||||
cv.Optional(CONF_POSITION, default="top"): DIRECTIONS.one_of,
|
||||
cv.Optional(CONF_SIZE, default="10%"): size,
|
||||
}
|
||||
|
@ -59,6 +59,24 @@ void PrometheusHandler::handleRequest(AsyncWebServerRequest *req) {
|
||||
this->text_sensor_row_(stream, obj, area, node, friendly_name);
|
||||
#endif
|
||||
|
||||
#ifdef USE_NUMBER
|
||||
this->number_type_(stream);
|
||||
for (auto *obj : App.get_numbers())
|
||||
this->number_row_(stream, obj, area, node, friendly_name);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SELECT
|
||||
this->select_type_(stream);
|
||||
for (auto *obj : App.get_selects())
|
||||
this->select_row_(stream, obj, area, node, friendly_name);
|
||||
#endif
|
||||
|
||||
#ifdef USE_MEDIA_PLAYER
|
||||
this->media_player_type_(stream);
|
||||
for (auto *obj : App.get_media_players())
|
||||
this->media_player_row_(stream, obj, area, node, friendly_name);
|
||||
#endif
|
||||
|
||||
req->send(stream);
|
||||
}
|
||||
|
||||
@ -511,6 +529,156 @@ void PrometheusHandler::text_sensor_row_(AsyncResponseStream *stream, text_senso
|
||||
}
|
||||
#endif
|
||||
|
||||
// Type-specific implementation
|
||||
#ifdef USE_NUMBER
|
||||
void PrometheusHandler::number_type_(AsyncResponseStream *stream) {
|
||||
stream->print(F("#TYPE esphome_number_value gauge\n"));
|
||||
stream->print(F("#TYPE esphome_number_failed gauge\n"));
|
||||
}
|
||||
void PrometheusHandler::number_row_(AsyncResponseStream *stream, number::Number *obj, std::string &area,
|
||||
std::string &node, std::string &friendly_name) {
|
||||
if (obj->is_internal() && !this->include_internal_)
|
||||
return;
|
||||
if (!std::isnan(obj->state)) {
|
||||
// We have a valid value, output this value
|
||||
stream->print(F("esphome_number_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
stream->print(F("\"} 0\n"));
|
||||
// Data itself
|
||||
stream->print(F("esphome_number_value{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
stream->print(F("\"} "));
|
||||
stream->print(obj->state);
|
||||
stream->print(F("\n"));
|
||||
} else {
|
||||
// Invalid state
|
||||
stream->print(F("esphome_number_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
stream->print(F("\"} 1\n"));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_SELECT
|
||||
void PrometheusHandler::select_type_(AsyncResponseStream *stream) {
|
||||
stream->print(F("#TYPE esphome_select_value gauge\n"));
|
||||
stream->print(F("#TYPE esphome_select_failed gauge\n"));
|
||||
}
|
||||
void PrometheusHandler::select_row_(AsyncResponseStream *stream, select::Select *obj, std::string &area,
|
||||
std::string &node, std::string &friendly_name) {
|
||||
if (obj->is_internal() && !this->include_internal_)
|
||||
return;
|
||||
if (obj->has_state()) {
|
||||
// We have a valid value, output this value
|
||||
stream->print(F("esphome_select_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
stream->print(F("\"} 0\n"));
|
||||
// Data itself
|
||||
stream->print(F("esphome_select_value{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
stream->print(F("\",value=\""));
|
||||
stream->print(obj->state.c_str());
|
||||
stream->print(F("\"} "));
|
||||
stream->print(F("1.0"));
|
||||
stream->print(F("\n"));
|
||||
} else {
|
||||
// Invalid state
|
||||
stream->print(F("esphome_select_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
stream->print(F("\"} 1\n"));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_MEDIA_PLAYER
|
||||
void PrometheusHandler::media_player_type_(AsyncResponseStream *stream) {
|
||||
stream->print(F("#TYPE esphome_media_player_state_value gauge\n"));
|
||||
stream->print(F("#TYPE esphome_media_player_volume gauge\n"));
|
||||
stream->print(F("#TYPE esphome_media_player_is_muted gauge\n"));
|
||||
stream->print(F("#TYPE esphome_media_player_failed gauge\n"));
|
||||
}
|
||||
void PrometheusHandler::media_player_row_(AsyncResponseStream *stream, media_player::MediaPlayer *obj,
|
||||
std::string &area, std::string &node, std::string &friendly_name) {
|
||||
if (obj->is_internal() && !this->include_internal_)
|
||||
return;
|
||||
stream->print(F("esphome_media_player_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
stream->print(F("\"} 0\n"));
|
||||
// Data itself
|
||||
stream->print(F("esphome_media_player_state_value{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
stream->print(F("\",value=\""));
|
||||
stream->print(media_player::media_player_state_to_string(obj->state));
|
||||
stream->print(F("\"} "));
|
||||
stream->print(F("1.0"));
|
||||
stream->print(F("\n"));
|
||||
stream->print(F("esphome_media_player_volume{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
stream->print(F("\"} "));
|
||||
stream->print(obj->volume);
|
||||
stream->print(F("\n"));
|
||||
stream->print(F("esphome_media_player_is_muted{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
stream->print(F("\"} "));
|
||||
if (obj->is_muted()) {
|
||||
stream->print(F("1.0"));
|
||||
} else {
|
||||
stream->print(F("0.0"));
|
||||
}
|
||||
stream->print(F("\n"));
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace prometheus
|
||||
} // namespace esphome
|
||||
#endif
|
||||
|
@ -128,6 +128,30 @@ class PrometheusHandler : public AsyncWebHandler, public Component {
|
||||
std::string &friendly_name);
|
||||
#endif
|
||||
|
||||
#ifdef USE_NUMBER
|
||||
/// Return the type for prometheus
|
||||
void number_type_(AsyncResponseStream *stream);
|
||||
/// Return the sensor state as prometheus data point
|
||||
void number_row_(AsyncResponseStream *stream, number::Number *obj, std::string &area, std::string &node,
|
||||
std::string &friendly_name);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SELECT
|
||||
/// Return the type for prometheus
|
||||
void select_type_(AsyncResponseStream *stream);
|
||||
/// Return the select state as prometheus data point
|
||||
void select_row_(AsyncResponseStream *stream, select::Select *obj, std::string &area, std::string &node,
|
||||
std::string &friendly_name);
|
||||
#endif
|
||||
|
||||
#ifdef USE_MEDIA_PLAYER
|
||||
/// Return the type for prometheus
|
||||
void media_player_type_(AsyncResponseStream *stream);
|
||||
/// Return the select state as prometheus data point
|
||||
void media_player_row_(AsyncResponseStream *stream, media_player::MediaPlayer *obj, std::string &area,
|
||||
std::string &node, std::string &friendly_name);
|
||||
#endif
|
||||
|
||||
web_server_base::WebServerBase *base_;
|
||||
bool include_internal_{false};
|
||||
std::map<EntityBase *, std::string> relabel_map_id_;
|
||||
|
@ -7,6 +7,10 @@ namespace spi {
|
||||
|
||||
const char *const TAG = "spi";
|
||||
|
||||
SPIDelegate *const SPIDelegate::NULL_DELEGATE = // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
new SPIDelegateDummy();
|
||||
// https://bugs.llvm.org/show_bug.cgi?id=48040
|
||||
|
||||
bool SPIDelegate::is_ready() { return true; }
|
||||
|
||||
GPIOPin *const NullPin::NULL_PIN = new NullPin(); // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
@ -75,6 +79,8 @@ void SPIComponent::dump_config() {
|
||||
}
|
||||
}
|
||||
|
||||
void SPIDelegateDummy::begin_transaction() { ESP_LOGE(TAG, "SPIDevice not initialised - did you call spi_setup()?"); }
|
||||
|
||||
uint8_t SPIDelegateBitBash::transfer(uint8_t data) { return this->transfer_(data, 8); }
|
||||
|
||||
void SPIDelegateBitBash::write(uint16_t data, size_t num_bits) { this->transfer_(data, num_bits); }
|
||||
|
@ -163,6 +163,8 @@ class Utility {
|
||||
}
|
||||
};
|
||||
|
||||
class SPIDelegateDummy;
|
||||
|
||||
// represents a device attached to an SPI bus, with a defined clock rate, mode and bit order. On Arduino this is
|
||||
// a thin wrapper over SPIClass.
|
||||
class SPIDelegate {
|
||||
@ -248,6 +250,21 @@ class SPIDelegate {
|
||||
uint32_t data_rate_{1000000};
|
||||
SPIMode mode_{MODE0};
|
||||
GPIOPin *cs_pin_{NullPin::NULL_PIN};
|
||||
static SPIDelegate *const NULL_DELEGATE; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
};
|
||||
|
||||
/**
|
||||
* A dummy SPIDelegate that complains if it's used.
|
||||
*/
|
||||
|
||||
class SPIDelegateDummy : public SPIDelegate {
|
||||
public:
|
||||
SPIDelegateDummy() = default;
|
||||
|
||||
uint8_t transfer(uint8_t data) override { return 0; }
|
||||
void end_transaction() override{};
|
||||
|
||||
void begin_transaction() override;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -365,7 +382,7 @@ class SPIClient {
|
||||
|
||||
virtual void spi_teardown() {
|
||||
this->parent_->unregister_device(this);
|
||||
this->delegate_ = nullptr;
|
||||
this->delegate_ = SPIDelegate::NULL_DELEGATE;
|
||||
}
|
||||
|
||||
bool spi_is_ready() { return this->delegate_->is_ready(); }
|
||||
@ -376,7 +393,7 @@ class SPIClient {
|
||||
uint32_t data_rate_{1000000};
|
||||
SPIComponent *parent_{nullptr};
|
||||
GPIOPin *cs_{nullptr};
|
||||
SPIDelegate *delegate_{nullptr};
|
||||
SPIDelegate *delegate_{SPIDelegate::NULL_DELEGATE};
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -455,8 +455,9 @@ void WebServer::handle_fan_request(AsyncWebServerRequest *request, const UrlMatc
|
||||
} else if (match.method == "toggle") {
|
||||
this->schedule_([obj]() { obj->toggle().perform(); });
|
||||
request->send(200);
|
||||
} else if (match.method == "turn_on") {
|
||||
auto call = obj->turn_on();
|
||||
} else if (match.method == "turn_on" || match.method == "turn_off") {
|
||||
auto call = match.method == "turn_on" ? obj->turn_on() : obj->turn_off();
|
||||
|
||||
if (request->hasParam("speed_level")) {
|
||||
auto speed_level = request->getParam("speed_level")->value();
|
||||
auto val = parse_number<int>(speed_level.c_str());
|
||||
@ -486,9 +487,6 @@ void WebServer::handle_fan_request(AsyncWebServerRequest *request, const UrlMatc
|
||||
}
|
||||
this->schedule_([call]() mutable { call.perform(); });
|
||||
request->send(200);
|
||||
} else if (match.method == "turn_off") {
|
||||
this->schedule_([obj]() { obj->turn_off().perform(); });
|
||||
request->send(200);
|
||||
} else {
|
||||
request->send(404);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
"""Constants used by esphome."""
|
||||
|
||||
__version__ = "2025.1.0-dev"
|
||||
__version__ = "2025.2.0-dev"
|
||||
|
||||
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
|
||||
VALID_SUBSTITUTIONS_CHARACTERS = (
|
||||
@ -490,6 +490,7 @@ CONF_MEMORY_BLOCKS = "memory_blocks"
|
||||
CONF_MESSAGE = "message"
|
||||
CONF_METHANE = "methane"
|
||||
CONF_METHOD = "method"
|
||||
CONF_MIC_GAIN = "mic_gain"
|
||||
CONF_MICROPHONE = "microphone"
|
||||
CONF_MIN_BRIGHTNESS = "min_brightness"
|
||||
CONF_MIN_COOLING_OFF_TIME = "min_cooling_off_time"
|
||||
|
6
tests/components/es7210/common.yaml
Normal file
6
tests/components/es7210/common.yaml
Normal file
@ -0,0 +1,6 @@
|
||||
i2c:
|
||||
- id: i2c_aic3204
|
||||
scl: ${scl_pin}
|
||||
sda: ${sda_pin}
|
||||
|
||||
es7210:
|
5
tests/components/es7210/test.esp32-ard.yaml
Normal file
5
tests/components/es7210/test.esp32-ard.yaml
Normal file
@ -0,0 +1,5 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO16
|
||||
sda_pin: GPIO17
|
||||
|
||||
<<: !include common.yaml
|
5
tests/components/es7210/test.esp32-c3-ard.yaml
Normal file
5
tests/components/es7210/test.esp32-c3-ard.yaml
Normal file
@ -0,0 +1,5 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO5
|
||||
sda_pin: GPIO4
|
||||
|
||||
<<: !include common.yaml
|
5
tests/components/es7210/test.esp32-c3-idf.yaml
Normal file
5
tests/components/es7210/test.esp32-c3-idf.yaml
Normal file
@ -0,0 +1,5 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO5
|
||||
sda_pin: GPIO4
|
||||
|
||||
<<: !include common.yaml
|
5
tests/components/es7210/test.esp32-idf.yaml
Normal file
5
tests/components/es7210/test.esp32-idf.yaml
Normal file
@ -0,0 +1,5 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO16
|
||||
sda_pin: GPIO17
|
||||
|
||||
<<: !include common.yaml
|
@ -805,9 +805,24 @@ lvgl:
|
||||
- logger.log:
|
||||
format: "keyboard value %s"
|
||||
args: [text.c_str()]
|
||||
- lvgl.keyboard.update:
|
||||
id: lv_keyboard
|
||||
hidden: true
|
||||
on_ready:
|
||||
- lvgl.widget.update:
|
||||
id: lv_keyboard
|
||||
- lvgl.keyboard.update:
|
||||
id: lv_keyboard
|
||||
hidden: true
|
||||
|
||||
- keyboard:
|
||||
id: lv_keyboard1
|
||||
mode: special
|
||||
on_ready:
|
||||
lvgl.keyboard.update:
|
||||
id: lv_keyboard1
|
||||
hidden: true
|
||||
mode: text_lower
|
||||
|
||||
font:
|
||||
- file: "gfonts://Roboto"
|
||||
|
@ -78,6 +78,26 @@ lock:
|
||||
}
|
||||
optimistic: true
|
||||
|
||||
select:
|
||||
- platform: template
|
||||
id: template_select1
|
||||
name: "Template select"
|
||||
optimistic: true
|
||||
options:
|
||||
- one
|
||||
- two
|
||||
- three
|
||||
initial_option: two
|
||||
|
||||
number:
|
||||
- platform: template
|
||||
id: template_number1
|
||||
name: "Template number"
|
||||
optimistic: true
|
||||
min_value: 0
|
||||
max_value: 100
|
||||
step: 1
|
||||
|
||||
prometheus:
|
||||
include_internal: true
|
||||
relabel:
|
||||
|
@ -1 +1,34 @@
|
||||
<<: !include common.yaml
|
||||
|
||||
i2s_audio:
|
||||
i2s_lrclk_pin: 1
|
||||
i2s_bclk_pin: 2
|
||||
i2s_mclk_pin: 3
|
||||
|
||||
media_player:
|
||||
- platform: i2s_audio
|
||||
name: "Media Player"
|
||||
dac_type: external
|
||||
i2s_dout_pin: 18
|
||||
mute_pin: 19
|
||||
on_state:
|
||||
- media_player.play:
|
||||
- media_player.play_media: http://localhost/media.mp3
|
||||
- media_player.play_media: !lambda 'return "http://localhost/media.mp3";'
|
||||
on_idle:
|
||||
- media_player.pause:
|
||||
on_play:
|
||||
- media_player.stop:
|
||||
on_pause:
|
||||
- media_player.toggle:
|
||||
- wait_until:
|
||||
media_player.is_idle:
|
||||
- wait_until:
|
||||
media_player.is_playing:
|
||||
- wait_until:
|
||||
media_player.is_announcing:
|
||||
- wait_until:
|
||||
media_player.is_paused:
|
||||
- media_player.volume_up:
|
||||
- media_player.volume_down:
|
||||
- media_player.volume_set: 50%
|
||||
|
Loading…
Reference in New Issue
Block a user