mirror of
https://github.com/esphome/esphome.git
synced 2026-07-10 08:55:36 +00:00
Simplify to uint8_t index, add friend declarations, fix tests
- Drop 9-bit index scheme in favor of plain uint8_t (max 255 unique source names, overflow warns in Python and returns 0) - Add friend declarations for setup()/original_setup() so generated code can call protected set_component_source_() - Move get_component_log_str() out of line - Fix test mocks to provide CORE.data dict
This commit is contained in:
@@ -274,6 +274,10 @@ void Component::call() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
const LogString *Component::get_component_log_str() const {
|
||||
return this->component_source_index_ == 0 ? LOG_STR("<unknown>")
|
||||
: component_source_lookup(this->component_source_index_);
|
||||
}
|
||||
bool Component::should_warn_of_blocking(uint32_t blocking_time) {
|
||||
// Convert centisecond threshold to milliseconds for comparison
|
||||
uint32_t threshold_ms = static_cast<uint32_t>(this->warn_if_blocking_over_) * 10U;
|
||||
@@ -544,6 +548,6 @@ void clear_setup_priority_overrides() {
|
||||
#endif
|
||||
|
||||
// Weak default for component_source_lookup - overridden by generated code
|
||||
__attribute__((weak)) const LogString *component_source_lookup(uint16_t) { return LOG_STR("<unknown>"); }
|
||||
__attribute__((weak)) const LogString *component_source_lookup(uint8_t) { return LOG_STR("<unknown>"); }
|
||||
|
||||
} // namespace esphome
|
||||
|
||||
+11
-26
@@ -11,6 +11,10 @@
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/optional.h"
|
||||
|
||||
// Forward declarations for friend access from codegen-generated setup()
|
||||
void setup(); // NOLINT(readability-redundant-declaration) - may be declared in Arduino.h
|
||||
void original_setup(); // NOLINT(readability-redundant-declaration)
|
||||
|
||||
namespace esphome {
|
||||
|
||||
// Forward declaration for LogString
|
||||
@@ -79,11 +83,6 @@ inline constexpr uint8_t STATUS_LED_WARNING = 0x08;
|
||||
inline constexpr uint8_t STATUS_LED_ERROR = 0x10;
|
||||
// Component loop override flag uses bit 5 (set at registration time)
|
||||
inline constexpr uint8_t COMPONENT_HAS_LOOP = 0x20;
|
||||
// High bit of 9-bit component_source index (bit 6 of component_state_)
|
||||
inline constexpr uint8_t COMPONENT_SOURCE_HIGH_BIT = 0x40;
|
||||
// Mask for the 9th bit of the component source index (bit 8)
|
||||
inline constexpr uint16_t COMPONENT_SOURCE_INDEX_HIGH = 0x100;
|
||||
|
||||
// Remove before 2026.8.0
|
||||
enum class RetryResult { DONE, RETRY };
|
||||
|
||||
@@ -91,7 +90,7 @@ inline constexpr uint8_t WARN_IF_BLOCKING_OVER_CS = 5U; // 50ms in centiseconds
|
||||
|
||||
/// Lookup component source name by index (1-based). Generated by Python codegen.
|
||||
/// Weak default returns "<unknown>" so builds without codegen still link.
|
||||
const LogString *component_source_lookup(uint16_t index);
|
||||
const LogString *component_source_lookup(uint8_t index);
|
||||
|
||||
class Component {
|
||||
public:
|
||||
@@ -151,10 +150,7 @@ class Component {
|
||||
*/
|
||||
virtual void on_powerdown() {}
|
||||
|
||||
uint8_t get_component_state() const {
|
||||
// Mask out COMPONENT_SOURCE_HIGH_BIT — it's internal to component source indexing
|
||||
return this->component_state_ & ~COMPONENT_SOURCE_HIGH_BIT;
|
||||
}
|
||||
uint8_t get_component_state() const { return this->component_state_; }
|
||||
|
||||
/** Reset this component back to the construction state to allow setup to run again.
|
||||
*
|
||||
@@ -300,31 +296,21 @@ class Component {
|
||||
*
|
||||
* Returns LOG_STR("<unknown>") if source not set
|
||||
*/
|
||||
const LogString *get_component_log_str() const {
|
||||
uint16_t idx = this->component_source_index_;
|
||||
if (this->component_state_ & COMPONENT_SOURCE_HIGH_BIT)
|
||||
idx |= COMPONENT_SOURCE_INDEX_HIGH;
|
||||
return idx == 0 ? LOG_STR("<unknown>") : component_source_lookup(idx);
|
||||
}
|
||||
const LogString *get_component_log_str() const;
|
||||
|
||||
bool should_warn_of_blocking(uint32_t blocking_time);
|
||||
|
||||
protected:
|
||||
friend class Application;
|
||||
friend void ::setup();
|
||||
friend void ::original_setup();
|
||||
|
||||
/** Set where this component was loaded from for some debug messages.
|
||||
*
|
||||
* This is set by the ESPHome core during setup, and should not be called manually.
|
||||
* @param index 1-based index into the component source lookup table (0 = not set)
|
||||
*/
|
||||
void set_component_source_(uint16_t index) {
|
||||
this->component_source_index_ = static_cast<uint8_t>(index & 0xFF);
|
||||
if (index & COMPONENT_SOURCE_INDEX_HIGH) {
|
||||
this->component_state_ |= COMPONENT_SOURCE_HIGH_BIT;
|
||||
} else {
|
||||
this->component_state_ &= ~COMPONENT_SOURCE_HIGH_BIT;
|
||||
}
|
||||
}
|
||||
void set_component_source_(uint8_t index) { this->component_source_index_ = index; }
|
||||
|
||||
virtual void call_setup();
|
||||
void call_dump_config_();
|
||||
@@ -550,8 +536,7 @@ class Component {
|
||||
/// Bit 3: STATUS_LED_WARNING
|
||||
/// Bit 4: STATUS_LED_ERROR
|
||||
/// Bit 5: Has overridden loop() (set at registration time)
|
||||
/// Bit 6: High bit of 9-bit component_source index
|
||||
/// Bit 7: Unused - reserved for future expansion
|
||||
/// Bits 6-7: Unused - reserved for future expansion
|
||||
uint8_t component_state_{0x00};
|
||||
volatile bool pending_enable_loop_{false}; ///< ISR-safe flag for enable_loop_soon_any_context
|
||||
};
|
||||
|
||||
@@ -26,8 +26,8 @@ _LOGGER = logging.getLogger(__name__)
|
||||
|
||||
_COMPONENT_SOURCE_DOMAIN = "component_source_pool"
|
||||
|
||||
# Maximum unique component source names (9-bit index, 0 = not set)
|
||||
_MAX_COMPONENT_SOURCES = 510
|
||||
# Maximum unique component source names (8-bit index, 0 = not set)
|
||||
_MAX_COMPONENT_SOURCES = 0xFF # 255
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -71,9 +71,12 @@ def register_component_source(name: str) -> int:
|
||||
return pool.sources[name]
|
||||
idx = len(pool.sources) + 1
|
||||
if idx > _MAX_COMPONENT_SOURCES:
|
||||
raise ValueError(
|
||||
f"Too many unique component source names (max {_MAX_COMPONENT_SOURCES}), got {idx}: '{name}'"
|
||||
_LOGGER.warning(
|
||||
"Too many unique component source names (max %d), '%s' will show as '<unknown>'",
|
||||
_MAX_COMPONENT_SOURCES,
|
||||
name,
|
||||
)
|
||||
return 0
|
||||
pool.sources[name] = idx
|
||||
_ensure_source_table_registered()
|
||||
return idx
|
||||
@@ -107,7 +110,7 @@ def _generate_source_table_code(
|
||||
|
||||
entries = ", ".join(var_names)
|
||||
lines.append(f"static const char *const {table_var}[] PROGMEM = {{{entries}}};")
|
||||
lines.append(f"const LogString *{lookup_fn}(uint16_t index) {{")
|
||||
lines.append(f"const LogString *{lookup_fn}(uint8_t index) {{")
|
||||
lines.append(f' if (index == 0 || index > {count}) return LOG_STR("<unknown>");')
|
||||
lines.append(" return reinterpret_cast<const LogString *>(")
|
||||
lines.append(f" progmem_read_ptr(&{table_var}[index - 1]));")
|
||||
|
||||
@@ -23,7 +23,7 @@ async def test_register_component(monkeypatch):
|
||||
app_mock = Mock(register_component_=Mock(return_value=var))
|
||||
monkeypatch.setattr(ch, "App", app_mock)
|
||||
|
||||
core_mock = Mock(component_ids=["foo.bar"])
|
||||
core_mock = Mock(component_ids=["foo.bar"], data={})
|
||||
monkeypatch.setattr(ch, "CORE", core_mock)
|
||||
|
||||
add_mock = Mock()
|
||||
@@ -59,7 +59,7 @@ async def test_register_component__with_setup_priority(monkeypatch):
|
||||
app_mock = Mock(register_component_=Mock(return_value=var))
|
||||
monkeypatch.setattr(ch, "App", app_mock)
|
||||
|
||||
core_mock = Mock(component_ids=["foo.bar"])
|
||||
core_mock = Mock(component_ids=["foo.bar"], data={})
|
||||
monkeypatch.setattr(ch, "CORE", core_mock)
|
||||
|
||||
add_mock = Mock()
|
||||
|
||||
Reference in New Issue
Block a user