Como executo um script quando um dispositivo Bluetooth se conecta?

16

Gostaria de iniciar o meu music player (Clementine) quando meu fone de ouvido bluetooth se conectar ao meu computador. Como detecto a conexão do dispositivo bluetooth para executar um script para iniciar o player?

Erigami
fonte

Respostas:

12

Eu não gostei da abordagem de votação, então eu pesquisei no bluez e no DBus. Acabei escrevendo o seguinte 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
fonte
É claro que o Bluez e o PulseAudio operam através do DBus de pesquisa. Desde que o fone de ouvido seja o adaptador padrão, isso funcionará bem na maioria dos casos. Certifique-se de conectar também o PulseAudio ao fone de ouvido, se quiser ouvir algo. Obrigado por compartilhar sua solução :)
Takkat 22/12/12
isso é ótimo se você souber o DEV_IDantes da conexão .. mas e se você quiser ser notificado de todos os eventos de conexão?
pstanton
4

Para descobrir uma conexão Bluetooth estabelecida com sucesso, podemos executar

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

Por isso, a conexão SDB será testada para uma conexão com o endereço MAC fornecido. Pode levar um tempo considerável até que a navegação atinja o tempo limite com um erro como

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

Não sabemos o objetivo exato do seu script, mas é mais provável que você deseje reproduzir áudio via Clementine quando um fone de ouvido foi conectado.

Então pudemos ver se existe um coletor de áudio Bluetooth com

pacmd list-sinks | grep xx_xx_xx_xx_xx_xx

Onde xx_xx_xx_xx_xx_xxestá o endereço MAC ( :precisa ser substituído por _). A saída informará se há um coletor de áudio Bluetooth disponível ou nada, se não houver.

Veja esta resposta sobre como mudar o áudio para este coletor.


Stream2ip

Com o stream2ip , podemos definir um comando do shell ou um script a ser executado após o estabelecimento de uma conexão. Também existe uma opção para iniciar automaticamente um media player suportado após o estabelecimento de uma conexão:

insira a descrição da imagem aqui

O Stream2ip também tentará reconectar o fluxo de reprodução atualmente em execução ao dispositivo de áudio Bluetooth, caso a conexão seja interrompida.

Takkat
fonte
Obrigado pela sua resposta. Você está sugerindo que eu sdptool browse <device-id>faça uma pesquisa até obter um código de retorno 0 e, em seguida, iniciar meu script, certo? Existe uma maneira de fazer isso sem pesquisar?
Erigami 17/05
Sdptool está lento. Eu iria para o pulseaudio. Você precisa de um loop, porque não sabemos quando o seu dispositivo está lá.
Takkat 17/05/12
2

@Erigami Sua resposta ajudou muito, mas para fazê-lo funcionar, eu faria algumas alterações. Estou usando o 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()

Ainda assim, se isso não funcionar, use e monitore o dbus do sistema.

dbus-monitor --system

d-feetpode ser usado ainda mais. É uma ferramenta GUI para assistir objetos dbus.

Hitul
fonte
11
Se você deseja melhorar outra resposta, sugira uma edição e não crie uma nova resposta.
David Foerster
1

Aqui está outro exemplo para monitorar todos os dispositivos Bluetooth. Não é necessário especificar um endereço MAC específico. Essa abordagem torna a configuração xinput persistente, mesmo quando o login / saída, suspensão / ativação e conectar / desconectar o seu dispositivo bluetooth.

Eu tenho um teclado Bluetooth compacto Thinkpad e desejo executar um comando xinput sempre que o teclado estiver conectado para ajustar a velocidade do trackpoint. Aqui estão os passos.

  1. Faça o download do código do bluetooth-ruunner do Github . Créditos concedidos aqui, quem primeiro escreveu isso para o Raspberry Pi. Modifique a seção a seguir do código para executar seus comamnds personalizados.

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

    No meu caso, isso equivale a ligar do terminal.

    $ xinput set-prop 'ThinkPad Compact Bluetooth Keyboard with TrackPoint' 'Device Accel Constant Deceleration' 0.6
  2. Salve a modificação. Tente executar seus scripts

    $ python bluetooth-runner.py

    Conecte e desconecte seu dispositivo Bluethooth. Você deve ver a mensagem correspondente impressa na tela.

  3. Agora, torne seu arquivo executável e copie-o em um dos diretórios do seu $PATH, digamos ~/bin/.

    $ chmod +x bluetooth-runner.py
    $ mkdir ~/bin # if you dont have it yet
    $ cp bluetooth-runner.py ~/bin
  4. Agora, certifique-se de executar o script de qualquer lugar do terminal (verifique se ele está no seu caminho de pesquisa).

  5. Inicie Startup Applicationso menu ubuntu. Adicione seus scripts à inicialização.

    Adicionar aplicativos de inicialização

  6. Agora, resta apenas um problema: no momento em que você faz o login, os scripts podem não capturar o primeiro evento do bluetooth. Isso ocorre porque o dispositivo bluetooth pode estar conectado antes que o script seja inicializado em segundo plano.

    Para resolver isso, adicione seu comando personalizado diretamente no Startup Applications. No meu caso, é o seguinte comando:

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

E agora você poderá desfrutar do seu dispositivo Bluetooth com o Ubuntu.

Yixing
fonte
O script python não monitora as conexões bluetooth.
Paulo Pedroso
0

Você escreve "quando o fone de ouvido se conecta ao seu computador". Como isso é feito automaticamente? Quando você precisar acioná-lo manualmente, poderá transformá-lo em um script e, em seguida, executá-lo depois que a conexão for estabelecida. Foi o que fiz para definir o dispositivo de saída padrão para o meu receptor bluetooth (para que eu possa alterar o volume com as teclas de hardware):

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

Onde bluetooth-connectfica assim: https://github.com/sblask/dotfiles/blob/c39d37ad67947b358b4a079cb41ae6f9e4a081d8/.bin/bluetooth-connect.symlink Supõe que tudo foi emparelhado e está pronto para conexão. Você encontra o endereço MAC no blueman ou executando pacmd list-sinks | grep -e 'name:' -e 'index'quando o dispositivo bluetooth está conectado. Você gostaria de correr bluetooth-connect && your-script. your-scriptsó será executado quando a conexão foi estabelecida com sucesso.

Sebastian Blask
fonte