[ACCEPTED]-Finding Bluetooth low energy with python-bluez

Accepted answer
Score: 29

As I said in the comment, that library won't 13 work with BLE.

Here's some example code 12 to do a simple BLE scan:

import sys
import os
import struct
from ctypes import (CDLL, get_errno)
from ctypes.util import find_library
from socket import (
    socket,
    AF_BLUETOOTH,
    SOCK_RAW,
    BTPROTO_HCI,
    SOL_HCI,
    HCI_FILTER,
)

if not os.geteuid() == 0:
    sys.exit("script only works as root")

btlib = find_library("bluetooth")
if not btlib:
    raise Exception(
        "Can't find required bluetooth libraries"
        " (need to install bluez)"
    )
bluez = CDLL(btlib, use_errno=True)

dev_id = bluez.hci_get_route(None)

sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)
sock.bind((dev_id,))

err = bluez.hci_le_set_scan_parameters(sock.fileno(), 0, 0x10, 0x10, 0, 0, 1000);
if err < 0:
    raise Exception("Set scan parameters failed")
    # occurs when scanning is still enabled from previous call

# allows LE advertising events
hci_filter = struct.pack(
    "<IQH", 
    0x00000010, 
    0x4000000000000000, 
    0
)
sock.setsockopt(SOL_HCI, HCI_FILTER, hci_filter)

err = bluez.hci_le_set_scan_enable(
    sock.fileno(),
    1,  # 1 - turn on;  0 - turn off
    0, # 0-filtering disabled, 1-filter out duplicates
    1000  # timeout
)
if err < 0:
    errnum = get_errno()
    raise Exception("{} {}".format(
        errno.errorcode[errnum],
        os.strerror(errnum)
    ))

while True:
    data = sock.recv(1024)
    # print bluetooth address from LE Advert. packet
    print(':'.join("{0:02x}".format(x) for x in data[12:6:-1]))

I had to piece all 11 of that together by looking at the hcitool and 10 gatttool source code that comes with Bluez. The 9 code is completely dependent on libbluetooth-dev so you'll 8 have to make sure you have that installed 7 first.

A better way would be to use dbus 6 to make calls to bluetoothd, but I haven't had a chance 5 to research that yet. Also, the dbus interface 4 is limited in what you can do with a BLE 3 connection after you make one.

EDIT:

Martin Tramšak 2 pointed out that in Python 2 you need to 1 change the last line to print(':'.join("{0:02x}".format(ord(x)) for x in data[12:6:-1]))

Score: 7

You could also try pygattlib. It can be used to discover 10 devices, and (currently) there is a basic 9 support for reading/writing characteristics. No 8 RSSI for now.

You could discover using the 7 following snippet:

from gattlib import DiscoveryService

service = DiscoveryService("hci0")
devices = service.discover(2)

DiscoveryService accepts the name of the 6 device, and the method discover accepts a timeout 5 (in seconds) for waiting responses. devices is 4 a dictionary, with BL address as keys, and 3 names as values.

pygattlib is packaged for Debian 2 (or Ubuntu), and also available as a pip 1 package.

More Related questions