基于Angstrom的ARM Linux主机与ESP32实现BLE Just Works安全连接配对求助
咱们先从你熟悉的命令行工具入手,再逐步覆盖Python脚本和C/C++实现的方案,帮你搞定Secure Connection配对的问题:
一、命令行工具(bluetoothctl/btmgmt)正确操作步骤
之前你不用Secure Connection能配对成功,大概率是没配置适配Just Works的代理类型和安全参数,试试下面的流程:
先确认你的蓝牙栈支持LE Secure Connections:
btmgmt info输出里找
LE Secure Connections字样,确保是supported和enabled状态,如果没enabled,执行:sudo btmgmt le-sec-conn on启动bluetoothctl交互模式:
sudo bluetoothctl配置代理(Just Works不需要输入输出,对应
NoInputNoOutput代理):agent on agent NoInputNoOutput default-agent扫描并配对目标ESP32设备:
scan on # 找到你的ESP32 MAC地址后,停止扫描 scan off trust <ESP32_MAC_ADDRESS> pair <ESP32_MAC_ADDRESS>这里要注意:如果之前配对过失败的记录,先执行
remove <ESP32_MAC_ADDRESS>清除旧配对信息再重试。
二、Python脚本实现(基于Bleak库)
Bleak是现代Python BLE库,对Secure Connection支持友好,适合快速验证:
首先安装Bleak(Angstrom Linux下可能需要用pip编译安装,确保有依赖):
pip install bleak
示例脚本:
import asyncio from bleak import BleakClient, BleakScanner ESP32_MAC = "你的ESP32 MAC地址" async def pair_secure_connection(): # 扫描设备(可选,确认设备在线) devices = await BleakScanner.discover() for d in devices: if d.address == ESP32_MAC: print(f"找到目标设备: {d.name}") # 连接并触发Secure Connection配对 async with BleakClient(ESP32_MAC, security_level="high") as client: print(f"已连接设备: {client.is_connected}") # 配对会在连接时自动触发,security_level="high"强制使用Secure Connection # 这里可以添加GATT操作,比如读取特征,验证配对是否生效 print("配对完成") if __name__ == "__main__": asyncio.run(pair_secure_connection())
说明:security_level="high"对应BLE Secure Connection,Just Works模式会自动处理无需用户输入。
三、C/C++代码实现(基于BlueZ DBus API)
如果需要更底层的控制,用BlueZ的DBus API是标准方案,以下是核心逻辑示例:
首先确保你的系统有BlueZ开发包(
libbluetooth-dev或Angstrom对应的包)。核心步骤代码片段(用GDBus调用bluetoothd的方法):
#include <gio/gio.h> #define ESP32_MAC "你的ESP32 MAC地址" #define BLUEZ_SERVICE "org.bluez" #define DEVICE_INTERFACE "org.bluez.Device1" static void pair_callback(GObject *source_object, GAsyncResult *res, gpointer user_data) { GError *error = NULL; g_dbus_proxy_call_finish(G_DBUS_PROXY(source_object), res, &error); if (error) { g_printerr("配对失败: %s\n", error->message); g_error_free(error); } else { g_print("配对成功!\n"); } g_main_loop_quit(user_data); } int main(int argc, char *argv[]) { GMainLoop *loop = g_main_loop_new(NULL, FALSE); GDBusProxy *device_proxy; GError *error = NULL; // 获取设备代理,注意把MAC的冒号换成下划线,比如AA:BB:CC:DD:EE:FF → AA_BB_CC_DD_EE_FF gchar *device_path = g_strdup_printf("/org/bluez/hci0/dev_%s", "AA_BB_CC_DD_EE_FF"); device_proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, BLUEZ_SERVICE, device_path, DEVICE_INTERFACE, NULL, &error); g_free(device_path); if (error) { g_printerr("获取设备代理失败: %s\n", error->message); g_error_free(error); return 1; } // 触发配对(需先注册NoInputNoOutput类型的Agent,可参考BlueZ官方simple-agent示例修改) g_dbus_proxy_call(device_proxy, "Pair", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, pair_callback, loop); g_main_loop_run(loop); g_object_unref(device_proxy); g_main_loop_unref(loop); return 0; }
说明:完整代码需要实现BlueZ的Agent注册逻辑,指定NoInputNoOutput的Capability,你可以参考BlueZ官方的simple-agent示例代码修改,把Capability设置为NoInputNoOutput即可适配Just Works模式。
关键注意事项
- BlueZ版本:确保Angstrom Linux的BlueZ版本≥5.48,旧版本对Secure Connection支持不完善,可执行
bluetoothd -v查看版本。 - 内核配置:检查内核是否开启
CONFIG_BT_SECURITY、CONFIG_BT_SMP、CONFIG_BT_BLE_SEC_CONN相关选项。 - ESP32配置:确认ESP-IDF的示例中开启了
CONFIG_BT_SSP_ENABLED和CONFIG_BT_BLE_SEC_CONN_ENABLED,并且安全级别设置为SP_LE_AUTH_BOND(你已经配置了这个,没问题)。
内容的提问来源于stack exchange,提问作者Oleg

