mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	Merge branch 'event_emitter_cleanup' into integration
This commit is contained in:
		| @@ -160,7 +160,6 @@ esphome/components/esp_ldo/* @clydebarrow | |||||||
| esphome/components/espnow/* @jesserockz | esphome/components/espnow/* @jesserockz | ||||||
| esphome/components/ethernet_info/* @gtjadsonsantos | esphome/components/ethernet_info/* @gtjadsonsantos | ||||||
| esphome/components/event/* @nohat | esphome/components/event/* @nohat | ||||||
| esphome/components/event_emitter/* @Rapsssito |  | ||||||
| esphome/components/exposure_notifications/* @OttoWinter | esphome/components/exposure_notifications/* @OttoWinter | ||||||
| esphome/components/ezo/* @ssieb | esphome/components/ezo/* @ssieb | ||||||
| esphome/components/ezo_pmp/* @carlos-sarmiento | esphome/components/ezo_pmp/* @carlos-sarmiento | ||||||
|   | |||||||
| @@ -26,11 +26,12 @@ from esphome.const import ( | |||||||
| from esphome.core import CORE | from esphome.core import CORE | ||||||
| from esphome.schema_extractors import SCHEMA_EXTRACT | from esphome.schema_extractors import SCHEMA_EXTRACT | ||||||
|  |  | ||||||
| AUTO_LOAD = ["esp32_ble", "bytebuffer", "event_emitter"] | AUTO_LOAD = ["esp32_ble", "bytebuffer"] | ||||||
| CODEOWNERS = ["@jesserockz", "@clydebarrow", "@Rapsssito"] | CODEOWNERS = ["@jesserockz", "@clydebarrow", "@Rapsssito"] | ||||||
| DEPENDENCIES = ["esp32"] | DEPENDENCIES = ["esp32"] | ||||||
| DOMAIN = "esp32_ble_server" | DOMAIN = "esp32_ble_server" | ||||||
|  |  | ||||||
|  |  | ||||||
| CONF_ADVERTISE = "advertise" | CONF_ADVERTISE = "advertise" | ||||||
| CONF_APPEARANCE = "appearance" | CONF_APPEARANCE = "appearance" | ||||||
| CONF_BROADCAST = "broadcast" | CONF_BROADCAST = "broadcast" | ||||||
| @@ -504,6 +505,7 @@ async def to_code_characteristic(service_var, char_conf): | |||||||
|             parse_properties(char_conf), |             parse_properties(char_conf), | ||||||
|         ), |         ), | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     if CONF_ON_WRITE in char_conf: |     if CONF_ON_WRITE in char_conf: | ||||||
|         on_write_conf = char_conf[CONF_ON_WRITE] |         on_write_conf = char_conf[CONF_ON_WRITE] | ||||||
|         cg.add_define("USE_ESP32_BLE_SERVER_CHARACTERISTIC_ON_WRITE") |         cg.add_define("USE_ESP32_BLE_SERVER_CHARACTERISTIC_ON_WRITE") | ||||||
| @@ -583,6 +585,7 @@ async def to_code(config): | |||||||
|             [(cg.uint16, "id")], |             [(cg.uint16, "id")], | ||||||
|             config[CONF_ON_DISCONNECT], |             config[CONF_ON_DISCONNECT], | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|     cg.add_define("USE_ESP32_BLE_SERVER") |     cg.add_define("USE_ESP32_BLE_SERVER") | ||||||
|     cg.add_define("USE_ESP32_BLE_ADVERTISING") |     cg.add_define("USE_ESP32_BLE_ADVERTISING") | ||||||
|     add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True) |     add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True) | ||||||
|   | |||||||
| @@ -73,7 +73,7 @@ void BLECharacteristic::notify() { | |||||||
| void BLECharacteristic::add_descriptor(BLEDescriptor *descriptor) { | void BLECharacteristic::add_descriptor(BLEDescriptor *descriptor) { | ||||||
|   // If the descriptor is the CCCD descriptor, listen to its write event to know if the client wants to be notified |   // If the descriptor is the CCCD descriptor, listen to its write event to know if the client wants to be notified | ||||||
|   if (descriptor->get_uuid() == ESPBTUUID::from_uint16(ESP_GATT_UUID_CHAR_CLIENT_CONFIG)) { |   if (descriptor->get_uuid() == ESPBTUUID::from_uint16(ESP_GATT_UUID_CHAR_CLIENT_CONFIG)) { | ||||||
|     descriptor->on(BLEDescriptorEvt::VectorEvt::ON_WRITE, [this](const std::vector<uint8_t> &value, uint16_t conn_id) { |     descriptor->on_write([this](std::span<const uint8_t> value, uint16_t conn_id) { | ||||||
|       if (value.size() != 2) |       if (value.size() != 2) | ||||||
|         return; |         return; | ||||||
|       uint16_t cccd = encode_uint16(value[1], value[0]); |       uint16_t cccd = encode_uint16(value[1], value[0]); | ||||||
| @@ -208,8 +208,9 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt | |||||||
|       if (!param->read.need_rsp) |       if (!param->read.need_rsp) | ||||||
|         break;  // For some reason you can request a read but not want a response |         break;  // For some reason you can request a read but not want a response | ||||||
|  |  | ||||||
|       this->EventEmitter<BLECharacteristicEvt::EmptyEvt, uint16_t>::emit_(BLECharacteristicEvt::EmptyEvt::ON_READ, |       if (this->on_read_callback_) { | ||||||
|                                                                           param->read.conn_id); |         (*this->on_read_callback_)(param->read.conn_id); | ||||||
|  |       } | ||||||
|  |  | ||||||
|       uint16_t max_offset = 22; |       uint16_t max_offset = 22; | ||||||
|  |  | ||||||
| @@ -277,8 +278,9 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt | |||||||
|       } |       } | ||||||
|  |  | ||||||
|       if (!param->write.is_prep) { |       if (!param->write.is_prep) { | ||||||
|         this->EventEmitter<BLECharacteristicEvt::VectorEvt, std::vector<uint8_t>, uint16_t>::emit_( |         if (this->on_write_callback_) { | ||||||
|             BLECharacteristicEvt::VectorEvt::ON_WRITE, this->value_, param->write.conn_id); |           (*this->on_write_callback_)(this->value_, param->write.conn_id); | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       break; |       break; | ||||||
| @@ -289,8 +291,9 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt | |||||||
|         break; |         break; | ||||||
|       this->write_event_ = false; |       this->write_event_ = false; | ||||||
|       if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC) { |       if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC) { | ||||||
|         this->EventEmitter<BLECharacteristicEvt::VectorEvt, std::vector<uint8_t>, uint16_t>::emit_( |         if (this->on_write_callback_) { | ||||||
|             BLECharacteristicEvt::VectorEvt::ON_WRITE, this->value_, param->exec_write.conn_id); |           (*this->on_write_callback_)(this->value_, param->exec_write.conn_id); | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|       esp_err_t err = |       esp_err_t err = | ||||||
|           esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, nullptr); |           esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, nullptr); | ||||||
|   | |||||||
| @@ -2,10 +2,12 @@ | |||||||
|  |  | ||||||
| #include "ble_descriptor.h" | #include "ble_descriptor.h" | ||||||
| #include "esphome/components/esp32_ble/ble_uuid.h" | #include "esphome/components/esp32_ble/ble_uuid.h" | ||||||
| #include "esphome/components/event_emitter/event_emitter.h" |  | ||||||
| #include "esphome/components/bytebuffer/bytebuffer.h" | #include "esphome/components/bytebuffer/bytebuffer.h" | ||||||
|  |  | ||||||
| #include <vector> | #include <vector> | ||||||
|  | #include <span> | ||||||
|  | #include <functional> | ||||||
|  | #include <memory> | ||||||
|  |  | ||||||
| #ifdef USE_ESP32 | #ifdef USE_ESP32 | ||||||
|  |  | ||||||
| @@ -22,22 +24,10 @@ namespace esp32_ble_server { | |||||||
|  |  | ||||||
| using namespace esp32_ble; | using namespace esp32_ble; | ||||||
| using namespace bytebuffer; | using namespace bytebuffer; | ||||||
| using namespace event_emitter; |  | ||||||
|  |  | ||||||
| class BLEService; | class BLEService; | ||||||
|  |  | ||||||
| namespace BLECharacteristicEvt { | class BLECharacteristic { | ||||||
| enum VectorEvt { |  | ||||||
|   ON_WRITE, |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| enum EmptyEvt { |  | ||||||
|   ON_READ, |  | ||||||
| }; |  | ||||||
| }  // namespace BLECharacteristicEvt |  | ||||||
|  |  | ||||||
| class BLECharacteristic : public EventEmitter<BLECharacteristicEvt::VectorEvt, std::vector<uint8_t>, uint16_t>, |  | ||||||
|                           public EventEmitter<BLECharacteristicEvt::EmptyEvt, uint16_t> { |  | ||||||
|  public: |  public: | ||||||
|   BLECharacteristic(ESPBTUUID uuid, uint32_t properties); |   BLECharacteristic(ESPBTUUID uuid, uint32_t properties); | ||||||
|   ~BLECharacteristic(); |   ~BLECharacteristic(); | ||||||
| @@ -76,6 +66,15 @@ class BLECharacteristic : public EventEmitter<BLECharacteristicEvt::VectorEvt, s | |||||||
|   bool is_created(); |   bool is_created(); | ||||||
|   bool is_failed(); |   bool is_failed(); | ||||||
|  |  | ||||||
|  |   // Direct callback registration - only allocates when callback is set | ||||||
|  |   void on_write(std::function<void(std::span<const uint8_t>, uint16_t)> &&callback) { | ||||||
|  |     this->on_write_callback_ = | ||||||
|  |         std::make_unique<std::function<void(std::span<const uint8_t>, uint16_t)>>(std::move(callback)); | ||||||
|  |   } | ||||||
|  |   void on_read(std::function<void(uint16_t)> &&callback) { | ||||||
|  |     this->on_read_callback_ = std::make_unique<std::function<void(uint16_t)>>(std::move(callback)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   bool write_event_{false}; |   bool write_event_{false}; | ||||||
|   BLEService *service_{}; |   BLEService *service_{}; | ||||||
| @@ -98,6 +97,9 @@ class BLECharacteristic : public EventEmitter<BLECharacteristicEvt::VectorEvt, s | |||||||
|   void remove_client_from_notify_list_(uint16_t conn_id); |   void remove_client_from_notify_list_(uint16_t conn_id); | ||||||
|   ClientNotificationEntry *find_client_in_notify_list_(uint16_t conn_id); |   ClientNotificationEntry *find_client_in_notify_list_(uint16_t conn_id); | ||||||
|  |  | ||||||
|  |   std::unique_ptr<std::function<void(std::span<const uint8_t>, uint16_t)>> on_write_callback_; | ||||||
|  |   std::unique_ptr<std::function<void(uint16_t)>> on_read_callback_; | ||||||
|  |  | ||||||
|   esp_gatt_perm_t permissions_ = ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE; |   esp_gatt_perm_t permissions_ = ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE; | ||||||
|  |  | ||||||
|   enum State : uint8_t { |   enum State : uint8_t { | ||||||
|   | |||||||
| @@ -74,9 +74,10 @@ void BLEDescriptor::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_ | |||||||
|         break; |         break; | ||||||
|       this->value_.attr_len = param->write.len; |       this->value_.attr_len = param->write.len; | ||||||
|       memcpy(this->value_.attr_value, param->write.value, param->write.len); |       memcpy(this->value_.attr_value, param->write.value, param->write.len); | ||||||
|       this->emit_(BLEDescriptorEvt::VectorEvt::ON_WRITE, |       if (this->on_write_callback_) { | ||||||
|                   std::vector<uint8_t>(param->write.value, param->write.value + param->write.len), |         (*this->on_write_callback_)(std::span<const uint8_t>(param->write.value, param->write.len), | ||||||
|                   param->write.conn_id); |                                     param->write.conn_id); | ||||||
|  |       } | ||||||
|       break; |       break; | ||||||
|     } |     } | ||||||
|     default: |     default: | ||||||
|   | |||||||
| @@ -1,30 +1,26 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "esphome/components/esp32_ble/ble_uuid.h" | #include "esphome/components/esp32_ble/ble_uuid.h" | ||||||
| #include "esphome/components/event_emitter/event_emitter.h" |  | ||||||
| #include "esphome/components/bytebuffer/bytebuffer.h" | #include "esphome/components/bytebuffer/bytebuffer.h" | ||||||
|  |  | ||||||
| #ifdef USE_ESP32 | #ifdef USE_ESP32 | ||||||
|  |  | ||||||
| #include <esp_gatt_defs.h> | #include <esp_gatt_defs.h> | ||||||
| #include <esp_gatts_api.h> | #include <esp_gatts_api.h> | ||||||
|  | #include <span> | ||||||
|  | #include <functional> | ||||||
|  | #include <memory> | ||||||
|  |  | ||||||
| namespace esphome { | namespace esphome { | ||||||
| namespace esp32_ble_server { | namespace esp32_ble_server { | ||||||
|  |  | ||||||
| using namespace esp32_ble; | using namespace esp32_ble; | ||||||
| using namespace bytebuffer; | using namespace bytebuffer; | ||||||
| using namespace event_emitter; |  | ||||||
|  |  | ||||||
| class BLECharacteristic; | class BLECharacteristic; | ||||||
|  |  | ||||||
| namespace BLEDescriptorEvt { | // Base class for BLE descriptors | ||||||
| enum VectorEvt { | class BLEDescriptor { | ||||||
|   ON_WRITE, |  | ||||||
| }; |  | ||||||
| }  // namespace BLEDescriptorEvt |  | ||||||
|  |  | ||||||
| class BLEDescriptor : public EventEmitter<BLEDescriptorEvt::VectorEvt, std::vector<uint8_t>, uint16_t> { |  | ||||||
|  public: |  public: | ||||||
|   BLEDescriptor(ESPBTUUID uuid, uint16_t max_len = 100, bool read = true, bool write = true); |   BLEDescriptor(ESPBTUUID uuid, uint16_t max_len = 100, bool read = true, bool write = true); | ||||||
|   virtual ~BLEDescriptor(); |   virtual ~BLEDescriptor(); | ||||||
| @@ -39,6 +35,12 @@ class BLEDescriptor : public EventEmitter<BLEDescriptorEvt::VectorEvt, std::vect | |||||||
|   bool is_created() { return this->state_ == CREATED; } |   bool is_created() { return this->state_ == CREATED; } | ||||||
|   bool is_failed() { return this->state_ == FAILED; } |   bool is_failed() { return this->state_ == FAILED; } | ||||||
|  |  | ||||||
|  |   // Direct callback registration - only allocates when callback is set | ||||||
|  |   void on_write(std::function<void(std::span<const uint8_t>, uint16_t)> &&callback) { | ||||||
|  |     this->on_write_callback_ = | ||||||
|  |         std::make_unique<std::function<void(std::span<const uint8_t>, uint16_t)>>(std::move(callback)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   BLECharacteristic *characteristic_{nullptr}; |   BLECharacteristic *characteristic_{nullptr}; | ||||||
|   ESPBTUUID uuid_; |   ESPBTUUID uuid_; | ||||||
| @@ -46,6 +48,8 @@ class BLEDescriptor : public EventEmitter<BLEDescriptorEvt::VectorEvt, std::vect | |||||||
|  |  | ||||||
|   esp_attr_value_t value_{}; |   esp_attr_value_t value_{}; | ||||||
|  |  | ||||||
|  |   std::unique_ptr<std::function<void(std::span<const uint8_t>, uint16_t)>> on_write_callback_; | ||||||
|  |  | ||||||
|   esp_gatt_perm_t permissions_{}; |   esp_gatt_perm_t permissions_{}; | ||||||
|  |  | ||||||
|   enum State : uint8_t { |   enum State : uint8_t { | ||||||
|   | |||||||
| @@ -153,14 +153,18 @@ void BLEServer::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t ga | |||||||
|     case ESP_GATTS_CONNECT_EVT: { |     case ESP_GATTS_CONNECT_EVT: { | ||||||
|       ESP_LOGD(TAG, "BLE Client connected"); |       ESP_LOGD(TAG, "BLE Client connected"); | ||||||
|       this->add_client_(param->connect.conn_id); |       this->add_client_(param->connect.conn_id); | ||||||
|       this->emit_(BLEServerEvt::EmptyEvt::ON_CONNECT, param->connect.conn_id); |       if (this->on_connect_callback_) { | ||||||
|  |         (*this->on_connect_callback_)(param->connect.conn_id); | ||||||
|  |       } | ||||||
|       break; |       break; | ||||||
|     } |     } | ||||||
|     case ESP_GATTS_DISCONNECT_EVT: { |     case ESP_GATTS_DISCONNECT_EVT: { | ||||||
|       ESP_LOGD(TAG, "BLE Client disconnected"); |       ESP_LOGD(TAG, "BLE Client disconnected"); | ||||||
|       this->remove_client_(param->disconnect.conn_id); |       this->remove_client_(param->disconnect.conn_id); | ||||||
|       this->parent_->advertising_start(); |       this->parent_->advertising_start(); | ||||||
|       this->emit_(BLEServerEvt::EmptyEvt::ON_DISCONNECT, param->disconnect.conn_id); |       if (this->on_disconnect_callback_) { | ||||||
|  |         (*this->on_disconnect_callback_)(param->disconnect.conn_id); | ||||||
|  |       } | ||||||
|       break; |       break; | ||||||
|     } |     } | ||||||
|     case ESP_GATTS_REG_EVT: { |     case ESP_GATTS_REG_EVT: { | ||||||
|   | |||||||
| @@ -13,6 +13,7 @@ | |||||||
| #include <vector> | #include <vector> | ||||||
| #include <unordered_map> | #include <unordered_map> | ||||||
| #include <unordered_set> | #include <unordered_set> | ||||||
|  | #include <functional> | ||||||
|  |  | ||||||
| #ifdef USE_ESP32 | #ifdef USE_ESP32 | ||||||
|  |  | ||||||
| @@ -24,18 +25,8 @@ namespace esp32_ble_server { | |||||||
| using namespace esp32_ble; | using namespace esp32_ble; | ||||||
| using namespace bytebuffer; | using namespace bytebuffer; | ||||||
|  |  | ||||||
| namespace BLEServerEvt { | // Base class for BLE server | ||||||
| enum EmptyEvt { | class BLEServer : public Component, public GATTsEventHandler, public BLEStatusEventHandler, public Parented<ESP32BLE> { | ||||||
|   ON_CONNECT, |  | ||||||
|   ON_DISCONNECT, |  | ||||||
| }; |  | ||||||
| }  // namespace BLEServerEvt |  | ||||||
|  |  | ||||||
| class BLEServer : public Component, |  | ||||||
|                   public GATTsEventHandler, |  | ||||||
|                   public BLEStatusEventHandler, |  | ||||||
|                   public Parented<ESP32BLE>, |  | ||||||
|                   public EventEmitter<BLEServerEvt::EmptyEvt, uint16_t> { |  | ||||||
|  public: |  public: | ||||||
|   void setup() override; |   void setup() override; | ||||||
|   void loop() override; |   void loop() override; | ||||||
| @@ -65,6 +56,14 @@ class BLEServer : public Component, | |||||||
|  |  | ||||||
|   void ble_before_disabled_event_handler() override; |   void ble_before_disabled_event_handler() override; | ||||||
|  |  | ||||||
|  |   // Direct callback registration - only allocates when callback is set | ||||||
|  |   void on_connect(std::function<void(uint16_t)> &&callback) { | ||||||
|  |     this->on_connect_callback_ = std::make_unique<std::function<void(uint16_t)>>(std::move(callback)); | ||||||
|  |   } | ||||||
|  |   void on_disconnect(std::function<void(uint16_t)> &&callback) { | ||||||
|  |     this->on_disconnect_callback_ = std::make_unique<std::function<void(uint16_t)>>(std::move(callback)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   struct ServiceEntry { |   struct ServiceEntry { | ||||||
|     ESPBTUUID uuid; |     ESPBTUUID uuid; | ||||||
| @@ -77,6 +76,9 @@ class BLEServer : public Component, | |||||||
|   void add_client_(uint16_t conn_id) { this->clients_.insert(conn_id); } |   void add_client_(uint16_t conn_id) { this->clients_.insert(conn_id); } | ||||||
|   void remove_client_(uint16_t conn_id) { this->clients_.erase(conn_id); } |   void remove_client_(uint16_t conn_id) { this->clients_.erase(conn_id); } | ||||||
|  |  | ||||||
|  |   std::unique_ptr<std::function<void(uint16_t)>> on_connect_callback_; | ||||||
|  |   std::unique_ptr<std::function<void(uint16_t)>> on_disconnect_callback_; | ||||||
|  |  | ||||||
|   std::vector<uint8_t> manufacturer_data_{}; |   std::vector<uint8_t> manufacturer_data_{}; | ||||||
|   esp_gatt_if_t gatts_if_{0}; |   esp_gatt_if_t gatts_if_{0}; | ||||||
|   bool registered_{false}; |   bool registered_{false}; | ||||||
|   | |||||||
| @@ -14,9 +14,10 @@ Trigger<std::vector<uint8_t>, uint16_t> *BLETriggers::create_characteristic_on_w | |||||||
|     BLECharacteristic *characteristic) { |     BLECharacteristic *characteristic) { | ||||||
|   Trigger<std::vector<uint8_t>, uint16_t> *on_write_trigger =  // NOLINT(cppcoreguidelines-owning-memory) |   Trigger<std::vector<uint8_t>, uint16_t> *on_write_trigger =  // NOLINT(cppcoreguidelines-owning-memory) | ||||||
|       new Trigger<std::vector<uint8_t>, uint16_t>(); |       new Trigger<std::vector<uint8_t>, uint16_t>(); | ||||||
|   characteristic->EventEmitter<BLECharacteristicEvt::VectorEvt, std::vector<uint8_t>, uint16_t>::on( |   characteristic->on_write([on_write_trigger](std::span<const uint8_t> data, uint16_t id) { | ||||||
|       BLECharacteristicEvt::VectorEvt::ON_WRITE, |     // Convert span to vector for trigger | ||||||
|       [on_write_trigger](const std::vector<uint8_t> &data, uint16_t id) { on_write_trigger->trigger(data, id); }); |     on_write_trigger->trigger(std::vector<uint8_t>(data.begin(), data.end()), id); | ||||||
|  |   }); | ||||||
|   return on_write_trigger; |   return on_write_trigger; | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @@ -25,9 +26,10 @@ Trigger<std::vector<uint8_t>, uint16_t> *BLETriggers::create_characteristic_on_w | |||||||
| Trigger<std::vector<uint8_t>, uint16_t> *BLETriggers::create_descriptor_on_write_trigger(BLEDescriptor *descriptor) { | Trigger<std::vector<uint8_t>, uint16_t> *BLETriggers::create_descriptor_on_write_trigger(BLEDescriptor *descriptor) { | ||||||
|   Trigger<std::vector<uint8_t>, uint16_t> *on_write_trigger =  // NOLINT(cppcoreguidelines-owning-memory) |   Trigger<std::vector<uint8_t>, uint16_t> *on_write_trigger =  // NOLINT(cppcoreguidelines-owning-memory) | ||||||
|       new Trigger<std::vector<uint8_t>, uint16_t>(); |       new Trigger<std::vector<uint8_t>, uint16_t>(); | ||||||
|   descriptor->on( |   descriptor->on_write([on_write_trigger](std::span<const uint8_t> data, uint16_t id) { | ||||||
|       BLEDescriptorEvt::VectorEvt::ON_WRITE, |     // Convert span to vector for trigger | ||||||
|       [on_write_trigger](const std::vector<uint8_t> &data, uint16_t id) { on_write_trigger->trigger(data, id); }); |     on_write_trigger->trigger(std::vector<uint8_t>(data.begin(), data.end()), id); | ||||||
|  |   }); | ||||||
|   return on_write_trigger; |   return on_write_trigger; | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @@ -35,8 +37,7 @@ Trigger<std::vector<uint8_t>, uint16_t> *BLETriggers::create_descriptor_on_write | |||||||
| #ifdef USE_ESP32_BLE_SERVER_ON_CONNECT | #ifdef USE_ESP32_BLE_SERVER_ON_CONNECT | ||||||
| Trigger<uint16_t> *BLETriggers::create_server_on_connect_trigger(BLEServer *server) { | Trigger<uint16_t> *BLETriggers::create_server_on_connect_trigger(BLEServer *server) { | ||||||
|   Trigger<uint16_t> *on_connect_trigger = new Trigger<uint16_t>();  // NOLINT(cppcoreguidelines-owning-memory) |   Trigger<uint16_t> *on_connect_trigger = new Trigger<uint16_t>();  // NOLINT(cppcoreguidelines-owning-memory) | ||||||
|   server->on(BLEServerEvt::EmptyEvt::ON_CONNECT, |   server->on_connect([on_connect_trigger](uint16_t conn_id) { on_connect_trigger->trigger(conn_id); }); | ||||||
|              [on_connect_trigger](uint16_t conn_id) { on_connect_trigger->trigger(conn_id); }); |  | ||||||
|   return on_connect_trigger; |   return on_connect_trigger; | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @@ -44,38 +45,22 @@ Trigger<uint16_t> *BLETriggers::create_server_on_connect_trigger(BLEServer *serv | |||||||
| #ifdef USE_ESP32_BLE_SERVER_ON_DISCONNECT | #ifdef USE_ESP32_BLE_SERVER_ON_DISCONNECT | ||||||
| Trigger<uint16_t> *BLETriggers::create_server_on_disconnect_trigger(BLEServer *server) { | Trigger<uint16_t> *BLETriggers::create_server_on_disconnect_trigger(BLEServer *server) { | ||||||
|   Trigger<uint16_t> *on_disconnect_trigger = new Trigger<uint16_t>();  // NOLINT(cppcoreguidelines-owning-memory) |   Trigger<uint16_t> *on_disconnect_trigger = new Trigger<uint16_t>();  // NOLINT(cppcoreguidelines-owning-memory) | ||||||
|   server->on(BLEServerEvt::EmptyEvt::ON_DISCONNECT, |   server->on_disconnect([on_disconnect_trigger](uint16_t conn_id) { on_disconnect_trigger->trigger(conn_id); }); | ||||||
|              [on_disconnect_trigger](uint16_t conn_id) { on_disconnect_trigger->trigger(conn_id); }); |  | ||||||
|   return on_disconnect_trigger; |   return on_disconnect_trigger; | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifdef USE_ESP32_BLE_SERVER_SET_VALUE_ACTION | #ifdef USE_ESP32_BLE_SERVER_SET_VALUE_ACTION | ||||||
| void BLECharacteristicSetValueActionManager::set_listener(BLECharacteristic *characteristic, | void BLECharacteristicSetValueActionManager::set_listener(BLECharacteristic *characteristic, | ||||||
|                                                           EventEmitterListenerID listener_id, |  | ||||||
|                                                           const std::function<void()> &pre_notify_listener) { |                                                           const std::function<void()> &pre_notify_listener) { | ||||||
|   // Find and remove existing listener for this characteristic |   // Find and remove existing listener for this characteristic | ||||||
|   auto *existing = this->find_listener_(characteristic); |   auto *existing = this->find_listener_(characteristic); | ||||||
|   if (existing != nullptr) { |   if (existing != nullptr) { | ||||||
|     // Remove the previous listener |  | ||||||
|     characteristic->EventEmitter<BLECharacteristicEvt::EmptyEvt, uint16_t>::off(BLECharacteristicEvt::EmptyEvt::ON_READ, |  | ||||||
|                                                                                 existing->listener_id); |  | ||||||
|     // Remove the pre-notify listener |  | ||||||
|     this->off(BLECharacteristicSetValueActionEvt::PRE_NOTIFY, existing->pre_notify_listener_id); |  | ||||||
|     // Remove from vector |     // Remove from vector | ||||||
|     this->remove_listener_(characteristic); |     this->remove_listener_(characteristic); | ||||||
|   } |   } | ||||||
|   // Create a new listener for the pre-notify event |  | ||||||
|   EventEmitterListenerID pre_notify_listener_id = |  | ||||||
|       this->on(BLECharacteristicSetValueActionEvt::PRE_NOTIFY, |  | ||||||
|                [pre_notify_listener, characteristic](const BLECharacteristic *evt_characteristic) { |  | ||||||
|                  // Only call the pre-notify listener if the characteristic is the one we are interested in |  | ||||||
|                  if (characteristic == evt_characteristic) { |  | ||||||
|                    pre_notify_listener(); |  | ||||||
|                  } |  | ||||||
|                }); |  | ||||||
|   // Save the entry to the vector |   // Save the entry to the vector | ||||||
|   this->listeners_.push_back({characteristic, listener_id, pre_notify_listener_id}); |   this->listeners_.push_back({characteristic, pre_notify_listener}); | ||||||
| } | } | ||||||
|  |  | ||||||
| BLECharacteristicSetValueActionManager::ListenerEntry *BLECharacteristicSetValueActionManager::find_listener_( | BLECharacteristicSetValueActionManager::ListenerEntry *BLECharacteristicSetValueActionManager::find_listener_( | ||||||
|   | |||||||
| @@ -4,7 +4,6 @@ | |||||||
| #include "ble_characteristic.h" | #include "ble_characteristic.h" | ||||||
| #include "ble_descriptor.h" | #include "ble_descriptor.h" | ||||||
|  |  | ||||||
| #include "esphome/components/event_emitter/event_emitter.h" |  | ||||||
| #include "esphome/core/automation.h" | #include "esphome/core/automation.h" | ||||||
|  |  | ||||||
| #include <vector> | #include <vector> | ||||||
| @@ -18,10 +17,6 @@ namespace esp32_ble_server { | |||||||
| namespace esp32_ble_server_automations { | namespace esp32_ble_server_automations { | ||||||
|  |  | ||||||
| using namespace esp32_ble; | using namespace esp32_ble; | ||||||
| using namespace event_emitter; |  | ||||||
|  |  | ||||||
| // Invalid listener ID constant - 0 is used as sentinel value in EventEmitter |  | ||||||
| static constexpr EventEmitterListenerID INVALID_LISTENER_ID = 0; |  | ||||||
|  |  | ||||||
| class BLETriggers { | class BLETriggers { | ||||||
|  public: |  public: | ||||||
| @@ -41,38 +36,29 @@ class BLETriggers { | |||||||
| }; | }; | ||||||
|  |  | ||||||
| #ifdef USE_ESP32_BLE_SERVER_SET_VALUE_ACTION | #ifdef USE_ESP32_BLE_SERVER_SET_VALUE_ACTION | ||||||
| enum BLECharacteristicSetValueActionEvt { |  | ||||||
|   PRE_NOTIFY, |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| // Class to make sure only one BLECharacteristicSetValueAction is active at a time for each characteristic | // Class to make sure only one BLECharacteristicSetValueAction is active at a time for each characteristic | ||||||
| class BLECharacteristicSetValueActionManager | class BLECharacteristicSetValueActionManager { | ||||||
|     : public EventEmitter<BLECharacteristicSetValueActionEvt, BLECharacteristic *> { |  | ||||||
|  public: |  public: | ||||||
|   // Singleton pattern |   // Singleton pattern | ||||||
|   static BLECharacteristicSetValueActionManager *get_instance() { |   static BLECharacteristicSetValueActionManager *get_instance() { | ||||||
|     static BLECharacteristicSetValueActionManager instance; |     static BLECharacteristicSetValueActionManager instance; | ||||||
|     return &instance; |     return &instance; | ||||||
|   } |   } | ||||||
|   void set_listener(BLECharacteristic *characteristic, EventEmitterListenerID listener_id, |   void set_listener(BLECharacteristic *characteristic, const std::function<void()> &pre_notify_listener); | ||||||
|                     const std::function<void()> &pre_notify_listener); |   bool has_listener(BLECharacteristic *characteristic) { return this->find_listener_(characteristic) != nullptr; } | ||||||
|   EventEmitterListenerID get_listener(BLECharacteristic *characteristic) { |   void emit_pre_notify(BLECharacteristic *characteristic) { | ||||||
|     for (const auto &entry : this->listeners_) { |     for (const auto &entry : this->listeners_) { | ||||||
|       if (entry.characteristic == characteristic) { |       if (entry.characteristic == characteristic) { | ||||||
|         return entry.listener_id; |         entry.pre_notify_listener(); | ||||||
|  |         break; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     return INVALID_LISTENER_ID; |  | ||||||
|   } |  | ||||||
|   void emit_pre_notify(BLECharacteristic *characteristic) { |  | ||||||
|     this->emit_(BLECharacteristicSetValueActionEvt::PRE_NOTIFY, characteristic); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   struct ListenerEntry { |   struct ListenerEntry { | ||||||
|     BLECharacteristic *characteristic; |     BLECharacteristic *characteristic; | ||||||
|     EventEmitterListenerID listener_id; |     std::function<void()> pre_notify_listener; | ||||||
|     EventEmitterListenerID pre_notify_listener_id; |  | ||||||
|   }; |   }; | ||||||
|   std::vector<ListenerEntry> listeners_; |   std::vector<ListenerEntry> listeners_; | ||||||
|  |  | ||||||
| @@ -87,24 +73,22 @@ template<typename... Ts> class BLECharacteristicSetValueAction : public Action<T | |||||||
|   void set_buffer(ByteBuffer buffer) { this->set_buffer(buffer.get_data()); } |   void set_buffer(ByteBuffer buffer) { this->set_buffer(buffer.get_data()); } | ||||||
|   void play(Ts... x) override { |   void play(Ts... x) override { | ||||||
|     // If the listener is already set, do nothing |     // If the listener is already set, do nothing | ||||||
|     if (BLECharacteristicSetValueActionManager::get_instance()->get_listener(this->parent_) == this->listener_id_) |     if (BLECharacteristicSetValueActionManager::get_instance()->has_listener(this->parent_)) | ||||||
|       return; |       return; | ||||||
|     // Set initial value |     // Set initial value | ||||||
|     this->parent_->set_value(this->buffer_.value(x...)); |     this->parent_->set_value(this->buffer_.value(x...)); | ||||||
|     // Set the listener for read events |     // Set the listener for read events | ||||||
|     this->listener_id_ = this->parent_->EventEmitter<BLECharacteristicEvt::EmptyEvt, uint16_t>::on( |     this->parent_->on_read([this, x...](uint16_t id) { | ||||||
|         BLECharacteristicEvt::EmptyEvt::ON_READ, [this, x...](uint16_t id) { |       // Set the value of the characteristic every time it is read | ||||||
|           // Set the value of the characteristic every time it is read |       this->parent_->set_value(this->buffer_.value(x...)); | ||||||
|           this->parent_->set_value(this->buffer_.value(x...)); |     }); | ||||||
|         }); |  | ||||||
|     // Set the listener in the global manager so only one BLECharacteristicSetValueAction is set for each characteristic |     // Set the listener in the global manager so only one BLECharacteristicSetValueAction is set for each characteristic | ||||||
|     BLECharacteristicSetValueActionManager::get_instance()->set_listener( |     BLECharacteristicSetValueActionManager::get_instance()->set_listener( | ||||||
|         this->parent_, this->listener_id_, [this, x...]() { this->parent_->set_value(this->buffer_.value(x...)); }); |         this->parent_, [this, x...]() { this->parent_->set_value(this->buffer_.value(x...)); }); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   BLECharacteristic *parent_; |   BLECharacteristic *parent_; | ||||||
|   EventEmitterListenerID listener_id_; |  | ||||||
| }; | }; | ||||||
| #endif  // USE_ESP32_BLE_SERVER_SET_VALUE_ACTION | #endif  // USE_ESP32_BLE_SERVER_SET_VALUE_ACTION | ||||||
|  |  | ||||||
|   | |||||||
| @@ -38,8 +38,7 @@ void ESP32ImprovComponent::setup() { | |||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| #endif | #endif | ||||||
|   global_ble_server->on(BLEServerEvt::EmptyEvt::ON_DISCONNECT, |   global_ble_server->on_disconnect([this](uint16_t conn_id) { this->set_error_(improv::ERROR_NONE); }); | ||||||
|                         [this](uint16_t conn_id) { this->set_error_(improv::ERROR_NONE); }); |  | ||||||
|  |  | ||||||
|   // Start with loop disabled - will be enabled by start() when needed |   // Start with loop disabled - will be enabled by start() when needed | ||||||
|   this->disable_loop(); |   this->disable_loop(); | ||||||
| @@ -57,12 +56,11 @@ void ESP32ImprovComponent::setup_characteristics() { | |||||||
|   this->error_->add_descriptor(error_descriptor); |   this->error_->add_descriptor(error_descriptor); | ||||||
|  |  | ||||||
|   this->rpc_ = this->service_->create_characteristic(improv::RPC_COMMAND_UUID, BLECharacteristic::PROPERTY_WRITE); |   this->rpc_ = this->service_->create_characteristic(improv::RPC_COMMAND_UUID, BLECharacteristic::PROPERTY_WRITE); | ||||||
|   this->rpc_->EventEmitter<BLECharacteristicEvt::VectorEvt, std::vector<uint8_t>, uint16_t>::on( |   this->rpc_->on_write([this](std::span<const uint8_t> data, uint16_t id) { | ||||||
|       BLECharacteristicEvt::VectorEvt::ON_WRITE, [this](const std::vector<uint8_t> &data, uint16_t id) { |     if (!data.empty()) { | ||||||
|         if (!data.empty()) { |       this->incoming_data_.insert(this->incoming_data_.end(), data.begin(), data.end()); | ||||||
|           this->incoming_data_.insert(this->incoming_data_.end(), data.begin(), data.end()); |     } | ||||||
|         } |   }); | ||||||
|       }); |  | ||||||
|   BLEDescriptor *rpc_descriptor = new BLE2902(); |   BLEDescriptor *rpc_descriptor = new BLE2902(); | ||||||
|   this->rpc_->add_descriptor(rpc_descriptor); |   this->rpc_->add_descriptor(rpc_descriptor); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,5 +0,0 @@ | |||||||
| CODEOWNERS = ["@Rapsssito"] |  | ||||||
|  |  | ||||||
| # Allows event_emitter to be configured in yaml, to allow use of the C++ api. |  | ||||||
|  |  | ||||||
| CONFIG_SCHEMA = {} |  | ||||||
| @@ -1,117 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include <vector> |  | ||||||
| #include <functional> |  | ||||||
| #include <limits> |  | ||||||
|  |  | ||||||
| #include "esphome/core/log.h" |  | ||||||
|  |  | ||||||
| namespace esphome { |  | ||||||
| namespace event_emitter { |  | ||||||
|  |  | ||||||
| using EventEmitterListenerID = uint32_t; |  | ||||||
| static constexpr EventEmitterListenerID INVALID_LISTENER_ID = 0; |  | ||||||
|  |  | ||||||
| // EventEmitter class that can emit events with a specific name (it is highly recommended to use an enum class for this) |  | ||||||
| // and a list of arguments. Supports multiple listeners for each event. |  | ||||||
| template<typename EvtType, typename... Args> class EventEmitter { |  | ||||||
|  public: |  | ||||||
|   EventEmitterListenerID on(EvtType event, std::function<void(Args...)> listener) { |  | ||||||
|     EventEmitterListenerID listener_id = this->get_next_id_(); |  | ||||||
|  |  | ||||||
|     // Find or create event entry |  | ||||||
|     EventEntry *entry = this->find_or_create_event_(event); |  | ||||||
|     entry->listeners.push_back({listener_id, listener}); |  | ||||||
|  |  | ||||||
|     return listener_id; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   void off(EvtType event, EventEmitterListenerID id) { |  | ||||||
|     EventEntry *entry = this->find_event_(event); |  | ||||||
|     if (entry == nullptr) |  | ||||||
|       return; |  | ||||||
|  |  | ||||||
|     // Remove listener with given id |  | ||||||
|     for (auto it = entry->listeners.begin(); it != entry->listeners.end(); ++it) { |  | ||||||
|       if (it->id == id) { |  | ||||||
|         // Swap with last and pop for efficient removal |  | ||||||
|         *it = entry->listeners.back(); |  | ||||||
|         entry->listeners.pop_back(); |  | ||||||
|  |  | ||||||
|         // Remove event entry if no more listeners |  | ||||||
|         if (entry->listeners.empty()) { |  | ||||||
|           this->remove_event_(event); |  | ||||||
|         } |  | ||||||
|         return; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|  protected: |  | ||||||
|   void emit_(EvtType event, Args... args) { |  | ||||||
|     EventEntry *entry = this->find_event_(event); |  | ||||||
|     if (entry == nullptr) |  | ||||||
|       return; |  | ||||||
|  |  | ||||||
|     // Call all listeners for this event |  | ||||||
|     for (const auto &listener : entry->listeners) { |  | ||||||
|       listener.callback(args...); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|  private: |  | ||||||
|   struct Listener { |  | ||||||
|     EventEmitterListenerID id; |  | ||||||
|     std::function<void(Args...)> callback; |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   struct EventEntry { |  | ||||||
|     EvtType event; |  | ||||||
|     std::vector<Listener> listeners; |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   EventEmitterListenerID get_next_id_() { |  | ||||||
|     // Simple incrementing ID, wrapping around at max |  | ||||||
|     EventEmitterListenerID next_id = (this->current_id_ + 1); |  | ||||||
|     if (next_id == INVALID_LISTENER_ID) { |  | ||||||
|       next_id = 1; |  | ||||||
|     } |  | ||||||
|     this->current_id_ = next_id; |  | ||||||
|     return this->current_id_; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   EventEntry *find_event_(EvtType event) { |  | ||||||
|     for (auto &entry : this->events_) { |  | ||||||
|       if (entry.event == event) { |  | ||||||
|         return &entry; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     return nullptr; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   EventEntry *find_or_create_event_(EvtType event) { |  | ||||||
|     EventEntry *entry = this->find_event_(event); |  | ||||||
|     if (entry != nullptr) |  | ||||||
|       return entry; |  | ||||||
|  |  | ||||||
|     // Create new event entry |  | ||||||
|     this->events_.push_back({event, {}}); |  | ||||||
|     return &this->events_.back(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   void remove_event_(EvtType event) { |  | ||||||
|     for (auto it = this->events_.begin(); it != this->events_.end(); ++it) { |  | ||||||
|       if (it->event == event) { |  | ||||||
|         // Swap with last and pop |  | ||||||
|         *it = this->events_.back(); |  | ||||||
|         this->events_.pop_back(); |  | ||||||
|         return; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   std::vector<EventEntry> events_; |  | ||||||
|   EventEmitterListenerID current_id_ = 0; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| }  // namespace event_emitter |  | ||||||
| }  // namespace esphome |  | ||||||
		Reference in New Issue
	
	Block a user