Conecte automáticamente un altavoz Bluetooth confiable

10

He seguido el siguiente tutorial ( http://mygeeks014.blogspot.nl/2015/01/audio-streaming-to-bluetooth-speaker.html ) para conectar un altavoz Bluetooth a mi Raspberry Pi. Todo funciona como se supone que debe hacerlo, pero el altavoz no se volverá a conectar automáticamente cuando Raspberry se reinicie o el altavoz se encienda / apague. En este momento vuelvo a conectar manualmente el altavoz a través de la interfaz gráfica de usuario de Raspbian, pero me pregunto si hay una solución simple para volver a conectar el altavoz a través de la CLI. Entonces podré escribir un CRON simple para volver a conectar el altavoz si aún no está conectado.

Den3243
fuente

Respuestas:

17

Aquí hay una explicación muy detallada:

Den3243

Aquí hay una solución de línea de comando:

Primero, escaneemos, emparejemos, confiemos en su dispositivo con "bluetoothctl". Para hacer eso, ejecute esto en la línea de comando, su terminal:

bluetoothctl -a

Debería obtener un símbolo del sistema diferente como:

[bluetooth]

Con su altavoz BT encendido, escriba esto:

scan on

En unos momentos, debería ver los dispositivos BT disponibles. Al lado del dispositivo estará su dirección MAC, como: 00: AA: 22: BB: 33. Ahora escriba esto:

info <your mac address>

Excluir los caracteres mayor y menor que. Lo que buscas es algún tipo de asociación previa con tu altavoz BT. Sabrá que hubo una asociación previa porque bluetoothctl mostrará información sobre su dispositivo BT. Parte de esta información será sobre el dispositivo emparejado y confiable. Esto es bueno.

Si bluetoothctl se queja de que no hay dispositivo, entonces debemos configurarlo en este momento. Para hacer eso, escriba esto:

pair <your mac address>

Debería ver un mensaje de éxito sobre el emparejamiento de su dispositivo con éxito. Ahora confiemos en nuestro nuevo dispositivo BT. Escribe esto:

trust <your mac address>

Nuevamente, debería ver un mensaje de éxito sobre la confianza. Déjame pre-advertirte. Su dispositivo BT podría conectarse y, de nuevo, no. No temas, no queremos que se conecte. Adelante, salgamos de "bluetoothctl". Para hacer eso, escriba:

quit

Ahora volverá a la línea de comandos. En una publicación anterior le sugerí que creara un directorio de scripts en su directorio de inicio. Si no lo has hecho, adelante y hazlo ahora. Escriba esto en el símbolo del sistema:

mkdir -p ~/scripts

Presione enter y ahora creemos nuestro script de autopair bash. Escribe esto:

nano ~/scripts/autopair

Ingrese este código en el script:

#!/bin/bash
bluetoothctl << EOF
connect [enter your MAC add]
EOF

Excluir los corchetes!

Ahora presione CTRL + x al mismo tiempo, y ahora presione Intro para guardar el script. Necesitamos hacerlo ejecutable. Para hacer eso, escriba esto:

chmod +x ~/scripts/autopair

Supongo que no utiliza altavoces analógicos externos conectados a la toma de 3,5 mm. Si esto es cierto, deshabilitemos alsa. Para hacer eso, editemos un archivo en el directorio / boot llamado config.txt. Para hacer eso, escriba esto en su terminal:

sudo nano /boot/config.txt

Avanza hasta el final del archivo y busca dos líneas que digan:

# Enable audio (loads snd_bcm2835)
dtparam=audio=on

Coloque un (signo de número #) delante de la línea que dice:

dtparam=audio=on

Para parecerse a:

#dtparam=audio=on

Presione CTRL + xy luego presione Entrar para guardar su archivo.

¿Asumo que tienes instalado pulseaudio? De lo contrario, ejecute este comando desde la línea de comando:

sudo apt-get update && sudo apt-get install pulseaudio -y

¡Esto te dará un componente muy importante para hacer que Bluetooth funcione! Ahora editemos nuestro archivo .bashrc en nuestro directorio de inicio. Escribe esto:

nano ~/.bashrc

Avanza hasta el final y agrega esta línea:

pulseaudio --start

Presione CTRL + xy ahora presione Entrar para guardar su archivo.

¡OKAY! Necesitamos entrar al mundo de Python. He escrito un programa Python que vigilará el dispositivo bluetooth. En resumen, activará la conexión entre RPi y su altavoz bluetooth, una vez que su altavoz bluetooth esté encendido. Y viceversa. Creemos un directorio llamado python en su directorio de inicio. Para hacerlo, escriba esto:

mkdir -p ~/python

Ahora creemos el archivo del programa python. Para hacer eso, escriba esto:

nano ~/python/on.py

Dentro de ese archivo, debemos copiar y pegar lo siguiente:

#!/usr/bin/python
#
# Monitor removal of bluetooth reciever
import os
import sys
import subprocess
import time

def blue_it():
    status = subprocess.call('ls /dev/input/event0 2>/dev/null', shell=True)
    while status == 0:
        print("Bluetooth UP")
        print(status)
        time.sleep(15)
        status = subprocess.call('ls /dev/input/event0 2>/dev/null', shell=True)
    else:
        waiting()

def waiting():
    subprocess.call('killall -9 pulseaudio', shell=True)
    time.sleep(3)
    subprocess.call('pulseaudio --start', shell=True)
    time.sleep(2)
    status = subprocess.call('ls /dev/input/event0 2>/dev/null', shell=True)  
    while status == 2:
        print("Bluetooth DOWN")
        print(status)
        subprocess.call('~/scripts/autopair', shell=True)
        time.sleep(15)
        status = subprocess.call('ls /dev/input/event0 2>/dev/null', shell=True)
    else:
        blue_it() 

blue_it()

Ahora presione CTRL + xy luego presione Entrar para guardar el archivo del programa Python. Ahora necesitamos hacer que este archivo sea ejecutable. Para hacer eso, escriba esto:

chmod +x ~/python/on.py

Finalmente, agreguemos esto a nuestro script .bashrc en nuestro directorio de inicio:

nano ~/.bashrc

Vaya al final del archivo y agregue estas dos líneas:

wait
~/python/on.py

Ahora presione CTRL + xy luego presione Entrar para guardar. Encienda su altavoz bluetooth y reinicie su Raspberry Pi.

¡Buena suerte!

-nitrolinux

Jason Woodruff
fuente
Gracias por tu comentario. También tengo que presionar el botón 'Sink Audio' en la interfaz de usuario, ¿hay alguna alternativa CLI para esto también?
Den3243
He actualizado mi respuesta original.
Jason Woodruff
1
¡Gracias por tu explicación muy detallada! Funciona de maravilla.
Den3243
Me alegro de que funcionó!
Jason Woodruff
¿No se bloqueará finalmente este script debido a la recursión infinita entre blue_it y esperar?
Kevin Chen
4

He encontrado que hay problemas actuales con pulseaudio5 especialmente cuando se trata de reproducción de audio a través de bluetooth. Como tal, propongo que en lugar de tener que depurarlos cuando vengan, simplemente use PulseAudio6 para lo que desee.

He creado un repositorio que automatizará todo lo que se encuentra debajo para que no tenga que hacer todo el trabajo de piernas, pero si todavía está dispuesto a hacerlo, continúe a continuación.

Repo: https://github.com/BaReinhard/a2dp_bluetooth

Proceso de instalación:

git clone https://github.com/bareinhard/a2dp_bluetooth
cd a2dp_bluetooth/a2dp_source
./configure

Espere hasta que finalice el proceso de instalación y reinicie. Al finalizar, deberá iniciar, vincular, confiar y conectar su dispositivo. Después del tiempo inicial, solo tendrá que encender el dispositivo.

Emparejamiento, confianza y conexión:

sudo bluetoothctl
[bluetooth]# power on
[bluetooth]# agent on
[bluetooth]# default-agent
[bluetooth]# scan on
[bluetooth]# pair XX:XX:XX:XX:XX
[bluetooth]# trust XX:XX:XX:XX:XX
[bluetooth]# connect XX:XX:XX:XX:XX
[bluetooth]# exit

-------------------- Tutorial completo: --------------------

Compilando PulseAudio 6

Agregue los siguientes archivos

/etc/init.d/pulseaudio

#!/bin/sh -e
### BEGIN INIT INFO
# Provides:          pulseaudio esound
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Should-Start:      udev network-manager
# Should-Stop:       udev network-manager
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start the PulseAudio sound server
# Description:       System mode startup script for
#                    the PulseAudio sound server.
### END INIT INFO

DAEMON=/usr/local/bin/pulseaudio
PIDDIR=/var/run/pulse
PIDFILE=$PIDDIR/pid
DAEMONUSER=pulse
PATH=/sbin:/bin:/usr/sbin:/usr/bin

test -x $DAEMON || exit 0

. /lib/lsb/init-functions

pulseaudio_start () {
        log_daemon_msg "Starting system PulseAudio Daemon"
        if [ ! -d $PIDDIR ]; then
                mkdir -p $PIDDIR
                chown $DAEMONUSER:$DAEMONUSER $PIDDIR
        fi
        start-stop-daemon -x $DAEMON -p $PIDFILE --start -- --system --disallow-exit --disallow-module-loading=0 --daemonize --log-target=syslog --high-priority
        status=$?
        if [ -e /var/run/pulse/.esd_auth ]; then
                chown pulse:pulse-access /var/run/pulse/.esd_auth
                chmod 640 /var/run/pulse/.esd_auth
        fi
        if [ -e /var/run/pulse/.pulse-cookie ]; then
                chown pulse:pulse-access /var/run/pulse/.pulse-cookie
                chmod 640 /var/run/pulse/.pulse-cookie
        fi
        log_end_msg ${status}
}

pulseaudio_stop () {
        log_daemon_msg "Stopping system PulseAudio Daemon"
        start-stop-daemon -p $PIDFILE --stop --retry 5 || echo -n "...which is not running"
        log_end_msg $?
}

case "$1" in
        start|stop)
                pulseaudio_${1}
                ;;
        restart|reload|force-reload)
                if [ -s $PIDFILE ] && kill -0 $(cat $PIDFILE) >/dev/null 2>&1; then
                        pulseaudio_stop
                        pulseaudio_start
                fi
                ;;
        force-stop)
                pulseaudio_stop
                killall pulseaudio || true
                sleep 2
                killall -9 pulseaudio || true
                ;;
        status)
                status_of_proc -p $PIDFILE "$DAEMON" "system-wide PulseAudio" && exit 0 || exit $?
                ;;
        *)
                echo "Usage: /etc/init.d/pulseaudio {start|stop|force-stop|restart|reload|force-reload|status}"
                exit 1
                ;;
