Jak uruchomić skrypt, gdy łączy się urządzenie Bluetooth?

16

Chciałbym uruchomić odtwarzacz muzyki (Clementine), gdy zestaw słuchawkowy Bluetooth połączy się z komputerem. Jak wykryć połączenie urządzenia Bluetooth, aby uruchomić skrypt, aby uruchomić odtwarzacz?

Erigami
źródło

Odpowiedzi:

12

Nie podobało mi się podejście do głosowania, więc zacząłem kopać na bluez i DBus. Skończyło się na napisaniu następującego skryptu:

#!/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
źródło
Oczywiście Bluez i PulseAudio działają poprzez odpytywanie DBus. Jeśli zestaw słuchawkowy jest domyślnym adapterem, w większości przypadków będzie działał dobrze. Jeśli chcesz coś usłyszeć, podłącz również PulseAudio do zestawu słuchawkowego. Dziękujemy za podzielenie się swoim rozwiązaniem :)
Takkat
to świetnie, jeśli znasz DEV_IDwcześniej połączenie ... ale co, jeśli chcesz otrzymywać powiadomienia o wszystkich zdarzeniach związanych z połączeniem?
pstanton
4

Aby odkryć udane połączenie Bluetooth, możemy uruchomić

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

W ten sposób połączenie SDB zostanie przetestowane pod kątem połączenia z danym adresem MAC. Może minąć sporo czasu, zanim przeglądanie się skończy z takim błędem jak

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

Nie znamy dokładnego celu skryptu, ale najprawdopodobniej chcesz odtwarzać dźwięk za pośrednictwem Clementine, gdy podłączony jest zestaw słuchawkowy.

Wtedy moglibyśmy zobaczyć, czy jest zlew audio Bluetooth

pacmd list-sinks | grep xx_xx_xx_xx_xx_xx

Gdzie xx_xx_xx_xx_xx_xxjest adres MAC ( :należy go zastąpić _). Wyjście powie ci wtedy, czy dostępny jest zlew audio Bluetooth, czy nic, jeśli nie.

Zobacz odpowiedź na temat przełączania audio na ten zlew.


Stream2ip

Za pomocą stream2ip możemy zdefiniować polecenie powłoki lub skrypt, który będzie uruchamiany po ustanowieniu połączenia. Istnieje również opcja automatycznego uruchomienia obsługiwanego odtwarzacza multimedialnego po ustanowieniu połączenia:

wprowadź opis zdjęcia tutaj

Stream2ip spróbuje również ponownie połączyć aktualnie uruchomiony strumień odtwarzania z urządzeniem audio Bluetooth w przypadku przerwania połączenia.

Takkat
źródło
Dziękuję za odpowiedź. Sugerujesz, żebym powinien sondować, sdptool browse <device-id>dopóki nie otrzymam kodu powrotu 0, a następnie nie uruchomię skryptu, prawda? Czy można to zrobić bez odpytywania?
Erigami,
Sdptool jest wolny. Poszedłbym na pulseaudio. Potrzebujesz pętli, ponieważ nie wiemy, kiedy jest tam Twoje urządzenie.
Takkat
2

@Erigami Twoja odpowiedź bardzo pomogła, ale żeby to zadziałało, zrobię kilka zmian. Używam 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()

Jeśli jednak to nie zadziała, użyj i monitoruj system dbus systemu.

dbus-monitor --system

d-feetmożna dalej wykorzystywać. Jest to narzędzie GUI do oglądania obiektów dbus.

Hitul
źródło
1
Jeśli chcesz poprawić inną odpowiedź, zasugeruj jej zmianę i nie twórz nowej odpowiedzi.
David Foerster,
1

Oto kolejny przykład monitorowania wszystkich urządzeń Bluetooth. Nie musi określać określonego adresu MAC. Takie podejście sprawia, że ​​ustawienie xinput jest trwałe nawet po zalogowaniu / wylogowaniu, zawieszeniu / wybudzeniu i podłączeniu / odłączeniu urządzenia Bluetooth.

Mam kompaktową klawiaturę Bluetooth Thinkpad i chcę uruchamiać polecenie xinput za każdym razem, gdy klawiatura jest podłączona, aby dostosować prędkość punktu ścieżki. Oto kroki.

  1. Pobierz kod z Github bluetooth-ruunner . Podziękowania przyznane tutaj, który jako pierwszy napisał to dla Raspberry Pi. Zmodyfikuj następującą sekcję kodu, aby uruchomić niestandardowe komponenty.

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

    W moim przypadku jest to równoważne z telefonowaniem z terminala.

    $ xinput set-prop 'ThinkPad Compact Bluetooth Keyboard with TrackPoint' 'Device Accel Constant Deceleration' 0.6
  2. Zapisz modyfikację. Spróbuj uruchomić swoje skrypty

    $ python bluetooth-runner.py

    Podłącz i odłącz urządzenie Bluethooth. Powinien zostać wyświetlony odpowiedni komunikat wydrukowany na ekranie.

  3. Teraz uczyń swój plik wykonywalnym i skopiuj go do jednego z katalogów $PATH, powiedzmy, twojego ~/bin/.

    $ chmod +x bluetooth-runner.py
    $ mkdir ~/bin # if you dont have it yet
    $ cp bluetooth-runner.py ~/bin
  4. Teraz upewnij się, że możesz uruchomić skrypt z dowolnego miejsca w terminalu (upewnij się, że znajduje się on na ścieżce wyszukiwania).

  5. Odpal Startup Applicationsz menu ubuntu. Dodaj swoje skrypty do startu.

    Dodaj aplikacje startowe

  6. Teraz pozostaje tylko jeden problem, w momencie logowania skrypty mogą nie wychwycić pierwszego zdarzenia Bluetooth. Wynika to z faktu, że urządzenie Bluetooth mogło zostać podłączone przed zainicjowaniem skryptu w tle.

    Aby rozwiązać ten problem, dodaj swoje niestandardowe polecenie bezpośrednio w Startup Applications. W moim przypadku jest to następujące polecenie:

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

A teraz będziesz mógł cieszyć się urządzeniem Bluetooth z Ubuntu.

Yixing
źródło
skrypt Pythona nie monitorował połączeń Bluetooth.
Paulo Pedroso
0

Piszesz „kiedy zestaw słuchawkowy łączy się z komputerem”. Jak to robi automatycznie? Gdy musisz uruchomić go ręcznie, równie dobrze możesz ustawić go jako skrypt, a następnie uruchomić skrypt po ustanowieniu połączenia. Oto, co zrobiłem, aby ustawić domyślne urządzenie wyjściowe w moim odbiorniku Bluetooth (dzięki czemu mogę zmienić głośność za pomocą klawiszy sprzętowych):

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

Gdzie bluetooth-connectwygląda to tak: https://github.com/sblask/dotfiles/blob/c39d37ad67947b358b4a079cb41ae6f9e4a081d8/.bin/bluetooth-connect.symlink Zakłada, że ​​wszystko zostało sparowane i jest gotowe do połączenia. Adres MAC można znaleźć w blueman lub uruchamiając, pacmd list-sinks | grep -e 'name:' -e 'index'gdy urządzenie Bluetooth jest podłączone. Chciałbyś uciec bluetooth-connect && your-script. your-scriptbędzie uruchamiany tylko po pomyślnym nawiązaniu połączenia.

Sebastian Blask
źródło