Amazon Dash ButtonからSlackに通知してみる

- 年末に注文しておいたAmazon Dash Buttonが届いたので、IoTボタンとして使ってみる
- 調べてみると世間ではピザを注文したりハックしている人が多数いるそうです
- 特にいいアイデアもないので、Slack通知に通知する方法を検証してみる

## Amazon Dash Button とは

<img width="1279" alt="pic1.png" src="https://qiita-image-store.s3.amazonaws.com/0/35325/865d8978-dca7-08a3-4383-5999e67e05d3.png">

- [Amazon Dash Button](https://www.amazon.co.jp/b?node=4752863051)  は、2016年12月にAmazonから販売開始されたガジェット
- 以下が公式の説明だが、要するにボタンを押すと決まった商品を購入できるガジェット

```
ボタンを「ぽちっ」。お気に入りの商品が少なくなったと気づいたら、ボタンを押すだけで商品をお届けします。
Wi-Fiに接続し、iPhoneやAndroidスマートフォンのAmazonショッピングアプリからお気に入りの商品を設定するだけ。
あとは必要な時にDash Buttonを押すだけで注文ができます。新しい買い物スタイルをご体験ください。
```

- 本体価格は500円だが、初回に500円割引きがあり、実質、無料でIoTボタンが購入できる
- Dashボタンのセットアップを途中で中止することで、IoTボタンとしてハックできるみたいで、ピザ注文したり、コーヒーいれたりいろいろとあるみたい
  - [Amazon Dash Buttonをハックしてワンプッシュで宅配ピザを注文したりコーヒーを淹れたりタクシーを呼んだりする改造例まとめ@Gigazine](http://gigazine.net/news/20161209-amazon-dash-button-hack/)

## Amazon Dash Button の仕組み

- Dashボタンの動作の仕組みは以下のページを参考にしました
  - [Amazon Dash Buttonの仕組みとハック@Qiita](http://qiita.com/dkawashi/items/e6621c4b712b509c73ec)
- 上記ページによるとDashボタンはボタンを押すと以下の仕組みで動作する
  1. 電源ON
  2. 設定しておいたWi-Fiに接続
  3. DHCPでIP取得
  4. 商品注文リクエスト
- Dashボタンをハックする仕組みとしては、同一NW内にある端末（Macbook etc）にて    
DashボタンのARP要求（上記の3の部分）を監視し、検知したらアクションを実施する流れ
- Dashボタンの初期セットアップを途中でやめることで3までが実行されるが、   
セットアップを最後まで設定してしまうとDashボタンを押すために商品が注文されるので注意してください

## Amazon Dash Button をハックしてみる

- Dashボタンのハックを試した環境は以下になります
    - Amazon Dash Button： [サントリー天然水 Dash Button](https://www.amazon.co.jp/Amazon-JK29LP-%E3%82%B5%E3%83%B3%E3%83%88%E3%83%AA%E3%83%BC%E5%A4%A9%E7%84%B6%E6%B0%B4-Dash-Button/dp/B01L2WOYT2)
    - Macbook pro： macOS Sierra 10.12.2
        - nodebrew 0.9.6
        - node 7.4.0
        - npm 4.0.5

### Dashボタンのセットアップ

- iPhone版, Android版のAmazonショッピングアプリをダウンロードして、初期セットアップを実施してください
- 初期セットアップは、[注文する商品を選択する画面]で必ずキャンセルを実施してください
- 詳細については、他の方の記事を参考にしてください
  - [Amazon Dash Buttonの仕組みとハック@Qiita](http://qiita.com/dkawashi/items/e6621c4b712b509c73ec)

### Macbook (Server側)のセットアップ

- 上記のDashボタンのセットアップ中に接続した同一のwifiに接続する
- MacbookでARPを検知監視し、DashボタンのMACアドレスとから要求があった場合にスクリプトを動作させる
- ライブラリとしては、nodejs製だけでなく、ruby製など色々と方法はあるらしいが、    
参考にしているページが [dasher](https://github.com/maddox/dasher) を利用しているので、今回もそれを利用する
  - dasher: nodejs製。libpcapを利用し、パケット送信を監視し、HTTPリクエストを放つ事ができる
- ローカル環境にdasherをインストールする

```bash
% git clone https://github.com/maddox/dasher.git
% cd dasher
% dasher git:(master) npm install

> socketwatcher@0.3.0 install /Users/daicho/work/dasher/node_modules/socketwatcher
> node-gyp rebuild

xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance

xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance

  CXX(target) Release/obj.target/socketwatcher/socket_watcher.o
../socket_watcher.cpp:104:37: warning: 'NewInstance' is deprecated [-Wdeprecated-declarations]
    info.GetReturnValue().Set(cons->NewInstance());
                                    ^
/Users/daicho/.node-gyp/7.4.0/include/node/v8.h:3292:52: note: 'NewInstance' has been explicitly marked deprecated here
  V8_DEPRECATED("Use maybe version", Local<Object> NewInstance() const);
                                                   ^
1 warning generated.
  SOLINK_MODULE(target) Release/socketwatcher.node

> pcap@2.0.0 install /Users/daicho/work/dasher/node_modules/pcap
> node-gyp rebuild

xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance

xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance

  CXX(target) Release/obj.target/pcap_binding/pcap_binding.o
  CXX(target) Release/obj.target/pcap_binding/pcap_session.o
../pcap_session.cc:46:37: warning: 'NewInstance' is deprecated [-Wdeprecated-declarations]
    info.GetReturnValue().Set(cons->NewInstance());
                                    ^
/Users/daicho/.node-gyp/7.4.0/include/node/v8.h:3292:52: note: 'NewInstance' has been explicitly marked deprecated here
  V8_DEPRECATED("Use maybe version", Local<Object> NewInstance() const);
                                                   ^
1 warning generated.
  SOLINK_MODULE(target) Release/pcap_binding.node
dasher@1.1.1 /Users/daicho/work/dasher
└─┬ node-dash-button@0.6.1 
  └─┬ pcap@2.0.0  (git+https://github.com/mranney/node_pcap.git#d920204745c8b00ef4b7a3fe27d902b263cdb70f)
    └── socketwatcher@0.3.0 
```

- dashボタンのMACアドレスを特定するために以下のスクリプトを実行後、Dashボタンを押す

```bash
% dasher git:(master) ./script/find_button 
Password:
Watching for arp & udp requests on your local network, please try to press your dash now
Dash buttons should appear as manufactured by 'Amazon Technologies Inc.' 
Possible dash hardware address detected: 38:e0:8e:07:75:9b Manufacturer: Mitsubishi Electric Corporation Protocol: arp
Possible dash hardware address detected: 78:4f:43:5e:bf:30 Manufacturer: unknown Protocol: arp
Possible dash hardware address detected: 38:e0:8e:07:75:9b Manufacturer: Mitsubishi Electric Corporation Protocol: arp
Possible dash hardware address detected: 38:e0:8e:07:75:9b Manufacturer: Mitsubishi Electric Corporation Protocol: arp
Possible dash hardware address detected: 38:e0:8e:07:75:9b Manufacturer: Mitsubishi Electric Corporation Protocol: arp
Possible dash hardware address detected: 38:e0:8e:07:75:9b Manufacturer: Mitsubishi Electric Corporation Protocol: arp
Possible dash hardware address detected: 38:e0:8e:07:75:9b Manufacturer: Mitsubishi Electric Corporation Protocol: arp
```

### SlackのIntegrationを使ってDashボタンからSlackに通知してみる

- SlackのIntegrationから[Incoming WebHooks]を追加し、Webhook URLを確認する
<img width="969" alt="pic2.png" src="https://qiita-image-store.s3.amazonaws.com/0/35325/873a5baa-b5ec-387b-a428-1e808a3a9e99.png">

  - 例：https://hooks.slack.com/services/xxxxxx/xxxxxx/xxxxxx
- 上記で確認した[DashボタンのMACアドレス]、[Webhook URL]を設定ファイルに記載し、起動する

```bash
% dasher git:(master) vim config/config.json
{"buttons":[
  {
    "name" : "test 天然水",
    "address": "38:e0:8e:07:75:9b",
    "url": "https://hooks.slack.com/services/xxxxxx/xxxxxx/xxxxxx",
    "method": "POST",
    "json": true,
    "body": {"text":"Hello, World from Amazon Dash Button!!!"}
  }
]}
% dasher git:(master) sudo npm run start
Password:

> dasher@1.1.1 start /Users/daicho/work/dasher
> node app.js

[2017-01-14T14:54:09.452Z] test 天然水 added.
[2017-01-14T14:54:25.191Z] test 天然水 pressed.
[2017-01-14T14:54:32.269Z] test 天然水 pressed.
[2017-01-14T14:54:40.049Z] test 天然水 pressed.
[2017-01-14T14:54:45.171Z] test 天然水 pressed.
[2017-01-14T14:54:52.138Z] test 天然水 pressed.
[2017-01-14T14:54:59.976Z] test 天然水 pressed.
```
- Slackを確認すると通知できているのが確認できる
<img width="1050" alt="pic3.png" src="https://qiita-image-store.s3.amazonaws.com/0/35325/7fe2e8c9-5a4c-98b7-ad65-ebe002cf651d.png">

### Amazon Dash Button から午前半休メールを出してみる

上記のSlackの例では、SlackのIntegrationで通知したが、IFTTTと連携すると別のサービスと連携しやすい。
次はIFTTTを使って、Gmailと連携することで、Dashボタンで午前半休メールを送れるようにする 

- [IFTTT](https://ifttt.com/discover)にログインし、「New Applet」を選択する ※ アカウントがない場合は事前に作成する
<img width="1413" alt="スクリーンショット 2017-01-15 22.21.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/35325/81ed60bf-7be6-d2bf-1d1a-7e04a1a67c63.png">
- 「this」を選択する
<img width="1268" alt="スクリーンショット 2017-01-15 22.22.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/35325/b7552ded-946c-a8af-9858-a815055367c6.png">
- 「Maker」で検索し、「maker」を選択する
<img width="681" alt="スクリーンショット 2017-01-15 22.24.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/35325/f722d8cc-82fc-e35a-cac0-2fd98d1b0c55.png">
- [Receive a web request]を選択し、イベント名に適当な「button_pressed」と入力し、[Create trigger]を選択する
<img width="522" alt="スクリーンショット 2017-01-15 22.26.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/35325/68065c80-56f5-c955-487e-e8acaea1f0dc.png">
- 「that」を選択する
<img width="1263" alt="スクリーンショット 2017-01-15 22.27.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/35325/65259b16-6eb3-bf87-d67d-ca78f90a3637.png">
- 「gmail」で検索し、「gmail」を選択する
<img width="701" alt="スクリーンショット 2017-01-15 22.28.28.png" src="https://qiita-image-store.s3.amazonaws.com/0/35325/644a584d-cdab-0a9f-16e1-7386f121e8a8.png">
- [Send an email]を選択し、「メールアドレス」「件名」「本文」を半休メールぽく記載する
  - Subject: ```{{OccurredAt}}：名前 午前半休```
  - Body: 
    ```
    お疲れ様です。名前です。<br><br>
    いつもお世話になっております。 本日の出社ですが、<br>
    {{Value1}}のため、午前半休を取得します。<br><br>
    お忙しい中、誠に申し訳ございませんが、<br>
    何卒よろしくお願いします。
    ```
- [Makerの設定](https://ifttt.com/services/maker/settings)より、Makerのキーを確認し、config.jsonを以下のように編集後に実行する

```bash
% dasher git:(master) vim config/config.json
{"buttons":[
  {
    "name": "test event",
    "address": "38:e0:8e:07:75:9b",
    "url": "https://maker.ifttt.com/trigger/button_pressed/with/key/[Makerのキー]",
    "method": "POST",
    "json": true,
    "body": {"value1": "昨晩からのひどい腹痛"}
  }
]}
% config git:(master) ✗ sudo npm run start

> dasher@1.1.1 start /Users/daicho/work/dasher
> node app.js

[2017-01-15T14:06:23.854Z] test event added.
[2017-01-15T14:06:41.440Z] test event pressed.
[2017-01-15T14:07:04.738Z] test event pressed.
```
- 指定したメールアドレスに午前半休メールがきていることが確認できる
<img width="946" alt="スクリーンショット 2017-01-15 23.16.09.png" src="https://qiita-image-store.s3.amazonaws.com/0/35325/40bd0d61-fd69-9a31-b5cc-5ecbfb5c2169.png">

## まとめ

- IFTTTを利用することでまったくプログラミングなしで、IoTボタンとして簡単にハックができ、アイデア次第で使えそう
- ただ、自宅サーバーとか持っている人とかなら別だけども、ARPを監視するPCを常に動作させるのはめんどくさそう