esac

exit 0

/etc/init.d/bluetooth

#!/bin/sh -e
### BEGIN INIT INFO
# Provides:            bluetooth
# Required-Start:      $local_fs $syslog dbus
# Required-Stop:       $local_fs $syslog
# Default-Start:       2 3 4 5
# Default-Stop:        0 1 6
# Short-Description:   Starts bluetooth daemons
### END INIT INFO

. /lib/lsb/init-functions

DESC=bluetoothd
DAEMON=/usr/libexec/bluetooth/bluetoothd
#SSD_OPTIONS="--oknodo --quiet --exec $DAEMON --plugin=a2dp"
SSD_OPTIONS="--oknodo --quiet --exec $DAEMON" #Change to this if you want media control using DBus at the expense of volume control 
HCI=hci0

case "${1}" in
    start)
       log_daemon_msg "Starting Bluetooth daemon bluetoothd..."
       start-stop-daemon --start --background $SSD_OPTIONS
       log_progress_msg "${DAEMON}"

       hciconfig $HCI up > /dev/null 2>&1
       log_end_msg 0
       ;;

    stop)
        log_daemon_msg "Stopping Bluetooth daemon bluetoothd..."
        start-stop-daemon --stop $SSD_OPTIONS
        log_progress_msg "${DAEMON}"
        log_end_msg 0
       ;;

    restart)
       ${0} stop
       sleep 1
       ${0} start
       ;;

    status)
        status_of_proc "$DAEMON" "$DESC" && exit 0 || exit $?
       ;;

    *)
         echo "Usage: ${0} {start|stop|restart|status}"
         exit 1
       ;;
esac

exit 0

Habilitar nuevos servicios init.d y hacer ejecutable

sudo chmod +x /etc/init.d/bluetooth
sudo chmod +x /etc/init.d/pulseaudio
sudo update-rc.d bluetooth defaults
sudo update-rc.d pulseaudio defaults

Asegúrese de tener todos los módulos necesarios.

sudo apt-get install bluez pulseaudio-module-bluetooth python-dbus libtool intltool libsndfile-dev libcap-dev libjson0-dev libasound2-dev libavahi-client-dev libbluetooth-dev libglib2.0-dev libsamplerate0-dev libsbc-dev libspeexdsp-dev libssl-dev libtdb-dev libbluetooth-dev intltool autoconf autogen automake build-essential libasound2-dev libflac-dev libogg-dev libtool libvorbis-dev pkg-config python -y

Cambie al Directorio de inicio e instale json-c desde la fuente git (requerido para PA6)

cd ~
git clone https://github.com/json-c/json-c.git
cd json-c
./configure 
make
sudo make install

Cambie a Home Directory e instale libsndfile desde la fuente git

git clone git://github.com/erikd/libsndfile.git
cd libsndfile
./autogen.sh
./configure --enable-werror
make
sudo make install

Asegúrese de que Bluetooth está buscando ( sudo hciconfig hci0 piscanestá en desuso)

