树莓派内置的蓝牙模块使其成为物联网(IoT)、智能家居控制、可穿戴设备交互和各类无线传感项目的理想平台,掌握其蓝牙开发能力,无论是使用低功耗蓝牙(BLE)进行传感器数据采集,还是利用经典蓝牙实现音频传输或文件分享,都能极大地扩展树莓派的应用场景,本文将深入讲解树莓派蓝牙开发的完整流程和关键技术点。

基础准备与开发环境搭建
-
硬件确认:
- 确保您的树莓派型号支持蓝牙(绝大多数现代型号如 Pi 3B+、Pi 4B、Pi Zero W/WH、Pi 400 及更新版本都内置蓝牙)。
- 一个兼容的USB蓝牙适配器(仅当内置蓝牙损坏或需要特定功能如蓝牙5.x时才需要)。
- 目标蓝牙设备(如BLE传感器、蓝牙耳机、另一台手机/电脑)。
-
系统更新与蓝牙工具安装:
- 启动树莓派,打开终端。
- 更新软件包列表并升级系统:
sudo apt update sudo apt full-upgrade -y sudo reboot
- 安装核心蓝牙开发工具包
bluez及其配套工具bluez-tools(或bluetoothctl的依赖):sudo apt install bluez bluez-tools libbluetooth-dev pi-bluetooth -y
libbluetooth-dev是开发蓝牙应用程序(如使用Pythonpybluez或bleak库)所必需的头文件和库。
-
验证蓝牙状态与基础操作:
- 检查蓝牙服务状态:
systemctl status bluetooth
- 启动/重启/停止蓝牙服务:
sudo systemctl start bluetooth # 启动 sudo systemctl restart bluetooth # 重启 sudo systemctl stop bluetooth # 停止
- 使用命令行工具
bluetoothctl进行设备扫描、配对、连接、信任等操作(交互式命令):bluetoothctl [bluetooth]# power on # 确保蓝牙已开启 [bluetooth]# scan on # 开始扫描设备 ... (等待发现目标设备) ... [bluetooth]# pair [设备MAC地址] # 配对设备 [bluetooth]# connect [设备MAC地址] # 连接设备 [bluetooth]# trust [设备MAC地址] # 信任设备(下次自动连接) [bluetooth]# exit
- 检查蓝牙服务状态:
低功耗蓝牙(BLE)开发实战
BLE是物联网设备通信的主流协议,功耗极低,Python的bleak库提供了现代、异步的BLE开发接口。
-
安装
bleak库:pip install bleak
-
扫描BLE设备:
import asyncio from bleak import BleakScanner async def scan_devices(): devices = await BleakScanner.discover() for d in devices: print(f"设备名称: {d.name}, MAC地址: {d.address}, 信号强度: {d.rssi} dBm") asyncio.run(scan_devices())此代码扫描周围所有BLE设备并打印基本信息。
-
连接BLE设备并读取/写入特征值(Characteristic):

- 需要知道目标设备的服务UUID(Service UUID) 和 特征值UUID(Characteristic UUID),这些信息通常由设备厂商提供(数据手册/SDK)。
import asyncio from bleak import BleakClient
替换为目标设备的MAC地址和服务/特征值UUID
TARGET_ADDRESS = “XX:XX:XX:XX:XX:XX”
SERVICE_UUID = “0000180f-0000-1000-8000-00805f9b34fb” # 示例:电池服务
CHARACTERISTIC_UUID = “00002a19-0000-1000-8000-00805f9b34fb” # 示例:电池电量特征async def read_battery_level():
async with BleakClient(TARGET_ADDRESS) as client:
print(f”已连接到 {TARGET_ADDRESS}”)检查服务是否存在(可选但推荐)
svc = client.services.get_service(SERVICE_UUID) if not svc: raise RuntimeError(f"服务 {SERVICE_UUID} 未找到!") # 读取特征值 battery_level = await client.read_gatt_char(CHARACTERISTIC_UUID) # 假设电量是1字节的整数 (0-100%) print(f"电池电量: {int.from_bytes(battery_level, byteorder='little')}%")asyncio.run(read_battery_level())
`async with`上下文管理器确保连接在使用后正确关闭。 `read_gatt_char`用于读取特征值数据。 写入特征值使用`write_gatt_char`方法(注意写入权限和数据类型)。 - 需要知道目标设备的服务UUID(Service UUID) 和 特征值UUID(Characteristic UUID),这些信息通常由设备厂商提供(数据手册/SDK)。
-
订阅通知(Notifications):
对于需要实时接收传感器数据的场景(如心率监测),订阅通知比轮询更高效。async def subscribe_to_notifications(): def notification_handler(sender, data): # 处理接收到的通知数据 (data) print(f"收到来自 {sender} 的数据: {data.hex()}") # 以16进制打印 async with BleakClient(TARGET_ADDRESS) as client: # ... (检查服务/特征值代码同上) ... # 启用通知 (通常需要写入CCCD描述符) await client.start_notify(CHARACTERISTIC_UUID, notification_handler) print("已开启通知,等待数据... (按 Ctrl+C 停止)") await asyncio.sleep(30.0) # 示例:监听30秒 await client.stop_notify(CHARACTERISTIC_UUID) asyncio.run(subscribe_to_notifications())- 定义
notification_handler回调函数处理接收到的数据。 start_notify启用通知,stop_notify停止通知。
- 定义
经典蓝牙(RFCOMM/SPP)开发
经典蓝牙常用于串行端口仿真(SPP),实现类似串口的双向通信,适用于需要较高带宽或兼容旧设备的场景,Python的pybluez是常用库(但维护状态需注意,Python 3支持可能需特定分支)。
-
安装
pybluez:pip install pybluez # 如果遇到兼容性问题,可能需要尝试: # pip install git+https://github.com/pybluez/pybluez.git#egg=pybluez
-
搜索经典蓝牙设备:
import bluetooth print("正在扫描经典蓝牙设备...") nearby_devices = bluetooth.discover_devices(lookup_names=True, duration=8) print("找到 %d 台设备" % len(nearby_devices)) for addr, name in nearby_devices: print(" %s - %s" % (addr, name)) -
建立RFCOMM连接与通信:
-
需要知道目标设备的RFCOMM端口号(Channel),可以通过服务发现协议(SDP)查询:

