2021年でも最強IoT物理ボタンなAmazonDashButtonで遊ぼう  〜セットアップ方法と、Pixela APIを叩く実例〜

2024-11-01追記

この記事を書いてから、3年ほど家庭で活用しています。
便利ですね。

たまにトラブるので、[amazon-dashトラブルシューティング](https://qiita.com/watahari/items/372fbbe2f1b7f2ce011a)を書きました。
ご参考まで。

追記ここまで

---

2021年にもなって……と思うかもしれませんが、 実際のところ今でもAmazon Dash Button は、**何かをトリガーする物理インタフェース**として、**「早い・安い・美味い」の三拍子が揃ったガジェット**であることは言うまでもありません。
逆に言えば2021年にもなって「ポチっと押したら何かが起こるIoTデバイス」がこんなに高価なモノばかり[^1]だとは、、といったところでしょう。

この記事では、Amazon Dash Button を、単なる物理インタフェースのスイッチトリガーとして利用する方法と、私が実際に利用している実例(Pixe.laへの記録)を紹介します。

# TL;DR

 * ヤフオクかメルカリでAmazon Dash Buttonを買う
 * ルータで、予め特定Amazonサーバへの接続を遮断する**（しないと文鎮化する）**
 * Amazon Dash ButtonのWi−Fi設定には、https://gist.github.com/fffonion/d4960503ff6782640286163d47a30080 のスクリプトを一部修正して利用した
 * Raspberry PiにNekmo/amazon-dashをインストールし、適切な設定ファイルを書いた
 * ボタンを押したことをトリガーにPixela APIを叩いてみた
 * たのしい！


# Amazon Dash Button とは？

![61PWrWW-pCL._AC_SL250_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602340/d35bc82b-7032-e249-3e08-51726706f9e9.jpeg)画像引用元：Amazon.co.jp

Amazon Dash Button（アマゾンダッシュボタン）とは、押すと特定の商品がAmazonで発注されるボタンです。2019/08/31にサービスを終了しており、**2021年現在、不用意に押すと文鎮化**します（回避方法は後ほど詳述します）。

しかし、世の中には素晴らしいクリエイター達により、延命と活用の手段が模索されています。

なお、「AWS IoT ボタン」という2,500円のボタンは未だ売っている(かも?) [^2] ようですが、これをホイホイ買える石油王の方はここで離脱していただいて結構です。

# 調達方法

既に終売となっています。この記事を読んで興味が湧いたのであれば、今すぐヤフオク・メルカリ等をチェックしてください。私は1年ほど前にメルカリで92円/個で購入しましたが、いまでも粘れば100〜500円程度で購入できると思います。[^3]

![IMG_4614.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602340/a9811d00-9ece-8033-6a57-04ffacabd100.jpeg)



# 利用方法　
### (0) 方針

要は↓を使う。

 * https://github.com/Nekmo/amazon-dash
 * https://docs.nekmo.org/amazon-dash/

ドキュメントのなかの "Amazon-dash is still alive" に感動した。

必要なもの。

 * Amazon Dash Button
 * ご家庭で余っているRaspberry Pi
 * Mac (以下、MacOSでの例となります)

### (1) セットアップと準備

ここからは、Amazon Dash Buttonのセットアップをしていく。
基本は上記の https://docs.nekmo.org/amazon-dash/ のドキュメントに沿っている。

#### (1-1) Amazon Dash Buttonが文鎮化しないようにする

2020年(2019年末?)から、Amazon Dash Button をインターネットにつなぐと、Amazonサーバにより文鎮化(bricked)されるようになってしまったらしい。[^4] [^5] [^6] [^7]
つまり、**以下の手順をやらないと、数百円の文鎮（ゴミ）を手に入れたことになる**。

文鎮化を防ぐためには、インターネットに繋がない、あるいはインターネットにつながっても特定のAmazonサーバに接続しないようにする必要がある。

まず、Wi-Fiルータで下記の5パターンのホストへの接続をブロックする。[^4]

 * `dash-button-na-aws-opf.amazon.com`
 * `0.amazon.pool.ntp.org`
 * `1.amazon.pool.ntp.org`
 * `2.amazon.pool.ntp.org`
 * `3.amazon.pool.ntp.org`

我が家の場合ASUS RT-AX86Uを利用しているため、「ファイアウォール」の「URL フィルター」から、これらをブロックした。
「AiProtection」配下の「ペアレンタルコントロール」で「時間設定」よりMacアドレス指定でのブロックも可能だが、この段階では Amazon Dash Button の Macアドレスが不明であるため、この手段とした。

![スクリーンショット 2020-09-28 15.10.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602340/41bfaece-912a-65a1-6115-cd56a8c188dc.png)


#### (1-2) Amazon Dash Button にWi-Fi設定をセットアップする

既に Amazon Dash Button 自体がEOLのため、Amazonアプリを利用したセットアップは利用できない。[^8]

https://docs.nekmo.org/amazon-dash/rescue.html#configure-wifi によればamazon-dashをインストールして`amazon-dash configure`でよいはずだが、これはうまくいかなかった。
（MacOS Xにはipコマンドがないため。Homebrewでiproute2macをインストールしてみたが、iproute2macでは無線LANカードを示すwlから始めるデバイスは返ってこない＝en0とかlo0等の伝統的名称だけが返ってくるため、amazon-dash configureの処理がうまく動かないようだった。）

FYI、コマンドがない状態でamazon-dash configureすると、下記のようにエラーになる。

```bash:
Is the blue light flashing? [y/N]: y
Traceback (most recent call last):
  File "/usr/local/var/pyenv/versions/3.7.2/bin/amazon-dash", line 6, in <module>
    catch(cli)()
  File "/usr/local/var/pyenv/versions/3.7.2/lib/python3.7/site-packages/amazon_dash/exceptions.py", line 103, in wrap
    return fn(*args, **kwargs)
  File "/usr/local/var/pyenv/versions/3.7.2/lib/python3.7/site-packages/click/core.py", line 829, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/var/pyenv/versions/3.7.2/lib/python3.7/site-packages/click/core.py", line 782, in main
    rv = self.invoke(ctx)
  File "/usr/local/var/pyenv/versions/3.7.2/lib/python3.7/site-packages/click/core.py", line 1259, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/local/var/pyenv/versions/3.7.2/lib/python3.7/site-packages/click/core.py", line 1066, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/var/pyenv/versions/3.7.2/lib/python3.7/site-packages/click/core.py", line 610, in invoke
    return callback(*args, **kwargs)
  File "/usr/local/var/pyenv/versions/3.7.2/lib/python3.7/site-packages/amazon_dash/management.py", line 164, in configure
    enable_wifi()
  File "/usr/local/var/pyenv/versions/3.7.2/lib/python3.7/site-packages/amazon_dash/wifi.py", line 136, in enable_wifi
    w = wifi_class()
  File "/usr/local/var/pyenv/versions/3.7.2/lib/python3.7/site-packages/amazon_dash/wifi.py", line 60, in __init__
    self.device = device or next(self.get_wireless_devices(), None)
  File "/usr/local/var/pyenv/versions/3.7.2/lib/python3.7/site-packages/amazon_dash/wifi.py", line 65, in get_wireless_devices
    devices = get_cmd_output(['ip', 'a'])
  File "/usr/local/var/pyenv/versions/3.7.2/lib/python3.7/site-packages/amazon_dash/wifi.py", line 25, in get_cmd_output
    output = subprocess.check_output(cmd)
  File "/usr/local/var/pyenv/versions/3.7.2/lib/python3.7/subprocess.py", line 395, in check_output
    **kwargs).stdout
  File "/usr/local/var/pyenv/versions/3.7.2/lib/python3.7/subprocess.py", line 472, in run
    with Popen(*popenargs, **kwargs) as process:
  File "/usr/local/var/pyenv/versions/3.7.2/lib/python3.7/subprocess.py", line 775, in __init__
    restore_signals, start_new_session)
  File "/usr/local/var/pyenv/versions/3.7.2/lib/python3.7/subprocess.py", line 1522, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'ip': 'ip'
```

ではどうするか？
https://gist.github.com/fffonion/d4960503ff6782640286163d47a30080 を使うとうまくいく。ただし、[gist のコメント](https://gist.github.com/fffonion/d4960503ff6782640286163d47a30080#gistcomment-3116629)にあるとおり、**修正が必要**。

```diff
- if 'Amazon Dash' in r.content.decode('utf-8'):
+ if 'Amazon Dash' in r.content:
```
```diff
-content = r.content.decode('utf-8')
+content = r.content
```

修正含め、下記のような手順となる。

```shell
$ curl "https://gist.githubusercontent.com/fffonion/d4960503ff6782640286163d47a30080/raw/6f7e00536fbcd7435a3d48e260881a805ae26fd5/setup-dashbutton.py" > setup-dashbutton.py
$ cp -r setup-dashbutton.py setup-dashbutton.py.original
$ vim setup-dashbutton.py
$ diff setup-dashbutton.py{,.original}
18c18
<             if 'Amazon Dash' in r.content.decode('utf-8'):
---
>             if 'Amazon Dash' in r.content:
25c25
<     content = r.content.decode('utf-8')
---
>     content = r.content

# ここからは対話型となるので、指示に従っていけばいい。
# ざっくりいうと
#  * Amazon Dash Button に設定したいWi-Fi（つまり家のWi-Fi）のSSIDとパスワードを引数にスクリプトを実行
#  * 設定したい Amazon Dash Button のボタンを5秒押し、青く点滅させる
#  * Macの接続Wi-FiをAmazon ConfigureMeに変更
#  * 後は待っていれば、Amazon Dash ButtonにWi-Fi設定される
$ python setup-dashbutton.py <Wi-FiのSSID> <Wi-Fiのパスワード>
* Long press the dash button until LED light blinks in blue
* Connect to Wifi with SSID "Amazon ConfigureMe"
* Waiting for connection...
+ Connected!
* Serial: XXXXXXXXXXX, MAC: XXXXXXXXXXX, Firmware: 40018220_JP, Battery: 77
* Configure Dash button to connect to "<Wi-FiのSSID>"
http://192.168.0.1/?amzn_ssid=<Wi-FiのSSID>&amzn_pw=<Wi-Fiのパスワード>
+ Dash button configured!
```
簡単で素晴らしい！
（十数回に1回くらい？はMac側が勝手にWi-Fi切り替えてしまって失敗するけれど、基本スムーズに設定可能で素晴らしかった）

### (2) Raspberry Piにamazon-dashをdaemonとして動作させる

ここまでで、Amazon Dash Buttonを押すと、自宅のWi-Fiに接続するようになった。
とはいえ実際にはAmazon側がEOLになっているし、Amazonと接続できないようにルータ側で設定したので、Amazon Dash Buttonの実行としては失敗する。

ところが、Amazonサーバへの実行の直前、無線LANルータのIPアドレスに対応したMACアドレスを取得しようとする**ARPパケットを送出する[^9] [^10]ので、これを同じWi-Fi内でキャプチャしておけば「Amazon Dash Button が押された」というイベントを検知することができる**。上述の https://github.com/Nekmo/amazon-dash はこれをやってくれるようだ。

ここからは、LANにWi-FiでつながっているRaspberry Pi(24/365で放置稼働)にて、amazon-dashをdaemonとして起動させておき、先程セットアップした Amazon Dash Button が押されたときにPixelaのAPIを叩くことを目標にしていく。

#### (2-1) インストール

https://docs.nekmo.org/amazon-dash/installation.html

`ssh pi@raspberrypi.local` なりVNCなりでRaspberry Piにログインして、下記を実施する。

```shell
$ sudo apt install tcpdump
$ sudo pip3 install -U amazon_dash
$ sudo python3 -m amazon_dash.install
$ amazon-dash --version
You are running Amazon-dash v1.4.0 using Python 3.7.3.
This is the latest release
Installation path: /usr/local/lib/python3.7/dist-packages/amazon_dash
Current path: /home/pi
```

とりあえずインストール完了。

#### (2-2) Amazon Dash Button の MACアドレスを特定する。

(1-2)でWi-Fi設定をしたときにしれっと表示されている。

```
* Serial: XXXXXXXXXXX, MAC: XXXXXXXXXXX, Firmware: 40018220_JP, Battery: 77
```
これをメモすればいい。

amazon-dashのdiscoveryモードでも特定が可能。

```
$ sudo amazon-dash discovery
Welcome to Amazon-dash v1.4.0 using Python 3.7.3
December 31 is the last day to block requests from your Amazon-dash 
buttons to Amazon servers. In 2020 your buttons can be bricked in an 
update from Amazon servers.
The discovery command lists the devices that are connected in your 
network. Each device will only be listed once. After executing this 
command wait approximately 10 seconds before pressing the Amazon Dash 
button. After pressing the button, the Mac address of the button will 
immediately appear on the screen. Remember the address to be able to 
create the configuration file.
<他のWi-Fi機器のMACアドレス>
<他のWi-Fi機器のMACアドレス>
<他のWi-Fi機器のMACアドレス>
<他のWi-Fi機器のMACアドレス>
00:00:5E:00:53:01 (Amazon Device)
<他のWi-Fi機器のMACアドレス>
^C
```

先程は`MAC:00005E005301`のような表示だったが、dicoveryモードではより見慣れた`00:00:5E:00:53:01`のような表記で表示されている。
（なお、上記例はいずれの値もダミーである）

#### (2-3) SystemdでDaemonとして起動しておく

https://docs.nekmo.org/amazon-dash/usage.html#systemd

ここはドキュメントのままでOK。

```
$ sudo systemctl start amazon-dash
$ sudo systemctl status amazon-dash
● amazon-dash.service - Amazon Dash service
   Loaded: loaded (/usr/lib/systemd/system/amazon-dash.service; disabled; vendor preset: enabled)
   Active: active (running) since Tue 2020-09-29 00:58:56 JST; 5s ago
 Main PID: 1079 (amazon-dash)
   CGroup: /system.slice/amazon-dash.service
           └─1079 /usr/bin/python3 /usr/local/bin/amazon-dash run --config /etc/amazon-dash.yml

 9月 29 00:58:56 raspberrypi systemd[1]: Started Amazon Dash service.
 9月 29 00:58:57 raspberrypi env[1079]: Welcome to Amazon-dash v1.4.0 using Python 3.7.3
 9月 29 00:58:57 raspberrypi env[1079]: December 31 is the last day to block requests from your Amazon-dash buttons to Amazon servers. In 2020 your buttons can be bricked in an update from Amazon servers.
 9月 29 00:58:57 raspberrypi env[1079]: Listening for events. Amazon-dash will execute the events associated with the registered buttons.
```

#### (2-4) ボタンが押されたときの挙動を設定ファイルに定義

https://docs.nekmo.org/amazon-dash/config_file.html

インストールした時点で `/etc/amazon-dash.yml` にダミー設定ファイルが配置されている。
とりあえずバックアップしつつ、編集していく。

```
$ sudo cp /etc/amazon-dash.yml{,.original}
$ sudo vim /etc/amazon-dash.yml
$ sudo cat /etc/amazon-dash.yml
# amazon-dash.yml
# ---------------
settings:
  delay: 10
devices:
  b4:7c:9c:a2:45:11:
    name: pixela-increment-sample
    url: 'https://pixe.la/v1/users/<userid>/graphs/<graph>/increment'
    method: put
    headers: {"X-USER-TOKEN": "<TOKEN>", "Content-Length":"0"}
    content-type: json
```

ここでは、（簡単に叩けて楽しいので大好きな）PixelaのインクリメントAPIを叩くようにした[^11]。
ここまで完成したら、amazon-dashをrestartして読み込ませておく。

```
sudo systemctl restart amazon-dash
```

#### (2-4) ボタンを押す

いよいよ Amazon Dash Button をポチッ！
LEDが赤点滅を繰り返すが、これは正常（先述のとおりルータでAmazonサーバとの疎通を遮断しているため）。

無事、pixe.laのグラフで、今日のPixelが1つincrementしたことを確認しよう。

![スクリーンショット 2021-08-30 4.06.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602340/f3c1ddd8-bd8f-b220-ad0b-5b7ccbfe06c2.png)


無事、今日もお酒を1杯飲んだことを飲酒グラフに記録できたのであった。[^12]



#### (2-5) ラズパイ再起動後にも立ち上がるようにしておく

こういうのは忘れないうちにやっておくに限る。

```
sudo systemctl enable amazon-dash
```

# まとめ

皆さんも是非、2021年の今こそ、Amazon Dash Buttonで遊びましょう！！！

Nekmo/amazon-dashがかなり柔軟で、IFTTT等と組み合わせれば可能性は無限大です。
そのうち、実際の利用例を活用する記事を書ければいいなと思っています。

![81D31793-301C-4FCE-9BF5-45EF6AF74A8B_1_105_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602340/05149e82-a023-b9bd-bb34-2579b086e9ac.jpeg)



## 参考にさせていただいたドキュメント
https://github.com/Nekmo/amazon-dash

https://docs.nekmo.org/amazon-dash/

https://qiita.com/eholic/items/3c65544a38315309363b

https://blog.christophermullins.com/2019/12/20/rescue-your-amazon-dash-buttons/

https://zmzlz.blogspot.com/2020/01/amazon-dash.html

https://xtech.nikkei.com/dm/atcl/feature/15/041100088/041800003/


[^1]: AWS IoT ボタンが2500円、ReButtonが2500円、MESHが6000円、どれもオモチャとしては高い。。。百均のBluetoothシャッターボタンが300円が比較的お手頃そうだが、近所のダイソーで品切れだった。

[^2]: 執筆現在は売り切れなので、本当に売っているかは不明 https://aws.amazon.com/jp/iotbutton/

[^3]: 安いまとめ買いを狙ってたので、そういうのを狙うといいです。もともとの定価は500円（ただし500円分商品注文可能なので実質タダ）ですが、終売のため流通数は少ない。殻割りすれば電池交換できますが、どうせなら一生分確保しておきたいですね。

[^4]: https://docs.nekmo.org/amazon-dash/block_connections.html

[^5]: https://blog.christophermullins.com/2019/12/20/rescue-your-amazon-dash-buttons/

[^6]: https://zmzlz.blogspot.com/2020/01/amazon-dash.html

[^7]: お仕事で公開APIクローズするときに四苦八苦したので、文鎮化したいAmazonの気持ちはよく分かる。。。

[^8]: EOL前は、Amazonアプリでセットアップの途中で止める（Wi-Fi設定後に、商品選択の手前で止める)手順が会った模様。

[^9]: https://xtech.nikkei.com/dm/atcl/feature/15/041100088/041800003/

[^10]: https://github.com/Nekmo/amazon-dash/blob/ca2829aae2072be64d2e84dcb5c8acb2979d15fa/amazon_dash/scan.py#L26

[^11]: https://docs.pixe.la/entry/increment-pixel

[^12]: 筆者の飲酒量グラフ　https://pixe.la/v1/users/watahari/graphs/sake.html