Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
19
Help us understand the problem. What is going on with this article?
@kat-kai

Amazon Dash ButtonイベントをWIFI_AP_STAモードのESP8266で取得する

More than 3 years have passed since last update.

はじめに

今回の記事では、Arduino IDEで開発可能で安価なWiFiモジュールESP8266を用いてAmazon Dashu Buttonのボタン押下イベントを取得しています。これまでのプロミスキャスモードによる手法ではなく、WIFI_AP_STAモードで取得することで外部サービスとの通信をサクッとすることができます。

Amazon Dash Buttonの通信は以下の通りになっています (rukihenaさんの記事より)

Amazon Dash Button は AmazonのサーバとHTTPSでしゃべるので、それに先立ち以下のような通信をしていると思われます。
①無線ネゴ→②WPA認証→③DHCP(ARP含む)→④DNS→⑤HTTPS

今回も①無線ネゴの段階で検出しています。①の段階でのAmazon Dash Buttonからのプローブ要求を検知しております。

実装

(15:45追記 注意点: 1度ボタンを押すと2回程度の重複検知が生じますのでご注意ください。)
(20:28追記 スマホ等の他の機器からのWiFi接続が少し不安定になります。同じSSIDが2つあるため、WiFiの繋ぎ変えが生じていそうです。)

esp8266ADB-AP_STA.ino
#include <ESP8266WiFi.h>

extern "C" {
  #include <user_interface.h>
}

//-------------------------------------------------------------------------
//  WiFi Data
//-------------------------------------------------------------------------
#define WLAN_SSID       "yourSSID"
#define WLAN_PASS       "yourPassword"
//-------------------------------------------------------------------------

//String monitoringMAC1 = "12:34:56:78:9a:bc"; //各アドレスにおいて0F以下であれば、0は省略されます。
//String monitoringMAC2 = "a:b:c:d:e:f"; //例えば0a:0b:0c:0d:0e:0fだと"a:b:c:d:e:f"と表記する必要があります。
uint8_t monitoringMAC1[6] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc};  //MACアドレスの比較法変更 (2017/01/11 9:15)
uint8_t monitoringMAC2[6] = { 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};

boolean detectingMAC1 = false;
boolean detectingMAC2 = false;

String getStrMAC(uint8_t mac[6]){
  String res = String(mac[0], HEX) + ":" + String(mac[1], HEX) + ":" + String(mac[2], HEX) + ":" +
                String(mac[3], HEX) + ":" + String(mac[4], HEX) + ":" + String(mac[5], HEX);
  return res;
}

void ICACHE_FLASH_ATTR wifi_handle_event_cb(System_Event_t *evt) {
  if (evt->event != EVENT_SOFTAPMODE_PROBEREQRECVED) return; //プローブ要求以外は無視

  uint8_t* mac = evt->event_info.ap_probereqrecved.mac;

  if (memcmp(mac,monitoringMAC1,6) == 0) detectingMAC1 = true;  //Thanks to @rukihena san
  if (memcmp(mac,monitoringMAC2,6) == 0) detectingMAC2 = true;
}

void setup() {
  Serial.begin(115200);

  connectWiFi();

  //既設アクセスポイントと同一のSSIDでsoftAP作成
  WiFi.softAP(WLAN_SSID, "pleasechangethisdummypassword");
  wifi_set_event_handler_cb(wifi_handle_event_cb);
}

void loop() {
  //milkcocoa->loop();  milkcocoa用
  if (detectingMAC1) {
    detectingMAC1 = false;
    detectMAC1();
  }

  if (detectingMAC2) {
    detectingMAC2 = false;
    detectMAC2();
  }
}

void connectWiFi() {
  WiFi.disconnect();
  delay(10);

  WiFi.mode(WIFI_AP_STA);
  WiFi.begin(WLAN_SSID, WLAN_PASS);

  while (WiFi.status() != WL_CONNECTED) {
    delay(450);
    Serial.print(".");
  }
  Serial.println();
  Serial.println("WiFi connected");
}

void detectMAC1() {
  Serial.println("ADB1 detected!");
}
void detectMAC2() {
  Serial.println("ADB2 detected!");
}

