ESP8266 / Slack / Amazon Dash Button > Amazon Dash Buttonを押したらSlackに通知する実装 > v0.1 to v0.4 / ESP8266 WiFi Repeater (NAT Router)

http://qiita.com/kat-kai/items/c898a439bafe5e605dae
の記事に触発された記事です。

**<font color=red>この記事内のコードはほとんど他の人のコードを切り貼りしています。全ての寄与はそれぞれの人によるものです。</font>**

また、コーディングルールを統一はしていません。来年気が向いたらします。

**<font color=red>SSL認証に失敗しています。</font>**

## 動作環境

以下を使っています。

- ESP8266ユニバーサル基板実装
  - 気圧計に使っていた基板を使用
  - http://qiita.com/7of9/items/00b4e13d54f53774df69
- 自宅のプロバイダでのWiFi接続
- Amazon Dash Button (JOY)

## 実装内容

1. プロミスキャスモードによりAmazon Dash Buttonの検知を行う
  - http://qiita.com/kat-kai/items/3b1d5c74138d77a27c4d
  - http://qiita.com/kat-kai/items/c898a439bafe5e605dae
2. アクセスポイントへWiFi接続する
3. Slackへ通知する
  - http://qiita.com/7of9/items/59c6d12cadad5b8c500a
  - にある参考リンクがコードのオリジナルです

## code v0.1

### code > WiFi設定

WifiConfig.h : 
自分のアクセスポイントを記載したファイル。
**<font color=red>注意: GitHubなどにチェックインしないこと</font>**

例

```
static const char *kSsid = "pi-31415-g";
static const char *kPass = "47voyager";
```

### code > Slack設定

slackConfig.h :
Slackのチャネル、Incoming WebHooksなどの設定ファイル。

**<font color=red>注意: GitHubなどにチェックインしないこと</font>**

例

```
static const char *kSlackUrl = "/services/PIPIPI/NAPIER/3141592653589793228";
static const String kSlackChannel = "#amazon_dash";
static const String kSlackUsername = "7of9";
```

kSlackUrl にはIncoming WebHooksのURLの`/services/`から始まる文字列を設定する。


### code > Dash設定

dashConfig.h :
Amazon Dash ButtonのMACアドレス
MACアドレスの調べ方は以下の1つ目のコードを実行します。
http://qiita.com/kat-kai/items/3b1d5c74138d77a27c4d

例

**<font color=red>注意: GitHubなどにチェックインしないこと</font>**

```
uint8_t targetMAC1[6] = { 0x12, 0x34, 0x56, 078, 0x9A, 0xBC};  //Amazon Dash Button MAC address
```

### code > プロミスキャス関連

ESP_Promiscuous.h

以下を使わせていただきました。感謝です。
http://qiita.com/kat-kai/items/3b1d5c74138d77a27c4d

### code 

