Python使用hcitool实现低功耗蓝牙设备搜索详解

本文介绍了如何在Python中使用hcitool工具扫描低功耗蓝牙设备(BLE),并详细解释了如何处理扫描过程中的异常,以及如何解析和过滤扫描结果。通过设置超时和捕获输出,程序能够在指定时间内停止扫描,并过滤掉未知设备和重复MAC地址,最终输出非unknown的设备列表。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文将介绍如何在 python 程序中使用 hcitool 工具对周围低功耗蓝牙设备(BLE)进行扫描。

设备及系统软件需求

设备依赖:

树莓派3B及更新版本设备

其他带有蓝牙功能的开发板(需确认软件支持)

配备蓝牙功能的x86主机或已安装蓝牙适配器

系统及软件依赖:

树莓派OS:Raspbian、Ubuntu Core

X86主机:Ubuntu、或其他Linux发行版 (Window及MacOS无原生支持Gatttool及Hcitool,因此不适应,若需要相应功能,可参考pybluez库)

软件:bluetooth、rpi-bluetooth (树莓派)

参考资料

参考开源库 penlin/pygatt ,以其中 /pygatt/backends/gatttool/gatttool.py 中 scan 方法为例,作相应修改完成。

前置知识

首先需要了解 hcitool 工具的使用。对于该工具的详细功能和参数的使用方法,可以使用:

hcitool --help

在开始使用 hcitool 工具之前,需要先进行一些配置。默认情况下, hcitool 工具需要有 root 权限,但是我们在使用中或者python程序中调用,都希望不需要使用 root 权限或者使用 sudo 来提权,我们可以通过以下配置来实现不需要 root 权限而对工具进行调用:

sudo setcap 'cap_net_raw,cap_net_admin+eip' `which hcitool`

完成配置后,我们就可以开始来了解 hcitool这个工具。以下介绍几个最主要常用的功能。首先是获取当前蓝牙设备的信息:

hcitool dev
>
Devices:
        hci0    00:1A:7D:DA:**:**

如果蓝牙设备正常,可以看到返回当前蓝牙的 Mac 地址,如果蓝牙设备不能正常使用,则不会有返回信息,我们可以通过手动关闭蓝牙来实验以下。

sudo hciconifg hci0 down
hcitool dev
>
Devices:

sudo hciconfig hci0 up
hcitool dev
>
Devices:
        hci0    00:1A:7D:DA:**:**

这里还有一个技巧,如果使用蓝牙扫描是出现 Set scan parameters failed: Input/output errer 的错误信息,可以使用上述的方法,手动重启蓝牙,即可解决问题。

接下来是对周围的低功耗蓝牙设备进行搜索:

hcitool lescan
>
LE Scan ...
20:91:**:B9:0B:** (unknown)
20:91:48:**:0B:EE UPots
20:91:48:B9:**:89 (unknown)
20:91:**:B9:08:89 UPots
20:91:48:**:0B:C2 (unknown)
20:91:48:B9:**:C2 UPots
20:91:48:**:0B:EE (unknown)

执行命令后,可以看到会不断打印出周围蓝牙设备的名称和 MAC 地址。

到这里为止,我们就完成对 hcitool 工具的基本了解了,下面将进入 python 编程部分。

使用 Python 调用 hcitool 工具完成 BLE 扫描

我们在刚才是试验中,已经了解到,当使用 hcitool 时,该工具不会自动停止,而是会不断打印搜索结果。这里我们需要使用 pexpecttimeout 来控制运行一定时间后就自动停止。

import pexpect

# 这里的 timeout 设置为 3 ,即 3 秒后就会停止
scan = pexpect.spawn('hcitoon lescan, timeout=3)

在运行后,正常情况下的输出结果应该和上面类似,以 LE Scan … 开头,下面接着就是搜索出来的设备和 MAC 地址,我们可以通过用 expect 来获取结果。这里有个技巧,因为我们的 hcitool 会不断打印到时间停止,所以我们可以通过 expect 捕获随便一个不存在的字符,这样程序就会直接进入 pexpect.TIMEOUT ,我们再通过 before 就能拿到所有的打印结果,接而进一步对结果处理即可。

scan.expect('foooooo') # 设置捕获一个不存在的字符串即可
scan.before
>
 b'LE Scan ...\r\n20:91:48:**:0B:C2 (unknown)\r\n
20:91:48:**:08:89 (unknown)\r\n
20:91:48:**:
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值