使用 python 寻找低功耗蓝牙

Posted

技术标签:

【中文标题】使用 python 寻找低功耗蓝牙【英文标题】:Finding Bluetooth low energy with python 【发布时间】:2014-07-10 09:21:45 【问题描述】:

是否可以修改此代码以包含蓝牙低功耗设备? https://code.google.com/p/pybluez/source/browse/trunk/examples/advanced/inquiry-with-rssi.py?r=1

我可以找到我的手机和其他蓝牙 4.0 设备等设备,但找不到任何 BLE。如果无法修改,是否可以运行 hcitool lescan 并从 python 中的 hci 转储中提取数据?我可以使用这些工具来查看我正在寻找的设备,它会在 hcidump 中提供 RSSI,这就是我的最终目标。从 BLE 设备获取 MAC 地址和 RSSI。

谢谢!

【问题讨论】:

该代码不支持 BLE 功能......它需要进行大量更改才能支持 BLE。 您知道那里有任何功能性 BLE 扫描代码吗?我已经搜索了很多,但没有找到。谢谢! 【参考方案1】:

正如我在评论中所说,该库不适用于 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]))

【讨论】:

另外,我并没有尝试建立连接,只接收我周围的 LE 设备并找到这些 LE 设备的 RSSI 和 MAC 地址。所以希望我能弄明白....再次感谢。 k.. RSSI 值在该数据包中...不过,不记得是哪些字节。 蒂姆,我试过你的代码,请原谅,我对此很陌生,我需要编辑什么吗? 中的文件“scanner.py”,第 61 行 print(':'.join("0:02x".format(x) for x in data[12:6:-1])) 文件“ scanner.py" 第 61 行,在 print(':'.join("0:02x".format(x) for x in data[12:6:-1])) Valueerror: 未知格式代码'x' 表示“str”类型的对象 感谢您的帮助。 对于 python 2.7,将最后一行更改为: print(':'.join("0:02x".format(ord(x)) for x in data[12:6:- 1])) 由于RSSI是作为数据包的最后一个字节发送的,所以可以这样访问:print ord(data[-1])【参考方案2】:

你也可以试试pygattlib。它可用于发现设备,并且(当前)对读/写特性有基本支持。暂时没有 RSSI。

您可以使用以下 sn-p 发现:

from gattlib import DiscoveryService

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

DiscoveryService 接受设备名称,discover 方法接受等待响应的超时时间(以秒为单位)。 devices是一个字典,以BL地址为键,名称为值。

pygattlib 是为 Debian(或 Ubuntu)打包的,也可以作为 pip 包提供。

【讨论】:

pygattlib 上是否支持 OSX? 很抱歉,我没有 OSX 来试用它。您可以获取源代码并尝试自己编译...并分享结果! ;)

以上是关于使用 python 寻找低功耗蓝牙的主要内容,如果未能解决你的问题,请参考以下文章

Android 低功耗蓝牙(Ble) 开发总结

Uni-App开发BLE低功耗蓝牙流程

iOS蓝牙(BLE4.0低功耗)详细渗透讲解

Android ble (蓝牙低功耗) 中的坑和技巧

解密:Ble低功耗蓝牙和蓝牙mesh网络之间的关系

Android 低功耗Ble 蓝牙4.0多连接 开源框架