¿Cómo ejecuto un script cuando se conecta un dispositivo Bluetooth?

16

Me gustaría iniciar mi reproductor de música (Clementine) cuando mis auriculares bluetooth se conectan a mi computadora. ¿Cómo detecto la conexión del dispositivo bluetooth para poder ejecutar un script para iniciar el reproductor?

Erigami
fuente

Respuestas:

12

No me gustó el enfoque de votación, así que investigué un poco sobre bluez y DBus. Terminé escribiendo el siguiente script:

#!/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()
Erigami
fuente
Por supuesto, Bluez y PulseAudio operan a través del sondeo DBus. Siempre y cuando el auricular sea el adaptador predeterminado, funcionará bien en la mayoría de los casos. Asegúrese de conectar también PulseAudio a los auriculares si desea escuchar algo. Gracias por compartir su solución :)
Takkat
eso es genial si sabes lo DEV_IDanterior a la conexión ... pero ¿qué pasa si quieres ser notificado de todos los eventos de conexión?
pstanton
4

Para descubrir una conexión Bluetooth establecida con éxito, podemos ejecutar

sdptool browse xx:xx:xx:xx:xx:xx

Con esto, la conexión SDB se probará para una conexión a la dirección MAC dada. Puede pasar un tiempo considerable hasta que se agote el tiempo de espera con un error como

Failed to connect to SDP server on 00:0C:78:4F:B6:B5: Host is down

No sabemos el propósito exacto de su secuencia de comandos, pero lo más probable es que desee reproducir audio a través de Clementine cuando se conectó un auricular.

Entonces podríamos ver si hay un receptor de audio Bluetooth con

pacmd list-sinks | grep xx_xx_xx_xx_xx_xx

¿Dónde xx_xx_xx_xx_xx_xxestá la dirección MAC ( :debe reemplazarse por _)? La salida le dirá si hay un receptor de audio Bluetooth disponible o nada si no es así.

Vea esta respuesta sobre cómo cambiar el audio a este sumidero.


Stream2ip

Con stream2ip podemos definir un comando de shell o un script para ejecutar después de establecer una conexión. También hay una opción para iniciar automáticamente un reproductor multimedia compatible después de establecer una conexión:

ingrese la descripción de la imagen aquí

Stream2ip también intentará volver a conectar la transmisión de reproducción que se está ejecutando actualmente al dispositivo de audio Bluetooth en caso de que se interrumpiera la conexión.

Takkat
fuente
Gracias por tu respuesta. Estás sugiriendo que debería sondear sdptool browse <device-id>hasta que obtenga un código de retorno 0 y luego comenzar mi script, ¿verdad? ¿Hay alguna manera de hacerlo sin encuestas?
Erigami
Sdptool es lento. Yo iría por pulseaudio. Necesita un bucle porque no sabemos cuándo está su dispositivo allí.
Takkat
2

@Erigami Tu respuesta ayudó mucho, pero para que funcione, debo hacer algunos cambios. Estoy usando 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()

Aún así, si esto no funciona, utilice y controle el sistema dbus.

dbus-monitor --system

d-feetSe puede utilizar más. Es una herramienta GUI para ver objetos dbus.

Hitul
fuente
1
Si desea mejorar otra respuesta, sugiérale que la edite y no cree una nueva respuesta.
David Foerster
1

Aquí hay otro ejemplo para monitorear todos los dispositivos Bluetooth. No necesita especificar una dirección MAC específica. Este enfoque hace que la configuración de xinput sea persistente incluso cuando inicie sesión / salga, suspenda / active y conecte / desconecte su dispositivo bluetooth.

Tengo un teclado Bluetooth compacto Thinkpad, y deseo ejecutar un comando xinput siempre que el teclado esté conectado para ajustar la velocidad del trackpoint. Aquí están los pasos.

  1. Descargue el código de Github bluetooth-ruunner . Créditos otorgados aquí que primero escribieron esto para Raspberry Pi. Modifique la siguiente sección del código para ejecutar sus comandos personalizados.

    subprocess.call(['xinput', 'set-prop',
                     'ThinkPad Compact Bluetooth Keyboard with TrackPoint',
                     'Device Accel Constant Deceleration', '0.6'])

    En mi caso, esto es equivalente a llamar desde la terminal.

    $ xinput set-prop 'ThinkPad Compact Bluetooth Keyboard with TrackPoint' 'Device Accel Constant Deceleration' 0.6
  2. Guarda la modificación. Intenta ejecutar tus scripts por

    $ python bluetooth-runner.py

    Conecte y desconecte su dispositivo Bluethooth. Debería ver el mensaje correspondiente impreso en la pantalla.

  3. Ahora, haga que su archivo sea ejecutable y cópielo en uno de los directorios de su $PATH, digamos ~/bin/.

    $ chmod +x bluetooth-runner.py
    $ mkdir ~/bin # if you dont have it yet
    $ cp bluetooth-runner.py ~/bin
  4. Ahora, asegúrese de que puede ejecutar el script desde cualquier lugar del terminal (asegúrese de que esté en su ruta de búsqueda).

  5. Enciende el Startup Applicationsdesde el menú de ubuntu. Agregue sus scripts al inicio.

    Agregar aplicaciones de inicio

  6. Ahora, solo queda un problema, en el momento en que inicia sesión, los scripts podrían no detectar el primer evento de bluetooth. Esto se debe a que su dispositivo bluetooth podría estar conectado antes de que su script se inicialice en segundo plano.

    Para resolver esto, agregue su comando personalizado directamente en Startup Applications. En mi caso, es el siguiente comando:

     xinput set-prop 'ThinkPad Compact Bluetooth Keyboard with TrackPoint' 'Device Accel Constant Deceleration' 0.6

Y ahora podrá disfrutar de su dispositivo Bluetooth con Ubuntu.

Yixing
fuente
La secuencia de comandos de Python no supervisó las conexiones Bluetooth.
Paulo Pedroso
0

Usted escribe "cuando su auricular se conecta a su computadora". ¿Cómo hace eso, automáticamente? Cuando tenga que activarlo manualmente, también podría convertirlo en un script y luego ejecutar su script después de que se haya establecido la conexión. Esto es lo que hice para configurar el dispositivo de salida predeterminado en mi receptor bluetooth (para que pueda cambiar el volumen con las teclas de hardware):

bluetooth-connect && pactl set-default-sink bluez_sink.0C_A6_94_9A_37_4D

Donde se bluetooth-connectve así: https://github.com/sblask/dotfiles/blob/c39d37ad67947b358b4a079cb41ae6f9e4a081d8/.bin/bluetooth-connect.symlink Asume que todo se ha emparejado y está listo para conectarse. Puede encontrar la dirección MAC en blueman o ejecutándose pacmd list-sinks | grep -e 'name:' -e 'index'cuando el dispositivo bluetooth está conectado. Te gustaría correr bluetooth-connect && your-script. your-scriptsolo se ejecutará cuando la conexión se haya establecido correctamente.

Sebastian Blask
fuente