1
0
mirror of https://github.com/esphome/esphome.git synced 2025-09-04 12:22:20 +01:00

Merge remote-tracking branch 'upstream/dev' into integration

This commit is contained in:
J. Nick Koston
2025-08-05 17:02:31 -10:00
30 changed files with 148 additions and 134 deletions

View File

@@ -40,11 +40,11 @@ esphome/components/analog_threshold/* @ianchi
esphome/components/animation/* @syndlex esphome/components/animation/* @syndlex
esphome/components/anova/* @buxtronix esphome/components/anova/* @buxtronix
esphome/components/apds9306/* @aodrenah esphome/components/apds9306/* @aodrenah
esphome/components/api/* @OttoWinter esphome/components/api/* @esphome/core
esphome/components/as5600/* @ammmze esphome/components/as5600/* @ammmze
esphome/components/as5600/sensor/* @ammmze esphome/components/as5600/sensor/* @ammmze
esphome/components/as7341/* @mrgnr esphome/components/as7341/* @mrgnr
esphome/components/async_tcp/* @OttoWinter esphome/components/async_tcp/* @esphome/core
esphome/components/at581x/* @X-Ryl669 esphome/components/at581x/* @X-Ryl669
esphome/components/atc_mithermometer/* @ahpohl esphome/components/atc_mithermometer/* @ahpohl
esphome/components/atm90e26/* @danieltwagner esphome/components/atm90e26/* @danieltwagner
@@ -91,7 +91,7 @@ esphome/components/bytebuffer/* @clydebarrow
esphome/components/camera/* @DT-art1 @bdraco esphome/components/camera/* @DT-art1 @bdraco
esphome/components/canbus/* @danielschramm @mvturnho esphome/components/canbus/* @danielschramm @mvturnho
esphome/components/cap1188/* @mreditor97 esphome/components/cap1188/* @mreditor97
esphome/components/captive_portal/* @OttoWinter esphome/components/captive_portal/* @esphome/core
esphome/components/ccs811/* @habbie esphome/components/ccs811/* @habbie
esphome/components/cd74hc4067/* @asoehlke esphome/components/cd74hc4067/* @asoehlke
esphome/components/ch422g/* @clydebarrow @jesterret esphome/components/ch422g/* @clydebarrow @jesterret
@@ -118,7 +118,7 @@ esphome/components/dallas_temp/* @ssieb
esphome/components/daly_bms/* @s1lvi0 esphome/components/daly_bms/* @s1lvi0
esphome/components/dashboard_import/* @esphome/core esphome/components/dashboard_import/* @esphome/core
esphome/components/datetime/* @jesserockz @rfdarter esphome/components/datetime/* @jesserockz @rfdarter
esphome/components/debug/* @OttoWinter esphome/components/debug/* @esphome/core
esphome/components/delonghi/* @grob6000 esphome/components/delonghi/* @grob6000
esphome/components/dfplayer/* @glmnet esphome/components/dfplayer/* @glmnet
esphome/components/dfrobot_sen0395/* @niklasweber esphome/components/dfrobot_sen0395/* @niklasweber
@@ -238,7 +238,7 @@ esphome/components/integration/* @OttoWinter
esphome/components/internal_temperature/* @Mat931 esphome/components/internal_temperature/* @Mat931
esphome/components/interval/* @esphome/core esphome/components/interval/* @esphome/core
esphome/components/jsn_sr04t/* @Mafus1 esphome/components/jsn_sr04t/* @Mafus1
esphome/components/json/* @OttoWinter esphome/components/json/* @esphome/core
esphome/components/kamstrup_kmp/* @cfeenstra1024 esphome/components/kamstrup_kmp/* @cfeenstra1024
esphome/components/key_collector/* @ssieb esphome/components/key_collector/* @ssieb
esphome/components/key_provider/* @ssieb esphome/components/key_provider/* @ssieb
@@ -468,7 +468,7 @@ esphome/components/template/event/* @nohat
esphome/components/template/fan/* @ssieb esphome/components/template/fan/* @ssieb
esphome/components/text/* @mauritskorse esphome/components/text/* @mauritskorse
esphome/components/thermostat/* @kbx81 esphome/components/thermostat/* @kbx81
esphome/components/time/* @OttoWinter esphome/components/time/* @esphome/core
esphome/components/tlc5947/* @rnauber esphome/components/tlc5947/* @rnauber
esphome/components/tlc5971/* @IJIJI esphome/components/tlc5971/* @IJIJI
esphome/components/tm1621/* @Philippe12 esphome/components/tm1621/* @Philippe12
@@ -512,7 +512,7 @@ esphome/components/wake_on_lan/* @clydebarrow @willwill2will54
esphome/components/watchdog/* @oarcher esphome/components/watchdog/* @oarcher
esphome/components/waveshare_epaper/* @clydebarrow esphome/components/waveshare_epaper/* @clydebarrow
esphome/components/web_server/ota/* @esphome/core esphome/components/web_server/ota/* @esphome/core
esphome/components/web_server_base/* @OttoWinter esphome/components/web_server_base/* @esphome/core
esphome/components/web_server_idf/* @dentra esphome/components/web_server_idf/* @dentra
esphome/components/weikai/* @DrCoolZic esphome/components/weikai/* @DrCoolZic
esphome/components/weikai_i2c/* @DrCoolZic esphome/components/weikai_i2c/* @DrCoolZic

View File

@@ -29,7 +29,7 @@ from esphome.core import CORE, coroutine_with_priority
DOMAIN = "api" DOMAIN = "api"
DEPENDENCIES = ["network"] DEPENDENCIES = ["network"]
AUTO_LOAD = ["socket"] AUTO_LOAD = ["socket"]
CODEOWNERS = ["@OttoWinter"] CODEOWNERS = ["@esphome/core"]
api_ns = cg.esphome_ns.namespace("api") api_ns = cg.esphome_ns.namespace("api")
APIServer = api_ns.class_("APIServer", cg.Component, cg.Controller) APIServer = api_ns.class_("APIServer", cg.Component, cg.Controller)

View File

@@ -10,7 +10,7 @@ from esphome.const import (
) )
from esphome.core import CORE, coroutine_with_priority from esphome.core import CORE, coroutine_with_priority
CODEOWNERS = ["@OttoWinter"] CODEOWNERS = ["@esphome/core"]
CONFIG_SCHEMA = cv.All( CONFIG_SCHEMA = cv.All(
cv.Schema({}), cv.Schema({}),

View File

@@ -14,7 +14,7 @@ from esphome.core import CORE, coroutine_with_priority
AUTO_LOAD = ["web_server_base", "ota.web_server"] AUTO_LOAD = ["web_server_base", "ota.web_server"]
DEPENDENCIES = ["wifi"] DEPENDENCIES = ["wifi"]
CODEOWNERS = ["@OttoWinter"] CODEOWNERS = ["@esphome/core"]
captive_portal_ns = cg.esphome_ns.namespace("captive_portal") captive_portal_ns = cg.esphome_ns.namespace("captive_portal")
CaptivePortal = captive_portal_ns.class_("CaptivePortal", cg.Component) CaptivePortal = captive_portal_ns.class_("CaptivePortal", cg.Component)

View File

@@ -13,7 +13,7 @@ from esphome.const import (
) )
from esphome.core import CORE from esphome.core import CORE
CODEOWNERS = ["@OttoWinter"] CODEOWNERS = ["@esphome/core"]
DEPENDENCIES = ["logger"] DEPENDENCIES = ["logger"]
CONF_DEBUG_ID = "debug_id" CONF_DEBUG_ID = "debug_id"

View File

@@ -345,7 +345,7 @@ async def to_code(config):
cg.add_define("USE_CAMERA") cg.add_define("USE_CAMERA")
if CORE.using_esp_idf: if CORE.using_esp_idf:
add_idf_component(name="espressif/esp32-camera", ref="2.1.0") add_idf_component(name="espressif/esp32-camera", ref="2.1.1")
for conf in config.get(CONF_ON_STREAM_START, []): for conf in config.get(CONF_ON_STREAM_START, []):
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)

View File

@@ -65,15 +65,6 @@ CONF_WAIT_FOR_SENT = "wait_for_sent"
MAX_ESPNOW_PACKET_SIZE = 250 # Maximum size of the payload in bytes MAX_ESPNOW_PACKET_SIZE = 250 # Maximum size of the payload in bytes
def _validate_unknown_peer(config):
if config[CONF_AUTO_ADD_PEER] and config.get(CONF_ON_UNKNOWN_PEER):
raise cv.Invalid(
f"'{CONF_ON_UNKNOWN_PEER}' cannot be used when '{CONF_AUTO_ADD_PEER}' is enabled.",
path=[CONF_ON_UNKNOWN_PEER],
)
return config
CONFIG_SCHEMA = cv.All( CONFIG_SCHEMA = cv.All(
cv.Schema( cv.Schema(
{ {
@@ -103,7 +94,6 @@ CONFIG_SCHEMA = cv.All(
}, },
).extend(cv.COMPONENT_SCHEMA), ).extend(cv.COMPONENT_SCHEMA),
cv.only_on_esp32, cv.only_on_esp32,
_validate_unknown_peer,
) )
@@ -124,7 +114,6 @@ async def _trigger_to_code(config):
async def to_code(config): async def to_code(config):
print(config)
var = cg.new_Pvariable(config[CONF_ID]) var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config) await cg.register_component(var, config)

View File

@@ -40,20 +40,20 @@ template<typename... Ts> class SendAction : public Action<Ts...>, public Parente
this->num_running_++; this->num_running_++;
send_callback_t send_callback = [this, x...](esp_err_t status) { send_callback_t send_callback = [this, x...](esp_err_t status) {
if (status == ESP_OK) { if (status == ESP_OK) {
if (this->sent_.empty() && this->flags_.wait_for_sent) { if (!this->sent_.empty()) {
this->play_next_(x...);
} else if (!this->sent_.empty()) {
this->sent_.play(x...); this->sent_.play(x...);
} else if (this->flags_.wait_for_sent) {
this->play_next_(x...);
} }
} else { } else {
if (this->error_.empty() && this->flags_.wait_for_sent) { if (!this->error_.empty()) {
this->error_.play(x...);
} else if (this->flags_.wait_for_sent) {
if (this->flags_.continue_on_error) { if (this->flags_.continue_on_error) {
this->play_next_(x...); this->play_next_(x...);
} else { } else {
this->stop_complex(); this->stop_complex();
} }
} else if (!this->error_.empty()) {
this->error_.play(x...);
} }
} }
}; };

View File

@@ -154,7 +154,7 @@ void ESPNowComponent::setup() {
} }
void ESPNowComponent::enable() { void ESPNowComponent::enable() {
if (this->state_ != ESPNOW_STATE_ENABLED) if (this->state_ == ESPNOW_STATE_ENABLED)
return; return;
ESP_LOGD(TAG, "Enabling"); ESP_LOGD(TAG, "Enabling");
@@ -178,11 +178,7 @@ void ESPNowComponent::enable_() {
this->apply_wifi_channel(); this->apply_wifi_channel();
} }
#ifdef USE_WIFI this->get_wifi_channel();
else {
this->wifi_channel_ = wifi::global_wifi_component->get_wifi_channel();
}
#endif
esp_err_t err = esp_now_init(); esp_err_t err = esp_now_init();
if (err != ESP_OK) { if (err != ESP_OK) {
@@ -215,6 +211,7 @@ void ESPNowComponent::enable_() {
for (auto peer : this->peers_) { for (auto peer : this->peers_) {
this->add_peer(peer.address); this->add_peer(peer.address);
} }
this->state_ = ESPNOW_STATE_ENABLED; this->state_ = ESPNOW_STATE_ENABLED;
} }
@@ -228,10 +225,6 @@ void ESPNowComponent::disable() {
esp_now_unregister_recv_cb(); esp_now_unregister_recv_cb();
esp_now_unregister_send_cb(); esp_now_unregister_send_cb();
for (auto peer : this->peers_) {
this->del_peer(peer.address);
}
esp_err_t err = esp_now_deinit(); esp_err_t err = esp_now_deinit();
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGE(TAG, "esp_now_deinit failed! 0x%x", err); ESP_LOGE(TAG, "esp_now_deinit failed! 0x%x", err);
@@ -267,7 +260,6 @@ void ESPNowComponent::loop() {
} }
} }
#endif #endif
// Process received packets // Process received packets
ESPNowPacket *packet = this->receive_packet_queue_.pop(); ESPNowPacket *packet = this->receive_packet_queue_.pop();
while (packet != nullptr) { while (packet != nullptr) {
@@ -275,14 +267,16 @@ void ESPNowComponent::loop() {
case ESPNowPacket::RECEIVED: { case ESPNowPacket::RECEIVED: {
const ESPNowRecvInfo info = packet->get_receive_info(); const ESPNowRecvInfo info = packet->get_receive_info();
if (!esp_now_is_peer_exist(info.src_addr)) { if (!esp_now_is_peer_exist(info.src_addr)) {
if (this->auto_add_peer_) { bool handled = false;
this->add_peer(info.src_addr); for (auto *handler : this->unknown_peer_handlers_) {
} else { if (handler->on_unknown_peer(info, packet->packet_.receive.data, packet->packet_.receive.size)) {
for (auto *handler : this->unknown_peer_handlers_) { handled = true;
if (handler->on_unknown_peer(info, packet->packet_.receive.data, packet->packet_.receive.size)) break; // If a handler returns true, stop processing further handlers
break; // If a handler returns true, stop processing further handlers
} }
} }
if (!handled && this->auto_add_peer_) {
this->add_peer(info.src_addr);
}
} }
// Intentionally left as if instead of else in case the peer is added above // Intentionally left as if instead of else in case the peer is added above
if (esp_now_is_peer_exist(info.src_addr)) { if (esp_now_is_peer_exist(info.src_addr)) {
@@ -343,6 +337,12 @@ void ESPNowComponent::loop() {
} }
} }
uint8_t ESPNowComponent::get_wifi_channel() {
wifi_second_chan_t dummy;
esp_wifi_get_channel(&this->wifi_channel_, &dummy);
return this->wifi_channel_;
}
esp_err_t ESPNowComponent::send(const uint8_t *peer_address, const uint8_t *payload, size_t size, esp_err_t ESPNowComponent::send(const uint8_t *peer_address, const uint8_t *payload, size_t size,
const send_callback_t &callback) { const send_callback_t &callback) {
if (this->state_ != ESPNOW_STATE_ENABLED) { if (this->state_ != ESPNOW_STATE_ENABLED) {

View File

@@ -110,6 +110,7 @@ class ESPNowComponent : public Component {
void set_wifi_channel(uint8_t channel) { this->wifi_channel_ = channel; } void set_wifi_channel(uint8_t channel) { this->wifi_channel_ = channel; }
void apply_wifi_channel(); void apply_wifi_channel();
uint8_t get_wifi_channel();
void set_auto_add_peer(bool value) { this->auto_add_peer_ = value; } void set_auto_add_peer(bool value) { this->auto_add_peer_ = value; }

View File

@@ -2,7 +2,7 @@ import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.core import coroutine_with_priority from esphome.core import coroutine_with_priority
CODEOWNERS = ["@OttoWinter"] CODEOWNERS = ["@esphome/core"]
json_ns = cg.esphome_ns.namespace("json") json_ns = cg.esphome_ns.namespace("json")
CONFIG_SCHEMA = cv.All( CONFIG_SCHEMA = cv.All(

View File

@@ -24,5 +24,5 @@ CONFIG_SCHEMA = (
async def to_code(config): async def to_code(config):
var = await mcp23xxx_base.register_mcp23xxx(config) var = await mcp23xxx_base.register_mcp23xxx(config, mcp23x08_base.NUM_PINS)
await i2c.register_i2c_device(var, config) await i2c.register_i2c_device(var, config)

View File

@@ -24,5 +24,5 @@ CONFIG_SCHEMA = (
async def to_code(config): async def to_code(config):
var = await mcp23xxx_base.register_mcp23xxx(config) var = await mcp23xxx_base.register_mcp23xxx(config, mcp23x17_base.NUM_PINS)
await i2c.register_i2c_device(var, config) await i2c.register_i2c_device(var, config)

View File

@@ -27,6 +27,6 @@ CONFIG_SCHEMA = (
async def to_code(config): async def to_code(config):
var = await mcp23xxx_base.register_mcp23xxx(config) var = await mcp23xxx_base.register_mcp23xxx(config, mcp23x08_base.NUM_PINS)
cg.add(var.set_device_address(config[CONF_DEVICEADDRESS])) cg.add(var.set_device_address(config[CONF_DEVICEADDRESS]))
await spi.register_spi_device(var, config) await spi.register_spi_device(var, config)

View File

@@ -27,6 +27,6 @@ CONFIG_SCHEMA = (
async def to_code(config): async def to_code(config):
var = await mcp23xxx_base.register_mcp23xxx(config) var = await mcp23xxx_base.register_mcp23xxx(config, mcp23x17_base.NUM_PINS)
cg.add(var.set_device_address(config[CONF_DEVICEADDRESS])) cg.add(var.set_device_address(config[CONF_DEVICEADDRESS]))
await spi.register_spi_device(var, config) await spi.register_spi_device(var, config)

View File

@@ -4,5 +4,7 @@ from esphome.components import mcp23xxx_base
AUTO_LOAD = ["mcp23xxx_base"] AUTO_LOAD = ["mcp23xxx_base"]
CODEOWNERS = ["@jesserockz"] CODEOWNERS = ["@jesserockz"]
NUM_PINS = 8
mcp23x08_base_ns = cg.esphome_ns.namespace("mcp23x08_base") mcp23x08_base_ns = cg.esphome_ns.namespace("mcp23x08_base")
MCP23X08Base = mcp23x08_base_ns.class_("MCP23X08Base", mcp23xxx_base.MCP23XXXBase) MCP23X08Base = mcp23x08_base_ns.class_("MCP23X08Base", mcp23xxx_base.MCP23XXXBase)

View File

@@ -6,19 +6,21 @@ namespace mcp23x08_base {
static const char *const TAG = "mcp23x08_base"; static const char *const TAG = "mcp23x08_base";
bool MCP23X08Base::digital_read(uint8_t pin) { bool MCP23X08Base::digital_read_hw(uint8_t pin) {
uint8_t bit = pin % 8; if (!this->read_reg(mcp23x08_base::MCP23X08_GPIO, &this->input_mask_)) {
uint8_t reg_addr = mcp23x08_base::MCP23X08_GPIO; this->status_set_warning(ESP_LOG_MSG_COMM_FAIL);
uint8_t value = 0; return false;
this->read_reg(reg_addr, &value); }
return value & (1 << bit); return true;
} }
void MCP23X08Base::digital_write(uint8_t pin, bool value) { void MCP23X08Base::digital_write_hw(uint8_t pin, bool value) {
uint8_t reg_addr = mcp23x08_base::MCP23X08_OLAT; uint8_t reg_addr = mcp23x08_base::MCP23X08_OLAT;
this->update_reg(pin, value, reg_addr); this->update_reg(pin, value, reg_addr);
} }
bool MCP23X08Base::digital_read_cache(uint8_t pin) { return this->input_mask_ & (1 << pin); }
void MCP23X08Base::pin_mode(uint8_t pin, gpio::Flags flags) { void MCP23X08Base::pin_mode(uint8_t pin, gpio::Flags flags) {
uint8_t iodir = mcp23x08_base::MCP23X08_IODIR; uint8_t iodir = mcp23x08_base::MCP23X08_IODIR;
uint8_t gppu = mcp23x08_base::MCP23X08_GPPU; uint8_t gppu = mcp23x08_base::MCP23X08_GPPU;

View File

@@ -1,7 +1,7 @@
#pragma once #pragma once
#include "esphome/core/component.h"
#include "esphome/components/mcp23xxx_base/mcp23xxx_base.h" #include "esphome/components/mcp23xxx_base/mcp23xxx_base.h"
#include "esphome/core/component.h"
#include "esphome/core/hal.h" #include "esphome/core/hal.h"
namespace esphome { namespace esphome {
@@ -22,10 +22,12 @@ enum MCP23S08GPIORegisters {
MCP23X08_OLAT = 0x0A, MCP23X08_OLAT = 0x0A,
}; };
class MCP23X08Base : public mcp23xxx_base::MCP23XXXBase { class MCP23X08Base : public mcp23xxx_base::MCP23XXXBase<8> {
public: public:
bool digital_read(uint8_t pin) override; bool digital_read_hw(uint8_t pin) override;
void digital_write(uint8_t pin, bool value) override; void digital_write_hw(uint8_t pin, bool value) override;
bool digital_read_cache(uint8_t pin) override;
void pin_mode(uint8_t pin, gpio::Flags flags) override; void pin_mode(uint8_t pin, gpio::Flags flags) override;
void pin_interrupt_mode(uint8_t pin, mcp23xxx_base::MCP23XXXInterruptMode interrupt_mode) override; void pin_interrupt_mode(uint8_t pin, mcp23xxx_base::MCP23XXXInterruptMode interrupt_mode) override;
@@ -33,6 +35,9 @@ class MCP23X08Base : public mcp23xxx_base::MCP23XXXBase {
void update_reg(uint8_t pin, bool pin_value, uint8_t reg_a) override; void update_reg(uint8_t pin, bool pin_value, uint8_t reg_a) override;
uint8_t olat_{0x00}; uint8_t olat_{0x00};
/// State read in digital_read_hw
uint8_t input_mask_{0x00};
}; };
} // namespace mcp23x08_base } // namespace mcp23x08_base

View File

@@ -4,5 +4,7 @@ from esphome.components import mcp23xxx_base
AUTO_LOAD = ["mcp23xxx_base"] AUTO_LOAD = ["mcp23xxx_base"]
CODEOWNERS = ["@jesserockz"] CODEOWNERS = ["@jesserockz"]
NUM_PINS = 16
mcp23x17_base_ns = cg.esphome_ns.namespace("mcp23x17_base") mcp23x17_base_ns = cg.esphome_ns.namespace("mcp23x17_base")
MCP23X17Base = mcp23x17_base_ns.class_("MCP23X17Base", mcp23xxx_base.MCP23XXXBase) MCP23X17Base = mcp23x17_base_ns.class_("MCP23X17Base", mcp23xxx_base.MCP23XXXBase)

View File

@@ -1,4 +1,5 @@
#include "mcp23x17_base.h" #include "mcp23x17_base.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h" #include "esphome/core/log.h"
namespace esphome { namespace esphome {
@@ -6,19 +7,31 @@ namespace mcp23x17_base {
static const char *const TAG = "mcp23x17_base"; static const char *const TAG = "mcp23x17_base";
bool MCP23X17Base::digital_read(uint8_t pin) { bool MCP23X17Base::digital_read_hw(uint8_t pin) {
uint8_t bit = pin % 8; uint8_t data;
uint8_t reg_addr = pin < 8 ? mcp23x17_base::MCP23X17_GPIOA : mcp23x17_base::MCP23X17_GPIOB; if (pin < 8) {
uint8_t value = 0; if (!this->read_reg(mcp23x17_base::MCP23X17_GPIOA, &data)) {
this->read_reg(reg_addr, &value); this->status_set_warning(ESP_LOG_MSG_COMM_FAIL);
return value & (1 << bit); return false;
}
this->input_mask_ = encode_uint16(this->input_mask_ >> 8, data);
} else {
if (!this->read_reg(mcp23x17_base::MCP23X17_GPIOB, &data)) {
this->status_set_warning(ESP_LOG_MSG_COMM_FAIL);
return false;
}
this->input_mask_ = encode_uint16(data, this->input_mask_ & 0xFF);
}
return true;
} }
void MCP23X17Base::digital_write(uint8_t pin, bool value) { void MCP23X17Base::digital_write_hw(uint8_t pin, bool value) {
uint8_t reg_addr = pin < 8 ? mcp23x17_base::MCP23X17_OLATA : mcp23x17_base::MCP23X17_OLATB; uint8_t reg_addr = pin < 8 ? mcp23x17_base::MCP23X17_OLATA : mcp23x17_base::MCP23X17_OLATB;
this->update_reg(pin, value, reg_addr); this->update_reg(pin, value, reg_addr);
} }
bool MCP23X17Base::digital_read_cache(uint8_t pin) { return this->input_mask_ & (1 << pin); }
void MCP23X17Base::pin_mode(uint8_t pin, gpio::Flags flags) { void MCP23X17Base::pin_mode(uint8_t pin, gpio::Flags flags) {
uint8_t iodir = pin < 8 ? mcp23x17_base::MCP23X17_IODIRA : mcp23x17_base::MCP23X17_IODIRB; uint8_t iodir = pin < 8 ? mcp23x17_base::MCP23X17_IODIRA : mcp23x17_base::MCP23X17_IODIRB;
uint8_t gppu = pin < 8 ? mcp23x17_base::MCP23X17_GPPUA : mcp23x17_base::MCP23X17_GPPUB; uint8_t gppu = pin < 8 ? mcp23x17_base::MCP23X17_GPPUA : mcp23x17_base::MCP23X17_GPPUB;

View File

@@ -1,7 +1,7 @@
#pragma once #pragma once
#include "esphome/core/component.h"
#include "esphome/components/mcp23xxx_base/mcp23xxx_base.h" #include "esphome/components/mcp23xxx_base/mcp23xxx_base.h"
#include "esphome/core/component.h"
#include "esphome/core/hal.h" #include "esphome/core/hal.h"
namespace esphome { namespace esphome {
@@ -34,10 +34,12 @@ enum MCP23X17GPIORegisters {
MCP23X17_OLATB = 0x15, MCP23X17_OLATB = 0x15,
}; };
class MCP23X17Base : public mcp23xxx_base::MCP23XXXBase { class MCP23X17Base : public mcp23xxx_base::MCP23XXXBase<16> {
public: public:
bool digital_read(uint8_t pin) override; bool digital_read_hw(uint8_t pin) override;
void digital_write(uint8_t pin, bool value) override; void digital_write_hw(uint8_t pin, bool value) override;
bool digital_read_cache(uint8_t pin) override;
void pin_mode(uint8_t pin, gpio::Flags flags) override; void pin_mode(uint8_t pin, gpio::Flags flags) override;
void pin_interrupt_mode(uint8_t pin, mcp23xxx_base::MCP23XXXInterruptMode interrupt_mode) override; void pin_interrupt_mode(uint8_t pin, mcp23xxx_base::MCP23XXXInterruptMode interrupt_mode) override;
@@ -46,6 +48,9 @@ class MCP23X17Base : public mcp23xxx_base::MCP23XXXBase {
uint8_t olat_a_{0x00}; uint8_t olat_a_{0x00};
uint8_t olat_b_{0x00}; uint8_t olat_b_{0x00};
/// State read in digital_read_hw
uint16_t input_mask_{0x00};
}; };
} // namespace mcp23x17_base } // namespace mcp23x17_base

View File

@@ -12,8 +12,9 @@ from esphome.const import (
CONF_OUTPUT, CONF_OUTPUT,
CONF_PULLUP, CONF_PULLUP,
) )
from esphome.core import coroutine from esphome.core import CORE, ID, coroutine
AUTO_LOAD = ["gpio_expander"]
CODEOWNERS = ["@jesserockz"] CODEOWNERS = ["@jesserockz"]
mcp23xxx_base_ns = cg.esphome_ns.namespace("mcp23xxx_base") mcp23xxx_base_ns = cg.esphome_ns.namespace("mcp23xxx_base")
@@ -36,9 +37,11 @@ MCP23XXX_CONFIG_SCHEMA = cv.Schema(
@coroutine @coroutine
async def register_mcp23xxx(config): async def register_mcp23xxx(config, num_pins):
var = cg.new_Pvariable(config[CONF_ID]) id: ID = config[CONF_ID]
var = cg.new_Pvariable(id)
await cg.register_component(var, config) await cg.register_component(var, config)
CORE.data.setdefault(CONF_MCP23XXX, {})[id.id] = num_pins
cg.add(var.set_open_drain_ints(config[CONF_OPEN_DRAIN_INTERRUPT])) cg.add(var.set_open_drain_ints(config[CONF_OPEN_DRAIN_INTERRUPT]))
return var return var
@@ -73,9 +76,12 @@ MCP23XXX_PIN_SCHEMA = pins.gpio_base_schema(
@pins.PIN_SCHEMA_REGISTRY.register(CONF_MCP23XXX, MCP23XXX_PIN_SCHEMA) @pins.PIN_SCHEMA_REGISTRY.register(CONF_MCP23XXX, MCP23XXX_PIN_SCHEMA)
async def mcp23xxx_pin_to_code(config): async def mcp23xxx_pin_to_code(config):
var = cg.new_Pvariable(config[CONF_ID]) parent_id: ID = config[CONF_MCP23XXX]
parent = await cg.get_variable(config[CONF_MCP23XXX]) parent = await cg.get_variable(parent_id)
num_pins = cg.TemplateArguments(CORE.data[CONF_MCP23XXX][parent_id.id])
var = cg.new_Pvariable(config[CONF_ID], num_pins)
cg.add(var.set_parent(parent)) cg.add(var.set_parent(parent))
num = config[CONF_NUMBER] num = config[CONF_NUMBER]

View File

@@ -1,24 +1,27 @@
#include "mcp23xxx_base.h" #include "mcp23xxx_base.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h" #include "esphome/core/log.h"
namespace esphome { namespace esphome {
namespace mcp23xxx_base { namespace mcp23xxx_base {
float MCP23XXXBase::get_setup_priority() const { return setup_priority::IO; } template<uint8_t N> void MCP23XXXGPIOPin<N>::setup() {
this->pin_mode(flags_);
void MCP23XXXGPIOPin::setup() {
pin_mode(flags_);
this->parent_->pin_interrupt_mode(this->pin_, this->interrupt_mode_); this->parent_->pin_interrupt_mode(this->pin_, this->interrupt_mode_);
} }
template<uint8_t N> void MCP23XXXGPIOPin<N>::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); }
void MCP23XXXGPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); } template<uint8_t N> bool MCP23XXXGPIOPin<N>::digital_read() {
bool MCP23XXXGPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; } return this->parent_->digital_read(this->pin_) != this->inverted_;
void MCP23XXXGPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); }
std::string MCP23XXXGPIOPin::dump_summary() const {
char buffer[32];
snprintf(buffer, sizeof(buffer), "%u via MCP23XXX", pin_);
return buffer;
} }
template<uint8_t N> void MCP23XXXGPIOPin<N>::digital_write(bool value) {
this->parent_->digital_write(this->pin_, value != this->inverted_);
}
template<uint8_t N> std::string MCP23XXXGPIOPin<N>::dump_summary() const {
return str_snprintf("%u via MCP23XXX", 15, pin_);
}
template class MCP23XXXGPIOPin<8>;
template class MCP23XXXGPIOPin<16>;
} // namespace mcp23xxx_base } // namespace mcp23xxx_base
} // namespace esphome } // namespace esphome

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "esphome/components/gpio_expander/cached_gpio.h"
#include "esphome/core/component.h" #include "esphome/core/component.h"
#include "esphome/core/hal.h" #include "esphome/core/hal.h"
@@ -8,15 +9,15 @@ namespace mcp23xxx_base {
enum MCP23XXXInterruptMode : uint8_t { MCP23XXX_NO_INTERRUPT = 0, MCP23XXX_CHANGE, MCP23XXX_RISING, MCP23XXX_FALLING }; enum MCP23XXXInterruptMode : uint8_t { MCP23XXX_NO_INTERRUPT = 0, MCP23XXX_CHANGE, MCP23XXX_RISING, MCP23XXX_FALLING };
class MCP23XXXBase : public Component { template<uint8_t N> class MCP23XXXBase : public Component, public gpio_expander::CachedGpioExpander<uint8_t, N> {
public: public:
virtual bool digital_read(uint8_t pin);
virtual void digital_write(uint8_t pin, bool value);
virtual void pin_mode(uint8_t pin, gpio::Flags flags); virtual void pin_mode(uint8_t pin, gpio::Flags flags);
virtual void pin_interrupt_mode(uint8_t pin, MCP23XXXInterruptMode interrupt_mode); virtual void pin_interrupt_mode(uint8_t pin, MCP23XXXInterruptMode interrupt_mode);
void set_open_drain_ints(const bool value) { this->open_drain_ints_ = value; } void set_open_drain_ints(const bool value) { this->open_drain_ints_ = value; }
float get_setup_priority() const override; float get_setup_priority() const override { return setup_priority::IO; }
void loop() override { this->reset_pin_cache_(); }
protected: protected:
// read a given register // read a given register
@@ -29,7 +30,7 @@ class MCP23XXXBase : public Component {
bool open_drain_ints_; bool open_drain_ints_;
}; };
class MCP23XXXGPIOPin : public GPIOPin { template<uint8_t N> class MCP23XXXGPIOPin : public GPIOPin {
public: public:
void setup() override; void setup() override;
void pin_mode(gpio::Flags flags) override; void pin_mode(gpio::Flags flags) override;
@@ -37,7 +38,7 @@ class MCP23XXXGPIOPin : public GPIOPin {
void digital_write(bool value) override; void digital_write(bool value) override;
std::string dump_summary() const override; std::string dump_summary() const override;
void set_parent(MCP23XXXBase *parent) { parent_ = parent; } void set_parent(MCP23XXXBase<N> *parent) { parent_ = parent; }
void set_pin(uint8_t pin) { pin_ = pin; } void set_pin(uint8_t pin) { pin_ = pin; }
void set_inverted(bool inverted) { inverted_ = inverted; } void set_inverted(bool inverted) { inverted_ = inverted; }
void set_flags(gpio::Flags flags) { flags_ = flags; } void set_flags(gpio::Flags flags) { flags_ = flags; }
@@ -46,7 +47,7 @@ class MCP23XXXGPIOPin : public GPIOPin {
gpio::Flags get_flags() const override { return this->flags_; } gpio::Flags get_flags() const override { return this->flags_; }
protected: protected:
MCP23XXXBase *parent_; MCP23XXXBase<N> *parent_;
uint8_t pin_; uint8_t pin_;
bool inverted_; bool inverted_;
gpio::Flags flags_; gpio::Flags flags_;

View File

@@ -118,8 +118,8 @@ async def register_select(var, config, *, options: list[str]):
await setup_select_core_(var, config, options=options) await setup_select_core_(var, config, options=options)
async def new_select(config, *, options: list[str]): async def new_select(config, *args, options: list[str]):
var = cg.new_Pvariable(config[CONF_ID]) var = cg.new_Pvariable(config[CONF_ID], *args)
await register_select(var, config, options=options) await register_select(var, config, options=options)
return var return var

View File

@@ -315,31 +315,19 @@ async def to_code(config):
cg.add_define("USE_AUDIO_FLAC_SUPPORT", True) cg.add_define("USE_AUDIO_FLAC_SUPPORT", True)
cg.add_define("USE_AUDIO_MP3_SUPPORT", True) cg.add_define("USE_AUDIO_MP3_SUPPORT", True)
# Wifi settings based on https://github.com/espressif/esp-adf/issues/297#issuecomment-783811702 # Based on https://github.com/espressif/esp-idf/blob/release/v5.4/examples/wifi/iperf/sdkconfig.defaults.esp32
esp32.add_idf_sdkconfig_option("CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM", 16) esp32.add_idf_sdkconfig_option("CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM", 16)
esp32.add_idf_sdkconfig_option("CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM", 512) esp32.add_idf_sdkconfig_option("CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM", 64)
esp32.add_idf_sdkconfig_option("CONFIG_ESP32_WIFI_STATIC_TX_BUFFER", True) esp32.add_idf_sdkconfig_option("CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER_NUM", 64)
esp32.add_idf_sdkconfig_option("CONFIG_ESP32_WIFI_TX_BUFFER_TYPE", 0) esp32.add_idf_sdkconfig_option("CONFIG_ESP_WIFI_AMPDU_TX_ENABLED", True)
esp32.add_idf_sdkconfig_option("CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM", 8) esp32.add_idf_sdkconfig_option("CONFIG_ESP_WIFI_TX_BA_WIN", 32)
esp32.add_idf_sdkconfig_option("CONFIG_ESP32_WIFI_CACHE_TX_BUFFER_NUM", 32) esp32.add_idf_sdkconfig_option("CONFIG_ESP_WIFI_AMPDU_RX_ENABLED", True)
esp32.add_idf_sdkconfig_option("CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED", True) esp32.add_idf_sdkconfig_option("CONFIG_ESP_WIFI_RX_BA_WIN", 32)
esp32.add_idf_sdkconfig_option("CONFIG_ESP32_WIFI_TX_BA_WIN", 16)
esp32.add_idf_sdkconfig_option("CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED", True) esp32.add_idf_sdkconfig_option("CONFIG_LWIP_TCP_SND_BUF_DEFAULT", 65534)
esp32.add_idf_sdkconfig_option("CONFIG_ESP32_WIFI_RX_BA_WIN", 32) esp32.add_idf_sdkconfig_option("CONFIG_LWIP_TCP_WND_DEFAULT", 65534)
esp32.add_idf_sdkconfig_option("CONFIG_LWIP_MAX_ACTIVE_TCP", 16) esp32.add_idf_sdkconfig_option("CONFIG_LWIP_TCP_RECVMBOX_SIZE", 64)
esp32.add_idf_sdkconfig_option("CONFIG_LWIP_MAX_LISTENING_TCP", 16) esp32.add_idf_sdkconfig_option("CONFIG_LWIP_TCPIP_RECVMBOX_SIZE", 64)
esp32.add_idf_sdkconfig_option("CONFIG_TCP_MAXRTX", 12)
esp32.add_idf_sdkconfig_option("CONFIG_TCP_SYNMAXRTX", 6)
esp32.add_idf_sdkconfig_option("CONFIG_TCP_MSS", 1436)
esp32.add_idf_sdkconfig_option("CONFIG_TCP_MSL", 60000)
esp32.add_idf_sdkconfig_option("CONFIG_TCP_SND_BUF_DEFAULT", 65535)
esp32.add_idf_sdkconfig_option("CONFIG_TCP_WND_DEFAULT", 512000)
esp32.add_idf_sdkconfig_option("CONFIG_TCP_RECVMBOX_SIZE", 512)
esp32.add_idf_sdkconfig_option("CONFIG_TCP_QUEUE_OOSEQ", True)
esp32.add_idf_sdkconfig_option("CONFIG_TCP_OVERSIZE_MSS", True)
esp32.add_idf_sdkconfig_option("CONFIG_LWIP_WND_SCALE", True)
esp32.add_idf_sdkconfig_option("CONFIG_LWIP_TCP_RCV_SCALE", 3)
esp32.add_idf_sdkconfig_option("CONFIG_LWIP_TCPIP_RECVMBOX_SIZE", 512)
# Allocate wifi buffers in PSRAM # Allocate wifi buffers in PSRAM
esp32.add_idf_sdkconfig_option("CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP", True) esp32.add_idf_sdkconfig_option("CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP", True)

View File

@@ -259,13 +259,10 @@ esp_err_t AudioPipeline::allocate_communications_() {
esp_err_t AudioPipeline::start_tasks_() { esp_err_t AudioPipeline::start_tasks_() {
if (this->read_task_handle_ == nullptr) { if (this->read_task_handle_ == nullptr) {
if (this->read_task_stack_buffer_ == nullptr) { if (this->read_task_stack_buffer_ == nullptr) {
if (this->task_stack_in_psram_) { // Reader task uses the AudioReader class which uses esp_http_client. This crashes on IDF 5.4 if the task stack is
RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_EXTERNAL); // in PSRAM. As a workaround, always allocate the read task in internal memory.
this->read_task_stack_buffer_ = stack_allocator.allocate(READ_TASK_STACK_SIZE); RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_INTERNAL);
} else { this->read_task_stack_buffer_ = stack_allocator.allocate(READ_TASK_STACK_SIZE);
RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_INTERNAL);
this->read_task_stack_buffer_ = stack_allocator.allocate(READ_TASK_STACK_SIZE);
}
} }
if (this->read_task_stack_buffer_ == nullptr) { if (this->read_task_stack_buffer_ == nullptr) {

View File

@@ -30,7 +30,7 @@ from esphome.core import CORE, coroutine_with_priority
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
CODEOWNERS = ["@OttoWinter"] CODEOWNERS = ["@esphome/core"]
IS_PLATFORM_COMPONENT = True IS_PLATFORM_COMPONENT = True
time_ns = cg.esphome_ns.namespace("time") time_ns = cg.esphome_ns.namespace("time")

View File

@@ -3,7 +3,7 @@ import esphome.config_validation as cv
from esphome.const import CONF_ID from esphome.const import CONF_ID
from esphome.core import CORE, coroutine_with_priority from esphome.core import CORE, coroutine_with_priority
CODEOWNERS = ["@OttoWinter"] CODEOWNERS = ["@esphome/core"]
DEPENDENCIES = ["network"] DEPENDENCIES = ["network"]

View File

@@ -2,7 +2,7 @@ dependencies:
espressif/esp-tflite-micro: espressif/esp-tflite-micro:
version: 1.3.3~1 version: 1.3.3~1
espressif/esp32-camera: espressif/esp32-camera:
version: 2.1.0 version: 2.1.1
espressif/mdns: espressif/mdns:
version: 1.8.2 version: 1.8.2
espressif/esp_wifi_remote: espressif/esp_wifi_remote: