You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 11:02:49