LoginSignup
10
13

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-05-29

本記事について

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 の活用フィールドが広がります。

関連記事

10
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
13