Un petit montage amusant né d’un question simple : comment est-ce que l’appairage d’une enceinte NFC fonctionne ? La réponse l’est assez (simple) : la puce NFC contient l’adresse MAC (aucun rapport avec Apple) de l’enceinte Bluetooth et un petit bout de code qui prévient le smartphone qu’il faut se connecter à l’enceinte. J’ai donc essayé de me programmer ma propre enceinte Bluetooth, avec un Raspberry Pi.
Qu’est-ce qu’il faut ?
Pour la partie enceinte, un Raspberry Pi (modèle B 256 Mo, ici), un adaptateur Bluetooth USB (j’en avais un qui traînait) et des enceintes. ici, j’ai testé avec la (mauvaise) sortie jack du Raspberry Pi mais on peut forcer la sortie HDMI ou une carte son USB.
Pour la partie NFC, il faut un tag NFC (j’ai utilisé des NTAG203) et un smartphone Android compatible NFC pour programmer le tag.
Comment ça marche
C’est assez simple : si vous passez le smartphone — Android, BlackBerry, Windows Phone, Symbian, tout sauf l’iPhone — sur le tag, il va normalement se connecter à l’enceinte. Attention au type de tag NFC : les téléphones récents veulent du NTAG203 (« compatible Galaxy S 4 »), donc n’essayer pas de tester — comme moi — avec un vieux MiFare. Si votre tag est incompatible (ça arrive), les résultats varient d’une erreur (BlackBerry), un bruit mais pas de réaction (Nexus 4) à « Ce tag n’est pas pris en charge » (Galaxy Zoom).
Côté Raspberry Pi
Le tuto provient en partie de là, avec quelques modifications. Attention, le fonctionnement reste assez aléatoire, sur trois installations, une n’a jamais accepté de fonctionner. Et bien évidemment, on est sur le codec de base en Bluetooth, le SBC, l’AptX n’est pas supporté (il nécessite une licence), ni l’AAC.
On installe les dépendances
sudo apt-get install bluez pulseaudio-module-bluetooth python-gobject python-gobject-2 bluez-tools
On adapte pulse audio.
sudo usermod -a -G lp pi
On modifie un fichier.
sudo nano /etc/bluetooth/audio.conf
Et on ajoute la ligne Enable=Source,Sink,Gateway,Socket,Media
sous [General]
.
On modifie un fichier.
sudo nano /etc/bluetooth/main.conf
Donner un nom à votre appareil, après Name=
, et ajouter la classe de l’appareil (Class = 0x20041C
).
Récupérez l’adresse MAC de votre adaptateur.
hcitool dev
Allez modifiez une fichier.
sudo nano /var/lib/bluetooth/adress:MAC/config
Modifiez le nom et la classe dans le fichier (0x20041C).
On modifie un fichier.
sudo nano /etc/pulse/daemon.conf
Sous les lignes qui commencent par resample
, ajouter la ligne suivante.
resample-method = trivial
Créer le script suivant.
sudo nano /etc/udev/rules.d/99-input.rules
Dans le fichier, ajoutez la ligne suivante.
KERNEL=="input[0-9]*", RUN+="/usr/lib/udev/bluetooth"
On crée un script.
sudo mkdir /usr/lib/udev
sudo nano /usr/lib/udev/bluetooth
Avec le contenu suivant.
#!/bin/sh
#change if you don't use default audio out
AUDIOSINK="alsa_output.platform-bcm2835_AUD0.0.analog-stereo"
echo "Executing bluetooth script...|$ACTION|" >> /var/log/bluetooth_dev
ACTION=$(expr "$ACTION" : "\([a-zA-Z]\+\).*")
if [ "$ACTION" = "add" ]
then
for dev in $(find /sys/devices/virtual/input/ -name input*)
do
if [ -f "$dev/name" ]
then
mac=$(cat "$dev/name" | sed 's/:/_/g')
bluez_dev=bluez_source.$mac
sleep 1
CONFIRM='sudo -u pi pactl list short | grep $bluez_dev'
if [ ! -z "$CONFIRM" ]
then
echo "Setting bluez_source to: $bluez_dev" >> /var/log/bluetooth_dev
echo pactl load-module module-loopback source=$bluez_dev sink=$AUDIOSINK rate=44100 adjust_time=0 >> /var/log/bluetooth_dev
sudo -u pi pactl load-module module-loopback source=$bluez_dev sink=$AUDIOSINK rate=44100 adjust_time=0 >> /var/log/bluetooth_dev
fi
fi
done
fi
On donne les bons droits.
sudo chmod 774 /usr/lib/udev/bluetooth
Maintenant, un script de démarrage.
sudo nano /etc/init.d/bluetooth-agent
Avec le contenu suivant.
### BEGIN INIT INFO
# Provides: bluetooth-agent
# Required-Start: $remote_fs $syslog bluetooth pulseaudio
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Makes Bluetooth discoverable and connectable to 0000
# Description: Start Bluetooth-Agent at boot time.
### END INIT INFO
#! /bin/sh
# /etc/init.d/bluetooth-agent
USER=root
HOME=/root
export USER HOME
case "$1" in
start)
echo "setting bluetooth discoverable"
sudo hciconfig hci0 piscan
start-stop-daemon -S -x /usr/bin/bluetooth-agent -c pi -b -- 0000
echo "bluetooth-agent startet pw: 0000"
;;
stop)
echo "Stopping bluetooth-agent"
start-stop-daemon -K -x /usr/bin/bluetooth-agent
;;
*)
echo "Usage: /etc/init.d/bluetooth-agent {start|stop}"
exit 1
;;
esac
exit 0
On donne les bons droits.
sudo chmod 755 /etc/init.d/bluetooth-agent
sudo update-rc.d bluetooth-agent defaults
Maintenant, une petite modification pour pulse audio.
sudo nano /etc/inittab
Commentez la ligne suivante avec un #.
1:2345:respawn:/sbin/getty 115200 tty1
Ajoutez la ligne suivante.
1:2345:respawn:/bin/login -f pi tty1 /dev/tty1 2>&1
Maintenant, il suffit de redémarrer.
Si ça marche, un Mac ou un iPhone devrait voir l’appareil en tant qu’enceinte Bluetooth et s’y connecter (code classique, 0000).
Truc à savoir, dans certains cas, le Raspberry ne sort pas le son qui provient de l’appareil, il faut entrer la ligne suivante. Ca m’est arrivé avec un Mac sous Mavericks et un smartphone Android, alors que l’iPhone ou un autre smartphone Android n’ont pas ce souci. Il faut mettre l’adresse MAC Bluetooth de l’appareil qui émet, avec les valeurs séparées d’un _.
pactl load-module module-loopback source=bluez_source.adresse_MAC sink=alsa_output.platform-bcm2835_AUD0.0.analog-stereo rate=44100 adjust_time=0
La partie NFC
La partie NFC est plus simple. Première chose, il faut un smartphone Android équipé en NFC et déjà appairé à votre enceinte. Ensuite, il faut installer l’application Easy Pairing Tag Writer (et éventuellement une application NXP).
On met le tag au bon endroit, on attend et… c’est fini.
Voilà, c’est fini.
Normalement, ça marche avec la majorité des téléphones NFC, il suffit d’effleurer le tag NFC et le Bluetooth s’activera, l’enceinte se connectera et le son passera sur l’enceinte. Techniquement, on peut appairer n’importe quel appareil Bluetooth de cette façon…
well done!!!
Vraiment cool :)
Est-ce que l’utilisation du RaspberryPi comme haut-parleur Bluetooth fonctionne bien ? Est-ce qu’il y’a de la latence, par exemple quand on regarde une vidéo ?
Malheureusement, oui, y a de la latence, comme toujours en Bluetooth.
Sinon, ça marche assez bien avec un iPhone ou un Android quand le flux se lance (comme expliqué, parfois ça marche pas).
AirPlay est franchement plus efficace, mais on a aussi de la latence.
Pour AirPlay, l’iPhone se synchronise avec l’enceinte pour la vidéo normalement (pas les Macs) mais si c’est sur un Ordi via AirMedia/Shairport/etc la synchro n’est pas toujours bonne.
À tester AirPlay en Bluetooth (en PAN).
En fait, en AirPlay « vidéo », le codec est pas le même qu’en audio.
En audio, c’est de l’ALAC, en vidéo, c’est de l’AAC basse latence (HE AAC, je crois). En Bluetooth, y a un codec basse latence qui existe mais y a pas vraiment d’appareils compatibles. Et ici, on n’a accès qu’au SBC, qui a une latence moyenne de 300 ms environ.
Oui mais comme on passe par le PAN (en IP donc) et si tu restes en audio, il serait bon de voir si la latence augmente. (Et oui à terme en synchro de la video même si autre codec).
Tu veux dire Bluetooth -> Mac -> borne en partage Bluetooth ? La bande passante est pas suffisante, si ?
De l’AirPlay basique, c’est de l’ALAC, donc sûrement au moins du 500 kb/s (ça doit dépendre de la musique), je suis pas certain qu’on tienne ça stable en Bluetooth.
C’est un des défauts du Bluetooth, la bande passante. En A2DP, l’AptX est par exemple désactivé dès qu’on a deux trucs sur le Mac, parce que le codec a un bitrate plus élevé que le SBC (enfin, plutôt il est pas adaptable) et en A2DP, on dépasse pas 350 kb/s au niveau codec.
Je viens de tester entre un MacBook et un PowerBook 12″ avec ShairPort dessus. C’est très hachuré sur du 320kbps et du 256VBR. Faudrait que je fasse un 256CBR ou un 128kbps pour voir. iperf me donne des pics à 419kbps (-w 64K -t 60) et les machines sont connectés à −68dBm (Link quality 80%). La seule chose est BT 2.1 (+EDR sur le MacBook je crois, pas sur le PowerBook) donc liaison radio 1Mbps. Le BT4 est censé être à 100Mbps (depuis le BT 3 non ?).
Bref ce n’est pas parfait mais c’est censé marcher avec les normes actuelles.
Le BT3, c’est toujours 2 mbps, c’est juste que ça peut (en théorie, jamais testé) utiliser du Wi-Fi pour la transmission. En gros, t’utilises du Bluetooth pour la connection/jumelage/etc. et du Wi-Fi pour le reste.
BT4, même chose, et le 4.0 LE a un débit encore plus faible (mais une latence meilleure).
Et normalement, en AirPlay de base, c’est de l’ALAC donc l’encodage importe peu, c’est réencodé en ALAC automatiquement. Après, avec l’ALAC, le débit varie un peu en fonction du contenu.
En théorie, on peut transmettre de l’AAC HE en AirPlay, mais que en vidéo, ShairPort, il montre que la partie audio et l’ALAC.
Je ne pensais pas au +HS du BT 3 mais bien à la seule connexion BT. Selon Wiki (US car le FR dit juste 1Mbps et « envie de monter à 100Mbps » d’où mon erreur) le BT 2.0 + EDR monte à 3Mbps (du coup assez pour l’audio) et le 3.0 + HS à 24Mbps (ce qui me semble très peu pour du 802.11).
Tu pourrais tester une liaison BT 4.0 (non LE du coup) pour voir ? Je suis sûr que ça passe aussi bien en ALAC qu’en AAC.
J’ai malheureusement qu’une machine en BT4.0 et je suis pas certain que le mode High Speed du BT3.0 existe sous OS X.
Et accessoirement, ShairPort permet que l’ALAC. L’AAC, à ma connaissance, c’est utilisé qu’en mode clone sur l’Apple TV, et éventuellement en mode vidéo sur un truc genre Freebox, mais là c’est un peu différent : c’est le récepteur qui décode la vidéo directement, y a pas de réencodage comme en AirPlay clone, et donc la bande passante est moins un souci vu que c’est pas du temps réel.
Bonjour le JDL,
Merci pour ce tuto, je me suis amusé avec :) c’est pratiquequand des potes viennent à la maison pour que tout le monde puisse gérer la musique.
sinon j’ai cherché un petit peu ton histoire de tag pas compatible (j’avais acheter des tag pas cher dis NFC) et je suis tombé sur site http://www.nfcwizard.com/fr/ qui à un utilitaire qui permet de savoir si le tag est compatible ou pas NFC
à la prochaine le JDL
Bonjour le JDL,
Je reviens sur cet article suite à quelques changements de Bluez.
Je m’explique, j’ai essayé la méthode que tu expliques sans succès. En fouillant un peu j’ai cru comprendre que le passage de Bluez 4 vers Bluez 5 rendait tout ça obsolète. Je me suis tourné vers des articles plus récents et j’ai trouvé plusieurs méthodes qui fonctionnent, comme celle-ci :
http://raspberrypi.stackexchange.com/questions/47708/setup-raspberry-pi-3-as-bluetooth-speaker
Et en effet, tout fonctionne très bien… jusqu’au reboot du RPi. J’ai alors 2 problèmes :
– je n’arrive pas à faire en sorte que mon téléphone se connecte tout seul au reboot du RPi (chose que j’ai plus ou moins réussi à résoudre mais pas avec une méthode très propre je pense)
– je suis obligé de relancer pulseaudio à la main à chaque reboot. Je n’ai pas trouvé de méthode propre pour contourner ce problème.
Si tu as des pistes pour résoudre ces problèmes je suis preneur :)
Merci d’avance !