cat << EOT | sudo tee -a /etc/bluetooth/main.conf
[Policy]
AutoEnable=true
EOT

Navegue al directorio de inicio e instale PulseAudio 6 desde la fuente git

git clone --branch v6.0 https://github.com/pulseaudio/pulseaudio
cd pulseaudio
sudo ./bootstrap.sh
sudo make
sudo make install
sudo ldconfig

Asegúrese de que el pulso esté en todos los grupos necesarios.

sudo addgroup --system pulse
sudo adduser --system --ingroup pulse --home /var/run/pulse pulse
sudo addgroup --system pulse-access
sudo adduser pulse audio
sudo adduser root pulse-access
sudo adduser pulse lp

Actualice /etc/pulse/system.pay /etc/pulse/daemon.conftenga el siguiente aspecto:

/etc/pulse/system.pa

#!/usr/bin/pulseaudio -nF
#
# This file is part of PulseAudio.
#
# PulseAudio is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# PulseAudio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PulseAudio; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.

# This startup script is used only if PulseAudio is started in system
# mode.

### Automatically load driver modules depending on the hardware available
.ifexists module-udev-detect.so
 #load-module module-udev-detect
 load-module module-udev-detect tsched=0
.else
### Use the static hardware detection module (for systems that lack udev/hal support)
load-module module-detect
.endif

### Load several protocols
.ifexists module-esound-protocol-unix.so
load-module module-esound-protocol-unix
.endif
load-module module-native-protocol-unix

### Automatically restore the volume of streams and devices
load-module module-stream-restore
load-module module-device-restore

### Automatically restore the default sink/source when changed by the user
### during runtime
### NOTE: This should be loaded as early as possible so that subsequent modules
### that look up the default sink/source get the right value
load-module module-default-device-restore

