[Raspberry Pi] [Watson] スマートスピーカー「もどき」を作ってみた

# はじめに

Raspberry Pi（通称：ラズパイ）とは、イギリスのRaspberry Pi財団によって開発されている、シングルボードコンピュータです。
元々は教育用の位置付けで開発されたそうです。
<img src="https://qiita-image-store.s3.amazonaws.com/0/122917/b55c88f0-d748-cf31-fc0f-32ff4d64b574.png" width=80% alt="Rapberry Pi 3 Model B">
（画像：[Wikipedia](https://ja.wikipedia.org/wiki/Raspberry_Pi)）

以下のような魅力を持っており、教育用途以外でもファンを増やし続けています。

- 安価であること
- コンパクトであること
- ごく簡単な電子工作でLEDやセンサーやモーターなどと接続できること
- DebianベースのRaspbianというOSによって動作し、Debian aptに対応したソフトウェアを簡単に導入できること
- Webサーバーが動作するためWebプログラミングができること
- 最新機種ではWi-FiやBluetoothが内蔵されておりコネクティビティが良いこと

私はつい最近、ラズパイを入手したばかりのズブの初心者なわけですが…
**そんな初心者が、Lチカ（※）程度の電子工作と、IBM Watsonとの連携により、最近話題のスマートスピーカー「もどき」を作ってみました。**

（※）LEDをチカチカさせるという、初歩的な電子工作のこと

認識違いなどがございましたら、コメントで教えていただけると嬉しいです！

なお、Lチカ学習前の方には、こちらの記事がとても分かりやすいと思います。
**参考リンク**
[レッツラズパイ！〜Raspberry3にOSをインストールしよう編〜](https://qiita.com/westvirginia/items/edc3b56da7be58419d70)
[レッツラズパイ！〜Lチカ＆Lピカをマスターしよう編〜](https://qiita.com/westvirginia/items/e339dbaf3286ea966483)

**＜ご注意＞**
本稿の内容は執筆時点の情報に基づいており、現在の情報と異なっている可能性があります。
本稿の内容は執筆者独自の見解であり、所属企業における立場、戦略、意見を代表するものではありません。

# 作ってみたモノ・使ったモノ

スイッチ（タクトスイッチという電子工作パーツ）を押しながら、マイクに、

:speaking_head:「今日の天気を教えて」と話しかけると…
　:ear:スピーカーから声で天気予報が流れます。

:speaking_head:「今日は一日休むって連絡して」と話しかけると…
　:zap:Slackに「本日は一日休暇をいただきます」とPOSTされます。
　:ear:スピーカーから「全休連絡を送信しました」と流れます。

![IMG_3772.JPG](https://qiita-image-store.s3.amazonaws.com/0/122917/7dad291a-4df6-b80f-efd0-7105380cf828.jpeg)

家にマイクがなかったのでマイク内蔵のWebカメラを利用しています。

- Rapberry Pi 3 Model B
    - OSはRaspbian、バージョンはStretchです。
- オーディオデバイス
    - USB Webカメラ
    - 3.5mmジャック スピーカー
- 電子工作
    - ブレッドボード：1個
    - ジャンパーワイヤー
        - オスーメス：4本
        - オスーオス：3本
    - タクトスイッチ：1個
    - 赤色LED：1個
    - 抵抗
        - 330Ω：1個
        - 10kΩ：1個
- IBM Cloudアカウント
- Slackアカウント

※赤色LEDはタクトスイッチが押されていることを示すために使っていますが、必須ではありません。
※ラズパイ内部のプルダウン抵抗機能を使用する場合、10kΩ抵抗は必要ありません。

プログラミングには、ラズパイ側、サーバーサイドともに「Node-RED」を利用しました。
Node-REDは、ほぼコーディングレスでプログラムを組める開発ツールです。

**参考リンク**
[Node-RED日本ユーザー会](https://nodered.jp/)

# Raspberry Pi側の開発

## USBマイクの設定と録音

カード番号とデバイス番号を確認しておき、arecordコマンドでそれらを指定することで、音声をwavファイルに保存できます。

**参考リンク**
[raspberry pi で USBカメラ(c270)から画像/音声入力/出力](https://qiita.com/kummn/items/6eaf7b1cbb8435c78f12)

## 電子工作

以下のような回路を組みました。
ごく初歩的なモノです。

![Qiita201803_ブレッドボード.png](https://qiita-image-store.s3.amazonaws.com/0/122917/0392f7bf-5362-bc13-bfac-36139632971d.png)

タクトスイッチの回路はPIN 18(GPIO 24)に接続されています。
赤色LEDはPIN 22(GPIO 25)です。

この図（ブレッドボード図）は、[Fritzing](http://fritzing.org/home/)というソフトで作成しました。
**参考リンク**
[【ハード】回路図作成ソフトの定番！『Fritzing』を使い倒す](http://lab-b.jp/2014/09/28/fritzing/)

## Node-RED

Raspbianのバージョン「Stretch」にはNode-REDがインストールされています。
GPIOにアクセスするためのノード（部品）も揃っていますので、とてもラクチンです♪

### タクトスイッチのフロー

![スクリーンショット 2018-03-05 14.19.08.png](https://qiita-image-store.s3.amazonaws.com/0/122917/a2e77e6a-8892-41e8-8513-70f358c4e09b.png)

左端がrpi-gpio-inノードです。
これに、タクトスイッチが繋がっている、PIN 18(GPIO 24)を指定しています。

rpi-gpio-outノードには赤色LEDが繋がっているPIN 22(GPIO 25)を指定しています。

タクトスイッチを押された／離された際にrpi-gpio-inノードが発火し、
・押された=HIGH(1)の場合、LEDを点灯し、arecordで録音を開始します。
・離された=LOW(0)の場合、LEDを消灯し、arecordをkillallし、メインフローを呼び出します。

インポート用のフロー定義はこちらです。
https://gist.github.com/y-some/b25d2bbd17b4ae808db59496dabbcfa7

### メインフロー

IBM Watson用のノードは追加する必要があります。

**参考リンク**
[RasberryPi2のNode-REDにWatson Cognitive関連のノードを追加してみました](https://qiita.com/Mitsu-Murakita/items/90907782b6aec9959328#4-watson-cognitive%E3%83%8E%E3%83%BC%E3%83%89%E3%81%AE%E8%BF%BD%E5%8A%A0)

![スクリーンショット 2018-03-05 14.25.33.png](https://qiita-image-store.s3.amazonaws.com/0/122917/49413bcf-0f95-cfd0-00ce-65dbba7997a7.png)

Watson Speech to Text(STT)に音声データを渡してテキストに変換し、それをパラメータとしてサーバーサイドを呼び出します。
サーバーサイドから返ってきたテキストをText to Speech(TTS)によってwavに変換させて、それをラズパイ側で再生します。

STTとTTSについては後述します。

インポート用のフロー定義はこちらです。
https://gist.github.com/y-some/e874c20b3323bed0458da9098f852535

# サーバーサイドの開発

IBM Cloudに構築しました。
[無料のライト・アカウント](https://www.ibm.com/cloud-computing/jp/ja/bluemix/developerslounge/liteservice/)でも概ね試すことができますが、一部は正規のアカウントが必要になります（後述）。

## Watsonサービス

### Speech to Text(STT) と Text to Speech(TTS)

STTは音声をテキストに変換、TTSはテキストを音声で読み上げるサービスです。
オーダーして、資格情報をメモしておきます。
必要な設定は特にありません。

### Conversation

Intents（意図）とEntities（類義語）を定義し、Dialog（対話）を作成して会話をシミュレーションします。
Entitiesの作成は任意なので、今回はIntentsとDialogだけを利用します。

まずはIntentsの登録です。
<img width="1223" alt="スクリーンショット 2018-03-04 19.22.28.png" src="https://qiita-image-store.s3.amazonaws.com/0/122917/c430d366-a1c6-fcd7-032d-53c1c03b8973.png">
他に、「半休Slack送信」「全休Slack送信」のIntentsも登録しておきます。
挨拶のIntentsなども登録しておくと面白いかと思います。

Dialogは単純です。
天気予報のIntentだったら戻り値として"wheather"を返し、半休だったら"halfdayoff"を返す、夜の挨拶だったら"今晩は"というテキストを返す、という感じです。
<img width="1094" alt="スクリーンショット 2018-03-04 19.49.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/122917/ad1742eb-f8af-62b3-36a6-34eaea3e05e7.png">

**参考リンク**
[Watson ConversationのTutorialを日本語でやってみた （前編）](
https://qiita.com/sukusuku_watson_editorial_room/items/2ab2b4738e31b276b91e)
[Watson ConversationのTutorialを日本語でやってみた （後編）](https://qiita.com/sukusuku_watson_editorial_room/items/e3111d2ccce996db7feb)

### Weather Company Data

2018年3月現在、ライト・アカウントでは利用できません。
正規のアカウントが必要になります。
コール数に制限がありますが、無料プランがあります。
詳細は[ドキュメント](https://www.ibm.com/ibm/jp/ja/weather.html)をご参照ください。

オーダーして、資格情報をメモしておきます。
必要な設定は特にありません。

## Node-RED

![スクリーンショット 2018-03-05 14.09.01.png](https://qiita-image-store.s3.amazonaws.com/0/122917/1ba4c064-5185-bcec-13f2-8449c0f16c59.png)

Conversationからの戻り値（"wheather" / "halfdayoff" / "今晩は"など）を判定して分岐しています。

Slackノードは追加が必要です。

**参考リンク**
[Bluemixでnode-redを立ち上げる](https://qiita.com/KURO-BLACK/items/77af2c98940320ca6ce9#_reference-f41d8339b6892bd267e2)
[node-redにSlackをつなげてみる](https://qiita.com/KURO-BLACK/items/0cb3fac16c26876e5d00)

インポート用のフロー定義はこちらです。
https://gist.github.com/y-some/ec39691c5529d88aee47de1c5a426485

# おわりに

ハンダ付けもなく、コーディングもほんの数行で、ここまで出来てしまいました。:open_mouth:

電子工作をもうちょっとレベルアップすれば、声で家電操作なんかも出来ちゃうと思います。
あるいは、対話フローを精緻化すれば、会社の受付システムなんかも出来ちゃうかも知れませんね。

市販のスマートスピーカーの方が精度は高いのでしょうが、ラズパイを使ったモノ作りは楽しいです！
ぜひ皆さんもラズパイにトライしてみてはいかがでしょうか？