Se connecter à un périphérique Bluetooth à partir de la ligne de commande

22

Contexte: j'utilise mon casque Bluetooth comme sortie audio. J'ai réussi à le faire fonctionner grâce à la longue liste d'instructions sur la documentation de la communauté BluetoothHeadset , et j'ai automatisé le processus d'activation du casque comme sortie audio par défaut dans un script, grâce à une autre question .

Cependant, étant donné que j'utilise le casque Bluetooth avec mon téléphone et mon ordinateur (et que le casque ne prend pas en charge deux connexions d'entrée) afin que le téléphone ne "vole" pas la connexion lorsque le combiné est allumé, je force le casque à mode découverte lors de la connexion à l'ordinateur (le téléphone peut s'y connecter automatiquement).

Donc, même si le casque est appairé correctement et se connecterait automatiquement dans un scénario "normal", je dois toujours utiliser la petite icône Bluetooth dans la zone de notification pour me connecter réellement à mon appareil (voir capture d'écran).

Ce que je veux éviter: Cette interface graphique pour la connexion à un appareil Bluetooth connu et couplé :

Connexion au casque Bluetooth à l'aide de l'icône

Ce que je veux à la place: je voudrais que le bluetooth fasse exactement ce que fait le clic sur l'élément de connexion dans l'interface graphique, uniquement en utilisant la ligne de commande. Je souhaite utiliser la ligne de commande pour pouvoir créer un seul raccourci clavier pour l'action et je n'aurais pas besoin de naviguer dans l'interface graphique à chaque fois que je souhaite établir une connexion avec l'appareil.

La question: comment puis-je tenter de me connecter à un périphérique Bluetooth spécifique, connu et couplé à partir de la ligne de commande?

Autre question: comment savoir si la connexion a réussi ou non?

Ilari Kajaste
la source
De quel outil de plateau s'agit-il? s'agit-il de l'icône de la barre Blueman Manager? L'applet Blueman Manager Tray doit-il répertorier les appareils Bluetooth couplés?
cipricus

Réponses:

10

Démon Bluetooth

Dans l'installation par défaut, un démon ( bluetoothd ) s'exécute en arrière-plan (exécuté à partir du fichier /etc/init.d/bluetooth). Ce démon prend soin de reconnaître et de se connecter aux périphériques Bluetooth connus et peut être configuré avec les fichiers de configuration dans /etc/bluetooth. Pour la connexion automatique d'un casque, la ligne suivante audio.confdoit être décommentée (supprimer #):

AutoConnect=true

Pour redémarrer le type de démon sudo /etc/init.d/bluetooth restart.

Remarque: L' utilisation de l'outil de ligne de commande sudo hcitool cc <MAC-Adress>n'a pas conduit à une connexion stable à un périphérique connu dans l'environnement de test ici lorsque le démon était en cours d'exécution.


DBus

Afin de connecter un casque déconnecté mais physiquement présent et couplé, nous pouvons utiliser D-Bus à partir d'un script. Voici un exemple en python:

#!/usr/bin/python
# Toggles headset connection

import dbus
from dbus.mainloop.glib import DBusGMainLoop

dbus_loop = DBusGMainLoop()
bus = dbus.SystemBus(mainloop=dbus_loop)

#Get dbus interface for headset
manager = bus.get_object('org.bluez', '/')
iface_m = dbus.Interface(manager, 'org.bluez.Manager')
adapterPath = iface_m.DefaultAdapter()
adapter = bus.get_object('org.bluez', adapterPath)
iface_a = dbus.Interface(adapter, 'org.bluez.Adapter')
devicePath = iface_a.ListDevices()[0]  # assuming first device
device = bus.get_object('org.bluez', devicePath)
iface_h = dbus.Interface(device, 'org.bluez.Headset')

#Check state of connection
connected = iface_h.IsConnected()
print 'Toggling connection. Please wait'
# toggle connection
if not connected:
    try:
        iface_h.Connect()
        print 'Connecting: ', devicePath
    except:
        print 'Device not found'
else:
    iface_h.Disconnect()
    print 'Disconnecting: ', devicePath

Dans le cas où nous avons plus d'un appareil Bluetooth, nous devrons devicePathbien sûr l'adapter de manière appropriée. L'exemple ci-dessus connectera a Headset. Modifiez l'interface avec un protocole différent pour tout autre service (par exemple AudioSink).


Pulseaudio

Si vous connaissez l'adresse MAC de votre appareil Bluetooth, vous pouvez le connecter en tant que récepteur de sortie pour pulseaudio en:

pacmd set-default-sink bluez_sink.xx_xx_xx_xx_xx_xx

Où xx_xx_xx_xx_xx_xx est l'adresse MAC (remplacez ':' par '_' pour que pulseaudio le reconnaisse).

Voir aussi cette réponse pour plus de détails.

Takkat
la source
Je connais l'adresse et j'ai remplacé le xx par celui-ci. Je ne suis Sink bluez_sink.xx_xx_xx_xx_xx_xx does not exist.essayé qu'en majuscules et en minuscules.
Ilari Kajaste
1
Oui, pulseaudio-module-bluetooth est isntalle. Non, rien ne correspond btou bluen'est répertorié dans pacmd list-sinks. (Il ne rapporte qu'un seul évier disponible.)
Ilari Kajaste
2
Ce n'est donc pas reconnu. C'est une condition préalable pour pouvoir se connecter par ligne de commande. Essayez de redémarrer BT ou essayez de redémarrer pulsaudio. Je n'ai pas encore découvert pourquoi il n'est parfois pas détecté.
Takkat
Hein? Il peut donc être dans un état où il est possible de se connecter à partir de l'interface graphique, mais pas à partir de la CLI?
Ilari Kajaste
1
@Takkat Oh, oui, bon point. Ma faute! J'utilise davantage le casque pour la découverte, donc il ne se connectera pas automatiquement. J'ai édité la question pour refléter cela. Désolé de vous avoir conduit sur un mauvais chemin.
Ilari Kajaste
6

