BLE(蓝牙低功耗)中如何有2个广告? [英] How to have 2 advertisements in BLE(BlueTooth Low Energy)?

查看:260
本文介绍了BLE(蓝牙低功耗)中如何有2个广告?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究BLE广告.我想知道BLE中是否有2个广告.我需要服务数据和制造商数据.我正在使用Python.该代码基于 https://git .kernel.org/pub/scm/bluetooth/bluez.git/tree/test/example-advertisement . 我需要支持EddyStone Beacon和一些制造商数据.但是我不知道如何实现它. 谢谢.

解决方案

要制作多个广告,关键项是每个广告都必须使用其发布的唯一D-Bus对象路径来创建./p>

在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, bus, 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, bus, index):
        Advertisement.__init__(self, bus, index, '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, 0x65, 0x62, 0x73, 0x69, 0x74, 0x65, 0x07]
        elif index == 1:
            prefix = [0x01]  # URL scheme = https://www.
            url = [0x62, 0x6c, 0x75, 0x65, 0x74, 0x6f, 0x6f, 0x74, 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(), {},
                                         reply_handler=register_ad_cb,
                                         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信标.

I'm working on BLE advertisement. I'd like to know if it's possible to have 2 advertisements in BLE. I need to have both service data and manufacturer data. I'm using Python. The code is based on https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/example-advertisement. I need to support EddyStone Beacon and some manufacturer data. But I don't know how to implement it. Thanks.

解决方案

The key item when wanting to do multiple advertisements, is that each advertisement must be created with its own unique D-Bus object path that it is published on.

In the BlueZ example they do this by having a PATH_BASE and appending the index value to it to make it unique:

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, bus, self.path)

They then use this unique path when calling RegisterAdvertisement:

    ad_manager.RegisterAdvertisement(test_advertisement.get_path(), {},
                                     reply_handler=register_ad_cb,
                                     error_handler=register_ad_error_cb)

To make something that ran, I modified the BlueZ example. These modifications focused on getting something to run with minimal changes rather than this is how I would do it in production.

First, I changed the TestAdvertisement to do a different advertisement depending if it was called with index 0 or index 1:

class TestAdvertisement(Advertisement):

    def __init__(self, bus, index):
        Advertisement.__init__(self, bus, index, '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, 0x65, 0x62, 0x73, 0x69, 0x74, 0x65, 0x07]
        elif index == 1:
            prefix = [0x01]  # URL scheme = https://www.
            url = [0x62, 0x6c, 0x75, 0x65, 0x74, 0x6f, 0x6f, 0x74, 0x68, 0x00]
        eddystone_data = frame_type + power + prefix + url
        self.add_service_data('FEAA', eddystone_data)

I then modified where TestAdvertisement was called so it was called twice, once with index=0 and once with 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(), {},
                                         reply_handler=register_ad_cb,
                                         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)

I also modified the code to unregister both advertisements to clean up at the end.

The example should show two Eddystone URL beacons with different URL's.

这篇关于BLE(蓝牙低功耗)中如何有2个广告?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