Amazon Dash ButtonをただのIoTボタンとして使う

2016年12月5日より、[Amazon　Dash Button](https://www.amazon.co.jp/b/?ie=UTF8&node=4752863051&ref=bb1_dascb5d4f8b6886&pf_rd_r=EH5T0N8B3Y4FYP9CH61H&pf_rd_p=9f4c80bf-b10e-44ca-bee3-0e6eb629c44d)で利用できるようになりました。これは、ボタンを押すだけでAmazonから一部の商品(天然水, ひげそりなど)が購入できるようになるという端末です。

今回はこのAmazon Dash Button(※ 以降ボタンと呼びます)を、押したらHTTPリクエストが飛ぶボタンとして利用し、おうちハックなどで利用できるようにしていきます。

とりあえずボタンを押したらSlackにWehbook飛ばすくらいまでやりました。
<img src="https://media.giphy.com/media/3oriNSrvaWGrdjCpiw/giphy.gif">

# ボタンの仕組み

ボタンは電源がオフされているので、以下のような順序で動きます。

1. 電源ON
2. 同時に設定されたWi-Fiネットワークに接続
3. IP重複検知のためにARPプローブ送信
4. IPが重複していたらIP再設定?(自信ない)
5. Amazonへ購入処理の実行(HTTP???)

参考 : [How I Hacked Amazon’s $5 WiFi Button to track Baby Data – Medium](https://medium.com/@edwardbenson/how-i-hacked-amazon-s-5-wifi-button-to-track-baby-data-794214b0bdd8)

# 本題 : Amazonの注文を行わずにIoTボタンとして使う方法

今回は同一ネットワーク内にいるサーバが、ボタンが上記\#3のARPプローブを送ってきたことを検知して、それをフックにHTTPリクエストを送るというものです。
簡単なnode.jsが動けばいいのでRaspberryPiとかの小型マシンで十分です。

ボタンをセットアップし、次にボタン押下イベントを拾うサーバアプリケーション(dasher)を設定していきます。

## ボタンセットアップ

ほぼ、[Amazonのサイトに記載されたセットアップ方法](https://www.amazon.co.jp/gp/help/customer/display.html/ref=amb_link_1?ie=UTF8&nodeId=201746340&pf_rd_m=AN1VRQENFRJN5&pf_rd_s=merchandised-search-leftnav&pf_rd_r=TSXWXYC79BGFWDKJCQD3&pf_rd_r=TSXWXYC79BGFWDKJCQD3&pf_rd_t=101&pf_rd_p=cf13d39a-e3f0-4ff4-a61f-037a02d68c1d&pf_rd_p=cf13d39a-e3f0-4ff4-a61f-037a02d68c1d&pf_rd_i=4752863051)の通りでいいのですが、一点だけ気をつけないといけないことが。<font color="red">**セットアップを最後まで完了させない**</font>ことです。

具体的には、Dash ButtonのWi-Fi設定を行った後に、ボタン押下時に**注文する商品を選択する画面でキャンセル**しましょう。

<img src="https://qiita-image-store.s3.amazonaws.com/0/20434/11705326-be6a-7ba7-1b93-8ae806ccd01a.png" width="200">

ここで商品を選択してしまうと、ただのIoTボタンとして使いたいのに毎回商品を頼んでしまうことになります。誤って大量に洗濯洗剤が届いてしまうなどの問題が起きぬよう…
ここで右上の `☓` をタップしてキャンセルしましょう。
キャンセルしていいのか確認するダイアログが出ますが華麗に無視で良いです。

最終的には以下の画像のように `セットアップを完了するにはアイテムを選択してください` と表示される状態になればOKです。

<img src="https://qiita-image-store.s3.amazonaws.com/0/20434/b1e4f602-ad50-c6a8-6214-15acd588c9a9.png" width="200">

## dasherでボタン押下イベントをフックする

ボタンと同一ネットワーク内にあるPCないしはサーバで[dasher](https://github.com/maddox/dasher)を動かすことで、
ボタン押下時に任意のサーバにHTTPリクエストを飛ばすことが出来るようになります。

### dasher

libpcapを利用してボタンのMACアドレスからのパケット送信を捉え、
configに書かれたパスに対してHTTPリクエストを投げるというものです。
node.js製です。

実態は[node-dash-button](https://github.com/hortinstein/node-dash-button)のラッパーです。node-dash-buttonの `detected` イベントにHTTPリクエストを放つfunctionを渡しているということになります。

### ボタンのMACアドレスを知る

dasherのREADMEに書いてあるとおりです。
dasherをcloneし、 以下の通り実行しつつボタンを押すと検出してくれます。
下記の `ee:ee:ee:ee:ee:ee` がボタンのMACアドレスとなります。
Manufacturerが `Amazon Technologies Inc.` となることを期待しているようですが、
私が実行したときは以下のように `unknown` となりました。

```
% ./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: ee:ee:ee:ee:ee:ee Manufacturer: unknown Protocol: udp
Possible dash hardware address detected: ee:ee:ee:ee:ee:ee Manufacturer: unknown Protocol: arp
```

## dasherを起動する

取得したMACアドレスと送りたいHTTPリクエストの情報を設定に書きます。
今回はSlackのIncoming Webhook URLを利用しました。

```json:config/config.json
{"buttons":[
  {
    "name" : "test 天然水",
    "address": "34:d2:70:b5:cf:ee",
    "url": "https://hooks.slack.com/services/xxxxxxxxxx/yyyyyyyyy/1234567890",
    "method": "POST",
    "json": true,
    "body": {"text":"Hello, World from Amazon Dash Button!!!"}
  }
]}
```

そして起動します。
設定ファイルに定義したボタンの押下を監視するようになります。

```

%  npm start

> dasher@1.1.1 start /Users/jun/Projects/github/dasher
> node app.js

[2016-12-05T16:39:33.654Z] test 天然水 added.
```

そのうえで、ボタンを押すと期待したとおりにHTTPリクエストが飛ぶことを確認できるはずです。
最後インジケータランプが赤く光りますが、セットアップ時に購入対象商品を選ばなかったことでボタンを押しても何も買えなかったということになり、失敗したとのインジケータが表示されます。
よって、特に気にしなくていいはずです。

# あわせ技

半年くらい前に書いた以下Lambda functionをAPI Gateway経由で叩けば、
Amazon Dash Buttonで対応していない商品もボタンで買えるようになるはず！！！

https://github.com/jsoizo/amazon-jp-auto-orderer
http://qiita.com/jsoizo/items/4150e992cae74bea8334