J'utilise ce script pour connecter mon périphérique audio Bluetooth. Si votre casque est déjà couplé, vous devriez pouvoir connecter votre casque de la même manière en utilisant org.bluez.Headset.Connect / Disconnect à la place de org.bluez.Audiosink.Connect / Disconnect .

#!/bin/bash

MAC_ADD="C8:84:47:10:11:CD"

MAC_ADD="dev_${MAC_ADD//:/_}"
BT_ADAPTER=`dbus-send --system --print-reply --dest=org.bluez / \
org.bluez.Manager.DefaultAdapter|awk '/object path/ {print $3}'`

BT_ADAPTER="${BT_ADAPTER//\"/}/$MAC_ADD"
echo "Connecting to $BT_ADAPTER..."

if [ "$1" == "on" ]; then
    dbus-send --print-reply --system --dest=org.bluez $BT_ADAPTER org.bluez.AudioSink.Connect
elif [ "$1" == "off" ]; then
    dbus-send --print-reply --system --dest=org.bluez $BT_ADAPTER org.bluez.AudioSink.Disconnect
fi

HTH!

doublerebel
la source
cela a fonctionné pour moi aussi 16.04, merci! d'autres, n'oubliez pas de passer l' onoption au script!
MInner
2

J'utilise i3 comme gestionnaire de fenêtres, je n'ai donc pas l'icône de plateau Bluetooth disponible. Pour une raison quelconque, le bouton de vérification dans les paramètres d'unité n'est pas sensible et j'ai donc besoin d'un moyen de le faire de temps en temps lorsque mes écouteurs ne se connectent pas.

entrez la description de l'image ici

Il semble que cela bluezait changé leur API dbus . La réponse utilisant org.bluez.Managerne semble plus fonctionner. Au lieu de cela, il est recommandé d'utiliser ObjectManager.

Voici un script python mis à jour qui connectera le premier casque Bluetooth non connecté qu'il trouve (probablement la liste comprend tous les appareils couplés?):

#!/usr/bin/env python
# Toggles headset connection

from __future__ import print_function
from __future__ import unicode_literals

import dbus
from dbus.mainloop.glib import DBusGMainLoop

def find_headset(bus):
  manager = dbus.Interface(bus.get_object("org.bluez", "/"),
                           "org.freedesktop.DBus.ObjectManager")
  objects = manager.GetManagedObjects()

  for path, ifaces in objects.items():
    if ("org.bluez.Device1" in ifaces and
        "org.freedesktop.DBus.Properties" in ifaces):
      iprops = dbus.Interface(
          bus.get_object("org.bluez", path),
          "org.freedesktop.DBus.Properties")
      props = iprops.GetAll("org.bluez.Device1")
      # Looking for a headset. Could also match on other properties like
      # "Name". See bluez docs for whats available.
      if props.get("Class") == 0x240404:
        if props.get("Connected"):
          print("Found headset {} ({}) but it is already connected"
                .format(props.get("Name"), props.get("Address")))
          continue
        return path

