#pragma once #include "esphome/core/component.h" #include "esphome/core/helpers.h" #include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h" #ifdef ARDUINO_ARCH_ESP32 #include #include #include #include #include namespace espbt = esphome::esp32_ble_tracker; namespace esphome { namespace ble_client { class BLEClient; class BLEService; class BLECharacteristic; class BLEClientNode { public: virtual void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) = 0; virtual void loop() = 0; void set_address(uint64_t address) { address_ = address; } espbt::ESPBTClient *client; // This should be transitioned to Established once the node no longer needs // the services/descriptors/characteristics of the parent client. This will // allow some memory to be freed. espbt::ClientState node_state; BLEClient *parent() { return this->parent_; } void set_ble_client_parent(BLEClient *parent) { this->parent_ = parent; } protected: BLEClient *parent_; uint64_t address_; }; class BLEDescriptor { public: espbt::ESPBTUUID uuid; uint16_t handle; BLECharacteristic *characteristic; }; class BLECharacteristic { public: ~BLECharacteristic(); espbt::ESPBTUUID uuid; uint16_t handle; esp_gatt_char_prop_t properties; std::vector descriptors; void parse_descriptors(); BLEDescriptor *get_descriptor(espbt::ESPBTUUID uuid); BLEDescriptor *get_descriptor(uint16_t uuid); BLEService *service; }; class BLEService { public: ~BLEService(); espbt::ESPBTUUID uuid; uint16_t start_handle; uint16_t end_handle; std::vector characteristics; BLEClient *client; void parse_characteristics(); BLECharacteristic *get_characteristic(espbt::ESPBTUUID uuid); BLECharacteristic *get_characteristic(uint16_t uuid); }; class BLEClient : public espbt::ESPBTClient, public Component { public: void setup() override; void dump_config() override; void loop() override; void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param); bool parse_device(const espbt::ESPBTDevice &device) override; void on_scan_end() override {} void connect(); void set_address(uint64_t address) { this->address = address; } void set_enabled(bool enabled); void register_ble_node(BLEClientNode *node) { node->client = this; node->set_ble_client_parent(this); this->nodes_.push_back(node); } BLEService *get_service(espbt::ESPBTUUID uuid); BLEService *get_service(uint16_t uuid); BLECharacteristic *get_characteristic(espbt::ESPBTUUID service, espbt::ESPBTUUID chr); BLECharacteristic *get_characteristic(uint16_t service, uint16_t chr); BLEDescriptor *get_descriptor(espbt::ESPBTUUID service, espbt::ESPBTUUID chr, espbt::ESPBTUUID descr); BLEDescriptor *get_descriptor(uint16_t service, uint16_t chr, uint16_t descr); // Get the configuration descriptor for the given characteristic handle. BLEDescriptor *get_config_descriptor(uint16_t handle); float parse_char_value(uint8_t *value, uint16_t length); int gattc_if; esp_bd_addr_t remote_bda; uint16_t conn_id; uint64_t address; bool enabled; std::string address_str() const; protected: void set_states(espbt::ClientState st) { this->set_state(st); for (auto &node : nodes_) node->node_state = st; } bool all_nodes_established() { if (this->state() != espbt::ClientState::Established) return false; for (auto &node : nodes_) if (node->node_state != espbt::ClientState::Established) return false; return true; } std::vector nodes_; std::vector services_; }; } // namespace ble_client } // namespace esphome #endif