Enqueue services to BLE Server

This commit is contained in:
Rapsssito 2024-06-21 00:11:45 +02:00
parent 4282918581
commit 05617fa9d9
7 changed files with 53 additions and 51 deletions

View file

@ -186,6 +186,7 @@ async def to_code(config):
desc_var = cg.new_Pvariable(descriptor[CONF_ID], parse_uuid(descriptor[CONF_UUID]), max_length) desc_var = cg.new_Pvariable(descriptor[CONF_ID], parse_uuid(descriptor[CONF_UUID]), max_length)
if CONF_VALUE in descriptor: if CONF_VALUE in descriptor:
cg.add(desc_var.set_value(parse_value(descriptor[CONF_VALUE]))) cg.add(desc_var.set_value(parse_value(descriptor[CONF_VALUE])))
cg.add(var.enqueue_start_service(service_var))
cg.add_define("USE_ESP32_BLE_SERVER") cg.add_define("USE_ESP32_BLE_SERVER")
if CORE.using_esp_idf: if CORE.using_esp_idf:
add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True) add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True)

View file

@ -289,7 +289,7 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt
} }
if (!param->write.is_prep) { if (!param->write.is_prep) {
this->on_write_(this->value_); if (this->on_write_) this->on_write_(this->value_);
} }
break; break;
@ -300,7 +300,7 @@ 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->on_write_(this->value_); if (this->on_write_) this->on_write_(this->value_);
} }
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);

View file

@ -38,9 +38,25 @@ void BLEServer::loop() {
return; return;
} }
switch (this->state_) { switch (this->state_) {
case RUNNING: case RUNNING: {
return; if (this->services_to_start_.empty()) break;
uint16_t index_to_remove = 0;
// Iterate over the services to start
for (unsigned i = 0; i < this->services_to_start_.size(); i++) {
BLEService *service = this->services_to_start_[i];
if (service->is_created()) {
service->start();
} else {
index_to_remove = i + 1;
}
}
// Remove the services that have been started
if (index_to_remove > 0) {
this->services_to_start_.erase(this->services_to_start_.begin(),
this->services_to_start_.begin() + index_to_remove - 1);
}
break;
}
case INIT: { case INIT: {
esp_err_t err = esp_ble_gatts_app_register(0); esp_err_t err = esp_ble_gatts_app_register(0);
if (err != ESP_OK) { if (err != ESP_OK) {
@ -66,14 +82,11 @@ void BLEServer::loop() {
break; break;
} }
case STARTING_SERVICE: { case STARTING_SERVICE: {
if (!this->device_information_service_->is_created()) {
break;
}
if (this->device_information_service_->is_running()) { if (this->device_information_service_->is_running()) {
this->state_ = RUNNING; this->state_ = RUNNING;
this->restart_advertising_(); this->restart_advertising_();
ESP_LOGD(TAG, "BLE server setup successfully"); ESP_LOGD(TAG, "BLE server setup successfully");
} else if (!this->device_information_service_->is_starting()) { } else if (this->device_information_service_->is_created()) {
this->device_information_service_->start(); this->device_information_service_->start();
} }
break; break;

View file

@ -46,6 +46,7 @@ class BLEServer : public Component, public GATTsEventHandler, public BLEStatusEv
BLEService *create_service(ESPBTUUID uuid, bool advertise = false, uint16_t num_handles = 15); BLEService *create_service(ESPBTUUID uuid, bool advertise = false, uint16_t num_handles = 15);
void remove_service(ESPBTUUID uuid, uint8_t inst_id = 0); void remove_service(ESPBTUUID uuid, uint8_t inst_id = 0);
BLEService *get_service(ESPBTUUID uuid, uint8_t inst_id = 0); BLEService *get_service(ESPBTUUID uuid, uint8_t inst_id = 0);
void enqueue_start_service(BLEService *service) { this->services_to_start_.push_back(service); }
esp_gatt_if_t get_gatts_if() { return this->gatts_if_; } esp_gatt_if_t get_gatts_if() { return this->gatts_if_; }
uint32_t get_connected_client_count() { return this->connected_clients_; } uint32_t get_connected_client_count() { return this->connected_clients_; }
@ -73,6 +74,7 @@ class BLEServer : public Component, public GATTsEventHandler, public BLEStatusEv
uint32_t connected_clients_{0}; uint32_t connected_clients_{0};
std::unordered_map<uint16_t, void *> clients_; std::unordered_map<uint16_t, void *> clients_;
std::unordered_map<std::string, BLEService *> services_; std::unordered_map<std::string, BLEService *> services_;
std::vector<BLEService *> services_to_start_;
BLEService *device_information_service_; BLEService *device_information_service_;
enum State : uint8_t { enum State : uint8_t {

View file

@ -52,16 +52,16 @@ void 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);
this->init_state_ = FAILED; this->state_ = FAILED;
return; return;
} }
this->init_state_ = CREATING; this->state_ = CREATING;
} }
void BLEService::do_delete() { void BLEService::do_delete() {
if (this->init_state_ == DELETING || this->init_state_ == DELETED) if (this->state_ == DELETING || this->state_ == DELETED)
return; return;
this->init_state_ = DELETING; this->state_ = DELETING;
this->created_characteristic_count_ = 0; this->created_characteristic_count_ = 0;
this->last_created_characteristic_ = nullptr; this->last_created_characteristic_ = nullptr;
this->stop_(); this->stop_();
@ -86,18 +86,12 @@ bool BLEService::do_create_characteristics_() {
return true; return true;
} }
void BLEService::enqueue_start() {
if (this->init_state_ == CREATED)
this->start();
else
this->should_start_ = true;
}
void BLEService::start() { void BLEService::start() {
if (this->do_create_characteristics_()) if (this->do_create_characteristics_())
return; return;
should_start_ = true; should_start_ = true;
this->state_ = STARTING;
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);
@ -105,7 +99,6 @@ void BLEService::start() {
} }
if (this->advertise_) if (this->advertise_)
esp32_ble::global_ble->advertising_add_service_uuid(this->uuid_); esp32_ble::global_ble->advertising_add_service_uuid(this->uuid_);
this->running_state_ = STARTING;
} }
void BLEService::stop() { void BLEService::stop() {
@ -114,9 +107,9 @@ void BLEService::stop() {
} }
void BLEService::stop_() { void BLEService::stop_() {
if (this->running_state_ == STOPPING || this->running_state_ == STOPPED) if (this->state_ == STOPPING || this->state_ == STOPPED)
return; return;
this->running_state_ = STOPPING; this->state_ = STOPPING;
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);
@ -126,17 +119,16 @@ void BLEService::stop_() {
esp32_ble::global_ble->advertising_remove_service_uuid(this->uuid_); esp32_ble::global_ble->advertising_remove_service_uuid(this->uuid_);
} }
bool BLEService::is_created() { return this->init_state_ == CREATED; }
bool BLEService::is_failed() { bool BLEService::is_failed() {
if (this->init_state_ == FAILED) if (this->state_ == FAILED)
return true; return true;
bool failed = false; bool failed = false;
for (auto *characteristic : this->characteristics_) for (auto *characteristic : this->characteristics_)
failed |= characteristic->is_failed(); failed |= characteristic->is_failed();
if (failed) if (failed)
this->init_state_ = FAILED; this->state_ = FAILED;
return this->init_state_ == FAILED; return this->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,
@ -146,7 +138,7 @@ 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;
this->init_state_ = CREATED; this->state_ = CREATED;
if (this->should_start_) if (this->should_start_)
this->start(); this->start();
} }
@ -154,18 +146,18 @@ void BLEService::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t g
} }
case ESP_GATTS_DELETE_EVT: case ESP_GATTS_DELETE_EVT:
if (param->del.service_handle == this->handle_) { if (param->del.service_handle == this->handle_) {
this->init_state_ = DELETED; this->state_ = DELETED;
} }
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_) {
this->running_state_ = RUNNING; this->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_) {
this->running_state_ = STOPPED; this->state_ = STOPPED;
} }
break; break;
} }