dbus_loop = DBusGMainLoop()
bus = dbus.SystemBus(mainloop=dbus_loop)
hpath = find_headset(bus)

if hpath:
  adapter = dbus.Interface(
      bus.get_object("org.bluez", hpath), "org.bluez.Device1")
  adapter.Connect()

cet exemple, comme l'autre exemple sur ce fil, utilise le dbuspackage python. Sur Ubuntu 16.04, j'ai installé ceci via apt-get install python-dbus.

Si vous souhaitez correspondre à d'autres critères, ce document apparaît pour afficher une liste de propriétés pouvant être interrogées via dbus.

J'ai ce script enregistré dans ~/.local/bin/bt-connect-headsetlequel est sur mon PATHafin que je puisse l'exécuter à partir du lanceur i3. Rendez-le exécutable ( chmod +x bt-connect-headset) si vous prévoyez de l'utiliser comme commande.

Ce script n'a été testé que sur un Ubuntu 16.04 à jour au 28/09/2018.

cheshirekow
la source
1
Utilisé votre script sur Ubuntu 18.10. Merci!
Brombomb
1
Super, cela a fonctionné pour moi dans Linux Mint 19 Cinnamon. Cependant, j'ai utilisé une classe d'unité 2360344au lieu de 0x240404.
dom_watson
1
fonctionne comme tel dans Mint Xfce 19.2. Je suis sûr que cela fonctionne dans Xubuntu. - Et un script pour déconnecter le bluetooth?
cipricus
1
@cipricus C'est exact, et c'est déjà mentionné dans la réponse. Il y a un lien dans la réponse sur la façon de faire correspondre d'autres critères si vous avez besoin de quelque chose de plus avancé (comme faire correspondre un appareil d'un nom particulier). Ce lien comprend également une liste des méthodes disponibles sur cette interface. Pour me déconnecter, je suppose que c'est la Disconnect()méthode. Je ne l'ai pas essayé, mais c'est probablement une valeur sûre;).
cheshirekow
J'avais tort. Je pensais que cela ne dépassait jamais le premier de la liste des appareils couplés, mais c'est le cas. J'ai peut-être également manqué le fait que vous disiez first unconnected bluetooth headset : utilisera-t-il toujours le casque (s'il est alimenté) avant un autre appareil comme les haut-parleurs Bluetooth (peu importe la position dans la liste)? C'est ce qui se passe dans mon cas. - De plus, pour me déconnecter, je ne peux pas le faire en changeant simplement la dernière ligne en adapter.Disconnect().)
cipricus
1

Après avoir essayé certains des éléments ci-dessus (les scripts ne fonctionnaient pas pour moi), j'ai trouvé la solution suivante.

Découvrez d'abord l'adresse MAC de l'appareil auquel vous souhaitez vous connecter

bluetoothctl

ceci entrera dans un shell et listera tous les appareils disponibles avec leur adresse. ("quitter" pour quitter le shell et revenir à l'invite)

Connectez-vous ensuite au périphérique Bluetooth XX: XX: XX: XX: XX: XX:

echo -e 'connect XX:XX:XX:XX:XX:XX' | bluetoothctl

Déconnecter

echo -e 'disconnect XX:XX:XX:XX:XX:XX' | bluetoothctl

cherchait depuis un bon moment - rien ne semblait fonctionner, je me sentais tellement soulagé quand je l'ai découvert. Je pensais que d'autres voudraient aussi le savoir. :))

Joseph
la source
Pourriez-vous modifier votre réponse pour ajouter comment obtenir l'adresse de l'appareil, afin que la réponse soit plus complète?
user3140225
1
@ user3140225 vient de le faire.
Joseph
Je comprends ~$ bluetoothctl Agent registered [UE BOOM 2]#. Alors disconnect "UE BOOM 2" Device UE BOOM 2 not available.
cipricus
@cipricus @ user3140225 Pourriez-vous publier la sortie de bluetoothctl? Vous devez alimenter les commandes avec l'adresse MAC de l'appareil - qui est la combinaison de valeurs HEX au format XX: XX: XX: XX: XX: XX, où X est soit une lettre soit un chiffre.
Joseph
Je peux voir le MAC comme dit ici . Ensuite, en essayant echo -e 'connect CC:AF:78:AF:59:03' | bluetoothctlj'obtiens:Agent registered [bluetooth]# connect CC:AF:78:AF:59:03 Device CC:AF:78:AF:59:03 not available
cipricus