ASK CLIで作る、「ラジ○体操第一」Alexa Skill

鍼灸院の院長に体が固いことを指摘され、ラジオ体操をすることにしました。
子供の頃は夏休みに毎日やらされていたので、音楽を聞けば画像がなくても踊れます。Alexa向けと言えましょう。
そこでAlexa Skillでラジオ体操のスキルを作ることにしました。
著作権の都合上、もちろん自分専用です。
さらに今回は、9月にリリースされたASK CLIを使ってみることにします。

# 用意するもの
- Mac 
- USのAWSのアカウント
- USのAlexa Skills Developerコンソールのアカウント
- Alexa が動作するデバイス(echoとかFire TV Stick） あるいはテスト用のアプリ（Astraなど）

Windowsでも多分できると思います。が、ASK CLIの説明が、どう見てもLinux / Mac向けでしたので、読み替えて進むのに限界があったらVirtualBoxなどでCentOSを使うのがいいかもしれません。




# Alexa Skills Developer consoleで App登録

まず、[Alexa SkillのDeveloper console](https://developer.amazon.com/edw/home.html)を開き、
左側の「Alexa Skills Kit」の下の「Get Started」をクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/173392/f2f11820-bfc2-61b6-7aa2-a8bcb5682e38.png)

↓

開いた画面の右肩にある「Add a new skill」を力一杯クリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/173392/e245496c-1858-ad24-1b02-da72a5ce6045.png)

↓

するとSkill Informationの設定画面がひらけます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/173392/05996440-11e3-6145-617b-723e08d899ff.png)

