web-dev-qa-db-ja.com

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

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

15
Erigami

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

正常に確立された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_xxはMACアドレスです(:_に置き換える必要があります)。出力には、使用可能なBluetoothオーディオシンクがあるかどうかが表示されます。

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


Stream2ip

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

enter image description here

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

4
Takkat

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

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

  1. Github bluetooth-ruunner からコードをダウンロードします。 ここ Raspberry Piの最初の作成者に与えられたクレジット。 Modifyコードの次のセクションを変更して、カスタムコマンドを実行します。

    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. UbuntuメニューからStartup Applicationsを起動します。スクリプトをスタートアップに追加します。

    Add startup applications

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

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

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

これで、UbuntuでBluetoothデバイスを楽しむことができるようになります。

1
Yixing

@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
Hitul

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

0
Sebastian Blask