检查 linux 上连接的蓝牙设备的电池电量

Check battery level of connected bluetooth device on linux

如何查看已连接蓝牙设备的电池电量?该设备在 Android 上显示电池电量,因此我假设该设备支持 GATT-based Battery Service。但是,通过在 bluetoothctl 中输入 "menu gatt",然后使用 "list-attributes [dev]" 列出设备的 GATT 属性,没有任何显示。

A similar question was posted to SO 但是 OP 似乎找到了一个对我不起作用的解决方案。当我在 bluetoothctl 中 运行 "info [dev]" 时,我没有看到电池服务的 UUID。

我更喜欢在命令行上 运行 并且与发行版无关的解决方案。

请让我知道是否应该将此问题发布到 SuperUser 上。

在 bluez 版本中,您使用的 Gatt 属性可能 experimental.If 因此您需要通过 运行 通过 -E 关键字的 bluetoothd deamon 启用实验特性 比如“/usr/libexec/bluetooth/bluetoothd -E” 这对我有用。

这是一个很好的问题,领先于目前可用的开发和工具。

简答(2018年10月)

you have to write it yourself! It won't be a one liner in the terminal. I am going to write this for myself in Python, but C has a little more documentation, so if you are skilled with C go for it.

长答案,但更推荐的起点是:

  1. 托尼·D:https://youtu.be/5fQR2PHMDWE?t=4644 managed to use bluetoothctl to read attributes and send data to a bluetooth device. Definitely check the video information, you will find great links and references: https://learn.adafruit.com/introduction-to-bluetooth-low-energy/gatt
  2. Szymon Janc:https://youtu.be/VMDyebKT5c4 LINUX 蓝牙堆栈的开发者和贡献者
  3. 肯定 查看此问题在移动设备上的回答方式。 Android 是 BAS(电池服务):https://android.stackexchange.com/questions/106073/displaying-bluetooth-gadgets-battery-status-on-the-phone

自 Bluez v5.48 起,您在 GATT 特性列表中看不到电池电量,因为此特定 GATT 特性已移至 DBUS org.bluez.Battery1 interface

从命令行:

  1. 使用 bluetoothctl
  2. 连接到您的目标 BLE 设备
  3. 然后通过运行请求DBUS:dbus-send --print-reply=literal --system --dest=org.bluez /org/bluez/hci0/dev_<mac_address_of_your_ble_peripheral> org.freedesktop.DBus.Properties.Get string:"org.bluez.Battery1" string:"Percentage"

在我的例子中,我的 BLE 外围设备具有以下 MAC 地址 C3:41:A6:C8:93:42:

$ dbus-send --print-reply=literal --system --dest=org.bluez \
    /org/bluez/hci0/dev_C3_41_A6_C8_93_42 org.freedesktop.DBus.Properties.Get \
    string:"org.bluez.Battery1" string:"Percentage"
   variant       byte 94

注意:您可能会使用 Bluez DBUS 扫描并连接到您的设备 API。

这是一种通过 pulseaudio 日志获取电池电量的方法 hack。 我的蓝牙耳机使用专有的 Apple HFP AT 命令,HFP/A2DP 协议由 pulseaudio 直接处理。似乎获得这些值的唯一方法是通过脉冲。

正如上面@OlivierM所说,UUID被bluetoothd过滤了。您可以通过从 src/gatt-client.c

中的 export_service() 函数中删除以下内容来撤消并导出 UUID,就像任何其他服务特征一样
if (gatt_db_service_get_claimed(attr))
     return;

对我来说运行这在终端有效:

upower --dump

默认情况下 Bluez 'hides' 电池服务 UUID。这是因为在 bluetoothd 启动时加载了 'battery plugin'。

如果您不想激活电池插件并使电池服务 UUID 再次对 bluetoothctl 或任何其他应用程序可见,请将 bluetoothd 的启动命令更改为如下所示:'bluetoothd -P battery'。这将确保未加载电池插件。在 Raspberry Pi 上,bluetooth.service 位于 /lib/systemd/system/bluetooth.service 中,因此您需要在该文件中进行更改。

这可能有点晚了,但对我来说这个 Python 项目运行良好:

https://github.com/TheWeirdDev/Bluetooth_Headset_Battery_Level

对于我的杂牌 X5 耳机,我只需将第 57 行的端口更改为 3。如果 "connection refused" 挂起或出错,请尝试不同的端口。

Python 程序通过 RFCOMM 使用 AT 命令,并且应该在 Pulseaudio 使用 A2DP 接收器(我的重新连接)时工作。 Python 需要 3,因为 2 没有 BT 串口。 Windows 可能无法工作,因为它缺少 bluez。它基本上与此处的 Pulseaudio hack 做同样的事情:

如果您想在交换命令时查看命令,请尝试我的调试分支:https://github.com/clst/Bluetooth_Headset_Battery_Level

(此答案特定于 headphones/headsets)

我一直在使用 clst 的回答中的 Python 程序一段时间,虽然它有效,但它需要我连接,然后断开连接并再次 运行 它。如果我正确理解问题,那是因为 只有一个程序可以打开一个套接字与蓝牙设备通信,所以它最终与 PulseAudio 争夺它。

我最近了解到 hsphfpd

hsphfpd is specification with some prototype implementation used for connecting Bluetooth devices with HSP and HFP profiles on Linux operating system.

基本上,由于一次只能有一个程序与耳机通信,并且在音频服务器中实现电池电量报告或在电源管理软件中实现音频都没有意义,因此它将该功能移至外部守护进程。这样,PulseAudio 和任何东西都可以同时使用耳机。有一个 version of PulseAudio 已修补以使用 hsphfpd。尽管它们都还只是原型,但它们似乎工作得很好。

hsphfpd 通过 DBus 报告电池状态(和其他内容),因此要从命令行获取它,您可以这样做

dbus-send --system --dest=org.hsphfpd --print-reply /org/hsphfpd/hci0/dev_XX_XX_XX_XX_XX_XX/hsp_hs org.freedesktop.DBus.Properties.Get string:org.hsphfpd.Endpoint string:BatteryLevel

甚至可以从程序中调用它。

如果您使用 Arch Linux,这两个都可以在 AUR 中使用。

在 Ubuntu 20+ 上,它会在电源面板的设备选项卡下显示电池