ESPHome 2025.10.0-dev
Loading...
Searching...
No Matches
ble_uuid.cpp
Go to the documentation of this file.
1#include "ble_uuid.h"
2
3#ifdef USE_ESP32
4#ifdef USE_ESP32_BLE_UUID
5
6#include <cstring>
7#include <cstdio>
8#include <cinttypes>
9#include "esphome/core/log.h"
11
12namespace esphome::esp32_ble {
13
14static const char *const TAG = "esp32_ble";
15
18 ESPBTUUID ret;
19 ret.uuid_.len = ESP_UUID_LEN_16;
20 ret.uuid_.uuid.uuid16 = uuid;
21 return ret;
22}
24 ESPBTUUID ret;
25 ret.uuid_.len = ESP_UUID_LEN_32;
26 ret.uuid_.uuid.uuid32 = uuid;
27 return ret;
28}
29ESPBTUUID ESPBTUUID::from_raw(const uint8_t *data) {
30 ESPBTUUID ret;
31 ret.uuid_.len = ESP_UUID_LEN_128;
32 memcpy(ret.uuid_.uuid.uuid128, data, ESP_UUID_LEN_128);
33 return ret;
34}
36 ESPBTUUID ret;
37 ret.uuid_.len = ESP_UUID_LEN_128;
38 for (uint8_t i = 0; i < ESP_UUID_LEN_128; i++)
39 ret.uuid_.uuid.uuid128[ESP_UUID_LEN_128 - 1 - i] = data[i];
40 return ret;
41}
42ESPBTUUID ESPBTUUID::from_raw(const std::string &data) {
43 ESPBTUUID ret;
44 if (data.length() == 4) {
45 ret.uuid_.len = ESP_UUID_LEN_16;
46 ret.uuid_.uuid.uuid16 = 0;
47 for (uint i = 0; i < data.length(); i += 2) {
48 uint8_t msb = data.c_str()[i];
49 uint8_t lsb = data.c_str()[i + 1];
50 uint8_t lsb_shift = i <= 2 ? (2 - i) * 4 : 0;
51
52 if (msb > '9')
53 msb -= 7;
54 if (lsb > '9')
55 lsb -= 7;
56 ret.uuid_.uuid.uuid16 += (((msb & 0x0F) << 4) | (lsb & 0x0F)) << lsb_shift;
57 }
58 } else if (data.length() == 8) {
59 ret.uuid_.len = ESP_UUID_LEN_32;
60 ret.uuid_.uuid.uuid32 = 0;
61 for (uint i = 0; i < data.length(); i += 2) {
62 uint8_t msb = data.c_str()[i];
63 uint8_t lsb = data.c_str()[i + 1];
64 uint8_t lsb_shift = i <= 6 ? (6 - i) * 4 : 0;
65
66 if (msb > '9')
67 msb -= 7;
68 if (lsb > '9')
69 lsb -= 7;
70 ret.uuid_.uuid.uuid32 += (((msb & 0x0F) << 4) | (lsb & 0x0F)) << lsb_shift;
71 }
72 } else if (data.length() == 16) { // how we can have 16 byte length string reprezenting 128 bit uuid??? needs to be
73 // investigated (lack of time)
74 ret.uuid_.len = ESP_UUID_LEN_128;
75 memcpy(ret.uuid_.uuid.uuid128, (uint8_t *) data.data(), 16);
76 } else if (data.length() == 36) {
77 // If the length of the string is 36 bytes then we will assume it is a long hex string in
78 // UUID format.
79 ret.uuid_.len = ESP_UUID_LEN_128;
80 int n = 0;
81 for (uint i = 0; i < data.length(); i += 2) {
82 if (data.c_str()[i] == '-')
83 i++;
84 uint8_t msb = data.c_str()[i];
85 uint8_t lsb = data.c_str()[i + 1];
86
87 if (msb > '9')
88 msb -= 7;
89 if (lsb > '9')
90 lsb -= 7;
91 ret.uuid_.uuid.uuid128[15 - n++] = ((msb & 0x0F) << 4) | (lsb & 0x0F);
92 }
93 } else {
94 ESP_LOGE(TAG, "ERROR: UUID value not 2, 4, 16 or 36 bytes - %s", data.c_str());
95 }
96 return ret;
97}
98ESPBTUUID ESPBTUUID::from_uuid(esp_bt_uuid_t uuid) {
99 ESPBTUUID ret;
100 ret.uuid_.len = uuid.len;
101 if (uuid.len == ESP_UUID_LEN_16) {
102 ret.uuid_.uuid.uuid16 = uuid.uuid.uuid16;
103 } else if (uuid.len == ESP_UUID_LEN_32) {
104 ret.uuid_.uuid.uuid32 = uuid.uuid.uuid32;
105 } else if (uuid.len == ESP_UUID_LEN_128) {
106 memcpy(ret.uuid_.uuid.uuid128, uuid.uuid.uuid128, ESP_UUID_LEN_128);
107 }
108 return ret;
109}
111 if (this->uuid_.len == ESP_UUID_LEN_128) {
112 return *this;
113 }
114 uint8_t data[] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
115 uint32_t uuid32;
116 if (this->uuid_.len == ESP_UUID_LEN_32) {
117 uuid32 = this->uuid_.uuid.uuid32;
118 } else {
119 uuid32 = this->uuid_.uuid.uuid16;
120 }
121 for (uint8_t i = 0; i < this->uuid_.len; i++) {
122 data[12 + i] = ((uuid32 >> i * 8) & 0xFF);
123 }
124 return ESPBTUUID::from_raw(data);
125}
126bool ESPBTUUID::contains(uint8_t data1, uint8_t data2) const {
127 if (this->uuid_.len == ESP_UUID_LEN_16) {
128 return (this->uuid_.uuid.uuid16 >> 8) == data2 && (this->uuid_.uuid.uuid16 & 0xFF) == data1;
129 } else if (this->uuid_.len == ESP_UUID_LEN_32) {
130 for (uint8_t i = 0; i < 3; i++) {
131 bool a = ((this->uuid_.uuid.uuid32 >> i * 8) & 0xFF) == data1;
132 bool b = ((this->uuid_.uuid.uuid32 >> (i + 1) * 8) & 0xFF) == data2;
133 if (a && b)
134 return true;
135 }
136 } else {
137 for (uint8_t i = 0; i < 15; i++) {
138 if (this->uuid_.uuid.uuid128[i] == data1 && this->uuid_.uuid.uuid128[i + 1] == data2)
139 return true;
140 }
141 }
142 return false;
143}
144bool ESPBTUUID::operator==(const ESPBTUUID &uuid) const {
145 if (this->uuid_.len == uuid.uuid_.len) {
146 switch (this->uuid_.len) {
147 case ESP_UUID_LEN_16:
148 if (uuid.uuid_.uuid.uuid16 == this->uuid_.uuid.uuid16) {
149 return true;
150 }
151 break;
152 case ESP_UUID_LEN_32:
153 if (uuid.uuid_.uuid.uuid32 == this->uuid_.uuid.uuid32) {
154 return true;
155 }
156 break;
157 case ESP_UUID_LEN_128:
158 for (uint8_t i = 0; i < ESP_UUID_LEN_128; i++) {
159 if (uuid.uuid_.uuid.uuid128[i] != this->uuid_.uuid.uuid128[i]) {
160 return false;
161 }
162 }
163 return true;
164 break;
165 }
166 } else {
167 return this->as_128bit() == uuid.as_128bit();
168 }
169 return false;
170}
171esp_bt_uuid_t ESPBTUUID::get_uuid() const { return this->uuid_; }
172std::string ESPBTUUID::to_string() const {
173 char buf[40]; // Enough for 128-bit UUID with dashes
174 char *pos = buf;
175
176 switch (this->uuid_.len) {
177 case ESP_UUID_LEN_16:
178 *pos++ = '0';
179 *pos++ = 'x';
180 *pos++ = format_hex_pretty_char(this->uuid_.uuid.uuid16 >> 12);
181 *pos++ = format_hex_pretty_char((this->uuid_.uuid.uuid16 >> 8) & 0x0F);
182 *pos++ = format_hex_pretty_char((this->uuid_.uuid.uuid16 >> 4) & 0x0F);
183 *pos++ = format_hex_pretty_char(this->uuid_.uuid.uuid16 & 0x0F);
184 *pos = '\0';
185 return std::string(buf);
186
187 case ESP_UUID_LEN_32:
188 *pos++ = '0';
189 *pos++ = 'x';
190 for (int shift = 28; shift >= 0; shift -= 4) {
191 *pos++ = format_hex_pretty_char((this->uuid_.uuid.uuid32 >> shift) & 0x0F);
192 }
193 *pos = '\0';
194 return std::string(buf);
195
196 default:
197 case ESP_UUID_LEN_128:
198 // Format: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
199 for (int8_t i = 15; i >= 0; i--) {
200 uint8_t byte = this->uuid_.uuid.uuid128[i];
201 *pos++ = format_hex_pretty_char(byte >> 4);
202 *pos++ = format_hex_pretty_char(byte & 0x0F);
203 if (i == 12 || i == 10 || i == 8 || i == 6) {
204 *pos++ = '-';
205 }
206 }
207 *pos = '\0';
208 return std::string(buf);
209 }
210 return "";
211}
212
213} // namespace esphome::esp32_ble
214
215#endif // USE_ESP32_BLE_UUID
216#endif // USE_ESP32
std::string to_string() const
Definition ble_uuid.cpp:172
static ESPBTUUID from_uuid(esp_bt_uuid_t uuid)
Definition ble_uuid.cpp:98
static ESPBTUUID from_uint32(uint32_t uuid)
Definition ble_uuid.cpp:23
static ESPBTUUID from_uint16(uint16_t uuid)
Definition ble_uuid.cpp:17
bool operator==(const ESPBTUUID &uuid) const
Definition ble_uuid.cpp:144
static ESPBTUUID from_raw(const uint8_t *data)
Definition ble_uuid.cpp:29
static ESPBTUUID from_raw_reversed(const uint8_t *data)
Definition ble_uuid.cpp:35
esp_bt_uuid_t get_uuid() const
Definition ble_uuid.cpp:171
ESPBTUUID as_128bit() const
Definition ble_uuid.cpp:110
bool contains(uint8_t data1, uint8_t data2) const
Definition ble_uuid.cpp:126
char format_hex_pretty_char(uint8_t v)
Convert a nibble (0-15) to uppercase hex char (used for pretty printing) This always uses uppercase (...
Definition helpers.h:399