Edited at

ESP8266でAmazon Dash Buttonのボタンプッシュを検知する方法


本記事について

ESP8266という、WiFi通信ができるArduino互換のマイコンがあります。

それを用いて、Amazon Dash Buttonのボタンプッシュを検知する方法です。

WiFiアクセスポイント不要。ESP8266のみでボタンプッシュを検知できます。


Amazon Dash Button ハックの仕組み

Amazon Dash Button ハックの仕組みについておさらいしておきます。

仕組みについては Amazon Dash ButtonをただのIoTボタンとして使う に詳しく書いてあります。

改めて説明すると、Amazon Dash Buttonは、ボタンが押されると、電源が入り、WiFiに接続し、インターネットを介してAmazonのサーバーにアクセスし、実際の注文を行います。

しかし、注文に絡むデバイスのため、本当にハックするのは難しく、改造等は行わないで、Amazon Dash ButtonがWiFiに接続したのを検知して、ボタンがプッシュされたとみなす、間接的なハックを行います。

ボタンを押すとAmazon Dash ButtonがWiFiに接続するようにするには、Amazon Dash ButtonにWiFiのアクセスポイント情報が登録されている必要があります。

そして、その登録のために、注文商品選択直前までAmazon Dash Buttonのセットアップを進め、そこでセットアップを中断しておきます。

そこまでセットアップが進んでいると、WiFiアクセスポイントの登録は完了していて、以後は、ボタンを押すとWiFiアクセスポイントに接続するようになります。


WiFi接続検知の方法

WiFi接続検知の方法は2つあります。


1つ目

Amazon Dash ButtonはWiFiへ接続の際、IPアドレス取得のため、まず自分のMACアドレスをネットワークにブロードキャストします。その仕組を利用して、ボタン検出する側の機器が同じWiFiネットワークに接続しておき、Amazon Dash ButtonのMACアドレスが配信されるのをウォッチして検出する方法です。


2つ目

ボタン検出する側の機器自らがWiFiのアクセスポイントとなり、Amazon Dash Buttonに登録アクセスポイントして登録する方法です。そして、Amazon Dash Buttonから、自らのアクセスポイントへのコネクションを検出します。

手順がシンプルなので、多くのハックは1つ目の方法を用いています。

しかし、1つ目の場合、常時別途WiFiアクセスポイントを用意する必要があり、ESP8266とAmazon Dash Buttonだけで動かすことができません。

WiFi環境が無い状況でも動作できるよう、ここでは2つ目の方法を用いました。


手順


ESP8266をアクセスポイントとして登録

ESP8266はWiFiを受けて、WiFi発信することができるので、仕様上はWiFiからWiFiへの中継ポイント、つまりNATになることができます。

しかし、ESP8266でNAT(NAPT)でWi-Fiを中継する に記載されているように、ESP8266のライブラリではその機能をOFFにされているため、一旦ライブラリを修正してその機能をONにしてライブラリを再コンパイルし、そのライブラリを使ってNATを実装し可動する必要があります。

そして、ESP8266をNATとして可動させ、Amazon Dash ButtonをそのNATを介してセットアップして、ESP8266をAmazon Dash Buttonに登録する必要があります。

幸い、A full functional WiFi Repeater にESP8266をNATにするソースとバイナリがありますので、今回はそのバイナリをインストールして使用しました。


NATインストール

詳細は A full functional WiFi Repeater の「Building and Flashing」に記載されています。


  1. ダウンロード

    A full functional WiFi Repeater で[Clone or download]-[Download ZIP]して解凍

  2. ソフトインストール

    https://www.espressif.com/en/support/download/other-tools からバイナリ書き込みツール「Flash Download Tools」をダウンロードしてインストール

  3. バイナリロード

    解凍したファイルの「firmware」にバイナリ「0x00000.bin」「0x10000.bin」があるのでそれを「Flash Download Tools」を使って書き込みます。

    (製品によってESP8266のFLASH SIZEが異なるので、使っているESP8266に合わせます)


NATセットアップ


  1. ESP8266セットアップ

    起動するとNATになっているので 詳細は A full functional WiFi Repeater の「Basic Web Config Interface」に従って、ブラウザでアクセスして設定します。

    (ここではデフォルトの設定を用いました)

  2. Amazon Dash Buttonセットアップ

    上記で設定したESP8266のアクセスポイントにAmazon Dash Buttonがアクセスするようにして、Amazon Dash Buttonのハックにあるのと同様の、商品選択直前までのセットアップを行います。


ボタン検知プログラム

ESP8266のアクセスポイント(SSIDとパスワード)がAmazon Dash Buttonに登録されましたので、後はボタン検知のESP8266のプログラムを書いて転送し実行するだけです。

サンプルプログラムは下記になります。


  • Amazon Dash ButtonがESP8266のアクセスポイントに接続すると、onStationConnected() コールバック関数が呼ばれますので、これをもってボタンプッシュ検知としています

  • DNSサーバーは必須ではないのですが、あった方がAmazon Dash Buttonがリトライをあきらめるのが早い(次のボタン検知可能までの間隔が短くなる)ようなので入れてあります

#include <ESP8266WiFi.h>

#include <DNSServer.h>

const char *ssid = "xxxx";
const char *password = "xxxxxxxxxx";
const byte dns_port = 53;
IPAddress apIP(192, 168, 4, 1);
IPAddress subnet(255, 255, 255, 0);
DNSServer dnsServer;
WiFiEventHandler stationConnectedHandler;

byte bConnection = 0;
int push_count= 0;
int send_frame = 0;
const int max_send_frame = 200000;
byte pin_a = 16;
byte pin_b = 14;

void setup() {
delay(1000);
Serial.begin(115200);
Serial.println();
Serial.println("Configuring access point...");

WiFi.softAPConfig(apIP, apIP, subnet);
WiFi.softAP(ssid, password);
stationConnectedHandler = WiFi.onSoftAPModeStationConnected(&onStationConnected);

IPAddress myIP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(myIP);

dnsServer.start(dns_port, "*", apIP);

pinMode(pin_a, OUTPUT);
pinMode(pin_b, OUTPUT);

digitalWrite(pin_a, LOW);
digitalWrite(pin_b, LOW);

}

void onStationConnected(const WiFiEventSoftAPModeStationConnected& evt) {
bConnection = 1;
send_frame = 0;
++push_count;

Serial.print("Station connected: ");
Serial.print(macToString(evt.mac) + " -> ");
Serial.println(push_count);

digitalWrite(pin_a, HIGH);
digitalWrite(pin_b, HIGH);
Serial.println("pin HIGH");
}

void pinOut(){
if(bConnection){
if(send_frame<max_send_frame){
++send_frame;
} else {
bConnection = 0;
digitalWrite(pin_a, LOW);
digitalWrite(pin_b, LOW);
Serial.println("pin LOW");
}
}
}

void loop() {
dnsServer.processNextRequest();
pinOut();
}

String macToString(const unsigned char* mac) {
char buf[20];
snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return String(buf);
}


最後に

WiFiアクセスポイント不要で、ESP8266だけでボタン検知できるようになるので、屋外等、任意の場所へと、Amazon Dash Button の活用フィールドが広がります。


関連記事