### Automatically move streams to the default sink if the sink they are
### connected to dies, similar for sources
load-module module-rescue-streams

### Make sure we always have a sink around, even if it is a null sink.
load-module module-always-sink

### Automatically suspend sinks/sources that become idle for too long
load-module module-suspend-on-idle

### Enable positioned event sounds
load-module module-position-event-sounds

### Automatically load driver modules for Bluetooth hardware
.ifexists module-bluetooth-discover.so
    load-module module-bluetooth-discover
.endif
load-module module-bluetooth-policy
load-module module-switch-on-connect

/etc/pulse/daemon.conf

# This file is part of PulseAudio.
#
# PulseAudio is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# PulseAudio is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PulseAudio; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
# USA.

## Configuration file for the PulseAudio daemon. See pulse-daemon.conf(5) for
## more information. Default values are commented out.  Use either ; or # for
## commenting.

; daemonize = no
; fail = yes
; allow-module-loading = yes
; allow-exit = yes
; use-pid-file = yes
; system-instance = no
; local-server-type = user
; enable-shm = yes
; shm-size-bytes = 0 # setting this 0 will use the system-default, usually 64 MiB
; lock-memory = no
; cpu-limit = no

; high-priority = yes
; nice-level = -15

; realtime-scheduling = yes
; realtime-priority = 5

exit-idle-time = -1
; scache-idle-time = 20

; dl-search-path = (depends on architecture)

; load-default-script-file = yes
; default-script-file = /etc/pulse/default.pa

; log-target = auto
; log-level = notice
; log-meta = no
; log-time = no
; log-backtrace = 0

# resample-method defaults to  speex-float-1 on most architectures,
# speex-fixed-1 on ARM
; resample-method = speex-float-1
resample-method = ffmpeg
enable-remixing = no
enable-lfe-remixing = no

; flat-volumes = yes

; rlimit-fsize = -1
; rlimit-data = -1
; rlimit-stack = -1
; rlimit-core = -1
; rlimit-as = -1
; rlimit-rss = -1
; rlimit-nproc = -1
; rlimit-nofile = 256
; rlimit-memlock = -1
; rlimit-locks = -1
; rlimit-sigpending = -1
; rlimit-msgqueue = -1
; rlimit-nice = 31
; rlimit-rtprio = 9
; rlimit-rttime = 1000000

default-sample-format = s16le
default-sample-rate = 44100
;alternate-sample-rate = 48000
default-sample-channels = 2
; default-channel-map = front-left,front-right

default-fragments = 10
default-fragment-size-msec = 10

; enable-deferred-volume = yes
; deferred-volume-safety-margin-usec = 8000
; deferred-volume-extra-delay-usec = 0

Configurar la regla de udev

Edite /etc/udev/rules.d/99-com.rulesy agregue las siguientes dos líneas:

SUBSYSTEM=="input", GROUP="input", MODE="0660"
KERNEL=="input[0-9]*", RUN+="/usr/local/bin/bluez-udev"

Crear /usr/local/bin/bluez-udev

/ usr / local / bin / bluez-udev

#!/bin/bash
name=$(sed 's/\"//g' <<< $NAME)
#exit if not a BT address
if [[ ! $name =~ ^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$ ]]; then exit 0;  fi

bt_name=`grep Name /var/lib/bluetooth/*/$name/info | awk -F'=' '{print $2}'`

audio_sink=bluez_source.$(sed 's/:/_/g' <<< $name)

action=$(expr "$ACTION" : "\([a-zA-Z]\+\).*")
logger "Action: $action"
if [ "$action" = "add" ]; then
    logger "[$(basename $0)] Bluetooth device is being added [$name] - $bt_name"
    logger "[$(basename $0)] Patching $audio_source into ALSA sink #$audio_sink"
    #hciconfig hci0 noscan
    bluetoothctl << EOT
