如何解决BLE蓝牙低功耗中如何有2个广告?
我正在研究BLE广告。我想知道BLE中是否有2个广告。我需要服务数据和制造商数据。我正在使用Python。该代码基于https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/example-advertisement。 我需要支持EddyStone Beacon和一些制造商数据。但是我不知道如何实现它。 谢谢。
解决方法
要进行多个广告时的关键项是,每个广告都必须使用其自己发布的唯一D-Bus对象路径来创建。
在BlueZ示例中,他们通过使用PATH_BASE
并将其附加index
值使其唯一来完成此操作:
class Advertisement(dbus.service.Object):
PATH_BASE = '/org/bluez/example/advertisement'
def __init__(self,bus,index,advertising_type):
self.path = self.PATH_BASE + str(index)
self.bus = bus
self.ad_type = advertising_type
self.service_uuids = None
self.manufacturer_data = None
self.solicit_uuids = None
self.service_data = None
self.local_name = None
self.include_tx_power = False
self.data = None
dbus.service.Object.__init__(self,self.path)
然后他们在呼叫RegisterAdvertisement
时使用此唯一路径:
ad_manager.RegisterAdvertisement(test_advertisement.get_path(),{},reply_handler=register_ad_cb,error_handler=register_ad_error_cb)
为了制作出可以运行的东西,我修改了BlueZ示例。 这些修改的重点是使某些东西以最小的变化运行,而不是我在生产中这样做。
首先,我更改了TestAdvertisement
来制作不同的广告,具体取决于它是使用索引0
还是索引1
来调用的:
class TestAdvertisement(Advertisement):
def __init__(self,index):
Advertisement.__init__(self,'broadcast')
self.add_service_uuid('FEAA')
frame_type = [0x10] # Frame Type = 0x10
power = [0x00] # Power = 0x00
if index == 0:
prefix = [0x02] # URL scheme = 0x02 (http://)
url = [0x73,0x61,0x6D,0x70,0x6C,0x65,0x77,0x62,0x73,0x69,0x74,0x07]
elif index == 1:
prefix = [0x01] # URL scheme = https://www.
url = [0x62,0x6c,0x75,0x6f,0x68,0x00]
eddystone_data = frame_type + power + prefix + url
self.add_service_data('FEAA',eddystone_data)
然后我修改了调用TestAdvertisement
的位置,因此它被调用了两次,一次是用index=0
,一次是用index=1
:
ad_manager = dbus.Interface(bus.get_object(BLUEZ_SERVICE_NAME,adapter),LE_ADVERTISING_MANAGER_IFACE)
mainloop = GLib.MainLoop()
test_advertisement= []
for ad_id in range(2):
test_advertisement.append(TestAdvertisement(bus=bus,index=ad_id))
print(f'{ad_id}: Registering advert path: {test_advertisement[ad_id].get_path()}')
ad_manager.RegisterAdvertisement(test_advertisement[ad_id].get_path(),error_handler=register_ad_error_cb)
if timeout > 0:
threading.Thread(target=shutdown,args=(timeout,)).start()
else:
print('Advertising forever...')
try:
mainloop.run() # blocks until mainloop.quit() is called
except KeyboardInterrupt:
print('Cleaning up advertisements')
for this_ad in test_advertisement:
ad_manager.UnregisterAdvertisement(this_ad)
print('Advertisement unregistered')
dbus.service.Object.remove_from_connection(this_ad)
我还修改了代码,以注销两个广告,最后进行清理。
该示例应显示两个具有不同URL的Eddystone URL信标。
,感谢@ukBaz!您的代码有效!我还尝试了2个内容不同的广告:一个拥有我们自己的特殊数据,另一个具有EddyStone-URL。我们之所以要拥有广告1,是因为我们的移动应用希望拥有一种方法来识别该服务是否来自我们的设备。因此,我们需要特殊的制造商数据,例如“ 1234”。同时,我们还需要支持EddyStone Beacon。因此,我们需要2个广告。我不确定这是否是最佳解决方案。请评论。 我尝试过这个。好像可以了包含2个内容不同的广告是否有副作用? 由于我们打算连接设备,因此我将“广播”更改为“外围设备”。这是我的代码(我主要更改了“如果索引== 0:”部分):
class TestAdvertisement(Advertisement):
def __init__(self,'peripheral')
if index == 0:
# My code to have special manufacturer data and service UUID
self.add_manufacturer_data(0x1234,b"1234567890")
self.add_service_uuid("1234")
elif index == 1:
self.add_service_uuid('FEAA')
frame_type = [0x10] # Frame Type = 0x10
power = [0x00] # Power = 0x00
prefix = [0x01] # URL scheme = https://www.
url = [0x62,0x00]
eddystone_data = frame_type + power + prefix + url
self.add_service_data('FEAA',eddystone_data)
由于注释不能很好地支持代码,因此我将其放在一个问题的答案中。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。