今日はホームページのボタンを追加して、LEDのオンオフを行いたいと思うのですが、その前にサーバのアドレスをホスト名でアクセツ出来る様に変更します。消去した、”MDNS.begin()を追加します。
#include <WiFi.h>
#include <WebServer.h>
#include <ESPmDNS.h>
const char* ssid = "xxxxx";
const char* password = "yyyyy";
WebServer server(80);
const int led = 2;
void handleRoot() {
digitalWrite(led, 1);
server.send(200, "text/plain", "hello from esp8266!");
digitalWrite(led, 0);
}
void setup(void) {
pinMode(led, OUTPUT);
digitalWrite(led, 0);
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED){
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
if (MDNS.begin("esp32")) {
Serial.println("MDNS responder started");
}
server.on("/", handleRoot);
server.begin();
Serial.println("HTTP server started");
}
void loop(void) {
server.handleClient();
}
ハイライトの部分が追加箇所です。MDNS.begin(“esp32″)でホスト名を”esp32″に設定しています。ブラウザのアドレスを指定する箇所にIPアドレスを入れる代わりに、”esp32.local” と入力してサーバにアクセス可能になります。スケッチをコンパイルして実行して下さい。
IPアドレスを入力した時と同じ結果になりました。
本題に入ります
作成するサーバはこんな感じ
- ホスト名(esp32.local)でサーバにアクセスすると”ON”ボタンの左が表示される。この時点ではESP32上のLEDは消灯している。
- ”ON”ボタンをクリックすると”OFF”ボタンの右が表示される。この時点でLEDは点灯する。
- 引き続きボタンを押すと、”ON”、”OFF”の動作を繰り返す。
例えば、”ON”ボタンが表示されている時のHTLMは、
<!DOCTYPE html> <html>
<head><meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>LED Control</title>
<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}
.button {display: block;width: 60px;background-color: #3498db;border: none;color: white;padding: 13px 30px;
text-decoration: none;font-size: 25px;margin: 0px auto 35px;cursor: pointer;border-radius: 4px;}
.button-on {background-color: #3498db;}
.button-on:active {background-color: #2980b9;}
.button-off {background-color: #34495e;}
.button-off:active {background-color: #2c3e50;}
</style>
</head>
<body>
<h2>Hello ESP32</h2>
<a class="button button-on" href="/led_on">ON</a>
</body>
</html>
ボタンが”OFF”の時は、15行目を変更するのみでその他は同じです。つまり、ボタンを押される度に15行目を書き換えて、LEDを”オン”、”オフ”する機能をスケッチに埋め込めば良いのです。こんな感じに埋め込みました。
#include <WiFi.h>
#include <WebServer.h>
#include <ESPmDNS.h>
const char* ssid = "XXXXXX";
const char* password = "YYYYYY";
WebServer server(80);
#define LED_pin 2
bool LED_status = LOW;
String index_HD =
"<!DOCTYPE html> <html>\n"
"<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n"
"<title>LED Control</title>\n"
"<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n"
".button {display: block;width: 60px;background-color: #3498db;border: none;color: white;padding: 13px 30px;\n"
"text-decoration: none;font-size: 25px;margin: 0px auto 35px;cursor: pointer;border-radius: 4px;}\n"
".button-on {background-color: #3498db;}\n"
".button-on:active {background-color: #2980b9;}\n"
".button-off {background-color: #34495e;}\n"
".button-off:active {background-color: #2c3e50;}\n"
"</style>\n"
"</head>\n"
"<body>\n"
"<h2>Hello ESP32</h2>\n";
void setup() {
Serial.begin(115200);
pinMode(LED_pin, OUTPUT);
digitalWrite(LED_pin, 0);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED){
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
if (MDNS.begin("esp32")) {
Serial.println("MDNS responder started");
}
server.on("/", handleRoot);
server.on("/led_on", handle_led_on);
server.on("/led_off", handle_led_off);
server.begin();
}
void loop() {
server.handleClient();
}
void handleRoot() {
LED_status = LOW;
digitalWrite(LED_pin, LOW);
server.send(200, "text/html", SendHTML(LED_status));
}
void handle_led_on() {
LED_status = HIGH;
digitalWrite(LED_pin, HIGH);
server.send(200, "text/html", SendHTML(true));
}
void handle_led_off() {
LED_status = LOW;
digitalWrite(LED_pin, LOW);
server.send(200, "text/html", SendHTML(false));
}
String SendHTML(uint8_t led_stat){
String ptr;
ptr = index_HD;
if(led_stat)
ptr +="<a class=\"button button-off\" href=\"/led_off\">OFF</a>\n";
else
ptr +="<a class=\"button button-on\" href=\"/led_on\">ON</a>\n";
ptr +="</body>\n";
ptr +="</html>\n";
return ptr;
}
WebServerクラスのインスタンス、”server(80)”の内部関数、”server.send(a,b,c)”ですが、これがクライアントにデータを送信しています。各引数ですが、
- a: HTTPステータスコード。
- クライアントの要求に対してサーバが問題無く対応出来た場合、”200”
- 要求されたデータが無い場合、”404”
- b: コンテンツタイプ。
- 今回はテキストなので、”text/html”を指定。
- c: コンテンツ。
- クライアントに送るデータ(HTML)をここに入れて送る
今回の場合は、server.send(200, “text/html”,prt);とし、クライアントに送りたいHTMLの文字列を、prtに代入しているだけです。
- 13から27行:String index_HD =
- 今回のサーバはクライアントに送るHTMLは、ボタン表示の部分を除いて他は同じです。その共通部分をここに宣言しています。
- 54から56行:ここで、処理関数を定義しています。
- クライアントからのクリエに処理関数を対応させます。
- 例えばクライアントから、”esp32.local/led_off”と要求が有った場合
- クリエは”/led_off”。
- この”led_off”に対応する関数を、server.on(“/led_off”, handle_led_off);と定義。
- void handle_led_off()は、実際の操作を行う関数
- esp32.local/ ー> server.on(“/”, handleRoot);
- esp32.local/led_on ー> server.on(“/led_on”, handle_led_on);
- esp32.local/led_off ー> server.on(“/led_off”, handle_led_off);
- 66行:void handleRoot()
- ルートをアクセスされた時の処理。LED_statusを”Low”にしLEDを消灯する。
- SendHTML(LED_status)でクライアントに送るHTMLを作成。その後、send()でクライアントに送信。
- 72行:void handle_led_on()
- LEDをオンさせる関数。
- ”OFF”ボタンが押されると実行する。
- 78行:void handle_led_off()
- LEDをオフさせる関数。
- ”ON”ボタンが押されると実行する。
- 84行:String SendHTML(uint8_t led_stat)
- ここでクライアントに送信されるHTMLが作られる。
- 89行から91行で状態に応じてボタン表示部を入れ替える。
- 戻り値は、完成したHTML。
スケッチの概要はこんな感じ。LEDとボタンのオンオフについてもちょっと説明すると
- クライアントがルートにアクセス。
- handleRoot()が実行される。
- LED_statusがLowに、LEDがOFFになる。
- 引数がLow(=0)でSendHTML()が実行。
- SendHTML()のボタン判断箇所で、led_stat=0なので、
- “ON”ボタンが選ばれる。
- ボタンは押されると、”/led_on”をサーバにリクエスト
- この時点で、LEDは、オフ。 ボタンは、”ON”表示となる。
- handleRoot()が実行される。
- ”ON”と表示されているボタンを押す。
- “/led_on”がリクエストされる。
- handle_led_on()を実行
- LED_statusがHighに、LEDがONになる。
- 引数がHigh(=1)でSendHTML()が実行。
- SendHTML()のボタン判断箇所で、led_stat=1なので、
- “OFF”ボタンが選ばれる。
- ボタンは押されると、”/led_off”をサーバにリクエスト
- この時点で、LEDは、オン。 ボタンは、”OFF”表示となる
- ”OFF”と表示されているボタンを押す。
- “/led_off”がリクエストされる。
- handle_led_off()を実行
- LED_statusがLowに、LEDがOFFになる。
- 引数がLow(=0)でSendHTML()が実行。
- SendHTML()のボタン判断箇所で、led_stat=0なので、
- “ON”ボタンが選ばれる。
- ボタンは押されると、”/led_on”をサーバにリクエスト
- この時点で、LEDは、オフ。 ボタンは、”ON”表示となる。
ボタン1つの設定になんだか大掛かりな気がしますが、でもこれでボタン1つでLEDがオンオフ出来る様になりました。もちろんパソコンでもスマホでもタブレットでも。