mirror of
https://github.com/esphome/esphome.git
synced 2026-07-10 08:55:36 +00:00
Merge remote-tracking branch 'origin/pack-entity-strings' into integration
This commit is contained in:
@@ -48,8 +48,8 @@ void arch_init() {
|
||||
void HOT arch_feed_wdt() { esp_task_wdt_reset(); }
|
||||
|
||||
uint8_t progmem_read_byte(const uint8_t *addr) { return *addr; }
|
||||
uint16_t progmem_read_uint16(const uint16_t *addr) { return *addr; }
|
||||
const char *progmem_read_ptr(const char *const *addr) { return *addr; }
|
||||
uint16_t progmem_read_uint16(const uint16_t *addr) { return *addr; }
|
||||
uint32_t arch_get_cpu_cycle_count() { return esp_cpu_get_cycle_count(); }
|
||||
uint32_t arch_get_cpu_freq_hz() {
|
||||
uint32_t freq = 0;
|
||||
|
||||
@@ -368,16 +368,11 @@ SETTERS = {
|
||||
}
|
||||
|
||||
|
||||
@setup_entity("camera")
|
||||
async def _setup_esp32_camera(var, config):
|
||||
pass
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
cg.add_define("USE_CAMERA")
|
||||
socket.require_wake_loop_threadsafe()
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await _setup_esp32_camera(var, config)
|
||||
await setup_entity(var, config, "camera")
|
||||
await cg.register_component(var, config)
|
||||
|
||||
for key, setter in SETTERS.items():
|
||||
|
||||
@@ -34,12 +34,12 @@ void HOT arch_feed_wdt() { system_soft_wdt_feed(); }
|
||||
uint8_t progmem_read_byte(const uint8_t *addr) {
|
||||
return pgm_read_byte(addr); // NOLINT
|
||||
}
|
||||
uint16_t progmem_read_uint16(const uint16_t *addr) {
|
||||
return pgm_read_word(addr); // NOLINT
|
||||
}
|
||||
const char *progmem_read_ptr(const char *const *addr) {
|
||||
return reinterpret_cast<const char *>(pgm_read_ptr(addr)); // NOLINT
|
||||
}
|
||||
uint16_t progmem_read_uint16(const uint16_t *addr) {
|
||||
return pgm_read_word(addr); // NOLINT
|
||||
}
|
||||
uint32_t IRAM_ATTR HOT arch_get_cpu_cycle_count() { return esp_get_cycle_count(); }
|
||||
uint32_t arch_get_cpu_freq_hz() { return F_CPU; }
|
||||
|
||||
|
||||
@@ -59,8 +59,8 @@ void HOT arch_feed_wdt() {
|
||||
}
|
||||
|
||||
uint8_t progmem_read_byte(const uint8_t *addr) { return *addr; }
|
||||
uint16_t progmem_read_uint16(const uint16_t *addr) { return *addr; }
|
||||
const char *progmem_read_ptr(const char *const *addr) { return *addr; }
|
||||
uint16_t progmem_read_uint16(const uint16_t *addr) { return *addr; }
|
||||
uint32_t arch_get_cpu_cycle_count() {
|
||||
struct timespec spec;
|
||||
clock_gettime(CLOCK_MONOTONIC, &spec);
|
||||
|
||||
@@ -36,8 +36,8 @@ void HOT arch_feed_wdt() { lt_wdt_feed(); }
|
||||
uint32_t arch_get_cpu_cycle_count() { return lt_cpu_get_cycle_count(); }
|
||||
uint32_t arch_get_cpu_freq_hz() { return lt_cpu_get_freq(); }
|
||||
uint8_t progmem_read_byte(const uint8_t *addr) { return *addr; }
|
||||
uint16_t progmem_read_uint16(const uint16_t *addr) { return *addr; }
|
||||
const char *progmem_read_ptr(const char *const *addr) { return *addr; }
|
||||
uint16_t progmem_read_uint16(const uint16_t *addr) { return *addr; }
|
||||
|
||||
} // namespace esphome
|
||||
|
||||
|
||||
@@ -34,10 +34,10 @@ void HOT arch_feed_wdt() { watchdog_update(); }
|
||||
uint8_t progmem_read_byte(const uint8_t *addr) {
|
||||
return pgm_read_byte(addr); // NOLINT
|
||||
}
|
||||
uint16_t progmem_read_uint16(const uint16_t *addr) { return *addr; }
|
||||
const char *progmem_read_ptr(const char *const *addr) {
|
||||
return reinterpret_cast<const char *>(pgm_read_ptr(addr)); // NOLINT
|
||||
}
|
||||
uint16_t progmem_read_uint16(const uint16_t *addr) { return *addr; }
|
||||
uint32_t HOT arch_get_cpu_cycle_count() { return ulMainGetRunTimeCounterValue(); }
|
||||
uint32_t arch_get_cpu_freq_hz() { return RP2040::f_cpu(); }
|
||||
|
||||
|
||||
@@ -60,8 +60,8 @@ void arch_restart() { sys_reboot(SYS_REBOOT_COLD); }
|
||||
uint32_t arch_get_cpu_cycle_count() { return k_cycle_get_32(); }
|
||||
uint32_t arch_get_cpu_freq_hz() { return sys_clock_hw_cycles_per_sec(); }
|
||||
uint8_t progmem_read_byte(const uint8_t *addr) { return *addr; }
|
||||
uint16_t progmem_read_uint16(const uint16_t *addr) { return *addr; }
|
||||
const char *progmem_read_ptr(const char *const *addr) { return *addr; }
|
||||
uint16_t progmem_read_uint16(const uint16_t *addr) { return *addr; }
|
||||
|
||||
Mutex::Mutex() {
|
||||
auto *mutex = new k_mutex();
|
||||
|
||||
@@ -236,33 +236,44 @@ def get_base_entity_object_id(
|
||||
return sanitize(snake_case(base_str))
|
||||
|
||||
|
||||
def setup_entity(platform: str) -> Callable:
|
||||
"""Decorator for component setup functions.
|
||||
def setup_entity(var_or_platform, config=None, platform=None):
|
||||
"""Set up entity properties — works as both decorator and direct call.
|
||||
|
||||
Wraps the function to:
|
||||
1. Set up common entity properties (name, icon, etc.)
|
||||
2. Run the wrapped function (which may call setup_device_class, etc.)
|
||||
3. Finalize entity strings (pack dc/uom/icon indices into uint32_t)
|
||||
|
||||
Usage::
|
||||
Decorator mode::
|
||||
|
||||
@setup_entity("sensor")
|
||||
async def setup_sensor_core_(var, config):
|
||||
setup_device_class(config)
|
||||
setup_unit_of_measurement(config)
|
||||
...
|
||||
|
||||
Direct call mode (for entities with no extra string properties)::
|
||||
|
||||
await setup_entity(var, config, "camera")
|
||||
"""
|
||||
if isinstance(var_or_platform, str) and config is None:
|
||||
# Decorator mode: @setup_entity("sensor")
|
||||
platform = var_or_platform
|
||||
|
||||
def decorator(func: Callable) -> Callable:
|
||||
@functools.wraps(func)
|
||||
async def wrapper(var: MockObj, config: ConfigType, *args, **kwargs) -> None:
|
||||
await _setup_entity_impl(var, config, platform)
|
||||
await func(var, config, *args, **kwargs)
|
||||
finalize_entity_strings(var, config)
|
||||
def decorator(func: Callable) -> Callable:
|
||||
@functools.wraps(func)
|
||||
async def wrapper(
|
||||
var: MockObj, config: ConfigType, *args, **kwargs
|
||||
) -> None:
|
||||
await _setup_entity_impl(var, config, platform)
|
||||
await func(var, config, *args, **kwargs)
|
||||
finalize_entity_strings(var, config)
|
||||
|
||||
return wrapper
|
||||
return wrapper
|
||||
|
||||
return decorator
|
||||
return decorator
|
||||
|
||||
# Direct call mode: await setup_entity(var, config, "camera")
|
||||
async def _do() -> None:
|
||||
await _setup_entity_impl(var_or_platform, config, platform)
|
||||
finalize_entity_strings(var_or_platform, config)
|
||||
|
||||
return _do()
|
||||
|
||||
|
||||
async def _setup_entity_impl(var: MockObj, config: ConfigType, platform: str) -> None:
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ void arch_feed_wdt();
|
||||
uint32_t arch_get_cpu_cycle_count();
|
||||
uint32_t arch_get_cpu_freq_hz();
|
||||
uint8_t progmem_read_byte(const uint8_t *addr);
|
||||
uint16_t progmem_read_uint16(const uint16_t *addr);
|
||||
const char *progmem_read_ptr(const char *const *addr);
|
||||
uint16_t progmem_read_uint16(const uint16_t *addr);
|
||||
|
||||
} // namespace esphome
|
||||
|
||||
@@ -23,6 +23,7 @@ from esphome.core.entity_helpers import (
|
||||
_setup_entity_impl,
|
||||
entity_duplicate_validator,
|
||||
get_base_entity_object_id,
|
||||
setup_entity,
|
||||
)
|
||||
from esphome.cpp_generator import MockObj
|
||||
from esphome.helpers import sanitize, snake_case
|
||||
@@ -924,3 +925,51 @@ async def test_setup_entity_with_entity_category(
|
||||
assert any(
|
||||
'set_entity_category("diagnostic")' in expr for expr in added_expressions
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_setup_entity_direct_call(setup_test_environment: list[str]) -> None:
|
||||
"""Test setup_entity in direct call mode (legacy / backward compat)."""
|
||||
added_expressions = setup_test_environment
|
||||
|
||||
var = MockObj("camera1")
|
||||
config = {
|
||||
CONF_NAME: "My Camera",
|
||||
CONF_DISABLED_BY_DEFAULT: False,
|
||||
CONF_ICON: "mdi:camera",
|
||||
}
|
||||
|
||||
# Direct call mode: await setup_entity(var, config, "camera")
|
||||
await setup_entity(var, config, "camera")
|
||||
|
||||
# Should have called set_name
|
||||
object_id = extract_object_id_from_expressions(added_expressions)
|
||||
assert object_id == "my_camera"
|
||||
|
||||
# Icon index should have been stored and finalized
|
||||
assert config.get("_entity_icon_idx", 0) > 0
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_setup_entity_decorator_mode(setup_test_environment: list[str]) -> None:
|
||||
"""Test setup_entity in decorator mode."""
|
||||
added_expressions = setup_test_environment
|
||||
|
||||
body_called = False
|
||||
|
||||
@setup_entity("sensor")
|
||||
async def my_setup(var, config):
|
||||
nonlocal body_called
|
||||
body_called = True
|
||||
|
||||
var = MockObj("sensor1")
|
||||
config = {
|
||||
CONF_NAME: "Temperature",
|
||||
CONF_DISABLED_BY_DEFAULT: False,
|
||||
}
|
||||
|
||||
await my_setup(var, config)
|
||||
|
||||
assert body_called
|
||||
object_id = extract_object_id_from_expressions(added_expressions)
|
||||
assert object_id == "temperature"
|
||||
|
||||
Reference in New Issue
Block a user