```c:esp8266_161231_slackAmazonDash.h
#include <ESP8266WiFi.h>
#include "ESP_Promiscuous.h"
#include "dashConfig.h"
#include "WifiConfig.h"
#include "slackConfig.h"

/*
 * v0.1 Dec. 31, 2016
 *   - add [slack submit] feature
 *   - add [Wifi connection] feature
 *   - add [amazon dash detection] feature
 */

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

byte channel = 5;  //WiFi channel (1-13)

unsigned long lastMillis = 0;

static const char *kSlackHost = "hooks.slack.com";
static const int kHttpsPort = 443;

boolean willSend = false;

static void ICACHE_FLASH_ATTR promisc_cb(uint8_t *buf, uint16_t len)
{  
    if (len == 12){
      //No accurate information about MAC address and length of the head of packet.
      struct RxControl *sniffer = (struct RxControl*) buf;
      return;
    } else if (len == 128) {
      //Management Packet
      struct sniffer_buf2 *sniffer = (struct sniffer_buf2*) buf;
      struct MAC_header *mac = (struct MAC_header*) sniffer->buf;

      int i;
      boolean MAC_Matching_Flag = true;

      for (i=0; i<6; i++) if (mac->addr2[i] != targetMAC1[i]) MAC_Matching_Flag = false;

      if (!MAC_Matching_Flag) return; //No hit
      if (millis() - lastMillis < 7000) return; //In order to avoid a duplicate detection; 1 cycle needs around 6,500 msec.

      lastMillis = millis();     

      //Handle it.
      wifi_promiscuous_enable(0);  //イベントを取得したら、WiFi接続のためにプロミスキャスモードを中断。
      willSend = true;
    } else {
      //Data Packet
      struct sniffer_buf *sniffer = (struct sniffer_buf*) buf;
      struct MAC_header *mac = (struct MAC_header*) sniffer->buf;

      return;
    }
}

void slack_submit()
{
  WiFiClientSecure client;

  // connect
  if (!client.connect(kSlackHost, kHttpsPort)) { 
    Serial.println("slack connection failed");
  } else {
    Serial.println("slack connection: OK");    
  }

  // SSL Certificate finngerprint for the host
  const char* fingerprint = "‎‎‎‎ab f0 5b a9 1a e0 ae 5f ce 32 2e 7c 66 67 49 ec dd 6d 6a 38";
  // verify the signature of the ssl certificate
 if (client.verify(fingerprint, kSlackHost)) {
   Serial.println("ssl cert matches");
 } else {
   Serial.println("ssl cert mismatch");
 }

  // submit
  String message = "Amazon Dash Pushed (ESP8266)";
  String payload="payload={\"channel\": \"" + kSlackChannel + "\", \"username\": \"" + kSlackUsername 
  + "\", \"text\": \"" + message + "\", \"icon_emoji\": \":ghost:\"}";
  Serial.println(payload.c_str());

  client.print("POST ");
  client.print(kSlackUrl);
  client.println(" HTTP/1.1");
  client.print("Host: ");
  client.println(kSlackHost);
  client.println("User-Agent: ArduinoIoT/1.0");
  client.println("Connection: close");
  client.println("Content-Type: application/x-www-form-urlencoded;");
  client.print("Content-Length: ");
  client.println(payload.length());
  client.println();
  client.println(payload);

  // リクエストを受け取る前に5秒以上は待った方がいいらしい
  delay(7000);

  while(client.available()) {
    String line = client.readStringUntil('\r');
    Serial.println(line);
  }
  client.stop();
}

void WiFi_setup()
{
  WiFi.begin(kSsid, kPass);
  while( WiFi.status() != WL_CONNECTED) {
    delay(500); // msec
  }
  Serial.println(WiFi.localIP());
}

void setup() {  
  WiFi.disconnect(); // to avoid WDT reset
  
  Serial.begin(115200);
  wifi_set_opmode(STATION_MODE);
  wifi_set_channel(channel);
  wifi_set_promiscuous_rx_cb(promisc_cb);

  Serial.println("Ready");
  
  // Start!
  wifi_promiscuous_enable(1);
}

void loop() {
  delay(100); // msec
  
  if (!willSend) {
    return;  
  }
  willSend = false;

  Serial.println("ADB push detected.");

  // submit to slack
  WiFi_setup();
  slack_submit();
  Serial.println("submitted to Slack.");

  WiFi.disconnect();

  wifi_promiscuous_enable(1);  //プロミスキャスモード再開
}
```

### 実行

実行すると以下となります。

```txt:実行
Ready
```

Amazon Dash Buttonを押しましょう。

```txt:結果
Ready
ADB push detected.
192.168.10.2
slack connection: OK
ssl cert mismatch
payload={"channel": "#amazon_dash", "username": "7of9", "text": "Amazon Dash Pushed (ESP8266)", "icon_emoji": ":ghost:"}
submitted to Slack.
```

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/97190ad0-d632-d991-a60e-8bacb12e6adb.png)


すごいですね！(それぞれの仕組みを見つけて実装した人が)

情報感謝です。

### 備考

ボタンを押す間隔は10秒程度おいた方がよさそうです。
短い間隔で押すとボタン押下検知あとのWiFi接続から進まなくなりました。
プロミスキャスモード移行やその中のdelay()処理などが関係するかもです。

### TODO1

SSLの認証はあいかわらず、mismatchです。

### TODO2

これをもって、バッテリーテストをしようと考えています。

1. CR-123A (1400mAh?)をESP8266の電源とする
2. ESP8266を放置
3. 時々Amazon Dash Buttonを押す
4. 3の繰り返し

Slackの投稿を見て、およその動作時間が分かります。
数日かかるかもしれません。

休み明けにテスト開始する予定です。

## v0.2 > 起動時Slack通知

起動時のメッセージをSlack通知するように変更しました。

### code

