mirror of
https://github.com/esphome/esphome.git
synced 2026-06-25 03:56:48 +00:00
Compare commits
1 Commits
api-server
...
improv-ser
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab233e6d83 |
@@ -13,11 +13,7 @@ from esphome.const import (
|
||||
CONF_WEB_SERVER,
|
||||
)
|
||||
from esphome.core import CORE, CoroPriority, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import (
|
||||
entity_duplicate_validator,
|
||||
queue_entity_register,
|
||||
setup_entity,
|
||||
)
|
||||
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
||||
from esphome.cpp_generator import MockObjClass
|
||||
|
||||
CODEOWNERS = ["@grahambrown11", "@hwstar"]
|
||||
@@ -185,7 +181,7 @@ async def setup_alarm_control_panel_core_(var, config):
|
||||
async def register_alarm_control_panel(var, config):
|
||||
if not CORE.has_id(config[CONF_ID]):
|
||||
var = cg.Pvariable(config[CONF_ID], var)
|
||||
queue_entity_register("alarm_control_panel", config)
|
||||
cg.add(cg.App.register_alarm_control_panel(var))
|
||||
CORE.register_platform_component("alarm_control_panel", var)
|
||||
await setup_alarm_control_panel_core_(var, config)
|
||||
|
||||
|
||||
@@ -30,11 +30,6 @@ APIServer *global_api_server = nullptr; // NOLINT(cppcoreguidelines-avoid-non-c
|
||||
|
||||
APIServer::APIServer() { global_api_server = this; }
|
||||
|
||||
// Custom deleter defined here so `delete` sees the complete APIConnection type.
|
||||
// This prevents libc++ from emitting an "incomplete type" error when other
|
||||
// translation units only have the forward declaration of APIConnection.
|
||||
void APIServer::APIConnectionDeleter::operator()(APIConnection *p) const { delete p; }
|
||||
|
||||
void APIServer::socket_failed_(const LogString *msg) {
|
||||
ESP_LOGW(TAG, "Socket %s: errno %d", LOG_STR_ARG(msg), errno);
|
||||
this->destroy_socket_();
|
||||
|
||||
@@ -193,13 +193,7 @@ class APIServer final : public Component,
|
||||
// Range-for view over the populated slice [0, api_connection_count_). Read-only with respect
|
||||
// to ownership — callers get `const unique_ptr&` so they can invoke non-const methods on the
|
||||
// APIConnection but cannot reset/move the slot and break the count invariant.
|
||||
// Custom deleter is defined out-of-line in api_server.cpp so libc++ does not
|
||||
// eagerly instantiate `delete static_cast<APIConnection *>(p)` here, where
|
||||
// only the forward declaration of APIConnection is visible (incomplete type).
|
||||
struct APIConnectionDeleter {
|
||||
void operator()(APIConnection *p) const;
|
||||
};
|
||||
using APIConnectionPtr = std::unique_ptr<APIConnection, APIConnectionDeleter>;
|
||||
using APIConnectionPtr = std::unique_ptr<APIConnection>;
|
||||
class ActiveClientsView {
|
||||
const APIConnectionPtr *begin_;
|
||||
const APIConnectionPtr *end_;
|
||||
@@ -298,7 +292,7 @@ class APIServer final : public Component,
|
||||
uint32_t last_connected_{0};
|
||||
|
||||
// Slots [0, api_connection_count_) are populated; trailing slots are always nullptr.
|
||||
std::array<APIConnectionPtr, MAX_API_CONNECTIONS> clients_{};
|
||||
std::array<std::unique_ptr<APIConnection>, MAX_API_CONNECTIONS> clients_{};
|
||||
// Vectors and strings (12 bytes each on 32-bit)
|
||||
// Shared proto write buffer for all connections.
|
||||
// Not pre-allocated: all send paths call prepare_first_message_buffer() which
|
||||
|
||||
@@ -62,7 +62,6 @@ from esphome.const import (
|
||||
from esphome.core import CORE, CoroPriority, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import (
|
||||
entity_duplicate_validator,
|
||||
queue_entity_register,
|
||||
setup_device_class,
|
||||
setup_entity,
|
||||
)
|
||||
@@ -625,7 +624,7 @@ async def setup_binary_sensor_core_(var, config):
|
||||
async def register_binary_sensor(var, config):
|
||||
if not CORE.has_id(config[CONF_ID]):
|
||||
var = cg.Pvariable(config[CONF_ID], var)
|
||||
queue_entity_register("binary_sensor", config)
|
||||
cg.add(cg.App.register_binary_sensor(var))
|
||||
CORE.register_platform_component("binary_sensor", var)
|
||||
await setup_binary_sensor_core_(var, config)
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ from esphome.const import (
|
||||
from esphome.core import CORE, CoroPriority, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import (
|
||||
entity_duplicate_validator,
|
||||
queue_entity_register,
|
||||
setup_device_class,
|
||||
setup_entity,
|
||||
)
|
||||
@@ -102,7 +101,7 @@ async def setup_button_core_(var, config):
|
||||
async def register_button(var, config):
|
||||
if not CORE.has_id(config[CONF_ID]):
|
||||
var = cg.Pvariable(config[CONF_ID], var)
|
||||
queue_entity_register("button", config)
|
||||
cg.add(cg.App.register_button(var))
|
||||
CORE.register_platform_component("button", var)
|
||||
await setup_button_core_(var, config)
|
||||
|
||||
|
||||
@@ -49,11 +49,7 @@ from esphome.const import (
|
||||
CONF_WEB_SERVER,
|
||||
)
|
||||
from esphome.core import CORE, CoroPriority, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import (
|
||||
entity_duplicate_validator,
|
||||
queue_entity_register,
|
||||
setup_entity,
|
||||
)
|
||||
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
||||
from esphome.cpp_generator import MockObjClass
|
||||
|
||||
IS_PLATFORM_COMPONENT = True
|
||||
@@ -446,7 +442,7 @@ async def setup_climate_core_(var, config):
|
||||
async def register_climate(var, config):
|
||||
if not CORE.has_id(config[CONF_ID]):
|
||||
var = cg.Pvariable(config[CONF_ID], var)
|
||||
queue_entity_register("climate", config)
|
||||
cg.add(cg.App.register_climate(var))
|
||||
CORE.register_platform_component("climate", var)
|
||||
await setup_climate_core_(var, config)
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@ from esphome.const import (
|
||||
from esphome.core import CORE, ID, CoroPriority, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import (
|
||||
entity_duplicate_validator,
|
||||
queue_entity_register,
|
||||
setup_device_class,
|
||||
setup_entity,
|
||||
)
|
||||
@@ -233,7 +232,7 @@ async def setup_cover_core_(var, config):
|
||||
async def register_cover(var, config):
|
||||
if not CORE.has_id(config[CONF_ID]):
|
||||
var = cg.Pvariable(config[CONF_ID], var)
|
||||
queue_entity_register("cover", config)
|
||||
cg.add(cg.App.register_cover(var))
|
||||
CORE.register_platform_component("cover", var)
|
||||
await setup_cover_core_(var, config)
|
||||
|
||||
|
||||
@@ -22,11 +22,7 @@ from esphome.const import (
|
||||
CONF_YEAR,
|
||||
)
|
||||
from esphome.core import CORE, CoroPriority, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import (
|
||||
entity_duplicate_validator,
|
||||
queue_entity_register,
|
||||
setup_entity,
|
||||
)
|
||||
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
||||
from esphome.cpp_generator import MockObjClass
|
||||
|
||||
CODEOWNERS = ["@rfdarter", "@jesserockz"]
|
||||
@@ -164,7 +160,7 @@ async def register_datetime(var, config):
|
||||
if not CORE.has_id(config[CONF_ID]):
|
||||
var = cg.Pvariable(config[CONF_ID], var)
|
||||
entity_type = config[CONF_TYPE].lower()
|
||||
queue_entity_register(entity_type, config)
|
||||
cg.add(getattr(cg.App, f"register_{entity_type}")(var))
|
||||
CORE.register_platform_component(entity_type, var)
|
||||
await setup_datetime_core_(var, config)
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ from esphome.const import (
|
||||
from esphome.core import CORE, CoroPriority, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import (
|
||||
entity_duplicate_validator,
|
||||
queue_entity_register,
|
||||
setup_device_class,
|
||||
setup_entity,
|
||||
)
|
||||
@@ -109,7 +108,7 @@ async def setup_event_core_(var, config, *, event_types: list[str]):
|
||||
async def register_event(var, config, *, event_types: list[str]):
|
||||
if not CORE.has_id(config[CONF_ID]):
|
||||
var = cg.Pvariable(config[CONF_ID], var)
|
||||
queue_entity_register("event", config)
|
||||
cg.add(cg.App.register_event(var))
|
||||
CORE.register_platform_component("event", var)
|
||||
await setup_event_core_(var, config, event_types=event_types)
|
||||
|
||||
|
||||
@@ -32,11 +32,7 @@ from esphome.const import (
|
||||
CONF_WEB_SERVER,
|
||||
)
|
||||
from esphome.core import CORE, CoroPriority, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import (
|
||||
entity_duplicate_validator,
|
||||
queue_entity_register,
|
||||
setup_entity,
|
||||
)
|
||||
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
||||
|
||||
IS_PLATFORM_COMPONENT = True
|
||||
|
||||
@@ -296,7 +292,7 @@ async def setup_fan_core_(var, config):
|
||||
async def register_fan(var, config):
|
||||
if not CORE.has_id(config[CONF_ID]):
|
||||
var = cg.Pvariable(config[CONF_ID], var)
|
||||
queue_entity_register("fan", config)
|
||||
cg.add(cg.App.register_fan(var))
|
||||
CORE.register_platform_component("fan", var)
|
||||
await setup_fan_core_(var, config)
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ void ImprovSerialComponent::setup() {
|
||||
global_improv_serial_component = this;
|
||||
#ifdef USE_ESP32
|
||||
this->uart_num_ = logger::global_logger->get_uart_num();
|
||||
this->uart_selection_ = logger::global_logger->get_uart();
|
||||
#elif defined(USE_ARDUINO)
|
||||
this->hw_serial_ = logger::global_logger->get_hw_serial();
|
||||
#endif
|
||||
@@ -29,7 +30,8 @@ void ImprovSerialComponent::setup() {
|
||||
}
|
||||
|
||||
void ImprovSerialComponent::loop() {
|
||||
if (this->last_read_byte_ && (millis() - this->last_read_byte_ > IMPROV_SERIAL_TIMEOUT)) {
|
||||
const uint32_t now = App.get_loop_component_start_time();
|
||||
if (this->last_read_byte_ && (now - this->last_read_byte_ > IMPROV_SERIAL_TIMEOUT)) {
|
||||
this->last_read_byte_ = 0;
|
||||
this->rx_buffer_.clear();
|
||||
ESP_LOGV(TAG, "Timeout");
|
||||
@@ -38,7 +40,7 @@ void ImprovSerialComponent::loop() {
|
||||
auto byte = this->read_byte_();
|
||||
while (byte.has_value()) {
|
||||
if (this->parse_improv_serial_byte_(byte.value())) {
|
||||
this->last_read_byte_ = millis();
|
||||
this->last_read_byte_ = now;
|
||||
} else {
|
||||
this->last_read_byte_ = 0;
|
||||
this->rx_buffer_.clear();
|
||||
@@ -62,55 +64,6 @@ void ImprovSerialComponent::loop() {
|
||||
|
||||
void ImprovSerialComponent::dump_config() { ESP_LOGCONFIG(TAG, "Improv Serial:"); }
|
||||
|
||||
optional<uint8_t> ImprovSerialComponent::read_byte_() {
|
||||
optional<uint8_t> byte;
|
||||
uint8_t data = 0;
|
||||
#ifdef USE_ESP32
|
||||
switch (logger::global_logger->get_uart()) {
|
||||
case logger::UART_SELECTION_UART0:
|
||||
case logger::UART_SELECTION_UART1:
|
||||
#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) && \
|
||||
!defined(USE_ESP32_VARIANT_ESP32C61) && !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3)
|
||||
case logger::UART_SELECTION_UART2:
|
||||
#endif // !USE_ESP32_VARIANT_ESP32C3 && !USE_ESP32_VARIANT_ESP32C6 && !USE_ESP32_VARIANT_ESP32C61 &&
|
||||
// !USE_ESP32_VARIANT_ESP32S2 && !USE_ESP32_VARIANT_ESP32S3
|
||||
if (this->uart_num_ >= 0) {
|
||||
size_t available;
|
||||
uart_get_buffered_data_len(this->uart_num_, &available);
|
||||
if (available) {
|
||||
uart_read_bytes(this->uart_num_, &data, 1, 0);
|
||||
byte = data;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#if defined(USE_LOGGER_USB_CDC) && defined(CONFIG_ESP_CONSOLE_USB_CDC)
|
||||
case logger::UART_SELECTION_USB_CDC:
|
||||
if (esp_usb_console_available_for_read()) {
|
||||
esp_usb_console_read_buf((char *) &data, 1);
|
||||
byte = data;
|
||||
}
|
||||
break;
|
||||
#endif // USE_LOGGER_USB_CDC
|
||||
#ifdef USE_LOGGER_USB_SERIAL_JTAG
|
||||
case logger::UART_SELECTION_USB_SERIAL_JTAG: {
|
||||
if (usb_serial_jtag_read_bytes((char *) &data, 1, 0)) {
|
||||
byte = data;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif // USE_LOGGER_USB_SERIAL_JTAG
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#elif defined(USE_ARDUINO)
|
||||
if (this->hw_serial_->available()) {
|
||||
this->hw_serial_->readBytes(&data, 1);
|
||||
byte = data;
|
||||
}
|
||||
#endif
|
||||
return byte;
|
||||
}
|
||||
|
||||
void ImprovSerialComponent::write_data_(const uint8_t *data, const size_t size) {
|
||||
// First, set length field
|
||||
this->tx_header_[TX_LENGTH_IDX] = this->tx_header_[TX_TYPE_IDX] == TYPE_RPC_RESPONSE ? size : 1;
|
||||
@@ -134,7 +87,7 @@ void ImprovSerialComponent::write_data_(const uint8_t *data, const size_t size)
|
||||
this->tx_header_[TX_CHECKSUM_IDX] = checksum;
|
||||
|
||||
#ifdef USE_ESP32
|
||||
switch (logger::global_logger->get_uart()) {
|
||||
switch (this->uart_selection_) {
|
||||
case logger::UART_SELECTION_UART0:
|
||||
case logger::UART_SELECTION_UART1:
|
||||
#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) && \
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/components/improv_base/improv_base.h"
|
||||
#include "esphome/components/logger/logger.h"
|
||||
#include "esphome/components/wifi/wifi_component.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/defines.h"
|
||||
@@ -66,7 +67,53 @@ class ImprovSerialComponent : public Component, public improv_base::ImprovBase {
|
||||
std::vector<uint8_t> build_rpc_settings_response_(improv::Command command);
|
||||
std::vector<uint8_t> build_version_info_();
|
||||
|
||||
optional<uint8_t> read_byte_();
|
||||
ESPHOME_ALWAYS_INLINE optional<uint8_t> read_byte_() {
|
||||
optional<uint8_t> byte;
|
||||
uint8_t data = 0;
|
||||
#ifdef USE_ESP32
|
||||
switch (this->uart_selection_) {
|
||||
case logger::UART_SELECTION_UART0:
|
||||
case logger::UART_SELECTION_UART1:
|
||||
#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) && \
|
||||
!defined(USE_ESP32_VARIANT_ESP32C61) && !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3)
|
||||
case logger::UART_SELECTION_UART2:
|
||||
#endif
|
||||
if (this->uart_num_ >= 0) {
|
||||
size_t available;
|
||||
uart_get_buffered_data_len(this->uart_num_, &available);
|
||||
if (available) {
|
||||
uart_read_bytes(this->uart_num_, &data, 1, 0);
|
||||
byte = data;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#if defined(USE_LOGGER_USB_CDC) && defined(CONFIG_ESP_CONSOLE_USB_CDC)
|
||||
case logger::UART_SELECTION_USB_CDC:
|
||||
if (esp_usb_console_available_for_read()) {
|
||||
esp_usb_console_read_buf((char *) &data, 1);
|
||||
byte = data;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef USE_LOGGER_USB_SERIAL_JTAG
|
||||
case logger::UART_SELECTION_USB_SERIAL_JTAG: {
|
||||
if (usb_serial_jtag_read_bytes((char *) &data, 1, 0)) {
|
||||
byte = data;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#elif defined(USE_ARDUINO)
|
||||
if (this->hw_serial_->available()) {
|
||||
this->hw_serial_->readBytes(&data, 1);
|
||||
byte = data;
|
||||
}
|
||||
#endif
|
||||
return byte;
|
||||
}
|
||||
void write_data_(const uint8_t *data = nullptr, size_t size = 0);
|
||||
|
||||
uint8_t tx_header_[TX_BUFFER_SIZE] = {
|
||||
@@ -86,6 +133,7 @@ class ImprovSerialComponent : public Component, public improv_base::ImprovBase {
|
||||
|
||||
#ifdef USE_ESP32
|
||||
uart_port_t uart_num_;
|
||||
logger::UARTSelection uart_selection_{logger::UART_SELECTION_UART0};
|
||||
#elif defined(USE_ARDUINO)
|
||||
Stream *hw_serial_{nullptr};
|
||||
#endif
|
||||
|
||||
@@ -12,7 +12,7 @@ import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_ID
|
||||
from esphome.core import CORE, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import queue_entity_register, setup_entity
|
||||
from esphome.core.entity_helpers import setup_entity
|
||||
from esphome.coroutine import CoroPriority
|
||||
from esphome.types import ConfigType
|
||||
|
||||
@@ -54,8 +54,8 @@ async def register_infrared(var: cg.Pvariable, config: ConfigType) -> None:
|
||||
"""Register an infrared device with the core."""
|
||||
cg.add_define("USE_IR_RF")
|
||||
await cg.register_component(var, config)
|
||||
queue_entity_register("infrared", config)
|
||||
await setup_infrared_core_(var, config)
|
||||
cg.add(cg.App.register_infrared(var))
|
||||
CORE.register_platform_component("infrared", var)
|
||||
|
||||
|
||||
|
||||
@@ -40,11 +40,7 @@ from esphome.const import (
|
||||
CONF_WHITE,
|
||||
)
|
||||
from esphome.core import CORE, ID, CoroPriority, HexInt, Lambda, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import (
|
||||
entity_duplicate_validator,
|
||||
queue_entity_register,
|
||||
setup_entity,
|
||||
)
|
||||
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
||||
from esphome.cpp_generator import MockObjClass
|
||||
import esphome.final_validate as fv
|
||||
from esphome.types import ConfigType
|
||||
@@ -409,7 +405,7 @@ async def setup_light_core_(light_var, config, output_var):
|
||||
|
||||
async def register_light(output_var, config):
|
||||
light_var = cg.new_Pvariable(config[CONF_ID], output_var)
|
||||
queue_entity_register("light", config)
|
||||
cg.add(cg.App.register_light(light_var))
|
||||
CORE.register_platform_component("light", light_var)
|
||||
await cg.register_component(light_var, config)
|
||||
await setup_light_core_(light_var, config, output_var)
|
||||
|
||||
@@ -13,11 +13,7 @@ from esphome.const import (
|
||||
CONF_WEB_SERVER,
|
||||
)
|
||||
from esphome.core import CORE, CoroPriority, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import (
|
||||
entity_duplicate_validator,
|
||||
queue_entity_register,
|
||||
setup_entity,
|
||||
)
|
||||
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
||||
from esphome.cpp_generator import MockObjClass
|
||||
|
||||
CODEOWNERS = ["@esphome/core"]
|
||||
@@ -116,7 +112,7 @@ async def _setup_lock_core(var, config):
|
||||
async def register_lock(var, config):
|
||||
if not CORE.has_id(config[CONF_ID]):
|
||||
var = cg.Pvariable(config[CONF_ID], var)
|
||||
queue_entity_register("lock", config)
|
||||
cg.add(cg.App.register_lock(var))
|
||||
CORE.register_platform_component("lock", var)
|
||||
await _setup_lock_core(var, config)
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ from esphome.core import CORE
|
||||
from esphome.core.entity_helpers import (
|
||||
entity_duplicate_validator,
|
||||
inherit_property_from,
|
||||
queue_entity_register,
|
||||
setup_entity,
|
||||
)
|
||||
from esphome.coroutine import CoroPriority, coroutine_with_priority
|
||||
@@ -263,7 +262,7 @@ async def setup_media_player_core_(var, config):
|
||||
async def register_media_player(var, config):
|
||||
if not CORE.has_id(config[CONF_ID]):
|
||||
var = cg.Pvariable(config[CONF_ID], var)
|
||||
queue_entity_register("media_player", config)
|
||||
cg.add(cg.App.register_media_player(var))
|
||||
CORE.register_platform_component("media_player", var)
|
||||
await setup_media_player_core_(var, config)
|
||||
|
||||
|
||||
@@ -82,7 +82,6 @@ from esphome.core import CORE, CoroPriority, coroutine_with_priority
|
||||
from esphome.core.config import UNIT_OF_MEASUREMENT_MAX_LENGTH
|
||||
from esphome.core.entity_helpers import (
|
||||
entity_duplicate_validator,
|
||||
queue_entity_register,
|
||||
setup_device_class,
|
||||
setup_entity,
|
||||
setup_unit_of_measurement,
|
||||
@@ -302,7 +301,7 @@ async def register_number(
|
||||
):
|
||||
if not CORE.has_id(config[CONF_ID]):
|
||||
var = cg.Pvariable(config[CONF_ID], var)
|
||||
queue_entity_register("number", config)
|
||||
cg.add(cg.App.register_number(var))
|
||||
CORE.register_platform_component("number", var)
|
||||
await setup_number_core_(
|
||||
var, config, min_value=min_value, max_value=max_value, step=step
|
||||
|
||||
@@ -12,7 +12,7 @@ import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_ID
|
||||
from esphome.core import CORE, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import queue_entity_register, setup_entity
|
||||
from esphome.core.entity_helpers import setup_entity
|
||||
from esphome.coroutine import CoroPriority
|
||||
from esphome.types import ConfigType
|
||||
|
||||
@@ -55,8 +55,8 @@ async def register_radio_frequency(var: cg.Pvariable, config: ConfigType) -> Non
|
||||
"""Register a radio frequency device with the core."""
|
||||
cg.add_define("USE_RADIO_FREQUENCY")
|
||||
await cg.register_component(var, config)
|
||||
queue_entity_register("radio_frequency", config)
|
||||
await setup_radio_frequency_core_(var, config)
|
||||
cg.add(cg.App.register_radio_frequency(var))
|
||||
CORE.register_platform_component("radio_frequency", var)
|
||||
|
||||
|
||||
|
||||
@@ -19,11 +19,7 @@ from esphome.const import (
|
||||
CONF_WEB_SERVER,
|
||||
)
|
||||
from esphome.core import CORE, ID, CoroPriority, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import (
|
||||
entity_duplicate_validator,
|
||||
queue_entity_register,
|
||||
setup_entity,
|
||||
)
|
||||
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
||||
from esphome.cpp_generator import MockObjClass, TemplateArguments
|
||||
from esphome.cpp_types import global_ns
|
||||
|
||||
@@ -117,7 +113,7 @@ async def setup_select_core_(var, config, *, options: list[str]):
|
||||
async def register_select(var, config, *, options: list[str]):
|
||||
if not CORE.has_id(config[CONF_ID]):
|
||||
var = cg.Pvariable(config[CONF_ID], var)
|
||||
queue_entity_register("select", config)
|
||||
cg.add(cg.App.register_select(var))
|
||||
CORE.register_platform_component("select", var)
|
||||
await setup_select_core_(var, config, options=options)
|
||||
|
||||
|
||||
@@ -109,7 +109,6 @@ from esphome.core import CORE, CoroPriority, coroutine_with_priority
|
||||
from esphome.core.config import UNIT_OF_MEASUREMENT_MAX_LENGTH
|
||||
from esphome.core.entity_helpers import (
|
||||
entity_duplicate_validator,
|
||||
queue_entity_register,
|
||||
setup_device_class,
|
||||
setup_entity,
|
||||
setup_unit_of_measurement,
|
||||
@@ -983,7 +982,7 @@ async def setup_sensor_core_(var, config):
|
||||
async def register_sensor(var, config):
|
||||
if not CORE.has_id(config[CONF_ID]):
|
||||
var = cg.Pvariable(config[CONF_ID], var)
|
||||
queue_entity_register("sensor", config)
|
||||
cg.add(cg.App.register_sensor(var))
|
||||
CORE.register_platform_component("sensor", var)
|
||||
await setup_sensor_core_(var, config)
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ from esphome.const import (
|
||||
from esphome.core import CORE, CoroPriority, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import (
|
||||
entity_duplicate_validator,
|
||||
queue_entity_register,
|
||||
setup_device_class,
|
||||
setup_entity,
|
||||
)
|
||||
@@ -167,7 +166,7 @@ async def setup_switch_core_(var, config):
|
||||
async def register_switch(var, config):
|
||||
if not CORE.has_id(config[CONF_ID]):
|
||||
var = cg.Pvariable(config[CONF_ID], var)
|
||||
queue_entity_register("switch", config)
|
||||
cg.add(cg.App.register_switch(var))
|
||||
CORE.register_platform_component("switch", var)
|
||||
await setup_switch_core_(var, config)
|
||||
|
||||
|
||||
@@ -14,11 +14,7 @@ from esphome.const import (
|
||||
CONF_WEB_SERVER,
|
||||
)
|
||||
from esphome.core import CORE, CoroPriority, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import (
|
||||
entity_duplicate_validator,
|
||||
queue_entity_register,
|
||||
setup_entity,
|
||||
)
|
||||
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
||||
from esphome.cpp_generator import MockObjClass
|
||||
|
||||
CODEOWNERS = ["@mauritskorse"]
|
||||
@@ -126,7 +122,7 @@ async def register_text(
|
||||
):
|
||||
if not CORE.has_id(config[CONF_ID]):
|
||||
var = cg.Pvariable(config[CONF_ID], var)
|
||||
queue_entity_register("text", config)
|
||||
cg.add(cg.App.register_text(var))
|
||||
CORE.register_platform_component("text", var)
|
||||
await setup_text_core_(
|
||||
var, config, min_length=min_length, max_length=max_length, pattern=pattern
|
||||
|
||||
@@ -22,7 +22,6 @@ from esphome.const import (
|
||||
from esphome.core import CORE, CoroPriority, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import (
|
||||
entity_duplicate_validator,
|
||||
queue_entity_register,
|
||||
setup_device_class,
|
||||
setup_entity,
|
||||
)
|
||||
@@ -222,7 +221,7 @@ async def setup_text_sensor_core_(var, config):
|
||||
async def register_text_sensor(var, config):
|
||||
if not CORE.has_id(config[CONF_ID]):
|
||||
var = cg.Pvariable(config[CONF_ID], var)
|
||||
queue_entity_register("text_sensor", config)
|
||||
cg.add(cg.App.register_text_sensor(var))
|
||||
CORE.register_platform_component("text_sensor", var)
|
||||
await setup_text_sensor_core_(var, config)
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ from esphome.const import (
|
||||
from esphome.core import CORE, CoroPriority, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import (
|
||||
entity_duplicate_validator,
|
||||
queue_entity_register,
|
||||
setup_device_class,
|
||||
setup_entity,
|
||||
)
|
||||
@@ -114,7 +113,7 @@ async def setup_update_core_(var, config):
|
||||
async def register_update(var, config):
|
||||
if not CORE.has_id(config[CONF_ID]):
|
||||
var = cg.Pvariable(config[CONF_ID], var)
|
||||
queue_entity_register("update", config)
|
||||
cg.add(cg.App.register_update(var))
|
||||
CORE.register_platform_component("update", var)
|
||||
await setup_update_core_(var, config)
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ from esphome.const import (
|
||||
from esphome.core import CORE, CoroPriority, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import (
|
||||
entity_duplicate_validator,
|
||||
queue_entity_register,
|
||||
setup_device_class,
|
||||
setup_entity,
|
||||
)
|
||||
@@ -163,7 +162,7 @@ async def _setup_valve_core(var, config):
|
||||
async def register_valve(var, config):
|
||||
if not CORE.has_id(config[CONF_ID]):
|
||||
var = cg.Pvariable(config[CONF_ID], var)
|
||||
queue_entity_register("valve", config)
|
||||
cg.add(cg.App.register_valve(var))
|
||||
CORE.register_platform_component("valve", var)
|
||||
await _setup_valve_core(var, config)
|
||||
|
||||
|
||||
@@ -9,11 +9,7 @@ from esphome.const import (
|
||||
CONF_VISUAL,
|
||||
)
|
||||
from esphome.core import CORE, CoroPriority, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import (
|
||||
entity_duplicate_validator,
|
||||
queue_entity_register,
|
||||
setup_entity,
|
||||
)
|
||||
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
||||
from esphome.cpp_generator import MockObjClass
|
||||
from esphome.types import ConfigType
|
||||
|
||||
@@ -94,7 +90,7 @@ async def register_water_heater(var: cg.Pvariable, config: ConfigType) -> cg.Pva
|
||||
|
||||
cg.add_define("USE_WATER_HEATER")
|
||||
|
||||
queue_entity_register("water_heater", config)
|
||||
cg.add(cg.App.register_water_heater(var))
|
||||
|
||||
CORE.register_platform_component("water_heater", var)
|
||||
await setup_water_heater_core_(var, config)
|
||||
|
||||
@@ -75,13 +75,6 @@ SENSOR_SCHEMA = cv.Schema({}).extend(zephyr_sensor)
|
||||
SWITCH_SCHEMA = cv.Schema({}).extend(zephyr_switch)
|
||||
NUMBER_SCHEMA = cv.Schema({}).extend(zephyr_number)
|
||||
|
||||
|
||||
def _validate_router_sleepy(config: ConfigType) -> ConfigType:
|
||||
if config.get(CONF_ROUTER) and config.get(CONF_SLEEPY):
|
||||
raise cv.Invalid("router and sleepy are mutually exclusive")
|
||||
return config
|
||||
|
||||
|
||||
CONFIG_SCHEMA = cv.All(
|
||||
cv.Schema(
|
||||
{
|
||||
@@ -89,7 +82,10 @@ CONFIG_SCHEMA = cv.All(
|
||||
cv.Optional(CONF_MODEL, default=CORE.name): cv.All(
|
||||
cv.string, cv.Length(max=31)
|
||||
),
|
||||
cv.Optional(CONF_ROUTER, default=False): cv.boolean,
|
||||
cv.OnlyWith(CONF_ROUTER, "esp32", default=False): cv.All(
|
||||
cv.requires_component("esp32"),
|
||||
cv.boolean,
|
||||
),
|
||||
cv.Optional(CONF_ON_JOIN): cv.All(
|
||||
cv.requires_component("nrf52"),
|
||||
automation.validate_automation(single=True),
|
||||
@@ -117,7 +113,6 @@ CONFIG_SCHEMA = cv.All(
|
||||
),
|
||||
}
|
||||
).extend(cv.COMPONENT_SCHEMA),
|
||||
_validate_router_sleepy,
|
||||
zigbee_require_vfs_select,
|
||||
zigbee_set_core_data,
|
||||
cv.Any(
|
||||
|
||||
@@ -190,9 +190,7 @@ void ZigbeeComponent::setup() {
|
||||
ESP_LOGE(TAG, "Cannot load settings, err: %d", err);
|
||||
return;
|
||||
}
|
||||
#ifdef CONFIG_ZIGBEE_ROLE_END_DEVICE
|
||||
zigbee_configure_sleepy_behavior(this->sleepy_);
|
||||
#endif
|
||||
zigbee_enable();
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,6 @@ from esphome.types import ConfigType
|
||||
from .const import (
|
||||
CONF_ON_JOIN,
|
||||
CONF_POWER_SOURCE,
|
||||
CONF_ROUTER,
|
||||
CONF_WIPE_ON_BOOT,
|
||||
KEY_ZIGBEE,
|
||||
POWER_SOURCE,
|
||||
@@ -161,10 +160,7 @@ zephyr_number = cv.Schema(
|
||||
async def zephyr_to_code(config: ConfigType) -> None:
|
||||
zephyr_add_prj_conf("ZIGBEE", True)
|
||||
zephyr_add_prj_conf("ZIGBEE_APP_UTILS", True)
|
||||
if config[CONF_ROUTER]:
|
||||
zephyr_add_prj_conf("ZIGBEE_ROLE_ROUTER", True)
|
||||
else:
|
||||
zephyr_add_prj_conf("ZIGBEE_ROLE_END_DEVICE", True)
|
||||
zephyr_add_prj_conf("ZIGBEE_ROLE_END_DEVICE", True)
|
||||
|
||||
zephyr_add_prj_conf("ZIGBEE_CHANNEL_SELECTION_MODE_MULTI", True)
|
||||
|
||||
|
||||
@@ -103,19 +103,10 @@ class Application {
|
||||
void set_current_component(Component *component) { this->current_component_ = component; }
|
||||
Component *get_current_component() { return this->current_component_; }
|
||||
|
||||
// Entity register methods (generated from entity_types.h).
|
||||
// Each entity type gets two overloads:
|
||||
// - register_<entity>(obj) — bare push_back
|
||||
// - register_<entity>(obj, name, hash, fields) — configure_entity_ + push_back
|
||||
// The 4-arg form lets codegen collapse `App.register_<entity>(obj); obj->configure_entity_(...);`
|
||||
// into a single call site, saving flash and a `main.cpp` line per entity.
|
||||
// Entity register methods (generated from entity_types.h)
|
||||
// NOLINTBEGIN(bugprone-macro-parentheses)
|
||||
#define ENTITY_TYPE_(type, singular, plural, count, upper) \
|
||||
void register_##singular(type *obj) { this->plural##_.push_back(obj); } \
|
||||
void register_##singular(type *obj, const char *name, uint32_t object_id_hash, uint32_t entity_fields) { \
|
||||
obj->configure_entity_(name, object_id_hash, entity_fields); \
|
||||
this->plural##_.push_back(obj); \
|
||||
}
|
||||
void register_##singular(type *obj) { this->plural##_.push_back(obj); }
|
||||
#define ENTITY_CONTROLLER_TYPE_(type, singular, plural, count, upper, callback) \
|
||||
ENTITY_TYPE_(type, singular, plural, count, upper)
|
||||
#include "esphome/core/entity_types.h"
|
||||
@@ -391,11 +382,7 @@ class Application {
|
||||
|
||||
/// Register a component, detecting loop() override at compile time.
|
||||
/// Uses HasLoopOverride<T> which handles ambiguous &T::loop from multiple inheritance.
|
||||
/// Optionally sets the component source index in the same call to avoid emitting
|
||||
/// a separate set_component_source_() line in generated code.
|
||||
template<typename T> void register_component_(T *comp, uint8_t source_index = 0) {
|
||||
if (source_index != 0)
|
||||
comp->set_component_source_(source_index);
|
||||
template<typename T> void register_component_(T *comp) {
|
||||
this->register_component_impl_(comp, HasLoopOverride<T>::value);
|
||||
}
|
||||
|
||||
|
||||
@@ -238,9 +238,6 @@ class EntityBase {
|
||||
protected:
|
||||
friend void ::setup();
|
||||
friend void ::original_setup();
|
||||
// Application's register_<entity>(obj, name, hash, fields) overloads call configure_entity_
|
||||
// before push_back, so codegen can emit a single combined call per entity.
|
||||
friend class Application;
|
||||
|
||||
/// Combined entity setup from codegen: set name, object_id hash, entity string indices, and flags.
|
||||
/// Bit layout of entity_fields is defined by the ENTITY_FIELD_*_SHIFT constants above.
|
||||
|
||||
@@ -23,7 +23,6 @@ from esphome.core.config import (
|
||||
UNIT_OF_MEASUREMENT_MAX_LENGTH,
|
||||
)
|
||||
from esphome.cpp_generator import MockObj, RawStatement, add, get_variable
|
||||
from esphome.cpp_types import App
|
||||
import esphome.final_validate as fv
|
||||
from esphome.helpers import cpp_string_escape, fnv1_hash_object_id, sanitize, snake_case
|
||||
from esphome.types import ConfigType, EntityMetadata
|
||||
@@ -53,12 +52,6 @@ _KEY_INTERNAL = "_entity_internal"
|
||||
_KEY_DISABLED_BY_DEFAULT = "_entity_disabled_by_default"
|
||||
_KEY_ENTITY_CATEGORY = "_entity_category"
|
||||
|
||||
# Private config key for the App.register_<method> entry point.
|
||||
# When set, finalize_entity_strings() emits a single combined call
|
||||
# `App.register_<method>(var, name, hash, packed)` instead of separate
|
||||
# `App.register_<method>(var)` and `var->configure_entity_(...)` calls.
|
||||
_KEY_REGISTER_METHOD = "_entity_register_method"
|
||||
|
||||
# Maximum unique strings per category (8-bit index, 0 = not set)
|
||||
_MAX_DEVICE_CLASSES = 0xFF # 255
|
||||
_MAX_UNITS = 0xFF # 255
|
||||
@@ -278,26 +271,11 @@ def _describe_packed_flags(config: ConfigType, entity_category: int) -> str:
|
||||
return ", ".join(parts)
|
||||
|
||||
|
||||
def queue_entity_register(method_name: str, config: ConfigType) -> None:
|
||||
"""Defer ``App.register_<method_name>(var)`` emission to ``finalize_entity_strings``.
|
||||
|
||||
When the deferred call is emitted, it is folded with ``configure_entity_`` into
|
||||
a single ``App.register_<method_name>(var, name, hash, packed)`` call site,
|
||||
which removes one statement and one method dispatch per entity from the
|
||||
generated ``main.cpp``.
|
||||
"""
|
||||
config[_KEY_REGISTER_METHOD] = method_name
|
||||
|
||||
|
||||
def finalize_entity_strings(var: MockObj, config: ConfigType) -> None:
|
||||
"""Emit the entity-registration / configure_entity_ tail.
|
||||
"""Emit a single configure_entity_() call with name, hash, packed string indices, and flags.
|
||||
|
||||
Call this at the end of each component's setup function, after
|
||||
setup_entity() and any register_device_class/register_unit_of_measurement calls.
|
||||
|
||||
If queue_entity_register() was called for this entity, emits one combined call
|
||||
``App.register_<method>(var, name, hash, packed)``. Otherwise falls back to a
|
||||
standalone ``var->configure_entity_(name, hash, packed)``.
|
||||
"""
|
||||
entity_name = config[_KEY_ENTITY_NAME]
|
||||
object_id_hash = config[_KEY_OBJECT_ID_HASH]
|
||||
@@ -317,13 +295,7 @@ def finalize_entity_strings(var: MockObj, config: ConfigType) -> None:
|
||||
)
|
||||
# Build inline comment describing the packed flags for readability
|
||||
comment = _describe_packed_flags(config, entity_category)
|
||||
register_method = config.get(_KEY_REGISTER_METHOD)
|
||||
if register_method is not None:
|
||||
expr = getattr(App, f"register_{register_method}")(
|
||||
var, entity_name, object_id_hash, packed
|
||||
)
|
||||
else:
|
||||
expr = var.configure_entity_(entity_name, object_id_hash, packed)
|
||||
expr = var.configure_entity_(entity_name, object_id_hash, packed)
|
||||
if comment:
|
||||
add(RawStatement(f"{expr}; // {comment}"))
|
||||
else:
|
||||
|
||||
@@ -197,9 +197,9 @@ async def register_component(var, config):
|
||||
)
|
||||
if name is not None:
|
||||
idx = register_component_source(name)
|
||||
add(App.register_component_(var, idx))
|
||||
else:
|
||||
add(App.register_component_(var))
|
||||
add(var.set_component_source_(idx))
|
||||
|
||||
add(App.register_component_(var))
|
||||
|
||||
# Collect C++ type for compile-time looping component count
|
||||
comp_entries = CORE.data.setdefault("looping_component_entries", [])
|
||||
|
||||
@@ -31,7 +31,7 @@ def test_binary_sensor_sets_mandatory_fields(generate_main):
|
||||
)
|
||||
|
||||
# Then
|
||||
assert 'App.register_binary_sensor(bs_1, "test bs1",' in main_cpp
|
||||
assert 'bs_1->configure_entity_("test bs1",' in main_cpp
|
||||
assert "bs_1->set_pin(" in main_cpp
|
||||
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ def test_button_sets_mandatory_fields(generate_main):
|
||||
main_cpp = generate_main("tests/component_tests/button/test_button.yaml")
|
||||
|
||||
# Then
|
||||
assert 'App.register_button(wol_1, "wol_test_1",' in main_cpp
|
||||
assert 'wol_1->configure_entity_("wol_test_1",' in main_cpp
|
||||
assert "wol_2->set_macaddr(18, 52, 86, 120, 144, 171);" in main_cpp
|
||||
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ def test_deep_sleep_setup(generate_main):
|
||||
in main_cpp
|
||||
)
|
||||
assert "new(deepsleep) deep_sleep::DeepSleepComponent();" in main_cpp
|
||||
assert "App.register_component_(deepsleep, " in main_cpp
|
||||
assert "App.register_component_(deepsleep);" in main_cpp
|
||||
|
||||
|
||||
def test_deep_sleep_sleep_duration(generate_main):
|
||||
|
||||
@@ -8,22 +8,12 @@ INTERNAL_BIT = 1 << 24
|
||||
|
||||
|
||||
def extract_packed_value(main_cpp: str, var_name: str) -> int:
|
||||
"""Extract the packed-fields argument from the entity's configure call.
|
||||
|
||||
Matches both legacy form ``var->configure_entity_(name, hash, packed)`` and the
|
||||
combined form ``App.register_<entity>(var, name, hash, packed)``.
|
||||
"""
|
||||
escaped_var = re.escape(var_name)
|
||||
legacy_pattern = (
|
||||
rf"{escaped_var}->configure_entity_\("
|
||||
"""Extract the third (packed) argument from a configure_entity_ call."""
|
||||
pattern = (
|
||||
rf"{re.escape(var_name)}->configure_entity_\("
|
||||
r'"(?:\\.|[^"\\])*"'
|
||||
r",\s*\w+,\s*(\d+)\)"
|
||||
)
|
||||
combined_pattern = (
|
||||
rf"App\.register_\w+\(\s*{escaped_var}\s*,\s*"
|
||||
r'"(?:\\.|[^"\\])*"'
|
||||
r",\s*\w+,\s*(\d+)\)"
|
||||
)
|
||||
match = re.search(combined_pattern, main_cpp) or re.search(legacy_pattern, main_cpp)
|
||||
assert match, f"configure call not found for {var_name}"
|
||||
match = re.search(pattern, main_cpp)
|
||||
assert match, f"configure_entity_ call not found for {var_name}"
|
||||
return int(match.group(1))
|
||||
|
||||
@@ -27,7 +27,7 @@ def test_web_server_ota_generated(generate_main: Callable[[str], str]) -> None:
|
||||
assert "global_web_server_base" in main_cpp
|
||||
|
||||
# Check component is registered
|
||||
assert "App.register_component_(web_server_webserverotacomponent_id" in main_cpp
|
||||
assert "App.register_component_(web_server_webserverotacomponent_id)" in main_cpp
|
||||
|
||||
|
||||
def test_web_server_ota_with_callbacks(generate_main: Callable[[str], str]) -> None:
|
||||
|
||||
@@ -28,7 +28,7 @@ def test_text_sets_mandatory_fields(generate_main):
|
||||
main_cpp = generate_main("tests/component_tests/text/test_text.yaml")
|
||||
|
||||
# Then
|
||||
assert 'App.register_text(it_1, "test 1 text",' in main_cpp
|
||||
assert 'it_1->configure_entity_("test 1 text",' in main_cpp
|
||||
|
||||
|
||||
def test_text_config_value_internal_set(generate_main):
|
||||
|
||||
@@ -28,9 +28,9 @@ def test_text_sensor_sets_mandatory_fields(generate_main):
|
||||
main_cpp = generate_main("tests/component_tests/text_sensor/test_text_sensor.yaml")
|
||||
|
||||
# Then
|
||||
assert 'App.register_text_sensor(ts_1, "Template Text Sensor 1",' in main_cpp
|
||||
assert 'App.register_text_sensor(ts_2, "Template Text Sensor 2",' in main_cpp
|
||||
assert 'App.register_text_sensor(ts_3, "Template Text Sensor 3",' in main_cpp
|
||||
assert 'ts_1->configure_entity_("Template Text Sensor 1",' in main_cpp
|
||||
assert 'ts_2->configure_entity_("Template Text Sensor 2",' in main_cpp
|
||||
assert 'ts_3->configure_entity_("Template Text Sensor 3",' in main_cpp
|
||||
|
||||
|
||||
def test_text_sensor_config_value_internal_set(generate_main):
|
||||
|
||||
@@ -1,4 +1 @@
|
||||
<<: !include common_nrf52.yaml
|
||||
|
||||
zigbee:
|
||||
router: true
|
||||
|
||||
@@ -34,9 +34,8 @@ async def test_register_component(monkeypatch):
|
||||
actual = await ch.register_component(var, {})
|
||||
|
||||
assert actual is var
|
||||
assert add_mock.call_count == 1
|
||||
app_mock.register_component_.assert_called_once()
|
||||
assert app_mock.register_component_.call_args.args[0] is var
|
||||
assert add_mock.call_count == 2
|
||||
app_mock.register_component_.assert_called_with(var)
|
||||
assert core_mock.component_ids == []
|
||||
|
||||
|
||||
@@ -78,9 +77,8 @@ async def test_register_component__with_setup_priority(monkeypatch):
|
||||
|
||||
assert actual is var
|
||||
add_mock.assert_called()
|
||||
assert add_mock.call_count == 3
|
||||
app_mock.register_component_.assert_called_once()
|
||||
assert app_mock.register_component_.call_args.args[0] is var
|
||||
assert add_mock.call_count == 4
|
||||
app_mock.register_component_.assert_called_with(var)
|
||||
assert core_mock.component_ids == []
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user