Raspberry pi でBluetooth(a2dp sink)

![withoutAmp.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166811/6278aea3-7f93-bce5-db00-b8333347927a.jpeg)

# やりたい事
スマホの音楽(Amazon Musicなど)をBluetooth(a2dp)で受信し、Raspberry pi3のI2S-DACに接続したスピーカーで流します。

# 環境
+ raspberry pi3
+ hifiberry dac(pcm1502mk)
+ アンプ・スピーカー

# 解説
[BlueALSA](https://github.com/arkq/bluez-alsa)を使って実現します。

BlueALSAが、bluetoothdとサウンドカード間を繋いでくれるイメージです。bluetoothdがa2dpでの接続を受け付けた際に音楽をサウンドカードに橋渡しできるように、BlueALSAのサービスをsystemdに登録します。BlueALSAの心臓にあたる[bluealsa](https://github.com/arkq/bluez-alsa/blob/master/doc/bluealsa.8.rst)と、スマホからの音楽をサウンドカードに渡す[bluealsa-aplay](https://github.com/arkq/bluez-alsa/blob/master/doc/bluealsa-aplay.1.rst)の２つのサービスを登録します。


## とりかかろう！
### 1. 事前ソフトのインストール
BlueALSAが必要とするソフトをインストールします。

```Dependencies
sudo apt-get update
sudo apt-get install libasound2-dev
sudo apt-get install dh-autoreconf
sudo apt-get install libortp-dev
sudo apt-get install bluez pi-bluetooth bluez-tools libbluetooth-dev
sudo apt-get install libusb-dev libglib2.0-dev libudev-dev libical-dev libreadline-dev
```
No package 'dbus-1' found のエラーが出たら、dbus-1 もインストールします。
```Dependencies2
sudo apt install git virtualenv build-essential python3-dev libdbus-glib-1-dev libgirepository1.0-dev
```
さらに続けます。

```Dependencies3
sudo apt-get install libsbc1 libsbc-dev
```

### 2. Bluez-Alsaのインストール

```Bluez-Alsa
sudo git clone https://github.com/Arkq/bluez-alsa.git
cd bluez-alsa
sudo autoreconf --install
sudo mkdir build && cd build
sudo ../configure --enable-manpages --enable-rfcomm --disable-hcitop --with-alsaplugindir=/usr/lib/arm-linux-gnueabihf/alsa-lib
sudo make && sudo make install
```

### 3. Bluetoothの設定

/etc/bluetooth/main.conf の内容を次の内容でアップデートします。

```vim:main.conf
[General]
Class = 0x20041C
```
このクラスの指定で、RasberryPiが、どういうbluetoothの機器かと言う事を指定します。この情報を周りのbluetooth機器にも伝えるので、ここでは、audioの機器であることを指定しています。


/etc/bluetooth/audio.conf を以下の中身で作ります。

```vim:audio.conf
[General]
Class = 0x20041C
Enable = Source,Sink,Media,Socket
```

### 4. bluealsaの設定
#### 4.1. bluealsaの自動起動用設定ファイルの作成
systemd を使用して、bluealsaを自動起動させるため、/lib/systemd/system/bluealsa.serviceファイルを作成します。

```vim:/lib/systemd/system/bluealsa.service
[Unit]
Description=BluezAlsa proxy
Requires=bluetooth.service
After=bluetooth.service

[Service]
Type=simple
User=root
Group=audio
ExecStart=/usr/bin/bluealsa -p a2dp-sink

[Install]
WantedBy=multi-user.target
```
bluealsaは、bluetooth.serviceの起動が前提なので、
Requires=bluetooth.service
After=bluetooth.service
が必要です。


#### 4.2. bluealsa-aplayの自動起動用の設定ファイル

```vim:/lib/systemd/system/bluealsa-aplay@.service
[Unit]
Description=BlueAlsa-Aplay -Dhw:1,0
Requires=bluetooth.service bluealsa.service

[Service]
Type=simple
User=root
Group=audio

ExecStart=/usr/bin/bluealsa-aplay -Dhw:1,0

[Install]
WantedBy=multi-user.target
```

bluealsa-aplayでは、使用するサウンドカードを-Dパラメータの後に指定します。古いbluealsa-aplayだと、-Dではなく、-dでした。今は、-dの指定は、無効です。パラメータでカードを指定しない場合、pulseaudioのデフォルトカードを使おうとするようで、ログ見てると急にpulseaudioが出て来て、ハマりました。

systemdが管理するこのbluealsa-aplay@.serviceの中で、パラメータに、%Iを指定して、`bluealesa-aplay -Dhw:1,0 %I`のようにして接続するbluetooth機器のアドレスをbluealsa-aplayに渡してもいいのですが、どうもわたさなくてもアドレスを拾ってくれるみたいなので、指定をやめました。

#### 4.3. udev登録

```vim:/etc/udev/rules.d/99-input.rules
KERNEL=="input[0-9]*", RUN+="/home/bluealsa/a2dp-autoconnect"
```
bluetooth機器が接続されて、uevent が送信された時、環境変数KERNELに"input[0-9]*"にマッチする文字列が設定されているのでこのudevのルールファイルが読まれ、bluetooth機器が接続された時に行われる既存の処理に加えて、RUNで指定したプログラムをudevデーモンが実行します。

udevデーモンは起動時に/usr/lib/udev/rules.d/*.rulesおよび/etc/udev/rules.d/*.rulesファイルからすべての規則を読み込んで解析し、メモリ内に保持するんですって。

#### 4.4. スクリプトa2dp-connect
```vim:/home/bluealsa/a2dp-autoconnect
#!/bin/bash
# at each BT connection/disconnection start/stop the service bluealsa-aplay
function log {
        sudo echo "[$(date)]: $*" >> /var/log/a2dp-autoconnect
}

# bluealsa-aplay でBTMACを指定できるようにBTMACを取得しています。
# 今回は使ってないので、下記行は無くてもOK
BTMAC=${PHYS//\"/}

if [ $ACTION = ＃"remove" ]
then
                log "Stop Played Connection " $BTMAC
                systemctl stop bluealsa-aplay@$BTMAC
elif [ $ACTION = "add" ]
then
                log "Start Played Connection " $BTMAC
                systemctl start bluealsa-aplay@$BTMAC
else
                log "Other action " $ACTION
fi
```

###### こーひーぶれいく：udevadm monitor での環境変数チェック
最初、参考にしていたページでは、bluetooth機器アドレスをbluealsa-aplayに渡していました。そしてこのアドレスは、環境変数NAMEを使って渡されていました。それで、私も同じようにしましたが、すると、私の環境では、なんとアドレスは渡されず、スマホの名前(motorola g52j)が渡されてきました。しばらく途方に暮れたのですが、`udvadm monitor -pk`を使って調べれそうな事にたどり着き、実行することでアドレスを取得できる環境変数PHYSを見つけました。結局は、アドレス指定しないことにしたのですが^^;。下記がその時のコマンド実行の様子です。

```vim:udevadm monitor -pk
nob@music:~ $
nob@music:~ $ udevadm monitor -pk
monitor will print the received events for:
KERNEL - the kernel uevent

KERNEL[1319.510073] add
/devices/platform/soc/3f201000.serial/tty/ttyAMA0/hci0/hci0:11
(bluetooth)
ACTION=add
DEVPATH=/devices/platform/soc/3f201000.serial/tty/ttyAMA0/hci0/hci0:11
SUBSYSTEM=bluetooth
DEVTYPE=link
SEQNUM=1623

KERNEL[1322.023904] add      /devices/virtual/input/input4 (input)
ACTION=add
DEVPATH=/devices/virtual/input/input4
SUBSYSTEM=input
PRODUCT=5/8/2e81/2020
NAME="moto g52j 5G (AVRCP)"
PHYS="b8:XX:XX:XX:XX:90"
PROP=0
EV=100007
KEY=2fc800 1452 0 0 0 0 10300 49e8 c00 e1680 f f8100000 10000ffc
REL=0
MODALIAS=input:b0005v0008p2E81e2020-e0,1,2,14,k71,72,73,8A,8B,A3,A5,A6,A7,A8,AB,AE,C8,C9,D0,161,164,166,16A,16C,18B,18E,18F,190,191,192,193,195,ramlsfw
SEQNUM=1624

KERNEL[1322.025135] add      /devices/virtual/input/input4/event2 (input)
ACTION=add
DEVPATH=/devices/virtual/input/input4/event2
SUBSYSTEM=input
DEVNAME=/dev/input/event2
SEQNUM=1625
MAJOR=13
MINOR=66

^C
nob@music:~ $
nob@music:~ $

```

### 5. deamonの再読み込み

```systemd-bluealsa
sudo systemctl daemon-reload
sudo systemctl enable bluealsa.service
```

systemd の挙動は、`journalctl`で確認しましょう。



### 6. blueatoothデバイス接続

さあ、スマホを接続しましょう！

```
nob@music:~ $
nob@music:~ $ sudo bluetoothctl
Agent registered
[CHG] Controller B8:XX:XX:XX:XX:90 Pairable: yes
[bluetooth]# scan on
Discovery started
[CHG] Controller B8:XX:XX:XX:XX:90 Discovering: yes
[NEW] Device 6C:XX:XX:XX:XX:8A moto g52j 5G
[CHG] Device 6C:XX:XX:XX:XX:8A RSSI: -63
[bluetooth]# connect 6C:XX:XX:XX:XX:8A
Attempting to connect to 6C:XX:XX:XX:XX:8A
[CHG] Device 6C:XX:XX:XX:XX:8A Connected: yes
[CHG] Device 6C:XX:XX:XX:XX:8A Modalias: bluetooth:v0008p2E81d2020
[CHG] Device 6C:XX:XX:XX:XX:8A UUIDs: 00001105-0000-1000-8000-00805f9b34fb
[CHG] Device 6C:XX:XX:XX:XX:8A UUIDs: 0000110a-0000-1000-8000-00805f9b34fb
[CHG] Device 6C:XX:XX:XX:XX:8A UUIDs: 0000110c-0000-1000-8000-00805f9b34fb
[CHG] Device 6C:XX:XX:XX:XX:8A UUIDs: 0000110e-0000-1000-8000-00805f9b34fb
[CHG] Device 6C:XX:XX:XX:XX:8A UUIDs: 00001112-0000-1000-8000-00805f9b34fb
[CHG] Device 6C:XX:XX:XX:XX:8A UUIDs: 00001115-0000-1000-8000-00805f9b34fb
[CHG] Device 6C:XX:XX:XX:XX:8A UUIDs: 00001116-0000-1000-8000-00805f9b34fb
[CHG] Device 6C:XX:XX:XX:XX:8A UUIDs: 0000111f-0000-1000-8000-00805f9b34fb
[CHG] Device 6C:XX:XX:XX:XX:8A UUIDs: 0000112d-0000-1000-8000-00805f9b34fb
[CHG] Device 6C:XX:XX:XX:XX:8A UUIDs: 0000112f-0000-1000-8000-00805f9b34fb
[CHG] Device 6C:XX:XX:XX:XX:8A UUIDs: 00001132-0000-1000-8000-00805f9b34fb
[CHG] Device 6C:XX:XX:XX:XX:8A UUIDs: 00001200-0000-1000-8000-00805f9b34fb
[CHG] Device 6C:XX:XX:XX:XX:8A UUIDs: 00001800-0000-1000-8000-00805f9b34fb
[CHG] Device 6C:XX:XX:XX:XX:8A UUIDs: 00001801-0000-1000-8000-00805f9b34fb
[CHG] Device 6C:XX:XX:XX:XX:8A UUIDs: 10000000-328e-0fbb-c642-1aa6699bdada
[CHG] Device 6C:XX:XX:XX:XX:8A UUIDs: a82efa21-ae5c-3dde-9bbc-f16da7b16c5a
[CHG] Device 6C:XX:XX:XX:XX:8A UUIDs: a924496e-cc7c-4dff-8a9f-9a76cc2e9d50
[CHG] Device 6C:XX:XX:XX:XX:8A UUIDs: badbadba-dbad-badb-adba-badbadbadbad
[CHG] Device 6C:XX:XX:XX:XX:8A ServicesResolved: yes
Request confirmation
[agent] Confirm passkey 044732 (yes/no): yes
[CHG] Device 6C:XX:XX:XX:XX:8A Paired: yes
Connection successful
[moto g52j 5G]# trust 6C:XX:XX:XX:XX:8A
[CHG] Device 6C:XX:XX:XX:XX:8A Trusted: yes
Changing 6C:XX:XX:XX:XX:8A trust succeeded
[moto g52j 5G]# exit
nob@music:~ $
```

さあ、スマホのアプリで希望の音楽を再生しましょう。

スピーカーから心地のいい音楽が流れていることでしょう！！