mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 15:12:06 +00:00 
			
		
		
		
	BLE loop use (#1882)
This commit is contained in:
		| @@ -20,14 +20,13 @@ void ESP32BLE::setup() { | |||||||
|   global_ble = this; |   global_ble = this; | ||||||
|   ESP_LOGCONFIG(TAG, "Setting up BLE..."); |   ESP_LOGCONFIG(TAG, "Setting up BLE..."); | ||||||
|  |  | ||||||
|   xTaskCreatePinnedToCore(ESP32BLE::ble_core_task_, |   if (!ble_setup_()) { | ||||||
|                           "ble_task",  // name |     ESP_LOGE(TAG, "BLE could not be set up"); | ||||||
|                           10000,       // stack size |     this->mark_failed(); | ||||||
|                           nullptr,     // input params |     return; | ||||||
|                           1,           // priority |   } | ||||||
|                           nullptr,     // handle, not needed |  | ||||||
|                           0            // core |   ESP_LOGD(TAG, "BLE setup complete"); | ||||||
|   ); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void ESP32BLE::mark_failed() { | void ESP32BLE::mark_failed() { | ||||||
| @@ -37,23 +36,6 @@ void ESP32BLE::mark_failed() { | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| bool ESP32BLE::can_proceed() { return this->ready_; } |  | ||||||
|  |  | ||||||
| void ESP32BLE::ble_core_task_(void *params) { |  | ||||||
|   if (!ble_setup_()) { |  | ||||||
|     ESP_LOGE(TAG, "BLE could not be set up"); |  | ||||||
|     global_ble->mark_failed(); |  | ||||||
|     return; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   global_ble->ready_ = true; |  | ||||||
|   ESP_LOGD(TAG, "BLE Setup complete"); |  | ||||||
|  |  | ||||||
|   while (true) { |  | ||||||
|     vTaskDelay(1000 / portTICK_PERIOD_MS); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| bool ESP32BLE::ble_setup_() { | bool ESP32BLE::ble_setup_() { | ||||||
|   esp_err_t err = nvs_flash_init(); |   esp_err_t err = nvs_flash_init(); | ||||||
|   if (err != ESP_OK) { |   if (err != ESP_OK) { | ||||||
| @@ -84,7 +66,7 @@ bool ESP32BLE::ble_setup_() { | |||||||
|     return false; |     return false; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (global_ble->has_server()) { |   if (this->has_server()) { | ||||||
|     err = esp_ble_gatts_register_callback(ESP32BLE::gatts_event_handler); |     err = esp_ble_gatts_register_callback(ESP32BLE::gatts_event_handler); | ||||||
|     if (err != ESP_OK) { |     if (err != ESP_OK) { | ||||||
|       ESP_LOGE(TAG, "esp_ble_gatts_register_callback failed: %d", err); |       ESP_LOGE(TAG, "esp_ble_gatts_register_callback failed: %d", err); | ||||||
| @@ -92,7 +74,7 @@ bool ESP32BLE::ble_setup_() { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (global_ble->has_client()) { |   if (this->has_client()) { | ||||||
|     err = esp_ble_gattc_register_callback(ESP32BLE::gattc_event_handler); |     err = esp_ble_gattc_register_callback(ESP32BLE::gattc_event_handler); | ||||||
|     if (err != ESP_OK) { |     if (err != ESP_OK) { | ||||||
|       ESP_LOGE(TAG, "esp_ble_gattc_register_callback failed: %d", err); |       ESP_LOGE(TAG, "esp_ble_gattc_register_callback failed: %d", err); | ||||||
| @@ -119,27 +101,28 @@ bool ESP32BLE::ble_setup_() { | |||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| // void ESP32BLE::loop() { | void ESP32BLE::loop() { | ||||||
| //   BLEEvent *ble_event = this->ble_events_.pop(); |   BLEEvent *ble_event = this->ble_events_.pop(); | ||||||
| //   while (ble_event != nullptr) { |   while (ble_event != nullptr) { | ||||||
| //     switch (ble_event->type_) { |     switch (ble_event->type_) { | ||||||
| //       case ble_event->GATTS: |       case ble_event->GATTS: | ||||||
| //         this->real_gatts_event_handler_(ble_event->event_.gatts.gatts_event, ble_event->event_.gatts.gatts_if, |         this->real_gatts_event_handler_(ble_event->event_.gatts.gatts_event, ble_event->event_.gatts.gatts_if, | ||||||
| //                                         &ble_event->event_.gatts.gatts_param); |                                         &ble_event->event_.gatts.gatts_param); | ||||||
| //         break; |         break; | ||||||
| //       case ble_event->GAP: |       case ble_event->GAP: | ||||||
| //         this->real_gap_event_handler_(ble_event->event_.gap.gap_event, &ble_event->event_.gap.gap_param); |         this->real_gap_event_handler_(ble_event->event_.gap.gap_event, &ble_event->event_.gap.gap_param); | ||||||
| //         break; |         break; | ||||||
| //       default: |       default: | ||||||
| //         break; |         break; | ||||||
| //     } |     } | ||||||
| //     delete ble_event; |     delete ble_event; | ||||||
| //     ble_event = this->ble_events_.pop(); |     ble_event = this->ble_events_.pop(); | ||||||
| //   } |   } | ||||||
| // } | } | ||||||
|  |  | ||||||
| void ESP32BLE::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) { | void ESP32BLE::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) { | ||||||
|   global_ble->real_gap_event_handler_(event, param); |   BLEEvent *new_event = new BLEEvent(event, param); | ||||||
|  |   global_ble->ble_events_.push(new_event); | ||||||
| } | } | ||||||
|  |  | ||||||
| void ESP32BLE::real_gap_event_handler_(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) { | void ESP32BLE::real_gap_event_handler_(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) { | ||||||
| @@ -152,7 +135,8 @@ void ESP32BLE::real_gap_event_handler_(esp_gap_ble_cb_event_t event, esp_ble_gap | |||||||
|  |  | ||||||
| void ESP32BLE::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, | void ESP32BLE::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, | ||||||
|                                    esp_ble_gatts_cb_param_t *param) { |                                    esp_ble_gatts_cb_param_t *param) { | ||||||
|   global_ble->real_gatts_event_handler_(event, gatts_if, param); |   BLEEvent *new_event = new BLEEvent(event, gatts_if, param); | ||||||
|  |   global_ble->ble_events_.push(new_event); | ||||||
| } | } | ||||||
|  |  | ||||||
| void ESP32BLE::real_gatts_event_handler_(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, | void ESP32BLE::real_gatts_event_handler_(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, | ||||||
|   | |||||||
| @@ -23,17 +23,14 @@ typedef struct { | |||||||
| class ESP32BLE : public Component { | class ESP32BLE : public Component { | ||||||
|  public: |  public: | ||||||
|   void setup() override; |   void setup() override; | ||||||
|   // void loop() override; |   void loop() override; | ||||||
|   void dump_config() override; |   void dump_config() override; | ||||||
|   float get_setup_priority() const override; |   float get_setup_priority() const override; | ||||||
|   void mark_failed() override; |   void mark_failed() override; | ||||||
|   bool can_proceed() override; |  | ||||||
|  |  | ||||||
|   bool has_server() { return this->server_ != nullptr; } |   bool has_server() { return this->server_ != nullptr; } | ||||||
|   bool has_client() { return false; } |   bool has_client() { return false; } | ||||||
|  |  | ||||||
|   bool is_ready() { return this->ready_; } |  | ||||||
|  |  | ||||||
|   void set_server(BLEServer *server) { this->server_ = server; } |   void set_server(BLEServer *server) { this->server_ = server; } | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
| @@ -45,10 +42,7 @@ class ESP32BLE : public Component { | |||||||
|   void real_gattc_event_handler_(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param); |   void real_gattc_event_handler_(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param); | ||||||
|   void real_gap_event_handler_(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param); |   void real_gap_event_handler_(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param); | ||||||
|  |  | ||||||
|   static void ble_core_task_(void *params); |   bool ble_setup_(); | ||||||
|   static bool ble_setup_(); |  | ||||||
|  |  | ||||||
|   bool ready_{false}; |  | ||||||
|  |  | ||||||
|   BLEServer *server_{nullptr}; |   BLEServer *server_{nullptr}; | ||||||
|   Queue<BLEEvent> ble_events_; |   Queue<BLEEvent> ble_events_; | ||||||
|   | |||||||
| @@ -13,10 +13,8 @@ static const char *TAG = "esp32_ble.characteristic"; | |||||||
|  |  | ||||||
| BLECharacteristic::BLECharacteristic(const ESPBTUUID uuid, uint32_t properties) : uuid_(uuid) { | BLECharacteristic::BLECharacteristic(const ESPBTUUID uuid, uint32_t properties) : uuid_(uuid) { | ||||||
|   this->set_value_lock_ = xSemaphoreCreateBinary(); |   this->set_value_lock_ = xSemaphoreCreateBinary(); | ||||||
|   this->create_lock_ = xSemaphoreCreateBinary(); |  | ||||||
|  |  | ||||||
|   xSemaphoreGive(this->set_value_lock_); |   xSemaphoreGive(this->set_value_lock_); | ||||||
|   xSemaphoreGive(this->create_lock_); |  | ||||||
|   this->properties_ = (esp_gatt_char_prop_t) 0; |   this->properties_ = (esp_gatt_char_prop_t) 0; | ||||||
|  |  | ||||||
|   this->set_broadcast_property((properties & PROPERTY_BROADCAST) != 0); |   this->set_broadcast_property((properties & PROPERTY_BROADCAST) != 0); | ||||||
| @@ -100,12 +98,11 @@ void BLECharacteristic::notify(bool notification) { | |||||||
|  |  | ||||||
| void BLECharacteristic::add_descriptor(BLEDescriptor *descriptor) { this->descriptors_.push_back(descriptor); } | void BLECharacteristic::add_descriptor(BLEDescriptor *descriptor) { this->descriptors_.push_back(descriptor); } | ||||||
|  |  | ||||||
| bool BLECharacteristic::do_create(BLEService *service) { | void BLECharacteristic::do_create(BLEService *service) { | ||||||
|   this->service_ = service; |   this->service_ = service; | ||||||
|   esp_attr_control_t control; |   esp_attr_control_t control; | ||||||
|   control.auto_rsp = ESP_GATT_RSP_BY_APP; |   control.auto_rsp = ESP_GATT_RSP_BY_APP; | ||||||
|  |  | ||||||
|   xSemaphoreTake(this->create_lock_, portMAX_DELAY); |  | ||||||
|   ESP_LOGV(TAG, "Creating characteristic - %s", this->uuid_.to_string().c_str()); |   ESP_LOGV(TAG, "Creating characteristic - %s", this->uuid_.to_string().c_str()); | ||||||
|  |  | ||||||
|   esp_bt_uuid_t uuid = this->uuid_.get_uuid(); |   esp_bt_uuid_t uuid = this->uuid_.get_uuid(); | ||||||
| @@ -114,15 +111,39 @@ bool BLECharacteristic::do_create(BLEService *service) { | |||||||
|  |  | ||||||
|   if (err != ESP_OK) { |   if (err != ESP_OK) { | ||||||
|     ESP_LOGE(TAG, "esp_ble_gatts_add_char failed: %d", err); |     ESP_LOGE(TAG, "esp_ble_gatts_add_char failed: %d", err); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   this->state_ = CREATING; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool BLECharacteristic::is_created() { | ||||||
|  |   if (this->state_ == CREATED) | ||||||
|  |     return true; | ||||||
|  |  | ||||||
|  |   if (this->state_ != CREATING_DEPENDENTS) | ||||||
|     return false; |     return false; | ||||||
|   } |  | ||||||
|  |  | ||||||
|   xSemaphoreWait(this->create_lock_, portMAX_DELAY); |  | ||||||
|  |  | ||||||
|  |   bool created = true; | ||||||
|   for (auto *descriptor : this->descriptors_) { |   for (auto *descriptor : this->descriptors_) { | ||||||
|     descriptor->do_create(this); |     created &= descriptor->is_created(); | ||||||
|   } |   } | ||||||
|   return true; |   if (created) | ||||||
|  |     this->state_ = CREATED; | ||||||
|  |   return this->state_ == CREATED; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool BLECharacteristic::is_failed() { | ||||||
|  |   if (this->state_ == FAILED) | ||||||
|  |     return true; | ||||||
|  |  | ||||||
|  |   bool failed = false; | ||||||
|  |   for (auto *descriptor : this->descriptors_) { | ||||||
|  |     failed |= descriptor->is_failed(); | ||||||
|  |   } | ||||||
|  |   if (failed) | ||||||
|  |     this->state_ = FAILED; | ||||||
|  |   return this->state_ == FAILED; | ||||||
| } | } | ||||||
|  |  | ||||||
| void BLECharacteristic::set_broadcast_property(bool value) { | void BLECharacteristic::set_broadcast_property(bool value) { | ||||||
| @@ -168,7 +189,12 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt | |||||||
|     case ESP_GATTS_ADD_CHAR_EVT: { |     case ESP_GATTS_ADD_CHAR_EVT: { | ||||||
|       if (this->uuid_ == ESPBTUUID::from_uuid(param->add_char.char_uuid)) { |       if (this->uuid_ == ESPBTUUID::from_uuid(param->add_char.char_uuid)) { | ||||||
|         this->handle_ = param->add_char.attr_handle; |         this->handle_ = param->add_char.attr_handle; | ||||||
|         xSemaphoreGive(this->create_lock_); |  | ||||||
|  |         for (auto *descriptor : this->descriptors_) { | ||||||
|  |           descriptor->do_create(this); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         this->state_ = CREATING_DEPENDENTS; | ||||||
|       } |       } | ||||||
|       break; |       break; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -42,10 +42,10 @@ class BLECharacteristic { | |||||||
|  |  | ||||||
|   void notify(bool notification = true); |   void notify(bool notification = true); | ||||||
|  |  | ||||||
|   bool do_create(BLEService *service); |   void do_create(BLEService *service); | ||||||
|   void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param); |   void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param); | ||||||
|  |  | ||||||
|   void on_write(const std::function<void(const std::vector<uint8_t> &)> &func) { this->on_write_ = func; } |   void on_write(const std::function<void(const std::vector<uint8_t> &)> &&func) { this->on_write_ = std::move(func); } | ||||||
|  |  | ||||||
|   void add_descriptor(BLEDescriptor *descriptor); |   void add_descriptor(BLEDescriptor *descriptor); | ||||||
|  |  | ||||||
| @@ -60,6 +60,9 @@ class BLECharacteristic { | |||||||
|   static const uint32_t PROPERTY_INDICATE = 1 << 4; |   static const uint32_t PROPERTY_INDICATE = 1 << 4; | ||||||
|   static const uint32_t PROPERTY_WRITE_NR = 1 << 5; |   static const uint32_t PROPERTY_WRITE_NR = 1 << 5; | ||||||
|  |  | ||||||
|  |   bool is_created(); | ||||||
|  |   bool is_failed(); | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   bool write_event_{false}; |   bool write_event_{false}; | ||||||
|   BLEService *service_; |   BLEService *service_; | ||||||
| @@ -70,13 +73,20 @@ class BLECharacteristic { | |||||||
|   uint16_t value_read_offset_{0}; |   uint16_t value_read_offset_{0}; | ||||||
|   std::vector<uint8_t> value_; |   std::vector<uint8_t> value_; | ||||||
|   SemaphoreHandle_t set_value_lock_; |   SemaphoreHandle_t set_value_lock_; | ||||||
|   SemaphoreHandle_t create_lock_; |  | ||||||
|  |  | ||||||
|   std::vector<BLEDescriptor *> descriptors_; |   std::vector<BLEDescriptor *> descriptors_; | ||||||
|  |  | ||||||
|   std::function<void(const std::vector<uint8_t> &)> on_write_; |   std::function<void(const std::vector<uint8_t> &)> on_write_; | ||||||
|  |  | ||||||
|   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 { | ||||||
|  |     FAILED = 0x00, | ||||||
|  |     INIT, | ||||||
|  |     CREATING, | ||||||
|  |     CREATING_DEPENDENTS, | ||||||
|  |     CREATED, | ||||||
|  |   } state_{INIT}; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| }  // namespace esp32_ble | }  // namespace esp32_ble | ||||||
|   | |||||||
| @@ -16,30 +16,25 @@ BLEDescriptor::BLEDescriptor(ESPBTUUID uuid, uint16_t max_len) { | |||||||
|   this->value_.attr_len = 0; |   this->value_.attr_len = 0; | ||||||
|   this->value_.attr_max_len = max_len; |   this->value_.attr_max_len = max_len; | ||||||
|   this->value_.attr_value = (uint8_t *) malloc(max_len); |   this->value_.attr_value = (uint8_t *) malloc(max_len); | ||||||
|  |  | ||||||
|   this->create_lock_ = xSemaphoreCreateBinary(); |  | ||||||
|   xSemaphoreGive(this->create_lock_); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| BLEDescriptor::~BLEDescriptor() { free(this->value_.attr_value); } | BLEDescriptor::~BLEDescriptor() { free(this->value_.attr_value); } | ||||||
|  |  | ||||||
| bool BLEDescriptor::do_create(BLECharacteristic *characteristic) { | void BLEDescriptor::do_create(BLECharacteristic *characteristic) { | ||||||
|   this->characteristic_ = characteristic; |   this->characteristic_ = characteristic; | ||||||
|   esp_attr_control_t control; |   esp_attr_control_t control; | ||||||
|   control.auto_rsp = ESP_GATT_AUTO_RSP; |   control.auto_rsp = ESP_GATT_AUTO_RSP; | ||||||
|  |  | ||||||
|   xSemaphoreTake(this->create_lock_, portMAX_DELAY); |  | ||||||
|   ESP_LOGV(TAG, "Creating descriptor - %s", this->uuid_.to_string().c_str()); |   ESP_LOGV(TAG, "Creating descriptor - %s", this->uuid_.to_string().c_str()); | ||||||
|   esp_bt_uuid_t uuid = this->uuid_.get_uuid(); |   esp_bt_uuid_t uuid = this->uuid_.get_uuid(); | ||||||
|   esp_err_t err = esp_ble_gatts_add_char_descr(this->characteristic_->get_service()->get_handle(), &uuid, |   esp_err_t err = esp_ble_gatts_add_char_descr(this->characteristic_->get_service()->get_handle(), &uuid, | ||||||
|                                                this->permissions_, &this->value_, &control); |                                                this->permissions_, &this->value_, &control); | ||||||
|   if (err != ESP_OK) { |   if (err != ESP_OK) { | ||||||
|     ESP_LOGE(TAG, "esp_ble_gatts_add_char_descr failed: %d", err); |     ESP_LOGE(TAG, "esp_ble_gatts_add_char_descr failed: %d", err); | ||||||
|     return false; |     this->state_ = FAILED; | ||||||
|  |     return; | ||||||
|   } |   } | ||||||
|   xSemaphoreWait(this->create_lock_, portMAX_DELAY); |   this->state_ = CREATING; | ||||||
|  |  | ||||||
|   return true; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void BLEDescriptor::set_value(const std::string &value) { this->set_value((uint8_t *) value.data(), value.length()); } | void BLEDescriptor::set_value(const std::string &value) { this->set_value((uint8_t *) value.data(), value.length()); } | ||||||
| @@ -60,7 +55,7 @@ void BLEDescriptor::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_ | |||||||
|           this->characteristic_->get_service()->get_handle() == param->add_char_descr.service_handle && |           this->characteristic_->get_service()->get_handle() == param->add_char_descr.service_handle && | ||||||
|           this->characteristic_ == this->characteristic_->get_service()->get_last_created_characteristic()) { |           this->characteristic_ == this->characteristic_->get_service()->get_last_created_characteristic()) { | ||||||
|         this->handle_ = param->add_char_descr.attr_handle; |         this->handle_ = param->add_char_descr.attr_handle; | ||||||
|         xSemaphoreGive(this->create_lock_); |         this->state_ = CREATED; | ||||||
|       } |       } | ||||||
|       break; |       break; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -16,22 +16,31 @@ class BLEDescriptor { | |||||||
|  public: |  public: | ||||||
|   BLEDescriptor(ESPBTUUID uuid, uint16_t max_len = 100); |   BLEDescriptor(ESPBTUUID uuid, uint16_t max_len = 100); | ||||||
|   virtual ~BLEDescriptor(); |   virtual ~BLEDescriptor(); | ||||||
|   bool do_create(BLECharacteristic *characteristic); |   void do_create(BLECharacteristic *characteristic); | ||||||
|  |  | ||||||
|   void set_value(const std::string &value); |   void set_value(const std::string &value); | ||||||
|   void set_value(const uint8_t *data, size_t length); |   void set_value(const uint8_t *data, size_t length); | ||||||
|  |  | ||||||
|   void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param); |   void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param); | ||||||
|  |  | ||||||
|  |   bool is_created() { return this->state_ == CREATED; } | ||||||
|  |   bool is_failed() { return this->state_ == FAILED; } | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   BLECharacteristic *characteristic_{nullptr}; |   BLECharacteristic *characteristic_{nullptr}; | ||||||
|   ESPBTUUID uuid_; |   ESPBTUUID uuid_; | ||||||
|   uint16_t handle_{0xFFFF}; |   uint16_t handle_{0xFFFF}; | ||||||
|   SemaphoreHandle_t create_lock_; |  | ||||||
|  |  | ||||||
|   esp_attr_value_t value_; |   esp_attr_value_t value_; | ||||||
|  |  | ||||||
|   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 { | ||||||
|  |     FAILED = 0x00, | ||||||
|  |     INIT, | ||||||
|  |     CREATING, | ||||||
|  |     CREATED, | ||||||
|  |   } state_{INIT}; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| }  // namespace esp32_ble | }  // namespace esp32_ble | ||||||
|   | |||||||
| @@ -18,7 +18,7 @@ namespace esp32_ble { | |||||||
|  |  | ||||||
| static const char *TAG = "esp32_ble.server"; | static const char *TAG = "esp32_ble.server"; | ||||||
|  |  | ||||||
| static const uint16_t DEVICE_INFORMATION_SERVICE_UUID = 0x180A; | static const uint16_t device_information_service__UUID = 0x180A; | ||||||
| static const uint16_t MODEL_UUID = 0x2A24; | static const uint16_t MODEL_UUID = 0x2A24; | ||||||
| static const uint16_t VERSION_UUID = 0x2A26; | static const uint16_t VERSION_UUID = 0x2A26; | ||||||
| static const uint16_t MANUFACTURER_UUID = 0x2A29; | static const uint16_t MANUFACTURER_UUID = 0x2A29; | ||||||
| @@ -32,59 +32,78 @@ void BLEServer::setup() { | |||||||
|   ESP_LOGD(TAG, "Setting up BLE Server..."); |   ESP_LOGD(TAG, "Setting up BLE Server..."); | ||||||
|  |  | ||||||
|   global_ble_server = this; |   global_ble_server = this; | ||||||
|   this->register_lock_ = xSemaphoreCreateBinary(); |  | ||||||
|   xSemaphoreGive(this->register_lock_); |  | ||||||
|   this->advertising_ = new BLEAdvertising(); |   this->advertising_ = new BLEAdvertising(); | ||||||
|  |  | ||||||
|   this->setup_server_(); |  | ||||||
|  |  | ||||||
|   for (auto *component : this->service_components_) { |  | ||||||
|     component->setup_service(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   ESP_LOGD(TAG, "BLE Server set up complete..."); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void BLEServer::setup_server_() { | void BLEServer::loop() { | ||||||
|   xSemaphoreTake(this->register_lock_, portMAX_DELAY); |   switch (this->state_) { | ||||||
|   esp_err_t err = esp_ble_gatts_app_register(0); |     case RUNNING: | ||||||
|   if (err != ESP_OK) { |       return; | ||||||
|     ESP_LOGE(TAG, "esp_ble_gatts_app_register failed: %d", err); |  | ||||||
|     this->mark_failed(); |     case INIT: { | ||||||
|     return; |       esp_err_t err = esp_ble_gatts_app_register(0); | ||||||
|  |       if (err != ESP_OK) { | ||||||
|  |         ESP_LOGE(TAG, "esp_ble_gatts_app_register failed: %d", err); | ||||||
|  |         this->mark_failed(); | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  |       this->state_ = REGISTERING; | ||||||
|  |       break; | ||||||
|  |     } | ||||||
|  |     case REGISTERING: { | ||||||
|  |       if (this->registered_) { | ||||||
|  |         this->device_information_service_ = this->create_service(device_information_service__UUID); | ||||||
|  |  | ||||||
|  |         this->create_device_characteristics_(); | ||||||
|  |  | ||||||
|  |         this->advertising_->set_scan_response(true); | ||||||
|  |         this->advertising_->set_min_preferred_interval(0x06); | ||||||
|  |         this->advertising_->start(); | ||||||
|  |  | ||||||
|  |         this->state_ = STARTING_SERVICE; | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  |     } | ||||||
|  |     case STARTING_SERVICE: { | ||||||
|  |       if (this->device_information_service_->is_running()) { | ||||||
|  |         for (auto *component : this->service_components_) { | ||||||
|  |           component->setup_service(); | ||||||
|  |         } | ||||||
|  |         this->state_ = SETTING_UP_COMPONENT_SERVICES; | ||||||
|  |       } else if (!this->device_information_service_->is_starting()) { | ||||||
|  |         this->device_information_service_->start(); | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  |     } | ||||||
|  |     case SETTING_UP_COMPONENT_SERVICES: { | ||||||
|  |       this->state_ = RUNNING; | ||||||
|  |       this->can_proceed_ = true; | ||||||
|  |       ESP_LOGD(TAG, "BLE server setup successfully"); | ||||||
|  |       break; | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|   xSemaphoreWait(this->register_lock_, portMAX_DELAY); |  | ||||||
|  |  | ||||||
|   this->device_information_service = this->create_service(DEVICE_INFORMATION_SERVICE_UUID); |  | ||||||
|  |  | ||||||
|   this->create_device_characteristics_(); |  | ||||||
|  |  | ||||||
|   this->advertising_->set_scan_response(true); |  | ||||||
|   this->advertising_->set_min_preferred_interval(0x06); |  | ||||||
|   this->advertising_->start(); |  | ||||||
|  |  | ||||||
|   this->device_information_service->start(); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| bool BLEServer::create_device_characteristics_() { | bool BLEServer::create_device_characteristics_() { | ||||||
|   if (this->model_.has_value()) { |   if (this->model_.has_value()) { | ||||||
|     BLECharacteristic *model = |     BLECharacteristic *model = | ||||||
|         this->device_information_service->create_characteristic(MODEL_UUID, BLECharacteristic::PROPERTY_READ); |         this->device_information_service_->create_characteristic(MODEL_UUID, BLECharacteristic::PROPERTY_READ); | ||||||
|     model->set_value(this->model_.value()); |     model->set_value(this->model_.value()); | ||||||
|   } else { |   } else { | ||||||
| #ifdef ARDUINO_BOARD | #ifdef ARDUINO_BOARD | ||||||
|     BLECharacteristic *model = |     BLECharacteristic *model = | ||||||
|         this->device_information_service->create_characteristic(MODEL_UUID, BLECharacteristic::PROPERTY_READ); |         this->device_information_service_->create_characteristic(MODEL_UUID, BLECharacteristic::PROPERTY_READ); | ||||||
|     model->set_value(ARDUINO_BOARD); |     model->set_value(ARDUINO_BOARD); | ||||||
| #endif | #endif | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   BLECharacteristic *version = |   BLECharacteristic *version = | ||||||
|       this->device_information_service->create_characteristic(VERSION_UUID, BLECharacteristic::PROPERTY_READ); |       this->device_information_service_->create_characteristic(VERSION_UUID, BLECharacteristic::PROPERTY_READ); | ||||||
|   version->set_value("ESPHome " ESPHOME_VERSION); |   version->set_value("ESPHome " ESPHOME_VERSION); | ||||||
|  |  | ||||||
|   BLECharacteristic *manufacturer = |   BLECharacteristic *manufacturer = | ||||||
|       this->device_information_service->create_characteristic(MANUFACTURER_UUID, BLECharacteristic::PROPERTY_READ); |       this->device_information_service_->create_characteristic(MANUFACTURER_UUID, BLECharacteristic::PROPERTY_READ); | ||||||
|   manufacturer->set_value(this->manufacturer_); |   manufacturer->set_value(this->manufacturer_); | ||||||
|  |  | ||||||
|   return true; |   return true; | ||||||
| @@ -134,7 +153,7 @@ void BLEServer::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t ga | |||||||
|     } |     } | ||||||
|     case ESP_GATTS_REG_EVT: { |     case ESP_GATTS_REG_EVT: { | ||||||
|       this->gatts_if_ = gatts_if; |       this->gatts_if_ = gatts_if; | ||||||
|       xSemaphoreGive(this->register_lock_); |       this->registered_ = true; | ||||||
|       break; |       break; | ||||||
|     } |     } | ||||||
|     default: |     default: | ||||||
|   | |||||||
| @@ -24,13 +24,17 @@ class BLEServiceComponent { | |||||||
|   virtual void setup_service(); |   virtual void setup_service(); | ||||||
|   virtual void on_client_connect(){}; |   virtual void on_client_connect(){}; | ||||||
|   virtual void on_client_disconnect(){}; |   virtual void on_client_disconnect(){}; | ||||||
|  |   virtual void start(); | ||||||
|  |   virtual void stop(); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| class BLEServer : public Component { | class BLEServer : public Component { | ||||||
|  public: |  public: | ||||||
|   void setup() override; |   void setup() override; | ||||||
|  |   void loop() override; | ||||||
|   void dump_config() override; |   void dump_config() override; | ||||||
|   float get_setup_priority() const override; |   float get_setup_priority() const override; | ||||||
|  |   bool can_proceed() override { return this->can_proceed_; } | ||||||
|  |  | ||||||
|   void teardown(); |   void teardown(); | ||||||
|  |  | ||||||
| @@ -53,27 +57,35 @@ class BLEServer : public Component { | |||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   bool create_device_characteristics_(); |   bool create_device_characteristics_(); | ||||||
|   void setup_server_(); |  | ||||||
|  |  | ||||||
|   void add_client_(uint16_t conn_id, void *client) { |   void add_client_(uint16_t conn_id, void *client) { | ||||||
|     this->clients_.insert(std::pair<uint16_t, void *>(conn_id, client)); |     this->clients_.insert(std::pair<uint16_t, void *>(conn_id, client)); | ||||||
|   } |   } | ||||||
|   bool remove_client_(uint16_t conn_id) { return this->clients_.erase(conn_id) > 0; } |   bool remove_client_(uint16_t conn_id) { return this->clients_.erase(conn_id) > 0; } | ||||||
|  |  | ||||||
|  |   bool can_proceed_{false}; | ||||||
|  |  | ||||||
|   std::string manufacturer_; |   std::string manufacturer_; | ||||||
|   optional<std::string> model_; |   optional<std::string> model_; | ||||||
|   esp_gatt_if_t gatts_if_{0}; |   esp_gatt_if_t gatts_if_{0}; | ||||||
|  |   bool registered_{false}; | ||||||
|   BLEAdvertising *advertising_; |   BLEAdvertising *advertising_; | ||||||
|  |  | ||||||
|   uint32_t connected_clients_{0}; |   uint32_t connected_clients_{0}; | ||||||
|   std::map<uint16_t, void *> clients_; |   std::map<uint16_t, void *> clients_; | ||||||
|  |  | ||||||
|   std::vector<BLEService *> services_; |   std::vector<BLEService *> services_; | ||||||
|   BLEService *device_information_service; |   BLEService *device_information_service_; | ||||||
|  |  | ||||||
|   std::vector<BLEServiceComponent *> service_components_; |   std::vector<BLEServiceComponent *> service_components_; | ||||||
|  |  | ||||||
|   SemaphoreHandle_t register_lock_; |   enum State : uint8_t { | ||||||
|  |     INIT = 0x00, | ||||||
|  |     REGISTERING, | ||||||
|  |     STARTING_SERVICE, | ||||||
|  |     SETTING_UP_COMPONENT_SERVICES, | ||||||
|  |     RUNNING, | ||||||
|  |   } state_{INIT}; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| extern BLEServer *global_ble_server; | extern BLEServer *global_ble_server; | ||||||
|   | |||||||
| @@ -10,15 +10,7 @@ namespace esp32_ble { | |||||||
| static const char *TAG = "esp32_ble.service"; | static const char *TAG = "esp32_ble.service"; | ||||||
|  |  | ||||||
| BLEService::BLEService(ESPBTUUID uuid, uint16_t num_handles, uint8_t inst_id) | BLEService::BLEService(ESPBTUUID uuid, uint16_t num_handles, uint8_t inst_id) | ||||||
|     : uuid_(uuid), num_handles_(num_handles), inst_id_(inst_id) { |     : uuid_(uuid), num_handles_(num_handles), inst_id_(inst_id) {} | ||||||
|   this->create_lock_ = xSemaphoreCreateBinary(); |  | ||||||
|   this->start_lock_ = xSemaphoreCreateBinary(); |  | ||||||
|   this->stop_lock_ = xSemaphoreCreateBinary(); |  | ||||||
|  |  | ||||||
|   xSemaphoreGive(this->create_lock_); |  | ||||||
|   xSemaphoreGive(this->start_lock_); |  | ||||||
|   xSemaphoreGive(this->stop_lock_); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| BLEService::~BLEService() { | BLEService::~BLEService() { | ||||||
|   for (auto &chr : this->characteristics_) |   for (auto &chr : this->characteristics_) | ||||||
| @@ -47,10 +39,9 @@ BLECharacteristic *BLEService::create_characteristic(ESPBTUUID uuid, esp_gatt_ch | |||||||
|   return characteristic; |   return characteristic; | ||||||
| } | } | ||||||
|  |  | ||||||
| bool BLEService::do_create(BLEServer *server) { | void BLEService::do_create(BLEServer *server) { | ||||||
|   this->server_ = server; |   this->server_ = server; | ||||||
|  |  | ||||||
|   xSemaphoreTake(this->create_lock_, portMAX_DELAY); |  | ||||||
|   esp_gatt_srvc_id_t srvc_id; |   esp_gatt_srvc_id_t srvc_id; | ||||||
|   srvc_id.is_primary = true; |   srvc_id.is_primary = true; | ||||||
|   srvc_id.id.inst_id = this->inst_id_; |   srvc_id.id.inst_id = this->inst_id_; | ||||||
| @@ -59,36 +50,58 @@ bool BLEService::do_create(BLEServer *server) { | |||||||
|   esp_err_t err = esp_ble_gatts_create_service(server->get_gatts_if(), &srvc_id, this->num_handles_); |   esp_err_t err = esp_ble_gatts_create_service(server->get_gatts_if(), &srvc_id, this->num_handles_); | ||||||
|   if (err != ESP_OK) { |   if (err != ESP_OK) { | ||||||
|     ESP_LOGE(TAG, "esp_ble_gatts_create_service failed: %d", err); |     ESP_LOGE(TAG, "esp_ble_gatts_create_service failed: %d", err); | ||||||
|     return false; |     this->init_state_ = FAILED; | ||||||
|  |     return; | ||||||
|   } |   } | ||||||
|   xSemaphoreWait(this->create_lock_, portMAX_DELAY); |   this->init_state_ = CREATING; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool BLEService::do_create_characteristics_() { | ||||||
|  |   if (this->created_characteristic_count_ >= this->characteristics_.size() && | ||||||
|  |       (this->last_created_characteristic_ == nullptr || this->last_created_characteristic_->is_created())) | ||||||
|  |     return false;  // Signifies there are no characteristics, or they are all finished being created. | ||||||
|  |  | ||||||
|  |   if (this->last_created_characteristic_ != nullptr && !this->last_created_characteristic_->is_created()) | ||||||
|  |     return true;  // Signifies that the previous characteristic is still being created. | ||||||
|  |  | ||||||
|  |   auto *characteristic = this->characteristics_[this->created_characteristic_count_++]; | ||||||
|  |   this->last_created_characteristic_ = characteristic; | ||||||
|  |   characteristic->do_create(this); | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| void BLEService::start() { | void BLEService::start() { | ||||||
|   for (auto *characteristic : this->characteristics_) { |   if (this->do_create_characteristics_()) | ||||||
|     this->last_created_characteristic_ = characteristic; |     return; | ||||||
|     characteristic->do_create(this); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   xSemaphoreTake(this->start_lock_, portMAX_DELAY); |  | ||||||
|   esp_err_t err = esp_ble_gatts_start_service(this->handle_); |   esp_err_t err = esp_ble_gatts_start_service(this->handle_); | ||||||
|   if (err != ESP_OK) { |   if (err != ESP_OK) { | ||||||
|     ESP_LOGE(TAG, "esp_ble_gatts_start_service failed: %d", err); |     ESP_LOGE(TAG, "esp_ble_gatts_start_service failed: %d", err); | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|   xSemaphoreWait(this->start_lock_, portMAX_DELAY); |   this->running_state_ = STARTING; | ||||||
| } | } | ||||||
|  |  | ||||||
| void BLEService::stop() { | void BLEService::stop() { | ||||||
|   xSemaphoreTake(this->stop_lock_, portMAX_DELAY); |  | ||||||
|   esp_err_t err = esp_ble_gatts_stop_service(this->handle_); |   esp_err_t err = esp_ble_gatts_stop_service(this->handle_); | ||||||
|   if (err != ESP_OK) { |   if (err != ESP_OK) { | ||||||
|     ESP_LOGE(TAG, "esp_ble_gatts_stop_service failed: %d", err); |     ESP_LOGE(TAG, "esp_ble_gatts_stop_service failed: %d", err); | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|   xSemaphoreWait(this->stop_lock_, portMAX_DELAY); |   this->running_state_ = STOPPING; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool BLEService::is_created() { return this->init_state_ == CREATED; } | ||||||
|  | bool BLEService::is_failed() { | ||||||
|  |   if (this->init_state_ == FAILED) | ||||||
|  |     return true; | ||||||
|  |   bool failed = false; | ||||||
|  |   for (auto *characteristic : this->characteristics_) | ||||||
|  |     failed |= characteristic->is_failed(); | ||||||
|  |  | ||||||
|  |   if (failed) | ||||||
|  |     this->init_state_ = FAILED; | ||||||
|  |   return this->init_state_ == FAILED; | ||||||
| } | } | ||||||
|  |  | ||||||
| void BLEService::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, | void BLEService::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, | ||||||
| @@ -98,19 +111,19 @@ void BLEService::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t g | |||||||
|       if (this->uuid_ == ESPBTUUID::from_uuid(param->create.service_id.id.uuid) && |       if (this->uuid_ == ESPBTUUID::from_uuid(param->create.service_id.id.uuid) && | ||||||
|           this->inst_id_ == param->create.service_id.id.inst_id) { |           this->inst_id_ == param->create.service_id.id.inst_id) { | ||||||
|         this->handle_ = param->create.service_handle; |         this->handle_ = param->create.service_handle; | ||||||
|         xSemaphoreGive(this->create_lock_); |         this->init_state_ = CREATED; | ||||||
|       } |       } | ||||||
|       break; |       break; | ||||||
|     } |     } | ||||||
|     case ESP_GATTS_START_EVT: { |     case ESP_GATTS_START_EVT: { | ||||||
|       if (param->start.service_handle == this->handle_) { |       if (param->start.service_handle == this->handle_) { | ||||||
|         xSemaphoreGive(this->start_lock_); |         this->running_state_ = RUNNING; | ||||||
|       } |       } | ||||||
|       break; |       break; | ||||||
|     } |     } | ||||||
|     case ESP_GATTS_STOP_EVT: { |     case ESP_GATTS_STOP_EVT: { | ||||||
|       if (param->start.service_handle == this->handle_) { |       if (param->start.service_handle == this->handle_) { | ||||||
|         xSemaphoreGive(this->stop_lock_); |         this->running_state_ = STOPPED; | ||||||
|       } |       } | ||||||
|       break; |       break; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -33,26 +33,44 @@ class BLEService { | |||||||
|  |  | ||||||
|   BLEServer *get_server() { return this->server_; } |   BLEServer *get_server() { return this->server_; } | ||||||
|  |  | ||||||
|   bool do_create(BLEServer *server); |   void do_create(BLEServer *server); | ||||||
|   void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param); |   void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param); | ||||||
|  |  | ||||||
|   void start(); |   void start(); | ||||||
|   void stop(); |   void stop(); | ||||||
|  |  | ||||||
|  protected: |   bool is_created(); | ||||||
|   bool errored_{false}; |   bool is_failed(); | ||||||
|  |  | ||||||
|  |   bool is_running() { return this->running_state_ == RUNNING; } | ||||||
|  |   bool is_starting() { return this->running_state_ == STARTING; } | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|   std::vector<BLECharacteristic *> characteristics_; |   std::vector<BLECharacteristic *> characteristics_; | ||||||
|   BLECharacteristic *last_created_characteristic_{nullptr}; |   BLECharacteristic *last_created_characteristic_{nullptr}; | ||||||
|  |   uint32_t created_characteristic_count_{0}; | ||||||
|   BLEServer *server_; |   BLEServer *server_; | ||||||
|   ESPBTUUID uuid_; |   ESPBTUUID uuid_; | ||||||
|   uint16_t num_handles_; |   uint16_t num_handles_; | ||||||
|   uint16_t handle_{0xFFFF}; |   uint16_t handle_{0xFFFF}; | ||||||
|   uint8_t inst_id_; |   uint8_t inst_id_; | ||||||
|  |  | ||||||
|   SemaphoreHandle_t create_lock_; |   bool do_create_characteristics_(); | ||||||
|   SemaphoreHandle_t start_lock_; |  | ||||||
|   SemaphoreHandle_t stop_lock_; |   enum InitState : uint8_t { | ||||||
|  |     FAILED = 0x00, | ||||||
|  |     INIT, | ||||||
|  |     CREATING, | ||||||
|  |     CREATING_DEPENDENTS, | ||||||
|  |     CREATED, | ||||||
|  |   } init_state_{INIT}; | ||||||
|  |  | ||||||
|  |   enum RunningState : uint8_t { | ||||||
|  |     STARTING, | ||||||
|  |     RUNNING, | ||||||
|  |     STOPPING, | ||||||
|  |     STOPPED, | ||||||
|  |   } running_state_{STOPPED}; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| }  // namespace esp32_ble | }  // namespace esp32_ble | ||||||
|   | |||||||
| @@ -53,7 +53,7 @@ template<class T> class Queue { | |||||||
|   SemaphoreHandle_t m; |   SemaphoreHandle_t m; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| // Received GAP and GATTC events are only queued, and get processed in the main loop(). | // Received GAP, GATTC and GATTS events are only queued, and get processed in the main loop(). | ||||||
| // This class stores each event in a single type. | // This class stores each event in a single type. | ||||||
| class BLEEvent { | class BLEEvent { | ||||||
|  public: |  public: | ||||||
| @@ -68,9 +68,18 @@ class BLEEvent { | |||||||
|     this->event_.gattc.gattc_if = i; |     this->event_.gattc.gattc_if = i; | ||||||
|     memcpy(&this->event_.gattc.gattc_param, p, sizeof(esp_ble_gattc_cb_param_t)); |     memcpy(&this->event_.gattc.gattc_param, p, sizeof(esp_ble_gattc_cb_param_t)); | ||||||
|     // Need to also make a copy of notify event data. |     // Need to also make a copy of notify event data. | ||||||
|     if (e == ESP_GATTC_NOTIFY_EVT) { |     switch (e) { | ||||||
|       memcpy(this->event_.gattc.notify_data, p->notify.value, p->notify.value_len); |       case ESP_GATTC_NOTIFY_EVT: | ||||||
|       this->event_.gattc.gattc_param.notify.value = this->event_.gattc.notify_data; |         memcpy(this->event_.gattc.data, p->notify.value, p->notify.value_len); | ||||||
|  |         this->event_.gattc.gattc_param.notify.value = this->event_.gattc.data; | ||||||
|  |         break; | ||||||
|  |       case ESP_GATTC_READ_CHAR_EVT: | ||||||
|  |       case ESP_GATTC_READ_DESCR_EVT: | ||||||
|  |         memcpy(this->event_.gattc.data, p->read.value, p->read.value_len); | ||||||
|  |         this->event_.gattc.gattc_param.read.value = this->event_.gattc.data; | ||||||
|  |         break; | ||||||
|  |       default: | ||||||
|  |         break; | ||||||
|     } |     } | ||||||
|     this->type_ = GATTC; |     this->type_ = GATTC; | ||||||
|   }; |   }; | ||||||
| @@ -79,6 +88,15 @@ class BLEEvent { | |||||||
|     this->event_.gatts.gatts_event = e; |     this->event_.gatts.gatts_event = e; | ||||||
|     this->event_.gatts.gatts_if = i; |     this->event_.gatts.gatts_if = i; | ||||||
|     memcpy(&this->event_.gatts.gatts_param, p, sizeof(esp_ble_gatts_cb_param_t)); |     memcpy(&this->event_.gatts.gatts_param, p, sizeof(esp_ble_gatts_cb_param_t)); | ||||||
|  |     // Need to also make a copy of write data. | ||||||
|  |     switch (e) { | ||||||
|  |       case ESP_GATTS_WRITE_EVT: | ||||||
|  |         memcpy(this->event_.gatts.data, p->write.value, p->write.len); | ||||||
|  |         this->event_.gatts.gatts_param.write.value = this->event_.gatts.data; | ||||||
|  |         break; | ||||||
|  |       default: | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|     this->type_ = GATTS; |     this->type_ = GATTS; | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
| @@ -92,13 +110,14 @@ class BLEEvent { | |||||||
|       esp_gattc_cb_event_t gattc_event; |       esp_gattc_cb_event_t gattc_event; | ||||||
|       esp_gatt_if_t gattc_if; |       esp_gatt_if_t gattc_if; | ||||||
|       esp_ble_gattc_cb_param_t gattc_param; |       esp_ble_gattc_cb_param_t gattc_param; | ||||||
|       uint8_t notify_data[64]; |       uint8_t data[64]; | ||||||
|     } gattc; |     } gattc; | ||||||
|  |  | ||||||
|     struct gatts_event { |     struct gatts_event { | ||||||
|       esp_gatts_cb_event_t gatts_event; |       esp_gatts_cb_event_t gatts_event; | ||||||
|       esp_gatt_if_t gatts_if; |       esp_gatt_if_t gatts_if; | ||||||
|       esp_ble_gatts_cb_param_t gatts_param; |       esp_ble_gatts_cb_param_t gatts_param; | ||||||
|  |       uint8_t data[64]; | ||||||
|     } gatts; |     } gatts; | ||||||
|   } event_; |   } event_; | ||||||
|   enum ble_event_t : uint8_t { |   enum ble_event_t : uint8_t { | ||||||
|   | |||||||
| @@ -14,7 +14,9 @@ ESP32ImprovComponent::ESP32ImprovComponent() { global_improv_component = this; } | |||||||
|  |  | ||||||
| void ESP32ImprovComponent::setup_service() { | void ESP32ImprovComponent::setup_service() { | ||||||
|   this->service_ = esp32_ble::global_ble_server->create_service(improv::SERVICE_UUID, true); |   this->service_ = esp32_ble::global_ble_server->create_service(improv::SERVICE_UUID, true); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ESP32ImprovComponent::setup_characteristics() { | ||||||
|   this->status_ = this->service_->create_characteristic( |   this->status_ = this->service_->create_characteristic( | ||||||
|       improv::STATUS_UUID, esp32_ble::BLECharacteristic::PROPERTY_READ | esp32_ble::BLECharacteristic::PROPERTY_NOTIFY); |       improv::STATUS_UUID, esp32_ble::BLECharacteristic::PROPERTY_READ | esp32_ble::BLECharacteristic::PROPERTY_NOTIFY); | ||||||
|   esp32_ble::BLEDescriptor *status_descriptor = new esp32_ble::BLE2902(); |   esp32_ble::BLEDescriptor *status_descriptor = new esp32_ble::BLE2902(); | ||||||
| @@ -62,16 +64,21 @@ void ESP32ImprovComponent::loop() { | |||||||
|       if (this->status_indicator_ != nullptr) |       if (this->status_indicator_ != nullptr) | ||||||
|         this->status_indicator_->turn_off(); |         this->status_indicator_->turn_off(); | ||||||
|  |  | ||||||
|  |       if (this->service_->is_created() && !this->setup_complete_) { | ||||||
|  |         this->setup_characteristics(); | ||||||
|  |       } | ||||||
|  |  | ||||||
|       if (this->should_start_ && this->setup_complete_) { |       if (this->should_start_ && this->setup_complete_) { | ||||||
|         ESP_LOGD(TAG, "Starting Improv service..."); |         if (this->service_->is_running()) { | ||||||
|  |           this->service_->get_server()->get_advertising()->start(); | ||||||
|  |  | ||||||
|         this->service_->start(); |           this->set_state_(improv::STATE_AWAITING_AUTHORIZATION); | ||||||
|         this->service_->get_server()->get_advertising()->start(); |           this->set_error_(improv::ERROR_NONE); | ||||||
|  |           this->should_start_ = false; | ||||||
|         this->set_state_(improv::STATE_AWAITING_AUTHORIZATION); |           ESP_LOGD(TAG, "Service started!"); | ||||||
|         this->set_error_(improv::ERROR_NONE); |         } else { | ||||||
|         this->should_start_ = false; |           this->service_->start(); | ||||||
|         ESP_LOGD(TAG, "Service started!"); |         } | ||||||
|       } |       } | ||||||
|       break; |       break; | ||||||
|     case improv::STATE_AWAITING_AUTHORIZATION: { |     case improv::STATE_AWAITING_AUTHORIZATION: { | ||||||
| @@ -191,7 +198,7 @@ void ESP32ImprovComponent::start() { | |||||||
|   this->should_start_ = true; |   this->should_start_ = true; | ||||||
| } | } | ||||||
|  |  | ||||||
| void ESP32ImprovComponent::end() { | void ESP32ImprovComponent::stop() { | ||||||
|   this->set_timeout("end-service", 1000, [this] { |   this->set_timeout("end-service", 1000, [this] { | ||||||
|     this->service_->stop(); |     this->service_->stop(); | ||||||
|     this->set_state_(improv::STATE_STOPPED); |     this->set_state_(improv::STATE_STOPPED); | ||||||
|   | |||||||
| @@ -21,11 +21,12 @@ class ESP32ImprovComponent : public Component, public esp32_ble::BLEServiceCompo | |||||||
|   void dump_config() override; |   void dump_config() override; | ||||||
|   void loop() override; |   void loop() override; | ||||||
|   void setup_service() override; |   void setup_service() override; | ||||||
|  |   void setup_characteristics(); | ||||||
|   void on_client_disconnect() override; |   void on_client_disconnect() override; | ||||||
|  |  | ||||||
|   float get_setup_priority() const override; |   float get_setup_priority() const override; | ||||||
|   void start(); |   void start() override; | ||||||
|   void end(); |   void stop() override; | ||||||
|   bool is_active() const { return this->state_ != improv::STATE_STOPPED; } |   bool is_active() const { return this->state_ != improv::STATE_STOPPED; } | ||||||
|  |  | ||||||
|   void set_authorizer(binary_sensor::BinarySensor *authorizer) { this->authorizer_ = authorizer; } |   void set_authorizer(binary_sensor::BinarySensor *authorizer) { this->authorizer_ = authorizer; } | ||||||
|   | |||||||
| @@ -508,7 +508,7 @@ void WiFiComponent::check_connecting_finished() { | |||||||
|     } |     } | ||||||
| #ifdef USE_IMPROV | #ifdef USE_IMPROV | ||||||
|     if (this->is_esp32_improv_active_()) { |     if (this->is_esp32_improv_active_()) { | ||||||
|       esp32_improv::global_improv_component->end(); |       esp32_improv::global_improv_component->stop(); | ||||||
|     } |     } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user