从命令行连接到蓝牙设备

背景:我正在使用我的蓝牙耳机作为音频输出。 我设法通过BluetoothHeadset社区文档的一长串说明来完成它,并且由于另一个问题 ,我已经自动将耳机激活为默认音频输出到脚本中。

但是,由于我将蓝牙耳机与我的手机和电脑一起使用(并且耳机不支持两个输入连接),以便手机在手机开机时不“窃取”连接,我强制将耳机插入连接到计算机时的发现模式(手机自动连接到它)。

因此,即使耳机配对正常并且在“正常”情况下自动连接,我也必须始终使用通知区域中的小蓝牙图标来实际连接到我的设备(参见屏幕截图)。

我想避免的:此GUI用于连接已知和配对的蓝牙设备:

使用图标连接蓝牙耳机

我想要的是:我想让蓝牙完全按照GUI中的连接项所做的,只使用命令行。 我想使用命令行,因此我可以为操作创建一个按键快捷键,并且每次我想要建立与设备的连接时都不需要导航GUI。

问题:如何从命令行尝试连接到特定的,已知的和配对的蓝牙设备

进一步的问题:如何判断连接是否成功?

蓝牙守护进程

在默认安装中,守护程序( bluetoothd )在后台运行(从文件/etc/init.d/bluetooth运行)。 该守护进程负责识别和连接已知的蓝牙设备,并且可以与/etc/bluetooth配置文件进行配置。 要自动连接耳机,应取消注释audio.conf的以下行(删除# ):

 AutoConnect=true 

要重新启动守护进程,请键入sudo /etc/init.d/bluetooth restart

备注:使用命令行工具sudo hcitool cc 在守护程序运行时未导致与测试环境中的已知设备的稳定连接。


的DBus

为了连接断开但实际存在且配对的耳机,我们可以使用脚本中的D-Bus 。 这是python中的一个例子:

 #!/usr/bin/python # Toggles headset connection import dbus from dbus.mainloop.glib import DBusGMainLoop dbus_loop = DBusGMainLoop() bus = dbus.SystemBus(mainloop=dbus_loop) #Get dbus interface for headset manager = bus.get_object('org.bluez', '/') iface_m = dbus.Interface(manager, 'org.bluez.Manager') adapterPath = iface_m.DefaultAdapter() adapter = bus.get_object('org.bluez', adapterPath) iface_a = dbus.Interface(adapter, 'org.bluez.Adapter') devicePath = iface_a.ListDevices()[0] # assuming first device device = bus.get_object('org.bluez', devicePath) iface_h = dbus.Interface(device, 'org.bluez.Headset') #Check state of connection connected = iface_h.IsConnected() print 'Toggling connection. Please wait' # toggle connection if not connected: try: iface_h.Connect() print 'Connecting: ', devicePath except: print 'Device not found' else: iface_h.Disconnect() print 'Disconnecting: ', devicePath 

如果我们有多个蓝牙设备,我们必须适当地调整devicePath 。 以上示例将连接Headset 。 将接口更改为任何其他服务的不同协议(例如AudioSink )。


pulseaudio的

如果您知道蓝牙设备的MAC地址,可以通过以下方式将其作为脉冲音频的输出接收器连接:

 pacmd set-default-sink bluez_sink.xx_xx_xx_xx_xx_xx 

其中xx_xx_xx_xx_xx_xx是MAC地址(将’:’替换为’_’以便pulseaudio识别它)。

有关更多详细信息,请参阅此答案 。

我使用此脚本连接我的蓝牙音频设备。 如果您的耳机已经配对,您应该能够使用org.bluez.Headset.Connect / Disconnect以相同的方式连接耳机,而不是org.bluez.Audiosink.Connect / Disconnect

 #!/bin/bash MAC_ADD="C8:84:47:10:11:CD" MAC_ADD="dev_${MAC_ADD//:/_}" BT_ADAPTER=`dbus-send --system --print-reply --dest=org.bluez / \ org.bluez.Manager.DefaultAdapter|awk '/object path/ {print $3}'` BT_ADAPTER="${BT_ADAPTER//\"/}/$MAC_ADD" echo "Connecting to $BT_ADAPTER..." if [ "$1" == "on" ]; then dbus-send --print-reply --system --dest=org.bluez $BT_ADAPTER org.bluez.AudioSink.Connect elif [ "$1" == "off" ]; then dbus-send --print-reply --system --dest=org.bluez $BT_ADAPTER org.bluez.AudioSink.Disconnect fi 

HTH!

我使用i3作为窗口管理器,因此我没有可用的蓝牙托盘图标。 由于某种原因,统一设置中的检查按钮不敏感,因此我需要一种方法来不时连接我的耳机。

在此处输入图像描述

似乎bluez 改变了他们的dbus API 。 使用org.bluez.Manager的答案似乎不再起作用。 相反,建议使用ObjectManager

这是一个更新的python脚本,它将连接它找到的第一个未连接的蓝牙耳机(可能是列表包括所有配对的设备?):

 #!/usr/bin/env python # Toggles headset connection from __future__ import print_function from __future__ import unicode_literals import dbus from dbus.mainloop.glib import DBusGMainLoop def find_headset(bus): manager = dbus.Interface(bus.get_object("org.bluez", "/"), "org.freedesktop.DBus.ObjectManager") objects = manager.GetManagedObjects() for path, ifaces in objects.items(): if ("org.bluez.Device1" in ifaces and "org.freedesktop.DBus.Properties" in ifaces): iprops = dbus.Interface( bus.get_object("org.bluez", path), "org.freedesktop.DBus.Properties") props = iprops.GetAll("org.bluez.Device1") # Looking for a headset. Could also match on other properties like # "Name". See bluez docs for whats available. if props.get("Class") == 0x240404: if props.get("Connected"): print("Found headset {} ({}) but it is already connected" .format(props.get("Name"), props.get("Address"))) continue return path dbus_loop = DBusGMainLoop() bus = dbus.SystemBus(mainloop=dbus_loop) hpath = find_headset(bus) if hpath: adapter = dbus.Interface( bus.get_object("org.bluez", hpath), "org.bluez.Device1") adapter.Connect() 

这个例子就像这个线程上的另一个例子一样,使用了dbus python包。 在ubuntu 16.04上,我通过apt-get install python-dbus

如果您希望与其他条件匹配,则本文档将显示可通过dbus查询的属性列表。

我把这个脚本保存在我的PATH上的~/.local/bin/bt-connect-headset ,所以我可以从i3启动器执行它。 如果您打算将其用作命令,请将其设为可执行文件( chmod +x bt-connect-headset )。

此脚本仅在截至09/28/2018的最新ubuntu 16.04上进行了测试。