```c:esp8266_161231_slackAmazonDash.ino
#include <ESP8266WiFi.h>
#include "ESP_Promiscuous.h"
#include "dashConfig.h"
#include "WifiConfig.h"
#include "slackConfig.h"

/*
 * v0.2 Dec. 31, 2016
 *   - slack_submit() takes [message] arg
 * v0.1 Dec. 31, 2016
 *   - add [slack submit] feature
 *   - add [Wifi connection] feature
 *   - add [amazon dash detection] feature
 */

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

byte channel = 5;  //WiFi channel (1-13)

unsigned long lastMillis = 0;

static const char *kSlackHost = "hooks.slack.com";
static const int kHttpsPort = 443;

boolean willSend = false;

static void ICACHE_FLASH_ATTR promisc_cb(uint8_t *buf, uint16_t len)
{  
    if (len == 12){
      //No accurate information about MAC address and length of the head of packet.
      struct RxControl *sniffer = (struct RxControl*) buf;
      return;
    } else if (len == 128) {
      //Management Packet
      struct sniffer_buf2 *sniffer = (struct sniffer_buf2*) buf;
      struct MAC_header *mac = (struct MAC_header*) sniffer->buf;

      int i;
      boolean MAC_Matching_Flag = true;

      for (i=0; i<6; i++) if (mac->addr2[i] != targetMAC1[i]) MAC_Matching_Flag = false;

      if (!MAC_Matching_Flag) return; //No hit
      if (millis() - lastMillis < 7000) return; //In order to avoid a duplicate detection; 1 cycle needs around 6,500 msec.

      lastMillis = millis();     

      //Handle it.
      wifi_promiscuous_enable(0);  //イベントを取得したら、WiFi接続のためにプロミスキャスモードを中断。
      willSend = true;
    } else {
      //Data Packet
      struct sniffer_buf *sniffer = (struct sniffer_buf*) buf;
      struct MAC_header *mac = (struct MAC_header*) sniffer->buf;

      return;
    }
}

void slack_submit(String message)
{
  WiFiClientSecure client;

  // connect
  if (!client.connect(kSlackHost, kHttpsPort)) { 
    Serial.println("slack connection failed");
  } else {
    Serial.println("slack connection: OK");    
  }

  // SSL Certificate finngerprint for the host
  const char* fingerprint = "‎‎‎‎ab f0 5b a9 1a e0 ae 5f ce 32 2e 7c 66 67 49 ec dd 6d 6a 38";
  // verify the signature of the ssl certificate
 if (client.verify(fingerprint, kSlackHost)) {
   Serial.println("ssl cert matches");
 } else {
   Serial.println("ssl cert mismatch");
 }

  // submit
  String payload="payload={\"channel\": \"" + kSlackChannel + "\", \"username\": \"" + kSlackUsername 
  + "\", \"text\": \"" + message + "\", \"icon_emoji\": \":ghost:\"}";
  Serial.println(payload.c_str());

  client.print("POST ");
  client.print(kSlackUrl);
  client.println(" HTTP/1.1");
  client.print("Host: ");
  client.println(kSlackHost);
  client.println("User-Agent: ArduinoIoT/1.0");
  client.println("Connection: close");
  client.println("Content-Type: application/x-www-form-urlencoded;");
  client.print("Content-Length: ");
  client.println(payload.length());
  client.println();
  client.println(payload);

  // リクエストを受け取る前に5秒以上は待った方がいいらしい
  delay(7000);

  while(client.available()) {
    String line = client.readStringUntil('\r');
    Serial.println(line);
  }
  client.stop();
}

void WiFi_setup()
{
  WiFi.begin(kSsid, kPass);
  while( WiFi.status() != WL_CONNECTED) {
    delay(500); // msec
  }
  Serial.println(WiFi.localIP());
}

void setup() {  
  WiFi.disconnect(); // to avoid WDT reset
  
  Serial.begin(115200);
  wifi_set_opmode(STATION_MODE);
  wifi_set_channel(channel);
  wifi_set_promiscuous_rx_cb(promisc_cb);

  Serial.println("Ready");

  WiFi_setup();
  slack_submit("Amazon Dash Detect Start");
  Serial.println("submitted to Slack.");
  WiFi.disconnect();
  
  // Start!
  wifi_promiscuous_enable(1);
}

void loop() {
  delay(100); // msec
  
  if (!willSend) {
    return;  
  }
  willSend = false;

  Serial.println("ADB push detected.");

  // submit to slack
  WiFi_setup();
  slack_submit("Amazon Dash Pushed (ESP8266)");
  Serial.println("submitted to Slack.");

  WiFi.disconnect();

  wifi_promiscuous_enable(1);  //プロミスキャスモード再開
}
```

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/0610c509-64e6-6c3c-effa-5866a1831bd4.png)