discoverable off
EOT
    # Grab Card Number
    PACARD=`pactl list cards | grep "Card #" | sed "s/Card #//"`

    # Grab Sink Input if it exists
    audio_source=`pactl pactl list sink-inputs | grep "Sink Input" | sed "s/Sink Input #//"`
    if [ $audio_source = "" ];then
        sleep 5
        audio_source=`pactl pactl list sink-inputs | grep "Sink Input" | sed "s/Sink Input #//"`

    fi
    pactl set-sink-volume $audio_sink 65537
    if [ $audio_source != "" ]; then
        pactl set-source-volume $audio_source 90%
    fi
    pactl set-card-profile $PACARD a2dp_sink


    pactl set-default-sink $audio_sink





    # loop back this source to the default sink
    handle=$(pactl load-module module-loopback source=$audio_source sink=$audio_sink)
    logger "[$(basename $0)] PulseAudio module-loopback returned handle [$handle]"
    logger "$bt_name"


fi

if [ "$action" = "remove" ]; then
    # Grab Sink Input if it exists
    audio_source=`pactl pactl list sink-inputs | grep "Sink Input" | sed "s/Sink Input #//"`
    if [ $audio_source = "" ];then
        sleep 5
        audio_source=`pactl pactl list sink-inputs | grep "Sink Input" | sed "s/Sink Input #//"`

    fi
    pactl set-sink-volume 0 65537
    if [ $audio_source = "" ]; then
#        pactl set-default-sink 0
        pactl set-source-volume $audio_source 90%
    else
        pactl move-sink-input $audio_source 0 
    fi

    logger "[$(basename $0)] Bluetooth device is being removed [$name] - $bt_name"
    #hciconfig hci0 pscan

    bluetoothctl << EOT
discoverable on
EOT

    # remove any loopback modules assigned to this source
    # only required for USB sound cards, which PulseAudio will not automatically remove
    for handle in $(pactl list short modules | grep module-loopback | grep source=$audio_source | cut -f 1); do
        logger "[$(basename $0)] Unloading module-loopback with handle [$handle]"
        pactl unload-module $handle
    done

    sleep 5
    amixer cset numid=3 80%
    amixer cset numid=3 80%
fi

Asegúrese de que bluez-udev sea ejecutable

sudo chmod +x /usr/local/bin/bluez-udev

Resumen

¿Qué se está haciendo aquí?

  • Crear servicios init.d para bluetooth y pulseaudio y habilitarlos
  • Instalación de dependencias para PulseAudio6
  • Compilar PulseAudio6 y agregar el usuario de pulso a los grupos necesarios (la mayoría ya se habrá hecho)
  • Configure daemon.conf y system.pa para cargar los módulos adecuados
  • Cree la regla udev, para ejecutar bluez-udev cada vez que se conecte un dispositivo. bluez-udev comprueba si el dispositivo es un dispositivo bluetooth, si lo es, intentará conectar el audio de reproducción actual al receptor del dispositivo bluetooth creado por pulseaudio. Al desconectar el bluetooth, la transmisión volverá al sumidero predeterminado o al sumidero 0. Ahí lo tiene, después de todo lo que debería tener ahora un dispositivo bluetooth conectado automáticamente, la regla bluez-udev conectará automáticamente la música que se está reproduciendo al nuevo dispositivo bluetooth conectado Por supuesto, si esto parece desalentador
Brett Reinhard
fuente
1

¿Has intentado crear un script Bash que use hcitool para conectarse?

#!/bin/bash
sudo hcitool cc [speaker Bluetooth address]


Agregue derechos ejecutables a ese archivo y luego agréguelo a cron (puede elegir en cualquier momento).

Esto funcionó para mí cuando intenté conectarme a un teclado Bluetooth. No estoy seguro de si funcionará para un orador (no estoy seguro si es un protocolo diferente). ¡Espero que esto ayude!

ALinuxLover
fuente
0

encontré esto aún mejor

sudo bluetoothctl <<EOF
power on
discoverable on
pairable on
agent NoInputNoOutput
default-agent 
EOF
Jochnickel
fuente