今回はWIFI_AP_STAモード(自身はアクセスポイントになりつつ、既設のアクセスポイントにクライアントとしても接続するモード)を用いています。また複数台検知も容易になりました。

まずsetup()で無線ルータに接続し、softAP()によりアクセスポイント作成後にwifi_set_event_handler_cb();でWiFiのイベントを取得します。

wifi_handle_event_cb()ではプローブ要求以外のイベントであれば無視し、プローブ要求してきたクライアントのMACアドレスを取得・比較します。今回でも、このコールバック関数内ではdetectingMAC1, detectingMAC2のフラグを立て、loop()内で処理します。

またWiFiイベントとして以下に示すイベントも取得できるようです。

(user_interface.hより)

EVENT_STAMODE_CONNECTED = 0,
EVENT_STAMODE_DISCONNECTED,
EVENT_STAMODE_AUTHMODE_CHANGE,
EVENT_STAMODE_GOT_IP,
EVENT_STAMODE_DHCP_TIMEOUT,
EVENT_SOFTAPMODE_STACONNECTED,
EVENT_SOFTAPMODE_STADISCONNECTED,
EVENT_SOFTAPMODE_PROBEREQRECVED,
EVENT_MAX 

IoTとして他のサービスとの連携

Milkcocoa

void detectMAC1(char *msg) {
    DataElement elem = DataElement();
    elem.setValue("Event", msg);
    milkcocoa->push(MILKCOCOA_DATASTORE, &elem);
    Serial.println("Done.");
}

例えばdetectMAC1()を上記のように変更すれば、milkcocoaとの連携も可能になります。

Line Notify (15:42追記)

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>

extern "C" {
  #include <user_interface.h>
}

const char* host = "notify-api.line.me";
String LINE_TOKEN = "yourtokenishere";
WiFiClientSecure client;

(中略)

void detectMAC1(String msg) {
  LinePost("message=" + msg, LINE_TOKEN);
}

String LinePost(String data, String Token) {
  Serial.println("httpsPost");
  if (client.connect(host, 443)) {
    Serial.println("Connect");
    client.println("POST /api/notify HTTP/1.1");
    client.println("Host: " + (String)host);
    client.println("User-Agent: ESP8266/1.0");
    client.println("Connection: close");
    client.println("Content-Type: application/x-www-form-urlencoded;");
    client.print("Authorization: Bearer ");
    client.println(Token);
    client.print("Content-Length: ");
    client.println(data.length());
    client.println();
    client.println(data);
    delay(10);
    String response = client.readString();
    int bodypos =  response.indexOf("\r\n\r\n") + 4;
    return response.substring(bodypos);
  }
  else {
    return "ERROR";
  }
}

Line Notifyのトークン取得後、上記コードにより連携可能となります。

セキュリティ問題

これまでのプロミスキャスモードと同様に、MACアドレスのみの照合なのでセキュリティ上の問題あり!どうしよう・・・

しかしWIFI_AP_STAモードを使うことでWiFi接続したままにできるので、他のサービスとの連携が一層スピーディーに行えるようになりました。例えばMilkcocoaへのpush時間は1秒もかからないです。まだ少し問題は残っているものの、外部サービスとの連携も低遅延で行えるようになりました。今後は押下イベント検出にARPが使えないかを検討していこうと思います。

ToDo

  • Line Notify, Twitter, IFTTT, Slack等の連携
  • SSID, パスワードでの認証, ARP? ちょっと難しそう。

参考文献

今回、以下の記事の内容・アイディアを参考に実装しました。
- ESP8266 > Amazon Dash Buttonの接続先アクセスポイントになる > v0.1 (失敗編): http://qiita.com/7of9/items/89b24045bf5e44f97be4
- Amazon Dash Button から低遅延で鍵を開ける: http://qiita.com/rukihena/items/aed9999a6a4376d68f0b

19
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
kat-kai
ESP8266/ESP32, Python (3.x), C#が好きです。ESP8266/ESP32で遊んでます(https://kat-kai.github.io)

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
19
Help us understand the problem. What is going on with this article?