ESPHome 2025.12.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 // 16-bit UUID as 4-character hex string
46 auto parsed = parse_hex<uint16_t>(data);
47 if (parsed.has_value()) {
48 ret.uuid_.len = ESP_UUID_LEN_16;
49 ret.uuid_.uuid.uuid16 = parsed.value();
50 }
51 } else if (data.length() == 8) {
52 // 32-bit UUID as 8-character hex string
53 auto parsed = parse_hex<uint32_t>(data);
54 if (parsed.has_value()) {
55 ret.uuid_.len = ESP_UUID_LEN_32;
56 ret.uuid_.uuid.uuid32 = parsed.value();
57 }
58 } else if (data.length() == 16) { // how we can have 16 byte length string reprezenting 128 bit uuid??? needs to be
59 // investigated (lack of time)
60 ret.uuid_.len = ESP_UUID_LEN_128;
61 memcpy(ret.uuid_.uuid.uuid128, (uint8_t *) data.data(), 16);
62 } else if (data.length() == 36) {
63 // If the length of the string is 36 bytes then we will assume it is a long hex string in
64 // UUID format.
65 ret.uuid_.len = ESP_UUID_LEN_128;
66 int n = 0;
67 for (uint i = 0; i < data.length(); i += 2) {
68 if (data.c_str()[i] == '-')
69 i++;
70 uint8_t msb = data.c_str()[i];
71 uint8_t lsb = data.c_str()[i + 1];
72
73 if (msb > '9')
74 msb -= 7;
75 if (lsb > '9')
76 lsb -= 7;
77 ret.uuid_.uuid.uuid128[15 - n++] = ((msb & 0x0F) << 4) | (lsb & 0x0F);
78 }
79 } else {
80 ESP_LOGE(TAG, "ERROR: UUID value not 2, 4, 16 or 36 bytes - %s", data.c_str());
81 }
82 return ret;
83}
84ESPBTUUID ESPBTUUID::from_uuid(esp_bt_uuid_t uuid) {
85 ESPBTUUID ret;
86 ret.uuid_.len = uuid.len;
87 if (uuid.len == ESP_UUID_LEN_16) {
88 ret.uuid_.uuid.uuid16 = uuid.uuid.uuid16;
89 } else if (uuid.len == ESP_UUID_LEN_32) {
90 ret.uuid_.uuid.uuid32 = uuid.uuid.uuid32;
91 } else if (uuid.len == ESP_UUID_LEN_128) {
92 memcpy(ret.uuid_.uuid.uuid128, uuid.uuid.uuid128, ESP_UUID_LEN_128);
93 }
94 return ret;
95}
97 if (this->uuid_.len == ESP_UUID_LEN_128) {
98 return *this;
99 }
100 uint8_t data[] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
101 uint32_t uuid32;
102 if (this->uuid_.len == ESP_UUID_LEN_32) {
103 uuid32 = this->uuid_.uuid.uuid32;
104 } else {
105 uuid32 = this->uuid_.uuid.uuid16;
106 }
107 for (uint8_t i = 0; i < this->uuid_.len; i++) {
108 data[12 + i] = ((uuid32 >> i * 8) & 0xFF);
109 }
110 return ESPBTUUID::from_raw(data);
111}
112bool ESPBTUUID::contains(uint8_t data1, uint8_t data2) const {
113 if (this->uuid_.len == ESP_UUID_LEN_16) {
114 return (this->uuid_.uuid.uuid16 >> 8) == data2 && (this->uuid_.uuid.uuid16 & 0xFF) == data1;
115 } else if (this->uuid_.len == ESP_UUID_LEN_32) {
116 for (uint8_t i = 0; i < 3; i++) {
117 bool a = ((this->uuid_.uuid.uuid32 >> i * 8) & 0xFF) == data1;
118 bool b = ((this->uuid_.uuid.uuid32 >> (i + 1) * 8) & 0xFF) == data2;
119 if (a && b)
120 return true;
121 }
122 } else {
123 for (uint8_t i = 0; i < 15; i++) {
124 if (this->uuid_.uuid.uuid128[i] == data1 && this->uuid_.uuid.uuid128[i + 1] == data2)
125 return true;
126 }
127 }
128 return false;
129}
130bool ESPBTUUID::operator==(const ESPBTUUID &uuid) const {
131 if (this->uuid_.len == uuid.uuid_.len) {
132 switch (this->uuid_.len) {
133 case ESP_UUID_LEN_16:
134 return this->uuid_.uuid.uuid16 == uuid.uuid_.uuid.uuid16;
135 case ESP_UUID_LEN_32:
136 return this->uuid_.uuid.uuid32 == uuid.uuid_.uuid.uuid32;
137 case ESP_UUID_LEN_128:
138 return memcmp(this->uuid_.uuid.uuid128, uuid.uuid_.uuid.uuid128, ESP_UUID_LEN_128) == 0;
139 default:
140 return false;
141 }
142 }
143 return this->as_128bit() == uuid.as_128bit();
144}
145esp_bt_uuid_t ESPBTUUID::get_uuid() const { return this->uuid_; }
146std::string ESPBTUUID::to_string() const {
147 char buf[40]; // Enough for 128-bit UUID with dashes
148 char *pos = buf;
149
150 switch (this->uuid_.len) {
151 case ESP_UUID_LEN_16:
152 *pos++ = '0';
153 *pos++ = 'x';
154 *pos++ = format_hex_pretty_char(this->uuid_.uuid.uuid16 >> 12);
155 *pos++ = format_hex_pretty_char((this->uuid_.uuid.uuid16 >> 8) & 0x0F);
156 *pos++ = format_hex_pretty_char((this->uuid_.uuid.uuid16 >> 4) & 0x0F);
157 *pos++ = format_hex_pretty_char(this->uuid_.uuid.uuid16 & 0x0F);
158 *pos = '\0';
159 return std::string(buf);
160
161 case ESP_UUID_LEN_32:
162 *pos++ = '0';
163 *pos++ = 'x';
164 for (int shift = 28; shift >= 0; shift -= 4) {
165 *pos++ = format_hex_pretty_char((this->uuid_.uuid.uuid32 >> shift) & 0x0F);
166 }
167 *pos = '\0';
168 return std::string(buf);
169
170 default:
171 case ESP_UUID_LEN_128:
172 // Format: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
173 for (int8_t i = 15; i >= 0; i--) {
174 uint8_t byte = this->uuid_.uuid.uuid128[i];
175 *pos++ = format_hex_pretty_char(byte >> 4);
176 *pos++ = format_hex_pretty_char(byte & 0x0F);
177 if (i == 12 || i == 10 || i == 8 || i == 6) {
178 *pos++ = '-';
179 }
180 }
181 *pos = '\0';
182 return std::string(buf);
183 }
184 return "";
185}
186
187} // namespace esphome::esp32_ble
188
189#endif // USE_ESP32_BLE_UUID
190#endif // USE_ESP32
std::string to_string() const
Definition ble_uuid.cpp:146
static ESPBTUUID from_uuid(esp_bt_uuid_t uuid)
Definition ble_uuid.cpp:84
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:130
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:145
ESPBTUUID as_128bit() const
Definition ble_uuid.cpp:96
bool contains(uint8_t data1, uint8_t data2) const
Definition ble_uuid.cpp:112
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:601
size_t parse_hex(const char *str, size_t length, uint8_t *data, size_t count)
Parse bytes from a hex-encoded string into a byte array.
Definition helpers.cpp:264