1

I am recently playing with Bluetooth on my Raspberry Pi. I understand the code such as:

sudo hcitool -i hci0 cmd 0x08 0x0008 1e 02 01 1a 1a ff 4c 00 02 15 e2 c5 6d b5 df fb 48 d2 b0 60 d0 f5 a7 10 96 e0 00 00 00 00 c5 00 00 00 00 00 00 00 00 00 00 00 00 00

I know that ogf 0x08, ocf 0x0008 is the LE Set Advertising Data command. And the list of commands can be found in Section 7.8 Part E, Vol. 4 of the Core Specification. But I can't find a document that explains the output of such commands. For example, the above command returns:

< HCI Command: ogf 0x08, ocf 0x0008, plen 44
  1E 02 01 1A 1A FF 4C 00 02 15 E2 C5 6D B5 DF FB 48 D2 B0 60 
  D0 F5 A7 10 96 E0 00 00 00 00 C5 00 00 00 00 00 00 00 00 00 
  00 00 00 00 
> HCI Event: 0x0e plen 4
  01 08 20 00 

After some website searching, I can guess that plen means parameter length. 0x0e means the HCI_Command_Complete (Sec. 7.7.14, Part E, Vol. 4). In addition, for 01 08 20 00, I guess 08 represents the ocf of the input command, and 00 probably means the command succeeded status. Please let me know if my guesses are wrong.

However, I still can't figure out the output of the following command:

sudo hcitool -i hci0 cmd 0x08 0x007

The output is

< HCI Command: ogf 0x08, ocf 0x0007, plen 0
> HCI Event: 0x0e plen 5
  01 07 20 00 0C

Does 00 mean the command succeeded and 0C gives the transmit power level? Or 0C is Command Disallowed error code?

To summarize, I do hope if someone could tell me or provide a reference for the code meaning in the "HCI Event". And I do need to know 01 07 20 00 0C asap since I want to know the TX power level.

Thank you so much in advance.

1 Answer 1

1

The easiest way of seeing what the HCI commands are doing is to have sudo btmon running in another terminal. btmon does a good job of giving more information about what is happening at the HCI low level. For example when I put your command in it gave the following output:

output from btmon

I would add the hcitool has been deprecated as documented at:

https://wiki.archlinux.org/index.php/bluetooth#Deprecated_BlueZ_tools

The preferred command line tools are btmgmt (low-level) and bluetoothctl (higher-level).

It looks like you are trying to create an iBeacon. If you are looking to do this with code then using BlueZ's DBus API would probably be the expected thing as working with HCI commands can be tricky and break your system. The DBus API docs are available at:

https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/advertising-api.txt

A simple python example of an ibeacon is:

import threading
import pydbus
from gi.repository import GLib


class Beacon:
    """
    <node>
        <interface name='org.bluez.LEAdvertisement1'>
            <method name='Release'>
                <annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
            </method>
            <annotation name="org.freedesktop.DBus.Properties.PropertiesChanged" value="const"/>
            <property name="Type" type="s" access="read"/>
            <property name="ServiceUUIDs" type="as" access="read"/>
            <property name="ServiceData" type="a{sv}" access="read"/>
            <property name="IncludeTxPower" type="b" access="read"/>
            <property name="ManufacturerData" type="a{qv}" access="read"/>
            <property name="SolicitUUIDs" type="as" access="read"/>
        </interface>
    </node>
    """
    LE_ADVERTISEMENT_IFACE = 'org.bluez.LEAdvertisement1'

    def Release(self):
        pass

    @property
    def Type(self):
        return 'broadcast'
    
    @property
    def ServiceUUIDs(self):
        return []

    @property
    def ServiceData(self):
        return {}

    @property
    def IncludeTxPower(self):
        return False

    @property
    def ManufacturerData(self):
        return {0x004c: pydbus.Variant('ay', [0x02, 0x15, 0xE2, 0xC5, 0x6D, 0xB5, 0xDF, 0xFB,
                                              0x48, 0xD2, 0xB0, 0x60, 0xD0, 0xF5, 0xA7, 0x10,
                                              0x96, 0xE0, 0x00, 0x01, 0x00, 0x02, 0x0c])}


    @property
    def SolicitUUIDs(self):
        return []

class LEAdvertisement:
    def __init__(self, object_path):
        bus = pydbus.SystemBus()
        reg1 = bus.register_object(object_path, Beacon(), None)


class LEAdvertisingManager:
    def __init__(self, object_path):
        lea_iface = 'org.bluez.LEAdvertisingManager1'
        bus = pydbus.SystemBus()
        ad_manager = bus.get('org.bluez', '/org/bluez/hci0')[lea_iface]
        ad_manager.RegisterAdvertisement(object_path, {})
        print('Registered Ad')


def publish_now():
    print('Publishing Ad')
    aloop = GLib.MainLoop()
    aloop.run()


def thread_function():
    print('Starting thread')
    LEAdvertisement(app_path)
    publish_now()
    print('thread finished')


if __name__ == '__main__':
    app_path = '/org/bluez/example/advertisement0099'

    loop = GLib.MainLoop()
    x = threading.Thread(target=thread_function, daemon=True)
    x.start()
    LEAdvertisingManager(app_path)

    try:
        loop.run()
    except KeyboardInterrupt:
        print("\nStopping ...")
        loop.quit()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.