Bluetooth 장치가 연결될 때 스크립트를 실행하려면 어떻게합니까?


16

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연결 이전의 내용을 알고 있으면 좋습니다 .. 모든 연결 이벤트에 대한 알림을 받으려면 어떻게합니까?
pstanton

4

성공적으로 설정된 블루투스 연결을 발견하기 위해

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

스크립트의 정확한 목적을 모르지만 헤드셋이 연결되어있을 때 Clementine을 통해 오디오를 재생하려고합니다.

그런 다음 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이 느립니다. 펄스 오디오로갑니다. 우리는 당신의 장치가 언제 있는지 모르기 때문에 루프가 필요합니다.
Takkat

2

@Erigami 귀하의 답변은 많은 도움이되었지만 제대로 작동하려면 몇 가지 사항을 변경하겠습니다. 우분투 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
다른 답변을 개선하려면 수정을 제안하고 새 답변을 만들지 마십시오.
David Foerster

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 Applications우분투 메뉴에서. 시작에 스크립트를 추가하십시오.

    시작 응용 프로그램 추가

  6. 이제 로그인 할 때 하나의 문제 만 남았습니다. 스크립트는 첫 번째 Bluetooth 이벤트를 포착하지 못할 수 있습니다 . 스크립트가 백그라운드에서 초기화되기 전에 블루투스 장치가 연결되었을 수 있기 때문입니다.

    이 문제를 해결하려면에 사용자 정의 명령을 직접 추가하십시오 Startup Applications. 제 경우에는 다음과 같은 명령입니다.

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

이제 Ubuntu를 통해 Bluetooth 장치를 즐길 수 있습니다.


파이썬 스크립트가 블루투스 연결을 모니터링하지 않았습니다.
Paulo Pedroso

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-script입니다. your-script연결이 성공적으로 완료된 경우에만 실행됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.