树莓派3 Python BLE广播添加制造数据后无法被检测的问题求助
树莓派3 Python BLE广播添加制造数据后无法被检测的问题求助
环境信息
- 硬件:树莓派3 + 支持BLE的蓝牙适配器
- 系统:Raspberry Pi OS Lite 32位(全新安装)
- Python版本:3.11.2
- 依赖:dbus、GLib相关系统库
问题描述
我在做一个BLE广播的小项目,通过Python调用BlueZ的DBUS接口实现功能。目前遇到一个奇怪的问题:如果不配置ManufacturerData(制造商标识数据),广播能正常被手机上的LightBlue或nRF Connect检测到,设备名"MyBrickPi"显示完全正常。
但只要我取消注释代码里的ManufacturerData相关配置,哪怕是最简单的配置(比如仅给一个厂商ID加单字节数据),运行脚本时没有任何报错,控制台也会输出Advertising started.,但手机端完全搜不到这个广播了。
我的代码
下面是完整的Python代码,其中ManufacturerData部分我尝试了多种写法,目前都被注释:
import dbus import dbus.mainloop.glib import dbus.service from gi.repository import GLib MANUFACTURER_ID = 0x0397 # LEGO厂商ID PAYLOAD_BYTES = b'\x10\x06\x18\x1a\xb6' class Advertisement(dbus.service.Object): PATH_BASE = '/org/bluez/example/advertisement' def __init__(self, bus, index): self.path = self.PATH_BASE + str(index) self.bus = bus super().__init__(bus, self.path) def get_path(self): return dbus.ObjectPath(self.path) def get_properties(self): return { 'org.bluez.LEAdvertisement1': { 'Type': 'peripheral', 'LocalName': 'MyBrickPi', # 以下是我尝试过的各种ManufacturerData配置,全部注释后广播正常 # 'ManufacturerData': { # dbus.Array([dbus.Byte(0x00)], signature='y') # dbus.UInt16(0x0397): dbus.Array([dbus.Byte(0x01)], signature='y') # dbus.UInt16(0x0397): dbus.Array([dbus.Byte(b) for b in b'\x10\x06\x18\x1a\xb6'], signature='y') # dbus.UInt16(0xFFFF): dbus.Array([dbus.Byte(0x01)], signature='y') # dbus.UInt16(0x0000): dbus.Array([dbus.Byte(0x01)], signature='y') # {dbus.UInt16(0x0000): [16, 5, 7, 24, 186, 175, 161]} # [{16: [[b'4a04389']]}] # }, # 'IncludeTxPower': True, # 'Appearance': dbus.UInt16(0), } } @dbus.service.method('org.freedesktop.DBus.Properties', in_signature='s', out_signature='a{sv}') def GetAll(self, interface): return self.get_properties()['org.bluez.LEAdvertisement1'] @dbus.service.method('org.bluez.LEAdvertisement1', in_signature='', out_signature='') def Release(self): print('Advertisement released') def main(): dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) bus = dbus.SystemBus() adapter_path = '/org/bluez/hci0' adapter = bus.get_object('org.bluez', adapter_path) adapter_props = dbus.Interface(adapter, 'org.freedesktop.DBus.Properties') # 确保蓝牙适配器已开启 try: powered = adapter_props.Get('org.bluez.Adapter1', 'Powered') if not powered: adapter_props.Set('org.bluez.Adapter1', 'Powered', dbus.Boolean(1)) except Exception as e: print(f"Failed to get/set adapter power state: {e}") return ad_manager = dbus.Interface(adapter, 'org.bluez.LEAdvertisingManager1') advertisement = Advertisement(bus, 0) def on_success(): print("Advertising started.") def on_error(error): print(f"Failed to advertise: {error}") ad_manager.RegisterAdvertisement(advertisement.get_path(), {}, reply_handler=on_success, error_handler=on_error) try: GLib.MainLoop().run() except KeyboardInterrupt: print("\nStopping advertisement...") try: ad_manager.UnregisterAdvertisement(advertisement) except Exception: print("Advertisement was not registered or already unregistered.") advertisement.remove_from_connection() if __name__ == '__main__': main()
我尝试过的排查方法
- 更换厂商ID:试过LEGO的0x0397、测试用的0xFFFF、0x0000,结果完全一致
- 简化Payload:从5字节数据缩减到单字节0x01,依然搜不到广播
- 调整其他参数:尝试开启
IncludeTxPower、设置Appearance,对问题无任何影响 - 检查适配器状态:用
bluetoothctl确认适配器已开启且处于可发现状态
期望结果
我最终想要实现的是:广播LEGO厂商ID(0x0397)加上自定义Payload数据(比如b'\x10\x06\x18\x1a\xb6'),只要能被手机检测到即可,Payload内容暂时可以简化。有没有朋友遇到过类似问题,或者能帮我看看ManufacturerData的配置哪里写错了?
内容来源于stack exchange
相关产品推荐
相关产品推荐

