mirror of
https://github.com/esphome/esphome.git
synced 2025-03-14 06:38:17 +00:00
Merge branch 'dev' into defaults2
This commit is contained in:
commit
adb3c8bb86
4
.github/workflows/stale.yml
vendored
4
.github/workflows/stale.yml
vendored
@ -17,7 +17,7 @@ jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v9.0.0
|
||||
- uses: actions/stale@v9.1.0
|
||||
with:
|
||||
days-before-pr-stale: 90
|
||||
days-before-pr-close: 7
|
||||
@ -37,7 +37,7 @@ jobs:
|
||||
close-issues:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v9.0.0
|
||||
- uses: actions/stale@v9.1.0
|
||||
with:
|
||||
days-before-pr-stale: -1
|
||||
days-before-pr-close: -1
|
||||
|
@ -133,6 +133,7 @@ esphome/components/ens160_i2c/* @latonita
|
||||
esphome/components/ens160_spi/* @latonita
|
||||
esphome/components/ens210/* @itn3rd77
|
||||
esphome/components/es7210/* @kahrendt
|
||||
esphome/components/es7243e/* @kbx81
|
||||
esphome/components/es8156/* @kbx81
|
||||
esphome/components/es8311/* @kahrendt @kroimon
|
||||
esphome/components/esp32/* @esphome/core
|
||||
|
@ -9,8 +9,6 @@ static const char *const TAG = "ads1115";
|
||||
static const uint8_t ADS1115_REGISTER_CONVERSION = 0x00;
|
||||
static const uint8_t ADS1115_REGISTER_CONFIG = 0x01;
|
||||
|
||||
static const uint8_t ADS1115_DATA_RATE_860_SPS = 0b111; // 3300_SPS for ADS1015
|
||||
|
||||
void ADS1115Component::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Setting up ADS1115...");
|
||||
uint16_t value;
|
||||
@ -43,9 +41,9 @@ void ADS1115Component::setup() {
|
||||
config |= 0b0000000100000000;
|
||||
}
|
||||
|
||||
// Set data rate - 860 samples per second (we're in singleshot mode)
|
||||
// Set data rate - 860 samples per second
|
||||
// 0bxxxxxxxx100xxxxx
|
||||
config |= ADS1115_DATA_RATE_860_SPS << 5;
|
||||
config |= ADS1115_860SPS << 5;
|
||||
|
||||
// Set comparator mode - hysteresis
|
||||
// 0bxxxxxxxxxxx0xxxx
|
||||
@ -77,7 +75,7 @@ void ADS1115Component::dump_config() {
|
||||
}
|
||||
}
|
||||
float ADS1115Component::request_measurement(ADS1115Multiplexer multiplexer, ADS1115Gain gain,
|
||||
ADS1115Resolution resolution) {
|
||||
ADS1115Resolution resolution, ADS1115Samplerate samplerate) {
|
||||
uint16_t config = this->prev_config_;
|
||||
// Multiplexer
|
||||
// 0bxBBBxxxxxxxxxxxx
|
||||
@ -89,6 +87,11 @@ float ADS1115Component::request_measurement(ADS1115Multiplexer multiplexer, ADS1
|
||||
config &= 0b1111000111111111;
|
||||
config |= (gain & 0b111) << 9;
|
||||
|
||||
// Sample rate
|
||||
// 0bxxxxxxxxBBBxxxxx
|
||||
config &= 0b1111111100011111;
|
||||
config |= (samplerate & 0b111) << 5;
|
||||
|
||||
if (!this->continuous_mode_) {
|
||||
// Start conversion
|
||||
config |= 0b1000000000000000;
|
||||
@ -101,8 +104,54 @@ float ADS1115Component::request_measurement(ADS1115Multiplexer multiplexer, ADS1
|
||||
}
|
||||
this->prev_config_ = config;
|
||||
|
||||
// about 1.2 ms with 860 samples per second
|
||||
delay(2);
|
||||
// Delay calculated as: ceil((1000/SPS)+.5)
|
||||
if (resolution == ADS1015_12_BITS) {
|
||||
switch (samplerate) {
|
||||
case ADS1115_8SPS:
|
||||
delay(9);
|
||||
break;
|
||||
case ADS1115_16SPS:
|
||||
delay(5);
|
||||
break;
|
||||
case ADS1115_32SPS:
|
||||
delay(3);
|
||||
break;
|
||||
case ADS1115_64SPS:
|
||||
case ADS1115_128SPS:
|
||||
delay(2);
|
||||
break;
|
||||
default:
|
||||
delay(1);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (samplerate) {
|
||||
case ADS1115_8SPS:
|
||||
delay(126); // NOLINT
|
||||
break;
|
||||
case ADS1115_16SPS:
|
||||
delay(63); // NOLINT
|
||||
break;
|
||||
case ADS1115_32SPS:
|
||||
delay(32);
|
||||
break;
|
||||
case ADS1115_64SPS:
|
||||
delay(17);
|
||||
break;
|
||||
case ADS1115_128SPS:
|
||||
delay(9);
|
||||
break;
|
||||
case ADS1115_250SPS:
|
||||
delay(5);
|
||||
break;
|
||||
case ADS1115_475SPS:
|
||||
delay(3);
|
||||
break;
|
||||
case ADS1115_860SPS:
|
||||
delay(2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// in continuous mode, conversion will always be running, rely on the delay
|
||||
// to ensure conversion is taking place with the correct settings
|
||||
|
@ -33,6 +33,17 @@ enum ADS1115Resolution {
|
||||
ADS1015_12_BITS = 12,
|
||||
};
|
||||
|
||||
enum ADS1115Samplerate {
|
||||
ADS1115_8SPS = 0b000,
|
||||
ADS1115_16SPS = 0b001,
|
||||
ADS1115_32SPS = 0b010,
|
||||
ADS1115_64SPS = 0b011,
|
||||
ADS1115_128SPS = 0b100,
|
||||
ADS1115_250SPS = 0b101,
|
||||
ADS1115_475SPS = 0b110,
|
||||
ADS1115_860SPS = 0b111
|
||||
};
|
||||
|
||||
class ADS1115Component : public Component, public i2c::I2CDevice {
|
||||
public:
|
||||
void setup() override;
|
||||
@ -42,7 +53,8 @@ class ADS1115Component : public Component, public i2c::I2CDevice {
|
||||
void set_continuous_mode(bool continuous_mode) { continuous_mode_ = continuous_mode; }
|
||||
|
||||
/// Helper method to request a measurement from a sensor.
|
||||
float request_measurement(ADS1115Multiplexer multiplexer, ADS1115Gain gain, ADS1115Resolution resolution);
|
||||
float request_measurement(ADS1115Multiplexer multiplexer, ADS1115Gain gain, ADS1115Resolution resolution,
|
||||
ADS1115Samplerate samplerate);
|
||||
|
||||
protected:
|
||||
uint16_t prev_config_{0};
|
||||
|
@ -5,6 +5,7 @@ from esphome.const import (
|
||||
CONF_GAIN,
|
||||
CONF_MULTIPLEXER,
|
||||
CONF_RESOLUTION,
|
||||
CONF_SAMPLE_RATE,
|
||||
DEVICE_CLASS_VOLTAGE,
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
UNIT_VOLT,
|
||||
@ -43,6 +44,17 @@ RESOLUTION = {
|
||||
"12_BITS": ADS1115Resolution.ADS1015_12_BITS,
|
||||
}
|
||||
|
||||
ADS1115Samplerate = ads1115_ns.enum("ADS1115Samplerate")
|
||||
SAMPLERATE = {
|
||||
"8": ADS1115Samplerate.ADS1115_8SPS,
|
||||
"16": ADS1115Samplerate.ADS1115_16SPS,
|
||||
"32": ADS1115Samplerate.ADS1115_32SPS,
|
||||
"64": ADS1115Samplerate.ADS1115_64SPS,
|
||||
"128": ADS1115Samplerate.ADS1115_128SPS,
|
||||
"250": ADS1115Samplerate.ADS1115_250SPS,
|
||||
"475": ADS1115Samplerate.ADS1115_475SPS,
|
||||
"860": ADS1115Samplerate.ADS1115_860SPS,
|
||||
}
|
||||
|
||||
ADS1115Sensor = ads1115_ns.class_(
|
||||
"ADS1115Sensor", sensor.Sensor, cg.PollingComponent, voltage_sampler.VoltageSampler
|
||||
@ -64,6 +76,9 @@ CONFIG_SCHEMA = (
|
||||
cv.Optional(CONF_RESOLUTION, default="16_BITS"): cv.enum(
|
||||
RESOLUTION, upper=True, space="_"
|
||||
),
|
||||
cv.Optional(CONF_SAMPLE_RATE, default="860"): cv.enum(
|
||||
SAMPLERATE, string=True
|
||||
),
|
||||
}
|
||||
)
|
||||
.extend(cv.polling_component_schema("60s"))
|
||||
@ -79,3 +94,4 @@ async def to_code(config):
|
||||
cg.add(var.set_multiplexer(config[CONF_MULTIPLEXER]))
|
||||
cg.add(var.set_gain(config[CONF_GAIN]))
|
||||
cg.add(var.set_resolution(config[CONF_RESOLUTION]))
|
||||
cg.add(var.set_samplerate(config[CONF_SAMPLE_RATE]))
|
||||
|
@ -8,7 +8,7 @@ namespace ads1115 {
|
||||
static const char *const TAG = "ads1115.sensor";
|
||||
|
||||
float ADS1115Sensor::sample() {
|
||||
return this->parent_->request_measurement(this->multiplexer_, this->gain_, this->resolution_);
|
||||
return this->parent_->request_measurement(this->multiplexer_, this->gain_, this->resolution_, this->samplerate_);
|
||||
}
|
||||
|
||||
void ADS1115Sensor::update() {
|
||||
@ -24,6 +24,7 @@ void ADS1115Sensor::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, " Multiplexer: %u", this->multiplexer_);
|
||||
ESP_LOGCONFIG(TAG, " Gain: %u", this->gain_);
|
||||
ESP_LOGCONFIG(TAG, " Resolution: %u", this->resolution_);
|
||||
ESP_LOGCONFIG(TAG, " Sample rate: %u", this->samplerate_);
|
||||
}
|
||||
|
||||
} // namespace ads1115
|
||||
|
@ -21,6 +21,7 @@ class ADS1115Sensor : public sensor::Sensor,
|
||||
void set_multiplexer(ADS1115Multiplexer multiplexer) { this->multiplexer_ = multiplexer; }
|
||||
void set_gain(ADS1115Gain gain) { this->gain_ = gain; }
|
||||
void set_resolution(ADS1115Resolution resolution) { this->resolution_ = resolution; }
|
||||
void set_samplerate(ADS1115Samplerate samplerate) { this->samplerate_ = samplerate; }
|
||||
float sample() override;
|
||||
|
||||
void dump_config() override;
|
||||
@ -29,6 +30,7 @@ class ADS1115Sensor : public sensor::Sensor,
|
||||
ADS1115Multiplexer multiplexer_;
|
||||
ADS1115Gain gain_;
|
||||
ADS1115Resolution resolution_;
|
||||
ADS1115Samplerate samplerate_;
|
||||
};
|
||||
|
||||
} // namespace ads1115
|
||||
|
@ -19,6 +19,7 @@ from .boards import BK72XX_BOARD_PINS, BK72XX_BOARDS
|
||||
|
||||
CODEOWNERS = ["@kuba2k2"]
|
||||
AUTO_LOAD = ["libretiny"]
|
||||
IS_TARGET_PLATFORM = True
|
||||
|
||||
COMPONENT_DATA = LibreTinyComponent(
|
||||
name=COMPONENT_BK72XX,
|
||||
|
@ -1,3 +0,0 @@
|
||||
import esphome.codegen as cg
|
||||
|
||||
custom_ns = cg.esphome_ns.namespace("custom")
|
@ -1,31 +1,5 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import binary_sensor
|
||||
from esphome.const import CONF_BINARY_SENSORS, CONF_ID, CONF_LAMBDA
|
||||
from .. import custom_ns
|
||||
|
||||
CustomBinarySensorConstructor = custom_ns.class_("CustomBinarySensorConstructor")
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(CustomBinarySensorConstructor),
|
||||
cv.Required(CONF_LAMBDA): cv.returning_lambda,
|
||||
cv.Required(CONF_BINARY_SENSORS): cv.ensure_list(
|
||||
binary_sensor.binary_sensor_schema()
|
||||
),
|
||||
}
|
||||
CONFIG_SCHEMA = cv.invalid(
|
||||
'The "custom" component has been removed. Consider conversion to an external component.\nhttps://esphome.io/guides/contributing#a-note-about-custom-components'
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
template_ = await cg.process_lambda(
|
||||
config[CONF_LAMBDA],
|
||||
[],
|
||||
return_type=cg.std_vector.template(binary_sensor.BinarySensorPtr),
|
||||
)
|
||||
|
||||
rhs = CustomBinarySensorConstructor(template_)
|
||||
custom = cg.variable(config[CONF_ID], rhs)
|
||||
for i, conf in enumerate(config[CONF_BINARY_SENSORS]):
|
||||
rhs = custom.Pget_binary_sensor(i)
|
||||
await binary_sensor.register_binary_sensor(rhs, conf)
|
||||
|
@ -1,16 +0,0 @@
|
||||
#include "custom_binary_sensor.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace custom {
|
||||
|
||||
static const char *const TAG = "custom.binary_sensor";
|
||||
|
||||
void CustomBinarySensorConstructor::dump_config() {
|
||||
for (auto *child : this->binary_sensors_) {
|
||||
LOG_BINARY_SENSOR("", "Custom Binary Sensor", child);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace custom
|
||||
} // namespace esphome
|
@ -1,26 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/binary_sensor/binary_sensor.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace esphome {
|
||||
namespace custom {
|
||||
|
||||
class CustomBinarySensorConstructor : public Component {
|
||||
public:
|
||||
CustomBinarySensorConstructor(const std::function<std::vector<binary_sensor::BinarySensor *>()> &init) {
|
||||
this->binary_sensors_ = init();
|
||||
}
|
||||
|
||||
binary_sensor::BinarySensor *get_binary_sensor(int i) { return this->binary_sensors_[i]; }
|
||||
|
||||
void dump_config() override;
|
||||
|
||||
protected:
|
||||
std::vector<binary_sensor::BinarySensor *> binary_sensors_;
|
||||
};
|
||||
|
||||
} // namespace custom
|
||||
} // namespace esphome
|
@ -1,30 +1,5 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import climate
|
||||
from esphome.const import CONF_ID, CONF_LAMBDA
|
||||
from .. import custom_ns
|
||||
|
||||
CustomClimateConstructor = custom_ns.class_("CustomClimateConstructor")
|
||||
CONF_CLIMATES = "climates"
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(CustomClimateConstructor),
|
||||
cv.Required(CONF_LAMBDA): cv.returning_lambda,
|
||||
cv.Required(CONF_CLIMATES): cv.ensure_list(climate.CLIMATE_SCHEMA),
|
||||
}
|
||||
CONFIG_SCHEMA = cv.invalid(
|
||||
'The "custom" component has been removed. Consider conversion to an external component.\nhttps://esphome.io/guides/contributing#a-note-about-custom-components'
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
template_ = await cg.process_lambda(
|
||||
config[CONF_LAMBDA],
|
||||
[],
|
||||
return_type=cg.std_vector.template(climate.Climate.operator("ptr")),
|
||||
)
|
||||
|
||||
rhs = CustomClimateConstructor(template_)
|
||||
custom = cg.variable(config[CONF_ID], rhs)
|
||||
for i, conf in enumerate(config[CONF_CLIMATES]):
|
||||
rhs = custom.Pget_climate(i)
|
||||
await climate.register_climate(rhs, conf)
|
||||
|
@ -1,22 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/climate/climate.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace esphome {
|
||||
namespace custom {
|
||||
|
||||
class CustomClimateConstructor {
|
||||
public:
|
||||
CustomClimateConstructor(const std::function<std::vector<climate::Climate *>()> &init) { this->climates_ = init(); }
|
||||
|
||||
climate::Climate *get_climate(int i) { return this->climates_[i]; }
|
||||
|
||||
protected:
|
||||
std::vector<climate::Climate *> climates_;
|
||||
};
|
||||
|
||||
} // namespace custom
|
||||
} // namespace esphome
|
@ -1,30 +1,5 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import cover
|
||||
from esphome.const import CONF_ID, CONF_LAMBDA
|
||||
from .. import custom_ns
|
||||
|
||||
CustomCoverConstructor = custom_ns.class_("CustomCoverConstructor")
|
||||
CONF_COVERS = "covers"
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(CustomCoverConstructor),
|
||||
cv.Required(CONF_LAMBDA): cv.returning_lambda,
|
||||
cv.Required(CONF_COVERS): cv.ensure_list(cover.COVER_SCHEMA),
|
||||
}
|
||||
CONFIG_SCHEMA = cv.invalid(
|
||||
'The "custom" component has been removed. Consider conversion to an external component.\nhttps://esphome.io/guides/contributing#a-note-about-custom-components'
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
template_ = await cg.process_lambda(
|
||||
config[CONF_LAMBDA],
|
||||
[],
|
||||
return_type=cg.std_vector.template(cover.Cover.operator("ptr")),
|
||||
)
|
||||
|
||||
rhs = CustomCoverConstructor(template_)
|
||||
custom = cg.variable(config[CONF_ID], rhs)
|
||||
for i, conf in enumerate(config[CONF_COVERS]):
|
||||
rhs = custom.Pget_cover(i)
|
||||
await cover.register_cover(rhs, conf)
|
||||
|
@ -1,21 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/components/cover/cover.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace esphome {
|
||||
namespace custom {
|
||||
|
||||
class CustomCoverConstructor {
|
||||
public:
|
||||
CustomCoverConstructor(const std::function<std::vector<cover::Cover *>()> &init) { this->covers_ = init(); }
|
||||
|
||||
cover::Cover *get_cover(int i) { return this->covers_[i]; }
|
||||
|
||||
protected:
|
||||
std::vector<cover::Cover *> covers_;
|
||||
};
|
||||
|
||||
} // namespace custom
|
||||
} // namespace esphome
|
@ -1,30 +1,5 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import light
|
||||
from esphome.const import CONF_ID, CONF_LAMBDA
|
||||
from .. import custom_ns
|
||||
|
||||
CustomLightOutputConstructor = custom_ns.class_("CustomLightOutputConstructor")
|
||||
CONF_LIGHTS = "lights"
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(CustomLightOutputConstructor),
|
||||
cv.Required(CONF_LAMBDA): cv.returning_lambda,
|
||||
cv.Required(CONF_LIGHTS): cv.ensure_list(light.ADDRESSABLE_LIGHT_SCHEMA),
|
||||
}
|
||||
CONFIG_SCHEMA = cv.invalid(
|
||||
'The "custom" component has been removed. Consider conversion to an external component.\nhttps://esphome.io/guides/contributing#a-note-about-custom-components'
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
template_ = await cg.process_lambda(
|
||||
config[CONF_LAMBDA],
|
||||
[],
|
||||
return_type=cg.std_vector.template(light.LightOutput.operator("ptr")),
|
||||
)
|
||||
|
||||
rhs = CustomLightOutputConstructor(template_)
|
||||
custom = cg.variable(config[CONF_ID], rhs)
|
||||
for i, conf in enumerate(config[CONF_LIGHTS]):
|
||||
rhs = custom.Pget_light(i)
|
||||
await light.register_light(rhs, conf)
|
||||
|
@ -1,24 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/light/light_output.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace esphome {
|
||||
namespace custom {
|
||||
|
||||
class CustomLightOutputConstructor {
|
||||
public:
|
||||
CustomLightOutputConstructor(const std::function<std::vector<light::LightOutput *>()> &init) {
|
||||
this->outputs_ = init();
|
||||
}
|
||||
|
||||
light::LightOutput *get_light(int i) { return this->outputs_[i]; }
|
||||
|
||||
protected:
|
||||
std::vector<light::LightOutput *> outputs_;
|
||||
};
|
||||
|
||||
} // namespace custom
|
||||
} // namespace esphome
|
@ -1,61 +1,5 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import output
|
||||
from esphome.const import CONF_ID, CONF_LAMBDA, CONF_OUTPUTS, CONF_TYPE, CONF_BINARY
|
||||
from .. import custom_ns
|
||||
|
||||
CustomBinaryOutputConstructor = custom_ns.class_("CustomBinaryOutputConstructor")
|
||||
CustomFloatOutputConstructor = custom_ns.class_("CustomFloatOutputConstructor")
|
||||
|
||||
CONF_FLOAT = "float"
|
||||
|
||||
CONFIG_SCHEMA = cv.typed_schema(
|
||||
{
|
||||
CONF_BINARY: cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(CustomBinaryOutputConstructor),
|
||||
cv.Required(CONF_LAMBDA): cv.returning_lambda,
|
||||
cv.Required(CONF_OUTPUTS): cv.ensure_list(
|
||||
output.BINARY_OUTPUT_SCHEMA.extend(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(output.BinaryOutput),
|
||||
}
|
||||
)
|
||||
),
|
||||
}
|
||||
),
|
||||
CONF_FLOAT: cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(CustomFloatOutputConstructor),
|
||||
cv.Required(CONF_LAMBDA): cv.returning_lambda,
|
||||
cv.Required(CONF_OUTPUTS): cv.ensure_list(
|
||||
output.FLOAT_OUTPUT_SCHEMA.extend(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(output.FloatOutput),
|
||||
}
|
||||
)
|
||||
),
|
||||
}
|
||||
),
|
||||
},
|
||||
lower=True,
|
||||
CONFIG_SCHEMA = cv.invalid(
|
||||
'The "custom" component has been removed. Consider conversion to an external component.\nhttps://esphome.io/guides/contributing#a-note-about-custom-components'
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
type = config[CONF_TYPE]
|
||||
if type == "binary":
|
||||
ret_type = output.BinaryOutputPtr
|
||||
klass = CustomBinaryOutputConstructor
|
||||
else:
|
||||
ret_type = output.FloatOutputPtr
|
||||
klass = CustomFloatOutputConstructor
|
||||
template_ = await cg.process_lambda(
|
||||
config[CONF_LAMBDA], [], return_type=cg.std_vector.template(ret_type)
|
||||
)
|
||||
|
||||
rhs = klass(template_)
|
||||
custom = cg.variable(config[CONF_ID], rhs)
|
||||
for i, conf in enumerate(config[CONF_OUTPUTS]):
|
||||
out = cg.Pvariable(conf[CONF_ID], custom.get_output(i))
|
||||
await output.register_output(out, conf)
|
||||
|
@ -1,37 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/output/binary_output.h"
|
||||
#include "esphome/components/output/float_output.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace esphome {
|
||||
namespace custom {
|
||||
|
||||
class CustomBinaryOutputConstructor {
|
||||
public:
|
||||
CustomBinaryOutputConstructor(const std::function<std::vector<output::BinaryOutput *>()> &init) {
|
||||
this->outputs_ = init();
|
||||
}
|
||||
|
||||
output::BinaryOutput *get_output(int i) { return this->outputs_[i]; }
|
||||
|
||||
protected:
|
||||
std::vector<output::BinaryOutput *> outputs_;
|
||||
};
|
||||
|
||||
class CustomFloatOutputConstructor {
|
||||
public:
|
||||
CustomFloatOutputConstructor(const std::function<std::vector<output::FloatOutput *>()> &init) {
|
||||
this->outputs_ = init();
|
||||
}
|
||||
|
||||
output::FloatOutput *get_output(int i) { return this->outputs_[i]; }
|
||||
|
||||
protected:
|
||||
std::vector<output::FloatOutput *> outputs_;
|
||||
};
|
||||
|
||||
} // namespace custom
|
||||
} // namespace esphome
|
@ -1,27 +1,5 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import sensor
|
||||
from esphome.const import CONF_ID, CONF_LAMBDA, CONF_SENSORS
|
||||
from .. import custom_ns
|
||||
|
||||
CustomSensorConstructor = custom_ns.class_("CustomSensorConstructor")
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(CustomSensorConstructor),
|
||||
cv.Required(CONF_LAMBDA): cv.returning_lambda,
|
||||
cv.Required(CONF_SENSORS): cv.ensure_list(sensor.sensor_schema()),
|
||||
}
|
||||
CONFIG_SCHEMA = cv.invalid(
|
||||
'The "custom" component has been removed. Consider conversion to an external component.\nhttps://esphome.io/guides/contributing#a-note-about-custom-components'
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
template_ = await cg.process_lambda(
|
||||
config[CONF_LAMBDA], [], return_type=cg.std_vector.template(sensor.SensorPtr)
|
||||
)
|
||||
|
||||
rhs = CustomSensorConstructor(template_)
|
||||
var = cg.variable(config[CONF_ID], rhs)
|
||||
for i, conf in enumerate(config[CONF_SENSORS]):
|
||||
sens = cg.Pvariable(conf[CONF_ID], var.get_sensor(i))
|
||||
await sensor.register_sensor(sens, conf)
|
||||
|
@ -1,16 +0,0 @@
|
||||
#include "custom_sensor.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace custom {
|
||||
|
||||
static const char *const TAG = "custom.sensor";
|
||||
|
||||
void CustomSensorConstructor::dump_config() {
|
||||
for (auto *child : this->sensors_) {
|
||||
LOG_SENSOR("", "Custom Sensor", child);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace custom
|
||||
} // namespace esphome
|
@ -1,24 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace esphome {
|
||||
namespace custom {
|
||||
|
||||
class CustomSensorConstructor : public Component {
|
||||
public:
|
||||
CustomSensorConstructor(const std::function<std::vector<sensor::Sensor *>()> &init) { this->sensors_ = init(); }
|
||||
|
||||
sensor::Sensor *get_sensor(int i) { return this->sensors_[i]; }
|
||||
|
||||
void dump_config() override;
|
||||
|
||||
protected:
|
||||
std::vector<sensor::Sensor *> sensors_;
|
||||
};
|
||||
|
||||
} // namespace custom
|
||||
} // namespace esphome
|
@ -1,27 +1,5 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import switch
|
||||
from esphome.const import CONF_ID, CONF_LAMBDA, CONF_SWITCHES
|
||||
from .. import custom_ns
|
||||
|
||||
CustomSwitchConstructor = custom_ns.class_("CustomSwitchConstructor")
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(CustomSwitchConstructor),
|
||||
cv.Required(CONF_LAMBDA): cv.returning_lambda,
|
||||
cv.Required(CONF_SWITCHES): cv.ensure_list(switch.switch_schema(switch.Switch)),
|
||||
}
|
||||
CONFIG_SCHEMA = cv.invalid(
|
||||
'The "custom" component has been removed. Consider conversion to an external component.\nhttps://esphome.io/guides/contributing#a-note-about-custom-components'
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
template_ = await cg.process_lambda(
|
||||
config[CONF_LAMBDA], [], return_type=cg.std_vector.template(switch.SwitchPtr)
|
||||
)
|
||||
|
||||
rhs = CustomSwitchConstructor(template_)
|
||||
var = cg.variable(config[CONF_ID], rhs)
|
||||
for i, conf in enumerate(config[CONF_SWITCHES]):
|
||||
switch_ = cg.Pvariable(conf[CONF_ID], var.get_switch(i))
|
||||
await switch.register_switch(switch_, conf)
|
||||
|
@ -1,16 +0,0 @@
|
||||
#include "custom_switch.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace custom {
|
||||
|
||||
static const char *const TAG = "custom.switch";
|
||||
|
||||
void CustomSwitchConstructor::dump_config() {
|
||||
for (auto *child : this->switches_) {
|
||||
LOG_SWITCH("", "Custom Switch", child);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace custom
|
||||
} // namespace esphome
|
@ -1,24 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/switch/switch.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace esphome {
|
||||
namespace custom {
|
||||
|
||||
class CustomSwitchConstructor : public Component {
|
||||
public:
|
||||
CustomSwitchConstructor(const std::function<std::vector<switch_::Switch *>()> &init) { this->switches_ = init(); }
|
||||
|
||||
switch_::Switch *get_switch(int i) { return this->switches_[i]; }
|
||||
|
||||
void dump_config() override;
|
||||
|
||||
protected:
|
||||
std::vector<switch_::Switch *> switches_;
|
||||
};
|
||||
|
||||
} // namespace custom
|
||||
} // namespace esphome
|
@ -1,32 +1,5 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import text_sensor
|
||||
from esphome.const import CONF_ID, CONF_LAMBDA, CONF_TEXT_SENSORS
|
||||
from .. import custom_ns
|
||||
|
||||
CustomTextSensorConstructor = custom_ns.class_("CustomTextSensorConstructor")
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(CustomTextSensorConstructor),
|
||||
cv.Required(CONF_LAMBDA): cv.returning_lambda,
|
||||
cv.Required(CONF_TEXT_SENSORS): cv.ensure_list(
|
||||
text_sensor.text_sensor_schema()
|
||||
),
|
||||
}
|
||||
CONFIG_SCHEMA = cv.invalid(
|
||||
'The "custom" component has been removed. Consider conversion to an external component.\nhttps://esphome.io/guides/contributing#a-note-about-custom-components'
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
template_ = await cg.process_lambda(
|
||||
config[CONF_LAMBDA],
|
||||
[],
|
||||
return_type=cg.std_vector.template(text_sensor.TextSensorPtr),
|
||||
)
|
||||
|
||||
rhs = CustomTextSensorConstructor(template_)
|
||||
var = cg.variable(config[CONF_ID], rhs)
|
||||
|
||||
for i, conf in enumerate(config[CONF_TEXT_SENSORS]):
|
||||
text = cg.Pvariable(conf[CONF_ID], var.get_text_sensor(i))
|
||||
await text_sensor.register_text_sensor(text, conf)
|
||||
|
@ -1,16 +0,0 @@
|
||||
#include "custom_text_sensor.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace custom {
|
||||
|
||||
static const char *const TAG = "custom.text_sensor";
|
||||
|
||||
void CustomTextSensorConstructor::dump_config() {
|
||||
for (auto *child : this->text_sensors_) {
|
||||
LOG_TEXT_SENSOR("", "Custom Text Sensor", child);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace custom
|
||||
} // namespace esphome
|
@ -1,26 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/text_sensor/text_sensor.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace esphome {
|
||||
namespace custom {
|
||||
|
||||
class CustomTextSensorConstructor : public Component {
|
||||
public:
|
||||
CustomTextSensorConstructor(const std::function<std::vector<text_sensor::TextSensor *>()> &init) {
|
||||
this->text_sensors_ = init();
|
||||
}
|
||||
|
||||
text_sensor::TextSensor *get_text_sensor(int i) { return this->text_sensors_[i]; }
|
||||
|
||||
void dump_config() override;
|
||||
|
||||
protected:
|
||||
std::vector<text_sensor::TextSensor *> text_sensors_;
|
||||
};
|
||||
|
||||
} // namespace custom
|
||||
} // namespace esphome
|
@ -1,31 +1,7 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_COMPONENTS, CONF_ID, CONF_LAMBDA
|
||||
|
||||
custom_component_ns = cg.esphome_ns.namespace("custom_component")
|
||||
CustomComponentConstructor = custom_component_ns.class_("CustomComponentConstructor")
|
||||
|
||||
MULTI_CONF = True
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(CustomComponentConstructor),
|
||||
cv.Required(CONF_LAMBDA): cv.returning_lambda,
|
||||
cv.Optional(CONF_COMPONENTS): cv.ensure_list(
|
||||
cv.Schema({cv.GenerateID(): cv.declare_id(cg.Component)}).extend(
|
||||
cv.COMPONENT_SCHEMA
|
||||
)
|
||||
),
|
||||
}
|
||||
|
||||
CONFIG_SCHEMA = cv.invalid(
|
||||
'The "custom" component has been removed. Consider conversion to an external component.\nhttps://esphome.io/guides/contributing#a-note-about-custom-components'
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
template_ = await cg.process_lambda(
|
||||
config[CONF_LAMBDA], [], return_type=cg.std_vector.template(cg.ComponentPtr)
|
||||
)
|
||||
|
||||
rhs = CustomComponentConstructor(template_)
|
||||
var = cg.variable(config[CONF_ID], rhs)
|
||||
for i, conf in enumerate(config.get(CONF_COMPONENTS, [])):
|
||||
comp = cg.Pvariable(conf[CONF_ID], var.get_component(i))
|
||||
await cg.register_component(comp, conf)
|
||||
|
@ -1,28 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/application.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace esphome {
|
||||
namespace custom_component {
|
||||
|
||||
class CustomComponentConstructor {
|
||||
public:
|
||||
CustomComponentConstructor(const std::function<std::vector<Component *>()> &init) {
|
||||
this->components_ = init();
|
||||
|
||||
for (auto *comp : this->components_) {
|
||||
App.register_component(comp);
|
||||
}
|
||||
}
|
||||
|
||||
Component *get_component(int i) const { return this->components_[i]; }
|
||||
|
||||
protected:
|
||||
std::vector<Component *> components_;
|
||||
};
|
||||
|
||||
} // namespace custom_component
|
||||
} // namespace esphome
|
@ -35,8 +35,8 @@ void DebugComponent::log_partition_info_() {
|
||||
esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_ANY, NULL);
|
||||
while (it != NULL) {
|
||||
const esp_partition_t *partition = esp_partition_get(it);
|
||||
ESP_LOGCONFIG(TAG, " %-12s %-4d %-8d 0x%08X 0x%08X", partition->label, partition->type, partition->subtype,
|
||||
partition->address, partition->size);
|
||||
ESP_LOGCONFIG(TAG, " %-12s %-4d %-8d 0x%08" PRIX32 " 0x%08" PRIX32, partition->label, partition->type,
|
||||
partition->subtype, partition->address, partition->size);
|
||||
it = esp_partition_next(it);
|
||||
}
|
||||
esp_partition_iterator_release(it);
|
||||
|
0
esphome/components/es7243e/__init__.py
Normal file
0
esphome/components/es7243e/__init__.py
Normal file
34
esphome/components/es7243e/audio_adc.py
Normal file
34
esphome/components/es7243e/audio_adc.py
Normal file
@ -0,0 +1,34 @@
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import i2c
|
||||
from esphome.components.audio_adc import AudioAdc
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_ID, CONF_MIC_GAIN
|
||||
|
||||
CODEOWNERS = ["@kbx81"]
|
||||
DEPENDENCIES = ["i2c"]
|
||||
|
||||
es7243e_ns = cg.esphome_ns.namespace("es7243e")
|
||||
ES7243E = es7243e_ns.class_("ES7243E", AudioAdc, cg.Component, i2c.I2CDevice)
|
||||
|
||||
ES7243E_MIC_GAINS = [0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 34.5, 36, 37.5]
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(ES7243E),
|
||||
cv.Optional(CONF_MIC_GAIN, default="24db"): cv.All(
|
||||
cv.decibel, cv.one_of(*ES7243E_MIC_GAINS)
|
||||
),
|
||||
}
|
||||
)
|
||||
.extend(cv.COMPONENT_SCHEMA)
|
||||
.extend(i2c.i2c_device_schema(0x10))
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
await i2c.register_i2c_device(var, config)
|
||||
|
||||
cg.add(var.set_mic_gain(config[CONF_MIC_GAIN]))
|
125
esphome/components/es7243e/es7243e.cpp
Normal file
125
esphome/components/es7243e/es7243e.cpp
Normal file
@ -0,0 +1,125 @@
|
||||
#include "es7243e.h"
|
||||
#include "es7243e_const.h"
|
||||
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
#include <cinttypes>
|
||||
|
||||
namespace esphome {
|
||||
namespace es7243e {
|
||||
|
||||
static const char *const TAG = "es7243e";
|
||||
|
||||
// Mark the component as failed; use only in setup
|
||||
#define ES7243E_ERROR_FAILED(func) \
|
||||
if (!(func)) { \
|
||||
this->mark_failed(); \
|
||||
return; \
|
||||
}
|
||||
|
||||
// Return false; use outside of setup
|
||||
#define ES7243E_ERROR_CHECK(func) \
|
||||
if (!(func)) { \
|
||||
return false; \
|
||||
}
|
||||
|
||||
void ES7243E::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "ES7243E audio ADC:");
|
||||
|
||||
if (this->is_failed()) {
|
||||
ESP_LOGE(TAG, " Failed to initialize");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ES7243E::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Setting up ES7243E...");
|
||||
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG01, 0x3A));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_RESET_REG00, 0x80));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_TEST_MODE_REGF9, 0x00));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG04, 0x02));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG04, 0x01));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_TEST_MODE_REGF9, 0x01));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_RESET_REG00, 0x1E));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG01, 0x00));
|
||||
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG02, 0x00));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG03, 0x20));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG04, 0x01));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ADC_CTRL_REG0D, 0x00));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG05, 0x00));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG06, 0x03)); // SCLK=MCLK/4
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG07, 0x00)); // LRCK=MCLK/256
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG08, 0xFF)); // LRCK=MCLK/256
|
||||
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG09, 0xCA));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_SDP_REG0A, 0x85));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_SDP_REG0B, 0x00));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ADC_CTRL_REG0E, 0xBF));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ADC_CTRL_REG0F, 0x80));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ADC_CTRL_REG14, 0x0C));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ADC_CTRL_REG15, 0x0C));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG17, 0x02));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG18, 0x26));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG19, 0x77));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG1A, 0xF4));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG1B, 0x66));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG1C, 0x44));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG1E, 0x00));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG1F, 0x0C));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG20, 0x1A)); // PGA gain +30dB
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG21, 0x1A));
|
||||
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_RESET_REG00, 0x80));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG01, 0x3A));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG16, 0x3F));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG16, 0x00));
|
||||
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_TEST_MODE_REGF9, 0x00));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG04, 0x01));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG17, 0x01));
|
||||
ES7243E_ERROR_FAILED(this->configure_mic_gain_());
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_RESET_REG00, 0x80));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG01, 0x3A));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG16, 0x3F));
|
||||
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_ANALOG_REG16, 0x00));
|
||||
|
||||
this->setup_complete_ = true;
|
||||
}
|
||||
|
||||
bool ES7243E::set_mic_gain(float mic_gain) {
|
||||
this->mic_gain_ = clamp<float>(mic_gain, 0, 37.5);
|
||||
if (this->setup_complete_) {
|
||||
return this->configure_mic_gain_();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ES7243E::configure_mic_gain_() {
|
||||
auto regv = this->es7243e_gain_reg_value_(this->mic_gain_);
|
||||
|
||||
ES7243E_ERROR_CHECK(this->write_byte(ES7243E_ANALOG_REG20, 0x10 | regv));
|
||||
ES7243E_ERROR_CHECK(this->write_byte(ES7243E_ANALOG_REG21, 0x10 | regv));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t ES7243E::es7243e_gain_reg_value_(float mic_gain) {
|
||||
// reg: 12 - 34.5dB, 13 - 36dB, 14 - 37.5dB
|
||||
mic_gain += 0.5;
|
||||
if (mic_gain <= 33.0) {
|
||||
return (uint8_t) mic_gain / 3;
|
||||
}
|
||||
if (mic_gain < 36.0) {
|
||||
return 12;
|
||||
}
|
||||
if (mic_gain < 37.0) {
|
||||
return 13;
|
||||
}
|
||||
return 14;
|
||||
}
|
||||
|
||||
} // namespace es7243e
|
||||
} // namespace esphome
|
37
esphome/components/es7243e/es7243e.h
Normal file
37
esphome/components/es7243e/es7243e.h
Normal file
@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/components/audio_adc/audio_adc.h"
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
#include "esphome/core/component.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace es7243e {
|
||||
|
||||
class ES7243E : public audio_adc::AudioAdc, public Component, public i2c::I2CDevice {
|
||||
/* Class for configuring an ES7243E ADC for microphone input.
|
||||
* Based on code from:
|
||||
* - https://github.com/espressif/esp-adf/ (accessed 20250116)
|
||||
*/
|
||||
public:
|
||||
void setup() override;
|
||||
float get_setup_priority() const override { return setup_priority::DATA; }
|
||||
void dump_config() override;
|
||||
|
||||
bool set_mic_gain(float mic_gain) override;
|
||||
|
||||
float mic_gain() override { return this->mic_gain_; };
|
||||
|
||||
protected:
|
||||
/// @brief Convert floating point mic gain value to register value
|
||||
/// @param mic_gain Gain value to convert
|
||||
/// @return Corresponding register value for specified gain
|
||||
uint8_t es7243e_gain_reg_value_(float mic_gain);
|
||||
|
||||
bool configure_mic_gain_();
|
||||
|
||||
bool setup_complete_{false};
|
||||
float mic_gain_{0};
|
||||
};
|
||||
|
||||
} // namespace es7243e
|
||||
} // namespace esphome
|
54
esphome/components/es7243e/es7243e_const.h
Normal file
54
esphome/components/es7243e/es7243e_const.h
Normal file
@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
|
||||
#include <cinttypes>
|
||||
|
||||
namespace esphome {
|
||||
namespace es7243e {
|
||||
|
||||
// ES7243E register addresses
|
||||
static const uint8_t ES7243E_RESET_REG00 = 0x00; // Reset control
|
||||
static const uint8_t ES7243E_CLOCK_MGR_REG01 = 0x01; // MCLK/BCLK/ADCCLK/Analog clocks on/off
|
||||
static const uint8_t ES7243E_CLOCK_MGR_REG02 = 0x02; // MCLK & BCLK configuration, source selection
|
||||
|
||||
static const uint8_t ES7243E_CLOCK_MGR_REG03 = 0x03; // ADC Over-sample rate control
|
||||
static const uint8_t ES7243E_CLOCK_MGR_REG04 = 0x04; // Pre-divide/Pre-multiplication
|
||||
static const uint8_t ES7243E_CLOCK_MGR_REG05 = 0x05; // CF/DSP clock divider
|
||||
static const uint8_t ES7243E_CLOCK_MGR_REG06 = 0x06; // BCLK divider at master mode
|
||||
static const uint8_t ES7243E_CLOCK_MGR_REG07 = 0x07; // BCLK/LRCK/SDOUT tri-state control/LRCK divider bit 11->8
|
||||
static const uint8_t ES7243E_CLOCK_MGR_REG08 = 0x08; // Master LRCK divider bit 7 to bit 0
|
||||
static const uint8_t ES7243E_CLOCK_MGR_REG09 = 0x09; // SEL S1/Timer for S1
|
||||
static const uint8_t ES7243E_SDP_REG0A = 0x0A; // SEL S3/Timer for S3
|
||||
static const uint8_t ES7243E_SDP_REG0B = 0x0B; // SDP out mute control/I2S/left-justify case/word length/format
|
||||
static const uint8_t ES7243E_SDP_REG0C = 0x0C; // NFS flag at slot0/LSB/TDM mode selection
|
||||
static const uint8_t ES7243E_ADC_CTRL_REG0D = 0x0D; // data mux/pol. inv./ram clear on lrck/mclk active/gain scale up
|
||||
static const uint8_t ES7243E_ADC_CTRL_REG0E = 0x0E; // volume control
|
||||
static const uint8_t ES7243E_ADC_CTRL_REG0F = 0x0F; // offset freeze/auto level control/automute control/VC ramp rate
|
||||
static const uint8_t ES7243E_ADC_CTRL_REG10 = 0x10; // automute noise gate/detection
|
||||
static const uint8_t ES7243E_ADC_CTRL_REG11 = 0x11; // automute SDP control/out gain select
|
||||
static const uint8_t ES7243E_ADC_CTRL_REG12 = 0x12; // controls for automute PDN_PGA/MOD/reset/digital circuit
|
||||
static const uint8_t ES7243E_ADC_CTRL_REG13 = 0x13; // ALC rate selection/ALC target level
|
||||
static const uint8_t ES7243E_ADC_CTRL_REG14 = 0x14; // ADCHPF stage1 coeff
|
||||
static const uint8_t ES7243E_ADC_CTRL_REG15 = 0x15; // ADCHPF stage2 coeff
|
||||
static const uint8_t ES7243E_ANALOG_REG16 = 0x16; // power-down/reset
|
||||
static const uint8_t ES7243E_ANALOG_REG17 = 0x17; // VMIDSEL
|
||||
static const uint8_t ES7243E_ANALOG_REG18 = 0x18; // ADC/ADCFL bias
|
||||
static const uint8_t ES7243E_ANALOG_REG19 = 0x19; // PGA1/PGA2 bias
|
||||
static const uint8_t ES7243E_ANALOG_REG1A = 0x1A; // ADCI1/ADCI23 bias
|
||||
static const uint8_t ES7243E_ANALOG_REG1B = 0x1B; // ADCSM/ADCCM bias
|
||||
static const uint8_t ES7243E_ANALOG_REG1C = 0x1C; // ADCVRP/ADCCPP bias
|
||||
static const uint8_t ES7243E_ANALOG_REG1D = 0x1D; // low power bits
|
||||
static const uint8_t ES7243E_ANALOG_REG1E = 0x1E; // low power bits
|
||||
static const uint8_t ES7243E_ANALOG_REG1F = 0x1F; // ADC_DMIC_ON/REFSEL/VX2OFF/VX1SEL/VMIDLVL
|
||||
static const uint8_t ES7243E_ANALOG_REG20 = 0x20; // select MIC1 as PGA1 input/PGA1 gain
|
||||
static const uint8_t ES7243E_ANALOG_REG21 = 0x21; // select MIC2 as PGA1 input/PGA2 gain
|
||||
static const uint8_t ES7243E_TEST_MODE_REGF7 = 0xF7;
|
||||
static const uint8_t ES7243E_TEST_MODE_REGF8 = 0xF8;
|
||||
static const uint8_t ES7243E_TEST_MODE_REGF9 = 0xF9;
|
||||
static const uint8_t ES7243E_I2C_CONF_REGFA = 0xFA; // I2C signals retime/reset registers to default
|
||||
static const uint8_t ES7243E_FLAG_REGFC = 0xFC; // CSM flag/ADC automute flag (RO)
|
||||
static const uint8_t ES7243E_CHIP_ID1_REGFD = 0xFD; // chip ID 1, reads 0x7A (RO)
|
||||
static const uint8_t ES7243E_CHIP_ID2_REGFE = 0xFE; // chip ID 2, reads 0x43 (RO)
|
||||
static const uint8_t ES7243E_CHIP_VERSION_REGFF = 0xFF; // chip version, reads 0x00 (RO)
|
||||
|
||||
} // namespace es7243e
|
||||
} // namespace esphome
|
@ -64,6 +64,7 @@ from .gpio import esp32_pin_to_code # noqa
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
CODEOWNERS = ["@esphome/core"]
|
||||
AUTO_LOAD = ["preferences"]
|
||||
IS_TARGET_PLATFORM = True
|
||||
|
||||
CONF_RELEASE = "release"
|
||||
|
||||
|
@ -34,6 +34,7 @@ from .gpio import PinInitialState, add_pin_initial_states_array
|
||||
CODEOWNERS = ["@esphome/core"]
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
AUTO_LOAD = ["preferences"]
|
||||
IS_TARGET_PLATFORM = True
|
||||
|
||||
|
||||
def set_core_data(config):
|
||||
|
@ -17,6 +17,7 @@ from .gpio import host_pin_to_code # noqa
|
||||
|
||||
CODEOWNERS = ["@esphome/core", "@clydebarrow"]
|
||||
AUTO_LOAD = ["network", "preferences"]
|
||||
IS_TARGET_PLATFORM = True
|
||||
|
||||
|
||||
def set_core_data(config):
|
||||
|
@ -47,6 +47,7 @@ from .const import (
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
CODEOWNERS = ["@kuba2k2"]
|
||||
AUTO_LOAD = ["preferences"]
|
||||
IS_TARGET_PLATFORM = True
|
||||
|
||||
|
||||
def _detect_variant(value):
|
||||
|
@ -186,6 +186,8 @@ CONFIG_SCHEMA = cv.All(
|
||||
esp32_s3_idf=USB_SERIAL_JTAG,
|
||||
esp32_c3_arduino=USB_CDC,
|
||||
esp32_c3_idf=USB_SERIAL_JTAG,
|
||||
esp32_c6_arduino=USB_CDC,
|
||||
esp32_c6_idf=USB_SERIAL_JTAG,
|
||||
rp2040=USB_CDC,
|
||||
bk72xx=DEFAULT,
|
||||
rtl87xx=DEFAULT,
|
||||
|
@ -72,9 +72,9 @@ void MQTTClimateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCo
|
||||
// max_temp
|
||||
root[MQTT_MAX_TEMP] = traits.get_visual_max_temperature();
|
||||
// target_temp_step
|
||||
root[MQTT_TARGET_TEMPERATURE_STEP] = traits.get_visual_target_temperature_step();
|
||||
root[MQTT_TARGET_TEMPERATURE_STEP] = roundf(traits.get_visual_target_temperature_step() * 10) * 0.1;
|
||||
// current_temp_step
|
||||
root[MQTT_CURRENT_TEMPERATURE_STEP] = traits.get_visual_current_temperature_step();
|
||||
root[MQTT_CURRENT_TEMPERATURE_STEP] = roundf(traits.get_visual_current_temperature_step() * 10) * 0.1;
|
||||
// temperature units are always coerced to Celsius internally
|
||||
root[MQTT_TEMPERATURE_UNIT] = "C";
|
||||
|
||||
|
@ -52,6 +52,14 @@ class Format:
|
||||
pass
|
||||
|
||||
|
||||
class BMPFormat(Format):
|
||||
def __init__(self):
|
||||
super().__init__("BMP")
|
||||
|
||||
def actions(self):
|
||||
cg.add_define("USE_ONLINE_IMAGE_BMP_SUPPORT")
|
||||
|
||||
|
||||
class PNGFormat(Format):
|
||||
def __init__(self):
|
||||
super().__init__("PNG")
|
||||
@ -62,7 +70,13 @@ class PNGFormat(Format):
|
||||
|
||||
|
||||
# New formats can be added here.
|
||||
IMAGE_FORMATS = {x.image_type: x for x in (PNGFormat(),)}
|
||||
IMAGE_FORMATS = {
|
||||
x.image_type: x
|
||||
for x in (
|
||||
BMPFormat(),
|
||||
PNGFormat(),
|
||||
)
|
||||
}
|
||||
|
||||
OnlineImage = online_image_ns.class_("OnlineImage", cg.PollingComponent, Image_)
|
||||
|
||||
|
101
esphome/components/online_image/bmp_image.cpp
Normal file
101
esphome/components/online_image/bmp_image.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
#include "bmp_image.h"
|
||||
|
||||
#ifdef USE_ONLINE_IMAGE_BMP_SUPPORT
|
||||
|
||||
#include "esphome/components/display/display.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace online_image {
|
||||
|
||||
static const char *const TAG = "online_image.bmp";
|
||||
|
||||
int HOT BmpDecoder::decode(uint8_t *buffer, size_t size) {
|
||||
size_t index = 0;
|
||||
if (this->current_index_ == 0 && index == 0 && size > 14) {
|
||||
/**
|
||||
* BMP file format:
|
||||
* 0-1: Signature (BM)
|
||||
* 2-5: File size
|
||||
* 6-9: Reserved
|
||||
* 10-13: Pixel data offset
|
||||
*
|
||||
* Integer values are stored in little-endian format.
|
||||
*/
|
||||
|
||||
// Check if the file is a BMP image
|
||||
if (buffer[0] != 'B' || buffer[1] != 'M') {
|
||||
ESP_LOGE(TAG, "Not a BMP file");
|
||||
return DECODE_ERROR_INVALID_TYPE;
|
||||
}
|
||||
|
||||
this->download_size_ = encode_uint32(buffer[5], buffer[4], buffer[3], buffer[2]);
|
||||
this->data_offset_ = encode_uint32(buffer[13], buffer[12], buffer[11], buffer[10]);
|
||||
|
||||
this->current_index_ = 14;
|
||||
index = 14;
|
||||
}
|
||||
if (this->current_index_ == 14 && index == 14 && size > this->data_offset_) {
|
||||
/**
|
||||
* BMP DIB header:
|
||||
* 14-17: DIB header size
|
||||
* 18-21: Image width
|
||||
* 22-25: Image height
|
||||
* 26-27: Number of color planes
|
||||
* 28-29: Bits per pixel
|
||||
* 30-33: Compression method
|
||||
* 34-37: Image data size
|
||||
* 38-41: Horizontal resolution
|
||||
* 42-45: Vertical resolution
|
||||
* 46-49: Number of colors in the color table
|
||||
*/
|
||||
|
||||
this->width_ = encode_uint32(buffer[21], buffer[20], buffer[19], buffer[18]);
|
||||
this->height_ = encode_uint32(buffer[25], buffer[24], buffer[23], buffer[22]);
|
||||
this->bits_per_pixel_ = encode_uint16(buffer[29], buffer[28]);
|
||||
this->compression_method_ = encode_uint32(buffer[33], buffer[32], buffer[31], buffer[30]);
|
||||
this->image_data_size_ = encode_uint32(buffer[37], buffer[36], buffer[35], buffer[34]);
|
||||
this->color_table_entries_ = encode_uint32(buffer[49], buffer[48], buffer[47], buffer[46]);
|
||||
|
||||
switch (this->bits_per_pixel_) {
|
||||
case 1:
|
||||
this->width_bytes_ = (this->width_ % 8 == 0) ? (this->width_ / 8) : (this->width_ / 8 + 1);
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(TAG, "Unsupported bits per pixel: %d", this->bits_per_pixel_);
|
||||
return DECODE_ERROR_UNSUPPORTED_FORMAT;
|
||||
}
|
||||
|
||||
if (this->compression_method_ != 0) {
|
||||
ESP_LOGE(TAG, "Unsupported compression method: %d", this->compression_method_);
|
||||
return DECODE_ERROR_UNSUPPORTED_FORMAT;
|
||||
}
|
||||
|
||||
if (!this->set_size(this->width_, this->height_)) {
|
||||
return DECODE_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
this->current_index_ = this->data_offset_;
|
||||
index = this->data_offset_;
|
||||
}
|
||||
while (index < size) {
|
||||
size_t paint_index = this->current_index_ - this->data_offset_;
|
||||
|
||||
uint8_t current_byte = buffer[index];
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
size_t x = (paint_index * 8) % this->width_ + i;
|
||||
size_t y = (this->height_ - 1) - (paint_index / this->width_bytes_);
|
||||
Color c = (current_byte & (1 << (7 - i))) ? display::COLOR_ON : display::COLOR_OFF;
|
||||
this->draw(x, y, 1, 1, c);
|
||||
}
|
||||
this->current_index_++;
|
||||
index++;
|
||||
}
|
||||
this->decoded_bytes_ += size;
|
||||
return size;
|
||||
};
|
||||
|
||||
} // namespace online_image
|
||||
} // namespace esphome
|
||||
|
||||
#endif // USE_ONLINE_IMAGE_BMP_SUPPORT
|
40
esphome/components/online_image/bmp_image.h
Normal file
40
esphome/components/online_image/bmp_image.h
Normal file
@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/defines.h"
|
||||
#ifdef USE_ONLINE_IMAGE_BMP_SUPPORT
|
||||
|
||||
#include "image_decoder.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace online_image {
|
||||
|
||||
/**
|
||||
* @brief Image decoder specialization for PNG images.
|
||||
*/
|
||||
class BmpDecoder : public ImageDecoder {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new BMP Decoder object.
|
||||
*
|
||||
* @param display The image to decode the stream into.
|
||||
*/
|
||||
BmpDecoder(OnlineImage *image) : ImageDecoder(image) {}
|
||||
|
||||
int HOT decode(uint8_t *buffer, size_t size) override;
|
||||
|
||||
protected:
|
||||
size_t current_index_{0};
|
||||
ssize_t width_{0};
|
||||
ssize_t height_{0};
|
||||
uint16_t bits_per_pixel_{0};
|
||||
uint32_t compression_method_{0};
|
||||
uint32_t image_data_size_{0};
|
||||
uint32_t color_table_entries_{0};
|
||||
size_t width_bytes_{0};
|
||||
size_t data_offset_{0};
|
||||
};
|
||||
|
||||
} // namespace online_image
|
||||
} // namespace esphome
|
||||
|
||||
#endif // USE_ONLINE_IMAGE_BMP_SUPPORT
|
@ -8,10 +8,11 @@ namespace online_image {
|
||||
|
||||
static const char *const TAG = "online_image.decoder";
|
||||
|
||||
void ImageDecoder::set_size(int width, int height) {
|
||||
this->image_->resize_(width, height);
|
||||
bool ImageDecoder::set_size(int width, int height) {
|
||||
bool resized = this->image_->resize_(width, height);
|
||||
this->x_scale_ = static_cast<double>(this->image_->buffer_width_) / width;
|
||||
this->y_scale_ = static_cast<double>(this->image_->buffer_height_) / height;
|
||||
return resized;
|
||||
}
|
||||
|
||||
void ImageDecoder::draw(int x, int y, int w, int h, const Color &color) {
|
||||
|
@ -4,6 +4,12 @@
|
||||
namespace esphome {
|
||||
namespace online_image {
|
||||
|
||||
enum DecodeError : int {
|
||||
DECODE_ERROR_INVALID_TYPE = -1,
|
||||
DECODE_ERROR_UNSUPPORTED_FORMAT = -2,
|
||||
DECODE_ERROR_OUT_OF_MEMORY = -3,
|
||||
};
|
||||
|
||||
class OnlineImage;
|
||||
|
||||
/**
|
||||
@ -24,7 +30,7 @@ class ImageDecoder {
|
||||
*
|
||||
* @param download_size The total number of bytes that need to be downloaded for the image.
|
||||
*/
|
||||
virtual void prepare(uint32_t download_size) { this->download_size_ = download_size; }
|
||||
virtual void prepare(size_t download_size) { this->download_size_ = download_size; }
|
||||
|
||||
/**
|
||||
* @brief Decode a part of the image. It will try reading from the buffer.
|
||||
@ -45,8 +51,9 @@ class ImageDecoder {
|
||||
*
|
||||
* @param width The image's width.
|
||||
* @param height The image's height.
|
||||
* @return true if the image was resized, false otherwise.
|
||||
*/
|
||||
void set_size(int width, int height);
|
||||
bool set_size(int width, int height);
|
||||
|
||||
/**
|
||||
* @brief Fill a rectangle on the display_buffer using the defined color.
|
||||
@ -68,8 +75,8 @@ class ImageDecoder {
|
||||
OnlineImage *image_;
|
||||
// Initializing to 1, to ensure it is distinguishable from initial "decoded_bytes_".
|
||||
// Will be overwritten anyway once the download size is known.
|
||||
uint32_t download_size_ = 1;
|
||||
uint32_t decoded_bytes_ = 0;
|
||||
size_t download_size_ = 1;
|
||||
size_t decoded_bytes_ = 0;
|
||||
double x_scale_ = 1.0;
|
||||
double y_scale_ = 1.0;
|
||||
};
|
||||
|
@ -6,6 +6,9 @@ static const char *const TAG = "online_image";
|
||||
|
||||
#include "image_decoder.h"
|
||||
|
||||
#ifdef USE_ONLINE_IMAGE_BMP_SUPPORT
|
||||
#include "bmp_image.h"
|
||||
#endif
|
||||
#ifdef USE_ONLINE_IMAGE_PNG_SUPPORT
|
||||
#include "png_image.h"
|
||||
#endif
|
||||
@ -118,9 +121,14 @@ void OnlineImage::update() {
|
||||
ESP_LOGD(TAG, "Starting download");
|
||||
size_t total_size = this->downloader_->content_length;
|
||||
|
||||
#ifdef USE_ONLINE_IMAGE_BMP_SUPPORT
|
||||
if (this->format_ == ImageFormat::BMP) {
|
||||
this->decoder_ = make_unique<BmpDecoder>(this);
|
||||
}
|
||||
#endif // ONLINE_IMAGE_BMP_SUPPORT
|
||||
#ifdef USE_ONLINE_IMAGE_PNG_SUPPORT
|
||||
if (this->format_ == ImageFormat::PNG) {
|
||||
this->decoder_ = esphome::make_unique<PngDecoder>(this);
|
||||
this->decoder_ = make_unique<PngDecoder>(this);
|
||||
}
|
||||
#endif // ONLINE_IMAGE_PNG_SUPPORT
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/components/http_request/http_request.h"
|
||||
#include "esphome/components/image/image.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/defines.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/components/http_request/http_request.h"
|
||||
#include "esphome/components/image/image.h"
|
||||
|
||||
#include "image_decoder.h"
|
||||
|
||||
@ -27,6 +27,8 @@ enum ImageFormat {
|
||||
JPEG,
|
||||
/** PNG format. */
|
||||
PNG,
|
||||
/** BMP format. */
|
||||
BMP,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -146,7 +148,7 @@ class OnlineImage : public PollingComponent,
|
||||
*/
|
||||
int buffer_height_;
|
||||
|
||||
friend void ImageDecoder::set_size(int width, int height);
|
||||
friend bool ImageDecoder::set_size(int width, int height);
|
||||
friend void ImageDecoder::draw(int x, int y, int w, int h, const Color &color);
|
||||
};
|
||||
|
||||
|
@ -41,7 +41,7 @@ static void draw_callback(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, ui
|
||||
decoder->draw(x, y, w, h, color);
|
||||
}
|
||||
|
||||
void PngDecoder::prepare(uint32_t download_size) {
|
||||
void PngDecoder::prepare(size_t download_size) {
|
||||
ImageDecoder::prepare(download_size);
|
||||
pngle_set_user_data(this->pngle_, this);
|
||||
pngle_set_init_callback(this->pngle_, init_callback);
|
||||
@ -51,7 +51,7 @@ void PngDecoder::prepare(uint32_t download_size) {
|
||||
int HOT PngDecoder::decode(uint8_t *buffer, size_t size) {
|
||||
if (!this->pngle_) {
|
||||
ESP_LOGE(TAG, "PNG decoder engine not initialized!");
|
||||
return -1;
|
||||
return DECODE_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
if (size < 256 && size < this->download_size_ - this->decoded_bytes_) {
|
||||
ESP_LOGD(TAG, "Waiting for data");
|
||||
|
@ -21,7 +21,7 @@ class PngDecoder : public ImageDecoder {
|
||||
PngDecoder(OnlineImage *image) : ImageDecoder(image), pngle_(pngle_new()) {}
|
||||
~PngDecoder() override { pngle_destroy(this->pngle_); }
|
||||
|
||||
void prepare(uint32_t download_size) override;
|
||||
void prepare(size_t download_size) override;
|
||||
int HOT decode(uint8_t *buffer, size_t size) override;
|
||||
|
||||
protected:
|
||||
|
@ -75,6 +75,8 @@ void PulseMeterSensor::loop() {
|
||||
case MeterState::RUNNING: {
|
||||
uint32_t delta_us = this->get_->last_detected_edge_us_ - this->last_processed_edge_us_;
|
||||
float pulse_width_us = delta_us / float(this->get_->count_);
|
||||
ESP_LOGV(TAG, "New pulse, delta: %" PRIu32 " µs, count: %" PRIu32 ", width: %.5f µs", delta_us,
|
||||
this->get_->count_, pulse_width_us);
|
||||
this->publish_state((60.0f * 1000000.0f) / pulse_width_us);
|
||||
} break;
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ from .gpio import rp2040_pin_to_code # noqa
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
CODEOWNERS = ["@jesserockz"]
|
||||
AUTO_LOAD = ["preferences"]
|
||||
IS_TARGET_PLATFORM = True
|
||||
|
||||
|
||||
def set_core_data(config):
|
||||
|
@ -19,6 +19,8 @@ from .boards import RTL87XX_BOARD_PINS, RTL87XX_BOARDS
|
||||
|
||||
CODEOWNERS = ["@kuba2k2"]
|
||||
AUTO_LOAD = ["libretiny"]
|
||||
IS_TARGET_PLATFORM = True
|
||||
|
||||
|
||||
COMPONENT_DATA = LibreTinyComponent(
|
||||
name=COMPONENT_RTL87XX,
|
||||
|
25
esphome/components/seeed_mr60bha2/binary_sensor.py
Normal file
25
esphome/components/seeed_mr60bha2/binary_sensor.py
Normal file
@ -0,0 +1,25 @@
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import binary_sensor
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
DEVICE_CLASS_OCCUPANCY,
|
||||
CONF_HAS_TARGET,
|
||||
)
|
||||
from . import CONF_MR60BHA2_ID, MR60BHA2Component
|
||||
|
||||
DEPENDENCIES = ["seeed_mr60bha2"]
|
||||
|
||||
CONFIG_SCHEMA = {
|
||||
cv.GenerateID(CONF_MR60BHA2_ID): cv.use_id(MR60BHA2Component),
|
||||
cv.Optional(CONF_HAS_TARGET): binary_sensor.binary_sensor_schema(
|
||||
device_class=DEVICE_CLASS_OCCUPANCY, icon="mdi:motion-sensor"
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
mr60bha2_component = await cg.get_variable(config[CONF_MR60BHA2_ID])
|
||||
|
||||
if has_target_config := config.get(CONF_HAS_TARGET):
|
||||
sens = await binary_sensor.new_binary_sensor(has_target_config)
|
||||
cg.add(mr60bha2_component.set_has_target_binary_sensor(sens))
|
@ -1,6 +1,7 @@
|
||||
#include "seeed_mr60bha2.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
#include <cinttypes>
|
||||
#include <utility>
|
||||
|
||||
namespace esphome {
|
||||
@ -12,10 +13,14 @@ static const char *const TAG = "seeed_mr60bha2";
|
||||
// items in an easy-to-read format, including the configuration key-value pairs.
|
||||
void MR60BHA2Component::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "MR60BHA2:");
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
LOG_BINARY_SENSOR(" ", "People Exist Binary Sensor", this->has_target_binary_sensor_);
|
||||
#endif
|
||||
#ifdef USE_SENSOR
|
||||
LOG_SENSOR(" ", "Breath Rate Sensor", this->breath_rate_sensor_);
|
||||
LOG_SENSOR(" ", "Heart Rate Sensor", this->heart_rate_sensor_);
|
||||
LOG_SENSOR(" ", "Distance Sensor", this->distance_sensor_);
|
||||
LOG_SENSOR(" ", "Target Number Sensor", this->num_targets_sensor_);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -94,7 +99,8 @@ bool MR60BHA2Component::validate_message_() {
|
||||
uint16_t frame_type = encode_uint16(data[5], data[6]);
|
||||
|
||||
if (frame_type != BREATH_RATE_TYPE_BUFFER && frame_type != HEART_RATE_TYPE_BUFFER &&
|
||||
frame_type != DISTANCE_TYPE_BUFFER) {
|
||||
frame_type != DISTANCE_TYPE_BUFFER && frame_type != PEOPLE_EXIST_TYPE_BUFFER &&
|
||||
frame_type != PRINT_CLOUD_BUFFER) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -144,6 +150,18 @@ void MR60BHA2Component::process_frame_(uint16_t frame_id, uint16_t frame_type, c
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PEOPLE_EXIST_TYPE_BUFFER:
|
||||
if (this->has_target_binary_sensor_ != nullptr && length >= 2) {
|
||||
uint16_t has_target_int = encode_uint16(data[1], data[0]);
|
||||
this->has_target_binary_sensor_->publish_state(has_target_int);
|
||||
if (has_target_int == 0) {
|
||||
this->breath_rate_sensor_->publish_state(0.0);
|
||||
this->heart_rate_sensor_->publish_state(0.0);
|
||||
this->distance_sensor_->publish_state(0.0);
|
||||
this->num_targets_sensor_->publish_state(0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case HEART_RATE_TYPE_BUFFER:
|
||||
if (this->heart_rate_sensor_ != nullptr && length >= 4) {
|
||||
uint32_t current_heart_rate_int = encode_uint32(data[3], data[2], data[1], data[0]);
|
||||
@ -155,7 +173,7 @@ void MR60BHA2Component::process_frame_(uint16_t frame_id, uint16_t frame_type, c
|
||||
}
|
||||
break;
|
||||
case DISTANCE_TYPE_BUFFER:
|
||||
if (!data[0]) {
|
||||
if (data[0] != 0) {
|
||||
if (this->distance_sensor_ != nullptr && length >= 8) {
|
||||
uint32_t current_distance_int = encode_uint32(data[7], data[6], data[5], data[4]);
|
||||
float distance_float;
|
||||
@ -164,6 +182,12 @@ void MR60BHA2Component::process_frame_(uint16_t frame_id, uint16_t frame_type, c
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PRINT_CLOUD_BUFFER:
|
||||
if (this->num_targets_sensor_ != nullptr && length >= 4) {
|
||||
uint32_t current_num_targets_int = encode_uint32(data[3], data[2], data[1], data[0]);
|
||||
this->num_targets_sensor_->publish_state(current_num_targets_int);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
#pragma once
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/defines.h"
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
#include "esphome/components/binary_sensor/binary_sensor.h"
|
||||
#endif
|
||||
#ifdef USE_SENSOR
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#endif
|
||||
@ -12,37 +15,23 @@
|
||||
|
||||
namespace esphome {
|
||||
namespace seeed_mr60bha2 {
|
||||
|
||||
static const uint8_t DATA_BUF_MAX_SIZE = 12;
|
||||
static const uint8_t FRAME_BUF_MAX_SIZE = 21;
|
||||
static const uint8_t LEN_TO_HEAD_CKSUM = 8;
|
||||
static const uint8_t LEN_TO_DATA_FRAME = 9;
|
||||
|
||||
static const uint8_t FRAME_HEADER_BUFFER = 0x01;
|
||||
static const uint16_t BREATH_RATE_TYPE_BUFFER = 0x0A14;
|
||||
static const uint16_t PEOPLE_EXIST_TYPE_BUFFER = 0x0F09;
|
||||
static const uint16_t HEART_RATE_TYPE_BUFFER = 0x0A15;
|
||||
static const uint16_t DISTANCE_TYPE_BUFFER = 0x0A16;
|
||||
|
||||
enum FrameLocation {
|
||||
LOCATE_FRAME_HEADER,
|
||||
LOCATE_ID_FRAME1,
|
||||
LOCATE_ID_FRAME2,
|
||||
LOCATE_LENGTH_FRAME_H,
|
||||
LOCATE_LENGTH_FRAME_L,
|
||||
LOCATE_TYPE_FRAME1,
|
||||
LOCATE_TYPE_FRAME2,
|
||||
LOCATE_HEAD_CKSUM_FRAME, // Header checksum: [from the first byte to the previous byte of the HEAD_CKSUM bit]
|
||||
LOCATE_DATA_FRAME,
|
||||
LOCATE_DATA_CKSUM_FRAME, // Data checksum: [from the first to the previous byte of the DATA_CKSUM bit]
|
||||
LOCATE_PROCESS_FRAME,
|
||||
};
|
||||
static const uint16_t PRINT_CLOUD_BUFFER = 0x0A04;
|
||||
|
||||
class MR60BHA2Component : public Component,
|
||||
public uart::UARTDevice { // The class name must be the name defined by text_sensor.py
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
SUB_BINARY_SENSOR(has_target);
|
||||
#endif
|
||||
#ifdef USE_SENSOR
|
||||
SUB_SENSOR(breath_rate);
|
||||
SUB_SENSOR(heart_rate);
|
||||
SUB_SENSOR(distance);
|
||||
SUB_SENSOR(num_targets);
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
@ -7,6 +7,7 @@ from esphome.const import (
|
||||
ICON_HEART_PULSE,
|
||||
ICON_PULSE,
|
||||
ICON_SIGNAL,
|
||||
ICON_COUNTER,
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
UNIT_BEATS_PER_MINUTE,
|
||||
UNIT_CENTIMETER,
|
||||
@ -18,12 +19,13 @@ DEPENDENCIES = ["seeed_mr60bha2"]
|
||||
|
||||
CONF_BREATH_RATE = "breath_rate"
|
||||
CONF_HEART_RATE = "heart_rate"
|
||||
CONF_NUM_TARGETS = "num_targets"
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(CONF_MR60BHA2_ID): cv.use_id(MR60BHA2Component),
|
||||
cv.Optional(CONF_BREATH_RATE): sensor.sensor_schema(
|
||||
accuracy_decimals=2,
|
||||
accuracy_decimals=0,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
icon=ICON_PULSE,
|
||||
),
|
||||
@ -40,6 +42,9 @@ CONFIG_SCHEMA = cv.Schema(
|
||||
accuracy_decimals=2,
|
||||
icon=ICON_SIGNAL,
|
||||
),
|
||||
cv.Optional(CONF_NUM_TARGETS): sensor.sensor_schema(
|
||||
icon=ICON_COUNTER,
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
@ -55,3 +60,6 @@ async def to_code(config):
|
||||
if distance_config := config.get(CONF_DISTANCE):
|
||||
sens = await sensor.new_sensor(distance_config)
|
||||
cg.add(mr60bha2_component.set_distance_sensor(sens))
|
||||
if num_targets_config := config.get(CONF_NUM_TARGETS):
|
||||
sens = await sensor.new_sensor(num_targets_config)
|
||||
cg.add(mr60bha2_component.set_num_targets_sensor(sens))
|
||||
|
@ -88,7 +88,7 @@ void SPIDelegateBitBash::write(uint16_t data, size_t num_bits) { this->transfer_
|
||||
uint16_t SPIDelegateBitBash::transfer_(uint16_t data, size_t num_bits) {
|
||||
// Clock starts out at idle level
|
||||
this->clk_pin_->digital_write(clock_polarity_);
|
||||
uint8_t out_data = 0;
|
||||
uint16_t out_data = 0;
|
||||
|
||||
for (uint8_t i = 0; i != num_bits; i++) {
|
||||
uint8_t shift;
|
||||
|
@ -22,7 +22,6 @@ from esphome.const import (
|
||||
CONF_PACKAGES,
|
||||
CONF_PLATFORM,
|
||||
CONF_SUBSTITUTIONS,
|
||||
TARGET_PLATFORMS,
|
||||
)
|
||||
from esphome.core import CORE, DocumentRange, EsphomeError
|
||||
import esphome.core.config as core_config
|
||||
@ -833,7 +832,7 @@ def validate_config(
|
||||
result[CONF_ESPHOME] = config[CONF_ESPHOME]
|
||||
result.add_output_path([CONF_ESPHOME], CONF_ESPHOME)
|
||||
try:
|
||||
core_config.preload_core_config(config, result)
|
||||
target_platform = core_config.preload_core_config(config, result)
|
||||
except vol.Invalid as err:
|
||||
result.add_error(err)
|
||||
return result
|
||||
@ -845,9 +844,9 @@ def validate_config(
|
||||
cv.All(cv.version_number, cv.validate_esphome_version)(min_version)
|
||||
|
||||
# First run platform validation steps
|
||||
for key in TARGET_PLATFORMS:
|
||||
if key in config:
|
||||
result.add_validation_step(LoadValidationStep(key, config[key]))
|
||||
result.add_validation_step(
|
||||
LoadValidationStep(target_platform, config[target_platform])
|
||||
)
|
||||
result.run_validation_steps()
|
||||
|
||||
if result.errors:
|
||||
|
@ -15,15 +15,6 @@ PLATFORM_LIBRETINY_OLDSTYLE = "libretiny"
|
||||
PLATFORM_RP2040 = "rp2040"
|
||||
PLATFORM_RTL87XX = "rtl87xx"
|
||||
|
||||
TARGET_PLATFORMS = [
|
||||
PLATFORM_BK72XX,
|
||||
PLATFORM_ESP32,
|
||||
PLATFORM_ESP8266,
|
||||
PLATFORM_HOST,
|
||||
PLATFORM_LIBRETINY_OLDSTYLE,
|
||||
PLATFORM_RP2040,
|
||||
PLATFORM_RTL87XX,
|
||||
]
|
||||
|
||||
SOURCE_FILE_EXTENSIONS = {".cpp", ".hpp", ".h", ".c", ".tcc", ".ino"}
|
||||
HEADER_FILE_EXTENSIONS = {".h", ".hpp", ".tcc"}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import logging
|
||||
import multiprocessing
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from esphome import automation
|
||||
import esphome.codegen as cg
|
||||
@ -28,7 +29,6 @@ from esphome.const import (
|
||||
CONF_TRIGGER_ID,
|
||||
CONF_VERSION,
|
||||
KEY_CORE,
|
||||
TARGET_PLATFORMS,
|
||||
__version__ as ESPHOME_VERSION,
|
||||
)
|
||||
from esphome.core import CORE, coroutine_with_priority
|
||||
@ -174,7 +174,31 @@ PRELOAD_CONFIG_SCHEMA = cv.Schema(
|
||||
)
|
||||
|
||||
|
||||
def preload_core_config(config, result):
|
||||
def _is_target_platform(name):
|
||||
from esphome.loader import get_component
|
||||
|
||||
try:
|
||||
if get_component(name, True).is_target_platform:
|
||||
return True
|
||||
except KeyError:
|
||||
pass
|
||||
return False
|
||||
|
||||
|
||||
def _list_target_platforms():
|
||||
target_platforms = []
|
||||
root = Path(__file__).parents[1]
|
||||
for path in (root / "components").iterdir():
|
||||
if not path.is_dir():
|
||||
continue
|
||||
if not (path / "__init__.py").is_file():
|
||||
continue
|
||||
if _is_target_platform(path.name):
|
||||
target_platforms += [path.name]
|
||||
return target_platforms
|
||||
|
||||
|
||||
def preload_core_config(config, result) -> str:
|
||||
with cv.prepend_path(CONF_ESPHOME):
|
||||
conf = PRELOAD_CONFIG_SCHEMA(config[CONF_ESPHOME])
|
||||
|
||||
@ -187,12 +211,16 @@ def preload_core_config(config, result):
|
||||
conf[CONF_BUILD_PATH] = os.path.join(build_path, CORE.name)
|
||||
CORE.build_path = CORE.relative_internal_path(conf[CONF_BUILD_PATH])
|
||||
|
||||
target_platforms = [key for key in TARGET_PLATFORMS if key in config]
|
||||
target_platforms = []
|
||||
|
||||
for domain, _ in config.items():
|
||||
if _is_target_platform(domain):
|
||||
target_platforms += [domain]
|
||||
|
||||
if not target_platforms:
|
||||
raise cv.Invalid(
|
||||
"Platform missing. You must include one of the available platform keys: "
|
||||
+ ", ".join(TARGET_PLATFORMS),
|
||||
+ ", ".join(_list_target_platforms()),
|
||||
[CONF_ESPHOME],
|
||||
)
|
||||
if len(target_platforms) > 1:
|
||||
@ -202,6 +230,7 @@ def preload_core_config(config, result):
|
||||
)
|
||||
|
||||
config[CONF_ESPHOME] = conf
|
||||
return target_platforms[0]
|
||||
|
||||
|
||||
def include_file(path, basename):
|
||||
|
@ -60,6 +60,7 @@
|
||||
#define USE_NETWORK
|
||||
#define USE_NEXTION_TFT_UPLOAD
|
||||
#define USE_NUMBER
|
||||
#define USE_ONLINE_IMAGE_BMP_SUPPORT
|
||||
#define USE_ONLINE_IMAGE_PNG_SUPPORT
|
||||
#define USE_OTA
|
||||
#define USE_OTA_PASSWORD
|
||||
|
@ -52,6 +52,10 @@ class ComponentManifest:
|
||||
def is_platform_component(self) -> bool:
|
||||
return getattr(self.module, "IS_PLATFORM_COMPONENT", False)
|
||||
|
||||
@property
|
||||
def is_target_platform(self) -> bool:
|
||||
return getattr(self.module, "IS_TARGET_PLATFORM", False)
|
||||
|
||||
@property
|
||||
def config_schema(self) -> Optional[Any]:
|
||||
return getattr(self.module, "CONFIG_SCHEMA", None)
|
||||
@ -169,13 +173,15 @@ def install_custom_components_meta_finder():
|
||||
install_meta_finder(custom_components_dir)
|
||||
|
||||
|
||||
def _lookup_module(domain):
|
||||
def _lookup_module(domain, exception):
|
||||
if domain in _COMPONENT_CACHE:
|
||||
return _COMPONENT_CACHE[domain]
|
||||
|
||||
try:
|
||||
module = importlib.import_module(f"esphome.components.{domain}")
|
||||
except ImportError as e:
|
||||
if exception:
|
||||
raise
|
||||
if "No module named" in str(e):
|
||||
_LOGGER.info(
|
||||
"Unable to import component %s: %s", domain, str(e), exc_info=False
|
||||
@ -184,6 +190,8 @@ def _lookup_module(domain):
|
||||
_LOGGER.error("Unable to import component %s:", domain, exc_info=True)
|
||||
return None
|
||||
except Exception: # pylint: disable=broad-except
|
||||
if exception:
|
||||
raise
|
||||
_LOGGER.error("Unable to load component %s:", domain, exc_info=True)
|
||||
return None
|
||||
|
||||
@ -192,14 +200,14 @@ def _lookup_module(domain):
|
||||
return manif
|
||||
|
||||
|
||||
def get_component(domain):
|
||||
def get_component(domain, exception=False):
|
||||
assert "." not in domain
|
||||
return _lookup_module(domain)
|
||||
return _lookup_module(domain, exception)
|
||||
|
||||
|
||||
def get_platform(domain, platform):
|
||||
full = f"{platform}.{domain}"
|
||||
return _lookup_module(full)
|
||||
return _lookup_module(full, False)
|
||||
|
||||
|
||||
_COMPONENT_CACHE = {}
|
||||
|
@ -10,4 +10,5 @@ sensor:
|
||||
- platform: ads1115
|
||||
multiplexer: A0_A1
|
||||
gain: 1.024
|
||||
sample_rate: 128
|
||||
id: ads1115_sensor
|
||||
|
@ -10,4 +10,5 @@ sensor:
|
||||
- platform: ads1115
|
||||
multiplexer: A0_A1
|
||||
gain: 1.024
|
||||
sample_rate: 128
|
||||
id: ads1115_sensor
|
||||
|
@ -10,4 +10,5 @@ sensor:
|
||||
- platform: ads1115
|
||||
multiplexer: A0_A1
|
||||
gain: 1.024
|
||||
sample_rate: 128
|
||||
id: ads1115_sensor
|
||||
|
@ -10,4 +10,5 @@ sensor:
|
||||
- platform: ads1115
|
||||
multiplexer: A0_A1
|
||||
gain: 1.024
|
||||
sample_rate: 128
|
||||
id: ads1115_sensor
|
||||
|
@ -10,4 +10,5 @@ sensor:
|
||||
- platform: ads1115
|
||||
multiplexer: A0_A1
|
||||
gain: 1.024
|
||||
sample_rate: 128
|
||||
id: ads1115_sensor
|
||||
|
@ -10,4 +10,5 @@ sensor:
|
||||
- platform: ads1115
|
||||
multiplexer: A0_A1
|
||||
gain: 1.024
|
||||
sample_rate: 128
|
||||
id: ads1115_sensor
|
||||
|
14
tests/components/es7243e/common.yaml
Normal file
14
tests/components/es7243e/common.yaml
Normal file
@ -0,0 +1,14 @@
|
||||
esphome:
|
||||
on_boot:
|
||||
then:
|
||||
- audio_adc.set_mic_gain: 0db
|
||||
- audio_adc.set_mic_gain: !lambda 'return 4;'
|
||||
|
||||
i2c:
|
||||
- id: i2c_es7243e
|
||||
scl: ${scl_pin}
|
||||
sda: ${sda_pin}
|
||||
|
||||
audio_adc:
|
||||
- platform: es7243e
|
||||
id: es7243e_adc
|
5
tests/components/es7243e/test.esp32-ard.yaml
Normal file
5
tests/components/es7243e/test.esp32-ard.yaml
Normal file
@ -0,0 +1,5 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO16
|
||||
sda_pin: GPIO17
|
||||
|
||||
<<: !include common.yaml
|
5
tests/components/es7243e/test.esp32-c3-ard.yaml
Normal file
5
tests/components/es7243e/test.esp32-c3-ard.yaml
Normal file
@ -0,0 +1,5 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO5
|
||||
sda_pin: GPIO4
|
||||
|
||||
<<: !include common.yaml
|
5
tests/components/es7243e/test.esp32-c3-idf.yaml
Normal file
5
tests/components/es7243e/test.esp32-c3-idf.yaml
Normal file
@ -0,0 +1,5 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO5
|
||||
sda_pin: GPIO4
|
||||
|
||||
<<: !include common.yaml
|
5
tests/components/es7243e/test.esp32-idf.yaml
Normal file
5
tests/components/es7243e/test.esp32-idf.yaml
Normal file
@ -0,0 +1,5 @@
|
||||
substitutions:
|
||||
scl_pin: GPIO16
|
||||
sda_pin: GPIO17
|
||||
|
||||
<<: !include common.yaml
|
@ -26,6 +26,10 @@ online_image:
|
||||
format: PNG
|
||||
type: RGB
|
||||
transparency: chroma_key
|
||||
- id: online_binary_bmp
|
||||
url: https://samples-files.com/samples/images/bmp/480-360-sample.bmp
|
||||
format: BMP
|
||||
type: BINARY
|
||||
|
||||
# Check the set_url action
|
||||
esphome:
|
||||
|
@ -9,6 +9,11 @@ uart:
|
||||
seeed_mr60bha2:
|
||||
id: my_seeed_mr60bha2
|
||||
|
||||
binary_sensor:
|
||||
- platform: seeed_mr60bha2
|
||||
has_target:
|
||||
name: "Person Information"
|
||||
|
||||
sensor:
|
||||
- platform: seeed_mr60bha2
|
||||
breath_rate:
|
||||
@ -17,3 +22,5 @@ sensor:
|
||||
name: "Real-time heart rate"
|
||||
distance:
|
||||
name: "Distance to detection object"
|
||||
num_targets:
|
||||
name: "Target Number"
|
||||
|
Loading…
x
Reference in New Issue
Block a user