services = bluetooth.find_service(address=TARGET_ADDRESS) for svc in services: print(f"服务名称: {svc['name']}, 端口: {svc['port']}, 协议: {svc['protocol']}") -
连接与通信示例:
import bluetooth TARGET_ADDRESS = "XX:XX:XX:XX:XX:XX" # 目标设备MAC PORT = 1 # 目标设备的RFCOMM端口号 (通常1是SPP) try: sock = bluetooth.BluetoothSocket(bluetooth.RFCOMM) sock.connect((TARGET_ADDRESS, PORT)) print("连接成功!") # 发送数据 sock.send("Hello from Raspberry Pi!n") # 接收数据 (示例:接收最多1024字节) data = sock.recv(1024) print(f"收到: {data.decode('utf-8')}") # 假设是UTF-8文本 except bluetooth.btcommon.BluetoothError as err: print(f"蓝牙错误: {err}") finally: sock.close() -
创建
BluetoothSocket对象,指定协议RFCOMM。 -
使用
connect连接目标地址和端口。 -
使用
send发送数据(通常是字节串)。 -
使用
recv接收数据。
-
进阶主题与注意事项
- 蓝牙服务端(Server): 树莓派也可以作为蓝牙服务端(如BLE外设或RFCOMM服务器)。
bleak支持BLE外设模式,pybluez支持创建RFCOMM监听套接字,这允许其他设备主动连接树莓派。 - 蓝牙5与长距离/高速模式: 较新的树莓派(如Pi 4B)支持蓝牙5.0,可通过
hcitool命令(如sudo hcitool cmd 0x08 0x0009查看支持特性)或配置/etc/bluetooth/main.conf尝试启用LE 2M PHY或LE Coded PHY(长距离),但需硬件和驱动支持。 - 权限问题: 确保运行Python脚本的用户(如
pi)有权限访问蓝牙设备(通常是bluetooth组),将用户加入bluetooth组:sudo usermod -aG bluetooth pi,然后注销或重启生效。 - 稳定性与调试:
- 遇到连接不稳定,尝试重启蓝牙服务
sudo systemctl restart bluetooth或重启树莓派。 - 使用
sudo hcidump -X或bluetoothctl show查看详细的蓝牙HCI层数据包和适配器信息,是强大的调试手段。 - 检查
/var/log/syslog中的蓝牙相关日志。
- 遇到连接不稳定,尝试重启蓝牙服务
- 安全性: 注意蓝牙通信(尤其是经典蓝牙)可能被窃听,对于敏感应用,务必使用安全配对(Secure Simple Pairing – SSP)并启用加密,BLE连接也可以加密。
树莓派的蓝牙功能,结合Python强大的库支持(bleak用于BLE,pybluez用于经典蓝牙),为开发者打开了无线连接各种设备的大门,从简单的BLE传感器数据读取到复杂的经典蓝牙文件传输或音频流,树莓派都能胜任,关键在于理解蓝牙协议栈的分层(HCI, L2CAP, ATT/GATT, RFCOMM/SDP)和掌握对应API的使用方法,实践出真知,多动手连接不同的设备,分析服务和特征值,逐步构建您的蓝牙应用,利用好命令行工具bluetoothctl和hcitool进行底层调试,能有效解决开发中遇到的疑难杂症。
您在实际树莓派蓝牙开发中遇到过哪些棘手的问题?是设备扫描不到、连接不稳定、数据解析困难,还是性能瓶颈?欢迎在评论区分享您的经历和解决方案,或者提出您遇到的挑战,我们共同探讨!
- 如何让树莓派自动重连断开的BLE设备?
- 在同时连接多个BLE设备时,如何优化资源管理和避免卡顿?
- 有没有更高效的方法解析复杂的BLE传感器数据格式?
- 经典蓝牙传输文件的最佳实践是什么?
原创文章,作者:世雄 - 原生数据库架构专家,如若转载,请注明出处:https://idctop.com/article/28016.html