ESPHome  2022.9.1
queue.h
Go to the documentation of this file.
1 #pragma once
2 
3 #ifdef USE_ESP32
4 
6 #include "esphome/core/helpers.h"
7 
8 #include <queue>
9 #include <mutex>
10 #include <cstring>
11 
12 #include <esp_gap_ble_api.h>
13 #include <esp_gatts_api.h>
14 #include <esp_gattc_api.h>
15 #include <freertos/FreeRTOS.h>
16 #include <freertos/semphr.h>
17 
18 /*
19  * BLE events come in from a separate Task (thread) in the ESP32 stack. Rather
20  * than trying to deal with various locking strategies, all incoming GAP and GATT
21  * events will simply be placed on a semaphore guarded queue. The next time the
22  * component runs loop(), these events are popped off the queue and handed at
23  * this safer time.
24  */
25 
26 namespace esphome {
27 namespace esp32_ble {
28 
29 template<class T> class Queue {
30  public:
31  Queue() { m_ = xSemaphoreCreateMutex(); }
32 
33  void push(T *element) {
34  if (element == nullptr)
35  return;
36  if (xSemaphoreTake(m_, 5L / portTICK_PERIOD_MS)) {
37  q_.push(element);
38  xSemaphoreGive(m_);
39  }
40  }
41 
42  T *pop() {
43  T *element = nullptr;
44 
45  if (xSemaphoreTake(m_, 5L / portTICK_PERIOD_MS)) {
46  if (!q_.empty()) {
47  element = q_.front();
48  q_.pop();
49  }
50  xSemaphoreGive(m_);
51  }
52  return element;
53  }
54 
55  protected:
56  std::queue<T *> q_;
57  SemaphoreHandle_t m_;
58 };
59 
60 // Received GAP, GATTC and GATTS events are only queued, and get processed in the main loop().
61 // This class stores each event in a single type.
62 class BLEEvent {
63  public:
64  BLEEvent(esp_gap_ble_cb_event_t e, esp_ble_gap_cb_param_t *p) {
65  this->event_.gap.gap_event = e;
66  memcpy(&this->event_.gap.gap_param, p, sizeof(esp_ble_gap_cb_param_t));
67  this->type_ = GAP;
68  };
69 
70  BLEEvent(esp_gattc_cb_event_t e, esp_gatt_if_t i, esp_ble_gattc_cb_param_t *p) {
71  this->event_.gattc.gattc_event = e;
72  this->event_.gattc.gattc_if = i;
73  memcpy(&this->event_.gattc.gattc_param, p, sizeof(esp_ble_gattc_cb_param_t));
74  // Need to also make a copy of notify event data.
75  switch (e) {
76  case ESP_GATTC_NOTIFY_EVT:
77  memcpy(this->event_.gattc.data, p->notify.value, p->notify.value_len);
78  this->event_.gattc.gattc_param.notify.value = this->event_.gattc.data;
79  break;
80  case ESP_GATTC_READ_CHAR_EVT:
81  case ESP_GATTC_READ_DESCR_EVT:
82  memcpy(this->event_.gattc.data, p->read.value, p->read.value_len);
83  this->event_.gattc.gattc_param.read.value = this->event_.gattc.data;
84  break;
85  default:
86  break;
87  }
88  this->type_ = GATTC;
89  };
90 
91  BLEEvent(esp_gatts_cb_event_t e, esp_gatt_if_t i, esp_ble_gatts_cb_param_t *p) {
92  this->event_.gatts.gatts_event = e;
93  this->event_.gatts.gatts_if = i;
94  memcpy(&this->event_.gatts.gatts_param, p, sizeof(esp_ble_gatts_cb_param_t));
95  // Need to also make a copy of write data.
96  switch (e) {
97  case ESP_GATTS_WRITE_EVT:
98  memcpy(this->event_.gatts.data, p->write.value, p->write.len);
99  this->event_.gatts.gatts_param.write.value = this->event_.gatts.data;
100  break;
101  default:
102  break;
103  }
104  this->type_ = GATTS;
105  };
106 
107  union {
108  // NOLINTNEXTLINE(readability-identifier-naming)
109  struct gap_event {
110  esp_gap_ble_cb_event_t gap_event;
111  esp_ble_gap_cb_param_t gap_param;
112  } gap;
113 
114  // NOLINTNEXTLINE(readability-identifier-naming)
115  struct gattc_event {
116  esp_gattc_cb_event_t gattc_event;
117  esp_gatt_if_t gattc_if;
118  esp_ble_gattc_cb_param_t gattc_param;
119  uint8_t data[64];
120  } gattc;
121 
122  // NOLINTNEXTLINE(readability-identifier-naming)
123  struct gatts_event {
124  esp_gatts_cb_event_t gatts_event;
125  esp_gatt_if_t gatts_if;
126  esp_ble_gatts_cb_param_t gatts_param;
127  uint8_t data[64];
128  } gatts;
129  } event_;
130  // NOLINTNEXTLINE(readability-identifier-naming)
131  enum ble_event_t : uint8_t {
135  } type_;
136 };
137 
138 } // namespace esp32_ble
139 } // namespace esphome
140 
141 #endif
esp_ble_gattc_cb_param_t gattc_param
Definition: queue.h:118
std::queue< T * > q_
Definition: queue.h:56
esp_gap_ble_cb_event_t gap_event
Definition: queue.h:110
BLEEvent(esp_gap_ble_cb_event_t e, esp_ble_gap_cb_param_t *p)
Definition: queue.h:64
esp_ble_gatts_cb_param_t gatts_param
Definition: queue.h:126
BLEEvent(esp_gatts_cb_event_t e, esp_gatt_if_t i, esp_ble_gatts_cb_param_t *p)
Definition: queue.h:91
esp_gatts_cb_event_t gatts_event
Definition: queue.h:124
esp_gattc_cb_event_t gattc_event
Definition: queue.h:116
esp_ble_gap_cb_param_t gap_param
Definition: queue.h:111
esp_gatt_if_t gattc_if
Definition: queue.h:117
void push(T *element)
Definition: queue.h:33
esp_gatt_if_t gatts_if
Definition: queue.h:125
Definition: a4988.cpp:4
SemaphoreHandle_t m_
Definition: queue.h:57
BLEEvent(esp_gattc_cb_event_t e, esp_gatt_if_t i, esp_ble_gattc_cb_param_t *p)
Definition: queue.h:70