如何在macOS上使用Python扫描蓝牙BR/EDR(经典蓝牙)设备?
解决macOS上Python扫描经典蓝牙(BR/EDR)设备并获取MAC地址的问题
你的核心问题在于Bleak是专门针对BLE(低功耗蓝牙)的库,无法正确处理经典蓝牙(BR/EDR)设备的扫描——macOS的隐私限制和Bleak的API设计导致它扫经典蓝牙时无法返回设备名称,且返回的是UUID格式而非传统MAC地址。要实现经典蓝牙设备的扫描和MAC地址获取,需要调用macOS原生的IOBluetooth框架,通过pyobjc桥接在Python中实现。
实现步骤
1. 依赖安装
首先安装pyobjc的IOBluetooth框架绑定:
pip install pyobjc-framework-IOBluetooth
2. 扫描经典蓝牙设备
以下代码可以扫描周边经典蓝牙设备,获取设备名称和标准MAC地址:
import objc from IOBluetooth import * def scan_classic_bluetooth_devices(timeout=10): # 初始化蓝牙扫描器 inquiry = IOBluetoothDeviceInquiry.alloc().init() inquiry.setDelegate_(objc.self) # 启动扫描,设置超时时间 inquiry.start() # 等待扫描完成 while inquiry.isInquiring(): objc.retainAutoreleasedReturnValue( NSRunLoop.currentRunLoop().runUntilDate_( NSDate.dateWithTimeIntervalSinceNow_(0.1) ) ) # 提取扫描到的设备信息 found_devices = [] for device in inquiry.foundDevices(): dev_name = device.name() or "未知设备" dev_mac = device.addressString() found_devices.append({"name": dev_name, "mac": dev_mac}) return found_devices if __name__ == "__main__": devices = scan_classic_bluetooth_devices() print("扫描到的经典蓝牙设备:") for idx, dev in enumerate(devices, 1): print(f"{idx}. 名称: {dev['name']}, MAC地址: {dev['mac']}")
3. 选择并连接目标设备
扫描完成后,让用户选择目标ESP32设备,再通过MAC地址建立RFCOMM连接(ESP32需配置为经典蓝牙串口模式,比如用Arduino的BluetoothSerial库):
def connect_to_device(mac_address): # 通过MAC地址获取设备对象 device = IOBluetoothDevice.deviceWithAddressString_(mac_address) if not device: print("未找到指定设备") return None # 匹配串口服务UUID(RFCOMM常用UUID:00001101-0000-1000-8000-00805F9B34FB) serial_uuid = IOBluetoothUUID.UUIDWithString_("00001101-0000-1000-8000-00805F9B34FB") rfcomm_channel = device.getRFCOMMChannelIDForServiceUUID_(serial_uuid) if rfcomm_channel == kIOBluetoothUnknownRFCOMMChannelID: print("无法获取RFCOMM通信通道") return None # 建立同步连接 success, error_code = device.openRFCOMMChannelSync_(None, rfcomm_channel) if success: print("设备连接成功") return device else: print(f"连接失败,错误码: {error_code}") return None # 示例:选择设备并连接 if __name__ == "__main__": devices = scan_classic_bluetooth_devices() if not devices: print("未扫描到任何经典蓝牙设备") exit() selected_idx = int(input("请输入目标设备的序号:")) - 1 selected_dev = devices[selected_idx] conn_device = connect_to_device(selected_dev["mac"]) # 连接成功后即可收发数据 if conn_device: # 示例:发送数据 conn_device.writeData_(b"Hello ESP32!\n") # 示例:读取数据(需根据实际情况处理) data = conn_device.readData_(1024) print(f"收到数据: {data.decode('utf-8')}")
注意事项
- 权限配置:macOS运行蓝牙相关代码需要权限,前往「系统偏好设置 → 安全性与隐私 → 蓝牙」,确保运行代码的终端/IDE被授予蓝牙权限。
- ESP32配置:需将ESP32设置为经典蓝牙模式(而非BLE),比如使用Arduino的
BluetoothSerial库开启蓝牙串口服务,并设置易识别的设备名称。 - 兼容性:该方案仅适用于macOS,因为直接调用了macOS原生蓝牙框架。
内容的提问来源于stack exchange,提问作者Yiming Designer
相关产品推荐
相关产品推荐