## v0.3 > promiscuousモード 20% duty cycle

promiscuousモードでの消費電力を抑えることにした。
ずっとpromiscuousモードにするのは無駄なので、20% duty cycleでpromiscuousモードをONにすることにした。

### code

主な変更は loop()内 (以下のcnt関連の処理追加)。

```c
  if (cnt == 5) {
    cnt = 0;
    wifi_promiscuous_enable(1);  //プロミスキャスモード再開
//    Serial.println("on");
  } else {
    wifi_promiscuous_enable(0);  //プロミスキャスモード停止    
//    Serial.println("off");
  }
```

以下がv0.3のコード。

```c:esp8266_161231_slackAmazonDash.ino
#include <ESP8266WiFi.h>
#include "ESP_Promiscuous.h"
#include "dashConfig.h"
#include "WifiConfig.h"
#include "slackConfig.h"

/*
 * v0.3 Jan. 04, 2017
 *   - use promiscuous mode with 20% duty cycle
 * v0.2 Dec. 31, 2016
 *   - slack_submit() takes [message] arg
 * v0.1 Dec. 31, 2016
 *   - add [slack submit] feature
 *   - add [Wifi connection] feature
 *   - add [amazon dash detection] feature
 */

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

byte channel = 5;  //WiFi channel (1-13)

unsigned long lastMillis = 0;

static const char *kSlackHost = "hooks.slack.com";
static const int kHttpsPort = 443;

boolean willSend = false;

static void ICACHE_FLASH_ATTR promisc_cb(uint8_t *buf, uint16_t len)
{  
    if (len == 12){
      //No accurate information about MAC address and length of the head of packet.
      struct RxControl *sniffer = (struct RxControl*) buf;
      return;
    } else if (len == 128) {
      //Management Packet
      struct sniffer_buf2 *sniffer = (struct sniffer_buf2*) buf;
      struct MAC_header *mac = (struct MAC_header*) sniffer->buf;

      int i;
      boolean MAC_Matching_Flag = true;

      for (i=0; i<6; i++) if (mac->addr2[i] != targetMAC1[i]) MAC_Matching_Flag = false;

      if (!MAC_Matching_Flag) return; //No hit
      if (millis() - lastMillis < 7000) return; //In order to avoid a duplicate detection; 1 cycle needs around 6,500 msec.

      lastMillis = millis();     

      //Handle it.
      wifi_promiscuous_enable(0);  //イベントを取得したら、WiFi接続のためにプロミスキャスモードを中断。
      willSend = true;
    } else {
      //Data Packet
      struct sniffer_buf *sniffer = (struct sniffer_buf*) buf;
      struct MAC_header *mac = (struct MAC_header*) sniffer->buf;

      return;
    }
}

void slack_submit(String message)
{
  WiFiClientSecure client;

  // connect
  if (!client.connect(kSlackHost, kHttpsPort)) { 
    Serial.println("slack connection failed");
  } else {
    Serial.println("slack connection: OK");    
  }

  // SSL Certificate finngerprint for the host
  const char* fingerprint = "‎‎‎‎ab f0 5b a9 1a e0 ae 5f ce 32 2e 7c 66 67 49 ec dd 6d 6a 38";
  // verify the signature of the ssl certificate
 if (client.verify(fingerprint, kSlackHost)) {
   Serial.println("ssl cert matches");
 } else {
   Serial.println("ssl cert mismatch");
 }

  // submit
  String payload="payload={\"channel\": \"" + kSlackChannel + "\", \"username\": \"" + kSlackUsername 
  + "\", \"text\": \"" + message + "\", \"icon_emoji\": \":ghost:\"}";
  Serial.println(payload.c_str());

  client.print("POST ");
  client.print(kSlackUrl);
  client.println(" HTTP/1.1");
  client.print("Host: ");
  client.println(kSlackHost);
  client.println("User-Agent: ArduinoIoT/1.0");
  client.println("Connection: close");
  client.println("Content-Type: application/x-www-form-urlencoded;");
  client.print("Content-Length: ");
  client.println(payload.length());
  client.println();
  client.println(payload);

  // リクエストを受け取る前に5秒以上は待った方がいいらしい
  delay(7000);

  while(client.available()) {
    String line = client.readStringUntil('\r');
    Serial.println(line);
  }
  client.stop();
}

void WiFi_setup()
{
  WiFi.begin(kSsid, kPass);
  while( WiFi.status() != WL_CONNECTED) {
    delay(500); // msec
  }
  Serial.println(WiFi.localIP());
}

void setup() {  
  WiFi.disconnect(); // to avoid WDT reset
  
  Serial.begin(115200);
  wifi_set_opmode(STATION_MODE);
  wifi_set_channel(channel);
  wifi_set_promiscuous_rx_cb(promisc_cb);

  Serial.println("Ready");

  WiFi_setup();
  slack_submit("Amazon Dash Detect Start");
  Serial.println("submitted to Slack.");
  WiFi.disconnect();
  
  // Start!
  wifi_promiscuous_enable(1);
}

void loop() {
  static int cnt = 0;

  delay(100); // msec
  cnt++;

  if (cnt == 5) {
    cnt = 0;
    wifi_promiscuous_enable(1);  //プロミスキャスモード再開
//    Serial.println("on");
  } else {
    wifi_promiscuous_enable(0);  //プロミスキャスモード停止    
//    Serial.println("off");
  }
  
  if (!willSend) {
    return;  
  }
  willSend = false;

  Serial.println("ADB push detected.");

  // submit to slack
  WiFi_setup();
  slack_submit("Amazon Dash Pushed (ESP8266)");
  Serial.println("submitted to Slack.");

  WiFi.disconnect();

  wifi_promiscuous_enable(1);  //プロミスキャスモード再開
}
```

