Ответы:
Мне не понравился подход к опросу, поэтому я немного покопался в bluez и DBus. В итоге я написал следующий скрипт:
#!/usr/bin/python
import dbus
from dbus.mainloop.glib import DBusGMainLoop
import gobject
import subprocess
# ID of the device we care about
DEV_ID = '00_1D_54_AB_DC_72'
dbus_loop = DBusGMainLoop()
bus = dbus.SystemBus(mainloop=dbus_loop)
# Figure out the path to the headset
man = bus.get_object('org.bluez', '/')
iface = dbus.Interface(man, 'org.bluez.Manager')
adapterPath = iface.DefaultAdapter()
headset = bus.get_object('org.bluez', adapterPath + '/dev_' + DEV_ID)
# ^^^ I'm not sure if that's kosher. But it works.
def cb(iface=None, mbr=None, path=None):
if ("org.bluez.Headset" == iface and path.find(DEV_ID) > -1):
print 'iface: %s' % iface
print 'mbr: %s' % mbr
print 'path: %s' % path
print "\n"
print "matched"
if mbr == "Connected":
subprocess.call(["clementine", "--play"])
print 'conn'
elif mbr == "Disconnected":
subprocess.call(["clementine", "--stop"])
print 'dconn'
headset.connect_to_signal("Connected", cb, interface_keyword='iface', member_keyword='mbr', path_keyword='path')
headset.connect_to_signal("Disconnected", cb, interface_keyword='iface', member_keyword='mbr', path_keyword='path')
loop = gobject.MainLoop()
loop.run()
DEV_ID
до подключения ... но что, если вы хотите получать уведомления обо всех событиях подключения?
Чтобы обнаружить успешно установленное соединение Bluetooth, мы можем запустить
sdptool browse xx:xx:xx:xx:xx:xx
Таким образом, соединение SDB будет проверено на соединение с данным MAC-адресом. Это может занять значительное время, пока время просмотра не закончится с ошибкой вроде
Failed to connect to SDP server on 00:0C:78:4F:B6:B5: Host is down
Мы не знаем точное назначение вашего сценария, но, скорее всего, вы хотите воспроизводить звук через Clementine, когда подключена гарнитура.
Тогда мы могли бы просто увидеть, есть ли аудио-приемник Bluetooth с
pacmd list-sinks | grep xx_xx_xx_xx_xx_xx
Где xx_xx_xx_xx_xx_xx
находится MAC-адрес ( :
необходимо заменить на _
). Затем на выходе будет указано, доступен ли приемник звука Bluetooth, или ничего, если нет.
Смотрите этот ответ о том, как переключить аудио на этот приемник.
С помощью stream2ip мы можем определить команду оболочки или скрипт для запуска после установления соединения. Также существует возможность автоматического запуска поддерживаемого медиаплеера после установления соединения:
Stream2ip также попытается повторно подключить текущий воспроизводимый поток к аудиоустройству Bluetooth в случае, если соединение было прервано.
sdptool browse <device-id>
пока я не получу код возврата 0, а затем запустить свой сценарий, верно? Есть ли способ сделать это без опроса?
@Erigami Ваш ответ очень помог, но чтобы это сработало, я бы внес некоторые изменения. Я использую Ubuntu 14.04.
#!/usr/bin/python
import dbus
from dbus.mainloop.glib import DBusGMainLoop
import gobject
import subprocess
# ID of the device we care about
DEV_ID = 'CC:C3:EA:A5:16:90'.replace(":", "_")
dbus_loop = DBusGMainLoop()
bus = dbus.SystemBus(mainloop=dbus_loop)
# Figure out the path to the headset
man = bus.get_object('org.bluez', '/')
iface = dbus.Interface(man, 'org.bluez.Manager')
adapterPath = iface.DefaultAdapter()
print(adapterPath + '/dev_' + DEV_ID)
headset = bus.get_object('org.bluez', adapterPath + '/dev_' + DEV_ID)
# ^^^ I'm not sure if that's kosher. But it works.
def cb(*args, **kwargs):
is_connected = args[-1]
if isinstance(is_connected, dbus.Boolean) and is_connected:
print("Connected")
elif isinstance(is_connected, dbus.Boolean) and not is_connected:
print("Disconnected")
headset.connect_to_signal("PropertyChanged", cb, interface_keyword='iface', member_keyword='mbr', path_keyword='path')
loop = gobject.MainLoop()
loop.run()
Тем не менее, если это не работает, тогда используйте и контролируйте систему dbus.
dbus-monitor --system
d-feet
можно использовать дальше. Это графический инструмент для наблюдения за объектами dbus.
Вот еще один пример для мониторинга всех устройств Bluetooth. Не нужно указывать конкретный MAC-адрес. Этот подход делает настройки xinput постоянными даже при входе / выходе, приостановке / пробуждении и подключении / отключении устройства Bluetooth.
У меня есть компактная Bluetooth-клавиатура Thinkpad, и я хочу запускать команду xinput всякий раз, когда подключена клавиатура, для регулировки скорости трекпойнта. Вот шаги.
Скачать код с Github bluetooth-ruunner . Кредиты даны здесь, кто первым написал это для Raspberry Pi. Измените следующий раздел кода для запуска ваших пользовательских команд.
subprocess.call(['xinput', 'set-prop',
'ThinkPad Compact Bluetooth Keyboard with TrackPoint',
'Device Accel Constant Deceleration', '0.6'])
В моем случае это эквивалентно звонку с терминала.
$ xinput set-prop 'ThinkPad Compact Bluetooth Keyboard with TrackPoint' 'Device Accel Constant Deceleration' 0.6
Сохраните модификацию. Попробуйте запустить ваши сценарии
$ python bluetooth-runner.py
Подключите и отключите устройство Bluethooth. Вы должны увидеть соответствующее сообщение, напечатанное на экране.
Теперь сделайте ваш файл исполняемым и скопируйте его в одну из папок $PATH
, скажем, в ~/bin/
.
$ chmod +x bluetooth-runner.py
$ mkdir ~/bin # if you dont have it yet
$ cp bluetooth-runner.py ~/bin
Теперь убедитесь, что вы можете запустить скрипт из любой точки терминала (убедитесь, что он находится в вашем пути поиска).
Запустите Startup Applications
из меню убунту. Добавьте свои скрипты в автозагрузку.
Теперь осталась только одна проблема: во время входа в систему сценарии могут не перехватить самое первое событие Bluetooth. Это связано с тем, что ваше устройство Bluetooth может быть подключено до инициализации сценария в фоновом режиме.
Чтобы решить эту проблему, добавьте свою команду непосредственно в Startup Applications
. В моем случае это следующая команда:
xinput set-prop 'ThinkPad Compact Bluetooth Keyboard with TrackPoint' 'Device Accel Constant Deceleration' 0.6
И теперь вы сможете наслаждаться своим устройством Bluetooth с Ubuntu.
Вы пишете «когда ваша гарнитура подключается к вашему компьютеру». Как это происходит автоматически? Когда вам нужно запустить его вручную, вы можете также сделать его сценарием, а затем запустить свой сценарий после установления соединения. Вот что я сделал, чтобы установить устройство вывода по умолчанию для моего Bluetooth-приемника (чтобы я мог изменить громкость с помощью аппаратных клавиш):
bluetooth-connect && pactl set-default-sink bluez_sink.0C_A6_94_9A_37_4D
Где это bluetooth-connect
выглядит так: https://github.com/sblask/dotfiles/blob/c39d37ad67947b358b4a079cb41ae6f9e4a081d8/.bin/bluetooth-connect.symlink Предполагается, что все сопряжено и готово к подключению. Вы найдете MAC-адрес в blueman или запустив его, pacmd list-sinks | grep -e 'name:' -e 'index'
когда подключено устройство Bluetooth. Вы хотели бы бежать bluetooth-connect && your-script
. your-script
будет запущен только после успешного установления соединения.