LED電球（スピーカー機能）をマイコン（Intel Edison）から制御する

市販されているLED電球にはBluetooth経由で色を変えたり音を鳴らすことのできるものがあります．[前前回](http://qiita.com/nobu_e753/items/7d6afca7b81ea46f9474)，[前回](http://qiita.com/nobu_e753/items/a6ce2c8ae1be1f66082c)はLED電球(PLAYBULB)のLED照明機能をマイコン（Intel Edison）から制御してみましたが，今回はスピーカー機能の制御にチャレンジします．

# やりたいこと

![slide.png](https://qiita-image-store.s3.amazonaws.com/0/156705/db509cba-bc77-bec1-30c7-63e0ecfaca95.png)

- マイコン上のプログラムからLED電球のスピーカー機能を利用して音を鳴らす

# 環境

- [Intel Edison](https://www.switch-science.com/catalog/1956/)
- [MiPow PLAYBULB color Smart LED](http://www.playbulb.com/en/playbulb-color.html)
- Python 3.5.3
- PulseAudio (初期状態でインストール済み)
- Gstreamer 1.10.4 

edisonやLED電球の設定は[LED電球をマイコン（Intel Edison）から制御する(1)](http://qiita.com/nobu_e753/items/7d6afca7b81ea46f9474)の「環境」の項を参照ください．

# 制御までの手順

利用したスピーカー機能付きLED電球（PLAYBULB）は音声のやり取りにBluetooth A2DP(Advanced Audio Distribution Profile)プロファイルを使っており，これは一般的なBluetoothスピーカーで使われている方式と同じです．言い換えると，今回のチャレンジは**マイコン（Intel Edison）からBluetoothスピーカーを制御する**のと同じです．

## [1] スピーカー機能のアドレスを調べる

LED電球をソケットにさし，スマートフォン用PLAYBULB専用制御アプリから音がならせるところまでは確認できているものとします．スピーカー機能にアクセスするためのアドレスを調べます．

```bash:bluetooth側設定
$ bluetoothctl 
[NEW] Controller 98:4F:EE:04:28:48 edison [default]
[bluetooth]$ scan on
Discovery started
[CHG] Controller 98:4F:EE:04:28:48 Discovering: yes
[NEW] Device DB:22:4B:13:AC:E6 PLAYBULB COLOUR LED    <-- LED照明機能
[NEW] Device AC:E6:4B:13:E4:9F PLAYBULB COLOUR        <-- スピーカー機能（今回はこっち
```

## [2] とりあえず音を鳴らしてみる

edison + Bluetooth スピーカーの制御については[公式のフォーラム](https://software.intel.com/en-us/articles/play-audio-from-your-intel-edison-via-bluetooth-using-advanced-audio-distribution-profile)にあるPulseAudio+Gstreamerの組み合わせでやることにします．これ以外にも[PulseAudio+mplayerで実践](http://qiita.com/biatunky/items/16e445a3ef9566b2225c)されている方もいらっしゃるようです．

```bash:bluetooth側設定（続き）
[bluetooth]$ agent DisplayYesNo         <-- 無いと動作しない場合がある．詳細は不明．
Agent registered
[bluetooth]$ default-agent              <-- 無いと動作しない場合がある．詳細は不明．
Default agent request successful
[bluetooth]$ trust AC:E6:4B:13:E4:9F    <-- デバイスを信頼できるものとして設定
[CHG] Device AC:E6:4B:13:E4:9F Trusted: yes
Changing AC:E6:4B:13:E4:9F trust succeeded
[bluetooth]$ pair AC:E6:4B:13:E4:9F     <-- ペアリング
Attempting to pair with AC:E6:4B:13:E4:9F
[CHG] Device AC:E6:4B:13:E4:9F Connected: yes
[CHG] Device AC:E6:4B:13:E4:9F UUIDs: 0000110b-0000-1000-8000-00805f9b34fb
[CHG] Device AC:E6:4B:13:E4:9F Paired: yes
Pairing successful
[CHG] Device AC:E6:4B:13:E4:9F Connected: no
[bluetooth]$ connect AC:E6:4B:13:E4:9F  <-- 接続. この時点で ピー とビープ音がなります
Attempting to connect to AC:E6:4B:13:E4:9F
[CHG] Device AC:E6:4B:13:E4:9F Connected: yes
Connection successful
[bluetooth]$ quit                       <-- bluetoothctlを抜けます
```

```bash:gstreamerインストール
$ opkg install gstreamer
```

```bash:音声再生
$ pactl list sinks | grep Name
        Name: alsa_output.platform-merr_dpcm_dummy.0.analog-stereo
        Name: alsa_output.0.analog-stereo
        Name: bluez_sink.AC_E6_4B_13_E4_9F             <-- これが接続されているBLEスピーカー名
$ pactl set-default-sink  bluez_sink.AC_E6_4B_13_E4_9F <-- 音声出力先を変更
$ gst-launch-1.0 filesrc location=hoge.wav ! wavparse ! pulsesink <-- Waveファイル再生
```

LED電球から音が流れましたか？スピーカーの接続さえうまく行けば，残りは簡単だと思います．なおPulseAudioとbluetoothctlのバージョンによってはうまくいかない，との記載も見かけましたが，bluetoothctlを初期状態の5.37から5.44にしても手元では動作しました．
あと，初期状態のままではとてつもない音量になることもあるので以下のように調整してやります．

```bash
$ pactl set-sink-volume bluez_sink.AC_E6_4B_13_E4_9F 50%
```

## [3] プログラム（Python）から制御するには？ 

GstreamerのPythonバインディングがいくつかあるようなのですが，edison上で動かした事例が見つけられず嫌な予感がしたので，おとなしく外部コマンドを呼ぶ形にしました．（もしIntel edison上でAPI経由でGstreamerをたたく事例をご存知の方がいらしたら教えていただきたく）．

```py:play.py
# -*- coding: utf-8 -*-
import subprocess
if __name__ == '__main__':
    tPlayer = subprocess.Popen("gst-launch-1.0 fdsrc fd=0 ! wavparse ! pulsesink",
                               shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
    tWaveData = open("./hoge.wav", "rb").read()
    tPlayer.communicate(tWaveData)
```

callで呼んでもよいのですが，このような形にしました．ファイルからWaveデータを読む部分をWebAPIから取得するように変更してやることで，WebAPIにて取得した音声データをそのまま出力できます．

# 応用

音・光の双方がプログラムから制御できると

- **音声案内と同時に光で案内するインフォメーションライト**
    - 例：「明日の天気は雨です」（青点灯
    - 例：「サーバーに障害が発生しました」（赤点滅

などの応用が可能になります．音声合成APIと組み合わせ状況に応じた音声を流すことでより幅も広がります．

# おまけ：Pechatと接続

少し前に，超小型のBluetoothスピーカー[Pechat](https://pechat.jp/)なるものの存在を教えてもらいましたのでこれも接続してみました．筐体はかなり小さいですが，ボリューム最大にすれば十分な大きさの音が鳴りました．

<blockquote class="twitter-tweet" data-lang="ja"><p lang="en" dir="ltr">Ble speaker control with Intel edison &amp; A2DP <a href="https://t.co/HOv62l7Y82">https://t.co/HOv62l7Y82</a></p>&mdash; nobu_e753 (@nobu_e753) <a href="https://twitter.com/nobu_e753/status/838401183257546753">2017年3月5日</a></blockquote>

セガトイズのアンパンマン（700円程度）に輪ゴムでPechatを括り付けてあります．ぬいぐるみがもうひとまわり大きければIntel edisonとバッテリーごと埋め込めそうですので，センサを足して「抱いたらしゃべるぬいぐるみ」，マイクを足して「お話ができるぬいぐるみ」も実現できそうです．

# まとめ

PulseAudioとgstreamerを使い，マイコン（Intel Edison）からLED電球（PLAYBULB）のBluetoothスピーカー機能を制御することができました．単体のBluetoothスピーカーについても同じ方法で制御ができました．