Raspberry Pi 3B + BluetoothスピーカでAmazon Alexaを安く構築（１　まずは音を鳴らす）

# 大目的

Amazon Echoをついに購入できて試していると、やはり技術革新を感じましたね。
なんてったって自分よりも-28歳の娘が説明書も見ずに「Alexaしりとりしよう」と言って会話が成立している。
さて、2台買いたいがAmazonから招待が来ないのです。手元にはRaspberryPiがあります。

そういうときに手があります。Raspberry PiをAmazon Echoにするという手が。
Amazonは開発者向けにAVS(Amazon Voice Service)を無料配布しており、その中にAlexa(Amazon Echoの声)が入っているとのこと。何とかして動かしたい。

これから、Raspberry Pi 3Bのみ、という状況から必要なハードウェアをできるだけ安い価格で買って、Echo相当のAlexa起動を目指します。 

Raspberry PiでEchoを作る先駆者の記事は下記。

https://qiita.com/bwtakacy/items/32226ed2406b5ebe1984

# 本章：まずはスピーカが鳴らない。。。Bluetoothでなんとかつなぐ。

ラズパイにはスピーカ用のアナログ出力がありますので、そこから音を出すのは何とかなります。
（mp3を再生するにはapt-get install mpg321）
今回はなんとかワイヤレススピーカから音を出したい。そうしないとAlexaの声も歌も聞けない。
（歌：http://www.itmedia.co.jp/news/articles/1712/19/news097.html）

### 購入品

- Bluetoothワイヤレススピーカ 1400円

お風呂でもつかえるらしいです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/96277/c695f4bf-0ab4-dcb1-edea-170fe96b7253.png)


### 既存品

- Raspberry Pi 3B

# まず準備

### Raspberry Piを最新に

```
# sudo apt-get dist-upgrade
# sudo rpi-update
```

# ラズパイから音を鳴らす

ラズパイから音を鳴らすにはPulseAudioというデーモンが動いている必要があるそうです。

```
sudo apt-get install pulseaudio pavucontrol
pulseaudio -D
```

これでまずアナログ出力からは音が鳴るはずです。
たとえば、mp3ファイルが手元にあり

```
mpg321 Chicken.mp3
```

とすれば[例えばチキンアタック](https://www.youtube.com/watch?v=miomuSGoPzI)も再生できるでしょう。

# ワイヤレススピーカをラズパイに接続する

ワイヤレススピーカを起動します。
まずはBluetoothとしてペアリング。下記記事に詳細が書いてあります。

https://qiita.com/Sam/items/5169d9f060aa31080b77

```
sudo apt-get install pi-bluetooth blueman pulseaudio-module-bluetooth
```

```
pi@raspberrypi:~ $ bluetoothctl
[bluetooth]# power on
Changing power on succeeded
[bluetooth]# agent on
Agent registered
[bluetooth]# scan on
Discovery started
[NEW] Device 30:21:18:71:23:51 Q50
```

```
[bluetooth]# pair 30:21:18:71:23:51
[CHG] Device 30:21:18:71:23:51 Paired: yes
Pairing successful
[bluetooth]# trust 30:21:18:71:23:51
[CHG] Device 30:21:18:71:23:51 Trusted: yes
[bluetooth]# connect 30:21:18:71:23:51
Attempting to connect to 30:21:18:71:23:51
[CHG] Device 30:21:18:71:23:51 Connected: yes
Connection successful
```

サービスは下記ファイルを作成して、

```
[Unit]
Description=Pulse Audio

[Service]
Type=simple
ExecStart=/usr/bin/pulseaudio --system --disallow-exit --disable-shm

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

下記コマンドでデーモンを起動し、さらに自動起動設定します。

```
$ sudo systemctl start pulseaudio.service
$ sudo systemctl status pulseaudio.service
$ sudo systemctl enable pulseaudio.service
```

# ワイヤレススピーカから音を出す

下記記事によりますと、pulseaudioデーモンの出力先にbluetoothを設定する必要があるそうです。

http://zokibayashi.hatenablog.com/entry/2017/10/10/020902

下記を末尾に追記します。

```/etc/pulse/system.pa
<前略>

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

.ifexists module-bluetooth-discover.so
load-module module-bluetooth-discover
.endif
```

/etc/dbus-1/system.d/pulseaudio-bluetooth.confに転送先設定をします。BluezというのがBluetooth転送プロトコル実装だそうです。

http://www.silex.jp/blog/wireless/2012/12/bluetooth4.html

```/etc/dbus-1/system.d/pulseaudio-bluetooth.conf
  <policy user="pulse">
    <!--　ここをコメントアウト
    <allow own="org.pulseaudio.Server"/>
     コメントアウト終わり -->
    <allow send_destination="org.bluez"/>
  </policy>
```

システムを再起動。

```
sudo reboot
```

もし音が鳴らなければpulseでの転送のアクセス権がないのかも。下記でアクセス権を与えます。

```
sudo usermod -a -G pulse-access,audio pi(ここはユーザ名)
```

# (2018/1/3追記) あとでAlexaをちゃんとbluetoothスピーカからしゃべらせるためのJava設定

のちのちAlexaサンプルアプリを実行するのですが、なぜかアナログ出力からしか音を出しません。
この理由、いろいろ調べていた結果、Javaアプリからだけ音が鳴らない（ほかの`mpg321`や`aplay`は音が鳴る）のはJavaがらみの設定というところまで絞り込んで、下記記事を見つけなんとかうまく音声を出す方法が分かりました。
https://stackoverflow.com/questions/45847635/java-audio-clip-cannot-be-closed-when-using-linux-pulseaudio

ちょっと紛らわしいですが、Alsaユーザランド→PulseAudio→Bluetoothスピーカという経路で転送しなければいけないそうです。
さてこのために、`sudo`で下記ファイルを編集し、下記4行を追加します。

```/usr/lib/jvm/java-8-oracle/jre/lib/sound.properties
javax.sound.sampled.Clip=com.sun.media.sound.DirectAudioDeviceProvider
javax.sound.sampled.Port=com.sun.media.sound.PortMixerProvider
javax.sound.sampled.SourceDataLine=com.sun.media.sound.DirectAudioDeviceProvider
javax.sound.sampled.TargetDataLine=com.sun.media.sound.DirectAudioDeviceProvider
```

# この次

スピーカからは音が鳴るようになったので、次は音声で制御できるようマイクを付けます。