### 検討

ADBボタン押下の取りこぼしがないか。

20秒ごとにADBを押下することを7回繰り返してみた。
7回とも検知できた。

20% duty cycleくらいだと失敗はないのかもしれない。

## v0.4 > Modem-SleepとLight-Sleepの使用

@exabugs さんの記事をもとに調べ始めた、省電力モード。
http://qiita.com/exabugs/items/9edf9e2ba8f69800e4c5

http://qiita.com/7of9/items/171a85605c08bd3b4a72
に書いたように「Modem-sleep」と「Light-sleep」のどちらがADB検知に使えるだろうか。

こういうのは実施してみるのが早い。

### code 

v0.4としての変更内容はsetup()に以下を追加したこと。

```c
//  wifi_set_sleep_type(NONE_SLEEP_T);
//  wifi_set_sleep_type(MODEM_SLEEP_T);
  wifi_set_sleep_type(LIGHT_SLEEP_T);
```

以下がv0.4のメインファイルのコード。

```c:esp8266_161231_slackAmazonDash.ino
#include <ESP8266WiFi.h>
#include "ESP_Promiscuous.h"
#include "dashConfig.h"
#include "WifiConfig.h"
#include "slackConfig.h"

/*
 * v0.4 Jan. 05, 2017
 *   - use [LIGHT_SLEEP_T] mode
 * v0.3 Jan. 04, 2017
 *   - use promiscuous mode with 20% duty cycle
 * v0.2 Dec. 31, 2016
 *   - slack_submit() takes [message] arg
 * v0.1 Dec. 31, 2016
 *   - add [slack submit] feature
 *   - add [Wifi connection] feature
 *   - add [amazon dash detection] feature
 */

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

byte channel = 5;  //WiFi channel (1-13)

unsigned long lastMillis = 0;

static const char *kSlackHost = "hooks.slack.com";
static const int kHttpsPort = 443;

boolean willSend = false;

static void ICACHE_FLASH_ATTR promisc_cb(uint8_t *buf, uint16_t len)
{  
    if (len == 12){
      //No accurate information about MAC address and length of the head of packet.
      struct RxControl *sniffer = (struct RxControl*) buf;
      return;
    } else if (len == 128) {
      //Management Packet
      struct sniffer_buf2 *sniffer = (struct sniffer_buf2*) buf;
      struct MAC_header *mac = (struct MAC_header*) sniffer->buf;

      int i;
      boolean MAC_Matching_Flag = true;

      for (i=0; i<6; i++) if (mac->addr2[i] != targetMAC1[i]) MAC_Matching_Flag = false;

      if (!MAC_Matching_Flag) return; //No hit
      if (millis() - lastMillis < 7000) return; //In order to avoid a duplicate detection; 1 cycle needs around 6,500 msec.

      lastMillis = millis();     

      //Handle it.
      wifi_promiscuous_enable(0);  //イベントを取得したら、WiFi接続のためにプロミスキャスモードを中断。
      willSend = true;
    } else {
      //Data Packet
      struct sniffer_buf *sniffer = (struct sniffer_buf*) buf;
      struct MAC_header *mac = (struct MAC_header*) sniffer->buf;

      return;
    }
}

void slack_submit(String message)
{
  WiFiClientSecure client;

  // connect
  if (!client.connect(kSlackHost, kHttpsPort)) { 
    Serial.println("slack connection failed");
  } else {
    Serial.println("slack connection: OK");    
  }

  // SSL Certificate finngerprint for the host
  const char* fingerprint = "‎‎‎‎ab f0 5b a9 1a e0 ae 5f ce 32 2e 7c 66 67 49 ec dd 6d 6a 38";
  // verify the signature of the ssl certificate
 if (client.verify(fingerprint, kSlackHost)) {
   Serial.println("ssl cert matches");
 } else {
   Serial.println("ssl cert mismatch");
 }

  // submit
  String payload="payload={\"channel\": \"" + kSlackChannel + "\", \"username\": \"" + kSlackUsername 
  + "\", \"text\": \"" + message + "\", \"icon_emoji\": \":ghost:\"}";
  Serial.println(payload.c_str());

  client.print("POST ");
  client.print(kSlackUrl);
  client.println(" HTTP/1.1");
  client.print("Host: ");
  client.println(kSlackHost);
  client.println("User-Agent: ArduinoIoT/1.0");
  client.println("Connection: close");
  client.println("Content-Type: application/x-www-form-urlencoded;");
  client.print("Content-Length: ");
  client.println(payload.length());
  client.println();
  client.println(payload);

  // リクエストを受け取る前に5秒以上は待った方がいいらしい
  delay(7000);

  while(client.available()) {
    String line = client.readStringUntil('\r');
    Serial.println(line);
  }
  client.stop();
}

void WiFi_setup()
{
  WiFi.begin(kSsid, kPass);
  while( WiFi.status() != WL_CONNECTED) {
    delay(500); // msec
  }
  Serial.println(WiFi.localIP());
}

void setup() {  
  WiFi.disconnect(); // to avoid WDT reset

//  wifi_set_sleep_type(NONE_SLEEP_T);
//  wifi_set_sleep_type(MODEM_SLEEP_T);
  wifi_set_sleep_type(LIGHT_SLEEP_T);
  
  Serial.begin(115200);
  wifi_set_opmode(STATION_MODE);
  wifi_set_channel(channel);
  wifi_set_promiscuous_rx_cb(promisc_cb);

  Serial.println("Ready");

  WiFi_setup();
  slack_submit("Amazon Dash Detect Start");
  Serial.println("submitted to Slack.");
  WiFi.disconnect();
  
  // Start!
  wifi_promiscuous_enable(1);
}

void loop() {
  static int cnt = 0;

  delay(100); // msec
  cnt++;

  if (cnt == 5) {
    cnt = 0;
    wifi_promiscuous_enable(1);  //プロミスキャスモード再開
//    Serial.println("on");
  } else {
    wifi_promiscuous_enable(0);  //プロミスキャスモード停止    
//    Serial.println("off");
  }
  
  if (!willSend) {
    return;  
  }
  willSend = false;

  Serial.println("ADB push detected.");

  // submit to slack
  WiFi_setup();
  slack_submit("Amazon Dash Pushed (ESP8266)");
  Serial.println("submitted to Slack.");

  WiFi.disconnect();

  wifi_promiscuous_enable(1);  //プロミスキャスモード再開
}
```

### 結果

Light-SleepとModem-Sleepともに、以下の試験を実施した。

1. 20秒ごとにADBを押下する
2. 手順１を7回繰り返す

Modem-Sleep、Light-Sleepともに7回のADB押下を検知できた。

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/4d6eac44-9715-2f38-67d9-b2a604c56f97.png)

Light-Sleepを採用することにした。

(追記 2017/01/07)
http://qiita.com/7of9/items/8712a71c8af267170da4
に試験結果を記載した。

Light-Sleepを使用しない場合と同じ14時間弱までの動作となった。
Light-Sleepのまま動作していない可能性がある。

本当にLight-Sleepが機能しているのか確認するには、消費電流測定が必要だ。

## Link to the ESP8266 WiFi Repeater (NAT Router)

@yesnoj gave me the information of the ESP8266 WiFi Repeater [on his comment](http://qiita.com/7of9/items/9bcdfa8223b6ec791a5c/#comment-0eadbbadb0e0c4c1ac34).
I appreciate it.