14static constexpr size_t BLE_WRITE_MAX_LOG_BYTES = 64;
22 static const char *
const TAG;
31 void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param)
final {
32 if (event == ESP_GATTC_SEARCH_CMPL_EVT)
33 this->
node_state = espbt::ClientState::ESTABLISHED;
39 virtual void on_gattc_event(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) {}
48 esp_ble_gattc_cb_param_t *param)
override {
49 if (event == ESP_GATTC_SEARCH_CMPL_EVT) {
50 this->
node_state = espbt::ClientState::ESTABLISHED;
62 esp_ble_gattc_cb_param_t *param)
override {
66 case ESP_GATTC_SEARCH_CMPL_EVT: {
67 this->
node_state = espbt::ClientState::ESTABLISHED;
70 case ESP_GATTC_CLOSE_EVT: {
85 void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
override {
86 if (event == ESP_GAP_BLE_PASSKEY_REQ_EVT && this->
parent_->
check_addr(param->ble_security.auth_cmpl.bd_addr))
95 void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
override {
96 if (event == ESP_GAP_BLE_PASSKEY_NOTIF_EVT && this->
parent_->
check_addr(param->ble_security.auth_cmpl.bd_addr)) {
97 this->
trigger(param->ble_security.key_notif.passkey);
107 if (event == ESP_GAP_BLE_NC_REQ_EVT && this->
parent_->
check_addr(param->ble_security.auth_cmpl.bd_addr)) {
108 this->
trigger(param->ble_security.key_notif.passkey);
118 ble_client_ = ble_client;
121 void set_service_uuid16(uint16_t uuid) { this->service_uuid_ = espbt::ESPBTUUID::from_uint16(uuid); }
125 void set_char_uuid16(uint16_t uuid) { this->char_uuid_ = espbt::ESPBTUUID::from_uint16(uuid); }
127 void set_char_uuid128(uint8_t *uuid) { this->char_uuid_ = espbt::ESPBTUUID::from_raw(uuid); }
130 this->value_.func = func;
136 this->value_.data = data;
140 void play(
const Ts &...
x)
override {}
144 this->var_ = std::make_tuple(
x...);
147 if (this->len_ >= 0) {
149 result = this->
write(this->value_.data, this->len_);
152 std::vector<uint8_t> value = this->value_.func(
x...);
153 result = this->
write(value);
171 if (this->
node_state != espbt::ClientState::ESTABLISHED) {
172 esph_log_w(
Automation::TAG,
"Cannot write to BLE characteristic - not connected");
175#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE
180 esp_ble_gattc_write_char(this->
parent()->get_gattc_if(), this->
parent()->get_conn_id(), this->char_handle_,
len,
181 const_cast<uint8_t *
>(data), this->write_type_, ESP_GATT_AUTH_REQ_NONE);
183 esph_log_e(
Automation::TAG,
"Error writing to characteristic: %s!", esp_err_to_name(err));
189 bool write(
const std::vector<uint8_t> &value) {
return this->
write(value.data(), value.size()); }
192 esp_ble_gattc_cb_param_t *param)
override {
194 case ESP_GATTC_WRITE_CHAR_EVT:
196 if (param->write.handle == this->char_handle_)
199 case ESP_GATTC_DISCONNECT_EVT:
203 case ESP_GATTC_SEARCH_CMPL_EVT: {
205 if (chr ==
nullptr) {
206 char char_buf[esp32_ble::UUID_STR_LEN];
207 char service_buf[esp32_ble::UUID_STR_LEN];
208 esph_log_w(
"ble_write_action",
"Characteristic %s was not found in service %s",
209 this->char_uuid_.
to_str(char_buf), this->service_uuid_.to_str(service_buf));
212 this->char_handle_ = chr->handle;
213 this->char_props_ = chr->properties;
214 if (this->char_props_ & ESP_GATT_CHAR_PROP_BIT_WRITE) {
215 this->write_type_ = ESP_GATT_WRITE_TYPE_RSP;
217 }
else if (this->char_props_ & ESP_GATT_CHAR_PROP_BIT_WRITE_NR) {
218 this->write_type_ = ESP_GATT_WRITE_TYPE_NO_RSP;
221 char char_buf[esp32_ble::UUID_STR_LEN];
222 esph_log_e(
Automation::TAG,
"Characteristic %s does not allow writing", this->char_uuid_.
to_str(char_buf));
225 this->
node_state = espbt::ClientState::ESTABLISHED;
226 char char_buf[esp32_ble::UUID_STR_LEN];
227 esph_log_d(
Automation::TAG,
"Found characteristic %s on device %s", this->char_uuid_.
to_str(char_buf),
240 std::vector<uint8_t> (*func)(Ts...);
245 std::tuple<Ts...> var_{};
246 uint16_t char_handle_{};
247 esp_gatt_char_prop_t char_props_{};
248 esp_gatt_write_type_t write_type_{};
255 void play(
const Ts &...
x)
override {
257 if (has_simple_value_) {
258 passkey = this->value_.simple;
260 passkey = this->value_.template_func(
x...);
262 if (passkey > 999999)
264 esp_bd_addr_t remote_bda;
265 memcpy(remote_bda, parent_->
get_remote_bda(),
sizeof(esp_bd_addr_t));
266 esp_ble_passkey_reply(remote_bda,
true, passkey);
270 this->value_.template_func = func;
271 this->has_simple_value_ =
false;
275 this->value_.simple = value;
276 this->has_simple_value_ =
true;
281 bool has_simple_value_ =
true;
285 } value_{.simple = 0};
292 void play(
const Ts &...
x)
override {
293 esp_bd_addr_t remote_bda;
294 memcpy(remote_bda, parent_->
get_remote_bda(),
sizeof(esp_bd_addr_t));
295 if (has_simple_value_) {
296 esp_ble_confirm_reply(remote_bda, this->value_.simple);
298 esp_ble_confirm_reply(remote_bda, this->value_.template_func(
x...));
303 this->value_.template_func = func;
304 this->has_simple_value_ =
false;
308 this->value_.simple = value;
309 this->has_simple_value_ =
true;
314 bool has_simple_value_ =
true;
318 } value_{.simple =
false};
325 void play(
const Ts &...
x)
override {
326 esp_bd_addr_t remote_bda;
327 memcpy(remote_bda, parent_->
get_remote_bda(),
sizeof(esp_bd_addr_t));
328 esp_ble_remove_bond_device(remote_bda);
339 ble_client_ = ble_client;
341 void on_gattc_event(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param)
override {
345 case ESP_GATTC_SEARCH_CMPL_EVT:
349 case ESP_GATTC_DISCONNECT_EVT:
358 void play(
const Ts &...
x)
override {}
369 if (this->
node_state == espbt::ClientState::ESTABLISHED) {
372 this->var_ = std::make_tuple(
x...);
379 std::tuple<Ts...> var_{};
386 ble_client_ = ble_client;
388 void on_gattc_event(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param)
override {
392 case ESP_GATTC_CLOSE_EVT:
393 case ESP_GATTC_DISCONNECT_EVT:
402 void play(
const Ts &...
x)
override {}
406 if (this->
node_state == espbt::ClientState::IDLE) {
409 this->var_ = std::make_tuple(
x...);
416 std::tuple<Ts...> var_{};
void play_next_(const Ts &...x)
virtual void stop_complex()
void play_next_tuple_(const std::tuple< Ts... > &tuple, std::index_sequence< S... >)
void trigger(const Ts &...x) ESPHOME_ALWAYS_INLINE
static const char *const TAG
void on_gattc_event(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) override
void play_complex(const Ts &...x) override
BLEClientConnectAction(BLEClient *ble_client)
void play(const Ts &...x) override
void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) override
BLEClientConnectTrigger(BLEClient *parent)
void play_complex(const Ts &...x) override
void play(const Ts &...x) override
BLEClientDisconnectAction(BLEClient *ble_client)
void on_gattc_event(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) override
void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) override
BLEClientDisconnectTrigger(BLEClient *parent)
void register_ble_node(BLEClientNode *node)
espbt::ClientState node_state
BLEClientNumericComparisonReplyAction(BLEClient *ble_client)
void set_value_template(bool(*func)(Ts...))
void set_value_simple(const bool &value)
void play(const Ts &...x) override
bool(* template_func)(Ts...)
void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override
BLEClientNumericComparisonRequestTrigger(BLEClient *parent)
void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override
BLEClientPasskeyNotificationTrigger(BLEClient *parent)
uint32_t(* template_func)(Ts...)
void play(const Ts &...x) override
void set_value_template(uint32_t(*func)(Ts...))
void set_value_simple(const uint32_t &value)
BLEClientPasskeyReplyAction(BLEClient *ble_client)
void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override
BLEClientPasskeyRequestTrigger(BLEClient *parent)
void play(const Ts &...x) override
BLEClientRemoveBondAction(BLEClient *ble_client)
void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) final
virtual void on_gattc_event(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param)
bool write(const uint8_t *data, size_t len)
Note about logging: the esph_log_X macros are used here because the CI checks complain about use of t...
void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) override
void set_service_uuid16(uint16_t uuid)
void set_value_template(std::vector< uint8_t >(*func)(Ts...))
void play(const Ts &...x) override
void set_char_uuid128(uint8_t *uuid)
void set_char_uuid32(uint32_t uuid)
void play_complex(const Ts &...x) override
void set_service_uuid128(uint8_t *uuid)
void set_service_uuid32(uint32_t uuid)
BLEClientWriteAction(BLEClient *ble_client)
bool write(const std::vector< uint8_t > &value)
void set_char_uuid16(uint16_t uuid)
void set_value_simple(const uint8_t *data, size_t len)
const char * to_str(char *buf) const
Write "0xABCD" / "0xABCDEF01" / the dashed 128-bit form, or "None" for an unset UUID,...
uint8_t * get_remote_bda()
const char * address_str() const
BLECharacteristic * get_characteristic(espbt::ESPBTUUID service, espbt::ESPBTUUID chr)
void disconnect() override
bool check_addr(esp_bd_addr_t &addr)
void run_later(std::function< void()> &&f)
char * format_hex_pretty_to(char *buffer, size_t buffer_size, const uint8_t *data, size_t length, char separator)
Format byte array as uppercase hex to buffer (base implementation).
constexpr size_t format_hex_pretty_size(size_t byte_count)
Calculate buffer size needed for format_hex_pretty_to with separator: "XX:XX:...:XX\0".