マイコン使って「IoT機器でも作ってみない？」2日目

# スマホからLEDを光らせてみよう！

えっ、そんなことできんの？って思うかもしれませんが、できます。
**そう、ESP32ならね。**

# 動作原理

ESP32は、Wi-Fiを使って通信することができます。
今回はその機能を使って、Wi-Fiでの通信によってLEDを光らせたり消したりしてみます。
そのためにまずはESP32上でWebサーバーを建てたいと思います。

# ESP32上でWebサーバーを建てる

まずは下記コードでESP32上でWebサーバーを建ててみましょう。

```cpp:main.ino
#include <WiFi.h>
#include <WebServer.h>

WebServer server(80);

const char* ssid = "SSID";
const char* password = "PASSWORD";

void setup() {
  // Serial Initialize
  Serial.begin(115200);
  Serial.println("Serial init");

  // WiFi Initialize
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi...");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println();
  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());

  // WebServer Initialize
  server.on("/", httpHandleRoot);
  server.onNotFound(httpHandleNotFound);
  server.begin();
  Serial.println("HTTP server started");
}

void loop() {
  server.handleClient();
}

void httpHandleRoot() {
  server.send(200, "text/html", "<h1>ESP32 Web Server</h1><div>" + (String)(millis() / 1000) + " seconds elapsed since ESP32 was started.</div>");
}

void httpHandleNotFound() {
  server.send(404, "text/html", "<h1>404 Not Found</h1>");
}
```

これを書き込んで、ESP32を起動してみましょう。
あ、もちろん **SSID** と **PASSWORD** は自分の環境に合わせてくださいね。

書き込んだら、シリアルモニターを開いてみましょう。
Wi-Fiの設定が正常に行われていれば、IPアドレスが表示されると思います。

じゃあブラウザで開いてみましょう...！

おぉ...

![IMG_4550.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1107984/0417d115-3997-b55b-9af9-390bf58cf069.png)

`4 seconds elapsed since ESP32 was started.`(ESP32が起動してから4秒経過)と表示されていますね。
これはさっきの`void httpHandleRoot()`で書いた文字が表示されていますね！

## ちょっと解説

### `setup`前

```cpp
#include <WiFi.h>
#include <WebServer.h>

WebServer server(80);

const char* ssid = "SSID";
const char* password = "PASSWORD";
```

まずは、WiFiとWebServerのライブラリをインクルードしています。

そして、WebServerのインスタンスを生成しています。
`server(80)`の`80`はポート番号です。HTTPサーバー[^HTTPServer]はデフォルトで`80`番ポートを使用します。

[^HTTPServer]: あえて区別化するためにこの言い方をしましたが、HTTPサーバーはここではWebサーバーと同じ意味です。何と区別したかというとHTTPSサーバーではデフォルトは`443`番ポートを使用するためです。

そして最後に接続するWi-FiのSSIDとパスワードを設定しています。

### `setup`

```cpp
// WiFi Initialize
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi...");
while (WiFi.status() != WL_CONNECTED) {
  Serial.print(".");
  delay(500);
}
Serial.println();
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());

// WebServer Initialize
server.on("/", httpHandleRoot);
server.onNotFound(httpHandleNotFound);
server.begin();
Serial.println("HTTP server started");
```

まずはWi-Fiを初期化しています。
`WiFi.begin(ssid, password)`でWi-Fiを初期化しています。（多分接続もしてる）
そして`while (WiFi.status() != WL_CONNECTED)`でWi-Fiの接続状態を確認しています。
`WL_CONNECTED`はWi-Fiが接続されている状態を表しており、Wi-Fiが接続されるまで`while`の中の処理を繰り返します。

そして、Wi-Fiが接続されたら`WiFi.localIP()`でIPアドレスを取得し、シリアルモニターに表示しています。

次にWebServerを初期化しています。
`server.on("/", httpHandleRoot)`で`/`というパスにアクセスされたときに`httpHandleRoot`という関数を呼び出すように設定しています。
`server.onNotFound(httpHandleNotFound)`で存在しないパスにアクセスされたときに`httpHandleNotFound`という関数を呼び出すように設定しています。
そして`server.begin()`でWebServerを起動しています。

### `loop`
```cpp
server.handleClient();
```

`loop`では`server.handleClient()`を呼び出しています。
これはWebServerの処理を行うための関数です。
これを呼び出さないとWebServerの処理が行われないので注意してください。

### `httpHandleRoot`と`httpHandleNotFound`

```cpp
void httpHandleRoot() {
  server.send(200, "text/html", "<h1>ESP32 Web Server</h1><div>" + (String)(millis() / 1000) + " seconds elapsed since ESP32 was started.</div>");
}

void httpHandleNotFound() {
  server.send(404, "text/html", "<h1>404 Not Found</h1>");
}
```

これらは`server.on`で設定した関数ですね。
`httpHandleRoot`は`/`というパスにアクセスされたときに呼び出されます。
`httpHandleNotFound`は存在しないパスにアクセスされたときに呼び出されます。

`server.send`はWebServerからレスポンスを返すための関数です。
`server.send(200, "text/html", "<h1>ESP32 ... started.</div>");`は、ステータスコード`200`(`OK`)、`Content-Type`が`text/html`、`<h1>ESP32 ... started.</div>`という文字列をレスポンスとして返すという意味です。

#### `<h1>ESP32 ... started.</div>`

これにはHTMLが使用されています。
HTMLについて知らない人はこのアドベントカレンダーの1日目の記事から見直してください。

https://qiita.com/nattyan_tv/items/d3cd6b16b89b8287d2fe

今回、秒数表示をするのに`(String)(millis() / 1000)`という式を使っています。

まず、`"A" + "B"`とすると`"AB"`という文字列になります。
これは2つの文字を結合しているからです。

次に、`(String)(millis() / 1000)`ですが、`millis()`はArduinoの起動からの経過時間をミリ秒で返します。
なので、`millis() / 1000`は秒数を返します。（え、なんで？[こうだからだよ](https://wa3.i-3-i.info/word1270.html)）

そして、`(String)`は`String`型に変換するためのキャストです。（キャストを知らない？[これが参考になるよ](https://wa3.i-3-i.info/word17966.html)）
`String`型はArduinoにおいて文字列を表す型です。
そのため、3つの文字を結合できて、起動してからの秒数を表示できるってわけ。

## ちょっと解説終わり

というわけで、ESP32上でWebサーバーを建てることができました。

# じゃあスマホからLEDを...え、時間？

そうです、時間がないので今回はここまでです。
次回は！！！ちゃんと！！！スマホからLEDを光らせてみます！！！