
本文介绍如何用简洁的 python 脚本将树莓派配置为 ble 外设,自动响应手机 app 连接并周期性推送传感器数据;同时说明如何设置设备名称使其在蓝牙扫描中可见。
本文介绍如何用简洁的 python 脚本将树莓派配置为 ble 外设,自动响应手机 app 连接并周期性推送传感器数据;同时说明如何设置设备名称使其在蓝牙扫描中可见。
要在树莓派上实现一个轻量、稳定且易集成的 BLE 数据发送端(GATT Server),关键在于:正确初始化 BLE 广播、定义可读/可通知的特征值(Characteristic)、处理连接生命周期,并设置设备可见名称。bluepy 等常用库虽支持客户端操作,但作为 BLE 外设(Peripheral)运行需底层协议栈支持(如 BlueZ 的 bluetoothd + D-Bus),配置复杂且易出错。相比之下,btfpy 是专为树莓派优化的原生 BLE 服务库,无需 D-Bus 或 GATT 配置文件,仅靠纯 Python + 简单文本定义即可启动标准 BLE 外设服务。
✅ 第一步:安装与准备
# 启用蓝牙服务(确保硬件正常) sudo systemctl enable bluetooth sudo systemctl start bluetooth # 安装 btfpy(需从源码编译,已适配 Raspberry Pi ARM 架构) git clone https://www.php.cn/link/bad1be88b3b4dc712aa6d7ee59ea48d3.git cd btferret make sudo make install
✅ 第二步:定义设备信息与服务(devices.txt)
创建 devices.txt 文件,声明设备名、服务 UUID 和特征值。这是 btfpy 的核心配置,替代了传统 BLE 开发中繁琐的 GATT XML 描述:
# DEVICE 行定义设备名称(即手机扫描时显示的名字!) DEVICE = MySensorPi TYPE=MESH NODE=1 ADDRESS = B8:27:EB:F1:50:C3 # 标准设备信息服务(必须保留,用于被发现) PRIMARY_SERVICE = 1800 LECHAR = Device name PERMIT=06 SIZE=06 UUID=2A00 ; index 0 # 自定义数据服务(你的传感器数据将在此广播) PRIMARY_SERVICE = 11223344-5566-7788-99AA-BBCCDDEEFF00 LECHAR = SensorData PERMIT=16 SIZE=16 UUID=ABCD ; index 1 — 支持 Notify
⚠️ 注意:DEVICE = MySensorPi 是你在手机 BLE 扫描 App(如 nRF Connect)中看到的设备名;若显示 “N/A”,一定是此处未配置或 Init_blue() 未加载该文件。
✅ 第三步:编写主服务脚本(ble_server.py)
以下脚本实现了完整流程:等待连接 → 连接成功打印日志 → 每 5 秒主动向已启用 Notify 的客户端推送新数据:
import btfpy
def ble_callback(clientnode, operation, cticn):
if operation == btfpy.LE_CONNECT:
print(f"[✅] Client connected: node {clientnode}")
elif operation == btfpy.LE_DISCONNECT:
print("[❌] Client disconnected")
return btfpy.SERVER_EXIT # 断开后退出服务(可选)
elif operation == btfpy.LE_TIMER:
# 此处为服务端定时任务(非客户端触发),每 timerds × 0.1 秒执行一次
# 向 index=1 的特征值(SensorData)写入当前传感器数据
import json
from datetime import datetime
sensor_data = {
"ts": datetime.now().isoformat(),
"temp": 23.5,
"humidity": 62.1,
"battery": 98
}
payload = json.dumps(sensor_data)[:16].encode('utf-8').ljust(16, b'\x00')
btfpy.Write_ctic(btfpy.Localnode(), 1, payload, 0)
print(f"[?] Broadcast: {payload[:16]}")
# 初始化蓝牙(加载 devices.txt)
if btfpy.Init_blue("devices.txt") != 0:
print("Failed to init BLE — check devices.txt path and syntax!")
exit(1)
# 预设初始值(可选)
btfpy.Write_ctic(btfpy.Localnode(), 1, b"Init Data", 0)
# 启动 BLE 服务:callback 为事件处理器,50 = 5.0 秒定时器(50 × 0.1s)
btfpy.Le_server(ble_callback, 50)
# 清理资源(程序退出时调用)
btfpy.Close_all()
✅ 第四步:运行与验证
python3 ble_server.py
- 手机打开 nRF Connect 或类似 BLE 扫描 App,搜索 MySensorPi;
- 点击连接 → 进入服务列表 → 找到 SensorData 特征值 → 长按并启用 Notify(⚠️ 关键!btfpy 的 Write_ctic(..., 0) 仅在 Notify 已启用时才向客户端推送);
- 即可实时看到每 5 秒更新的 JSON 数据包。
? 常见问题排查
- 树莓派不显示在扫描列表? → 检查 devices.txt 中 DEVICE = xxx 是否存在且无拼写错误;确认 Init_blue("devices.txt") 路径正确;运行 hciconfig hci0 up 确保蓝牙接口激活。
- 连接后无数据? → 客户端必须显式启用 Notify(不是 Read!),否则 Write_ctic 不触发传输。
- 想改推送频率? → 调整 Le_server(callback, timerds) 的 timerds 参数(单位:0.1 秒)。例如 100 = 10 秒。
- 需发送真实传感器数据? → 替换 ble_callback 中的 sensor_data 字典,接入 GPIO/DHT22/ADS1115 等模块读取逻辑即可。
通过 btfpy,你绕过了 BlueZ D-Bus 的复杂抽象,用不到 30 行核心代码就构建了一个符合 Bluetooth SIG 规范的 BLE 外设——它轻量、可靠,且天然适配 Flutter(通过 flutter_blue_plus 或 ble_lib 库轻松订阅 Notify)。这才是面向嵌入式 IoT 场景的极简实践之道。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











