Wie führe ich ein Skript aus, wenn sich ein Bluetooth-Gerät verbindet?

16

Ich möchte meinen Musik-Player (Clementine) starten, wenn sich mein Bluetooth-Headset mit meinem Computer verbindet. Wie erkenne ich, dass das Bluetooth-Gerät eine Verbindung herstellt, damit ich ein Skript ausführen kann, um den Player zu starten?

Erigami
quelle

Antworten:

12

Ich mochte den Umfrageansatz nicht und grub ein bisschen in Bluez und DBus. Am Ende habe ich folgendes Skript geschrieben:

#!/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
quelle
Natürlich arbeiten Bluez und PulseAudio mit Polling-DBus. Solange Ihr Headset der Standardadapter ist, funktioniert dies in den meisten Fällen einwandfrei. Stellen Sie sicher, dass Sie PulseAudio auch an das Headset anschließen, wenn Sie etwas hören möchten. Vielen Dank für die Freigabe Ihrer Lösung :)
Takkat
Das ist großartig, wenn Sie DEV_IDvor der Verbindung Bescheid wissen . Aber was ist, wenn Sie über alle Verbindungsereignisse informiert werden möchten?
pstanton
4

Um eine erfolgreich eingerichtete Bluetooth-Verbindung zu finden, können wir ausführen

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

Dadurch wird die SDB-Verbindung auf eine Verbindung zu der angegebenen MAC-Adresse getestet. Es kann einige Zeit dauern, bis das Browsen mit einem Fehler wie z. B. abläuft

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

Wir kennen den genauen Zweck Ihres Skripts nicht, aber höchstwahrscheinlich möchten Sie Audio über Clementine wiedergeben, wenn ein Headset angeschlossen wurde.

Dann könnten wir nur sehen, ob es eine Bluetooth-Audio-Senke mit gibt

pacmd list-sinks | grep xx_xx_xx_xx_xx_xx

Wo xx_xx_xx_xx_xx_xxist die MAC-Adresse ( :muss durch ersetzt werden _). Der Ausgang zeigt Ihnen dann an, ob eine Bluetooth-Audio-Senke verfügbar ist oder nichts, wenn dies nicht der Fall ist.

In dieser Antwort erfahren Sie, wie Sie Audio auf diese Senke umschalten.


Stream2ip

Mit stream2ip können wir einen Shell-Befehl oder ein Skript definieren, das ausgeführt wird, nachdem eine Verbindung hergestellt wurde. Es gibt auch eine Option, um einen unterstützten Media Player automatisch zu starten, nachdem eine Verbindung hergestellt wurde:

Bildbeschreibung hier eingeben

Stream2ip versucht außerdem, den aktuell ausgeführten Wiedergabestream erneut mit dem Bluetooth-Audiogerät zu verbinden, falls die Verbindung unterbrochen wurde.

Takkat
quelle
Danke für deine Antwort. Sie schlagen vor, dass ich mit abfragen soll, sdptool browse <device-id>bis ich einen Rückkehrcode 0 erhalte und dann mein Skript starte, oder? Gibt es eine Möglichkeit, dies ohne Umfragen zu tun?
Erigami
Sdptool ist langsam. Ich würde für Pulseaudio gehen. Sie benötigen eine Schleife, da wir nicht wissen, wann Ihr Gerät dort ist.
Takkat
2

@Erigami Deine Antwort hat mir sehr geholfen, aber damit es funktioniert, müsste ich ein paar Änderungen vornehmen. Ich benutze 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()

Wenn dies immer noch nicht funktioniert, verwenden und überwachen Sie den System-Dbus.

dbus-monitor --system

d-feetkann weiter verwendet werden. Es ist ein GUI-Tool zum Beobachten von Dbus-Objekten.

Hitul
quelle
1
Wenn Sie eine andere Antwort verbessern möchten, schlagen Sie bitte eine Änderung vor und erstellen Sie keine neue Antwort.
David Foerster
1

