2021-06-08 01:56:21 +02:00
|
|
|
#include "ble_service.h"
|
|
|
|
#include "ble_server.h"
|
|
|
|
#include "esphome/core/log.h"
|
|
|
|
|
2021-09-20 11:47:51 +02:00
|
|
|
#ifdef USE_ESP32
|
2021-06-08 01:56:21 +02:00
|
|
|
|
|
|
|
namespace esphome {
|
2021-06-11 22:31:15 +02:00
|
|
|
namespace esp32_ble_server {
|
2021-06-08 01:56:21 +02:00
|
|
|
|
2021-06-11 22:31:15 +02:00
|
|
|
static const char *const TAG = "esp32_ble_server.service";
|
2021-06-08 01:56:21 +02:00
|
|
|
|
2023-11-06 03:54:39 +01:00
|
|
|
BLEService::BLEService(ESPBTUUID uuid, uint16_t num_handles, uint8_t inst_id, bool advertise)
|
|
|
|
: uuid_(uuid), num_handles_(num_handles), inst_id_(inst_id), advertise_(advertise) {}
|
2021-06-08 01:56:21 +02:00
|
|
|
|
|
|
|
BLEService::~BLEService() {
|
|
|
|
for (auto &chr : this->characteristics_)
|
2021-09-13 18:11:27 +02:00
|
|
|
delete chr; // NOLINT(cppcoreguidelines-owning-memory)
|
2021-06-08 01:56:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
BLECharacteristic *BLEService::get_characteristic(ESPBTUUID uuid) {
|
2022-01-24 20:56:36 +01:00
|
|
|
for (auto *chr : this->characteristics_) {
|
2021-06-08 01:56:21 +02:00
|
|
|
if (chr->get_uuid() == uuid)
|
|
|
|
return chr;
|
2022-01-24 20:56:36 +01:00
|
|
|
}
|
2021-06-08 01:56:21 +02:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
BLECharacteristic *BLEService::get_characteristic(uint16_t uuid) {
|
|
|
|
return this->get_characteristic(ESPBTUUID::from_uint16(uuid));
|
|
|
|
}
|
|
|
|
BLECharacteristic *BLEService::create_characteristic(uint16_t uuid, esp_gatt_char_prop_t properties) {
|
|
|
|
return create_characteristic(ESPBTUUID::from_uint16(uuid), properties);
|
|
|
|
}
|
2021-06-08 22:45:51 +02:00
|
|
|
BLECharacteristic *BLEService::create_characteristic(const std::string &uuid, esp_gatt_char_prop_t properties) {
|
2021-06-08 01:56:21 +02:00
|
|
|
return create_characteristic(ESPBTUUID::from_raw(uuid), properties);
|
|
|
|
}
|
|
|
|
BLECharacteristic *BLEService::create_characteristic(ESPBTUUID uuid, esp_gatt_char_prop_t properties) {
|
2021-09-13 18:11:27 +02:00
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
|
2021-06-08 01:56:21 +02:00
|
|
|
BLECharacteristic *characteristic = new BLECharacteristic(uuid, properties);
|
|
|
|
this->characteristics_.push_back(characteristic);
|
|
|
|
return characteristic;
|
|
|
|
}
|
|
|
|
|
2021-06-10 04:04:39 +02:00
|
|
|
void BLEService::do_create(BLEServer *server) {
|
2021-06-08 01:56:21 +02:00
|
|
|
this->server_ = server;
|
|
|
|
|
|
|
|
esp_gatt_srvc_id_t srvc_id;
|
|
|
|
srvc_id.is_primary = true;
|
|
|
|
srvc_id.id.inst_id = this->inst_id_;
|
|
|
|
srvc_id.id.uuid = this->uuid_.get_uuid();
|
|
|
|
|
|
|
|
esp_err_t err = esp_ble_gatts_create_service(server->get_gatts_if(), &srvc_id, this->num_handles_);
|
|
|
|
if (err != ESP_OK) {
|
|
|
|
ESP_LOGE(TAG, "esp_ble_gatts_create_service failed: %d", err);
|
2021-06-10 04:04:39 +02:00
|
|
|
this->init_state_ = FAILED;
|
|
|
|
return;
|
2021-06-08 01:56:21 +02:00
|
|
|
}
|
2021-06-10 04:04:39 +02:00
|
|
|
this->init_state_ = CREATING;
|
|
|
|
}
|
|
|
|
|
2023-11-06 03:54:39 +01:00
|
|
|
void BLEService::do_delete() {
|
|
|
|
if (this->init_state_ == DELETING || this->init_state_ == DELETED)
|
|
|
|
return;
|
|
|
|
this->init_state_ = DELETING;
|
|
|
|
this->created_characteristic_count_ = 0;
|
|
|
|
this->last_created_characteristic_ = nullptr;
|
|
|
|
this->stop_();
|
|
|
|
esp_err_t err = esp_ble_gatts_delete_service(this->handle_);
|
|
|
|
if (err != ESP_OK) {
|
|
|
|
ESP_LOGE(TAG, "esp_ble_gatts_delete_service failed: %d", err);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-10 04:04:39 +02:00
|
|
|
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.
|
2021-06-08 01:56:21 +02:00
|
|
|
|
2021-06-10 04:04:39 +02:00
|
|
|
auto *characteristic = this->characteristics_[this->created_characteristic_count_++];
|
|
|
|
this->last_created_characteristic_ = characteristic;
|
|
|
|
characteristic->do_create(this);
|
2021-06-08 01:56:21 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BLEService::start() {
|
2021-06-10 04:04:39 +02:00
|
|
|
if (this->do_create_characteristics_())
|
|
|
|
return;
|
2023-11-06 03:54:39 +01:00
|
|
|
should_start_ = true;
|
2021-06-08 01:56:21 +02:00
|
|
|
|
|
|
|
esp_err_t err = esp_ble_gatts_start_service(this->handle_);
|
|
|
|
if (err != ESP_OK) {
|
|
|
|
ESP_LOGE(TAG, "esp_ble_gatts_start_service failed: %d", err);
|
|
|
|
return;
|
|
|
|
}
|
2023-11-06 03:54:39 +01:00
|
|
|
if (this->advertise_)
|
|
|
|
esp32_ble::global_ble->advertising_add_service_uuid(this->uuid_);
|
2021-06-10 04:04:39 +02:00
|
|
|
this->running_state_ = STARTING;
|
2021-06-08 01:56:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void BLEService::stop() {
|
2023-11-06 03:54:39 +01:00
|
|
|
should_start_ = false;
|
|
|
|
this->stop_();
|
|
|
|
}
|
|
|
|
|
|
|
|
void BLEService::stop_() {
|
|
|
|
if (this->running_state_ == STOPPING || this->running_state_ == STOPPED)
|
|
|
|
return;
|
|
|
|
this->running_state_ = STOPPING;
|
2021-06-08 01:56:21 +02:00
|
|
|
esp_err_t err = esp_ble_gatts_stop_service(this->handle_);
|
|
|
|
if (err != ESP_OK) {
|
|
|
|
ESP_LOGE(TAG, "esp_ble_gatts_stop_service failed: %d", err);
|
|
|
|
return;
|
|
|
|
}
|
2023-11-06 03:54:39 +01:00
|
|
|
if (this->advertise_)
|
|
|
|
esp32_ble::global_ble->advertising_remove_service_uuid(this->uuid_);
|
2021-06-10 04:04:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2021-06-08 01:56:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void BLEService::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
|
|
|
|
esp_ble_gatts_cb_param_t *param) {
|
|
|
|
switch (event) {
|
|
|
|
case ESP_GATTS_CREATE_EVT: {
|
|
|
|
if (this->uuid_ == ESPBTUUID::from_uuid(param->create.service_id.id.uuid) &&
|
|
|
|
this->inst_id_ == param->create.service_id.id.inst_id) {
|
|
|
|
this->handle_ = param->create.service_handle;
|
2021-06-10 04:04:39 +02:00
|
|
|
this->init_state_ = CREATED;
|
2023-11-06 03:54:39 +01:00
|
|
|
if (this->should_start_)
|
|
|
|
this->start();
|
2021-06-08 01:56:21 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2023-11-06 03:54:39 +01:00
|
|
|
case ESP_GATTS_DELETE_EVT:
|
|
|
|
if (param->del.service_handle == this->handle_) {
|
|
|
|
this->init_state_ = DELETED;
|
|
|
|
}
|
|
|
|
break;
|
2021-06-08 01:56:21 +02:00
|
|
|
case ESP_GATTS_START_EVT: {
|
|
|
|
if (param->start.service_handle == this->handle_) {
|
2021-06-10 04:04:39 +02:00
|
|
|
this->running_state_ = RUNNING;
|
2021-06-08 01:56:21 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ESP_GATTS_STOP_EVT: {
|
|
|
|
if (param->start.service_handle == this->handle_) {
|
2021-06-10 04:04:39 +02:00
|
|
|
this->running_state_ = STOPPED;
|
2021-06-08 01:56:21 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto *characteristic : this->characteristics_) {
|
|
|
|
characteristic->gatts_event_handler(event, gatts_if, param);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-11 22:31:15 +02:00
|
|
|
} // namespace esp32_ble_server
|
2021-06-08 01:56:21 +02:00
|
|
|
} // namespace esphome
|
|
|
|
|
|
|
|
#endif
|