#pragma once #include #include #include #include #include "esphome/core/component.h" #include "esphome/core/entity_base.h" #include "esphome/core/helpers.h" #include "esphome/core/string_ref.h" namespace esphome { namespace event { #define LOG_EVENT(prefix, type, obj) \ if ((obj) != nullptr) { \ ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \ LOG_ENTITY_ICON(TAG, prefix, *(obj)); \ LOG_ENTITY_DEVICE_CLASS(TAG, prefix, *(obj)); \ } class Event : public EntityBase { public: void trigger(const std::string &event_type); /// Set the event types supported by this event (from initializer list). void set_event_types(std::initializer_list event_types) { this->types_ = event_types; this->last_event_type_ = nullptr; // Reset when types change } /// Set the event types supported by this event (from FixedVector). void set_event_types(const FixedVector &event_types); /// Set the event types supported by this event (from vector). void set_event_types(const std::vector &event_types); // Deleted overloads to catch incorrect std::string usage at compile time with clear error messages void set_event_types(std::initializer_list event_types) = delete; void set_event_types(const FixedVector &event_types) = delete; void set_event_types(const std::vector &event_types) = delete; /// Return the event types supported by this event. const FixedVector &get_event_types() const { return this->types_; } /// Return the last triggered event type, or empty StringRef if no event triggered yet. StringRef get_last_event_type() const { return StringRef::from_maybe_nullptr(this->last_event_type_); } /// Return event type by index, or nullptr if index is out of bounds. const char *get_event_type(uint8_t index) const { return index < this->types_.size() ? this->types_[index] : nullptr; } /// Return index of last triggered event type, or max uint8_t if no event triggered yet. uint8_t get_last_event_type_index() const { if (this->last_event_type_ == nullptr) return std::numeric_limits::max(); // Most events have <3 types, uint8_t is sufficient for all reasonable scenarios const uint8_t size = static_cast(this->types_.size()); for (uint8_t i = 0; i < size; i++) { if (this->types_[i] == this->last_event_type_) return i; } return std::numeric_limits::max(); } /// Check if an event has been triggered. bool has_event() const { return this->last_event_type_ != nullptr; } template void add_on_event_callback(F &&callback) { this->event_callback_.add(std::forward(callback)); } protected: LazyCallbackManager event_callback_; FixedVector types_; private: /// Last triggered event type - must point to entry in types_ to ensure valid lifetime. /// Set by trigger() after validation, reset to nullptr when types_ changes. const char *last_event_type_{nullptr}; }; } // namespace event } // namespace esphome