10static const char *
const TAG =
"zephyr_ble_server";
12static k_work advertise_work;
16#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
17#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)
19static const bt_data AD[] = {
20 BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
21 BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
24static const bt_data SD[] = {
26 BT_DATA_BYTES(BT_DATA_UUID128_ALL, 0x84, 0xaa, 0x60, 0x74, 0x52, 0x8a, 0x8b, 0x86, 0xd3, 0x4c, 0xb7, 0x1d, 0x1d,
31const bt_le_adv_param *
const ADV_PARAM = BT_LE_ADV_CONN;
33static void advertise(k_work *work) {
34 int rc = bt_le_adv_stop();
36 ESP_LOGE(TAG,
"Advertising failed to stop (rc %d)", rc);
39 rc = bt_le_adv_start(
ADV_PARAM, AD, ARRAY_SIZE(AD), SD, ARRAY_SIZE(SD));
41 ESP_LOGE(TAG,
"Advertising failed to start (rc %d)", rc);
44 ESP_LOGI(TAG,
"Advertising successfully started");
48 char addr[BT_ADDR_LE_STR_LEN];
49 bt_addr_le_to_str(bt_conn_get_dst(conn), addr,
sizeof(addr));
51 ESP_LOGE(TAG,
"Failed to connect to %s (%u)", addr, err);
54 ESP_LOGI(TAG,
"Connected %s", addr);
56 if (bt_conn_set_security(conn, BT_SECURITY_L4)) {
57 ESP_LOGE(TAG,
"Failed to set security");
60 conn = bt_conn_ref(conn);
65 char addr[BT_ADDR_LE_STR_LEN];
67 bt_addr_le_to_str(bt_conn_get_dst(conn), addr,
sizeof(addr));
69 ESP_LOGI(TAG,
"Disconnected from %s (reason 0x%02x)", addr, reason);
76 k_work_submit(&advertise_work);
80static void identity_resolved(bt_conn *conn,
const bt_addr_le_t *rpa,
const bt_addr_le_t *identity) {
81 char addr_identity[BT_ADDR_LE_STR_LEN];
82 char addr_rpa[BT_ADDR_LE_STR_LEN];
84 bt_addr_le_to_str(identity, addr_identity,
sizeof(addr_identity));
85 bt_addr_le_to_str(rpa, addr_rpa,
sizeof(addr_rpa));
87 ESP_LOGD(TAG,
"Identity resolved %s -> %s", addr_rpa, addr_identity);
90static void security_changed(bt_conn *conn, bt_security_t level, bt_security_err err) {
91 char addr[BT_ADDR_LE_STR_LEN];
93 bt_addr_le_to_str(bt_conn_get_dst(conn), addr,
sizeof(addr));
96 ESP_LOGD(TAG,
"Security changed: %s level %u", addr, level);
98 ESP_LOGE(TAG,
"Security failed: %s level %u err %d", addr, level, err);
102static void pairing_complete(bt_conn *conn,
bool bonded) {
103 char addr[BT_ADDR_LE_STR_LEN];
105 bt_addr_le_to_str(bt_conn_get_dst(conn), addr,
sizeof(addr));
107 ESP_LOGD(TAG,
"Pairing completed: %s, bonded: %d", addr, bonded);
110static void pairing_failed(bt_conn *conn, bt_security_err reason) {
111 char addr[BT_ADDR_LE_STR_LEN];
113 bt_addr_le_to_str(bt_conn_get_dst(conn), addr,
sizeof(addr));
115 ESP_LOGE(TAG,
"Pairing failed conn: %s, reason %d", addr, reason);
117 bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
120static void bond_deleted(uint8_t
id,
const bt_addr_le_t *peer) {
121 char addr[BT_ADDR_LE_STR_LEN];
123 bt_addr_le_to_str(peer, addr,
sizeof(addr));
124 ESP_LOGD(TAG,
"Bond deleted for %s, id %u", addr,
id);
127static void auth_passkey_display(bt_conn *conn,
unsigned int passkey) {
128 char addr[BT_ADDR_LE_STR_LEN];
131 bt_addr_le_to_str(bt_conn_get_dst(conn), addr,
sizeof(addr));
133 snprintk(passkey_str, 7,
"%06u", passkey);
135 ESP_LOGI(TAG,
"Passkey for %s: %s", addr, passkey_str);
138static void conn_addr_str(bt_conn *conn,
char *addr,
size_t len) {
139 struct bt_conn_info info;
141 if (bt_conn_get_info(conn, &info) < 0) {
147 case BT_CONN_TYPE_LE:
148 bt_addr_le_to_str(info.le.dst, addr,
len);
151 ESP_LOGE(TAG,
"Not implemented");
157static void auth_cancel(bt_conn *conn) {
158 char addr[BT_ADDR_LE_STR_LEN];
160 conn_addr_str(conn, addr,
sizeof(addr));
162 ESP_LOGI(TAG,
"Pairing cancelled: %s", addr);
166 char addr[BT_ADDR_LE_STR_LEN];
169 bt_addr_le_to_str(bt_conn_get_dst(conn), addr,
sizeof(addr));
171 snprintk(passkey_str, 7,
"%06u", passkey);
173 ESP_LOGI(TAG,
"Confirm passkey for %s: %s", addr, passkey_str);
177static void auth_pairing_confirm(bt_conn *conn) {
179 auto err = bt_conn_auth_pairing_confirm(conn);
181 ESP_LOGE(TAG,
"Can't confirm pairing (err: %d)", err);
185 char addr[BT_ADDR_LE_STR_LEN];
187 bt_addr_le_to_str(bt_conn_get_dst(conn), addr,
sizeof(addr));
189 ESP_LOGI(TAG,
"Pairing confirmed: %s", addr);
197 k_work_init(&advertise_work, advertise);
199 static bt_conn_cb conn_callbacks = {
203 .identity_resolved = identity_resolved,
204 .security_changed = security_changed,
208 bt_conn_cb_register(&conn_callbacks);
210 static struct bt_conn_auth_info_cb conn_auth_info_callbacks = {
211 .pairing_complete = pairing_complete, .pairing_failed = pairing_failed, .bond_deleted = bond_deleted};
212 err = bt_conn_auth_info_cb_register(&conn_auth_info_callbacks);
214 ESP_LOGE(TAG,
"Failed to register authorization info callbacks.");
216 static struct bt_conn_auth_cb auth_cb = {
217 .passkey_display = auth_passkey_display,
219 .cancel = auth_cancel,
220 .pairing_confirm = auth_pairing_confirm,
222 err = bt_conn_auth_cb_register(&auth_cb);
224 ESP_LOGE(TAG,
"Failed to set auth handlers (%d)", err);
228 err = bt_enable(
nullptr);
230 ESP_LOGE(TAG,
"Bluetooth enable failed: %d", err);
233#ifdef CONFIG_BT_SETTINGS
234 err = settings_load();
236 ESP_LOGE(TAG,
"Cannot load settings, err: %d", err);
239 k_work_submit(&advertise_work);
242#ifdef ESPHOME_LOG_HAS_DEBUG
243static const char *role_str(uint8_t role) {
245 case BT_CONN_ROLE_CENTRAL:
247 case BT_CONN_ROLE_PERIPHERAL:
254static void connection_info(bt_conn *conn,
void *user_data) {
255 char addr[BT_ADDR_LE_STR_LEN];
256 struct bt_conn_info info;
258 if (bt_conn_get_info(conn, &info) < 0) {
259 ESP_LOGE(TAG,
"Unable to get info: conn %p", conn);
264 case BT_CONN_TYPE_LE:
265 bt_addr_le_to_str(info.le.dst, addr,
sizeof(addr));
266 ESP_LOGD(TAG,
" %u [LE][%s] %s: Interval %u latency %u timeout %u security L%u", info.id, role_str(info.role),
267 addr, info.le.interval, info.le.latency, info.le.timeout, info.security.level);
270 ESP_LOGE(TAG,
"Not implemented");
274#ifdef CONFIG_BT_BONDABLE
275static void bond_info(
const struct bt_bond_info *info,
void *user_data) {
276 char addr[BT_ADDR_LE_STR_LEN];
278 bt_addr_le_to_str(&info->addr, addr,
sizeof(addr));
279 ESP_LOGD(TAG,
" Bond remote identity: %s", addr);
292 " security manager: YES",
294 " security manager: NO",
296 YESNO(this->
conn_), bt_get_name(), bt_get_appearance(), YESNO(bt_is_ready()));
298#ifdef ESPHOME_LOG_HAS_DEBUG
299 bt_conn_foreach(BT_CONN_TYPE_ALL, connection_info,
nullptr);
300#ifdef CONFIG_BT_BONDABLE
301 bt_foreach_bond(BT_ID_DEFAULT, bond_info,
nullptr);
307 if (this->
conn_ ==
nullptr) {
308 ESP_LOGE(TAG,
"Not connected");
311 ESP_LOGD(TAG,
"Numeric comparison %s", accept ?
"accepted" :
"rejected");
313 bt_conn_auth_passkey_confirm(this->
conn_);
315 bt_conn_auth_cancel(this->
conn_);