Hier ist ein weiteres Beispiel für die Überwachung aller Bluetooth-Geräte. Es muss keine bestimmte MAC-Adresse angegeben werden. Dieser Ansatz sorgt dafür, dass die Einstellung für den X-Eingang auch dann erhalten bleibt, wenn Sie sich an- oder abmelden, aussetzen / aufwecken und Ihr Bluetooth-Gerät verbinden / trennen.

Ich habe eine Thinkpad-Bluetooth-Kompakttastatur und möchte jedes Mal, wenn die Tastatur angeschlossen ist, einen Befehl xinput ausführen, um die Geschwindigkeit des Trackpoints anzupassen. Hier sind die Schritte.

  1. Laden Sie den Code von Github bluetooth-ruunner herunter . Danksagung an diejenigen , die dies zum ersten Mal für Raspberry Pi geschrieben haben. Ändern Sie den folgenden Abschnitt des Codes, um Ihre benutzerdefinierten Befehle auszuführen.

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

    In meinem Fall entspricht dies einem Anruf vom Terminal.

    $ xinput set-prop 'ThinkPad Compact Bluetooth Keyboard with TrackPoint' 'Device Accel Constant Deceleration' 0.6
  2. Speichern Sie die Änderung. Versuchen Sie, Ihre Skripte nach auszuführen

    $ python bluetooth-runner.py

    Verbinden und trennen Sie Ihr Bluethooth-Gerät. Sie sollten die entsprechende Meldung auf dem Bildschirm sehen.

  3. Nun machen Sie Ihre Datei ausführbar und kopieren Sie sie in einem Verzeichnis in Ihrem $PATHsagen ~/bin/.

    $ chmod +x bluetooth-runner.py
    $ mkdir ~/bin # if you dont have it yet
    $ cp bluetooth-runner.py ~/bin
  4. Stellen Sie nun sicher, dass Sie das Skript von einer beliebigen Stelle im Terminal ausführen können (stellen Sie sicher, dass es sich in Ihrem Suchpfad befindet).

  5. Starten Sie die Startup Applicationsaus dem Ubuntu-Menü. Fügen Sie dem Start Ihre Skripte hinzu.

    Fügen Sie Startanwendungen hinzu

  6. Jetzt gibt es nur noch ein Problem. Wenn Sie sich anmelden, fangen die Skripte möglicherweise nicht das erste Bluetooth-Ereignis ab. Dies liegt daran, dass Ihr Bluetooth-Gerät möglicherweise verbunden ist, bevor Ihr Skript im Hintergrund initialisiert wird.

    Um dies zu lösen, fügen Sie Ihren benutzerdefinierten Befehl direkt in ein Startup Applications. In meinem Fall ist es der folgende Befehl:

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

Und jetzt können Sie Ihr Bluetooth-Gerät mit Ubuntu genießen.

Yixing
quelle
Python-Skript hat keine Bluetooth-Verbindungen überwacht.
Paulo Pedroso
0

Sie schreiben "Wenn Ihr Headset mit Ihrem Computer verbunden ist". Wie macht es das automatisch? Wenn Sie es manuell auslösen müssen, können Sie es auch zu einem Skript machen und dann das Skript ausführen, nachdem die Verbindung hergestellt wurde. So habe ich das Standardausgabegerät für meinen Bluetooth-Empfänger festgelegt (damit ich die Lautstärke mit den Hardwaretasten ändern kann):

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

Wo bluetooth-connectsieht das so aus: https://github.com/sblask/dotfiles/blob/c39d37ad67947b358b4a079cb41ae6f9e4a081d8/.bin/bluetooth-connect.symlink Es wird vorausgesetzt, dass alles gepaart und bereit ist, eine Verbindung herzustellen. Sie finden die MAC-Adresse in blueman oder indem Sie ausführen, pacmd list-sinks | grep -e 'name:' -e 'index'wenn das Bluetooth-Gerät verbunden ist. Du würdest laufen wollen bluetooth-connect && your-script. your-scriptwird nur ausgeführt, wenn die Verbindung erfolgreich hergestellt wurde.

Sebastian Blask
quelle