View file

@ -42,20 +42,18 @@ class BLEService {
void do_delete(); void do_delete();
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 enqueue_start();
void start(); void start();
void stop(); void stop();
bool is_created();
bool is_failed(); bool is_failed();
bool is_created() { return this->state_ == CREATED; }
bool is_running() { return this->running_state_ == RUNNING; } bool is_running() { return this->state_ == RUNNING; }
bool is_starting() { return this->running_state_ == STARTING; } bool is_starting() { return this->state_ == STARTING; }
bool is_deleted() { return this->init_state_ == DELETED; } bool is_deleted() { return this->state_ == DELETED; }
void on_client_connect(const std::function<void(const uint16_t)> &&func) { this->on_client_connect_ = func; } void on_client_connect(const std::function<void(const uint16_t)> &&func) { this->on_client_connect_ = func; }
void on_client_disconnect(const std::function<void(const uint16_t)> &&func) { this->on_client_disconnect_ = func; } void on_client_disconnect(const std::function<void(const uint16_t)> &&func) { this->on_client_disconnect_ = func; }
void emit_client_connect(const uint16_t conn_id) { this->on_client_connect_(conn_id); } void emit_client_connect(const uint16_t conn_id) { if (this->on_client_connect_ && this->is_running()) this->on_client_connect_(conn_id); }
void emit_client_disconnect(const uint16_t conn_id) { this->on_client_disconnect_(conn_id); } void emit_client_disconnect(const uint16_t conn_id) { if (this->on_client_disconnect_ && this->is_running()) this->on_client_disconnect_(conn_id); }
protected: protected:
std::vector<BLECharacteristic *> characteristics_; std::vector<BLECharacteristic *> characteristics_;
@ -74,22 +72,18 @@ class BLEService {
bool do_create_characteristics_(); bool do_create_characteristics_();
void stop_(); void stop_();
enum InitState : uint8_t { enum State : uint8_t {
FAILED = 0x00, FAILED = 0x00,
INIT, INIT,
CREATING, CREATING,
CREATING_DEPENDENTS,
CREATED, CREATED,
DELETING,
DELETED,
} init_state_{INIT};
enum RunningState : uint8_t {
STARTING, STARTING,
RUNNING, RUNNING,
STOPPING, STOPPING,
STOPPED, STOPPED,
} running_state_{STOPPED}; DELETING,
DELETED,
} state_{INIT};
}; };
} // namespace esp32_ble_server } // namespace esp32_ble_server

View file

@ -88,15 +88,15 @@ void ESP32ImprovComponent::loop() {
case improv::STATE_STOPPED: case improv::STATE_STOPPED:
this->set_status_indicator_state_(false); this->set_status_indicator_state_(false);
if (this->service_->is_created() && this->should_start_ && this->setup_complete_) { if (this->should_start_ && this->setup_complete_) {
if (this->service_->is_running()) { if (this->service_->is_created()) {
this->service_->start();
} else if (this->service_->is_running()) {
esp32_ble::global_ble->advertising_start(); esp32_ble::global_ble->advertising_start();
this->set_state_(improv::STATE_AWAITING_AUTHORIZATION); this->set_state_(improv::STATE_AWAITING_AUTHORIZATION);
this->set_error_(improv::ERROR_NONE); this->set_error_(improv::ERROR_NONE);
ESP_LOGD(TAG, "Service started!"); ESP_LOGD(TAG, "Service started!");
} else {
this->service_->start();
} }
} }
break; break;