Collega automaticamente un altoparlante Bluetooth affidabile


10

Ho seguito il seguente tutorial ( http://mygeeks014.blogspot.nl/2015/01/audio-streaming-to-bluetooth-speaker.html ) per collegare un altoparlante Bluetooth al mio Raspberry Pi. Tutto funziona come dovrebbe, ma l'altoparlante non si riconnetterà automaticamente quando Raspberry viene riavviato o l'altoparlante viene acceso / spento. In questo momento ricollego manualmente l'altoparlante tramite la GUI di Raspbian, ma mi chiedo se esiste una soluzione semplice per ricollegare l'altoparlante tramite l'interfaccia della riga di comando. Sarò quindi in grado di scrivere un semplice CRON per ricollegare l'altoparlante se non è ancora collegato.

Risposte:


17

Ecco una spiegazione molto dettagliata:

Den3243

Ecco una soluzione da riga di comando:

Per prima cosa, scansioniamo, abbiniamo, fidiamo del tuo dispositivo con "bluetoothctl". Per fare ciò, eseguilo dalla riga di comando, il tuo terminale:

bluetoothctl -a

Dovresti ricevere un prompt dei comandi diverso come:

[bluetooth]

Con l'altoparlante BT acceso, digitare questo:

scan on

In pochi istanti, dovresti vedere i dispositivi BT disponibili. Accanto al dispositivo ci sarà l'indirizzo MAC, come: 00: AA: 22: BB: 33. Ora digita questo:

info <your mac address>

Escludere il maggiore di e minore di caratteri. Quello che stai cercando è una sorta di associazione precedente con il tuo altoparlante BT. Saprai che c'era un'associazione precedente perché bluetoothctl mostrerà informazioni sul tuo dispositivo BT. Alcune di queste informazioni riguarderanno il dispositivo associato e attendibile. Questo è buono.

Se bluetoothctl si lamenta della mancanza di un dispositivo, è necessario configurarlo in questo momento. Per farlo, digita questo:

pair <your mac address>

Dovresti visualizzare un messaggio di successo sull'associazione del tuo dispositivo correttamente. Ora fidiamoci del nostro nuovo dispositivo BT. Digita questo:

trust <your mac address>

Ancora una volta, dovresti vedere un messaggio di successo sulla fiducia. Lascia che ti avverta. Il dispositivo BT potrebbe connettersi, quindi potrebbe non esserlo. Non temere, non vogliamo che si connetta. Vai avanti e usciamo da "bluetoothctl". Per farlo, digita:

quit

Ora verrai riportato al prompt della riga di comando. In un post precedente ti avevo suggerito di creare una directory di script nella tua home directory. Se non l'hai fatto, vai avanti e fallo ora. Digita questo al prompt dei comandi:

mkdir -p ~/scripts

Premi Invio e ora creiamo il nostro script bash autopair. Digita questo:

nano ~/scripts/autopair

Inserisci questo codice nello script:

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

Escludi le parentesi!

Ora premi CTRL + x contemporaneamente e ora premi invio per salvare lo script. Dobbiamo renderlo eseguibile. Per farlo, digita questo:

chmod +x ~/scripts/autopair

Suppongo che non si usi la spina per altoparlanti analogici esterni nella presa da 3,5 mm. Se questo è vero, disabilitiamo alsa. Per fare ciò, modifichiamo un file nella directory / boot chiamato config.txt. Per farlo, digita questo nel tuo terminale:

sudo nano /boot/config.txt

Scorri la pagina fino alla fine del file e cerca due righe che leggano:

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

Metti un (cancelletto #) davanti alla linea che dice:

dtparam=audio=on

Per assomigliare a:

#dtparam=audio=on

Premere CTRL + x, quindi premere Invio per salvare il file.

Suppongo che abbiate installato pulseaudio? In caso contrario, vai avanti ed esegui questo comando dalla riga di comando:

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

Questo ti darà un componente molto importante per far funzionare il bluetooth! Ora modificiamo il nostro file .bashrc nella nostra home directory. Digita questo:

nano ~/.bashrc

Pagina in basso e aggiungi questa riga:

pulseaudio --start

Premi CTRL + x e ora premi Invio per salvare il tuo file.

OK! Dobbiamo entrare nel mondo Python. Ho scritto un programma Python che controllerà il dispositivo bluetooth. In breve, attiverà la connessione tra RPi e l'altoparlante bluetooth, una volta acceso l'altoparlante bluetooth. E viceversa. Creiamo una directory chiamata python nella tua home directory Per farlo, digita questo:

mkdir -p ~/python

Ora creiamo il file di programma python. Per farlo, digita questo:

nano ~/python/on.py

All'interno di quel file, dobbiamo copiare e incollare quanto segue:

#!/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()

Ora premi CTRL + x e quindi premi Invio per salvare il file di programma Python. Ora dobbiamo rendere eseguibile questo file. Per farlo, digita questo:

chmod +x ~/python/on.py

Infine, aggiungiamo questo al nostro script .bashrc nella nostra directory home:

nano ~/.bashrc

Scorri la pagina fino alla fine del file e aggiungi queste due righe:

wait
~/python/on.py

Ora premi CTRL + x, quindi premi Invio per salvare. Accendi l'altoparlante bluetooth e riavvia Raspberry Pi.

In bocca al lupo!

-nitrolinux


Grazie per il tuo commento. Devo anche premere il pulsante "Sink Audio" nell'interfaccia utente, esiste un'alternativa alla CLI anche per questo?
Den3243,

Ho aggiornato la mia risposta originale.
Jason Woodruff,

1
Grazie per la tua spiegazione molto dettagliata! Funziona come un fascino.
Den3243,

Sono contento che abbia funzionato!
Jason Woodruff,

questo script alla fine non andrà in crash a causa della ricorsione infinita tra blue_it e in attesa?
Kevin Chen il

4

Ho scoperto che ci sono problemi attuali con pulseaudio5 soprattutto quando si tratta di riproduzione audio tramite bluetooth. In quanto tale, propongo che invece di dover eseguire il debug di quelli quando arrivano semplicemente usi PulseAudio6 per quello che vuoi.

Ho creato un repository che automatizzerà tutto ciò che segue, quindi non è necessario eseguire tutto il lavoro delle gambe, ma se hai ancora intenzione di farlo da solo, continua sotto.

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

Processo di installazione:

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

Attendere il completamento del processo di installazione e riavviare. Al termine dovrai associare, accoppiare, fidare e connettere il dispositivo in modo iniziale. Dopo il tempo iniziale dovrai solo accendere il dispositivo.

Associazione, fiducia e connessione:

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

-------------------- Soluzione completa: --------------------

Compiling PulseAudio 6

Aggiungi i seguenti file

/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

Abilitare i nuovi servizi init.d e renderlo eseguibile

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

Assicurati di avere tutti i moduli necessari

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

Passa alla directory principale e installa json-c dal sorgente git (richiesto per PA6)

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

Passa alla directory principale e installa libsndfile dal sorgente git

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

Assicurati che il Bluetooth stia effettuando una ricerca ( sudo hciconfig hci0 piscansia obsoleto)

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

Passare alla directory principale e installare PulseAudio 6 dalla sorgente git

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

Assicurarsi che il polso sia in tutti i gruppi necessari

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

Aggiorna /etc/pulse/system.pae /etc/pulse/daemon.confguarda come segue:

/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

Imposta la regola udev

Modifica /etc/udev/rules.d/99-com.rulese aggiungi le seguenti due righe:

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

Creare /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

Assicurarsi che bluez-udev sia eseguibile

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

Sommario

Cosa si fa qui?

  • Creare servizi init.d per bluetooth e pulseaudio e abilitarli
  • Installazione delle dipendenze per PulseAudio6
  • Compilazione di PulseAudio6 e aggiunta dell'utente di impulsi ai gruppi necessari (la maggior parte sarà già stata eseguita)
  • Installa daemon.conf e system.pa per caricare i moduli corretti
  • Crea regola udev, per eseguire bluez-udev ogni volta che un dispositivo è connesso. bluez-udev verifica se il dispositivo è un dispositivo bluetooth, in tal caso proverà a connettere l'audio in riproduzione corrente al sink del dispositivo bluetooth creato da pulseaudio. Dopo la disconnessione bluetooth, lo stream tornerà al sink predefinito o al sink 0. Ecco fatto, dopo tutto quello che dovresti avere ora un dispositivo bluetooth collegato automaticamente, la regola bluez-udev collegherà automaticamente la musica in riproduzione al nuovo dispositivo bluetooth collegato. Certo, se questo sembra scoraggiante

1

Hai provato a creare uno script Bash che utilizza hcitool per connettersi?

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


Aggiungi i diritti eseguibili a quel file, quindi aggiungilo a cron (puoi scegliere in qualsiasi momento).

Questo ha funzionato per me quando ho provato a connettermi a una tastiera Bluetooth. Non sono sicuro che funzionerà per un oratore (non sono sicuro se si tratta di un protocollo diverso). Spero che sia di aiuto!


0

trovato questo ancora meglio

sudo bluetoothctl <<EOF
power on
discoverable on
pairable on
agent NoInputNoOutput
default-agent 
EOF
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.