diff --git a/CODEOWNERS b/CODEOWNERS index 8632c91ff8..629aaeab40 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -86,7 +86,7 @@ esphome/components/cap1188/* @mreditor97 esphome/components/captive_portal/* @OttoWinter esphome/components/ccs811/* @habbie esphome/components/cd74hc4067/* @asoehlke -esphome/components/ch422g/* @jesterret +esphome/components/ch422g/* @clydebarrow @jesterret esphome/components/climate/* @esphome/core esphome/components/climate_ir/* @glmnet esphome/components/color_temperature/* @jesserockz @@ -153,6 +153,7 @@ esphome/components/ft63x6/* @gpambrozio esphome/components/gcja5/* @gcormier esphome/components/gdk101/* @Szewcson esphome/components/globals/* @esphome/core +esphome/components/gp2y1010au0f/* @zry98 esphome/components/gp8403/* @jesserockz esphome/components/gpio/* @esphome/core esphome/components/gpio/one_wire/* @ssieb diff --git a/esphome/components/bl0906/sensor.py b/esphome/components/bl0906/sensor.py index bc370c9252..42c6f06092 100644 --- a/esphome/components/bl0906/sensor.py +++ b/esphome/components/bl0906/sensor.py @@ -145,8 +145,9 @@ FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema( ), ) async def reset_energy_to_code(config, action_id, template_arg, args): - paren = await cg.get_variable(config[CONF_ID]) - return cg.new_Pvariable(action_id, template_arg, paren) + var = cg.new_Pvariable(action_id, template_arg) + await cg.register_parented(var, config[CONF_ID]) + return var async def to_code(config): diff --git a/esphome/components/ch422g/__init__.py b/esphome/components/ch422g/__init__.py index cf8b5f65d3..6a7bace0a2 100644 --- a/esphome/components/ch422g/__init__.py +++ b/esphome/components/ch422g/__init__.py @@ -1,18 +1,20 @@ from esphome import pins import esphome.codegen as cg from esphome.components import i2c +from esphome.components.i2c import I2CBus import esphome.config_validation as cv from esphome.const import ( + CONF_I2C_ID, CONF_ID, CONF_INPUT, CONF_INVERTED, CONF_MODE, CONF_NUMBER, + CONF_OPEN_DRAIN, CONF_OUTPUT, - CONF_RESTORE_VALUE, ) -CODEOWNERS = ["@jesterret"] +CODEOWNERS = ["@jesterret", "@clydebarrow"] DEPENDENCIES = ["i2c"] MULTI_CONF = True ch422g_ns = cg.esphome_ns.namespace("ch422g") @@ -23,29 +25,36 @@ CH422GGPIOPin = ch422g_ns.class_( ) CONF_CH422G = "ch422g" -CONFIG_SCHEMA = ( - cv.Schema( - { - cv.Required(CONF_ID): cv.declare_id(CH422GComponent), - cv.Optional(CONF_RESTORE_VALUE, default=False): cv.boolean, - } - ) - .extend(cv.COMPONENT_SCHEMA) - .extend(i2c.i2c_device_schema(0x24)) -) + +# Note that no address is configurable - each register in the CH422G has a dedicated i2c address +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_ID): cv.declare_id(CH422GComponent), + cv.GenerateID(CONF_I2C_ID): cv.use_id(I2CBus), + } +).extend(cv.COMPONENT_SCHEMA) async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) - cg.add(var.set_restore_value(config[CONF_RESTORE_VALUE])) await cg.register_component(var, config) - await i2c.register_i2c_device(var, config) + # Can't use register_i2c_device because there is no CONF_ADDRESS + parent = await cg.get_variable(config[CONF_I2C_ID]) + cg.add(var.set_i2c_bus(parent)) + + +# This is used as a final validation step so that modes have been fully transformed. +def pin_mode_check(pin_config, _): + if pin_config[CONF_MODE][CONF_INPUT] and pin_config[CONF_NUMBER] >= 8: + raise cv.Invalid("CH422G only supports input on pins 0-7") + if pin_config[CONF_MODE][CONF_OPEN_DRAIN] and pin_config[CONF_NUMBER] < 8: + raise cv.Invalid("CH422G only supports open drain output on pins 8-11") CH422G_PIN_SCHEMA = pins.gpio_base_schema( CH422GGPIOPin, - cv.int_range(min=0, max=7), - modes=[CONF_INPUT, CONF_OUTPUT], + cv.int_range(min=0, max=11), + modes=[CONF_INPUT, CONF_OUTPUT, CONF_OPEN_DRAIN], ).extend( { cv.Required(CONF_CH422G): cv.use_id(CH422GComponent), @@ -53,7 +62,7 @@ CH422G_PIN_SCHEMA = pins.gpio_base_schema( ) -@pins.PIN_SCHEMA_REGISTRY.register(CONF_CH422G, CH422G_PIN_SCHEMA) +@pins.PIN_SCHEMA_REGISTRY.register(CONF_CH422G, CH422G_PIN_SCHEMA, pin_mode_check) async def ch422g_pin_to_code(config): var = cg.new_Pvariable(config[CONF_ID]) parent = await cg.get_variable(config[CONF_CH422G]) diff --git a/esphome/components/ch422g/ch422g.cpp b/esphome/components/ch422g/ch422g.cpp index 25038991ed..0db179d99e 100644 --- a/esphome/components/ch422g/ch422g.cpp +++ b/esphome/components/ch422g/ch422g.cpp @@ -4,33 +4,33 @@ namespace esphome { namespace ch422g { -const uint8_t CH422G_REG_IN = 0x26; -const uint8_t CH422G_REG_OUT = 0x38; -const uint8_t OUT_REG_DEFAULT_VAL = 0xdf; +static const uint8_t CH422G_REG_MODE = 0x24; +static const uint8_t CH422G_MODE_OUTPUT = 0x01; // enables output mode on 0-7 +static const uint8_t CH422G_MODE_OPEN_DRAIN = 0x04; // enables open drain mode on 8-11 +static const uint8_t CH422G_REG_IN = 0x26; // read reg for input bits +static const uint8_t CH422G_REG_OUT = 0x38; // write reg for output bits 0-7 +static const uint8_t CH422G_REG_OUT_UPPER = 0x23; // write reg for output bits 8-11 static const char *const TAG = "ch422g"; void CH422GComponent::setup() { ESP_LOGCONFIG(TAG, "Setting up CH422G..."); - // Test to see if device exists - if (!this->read_inputs_()) { + // set outputs before mode + this->write_outputs_(); + // Set mode and check for errors + if (!this->set_mode_(this->mode_value_) || !this->read_inputs_()) { ESP_LOGE(TAG, "CH422G not detected at 0x%02X", this->address_); this->mark_failed(); return; } - // restore defaults over whatever got saved on last boot - if (!this->restore_value_) { - this->write_output_(OUT_REG_DEFAULT_VAL); - } - - ESP_LOGD(TAG, "Initialization complete. Warning: %d, Error: %d", this->status_has_warning(), - this->status_has_error()); + ESP_LOGCONFIG(TAG, "Initialization complete. Warning: %d, Error: %d", this->status_has_warning(), + this->status_has_error()); } void CH422GComponent::loop() { // Clear all the previously read flags. - this->pin_read_cache_ = 0x00; + this->pin_read_flags_ = 0x00; } void CH422GComponent::dump_config() { @@ -41,82 +41,99 @@ void CH422GComponent::dump_config() { } } -// ch422g doesn't have any flag support (needs docs?) -void CH422GComponent::pin_mode(uint8_t pin, gpio::Flags flags) {} +void CH422GComponent::pin_mode(uint8_t pin, gpio::Flags flags) { + if (pin < 8) { + if (flags & gpio::FLAG_OUTPUT) { + this->mode_value_ |= CH422G_MODE_OUTPUT; + } + } else { + if (flags & gpio::FLAG_OPEN_DRAIN) { + this->mode_value_ |= CH422G_MODE_OPEN_DRAIN; + } + } +} bool CH422GComponent::digital_read(uint8_t pin) { - if (this->pin_read_cache_ == 0 || this->pin_read_cache_ & (1 << pin)) { + if (this->pin_read_flags_ == 0 || this->pin_read_flags_ & (1 << pin)) { // Read values on first access or in case it's being read again in the same loop this->read_inputs_(); } - this->pin_read_cache_ |= (1 << pin); - return this->state_mask_ & (1 << pin); + this->pin_read_flags_ |= (1 << pin); + return (this->input_bits_ & (1 << pin)) != 0; } void CH422GComponent::digital_write(uint8_t pin, bool value) { if (value) { - this->write_output_(this->state_mask_ | (1 << pin)); + this->output_bits_ |= (1 << pin); } else { - this->write_output_(this->state_mask_ & ~(1 << pin)); + this->output_bits_ &= ~(1 << pin); } + this->write_outputs_(); } bool CH422GComponent::read_inputs_() { if (this->is_failed()) { return false; } - - uint8_t temp = 0; - if ((this->last_error_ = this->read(&temp, 1)) != esphome::i2c::ERROR_OK) { - this->status_set_warning(str_sprintf("read_inputs_(): I2C I/O error: %d", (int) this->last_error_).c_str()); - return false; + uint8_t result; + // reading inputs requires the chip to be in input mode, possibly temporarily. + if (this->mode_value_ & CH422G_MODE_OUTPUT) { + this->set_mode_(this->mode_value_ & ~CH422G_MODE_OUTPUT); + result = this->read_reg_(CH422G_REG_IN); + this->set_mode_(this->mode_value_); + } else { + result = this->read_reg_(CH422G_REG_IN); } - - uint8_t output = 0; - if ((this->last_error_ = this->bus_->read(CH422G_REG_IN, &output, 1)) != esphome::i2c::ERROR_OK) { - this->status_set_warning(str_sprintf("read_inputs_(): I2C I/O error: %d", (int) this->last_error_).c_str()); - return false; - } - - this->state_mask_ = output; + this->input_bits_ = result; this->status_clear_warning(); - return true; } -bool CH422GComponent::write_output_(uint8_t value) { - const uint8_t temp = 1; - if ((this->last_error_ = this->write(&temp, 1, false)) != esphome::i2c::ERROR_OK) { - this->status_set_warning(str_sprintf("write_output_(): I2C I/O error: %d", (int) this->last_error_).c_str()); +// Write a register. Can't use the standard write_byte() method because there is no single pre-configured i2c address. +bool CH422GComponent::write_reg_(uint8_t reg, uint8_t value) { + auto err = this->bus_->write(reg, &value, 1); + if (err != i2c::ERROR_OK) { + this->status_set_warning(str_sprintf("write failed for register 0x%X, error %d", reg, err).c_str()); return false; } - - uint8_t write_mask = value; - if ((this->last_error_ = this->bus_->write(CH422G_REG_OUT, &write_mask, 1)) != esphome::i2c::ERROR_OK) { - this->status_set_warning( - str_sprintf("write_output_(): I2C I/O error: %d for write_mask: %d", (int) this->last_error_, (int) write_mask) - .c_str()); - return false; - } - - this->state_mask_ = value; this->status_clear_warning(); return true; } +uint8_t CH422GComponent::read_reg_(uint8_t reg) { + uint8_t value; + auto err = this->bus_->read(reg, &value, 1); + if (err != i2c::ERROR_OK) { + this->status_set_warning(str_sprintf("read failed for register 0x%X, error %d", reg, err).c_str()); + return 0; + } + this->status_clear_warning(); + return value; +} + +bool CH422GComponent::set_mode_(uint8_t mode) { return this->write_reg_(CH422G_REG_MODE, mode); } + +bool CH422GComponent::write_outputs_() { + return this->write_reg_(CH422G_REG_OUT, static_cast(this->output_bits_)) && + this->write_reg_(CH422G_REG_OUT_UPPER, static_cast(this->output_bits_ >> 8)); +} + float CH422GComponent::get_setup_priority() const { return setup_priority::IO; } // Run our loop() method very early in the loop, so that we cache read values // before other components call our digital_read() method. float CH422GComponent::get_loop_priority() const { return 9.0f; } // Just after WIFI -void CH422GGPIOPin::setup() { pin_mode(flags_); } void CH422GGPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); } -bool CH422GGPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; } +bool CH422GGPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) ^ this->inverted_; } -void CH422GGPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); } +void CH422GGPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value ^ this->inverted_); } std::string CH422GGPIOPin::dump_summary() const { return str_sprintf("EXIO%u via CH422G", pin_); } +void CH422GGPIOPin::set_flags(gpio::Flags flags) { + flags_ = flags; + this->parent_->pin_mode(this->pin_, flags); +} } // namespace ch422g } // namespace esphome diff --git a/esphome/components/ch422g/ch422g.h b/esphome/components/ch422g/ch422g.h index 781df65437..30780e09ad 100644 --- a/esphome/components/ch422g/ch422g.h +++ b/esphome/components/ch422g/ch422g.h @@ -23,32 +23,30 @@ class CH422GComponent : public Component, public i2c::I2CDevice { void pin_mode(uint8_t pin, gpio::Flags flags); float get_setup_priority() const override; - float get_loop_priority() const override; - void dump_config() override; - void set_restore_value(bool restore_value) { this->restore_value_ = restore_value; } - protected: + bool write_reg_(uint8_t reg, uint8_t value); + uint8_t read_reg_(uint8_t reg); + bool set_mode_(uint8_t mode); bool read_inputs_(); - - bool write_output_(uint8_t value); + bool write_outputs_(); /// The mask to write as output state - 1 means HIGH, 0 means LOW - uint8_t state_mask_{0x00}; + uint16_t output_bits_{0x00}; /// Flags to check if read previously during this loop - uint8_t pin_read_cache_ = {0x00}; - /// Storage for last I2C error seen - esphome::i2c::ErrorCode last_error_; - /// Whether we want to override stored values on expander - bool restore_value_{false}; + uint8_t pin_read_flags_ = {0x00}; + /// Copy of last read values + uint8_t input_bits_ = {0x00}; + /// Copy of the mode value + uint8_t mode_value_{}; }; -/// Helper class to expose a CH422G pin as an internal input GPIO pin. +/// Helper class to expose a CH422G pin as a GPIO pin. class CH422GGPIOPin : public GPIOPin { public: - void setup() override; + void setup() override{}; void pin_mode(gpio::Flags flags) override; bool digital_read() override; void digital_write(bool value) override; @@ -57,13 +55,13 @@ class CH422GGPIOPin : public GPIOPin { void set_parent(CH422GComponent *parent) { parent_ = parent; } void set_pin(uint8_t pin) { pin_ = pin; } void set_inverted(bool inverted) { inverted_ = inverted; } - void set_flags(gpio::Flags flags) { flags_ = flags; } + void set_flags(gpio::Flags flags); protected: - CH422GComponent *parent_; - uint8_t pin_; - bool inverted_; - gpio::Flags flags_; + CH422GComponent *parent_{}; + uint8_t pin_{}; + bool inverted_{}; + gpio::Flags flags_{}; }; } // namespace ch422g diff --git a/esphome/components/gp2y1010au0f/__init__.py b/esphome/components/gp2y1010au0f/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/gp2y1010au0f/gp2y1010au0f.cpp b/esphome/components/gp2y1010au0f/gp2y1010au0f.cpp new file mode 100644 index 0000000000..95b7653e51 --- /dev/null +++ b/esphome/components/gp2y1010au0f/gp2y1010au0f.cpp @@ -0,0 +1,67 @@ +#include "gp2y1010au0f.h" +#include "esphome/core/hal.h" +#include "esphome/core/log.h" + +#include + +namespace esphome { +namespace gp2y1010au0f { + +static const char *const TAG = "gp2y1010au0f"; +static const float MIN_VOLTAGE = 0.0f; +static const float MAX_VOLTAGE = 4.0f; + +void GP2Y1010AU0FSensor::dump_config() { + LOG_SENSOR("", "Sharp GP2Y1010AU0F PM2.5 Sensor", this); + ESP_LOGCONFIG(TAG, " Sampling duration: %" PRId32 " ms", this->sample_duration_); + ESP_LOGCONFIG(TAG, " ADC voltage multiplier: %.3f", this->voltage_multiplier_); + LOG_UPDATE_INTERVAL(this); +} + +void GP2Y1010AU0FSensor::update() { + is_sampling_ = true; + + this->set_timeout("read", this->sample_duration_, [this]() { + this->is_sampling_ = false; + if (this->num_samples_ == 0) + return; + + float mean = this->sample_sum_ / float(this->num_samples_); + ESP_LOGD(TAG, "ADC read voltage: %.3f V (mean from %" PRId32 " samples)", mean, this->num_samples_); + + // PM2.5 calculation + // ref: https://www.howmuchsnow.com/arduino/airquality/ + int16_t pm_2_5_value = 170 * mean; + this->publish_state(pm_2_5_value); + }); + + // reset readings + this->num_samples_ = 0; + this->sample_sum_ = 0.0f; +} + +void GP2Y1010AU0FSensor::loop() { + if (!this->is_sampling_) + return; + + // enable the internal IR LED + this->led_output_->turn_on(); + // wait for the sensor to stabilize + delayMicroseconds(this->sample_wait_before_); + // perform a single sample + float read_voltage = this->source_->sample(); + // disable the internal IR LED + this->led_output_->turn_off(); + + if (std::isnan(read_voltage)) + return; + read_voltage = read_voltage * this->voltage_multiplier_ - this->voltage_offset_; + if (read_voltage < MIN_VOLTAGE || read_voltage > MAX_VOLTAGE) + return; + + this->num_samples_++; + this->sample_sum_ += read_voltage; +} + +} // namespace gp2y1010au0f +} // namespace esphome diff --git a/esphome/components/gp2y1010au0f/gp2y1010au0f.h b/esphome/components/gp2y1010au0f/gp2y1010au0f.h new file mode 100644 index 0000000000..5ee58e68d2 --- /dev/null +++ b/esphome/components/gp2y1010au0f/gp2y1010au0f.h @@ -0,0 +1,52 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/voltage_sampler/voltage_sampler.h" +#include "esphome/components/output/binary_output.h" + +namespace esphome { +namespace gp2y1010au0f { + +class GP2Y1010AU0FSensor : public sensor::Sensor, public PollingComponent { + public: + void update() override; + void loop() override; + void dump_config() override; + float get_setup_priority() const override { + // after the base sensor has been initialized + return setup_priority::DATA - 1.0f; + } + + void set_adc_source(voltage_sampler::VoltageSampler *source) { source_ = source; } + void set_voltage_refs(float offset, float multiplier) { + this->voltage_offset_ = offset; + this->voltage_multiplier_ = multiplier; + } + void set_led_output(output::BinaryOutput *output) { led_output_ = output; } + + protected: + // duration in ms of the sampling phase + uint32_t sample_duration_ = 100; + // duration in us of the wait before sampling + // ref: https://global.sharp/products/device/lineup/data/pdf/datasheet/gp2y1010au_appl_e.pdf + uint32_t sample_wait_before_ = 280; + // duration in us of the wait after sampling + // it seems no need to delay on purpose since one ADC sampling takes longer than that (300-400 us on ESP8266) + // uint32_t sample_wait_after_ = 40; + // the sampling source to read voltage from + voltage_sampler::VoltageSampler *source_; + // ADC voltage reading offset + float voltage_offset_ = 0.0f; + // ADC voltage reading multiplier + float voltage_multiplier_ = 1.0f; + // the binary output to control the sampling LED + output::BinaryOutput *led_output_; + + float sample_sum_ = 0.0f; + uint32_t num_samples_ = 0; + bool is_sampling_ = false; +}; + +} // namespace gp2y1010au0f +} // namespace esphome diff --git a/esphome/components/gp2y1010au0f/sensor.py b/esphome/components/gp2y1010au0f/sensor.py new file mode 100644 index 0000000000..7e1bd277a6 --- /dev/null +++ b/esphome/components/gp2y1010au0f/sensor.py @@ -0,0 +1,61 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import sensor, voltage_sampler, output +from esphome.const import ( + CONF_SENSOR, + CONF_OUTPUT, + DEVICE_CLASS_PM25, + STATE_CLASS_MEASUREMENT, + UNIT_MICROGRAMS_PER_CUBIC_METER, + ICON_CHEMICAL_WEAPON, +) + +DEPENDENCIES = ["output"] +AUTO_LOAD = ["voltage_sampler"] +CODEOWNERS = ["@zry98"] + +CONF_ADC_VOLTAGE_OFFSET = "adc_voltage_offset" +CONF_ADC_VOLTAGE_MULTIPLIER = "adc_voltage_multiplier" + +gp2y1010au0f_ns = cg.esphome_ns.namespace("gp2y1010au0f") +GP2Y1010AU0FSensor = gp2y1010au0f_ns.class_( + "GP2Y1010AU0FSensor", sensor.Sensor, cg.PollingComponent +) + +CONFIG_SCHEMA = ( + sensor.sensor_schema( + GP2Y1010AU0FSensor, + unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER, + accuracy_decimals=0, + device_class=DEVICE_CLASS_PM25, + state_class=STATE_CLASS_MEASUREMENT, + icon=ICON_CHEMICAL_WEAPON, + ) + .extend( + { + cv.Required(CONF_SENSOR): cv.use_id(voltage_sampler.VoltageSampler), + cv.Optional(CONF_ADC_VOLTAGE_OFFSET, default=0.0): cv.float_, + cv.Optional(CONF_ADC_VOLTAGE_MULTIPLIER, default=1.0): cv.float_, + cv.Required(CONF_OUTPUT): cv.use_id(output.BinaryOutput), + } + ) + .extend(cv.polling_component_schema("60s")) +) + + +async def to_code(config): + var = await sensor.new_sensor(config) + await cg.register_component(var, config) + + # the ADC sensor to read voltage from + adc_sensor = await cg.get_variable(config[CONF_SENSOR]) + cg.add(var.set_adc_source(adc_sensor)) + cg.add( + var.set_voltage_refs( + config[CONF_ADC_VOLTAGE_OFFSET], config[CONF_ADC_VOLTAGE_MULTIPLIER] + ) + ) + + # the binary output to control the module's internal IR LED + led_output = await cg.get_variable(config[CONF_OUTPUT]) + cg.add(var.set_led_output(led_output)) diff --git a/esphome/components/inkplate6/display.py b/esphome/components/inkplate6/display.py index 58a146d2fd..8fe7f7d41d 100644 --- a/esphome/components/inkplate6/display.py +++ b/esphome/components/inkplate6/display.py @@ -53,6 +53,8 @@ MODELS = { "inkplate_10": InkplateModel.INKPLATE_10, "inkplate_6_plus": InkplateModel.INKPLATE_6_PLUS, "inkplate_6_v2": InkplateModel.INKPLATE_6_V2, + "inkplate_5": InkplateModel.INKPLATE_5, + "inkplate_5_v2": InkplateModel.INKPLATE_5_V2, } CONFIG_SCHEMA = cv.All( diff --git a/esphome/components/inkplate6/inkplate.h b/esphome/components/inkplate6/inkplate.h index 2946c89e1c..ca2ad46f1e 100644 --- a/esphome/components/inkplate6/inkplate.h +++ b/esphome/components/inkplate6/inkplate.h @@ -15,6 +15,8 @@ enum InkplateModel : uint8_t { INKPLATE_10 = 1, INKPLATE_6_PLUS = 2, INKPLATE_6_V2 = 3, + INKPLATE_5 = 4, + INKPLATE_5_V2 = 5, }; class Inkplate6 : public display::DisplayBuffer, public i2c::I2CDevice { @@ -29,7 +31,7 @@ class Inkplate6 : public display::DisplayBuffer, public i2c::I2CDevice { const uint8_t pixelMaskLUT[8] = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80}; const uint8_t pixelMaskGLUT[2] = {0x0F, 0xF0}; - const uint8_t waveform3BitAll[4][8][9] = {// INKPLATE_6 + const uint8_t waveform3BitAll[6][8][9] = {// INKPLATE_6 {{0, 1, 1, 0, 0, 1, 1, 0, 0}, {0, 1, 2, 1, 1, 2, 1, 0, 0}, {1, 1, 1, 2, 2, 1, 0, 0, 0}, @@ -64,7 +66,25 @@ class Inkplate6 : public display::DisplayBuffer, public i2c::I2CDevice { {1, 1, 1, 1, 2, 2, 1, 0, 0}, {0, 1, 1, 1, 2, 2, 1, 0, 0}, {0, 0, 0, 0, 1, 1, 2, 0, 0}, - {0, 0, 0, 0, 0, 1, 2, 0, 0}}}; + {0, 0, 0, 0, 0, 1, 2, 0, 0}}, + // INKPLATE_5 + {{0, 0, 1, 1, 0, 1, 1, 1, 0}, + {0, 1, 1, 1, 1, 2, 0, 1, 0}, + {1, 2, 2, 0, 2, 1, 1, 1, 0}, + {1, 1, 1, 2, 0, 1, 1, 2, 0}, + {0, 1, 1, 1, 2, 0, 1, 2, 0}, + {0, 0, 0, 1, 1, 2, 1, 2, 0}, + {1, 1, 1, 2, 0, 2, 1, 2, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}}, + // INKPLATE_5_V2 + {{0, 0, 1, 1, 2, 1, 1, 1, 0}, + {1, 1, 2, 2, 1, 2, 1, 1, 0}, + {0, 1, 2, 2, 1, 1, 2, 1, 0}, + {0, 0, 1, 1, 1, 1, 1, 2, 0}, + {1, 2, 1, 2, 1, 1, 1, 2, 0}, + {0, 1, 1, 1, 2, 0, 1, 2, 0}, + {1, 1, 1, 2, 2, 2, 1, 2, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}}}; void set_greyscale(bool greyscale) { this->greyscale_ = greyscale; @@ -146,6 +166,10 @@ class Inkplate6 : public display::DisplayBuffer, public i2c::I2CDevice { return 800; } else if (this->model_ == INKPLATE_10) { return 1200; + } else if (this->model_ == INKPLATE_5) { + return 960; + } else if (this->model_ == INKPLATE_5_V2) { + return 1280; } else if (this->model_ == INKPLATE_6_PLUS) { return 1024; } @@ -155,6 +179,10 @@ class Inkplate6 : public display::DisplayBuffer, public i2c::I2CDevice { int get_height_internal() override { if (this->model_ == INKPLATE_6 || this->model_ == INKPLATE_6_V2) { return 600; + } else if (this->model_ == INKPLATE_5) { + return 540; + } else if (this->model_ == INKPLATE_5_V2) { + return 720; } else if (this->model_ == INKPLATE_10) { return 825; } else if (this->model_ == INKPLATE_6_PLUS) { diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index 240b407819..336d928f71 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -11,6 +11,7 @@ from esphome.const import ( CONF_BIRTH_MESSAGE, CONF_BROKER, CONF_CERTIFICATE_AUTHORITY, + CONF_CLEAN_SESSION, CONF_CLIENT_CERTIFICATE, CONF_CLIENT_CERTIFICATE_KEY, CONF_CLIENT_ID, @@ -209,6 +210,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_PORT, default=1883): cv.port, cv.Optional(CONF_USERNAME, default=""): cv.string, cv.Optional(CONF_PASSWORD, default=""): cv.string, + cv.Optional(CONF_CLEAN_SESSION, default=False): cv.boolean, cv.Optional(CONF_CLIENT_ID): cv.string, cv.SplitDefault(CONF_IDF_SEND_ASYNC, esp32_idf=False): cv.All( cv.boolean, cv.only_with_esp_idf @@ -325,6 +327,7 @@ async def to_code(config): cg.add(var.set_broker_port(config[CONF_PORT])) cg.add(var.set_username(config[CONF_USERNAME])) cg.add(var.set_password(config[CONF_PASSWORD])) + cg.add(var.set_clean_session(config[CONF_CLEAN_SESSION])) if CONF_CLIENT_ID in config: cg.add(var.set_client_id(config[CONF_CLIENT_ID])) diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index c19b24c0cf..b5ac285026 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -147,6 +147,7 @@ void MQTTClientComponent::dump_config() { this->ip_.str().c_str()); ESP_LOGCONFIG(TAG, " Username: " LOG_SECRET("'%s'"), this->credentials_.username.c_str()); ESP_LOGCONFIG(TAG, " Client ID: " LOG_SECRET("'%s'"), this->credentials_.client_id.c_str()); + ESP_LOGCONFIG(TAG, " Clean Session: %s", YESNO(this->credentials_.clean_session)); if (this->is_discovery_ip_enabled()) { ESP_LOGCONFIG(TAG, " Discovery IP enabled"); } @@ -246,6 +247,7 @@ void MQTTClientComponent::start_connect_() { this->mqtt_backend_.disconnect(); this->mqtt_backend_.set_client_id(this->credentials_.client_id.c_str()); + this->mqtt_backend_.set_clean_session(this->credentials_.clean_session); const char *username = nullptr; if (!this->credentials_.username.empty()) username = this->credentials_.username.c_str(); diff --git a/esphome/components/mqtt/mqtt_client.h b/esphome/components/mqtt/mqtt_client.h index b0d3bbe66d..887800f201 100644 --- a/esphome/components/mqtt/mqtt_client.h +++ b/esphome/components/mqtt/mqtt_client.h @@ -51,6 +51,7 @@ struct MQTTCredentials { std::string username; std::string password; std::string client_id; ///< The client ID. Will automatically be truncated to 23 characters. + bool clean_session; ///< Whether the session will be cleaned or remembered between connects. }; /// Simple data struct for Home Assistant component availability. @@ -254,6 +255,7 @@ class MQTTClientComponent : public Component { void set_username(const std::string &username) { this->credentials_.username = username; } void set_password(const std::string &password) { this->credentials_.password = password; } void set_client_id(const std::string &client_id) { this->credentials_.client_id = client_id; } + void set_clean_session(const bool &clean_session) { this->credentials_.clean_session = clean_session; } void set_on_connect(mqtt_on_connect_callback_t &&callback); void set_on_disconnect(mqtt_on_disconnect_callback_t &&callback); diff --git a/esphome/components/remote_transmitter/__init__.py b/esphome/components/remote_transmitter/__init__.py index d203ff3417..f979939739 100644 --- a/esphome/components/remote_transmitter/__init__.py +++ b/esphome/components/remote_transmitter/__init__.py @@ -1,10 +1,14 @@ +from esphome import automation, pins import esphome.codegen as cg +from esphome.components import esp32_rmt, remote_base import esphome.config_validation as cv -from esphome import pins -from esphome.components import remote_base, esp32_rmt from esphome.const import CONF_CARRIER_DUTY_PERCENT, CONF_ID, CONF_PIN, CONF_RMT_CHANNEL AUTO_LOAD = ["remote_base"] + +CONF_ON_TRANSMIT = "on_transmit" +CONF_ON_COMPLETE = "on_complete" + remote_transmitter_ns = cg.esphome_ns.namespace("remote_transmitter") RemoteTransmitterComponent = remote_transmitter_ns.class_( "RemoteTransmitterComponent", remote_base.RemoteTransmitterBase, cg.Component @@ -19,6 +23,8 @@ CONFIG_SCHEMA = cv.Schema( cv.percentage_int, cv.Range(min=1, max=100) ), cv.Optional(CONF_RMT_CHANNEL): esp32_rmt.validate_rmt_channel(tx=True), + cv.Optional(CONF_ON_TRANSMIT): automation.validate_automation(single=True), + cv.Optional(CONF_ON_COMPLETE): automation.validate_automation(single=True), } ).extend(cv.COMPONENT_SCHEMA) @@ -32,3 +38,13 @@ async def to_code(config): await cg.register_component(var, config) cg.add(var.set_carrier_duty_percent(config[CONF_CARRIER_DUTY_PERCENT])) + + if on_transmit_config := config.get(CONF_ON_TRANSMIT): + await automation.build_automation( + var.get_transmit_trigger(), [], on_transmit_config + ) + + if on_complete_config := config.get(CONF_ON_COMPLETE): + await automation.build_automation( + var.get_complete_trigger(), [], on_complete_config + ) diff --git a/esphome/components/remote_transmitter/remote_transmitter.h b/esphome/components/remote_transmitter/remote_transmitter.h index a5896796c0..4abe687d23 100644 --- a/esphome/components/remote_transmitter/remote_transmitter.h +++ b/esphome/components/remote_transmitter/remote_transmitter.h @@ -33,6 +33,9 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase, void set_carrier_duty_percent(uint8_t carrier_duty_percent) { this->carrier_duty_percent_ = carrier_duty_percent; } + Trigger<> *get_transmit_trigger() const { return this->transmit_trigger_; }; + Trigger<> *get_complete_trigger() const { return this->complete_trigger_; }; + protected: void send_internal(uint32_t send_times, uint32_t send_wait) override; #if defined(USE_ESP8266) || defined(USE_LIBRETINY) @@ -57,6 +60,9 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase, bool inverted_{false}; #endif uint8_t carrier_duty_percent_; + + Trigger<> *transmit_trigger_{new Trigger<>()}; + Trigger<> *complete_trigger_{new Trigger<>()}; }; } // namespace remote_transmitter diff --git a/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp b/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp index eea35019ff..bce2408723 100644 --- a/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +++ b/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp @@ -124,6 +124,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen ESP_LOGE(TAG, "Empty data"); return; } + this->transmit_trigger_->trigger(); for (uint32_t i = 0; i < send_times; i++) { esp_err_t error = rmt_write_items(this->channel_, this->rmt_temp_.data(), this->rmt_temp_.size(), true); if (error != ESP_OK) { @@ -135,6 +136,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen if (i + 1 < send_times) delayMicroseconds(send_wait); } + this->complete_trigger_->trigger(); } } // namespace remote_transmitter diff --git a/esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp b/esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp index 1c0eb94e61..613f00b7f5 100644 --- a/esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +++ b/esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp @@ -76,6 +76,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen uint32_t on_time, off_time; this->calculate_on_off_time_(this->temp_.get_carrier_frequency(), &on_time, &off_time); this->target_time_ = 0; + this->transmit_trigger_->trigger(); for (uint32_t i = 0; i < send_times; i++) { for (int32_t item : this->temp_.get_data()) { if (item > 0) { @@ -93,6 +94,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen if (i + 1 < send_times) this->target_time_ += send_wait; } + this->complete_trigger_->trigger(); } } // namespace remote_transmitter diff --git a/esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp b/esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp index 78bb280482..ad9265fb14 100644 --- a/esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +++ b/esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp @@ -78,6 +78,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen uint32_t on_time, off_time; this->calculate_on_off_time_(this->temp_.get_carrier_frequency(), &on_time, &off_time); this->target_time_ = 0; + this->transmit_trigger_->trigger(); for (uint32_t i = 0; i < send_times; i++) { InterruptLock lock; for (int32_t item : this->temp_.get_data()) { @@ -96,6 +97,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen if (i + 1 < send_times) this->target_time_ += send_wait; } + this->complete_trigger_->trigger(); } } // namespace remote_transmitter diff --git a/esphome/components/tcs34725/tcs34725.cpp b/esphome/components/tcs34725/tcs34725.cpp index 88c59eb761..c9b2ae321a 100644 --- a/esphome/components/tcs34725/tcs34725.cpp +++ b/esphome/components/tcs34725/tcs34725.cpp @@ -1,6 +1,7 @@ #include "tcs34725.h" #include "esphome/core/log.h" #include "esphome/core/hal.h" +#include namespace esphome { namespace tcs34725 { @@ -211,7 +212,7 @@ void TCS34725Component::update() { if (raw_c == 0) { channel_c = channel_r = channel_g = channel_b = 0.0f; } else { - float max_count = this->integration_time_ * 1024.0f / 2.4; + float max_count = this->integration_time_ <= 153.6f ? this->integration_time_ * 1024.0f / 2.4f : 65535.0f; float sum = raw_c; channel_r = raw_r / sum * 100.0f; channel_g = raw_g / sum * 100.0f; @@ -254,7 +255,8 @@ void TCS34725Component::update() { // change integration time an gain to achieve maximum resolution an dynamic range // calculate optimal integration time to achieve 70% satuaration float integration_time_ideal; - integration_time_ideal = 60 / ((float) raw_c / 655.35) * this->integration_time_; + + integration_time_ideal = 60 / ((float) std::max((uint16_t) 1, raw_c) / 655.35f) * this->integration_time_; uint8_t gain_reg_val_new = this->gain_reg_; // increase gain if less than 20% of white channel used and high integration time diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index 6008acb95d..c430d160f2 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -130,11 +130,16 @@ void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, voi } void WiFiComponent::wifi_pre_setup_() { -#ifdef USE_ESP32_IGNORE_EFUSE_MAC_CRC uint8_t mac[6]; +#ifdef USE_ESP32_IGNORE_EFUSE_MAC_CRC get_mac_address_raw(mac); set_mac_address(mac); ESP_LOGV(TAG, "Use EFuse MAC without checking CRC: %s", get_mac_address_pretty().c_str()); +#else + if (has_custom_mac_address()) { + get_mac_address_raw(mac); + set_mac_address(mac); + } #endif esp_err_t err = esp_netif_init(); if (err != ERR_OK) { diff --git a/esphome/const.py b/esphome/const.py index 6e7bbdec98..40b7a1c419 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -120,6 +120,7 @@ CONF_CHANNELS = "channels" CONF_CHARACTERISTIC_UUID = "characteristic_uuid" CONF_CHECK = "check" CONF_CHIPSET = "chipset" +CONF_CLEAN_SESSION = "clean_session" CONF_CLEAR_IMPEDANCE = "clear_impedance" CONF_CLIENT_CERTIFICATE = "client_certificate" CONF_CLIENT_CERTIFICATE_KEY = "client_certificate_key" diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index e75b06ccd3..2e99b0df70 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -671,9 +671,17 @@ void get_mac_address_raw(uint8_t *mac) { // NOLINT(readability-non-const-parame // match the CRC that goes along with it. For those devices, this // work-around reads and uses the MAC address as-is from EFuse, // without doing the CRC check. - esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, mac, 48); + if (has_custom_mac_address()) { + esp_efuse_read_field_blob(ESP_EFUSE_MAC_CUSTOM, mac, 48); + } else { + esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, mac, 48); + } #else - esp_efuse_mac_get_default(mac); + if (has_custom_mac_address()) { + esp_efuse_mac_get_custom(mac); + } else { + esp_efuse_mac_get_default(mac); + } #endif #elif defined(USE_ESP8266) wifi_get_macaddr(STATION_IF, mac); @@ -685,20 +693,53 @@ void get_mac_address_raw(uint8_t *mac) { // NOLINT(readability-non-const-parame // this should be an error, but that messes with CI checks. #error No mac address method defined #endif } + std::string get_mac_address() { uint8_t mac[6]; get_mac_address_raw(mac); return str_snprintf("%02x%02x%02x%02x%02x%02x", 12, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); } + std::string get_mac_address_pretty() { uint8_t mac[6]; get_mac_address_raw(mac); return str_snprintf("%02X:%02X:%02X:%02X:%02X:%02X", 17, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); } + #ifdef USE_ESP32 void set_mac_address(uint8_t *mac) { esp_base_mac_addr_set(mac); } #endif +bool has_custom_mac_address() { +#ifdef USE_ESP32 + uint8_t mac[6]; +#if defined(CONFIG_SOC_IEEE802154_SUPPORTED) || defined(USE_ESP32_IGNORE_EFUSE_MAC_CRC) + return (esp_efuse_read_field_blob(ESP_EFUSE_MAC_CUSTOM, mac, 48) == ESP_OK) && mac_address_is_valid(mac); +#else + return (esp_efuse_mac_get_custom(mac) == ESP_OK) && mac_address_is_valid(mac); +#endif +#else + return false; +#endif +} + +bool mac_address_is_valid(const uint8_t *mac) { + bool is_all_zeros = true; + bool is_all_ones = true; + + for (uint8_t i = 0; i < 6; i++) { + if (mac[i] != 0) { + is_all_zeros = false; + } + } + for (uint8_t i = 0; i < 6; i++) { + if (mac[i] != 0xFF) { + is_all_ones = false; + } + } + return !(is_all_zeros || is_all_ones); +} + void delay_microseconds_safe(uint32_t us) { // avoids CPU locks that could trigger WDT or affect WiFi/BT stability uint32_t start = micros(); diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 3e6fe9433e..7df4b84230 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -635,6 +635,14 @@ std::string get_mac_address_pretty(); void set_mac_address(uint8_t *mac); #endif +/// Check if a custom MAC address is set (ESP32 & variants) +/// @return True if a custom MAC address is set (ESP32 & variants), else false +bool has_custom_mac_address(); + +/// Check if the MAC address is not all zeros or all ones +/// @return True if MAC is valid, else false +bool mac_address_is_valid(const uint8_t *mac); + /// Delay for the given amount of microseconds, possibly yielding to other processes during the wait. void delay_microseconds_safe(uint32_t us); diff --git a/esphome/core/ring_buffer.cpp b/esphome/core/ring_buffer.cpp index d8ca831de0..f97c686684 100644 --- a/esphome/core/ring_buffer.cpp +++ b/esphome/core/ring_buffer.cpp @@ -11,16 +11,26 @@ namespace esphome { static const char *const TAG = "ring_buffer"; +RingBuffer::~RingBuffer() { + if (this->handle_ != nullptr) { + vStreamBufferDelete(this->handle_); + ExternalRAMAllocator allocator(ExternalRAMAllocator::ALLOW_FAILURE); + allocator.deallocate(this->storage_, this->size_); + } +} + std::unique_ptr RingBuffer::create(size_t len) { std::unique_ptr rb = make_unique(); + rb->size_ = len + 1; + ExternalRAMAllocator allocator(ExternalRAMAllocator::ALLOW_FAILURE); - rb->storage_ = allocator.allocate(len + 1); + rb->storage_ = allocator.allocate(rb->size_); if (rb->storage_ == nullptr) { return nullptr; } - rb->handle_ = xStreamBufferCreateStatic(len + 1, 1, rb->storage_, &rb->structure_); + rb->handle_ = xStreamBufferCreateStatic(rb->size_, 1, rb->storage_, &rb->structure_); ESP_LOGD(TAG, "Created ring buffer with size %u", len); return rb; } diff --git a/esphome/core/ring_buffer.h b/esphome/core/ring_buffer.h index 97ffefcefa..c0511fb52e 100644 --- a/esphome/core/ring_buffer.h +++ b/esphome/core/ring_buffer.h @@ -12,6 +12,8 @@ namespace esphome { class RingBuffer { public: + ~RingBuffer(); + /** * @brief Reads from the ring buffer, waiting up to a specified number of ticks if necessary. * @@ -83,6 +85,7 @@ class RingBuffer { StreamBufferHandle_t handle_; StaticStreamBuffer_t structure_; uint8_t *storage_; + size_t size_{0}; }; } // namespace esphome diff --git a/esphome/voluptuous_schema.py b/esphome/voluptuous_schema.py index 7f1573b443..15f9206f21 100644 --- a/esphome/voluptuous_schema.py +++ b/esphome/voluptuous_schema.py @@ -226,4 +226,6 @@ class _Schema(vol.Schema): if isinstance(schema, vol.Schema): schema = schema.schema ret = super().extend(schema, extra=extra) - return _Schema(ret.schema, extra=ret.extra, extra_schemas=self._extra_schemas) + return _Schema( + ret.schema, extra=ret.extra, extra_schemas=self._extra_schemas.copy() + ) diff --git a/esphome/wizard.py b/esphome/wizard.py index 319fb31938..b1057189fd 100644 --- a/esphome/wizard.py +++ b/esphome/wizard.py @@ -92,7 +92,7 @@ rp2040: board: {board} framework: # Required until https://github.com/platformio/platform-raspberrypi/pull/36 is merged - platform_version: https://github.com/maxgerhardt/platform-raspberrypi.git + platform_version: https://github.com/maxgerhardt/platform-raspberrypi.git#5e87ae34ca025274df25b3303e9e9cb6c120123c """ BK72XX_CONFIG = """ diff --git a/platformio.ini b/platformio.ini index e3593bf43f..fc38923f65 100644 --- a/platformio.ini +++ b/platformio.ini @@ -165,7 +165,7 @@ platform_packages = extends = common:arduino board_build.filesystem_size = 0.5m -platform = https://github.com/maxgerhardt/platform-raspberrypi.git +platform = https://github.com/maxgerhardt/platform-raspberrypi.git#5e87ae34ca025274df25b3303e9e9cb6c120123c platform_packages = ; earlephilhower/framework-arduinopico@~1.20602.0 ; Cannot use the platformio package until old releases stop getting deleted earlephilhower/framework-arduinopico@https://github.com/earlephilhower/arduino-pico/releases/download/3.9.4/rp2040-3.9.4.zip diff --git a/tests/components/bl0906/common.yaml b/tests/components/bl0906/common.yaml index 944791369c..29321a9471 100644 --- a/tests/components/bl0906/common.yaml +++ b/tests/components/bl0906/common.yaml @@ -8,6 +8,7 @@ uart: sensor: - platform: bl0906 + id: bl frequency: name: 'Frequency' temperature: @@ -60,3 +61,9 @@ sensor: name: 'Total_Energy' total_power: name: 'Total_Power' + +button: + - platform: template + id: reset + on_press: + - bl0906.reset_energy: bl diff --git a/tests/components/ch422g/common.yaml b/tests/components/ch422g/common.yaml index 02061bda59..d65956ecac 100644 --- a/tests/components/ch422g/common.yaml +++ b/tests/components/ch422g/common.yaml @@ -1,6 +1,5 @@ ch422g: - id: ch422g_hub - address: 0x24 binary_sensor: - platform: gpio @@ -11,10 +10,18 @@ binary_sensor: number: 1 mode: INPUT inverted: true +output: - platform: gpio - id: ch422g_output + id: ch422_out_0 pin: ch422g: ch422g_hub number: 0 mode: OUTPUT inverted: false + - platform: gpio + id: ch422_out_11 + pin: + ch422g: ch422g_hub + number: 11 + mode: OUTPUT_OPEN_DRAIN + inverted: true diff --git a/tests/components/gp2y1010au0f/test.esp32-idf.yaml b/tests/components/gp2y1010au0f/test.esp32-idf.yaml new file mode 100644 index 0000000000..eb5ad0ea67 --- /dev/null +++ b/tests/components/gp2y1010au0f/test.esp32-idf.yaml @@ -0,0 +1,16 @@ +sensor: + - platform: adc + pin: GPIO36 + id: adc_sensor + + - platform: gp2y1010au0f + sensor: adc_sensor + name: Dust Sensor + adc_voltage_offset: 0.2 + adc_voltage_multiplier: 3.3 + output: dust_sensor_led + +output: + - platform: gpio + id: dust_sensor_led + pin: GPIO32 diff --git a/tests/components/mqtt/common.yaml b/tests/components/mqtt/common.yaml index b7d1655ec9..f7a727ab2f 100644 --- a/tests/components/mqtt/common.yaml +++ b/tests/components/mqtt/common.yaml @@ -10,6 +10,7 @@ mqtt: port: 1883 username: debug password: debug + clean_session: True client_id: someclient use_abbreviations: false discovery: true diff --git a/tests/test_build_components/build_components_base.rp2040-ard.yaml b/tests/test_build_components/build_components_base.rp2040-ard.yaml index 6c6a27e0a7..f9815578c5 100644 --- a/tests/test_build_components/build_components_base.rp2040-ard.yaml +++ b/tests/test_build_components/build_components_base.rp2040-ard.yaml @@ -6,7 +6,7 @@ rp2040: board: rpipicow framework: # Waiting for https://github.com/platformio/platform-raspberrypi/pull/36 - platform_version: https://github.com/maxgerhardt/platform-raspberrypi.git + platform_version: https://github.com/maxgerhardt/platform-raspberrypi.git#5e87ae34ca025274df25b3303e9e9cb6c120123c logger: level: VERY_VERBOSE