Skill type =  Custom Interaction Model
Language = English (U.S）　

![image.png](https://qiita-image-store.s3.amazonaws.com/0/173392/3a6ff707-0618-3b5d-c10c-8ce34fdb114d.png)
本来日本語を選びたいのですが、対応してないので仕方なしにUS英語を選びます。早く日本語対応してくれーToT


Name = Radio Taisou No.1
Invocation Name = rajio taisou dai ichi

Alexaに「〜のスキルを起動して」と呼びかける時の名前は、**日本語のローマ字読み**にしてみました。これで、「アレクサ、オープン　ラジオ　タイソウ ダイ　イチィ」と、呼びかければ起動してくれるようになります。(^^;)

↓
画面を下にスクロールすると背景が灰色の入力欄が出てきます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/173392/ff145304-2cb1-81dc-e2f0-01809f431a80.png)

Audio Player = Yes
Video App = No
Render templare = No

Nextをクリックします。

IDが生成されました。
以下のamzn1,ask.〜798の部分が、今後Application IDとかAPP IDとか呼ばれるものになります。

（このIDのアプリは、デベロッパーサイトからもう消しましたんで、ここに書いてますが、
本来はあんまり他人に教えない方が良いと思います。
理由は、悪用できないとも限らないから。）

![image.png](https://qiita-image-store.s3.amazonaws.com/0/173392/7c9ba8d2-08f2-c557-e0ab-d0527c877c66.png)

次はIntentとかUtterancesの設定になるんですが、実はSkill Builderの使い方が未だによくわからないんですよねー。もうリリースされてから半年以上経つと思うんですが、未だにbetaですし。。

そこで新兵器のASK CLIを使います。


# アマゾン公式のサンプルコード、ラジオ放送用node.jsをダウンロード

Lambda関数のサンプルコードを、Githubからダウンロードします。
https://github.com/alexa/skill-sample-nodejs-audio-player


![image.png](https://qiita-image-store.s3.amazonaws.com/0/173392/42a6ed74-44aa-6324-015e-f0cfa936de20.png)

ダウンロードしたらzipを解凍して、
「**single-stream**」フォルダを好きな場所に移動して、好きなエディタで開きます。

以後、便宜的にローカルのパスは~/single-stream/と記載します。

なお、コードの編集はメモ帳でもいいですが、編集対象ファイルが多いので、IDEを使うことをオススメします。Node.jsに対応してるものがいいですね。私は前職のパイセンが勧めてくれたNetBeansを使っております。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/173392/8938e8b6-6e9a-7278-8b5b-b7866162669e.png)


さて、このファイル群を、Readmeに沿って編集してきましょう。
https://github.com/alexa/skill-sample-nodejs-audio-player/blob/mainline/single-stream/README.md

おっとその前にまず、ASK CLIをインストールします。

# ASK CLIのインストール


**ASK CLI**とは、**Alexa Skills Kit Command Line Interface**の略で、ローカルマシンにインストールするコマンドラインツールです。

- 以前のデバッグ時には何十回も手動でやっていた、ローカルでファイル群をzip圧縮してLambdaにアップするという作業を、deployコマンド一発でやってくれる優れもの。
- Deployの際の認証は、AWSで発行するLambda専用のIAMのクレデンシャルを使用する。

あと実は、アプリIDも発行できるようです。
夢が膨らみますね。


[インストール手順](https://developer.amazon.com/ja/docs/smapi/quick-start-alexa-skills-kit-command-line-interface.html)をなぞりながら進めて行きます。
まずMacでターミナルを開き、nodeが入ってるか確認コマンドを実行します。

```
$ node --version
```
「v6.11.4」のように、バージョンが表示されたのでOKです。

次に、[AWSでIAMを作成して、クレデンシャルを発行し、ローカルマシンのとある場所に保存します。](https://developer.amazon.com/ja/docs/smapi/set-up-credentials-for-an-amazon-web-services-account.html)
実はここでハマったので、手順を[こちら](https://qiita.com/sitopp/items/a779da7f7c4e8c25a21b#iam%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E4%BD%9C%E6%88%90%E3%82%AF%E3%83%AC%E3%83%87%E3%83%B3%E3%82%B7%E3%83%A3%E3%83%AB%E4%BD%9C%E6%88%90)に書きました。よろしければご覧ください。


次にnpmを使ってASK CLIをインストールします。
Linuxの場合はsudoをつけろとあるので、Macなのでつけて実行します。

```
$ sudo npm install -g ask-cli
```

次に認証情報を初期化＆書き込みをします。

```
$ ask init
```
以下のようにガイダンスが出ますので、「default」が既にあればそれを選びます。無ければ「Create new profile」を選びます。

```
? Please create a new profile or overwrite the existing profile.
 (Use arrow keys)
  ──────────────
❯ Create new profile 
  ──────────────
  Profile              Associated AWS Profile
  [default]                 ** NULL **
```
次に、lambda関数のデプロイ用に、先ほど「~/.aws/credentials」に書き込んだユーザー名を指定します。（[私の場合は 「default」でした](https://qiita.com/sitopp/items/a779da7f7c4e8c25a21b#iam%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E4%BD%9C%E6%88%90%E3%82%AF%E3%83%AC%E3%83%87%E3%83%B3%E3%82%B7%E3%83%A3%E3%83%AB%E4%BD%9C%E6%88%90)）

```
-------------------- Initialize CLI --------------------
Setting up ask profile: [default]
? Please choose one from the following AWS profiles for skill's Lambda function deployment.
 (Use arrow keys)
❯ default 
  ──────────────
  skip AWS credential for ask-cli 
  ──────────────
```
すると自動的にブラウザに遷移し、Amazon Loginが走ります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/173392/4c30363d-36ab-442b-7590-2a16ccc8ad95.png)
↓
「Sign in was successful. Close this browser and return to the command line interface.」というメッセージが出たら、ブラウザは閉じてOKです。

ターミナル側のジョブも同時に完了してます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/173392/16d2c256-38cc-89c0-8ee9-bdaec9eb0086.png)

さて、先ほどGithubからダウンロードした「single-stream」を置いたディレクトリに移動します。
便宜上、「~/single-stream/」とします。
移動したらnpmをインストールします。

```
$ cd ~/single-stream/
$ (cd lambda && npm install)
$ (cd lambda/src && npm install)
```
ライセンス関連のワーニングが出ますが、動作には影響ないようです。

# ラ。。。の音源のMP3ファイルをゲットする

ここは詳しく書きません！(^^;)(^^;)(^^;)
- MP3ファイル
- httpsアクセスできる状態にしておく
例）https://s3.amazonaws.com/***自分のバケット***/radioTaisou_1.mp4


# Alexa公式サンプルの、ラジオ放送用node.jsをカスタマイズ

ここからがついにSKill本体の編集です。


### 1. `./skill.json`

![image.png](https://qiita-image-store.s3.amazonaws.com/0/173392/17832cd2-a719-0f71-380f-61f6b904cb94.png)
（実際はもっと長いけど省略）

以下の箇所を自分のSkillの設定に合わせて書き換え。


17行目、34行目 
"name": "My Radio",
↓
"name": "Radio Taisou No.1",
6行目、23行目
"summary": "Listen to My Radio, less bla bla bla, more la la la.",
↓
"summary": "Japanese most famous workout dance.",

8〜10行目、25〜27行目
"Alexa, open My Radio",
"Alexa, play My Radio",
"Alexa, ask My Radio to play"
↓
"Alexa, open Rajio taisou dai ichi",
"Alexa, play Rajio taisou dai ichi",
"Alexa, ask Rajio taisou dai ichi to play"

18行目、35行目
          "description": "Listen to My Radio, with less bla bla bla, and more la la la.\n\nMy Radio provides a high quality sound 24/7 with the best music.\n\nTo start, just say \"Alexa, launch My Radio\" or \"Alexa, play my radio\" to start the radio\".\n\nAt anytime, you can stop the radio by saying \"Alexa, stop\"",
↓
          "description": "Let's play japanese most famous workout dance.\n\nTo start, just say \"Alexa, launch My Rajio taisou dai ichi\" or \"Alexa, play my Rajio taisou dai ichi\" to start the radio\".\n\nAt anytime, you can stop the radio by saying \"Alexa, stop\"",


書き換えたら保存。(^^)

### 2. `./lambda/src/audioAssets.js`

![image.png](https://qiita-image-store.s3.amazonaws.com/0/173392/35db5ecf-a3ee-260e-51f7-10e691da4da1.png)

4〜7行目
title: 'My Radio',
subtitle: 'Less bla bla, more la la',
cardContent: "Visit our web site https://www.myradio.com",
url: 'https://audio1.maxi80.com',
↓
title: 'Radio Taisou No.1',
subtitle: 'Less bla bla, more la la',
cardContent: "this skill plays only music. If you're Japanese, you'ld know the dance.",
url: （音源ファイルのURLをここに書く）,
largeImageUrl:（個人用なので特に差し替えない）
smallImageUrl:（個人用なので特に差し替えない）


保存！(^^) 

### 3. `./models/*.json`

my radio
↓
rajio taisou dai ichi


保存！(^^) 

# ローカルでテストする

```
$ cd ~/single-stream/
$ (cd lambda && npm test)
```

![スクリーンショット 2017-10-26 1.24.22.png](https://qiita-image-store.s3.amazonaws.com/0/173392/a801c19e-0401-5851-2dd2-a91e3a2a95fc.png)

盛大なワーニングが。。
「Warning: Application ID is not set」
うーん、おっしゃる通りセットしてないです。手順にもなかったですしね！
App IDとかappIDとかで検索して、どうやらデフォルトが「amzn1.ask.skill.123」らしいことがわかったので、「amzn1.ask.skill.123」でプロジェクト内を検索し、ヒットした箇所を片っ端から直していきます。ここら辺はGithub上の手順書に記載がないので、正しいかどうかわからず、手探りです。



### 4. `./lambda/src/constants.js`

7行目に追加
appId : '自分のスキルのapplication id',
例）
appId : 'amzn1.ask.skill.3696b9a6-a826-472d-944c-b96c364cd798',

「自分のスキルのapplication id」は、[Alexa SkillのDeveloper console](https://developer.amazon.com/edw/home.html)で確認できます。

### 5. `./lambda/test/launch_request.json`

7行目と19行目を
"applicationId": "amzn1.ask.skill.123"
↓
"applicationId": "自分のスキルのapplication id"

### 6. `./lambda/test/next_intent.json`

7行目と21行目を
"applicationId": "amzn1.ask.skill.123"
↓
"applicationId": "自分のスキルのapplication id"

### 7. `./lambda/test/play_intent.json`

7行目と21行目を
"applicationId": "amzn1.ask.skill.123"
↓
"applicationId": "自分のスキルのapplication id"


### 8. `./lambda/test/playback_stopped.json`

12行目を
"applicationId": "amzn1.ask.skill.123"
↓
"applicationId": "自分のスキルのapplication id"


### 9. `./lambda/test/system_exception.json`

6行目を同様に修正。
"applicationId": "amzn1.ask.skill.123"
↓
"applicationId": "自分のスキルのapplication id"

# ローカルでテストする（２回目）

```
$ cd ~/single-stream/
$ (cd lambda && npm test)
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/173392/f7c2505e-46fb-9789-c07b-1901f1fdb196.png)

今度はうまくいきました！！
だいぶ疲れたぞー。。

# デプロイ

ついにこの時がきました！
Macのターミナルから実行します。

```
ask deploy
```

![スクリーンショット 2017-10-27 0.36.35.png](https://qiita-image-store.s3.amazonaws.com/0/173392/8e24216e-a065-7a22-1adc-76ed317ea601.png)


エラーが1箇所出たんですが、ジョブは実行を続けて、deployまで完了しました。
そのエラーっていうのはこれ。
- 1行目、「 Error: Cannot find module'./build/Release/DTraceProviderBindings'」

**DTraceProviderBindingsって何？**

ググったんですが、ちゃんと解決してる例が見当たらず。。
中にはNode.jsのバージョンダウンでなおったという噂もあったり、まだこのCLI自体が出たばっかりなのでバグってるんじゃないか疑惑もあり。後日調べます。。

### Alexa Skills開発用コンソールとAWSのLambdaをチェック

まず、開発用コンソールから。
![スクリーンショット 2017-10-27 0.39.22.png](https://qiita-image-store.s3.amazonaws.com/0/173392/ef49de12-70b5-9571-2cac-bb63ac616479.png)
あれっ、deploy成功したはずなのに、Interaction Modelの中に入ってない。。 ToT 
どういうこと？！

慌てつつ「Back to All skills」リンクを踏んで一覧画面に戻ると、同じアプリ名のものが２個ありました。。。
10月24日と
10月27日。
![スクリーンショット 2017-10-27 0.43.12.png](https://qiita-image-store.s3.amazonaws.com/0/173392/4b22c5b2-6c9e-eb66-d099-745b1587e782.png)

どうやら、ASK CLIでアップしたときに、上書きではなく、新しいAppとして生成してしまったようです。全くそんなつもりは無かったのですが。。
何かパラメタの指定を間違えたのかもしれません。
デバッグで何回もdeployすると思いますが、次回deployするときにも、また新しいIDで生成されたら厄介なので、あとで上書きの方法を調べることにします。が、今は先へ進みます。


次にAWSのダッシュボードでLambda関数ができたかチェックします。
無事にできていました！よかったー(^^)
![スクリーンショット 2017-10-27 0.42.00.png](https://qiita-image-store.s3.amazonaws.com/0/173392/14b54f7a-8be5-8538-8069-82c700ba9f2d.png)


# Lambda関数のテスト

上のキャプチャの画面で、「ask-custom-myradio-default」の字のところをクリックします。

「テストイベントの選択..▼」というプルダウンリストで、「テストイベントの設定」を選ぶと、ポップアップが開きます。

「新しいテストイベントの作成」ラジオボタンを選んだ状態で、「イベントテンプレート」のプルダウンリストから、「Alexa Start Session」を選択します。

![スクリーンショット 2017-10-27 0.52.05.png](https://qiita-image-store.s3.amazonaws.com/0/173392/7250931e-b89c-dd60-e0e1-2213e05c60a9.png)

すると自動的にテストコードが生成されます。
「イベント名」に、適当な名前を入力します。
例）start1
![スクリーンショット 2017-10-27 0.57.51.png](https://qiita-image-store.s3.amazonaws.com/0/173392/6e4116f1-e1a2-b777-6dc1-c95a770ee758.png)

下までスクロールし、「作成」をクリックします。
元の画面に戻ったら、「テスト」ボタンをクリックします。

すると。。
失敗してしまいました orz
<img width="300" src="https://qiita-image-store.s3.amazonaws.com/0/173392/3d3c7a81-7f44-46ae-728a-1c8c04e04ced.png">

「ログ」のところをクリックすると、Cloud Watchのロググループに遷移します。

The applicationIds don't match: amzn1.ask.skill.[unique-value-here]〜
というメッセージが表示されています。

そりゃそうだ、app IDは新しく発行されたから、さっき書いたものと違って当然です。

Deployするたびに新しく生成せず、上書きするようにしなければ、テストもできないことになっちゃうー

とほほほ

もうこのスキルを作り始めてから6日ほど経っており、その間にわがアーセナルはリーグカップでノリッヂにホームで2-1で勝ち、プレミアリーグでもスウォンジーに2-1で勝っており、その前も含めるとなんと9日間で4勝もしており、、、
<img width=400" src="https://img.qoly.jp/media/0100b8af-1824-31e0-78f6-7ea1827eede8">
[ジルーがプシュカシュ賞をとりましたね！おめでとう！おめでとうござりまする！(^^)](http://www.goal.com/jp/%E3%83%8B%E3%83%A5%E3%83%BC%E3%82%B9/%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%94%E3%82%AA%E3%83%B3%E3%82%AD%E3%83%83%E3%82%AF%E5%BC%BE%E3%81%AE%E3%82%B8%E3%83%AB%E3%83%BC%E3%81%8C%E3%83%97%E3%82%B9%E3%82%AB%E3%82%B7%E3%83%A5%E8%B3%9E%E3%82%92%E5%8F%97%E8%B3%9E%E5%90%8C%E5%83%9A%E3%81%A8%E5%AE%B6%E6%97%8F%E3%81%AB%E6%84%9F%E8%AC%9D/mu0npsd5zf7s1u5qkoh74n9zs)


自分も早く結果を出さなければ！


ええい、こうなったら。。
新しくできたスキルから元のスキルにInteraction Modelをコピペしてやるのです！

# 新しく生成されてたスキルから、必要な分をコピー

[Alexa skills kitのデベロッパーコンソール](https://developer.amazon.com/edw/home.html#/)に行き、
スキル一覧から、新旧二つのスキルをブラウザ２面で開き、「Interaction Model」で、以下の２箇所の内容をコピーしました。

- Built-in intents for playback control
　![スクリーンショット 2017-10-30 3.14.29.png](https://qiita-image-store.s3.amazonaws.com/0/173392/f1dc335b-2134-ec2f-7a7b-f551cb65961b.png)
　

- Sample Utterances
　![スクリーンショット 2017-10-30 3.19.04.png](https://qiita-image-store.s3.amazonaws.com/0/173392/fe9b2565-789c-d491-9a27-2f049b865094.png)


そして、「Test」＞「Service Simulator」>「Enter Utterance」に「Alexa, open radio taisou day ichi」と入力し、「Ask Radio taisou No.1」ボタンをクリック！ 

![スクリーンショット 2017-10-30 3.23.21.png](https://qiita-image-store.s3.amazonaws.com/0/173392/4a525a5d-88e3-58fb-be1c-b9f8713ac5d3.png)

JSONが返ってきました！！うおおおお！でけたー！
![スクリーンショット 2017-10-30 3.24.38.png](https://qiita-image-store.s3.amazonaws.com/0/173392/c7ef0703-19f5-ea53-faa0-26b7543b66ab.png)

# 実機テスト

ここまでくればもう実機でも動くはず。そこでMacを離れ、iPhoneを手に持ちます。

## Alexa AppでEnableにする

iPhoneのAlexa Appを開く＞Skill＞your skillを開くと、
開発中でも、同じAmazonアカウントに紐づくものなら一覧に表示されます。

<img width="250" alt="6831C7C1-F262-4571-8D85-A4EDF19E4EB8.png" src="https://qiita-image-store.s3.amazonaws.com/0/173392/43379d97-4c5b-800d-1a5d-aeeb2aed457c.png">

ただし初期値は「Disable」状態なので、Skillの詳細画面で「Enable」にしてやる必要があります。
以下は変更後。
<img width="250" src="https://qiita-image-store.s3.amazonaws.com/0/173392/c2307340-2608-e0b1-52a8-7b7761ad2f6f.png">

## Amazon Echo dotみたいなアレに呼びかけて鳴らす

ここは日本ですので大人の事情でアレと呼んでいます。そのアレに呼びかけると、ちゃんと答えてくれました。

<a href="https://youtu.be/8u7RonzVLZI"><img width="250" src="https://qiita-image-store.s3.amazonaws.com/0/173392/8df8b882-d68f-171e-af0a-52cbbebb7a4f.png"></a>


長かった。。
ASK CLIに関しては釈然としない気持ちでいっぱいです。
が、当初の目的は健康増進のためのスキル作りでしたので、達成と言えるでしょう！
お疲れさまっしたー(^^)



# 残課題

- ASK CLIでdeployするたびに新しいApp IDを生成してしまう不具合の回避方法を調べる。
- DTraceProviderBindingsのエラーの原因を調べる。
- 「体操したよ」とSNSに報告すると、うっすら承認欲求が満たされてモチベーションがわくかもしんない。

今日のところは以上でーす！