14static k_work advertise_work;
19static constexpr size_t MAX_ADV_NAME_LEN = BT_GAP_ADV_MAX_ADV_DATA_LEN - 3 - 2;
21static const bt_data SD[] = {
23 BT_DATA_BYTES(BT_DATA_UUID128_ALL, 0x84, 0xaa, 0x60, 0x74, 0x52, 0x8a, 0x8b, 0x86, 0xd3, 0x4c, 0xb7, 0x1d, 0x1d,
28const bt_le_adv_param *
const ADV_PARAM = BT_LE_ADV_CONN;
30static void advertise(k_work *work) {
31 int rc = bt_le_adv_stop();
33 ESP_LOGE(TAG,
"Advertising failed to stop (rc %d)", rc);
37 char name[MAX_ADV_NAME_LEN + 1];
39 const size_t name_len =
42 const uint8_t name_type = name_len < app_name.length() ? BT_DATA_NAME_SHORTENED : BT_DATA_NAME_COMPLETE;
43 static constexpr uint8_t FLAGS[] = {BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR};
44 const bt_data ad[] = {
45 BT_DATA(BT_DATA_FLAGS, FLAGS,
sizeof(FLAGS)),
46 BT_DATA(name_type, name,
static_cast<uint8_t
>(name_len)),
49 rc = bt_le_adv_start(
ADV_PARAM, ad, ARRAY_SIZE(ad), SD, ARRAY_SIZE(SD));
51 ESP_LOGE(TAG,
"Advertising failed to start (rc %d)", rc);
54 ESP_LOGI(TAG,
"Advertising successfully started");
58 char addr[BT_ADDR_LE_STR_LEN];
59 bt_addr_le_to_str(bt_conn_get_dst(conn), addr,
sizeof(addr));
61 ESP_LOGE(TAG,
"Failed to connect to %s (%u)", addr, err);
64 ESP_LOGI(TAG,
"Connected %s", addr);
66 if (bt_conn_set_security(conn, BT_SECURITY_L4)) {
67 ESP_LOGE(TAG,
"Failed to set security");
70 conn = bt_conn_ref(conn);
75 char addr[BT_ADDR_LE_STR_LEN];
77 bt_addr_le_to_str(bt_conn_get_dst(conn), addr,
sizeof(addr));
79 ESP_LOGI(TAG,
"Disconnected from %s (reason 0x%02x)", addr, reason);
86 k_work_submit(&advertise_work);
90static void identity_resolved(bt_conn *conn,
const bt_addr_le_t *rpa,
const bt_addr_le_t *identity) {
91 char addr_identity[BT_ADDR_LE_STR_LEN];
92 char addr_rpa[BT_ADDR_LE_STR_LEN];
94 bt_addr_le_to_str(identity, addr_identity,
sizeof(addr_identity));
95 bt_addr_le_to_str(rpa, addr_rpa,
sizeof(addr_rpa));
97 ESP_LOGD(TAG,
"Identity resolved %s -> %s", addr_rpa, addr_identity);
100static void security_changed(bt_conn *conn, bt_security_t level, bt_security_err err) {
101 char addr[BT_ADDR_LE_STR_LEN];
103 bt_addr_le_to_str(bt_conn_get_dst(conn), addr,
sizeof(addr));
106 ESP_LOGD(TAG,
"Security changed: %s level %u", addr, level);
108 ESP_LOGE(TAG,
"Security failed: %s level %u err %d", addr, level, err);
112static void pairing_complete(bt_conn *conn,
bool bonded) {
113 char addr[BT_ADDR_LE_STR_LEN];
115 bt_addr_le_to_str(bt_conn_get_dst(conn), addr,
sizeof(addr));
117 ESP_LOGD(TAG,
"Pairing completed: %s, bonded: %d", addr, bonded);
120static void pairing_failed(bt_conn *conn, bt_security_err reason) {
121 char addr[BT_ADDR_LE_STR_LEN];
123 bt_addr_le_to_str(bt_conn_get_dst(conn), addr,
sizeof(addr));
125 ESP_LOGE(TAG,
"Pairing failed conn: %s, reason %d", addr, reason);
127 bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
130static void bond_deleted(uint8_t
id,
const bt_addr_le_t *peer) {
131 char addr[BT_ADDR_LE_STR_LEN];
133 bt_addr_le_to_str(peer, addr,
sizeof(addr));
134 ESP_LOGD(TAG,
"Bond deleted for %s, id %u", addr,
id);
137static void auth_passkey_display(bt_conn *conn,
unsigned int passkey) {
138 char addr[BT_ADDR_LE_STR_LEN];
141 bt_addr_le_to_str(bt_conn_get_dst(conn), addr,
sizeof(addr));
143 snprintk(passkey_str, 7,
"%06u", passkey);
145 ESP_LOGI(TAG,
"Passkey for %s: %s", addr, passkey_str);
148static void conn_addr_str(bt_conn *conn,
char *addr,
size_t len) {
149 struct bt_conn_info info;
151 if (bt_conn_get_info(conn, &info) < 0) {
157 case BT_CONN_TYPE_LE:
158 bt_addr_le_to_str(info.le.dst, addr,
len);
161 ESP_LOGE(TAG,
"Not implemented");
167static void auth_cancel(bt_conn *conn) {
168 char addr[BT_ADDR_LE_STR_LEN];
170 conn_addr_str(conn, addr,
sizeof(addr));
172 ESP_LOGI(TAG,
"Pairing cancelled: %s", addr);
176 char addr[BT_ADDR_LE_STR_LEN];
179 bt_addr_le_to_str(bt_conn_get_dst(conn), addr,
sizeof(addr));
181 snprintk(passkey_str, 7,
"%06u", passkey);
183 ESP_LOGI(TAG,
"Confirm passkey for %s: %s", addr, passkey_str);
187static void auth_pairing_confirm(bt_conn *conn) {
189 auto err = bt_conn_auth_pairing_confirm(conn);
191 ESP_LOGE(TAG,
"Can't confirm pairing (err: %d)", err);
195 char addr[BT_ADDR_LE_STR_LEN];
197 bt_addr_le_to_str(bt_conn_get_dst(conn), addr,
sizeof(addr));
199 ESP_LOGI(TAG,
"Pairing confirmed: %s", addr);
207 k_work_init(&advertise_work, advertise);
209 static bt_conn_cb conn_callbacks = {
213 .identity_resolved = identity_resolved,
214 .security_changed = security_changed,
218 bt_conn_cb_register(&conn_callbacks);
220 static struct bt_conn_auth_info_cb conn_auth_info_callbacks = {
221 .pairing_complete = pairing_complete, .pairing_failed = pairing_failed, .bond_deleted = bond_deleted};
222 err = bt_conn_auth_info_cb_register(&conn_auth_info_callbacks);
224 ESP_LOGE(TAG,
"Failed to register authorization info callbacks.");
226 static struct bt_conn_auth_cb auth_cb = {
227 .passkey_display = auth_passkey_display,
229 .cancel = auth_cancel,
230 .pairing_confirm = auth_pairing_confirm,
232 err = bt_conn_auth_cb_register(&auth_cb);
234 ESP_LOGE(TAG,
"Failed to set auth handlers (%d)", err);
238 err = bt_enable(
nullptr);
240 ESP_LOGE(TAG,
"Bluetooth enable failed: %d", err);
243#ifdef CONFIG_BT_SETTINGS
244 err = settings_load();
246 ESP_LOGE(TAG,
"Cannot load settings, err: %d", err);
249 k_work_submit(&advertise_work);
252#ifdef ESPHOME_LOG_HAS_DEBUG
253static const char *role_str(uint8_t role) {
255 case BT_CONN_ROLE_CENTRAL:
257 case BT_CONN_ROLE_PERIPHERAL:
266static void connection_info(bt_conn *conn,
void *user_data) {
267 char addr[BT_ADDR_LE_STR_LEN];
268 struct bt_conn_info info;
270 if (bt_conn_get_info(conn, &info) < 0) {
271 ESP_LOGE(TAG,
"Unable to get info: conn %p", conn);
276 case BT_CONN_TYPE_LE:
277 bt_addr_le_to_str(info.le.dst, addr,
sizeof(addr));
278 ESP_LOGD(TAG,
" %u [LE][%s] %s: Interval %u latency %u timeout %u security L%u", info.id, role_str(info.role),
279 addr, info.le.interval, info.le.latency, info.le.timeout, info.security.level);
282 ESP_LOGE(TAG,
"Not implemented");
286#ifdef CONFIG_BT_BONDABLE
287static void bond_info(
const struct bt_bond_info *info,
void *user_data) {
288 char addr[BT_ADDR_LE_STR_LEN];
290 bt_addr_le_to_str(&info->addr, addr,
sizeof(addr));
291 ESP_LOGD(TAG,
" Bond remote identity: %s", addr);
304 " security manager: YES",
306 " security manager: NO",
308 YESNO(this->
conn_), bt_get_name(), bt_get_appearance(), YESNO(bt_is_ready()));
310#ifdef ESPHOME_LOG_HAS_DEBUG
311 bt_conn_foreach(BT_CONN_TYPE_ALL, connection_info,
nullptr);
312#ifdef CONFIG_BT_BONDABLE
313 bt_foreach_bond(BT_ID_DEFAULT, bond_info,
nullptr);
319 if (this->
conn_ ==
nullptr) {
320 ESP_LOGE(TAG,
"Not connected");
323 ESP_LOGD(TAG,
"Numeric comparison %s", accept ?
"accepted" :
"rejected");
325 bt_conn_auth_passkey_confirm(this->
conn_);
327 bt_conn_auth_cancel(this->
conn_);