mirror of
https://github.com/esphome/esphome.git
synced 2025-09-28 16:12:24 +01:00
147 lines
5.3 KiB
C++
147 lines
5.3 KiB
C++
#pragma once
|
|
|
|
#include "ble_server.h"
|
|
#include "ble_characteristic.h"
|
|
#include "ble_descriptor.h"
|
|
|
|
#include "esphome/components/event_emitter/event_emitter.h"
|
|
#include "esphome/core/automation.h"
|
|
|
|
#include <vector>
|
|
#include <functional>
|
|
|
|
#ifdef USE_ESP32
|
|
|
|
namespace esphome {
|
|
namespace esp32_ble_server {
|
|
// Interface to interact with ESPHome actions and triggers
|
|
namespace esp32_ble_server_automations {
|
|
|
|
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 {
|
|
public:
|
|
#ifdef USE_ESP32_BLE_SERVER_CHARACTERISTIC_ON_WRITE
|
|
static Trigger<std::vector<uint8_t>, uint16_t> *create_characteristic_on_write_trigger(
|
|
BLECharacteristic *characteristic);
|
|
#endif
|
|
#ifdef USE_ESP32_BLE_SERVER_DESCRIPTOR_ON_WRITE
|
|
static Trigger<std::vector<uint8_t>, uint16_t> *create_descriptor_on_write_trigger(BLEDescriptor *descriptor);
|
|
#endif
|
|
#ifdef USE_ESP32_BLE_SERVER_ON_CONNECT
|
|
static Trigger<uint16_t> *create_server_on_connect_trigger(BLEServer *server);
|
|
#endif
|
|
#ifdef USE_ESP32_BLE_SERVER_ON_DISCONNECT
|
|
static Trigger<uint16_t> *create_server_on_disconnect_trigger(BLEServer *server);
|
|
#endif
|
|
};
|
|
|
|
#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 BLECharacteristicSetValueActionManager
|
|
: public EventEmitter<BLECharacteristicSetValueActionEvt, BLECharacteristic *> {
|
|
public:
|
|
// Singleton pattern
|
|
static BLECharacteristicSetValueActionManager *get_instance() {
|
|
static BLECharacteristicSetValueActionManager instance;
|
|
return &instance;
|
|
}
|
|
void set_listener(BLECharacteristic *characteristic, EventEmitterListenerID listener_id,
|
|
const std::function<void()> &pre_notify_listener);
|
|
EventEmitterListenerID get_listener(BLECharacteristic *characteristic) {
|
|
for (const auto &entry : this->listeners_) {
|
|
if (entry.characteristic == characteristic) {
|
|
return entry.listener_id;
|
|
}
|
|
}
|
|
return INVALID_LISTENER_ID;
|
|
}
|
|
void emit_pre_notify(BLECharacteristic *characteristic) {
|
|
this->emit_(BLECharacteristicSetValueActionEvt::PRE_NOTIFY, characteristic);
|
|
}
|
|
|
|
private:
|
|
struct ListenerEntry {
|
|
BLECharacteristic *characteristic;
|
|
EventEmitterListenerID listener_id;
|
|
EventEmitterListenerID pre_notify_listener_id;
|
|
};
|
|
std::vector<ListenerEntry> listeners_;
|
|
|
|
ListenerEntry *find_listener_(BLECharacteristic *characteristic);
|
|
void remove_listener_(BLECharacteristic *characteristic);
|
|
};
|
|
|
|
template<typename... Ts> class BLECharacteristicSetValueAction : public Action<Ts...> {
|
|
public:
|
|
BLECharacteristicSetValueAction(BLECharacteristic *characteristic) : parent_(characteristic) {}
|
|
TEMPLATABLE_VALUE(std::vector<uint8_t>, buffer)
|
|
void set_buffer(ByteBuffer buffer) { this->set_buffer(buffer.get_data()); }
|
|
void play(Ts... x) override {
|
|
// If the listener is already set, do nothing
|
|
if (BLECharacteristicSetValueActionManager::get_instance()->get_listener(this->parent_) == this->listener_id_)
|
|
return;
|
|
// Set initial value
|
|
this->parent_->set_value(this->buffer_.value(x...));
|
|
// Set the listener for read events
|
|
this->listener_id_ = this->parent_->EventEmitter<BLECharacteristicEvt::EmptyEvt, uint16_t>::on(
|
|
BLECharacteristicEvt::EmptyEvt::ON_READ, [this, x...](uint16_t id) {
|
|
// Set the value of the characteristic every time it is read
|
|
this->parent_->set_value(this->buffer_.value(x...));
|
|
});
|
|
// Set the listener in the global manager so only one BLECharacteristicSetValueAction is set for each characteristic
|
|
BLECharacteristicSetValueActionManager::get_instance()->set_listener(
|
|
this->parent_, this->listener_id_, [this, x...]() { this->parent_->set_value(this->buffer_.value(x...)); });
|
|
}
|
|
|
|
protected:
|
|
BLECharacteristic *parent_;
|
|
EventEmitterListenerID listener_id_;
|
|
};
|
|
#endif // USE_ESP32_BLE_SERVER_SET_VALUE_ACTION
|
|
|
|
#ifdef USE_ESP32_BLE_SERVER_NOTIFY_ACTION
|
|
template<typename... Ts> class BLECharacteristicNotifyAction : public Action<Ts...> {
|
|
public:
|
|
BLECharacteristicNotifyAction(BLECharacteristic *characteristic) : parent_(characteristic) {}
|
|
void play(Ts... x) override {
|
|
#ifdef USE_ESP32_BLE_SERVER_SET_VALUE_ACTION
|
|
// Call the pre-notify event
|
|
BLECharacteristicSetValueActionManager::get_instance()->emit_pre_notify(this->parent_);
|
|
#endif
|
|
// Notify the characteristic
|
|
this->parent_->notify();
|
|
}
|
|
|
|
protected:
|
|
BLECharacteristic *parent_;
|
|
};
|
|
#endif // USE_ESP32_BLE_SERVER_NOTIFY_ACTION
|
|
|
|
#ifdef USE_ESP32_BLE_SERVER_DESCRIPTOR_SET_VALUE_ACTION
|
|
template<typename... Ts> class BLEDescriptorSetValueAction : public Action<Ts...> {
|
|
public:
|
|
BLEDescriptorSetValueAction(BLEDescriptor *descriptor) : parent_(descriptor) {}
|
|
TEMPLATABLE_VALUE(std::vector<uint8_t>, buffer)
|
|
void set_buffer(ByteBuffer buffer) { this->set_buffer(buffer.get_data()); }
|
|
void play(Ts... x) override { this->parent_->set_value(this->buffer_.value(x...)); }
|
|
|
|
protected:
|
|
BLEDescriptor *parent_;
|
|
};
|
|
#endif // USE_ESP32_BLE_SERVER_DESCRIPTOR_SET_VALUE_ACTION
|
|
|
|
} // namespace esp32_ble_server_automations
|
|
} // namespace esp32_ble_server
|
|
} // namespace esphome
|
|
|
|
#endif
|