Help us understand the problem. What is going on with this article?

BluezをD-busから使う LE advertise

More than 3 years have passed since last update.

BlueZをD-Busから使う方法について

LEのAdvertiseする方法を調べました。

Bluezのバージョンについて

  • D-Bus から LE advertisetをするには5.30以降が必要です。下記は5.40で確認しました。

leadv.py

  • Bluezのexample-advertisementを参考にしました。
leadv.py
#!/usr/bin/python

import dbus
import dbus.mainloop.glib
import dbus.service
import gobject as GObject

mainloop = None

BLUEZ_SERVICE_NAME = 'org.bluez'
LE_ADVERTISING_MANAGER_IFACE = 'org.bluez.LEAdvertisingManager1'
DBUS_OM_IFACE = 'org.freedesktop.DBus.ObjectManager'
DBUS_PROP_IFACE = 'org.freedesktop.DBus.Properties'

LE_ADVERTISEMENT_IFACE = 'org.bluez.LEAdvertisement1'

class FixedAdvertisement(dbus.service.Object):
    PATH_BASE = '/org/bluez/example/fixedadvertisement'

    def __init__(self, bus, index, advertising_type):
        self.path = self.PATH_BASE + str(index)
        self.bus = bus
        self.ad_type = advertising_type
        dbus.service.Object.__init__(self, bus, self.path)

    def get_path(self):
        return dbus.ObjectPath(self.path)

    @dbus.service.method(DBUS_PROP_IFACE,
                         in_signature='s',
                         out_signature='a{sv}')
    def GetAll(self, interface):
        if interface != LE_ADVERTISEMENT_IFACE:
            raise InvalidArgsException()

        properties = dict()
        properties['Type'] = self.ad_type
        return properties

    @dbus.service.method(LE_ADVERTISEMENT_IFACE,
                         in_signature='',
                         out_signature='')
    def Release(self):
        print '%s: Released!' % self.path

def register_ad_cb():
    print 'Advertisement registered'

def register_ad_error_cb(error):
    print 'Failed to register advertisement: ' + str(error)
    mainloop.quit()

def find_adapter(bus):
    remote_om = dbus.Interface(bus.get_object(BLUEZ_SERVICE_NAME, '/'),
                               DBUS_OM_IFACE)
    objects = remote_om.GetManagedObjects()

    for o, props in objects.iteritems():
        if LE_ADVERTISING_MANAGER_IFACE in props:
            return o

    return None

def main():
    global mainloop

    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

    bus = dbus.SystemBus()

    adapter = find_adapter(bus)
    if not adapter:
        print 'LEAdvertisingManager1 interface not found'
        return

    ad_manager = dbus.Interface(bus.get_object(BLUEZ_SERVICE_NAME, adapter),
                                LE_ADVERTISING_MANAGER_IFACE)

    ad_manager.RegisterAdvertisement(FixedAdvertisement(bus, 0, 'broadcast').get_path(), {},
                                     reply_handler=register_ad_cb,
                                     error_handler=register_ad_error_cb)

    mainloop = GObject.MainLoop()
    mainloop.run()

if __name__ == '__main__':
    main()
  • FixedAdvertisementクラスはアドバタイズデータのクラスです。
    • サービスデーモンから呼ばれるので、GetAll()とRemove()のメソッドをクラスに用意する必要があります。
    • GetAll()では、アドバタイズデータをpropertisとして返します。
    • Remove()はアドバタイズを停止するときに呼ばれれます。
    • GetAll()とRemove()は定義する際に@dbus.service.methodのおまじないが必要です。
  • register_ad_cb()とregister_ad_error_cb()はRegisterAdvertisement()で登録するコールバック関数です。
  • find_adapter()はAdapterを探して、LE_ADVERTISING_MANAGER_IFACEの有無からLE advertiseが使えるか判定します。
  • メイン
    • mainloopのおまじない
    • busとadapterの取得
    • アドバタイズマネージャの取得
    • FixedAdvertisementを生成して、RegisterAdvertisement()に登録する
    • メインループ

動作例

  • アドバタイズはスマートフォン等のアプリで確認してください。
pi@raspberrypi: $ ./leadv.py
Advertisement registered

アドバタイズで指定できるパラメータ

  • Type : broadcast or peripheral
  • ServiceUUIDs
  • ManufacturerData
  • SolicitUUIDs
  • ServiceData
  • IncludeTxPower

参考

eggman
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした