安いWi-Fi機能付きのESP8266マイコンを試す（WiFi クラサバ編）

## 前の記事

### 準備編
https://qiita.com/Tama79/items/dec21779bb16a1d04c1e

## Arudiono IDEで使う
### 作りたかった機能
クライアントからサーバを操作（サーバはWebサーバ）する！

機能1.クライアントからサーバのビルトインLEDのON/OFF
　・/led/on でLEDをOn
　・/led/off でLEDをOff

機能2.クライアントからサーバのAD値の取得
　・/ad/ でAD値（生値）を取得

<details><summary>Wi-Fiクライアント</summary><div>
スケッチ

```
#include <ESP8266WiFi.h>

const uint8_t TARGET_LED_PIN  = LED_BUILTIN;
const uint8_t LED_ON          = LOW;
const uint8_t LED_OFF         = HIGH;

const unsigned long DELAY_TERM = 5000;
const unsigned long SERIAL_SPEED = 115200;

const char* WIFI_SSID       = "ｘｘｘｘｘｘｘｘｘｘ";
const char* WIFI_PASSWORD   = "ｘｘｘｘｘｘｘｘｘｘ";

const WiFiMode_t WIFI_MODE  = WIFI_STA;

const unsigned long WIFI_CONNECTED_CHECK_MS = 500;
const unsigned long WIFI_CONNECTED_TIMEOUT  = 10000;

const unsigned long WIFI_GET_DATA_TERM  = 1000;
const unsigned long WIFI_GET_DATA_WAIT  = 100;
const char* CONNECT_HOST = "192.168.0.5";
const char* CONNECT_HOST_CONTENTS[] = {"/404.non.html", "/", "/led/on", "/led/off", "/ad/"};
const int CONNECT_PORT = 80;
const int URL_INDEX_MIN = 0;
const int URL_INDEX_MAX = 4;

bool ConnectedStatus;

void setup() {
  Serial.begin(SERIAL_SPEED);
  Serial.println("");

  // ボード上のLEDを指定
  pinMode(TARGET_LED_PIN, OUTPUT);
  digitalWrite(TARGET_LED_PIN, LED_OFF);  // 消灯

  //  WiFi接続
  ConnectedStatus = false;
  ConnectedStatus = connect_WiFi(WIFI_SSID, WIFI_PASSWORD, WIFI_CONNECTED_TIMEOUT);
  if (ConnectedStatus)
  {
    Serial.print("Connected. local IP address: ");
    Serial.println(WiFi.localIP());
  }
}

//  WiFi(Connect)
bool connect_WiFi(const char* ssid, const char* password, long connectTimeoutMS) {
  bool  connected = false;
  long  connectCheckTime = 0;

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    connectCheckTime = connectCheckTime + WIFI_CONNECTED_CHECK_MS;
    delay(WIFI_CONNECTED_CHECK_MS);

    connected = true;
    if (connectCheckTime > connectTimeoutMS)
    {
      connected = false;
      break;
    }
  }

  return connected;
}

int urlindex = 0;

void loop() {
  WiFiClient client;

  delay(WIFI_GET_DATA_TERM);

  if (ConnectedStatus)
  {
    digitalWrite(TARGET_LED_PIN, LED_ON);  // 点灯

    Serial.print("Local IP address: ");
    Serial.println(WiFi.localIP());
 
    Serial.print("connecting to ");
    Serial.println(CONNECT_HOST);
 
    // Use WiFiClient class to create TCP connections
    if (!client.connect(CONNECT_HOST, CONNECT_PORT)) {
      Serial.println("connection failed");
      return;
    }
  
    String url;
    if ((urlindex >= URL_INDEX_MIN) && (urlindex <= URL_INDEX_MAX)) {
      url = CONNECT_HOST_CONTENTS[urlindex];
      urlindex = urlindex + 1;
    }
    if (urlindex > URL_INDEX_MAX) {
      urlindex = 0;
    }

    Serial.print("Requesting URL: ");
    Serial.print(urlindex);
    Serial.print(" - ");
    Serial.println(url);
 
    // This will send the request to the server
    client.print(String("GET ") + url + " HTTP/1.1\r\n" +
                "Host: " + CONNECT_HOST + "\r\n" +
                "Connection: close\r\n\r\n");
    delay(WIFI_GET_DATA_WAIT);
  
    // Read all the lines of the reply from server and print them to Serial
    while(client.available()){
      String line = client.readStringUntil('\r');
      Serial.print(line);
    }
 
    Serial.println();
    Serial.println("closing connection");
  } else {
    //  接続無し
    Serial.println();
    Serial.println("nothing");
  }

  digitalWrite(TARGET_LED_PIN, LED_OFF);  // 消灯
}
```
下の3つは、自分の環境に合わせて変更してください。
const char* WIFI_SSID       = "ｘｘｘｘｘｘｘｘｘｘ";
const char* WIFI_PASSWORD   = "ｘｘｘｘｘｘｘｘｘｘ";
const char* CONNECT_HOST = "192.168.0.5";
</div>
</details>

<details><summary>WiFiサーバ</summary><div>
スケッチ

```
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <Ticker.h>

//  LED関連
const uint8_t TARGET_LED_PIN  = LED_BUILTIN;
const uint8_t LED_ON          = LOW;
const uint8_t LED_OFF         = HIGH;

//  AD関連
const  uint8_t AD_PIN = A0;

Ticker AD_check_ticker;
const unsigned long AD_CHECK_TERM_MS = 500;

//  通常制御関連
const unsigned long DELAY_TERM = 5000;
const unsigned long SERIAL_SPEED = 115200;

//  Wi-Fi接続先サーバ関連
const char* WIFI_SSID       = "ｘｘｘｘｘｘｘｘｘｘ";
const char* WIFI_PASSWORD   = "ｘｘｘｘｘｘｘｘｘｘ";

//  Wi-Fi接続関連
const unsigned long WIFI_CONNECTED_CHECK_MS = 500;
const unsigned long WIFI_CONNECTED_TIMEOUT  = 10000;

const unsigned long WIFI_GET_DATA_TERM  = 5000;
const int SERVER_PORT = 80;

//  Wi-Fiモード
ESP8266WebServer server(SERVER_PORT);
const WiFiMode_t WIFI_MODE  = WIFI_STA;

//  HTMLヘッダ・フッタ
#define HTML_HEADER "<!doctype html>"\
  "<html><head><meta charset=\"UTF-8\"/>"\
  "<meta name=\"viewport\" content=\"width=device-width\"/>"\
  "</head><body>"
#define HTML_FOOTER "</body></html>"

//  制御情報（グローバル変数）
bool ConnectedStatus;
int RootCalledTimes = 0;
int ADLatestValue = 0;

void setup() {
  Serial.begin(SERIAL_SPEED);
  Serial.println("");

  // ボード上のLEDを指定
  pinMode(TARGET_LED_PIN, OUTPUT);
  digitalWrite(TARGET_LED_PIN, LED_OFF);  // 消灯

  //  ボード上のADポートを指定
  pinMode(AD_PIN, INPUT);
  ADLatestValue = 0;

  //  AD定周期読取処理
  AD_check_ticker.attach_ms(AD_CHECK_TERM_MS, ADInput);

  //  WiFi接続
  ConnectedStatus = false;
  ConnectedStatus = connect_WiFi(WIFI_SSID, WIFI_PASSWORD, WIFI_CONNECTED_TIMEOUT);
  if (ConnectedStatus)
  {
    Serial.print("Connected. local IP address: ");
    Serial.println(WiFi.localIP());

    //  サーバリクエスト実装
    // Setup WebServer Handlers
    server.on("/", [](){
      String html;

      html = HTML_HEADER;
      html += "<h1>Call Times</h1>";
      html += RootCalledTimes;
      html += HTML_FOOTER;

      RootCalledTimes += 1;
      server.send(200, "text/html", html);
    });

    server.on("/led/on", [](){
      String html;

      html = HTML_HEADER;
      html +=  "<h1>LED ON</h1>";
      html += HTML_FOOTER;
      digitalWrite(TARGET_LED_PIN, LED_ON);  // 点灯

      server.send(200, "text/html", html);
    });

    server.on("/led/off", [](){
      String html;

      html = HTML_HEADER;
      html +=  "<h1>LED OFF</h1>";
      html += HTML_FOOTER;
      digitalWrite(TARGET_LED_PIN, LED_OFF);  // 消灯

      server.send(200, "text/html", html);
    });

    server.on("/ad/", [](){
      String html;

      html = ADLatestValue;

      server.send(200, "text/html", html);
    });
    server.begin();
  }
}

//  AD入力
void ADInput() {
  int input_val = 0;

  input_val = analogRead(AD_PIN);
  ADLatestValue = input_val;

  Serial.printf("ADC = %d\r\n", input_val);
}


//  WiFi(Connect)
bool connect_WiFi(const char* ssid, const char* password, long connectTimeoutMS) {
  bool  connected = false;
  long  connectCheckTime = 0;

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    connectCheckTime = connectCheckTime + WIFI_CONNECTED_CHECK_MS;
    delay(WIFI_CONNECTED_CHECK_MS);

    connected = true;
    if (connectCheckTime > connectTimeoutMS)
    {
      connected = false;
      break;
    }
  }

  return connected;
}

void loop() {
  if (ConnectedStatus)
  {
    server.handleClient(); 
  } else {
    //  接続無し
  }

}
```
下の3つは、自分の環境に合わせて変更してください。
const char* WIFI_SSID       = "ｘｘｘｘｘｘｘｘｘｘ";
const char* WIFI_PASSWORD   = "ｘｘｘｘｘｘｘｘｘｘ";
</div>
</details>

## 謝辞
### 以下の記事を参考に作りました。
https://iot.keicode.com/esp8266/esp8266-webserver.php

## 最後に
スケッチコードはCC BY-SA 4.0（著作者の情報とCCライセンス継承はお願いします。商用利用・改変・再配布は問題なし）です。