DashButtonで開発してますか!?
ついに自分もDash Buttonの普通じゃない使い方に手を出してみました。
Dash Buttonを汎用ボタンとして利用する際にDash Buttonが押された際のARPを観測するとうい方法が用いられているブログをよく見かけます。また、ARPを検出する際にnode.jsを用いているサイトがほとんどでした。
このブログでもDash ButtonからのARPを検出して利用しますが、個人的にPythonが好き&他のプログラムとの関連もありPythonでできたらいいな〜と思って、PythonでARPの検出を行いました。
ARPとはなんぞや
って感じに説明されています。とりあえず、ネットワークに接続するときに用いられる通信で、この通信には接続するデバイス(今回はDash Button)の固有のネットワーク用のアドレス?(MACアドレス)が含まれているって理解でいいと思います。そして、Dash Buttonを押した際には必ずこの通信が行われます。
このARPを(何かで)検出し、それを発している端末が特定のボタンであれば、それに対応した操作を行うといった流れです。
環境
- Mac OS X Sierra(10.12.3)
- Python3 (3.4.3) Virtualenvで利用
Dash Buttonの設定
なにもせずにDash Buttonで開発を行うと、ボタンを押すたび商品が注文されてしまい大変なことになります。そこで、まずはボタンが押しても商品が注文されないようにします。やり方としては、ボタンのWi-Fi接続の設定はするけど、商品を選択しない。って状態で止めておきます。すでにボタンの設定が完了して商品の選択までされている場合は、一度ボタンの初期化をしてから作業を行ってください。
参考: Dash Buttonを初期化する。 | たくのこWeb
設定方法
[Dash buttonが初期化された状態で]- スマホでAmazonアプリを開く
- [メニュー -> アカウントサービス -> Dash端末の新しい端末をセットアップ]
- 指示に従ってセットアップをすすめる。
- Dash Buttonのセットアップ の画面で右上の[✗]を押してセットアップを終了する。
- Dash端末の端末を管理を押して、セットアップが完了していない状態のボタンがあればOK。
これで設定は完了です。ARPは送信するけど、商品は注文しないボタンの完成です。
環境構築
Pythonからネットワーク関連を触るために、scapyというものを利用しますので、パッケージをインストールします。python3で利用する際にはscapy-python3を選択します。(自分はPyCharmで開発を行っているため、そこからインストールしました。)
とりあえず、scapyがインストールできたか確認
Pythonシェルにてとりあえずインポートしてみる。
import scapy
ここで、scapyに関して以下のエラーが出てきたので…
...(エラーメッセージ) OSError: Cannot find libdnet.so
brewでlibdentをbrewでインストールすることで解決しました。
(参考: python 3.x – Python3 – installing Scapy in OS – Stack Overflow
brew install libdnet
またまた、pythonシェルで以下を実行した際にWARNINGが出てきたので…
from scapy.all import srp, Ether, ARP, conf WARNING: Could not load module netifaces: No module named 'netifaces'
netifacesについてもインストール。これはPythonパッケージです。
これについては、netifacesとnetifaces-py3があったのですが、netifacesで良さげでした。
プログラム
環境も揃ったので、プログラムを作成していきます。
PythonでARPを検出する際にいろいろなサイトを調べたのですが、scapy公式のサンプルが分かりやすかったので、そちらを参考にさせていただきました。
(参考: Usage — Scapy v2.1.1-dev documentation | #simplistic-arp-monitor)
from scapy.all import sniff, ARP def arp_monitor_callback(pkt): if ARP in pkt and pkt[ARP].op in (1,2): return pkt.sprintf("%ARP.hwsrc% | %ARP.psrc%") print(sniff(prn=arp_monitor_callback, filter="arp", store=0))
上記を実行して、Dash Buttonを適当に押した結果です。
WARNING: No route found for IPv6 destination :: (no default route?). This affects only IPv6 WARNING: No route found for IPv6 destination :: (no default route?). This affects only IPv6 1c:b1:7f:**:**:** | 192.168.**.* b8:e8:56:**:**:** | 192.168.**.*** 68:54:fd:**:**:** | 192.168.**.*** 34:d2:70:**:**:** | 192.168.**.*** 34:d2:70:**:**:** | 192.168.**.*** 34:d2:70:**:**:** | 192.168.**.*** 1c:b1:7f:**:**:** | 192.168.**.* b8:e8:56:**:**:** | 192.168.**.*** 1c:b1:7f:**:**:** | 192.168.**.* 68:54:fd:**:**:** | 192.168.**.*** 1c:b1:7f:**:**:** | 192.168.**.* .... [shell]
(隠す必要があるかわかりませんが、Macアドレスの下6桁とIPの下位の方は隠しました。)
WARNINGはIPv6のパケットが取れないよ的な意味だと解釈したので、とりあえず無視です。
押したタイミングと表示されたタイミングとかでなんとなくわかると思うのですが、表示されたMacアドレスの上位6桁(24ビット)はOUTと呼ばれるもので、製品を提供するベンダーごとに割り当てられたものです。
[MACアドレス検索 – UIC]で調べると、そのMacアドレスを利用しているベンダーがわかります。
検出されたパケットのうち、[68:54:fd:**:**:**]を調べてみると、
[Amazon Technologies Inc.]と出てきます。どうやら当たっていそうです。自分はDash Buttonを2つ所有しているので、[34:d2:70:**:**:**]の方もDashButtonです。[1c:b1:7f:**:**:** ]は使用しているMacBook Airから出るARPになります。
制作物
以前作成したサーボモータを利用して、部屋のスイッチを物理的に押す装置を動かしてみました!
まとめ
これにて、無事にDash ButtonからのARPを検出することができました。ARPの送信元でボタンを識別することで煮るなり焼くなり好きなことができそうです。
また、ボタンが悪いのかPythonが悪いのかわかりませんが、たまにARPの取得漏れや2重に検出したりがあります。原因は不明で今のところ困ってないですが、ちょっとスッキリしないな〜って感じです。
参考サイト
How to Build an ARP Scanner Using Scapy and Python « Null Byte ← あんまりうまくいかなかった…。