Finding Bluetooth low energy with python

后端 未结 2 960
予麋鹿
予麋鹿 2021-02-02 03:18

Is it possible for this code to be modified to include Bluetooth Low Energy devices as well? https://code.google.com/p/pybluez/source/browse/trunk/examples/advanced/inquiry-wit

相关标签:
2条回答
  • 2021-02-02 03:32

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

    Here's some example code 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 of that together by looking at the hcitool and gatttool source code that comes with Bluez. The code is completely dependent on libbluetooth-dev so you'll have to make sure you have that installed first.

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

    EDIT:

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

    0 讨论(0)
  • 2021-02-02 03:44

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

    You could discover using the following snippet:

    from gattlib import DiscoveryService
    
    service = DiscoveryService("hci0")
    devices = service.discover(2)
    

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

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

    0 讨论(0)
提交回复
热议问题