Bluetoothデバイスが接続されたときにスクリプトを実行するにはどうすればよいですか?


16

Bluetoothヘッドセットがコンピューターに接続したときに、音楽プレーヤー(Clementine)を起動したいです。Bluetoothデバイスの接続を検出して、プレーヤーを起動するスクリプトを実行するにはどうすればよいですか?

回答:


12

私はポーリングのアプローチが好きではなかったので、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()

もちろん、BluezとPulseAudioは、DBusのポーリングを通じて動作します。ヘッドセットがデフォルトのアダプターである限り、ほとんどの場合それは正常に機能します。何かを聞きたい場合は、必ずPulseAudioをヘッドセットに接続してください。ソリューションを共有していただきありがとうございます:)
Takkat

DEV_ID接続前のことを知っていれば素晴らしいことですが、すべての接続イベントを通知したい場合はどうでしょうか?
プスタントン

4

正常に確立された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

スクリプトの正確な目的はわかりませんが、ほとんどの場合、ヘッドセットが接続されているときにクレメンタイン経由でオーディオを再生したいと考えています。

その後、Bluetoothオーディオシンクが

pacmd list-sinks | grep xx_xx_xx_xx_xx_xx

xx_xx_xx_xx_xx_xxMACアドレスはどこにありますか(:で置き換える必要があります_)。出力には、使用可能なBluetoothオーディオシンクがあるかどうかが表示されます。

オーディオをこのシンクに切り替える方法については、この回答を参照してください。


Stream2ip

stream2ip我々は、シェルコマンドまたは接続が確立された後に実行するスクリプトを定義することができます。接続が確立された後に、サポートされているメディアプレーヤーを自動的に開始するオプションもあります。

ここに画像の説明を入力してください

Stream2ipは、接続が中断された場合に、現在実行中の再生ストリームをBluetoothオーディオデバイスに再接続しようとします。


ご回答有難うございます。sdptool browse <device-id>0のリターンコードを取得してからスクリプトを開始するまで、ポーリングする必要があることを提案していますか?ポーリングなしでそれを行う方法はありますか?
折り紙

Sdptoolは遅いです。pulseaudioに行きます。デバイスがいつ存在するかわからないため、ループが必要です。
Takkat

2

@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オブジェクトを監視するGUIツールです。


1
別の回答を改善したい場合は、編集を提案し、新しい回答を作成しないでください。
デビッドフォースター

1

すべてのBluetoothデバイスを監視する別の例を次に示します。特定のMACアドレスを指定する必要はありません。このアプローチにより、Bluetoothデバイスのログイン/アウト、サスペンド/ウェイク、および接続/切断時でもxinput設定が維持されます。

ThinkpadのコンパクトなBluetoothキーボードを使用しており、キーボードが接続されていてトラックポイントの速度を調整するたびにxinputコマンドを実行したい。手順は次のとおりです。

  1. 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
  2. 変更を保存します。スクリプトを実行してみてください

    $ python bluetooth-runner.py

    Bluethoothデバイスを接続および切断します。画面に対応するメッセージが印刷されます。

  3. 今、あなたのファイルを実行可能にしますし、あなたの中のディレクトリの一つにそれをコピーし$PATH、言います~/bin/

    $ chmod +x bluetooth-runner.py
    $ mkdir ~/bin # if you dont have it yet
    $ cp bluetooth-runner.py ~/bin
  4. ここで、端末のどこからでもスクリプトを実行できることを確認します(検索パスにあることを確認してください)。

  5. アップ火災Startup ApplicationsUbuntuのメニューから。スクリプトをスタートアップに追加します。

    スタートアップアプリケーションを追加する

  6. これで、ログイン時の問題が1つだけ残りました。スクリプトは、最初の bluetoothイベントをキャッチできません。これは、スクリプトがバックグラウンドで初期化される前に、Bluetoothデバイスが接続される可能性があるためです。

    これを解決するには、カスタムコマンドをに直接追加しますStartup Applications。私の場合、次のコマンドです。

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

これで、UbuntuでBluetoothデバイスを楽しむことができます。


Pythonスクリプトは、Bluetooth接続を監視しませんでした。
パウロ・ペドロソ

0

「ヘッドセットがコンピューターに接続するとき」と書きます。それはどうやって自動的に行われますか?手動でトリガーする必要がある場合は、それをスクリプトにして、接続が確立された後にスクリプトを実行することもできます。これは、デフォルトの出力デバイスを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-scriptyour-script接続が正常に確立されたときにのみ実行されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.