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