「子供のオムツを替えたタイミングを記録する」ために Amazon Dash Button を使って「うんちダッシュボダン」を作ったので、その作り方について。
汎用ボタンとしての Amazon Dash Button
Amazon Dash Button は、ボタンを押すだけで Amazon で商品が注文されるというアレだが、ちょっしたハックをすることで汎用ボタンとして使うことが出来る。
家の中のどこにでも置いておける汎用ボタン、これは驚異的に便利。
同じものを自分で作ろうとすると、電源はどう取るとかネットワークにどう繋ぐとか配線を考えないとぐちゃぐちゃになるとかして非常に面倒くさい。
これがたったの 500 円で買えるのだから Amazon は神。
もちろんそのままボタンを押すだけでは普通に商品が注文されてしまうので、ボダン押下を検出しつつ注文が飛ばないようにハックする。
maddox/dasher や Nekmo/amazon-dash といったツールも存在するが、ハックの仕組み自体が単純なので tcpdump
コマンドさえ使えればシェルスクリプトだけでも実現できる。
以下、Amazon Dash Button ハックの仕組みと、ラズパイで動かした際のスクリプトについて解説する。
Amazon Dash Button の押下を検出できる仕組み
- Dash Button は通常は電源がオフになっていて、ボタンを押したときだけ電源が入る
- ボタンが押された (電源が入った) タイミングで DHCP で IP アドレスを取得しにいく
- DHCP で IP アドレスが割り当てられる際に、ネットワーク全体に ARP パケットが Broadcast される 1
- この ARP パケットを拾うことで、Dash Button が押されたことを検出できる
- Dash Button は IP アドレスが割り当てられたあと Amazon のサーバと通信して商品を注文しようとする
- あらかじめ Dash Button の初期設定を途中でキャンセルしておくことで注文が失敗する
- 初期設定を途中でキャンセルする詳しい方法はググって欲しい
環境
今回は以下のような環境で動かした。
- Raspberry Pi 3B
- Raspbian
-
tcpdump
をインストール済み-
apt install tcpdump
で入る
-
-
awscli
をインストール済み- (今回はボタンを押したら AWS Lambda が実行されるようにしたいので)
-
aws configure
で認証情報を設定済み
ラズパイでなくても、自宅のネットワークに接続されていて tcpdump
が使えるマシンならなんでもよい。
スクリプト
#!/bin/bash -eu
while true
do
MAC_ADDR=$(sudo tcpdump -c 1 -e arp 2>/dev/null | awk '{print toupper($2)}')
case $MAC_ADDR in
# 以下は検出したい Dash Button の MAC アドレスに書き換える
# MAC アドレスは tcpdump -e arp で調べる
34:D2:70:AA:BB:CC)
# 以下、ボタン押下時に実行したいスクリプト
echo "Amazon Dash Button (${MAC_ADDR}) is pressed!"
aws lambda invoke /dev/null --function-name myfunction > /dev/null &
;;
esac
done
case
の中身を増やせば複数の Dash Button の検出にも対応できる。
このスクリプトを実行中に Dash Button を押せば、記述したスクリプトが実行される。この場合だと、myfunction
という名前の AWS Lambda Function が実行される。
スクリプトの実行に時間がかかる場合は &
を指定してバックグラウンドで実行するなどしないと、連続してボタンが押された場合に検出できないことがあるので注意が必要。
自動起動させる
ラズパイ起動時に上記スクリプトが自動で起動するように Systemd の設定をしておく。
[Unit]
Description=amazon-dash
[Service]
User=pi
ExecStart=/home/pi/amazon-dash.sh
[Install]
WantedBy=multi-user.target
このような設定ファイルを配置して
$ sudo systemctl enable amazon-dash
これで完了。
動かした様子
-
DHCP では、割り当てた IP アドレスが同じネットワーク内で重複していないか確認するために ARP パケットを飛ばす ↩