用Python查找蓝牙低能耗设备

10 投票
2 回答
45042 浏览
提问于 2025-04-18 07:13

这个代码能不能改一下,让它也能找到蓝牙低能耗设备呢? https://code.google.com/p/pybluez/source/browse/trunk/examples/advanced/inquiry-with-rssi.py?r=1

我能找到像我的手机和其他蓝牙4.0设备,但就是找不到任何蓝牙低能耗设备。如果这个代码不能改,那有没有办法在Python里运行hcitool lescan,然后从hci dump中提取数据呢?我可以用这些工具看到我想找的设备,并且在hcidump里能看到RSSI值,这正是我想要的。我的目标是从蓝牙低能耗设备获取MAC地址和RSSI值。

谢谢!

2 个回答

7

你也可以试试 pygattlib。这个工具可以用来发现设备,目前它支持基本的读取和写入特性。不过现在还没有RSSI(信号强度指示)功能。

你可以用下面的代码片段来发现设备:

from gattlib import DiscoveryService

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

DiscoveryService 这个类需要你提供设备的名称,而 discover 方法则需要一个超时时间(以秒为单位),用来等待设备的响应。 devices 是一个字典,里面的键是蓝牙地址,值是设备的名称。

pygattlib 可以在Debian(或Ubuntu)上安装,也可以通过pip包管理工具来获取。

29

正如我在评论中提到的,那个库是无法与BLE(蓝牙低功耗)一起使用的。

这里有一些简单的代码示例,可以用来进行BLE扫描:

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]))

我需要通过查看Bluez中附带的hcitoolgatttool的源代码,把这些代码拼凑在一起。这个代码完全依赖于libbluetooth-dev,所以你得先确保安装了这个库。

更好的方法是使用dbus来调用bluetoothd,但我还没有机会去研究这个。还有,使用dbus接口后,你在BLE连接上能做的事情是有限的。

编辑:

Martin Tramšak指出,在Python 2中,你需要把最后一行改成print(':'.join("{0:02x}".format(ord(x)) for x in data[12:6:-1]))

撰写回答