Arduino環境でESP8266を用いたサーバー構築
こんにちは、くろべこです。
アマゾンで1個500円程度で購入できるWiFi開発ボードESP8266があることは皆さんご存じかと思います。今回は、初めて使う方やこれから使う方をを対象にして、ESP8266でサーバーを構築する方法について取り上げていきたいと思います。
サーバーを構築する方法として【ステーションモード(STA)】と【アクセスポイントモード(AP)】がありますが、本記事で紹介するのはステーションモードになります。
■ステーションモード:WiFi子機
■ステーションモード:WiFi親機
イメージはこんな感じで、ステーションモードが家庭内のWifiルーターの子機となり、アクセスポイントモードがESP8266自身が無線親機となります。
早速、次項からはステーションモードでHTTPサーバーをESPに実装していきたいと思います。ESP8266のサンプルプログラムを使用するので1時間程度あれば誰でもできると思います。
ESP8266 HelloServer
サンプルプログラムはESP8266の開発環境を導入した時にデフォルトでついてくる【HelloServer】を使用してみましょう。
もし、ESP8266の開発環境をArduinoに導入していない場合は以下のサイトが参考になりますので、まず開発環境を整えてください。
サンプルプログラムが開けましたら、早速書き込みを行ってください。Arduinoよりは書き込みが長いと思いますが、100%になるまで待ちましょう。
書き込みが終了しましたら、シリアルモニタを開いてリセットボタンを押してみてください。正常に無線に繋がったらIPアドレスが割り振られるはずです。
WiFiに繋がらない場合
- シリアルモニタのデータレートが合っていない
- SSIDの打ち間違え
- PASSの打ち間違え
そして、ブラウザのURLを打ち込むところに割り振られたIPアドレスをコピペしてみましょう。ここでは【100.64.1.29】です。うまくいっていたら下の図のように【hello from esp8266!】という文字が書いてあるページが開かれるはずです。
HelloServerのコード解説
目標のESP8266でサーバー構築はできたと思いますが、使用したHelloServerのコードについて少し解説したいと思いますね。
■ヘッダーファイルのインクルードと定数/変数定義
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> #include <ESP8266mDNS.h> #ifndef STASSID #define STASSID "" #define STAPSK "" #endif const char* ssid = STASSID; const char* password = STAPSK; ESP8266WebServer server(80); const int led = 13; |
<ESP8266WiFi.h>
ArduinoのWiFi.hに基づいたヘッダーファイル
<WiFiClient.h>
サーバーへのリクエスト等を行うためのクライアントヘッダ。今回のコードでは削除しても問題ないです。
<ESP8266WebServer.h>
クライアントからのGET/POSTの処理についてのヘッダ。後述するhandleRoot関数でリクエストに対するWebデータを作成して、handleClientでリクエストに対してWebデータのレスポンスが出来る。
<ESP8266mDNS.h>
マルチドメイン(mDNS)を使用することが出来る。mDNSというのはローカルネットワーク内でお手軽にホスト名の解決をしてくれる仕組みです。HelloServerでは【http://esp8266.local】というホスト名でもアクセスできるようにIPアドレスとドメイン名を紐づける為のヘッダです。
ESP8266WebServer server(80)
ネットワーク間でUDPやTCP通信をするためには機能ごとにポートと呼ばれる扉を設定する必要があります。今回は【HTTP】というアプリケーションに則ったTCP通信なので80番ポートになります。このように役割が決まっている通信に関してはポート番号はすでに予約されています。俗に言うウェルノウン(よく知られている)ポートというやつです。今回はサーバー設定なので80番ポートを開放して待ち受けている状態です。
■クライアントにウェブページ(HTML)を返す関数(handleRoot/handleNotFound)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
void handleRoot() { digitalWrite(led, 1); server.send(200, "text/plain", "hello from esp8266!"); digitalWrite(led, 0); } void handleNotFound() { digitalWrite(led, 1); String message = "File Not Found\n\n"; message += "URI: "; message += server.uri(); message += "\nMethod: "; message += (server.method() == HTTP_GET) ? "GET" : "POST"; message += "\nArguments: "; message += server.args(); message += "\n"; for (uint8_t i = 0; i < server.args(); i++) { message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; } server.send(404, "text/plain", message); digitalWrite(led, 0); } |
handleRoot(){}
クライアントからのリクエストに対して返すHTTPデータになります。実際に返すデータはserver.send(HTTPステータスコード, データフォーマット, データ)で返します。
handleNotFound(){}
クライアントが誤ったルートパスでアクセスしたときに返答するデータです。いわゆる404エラーというやつですね。
HTTPステータスコード
- 1xx:情報
- 2xx:アクセス成功
- 3xx:リダイレクション
- 4xx:クライアントエラー
- 5xx:サーバーエラー
■セットアップ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
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("esp8266")) { Serial.println("MDNS responder started"); } server.on("/", handleRoot); server.on("/inline", []() { server.send(200, "text/plain", "this works as well"); }); server.on("/gif", []() { static const uint8_t gif[] PROGMEM = { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x10, 0x00, 0x10, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x02, 0x19, 0x8c, 0x8f, 0xa9, 0xcb, 0x9d, 0x00, 0x5f, 0x74, 0xb4, 0x56, 0xb0, 0xb0, 0xd2, 0xf2, 0x35, 0x1e, 0x4c, 0x0c, 0x24, 0x5a, 0xe6, 0x89, 0xa6, 0x4d, 0x01, 0x00, 0x3b }; char gif_colored[sizeof(gif)]; memcpy_P(gif_colored, gif, sizeof(gif)); // Set the background to a random set of colors gif_colored[16] = millis() % 256; gif_colored[17] = millis() % 256; gif_colored[18] = millis() % 256; server.send(200, "image/gif", gif_colored, sizeof(gif_colored)); }); server.onNotFound(handleNotFound); server.begin(); Serial.println("HTTP server started"); } |
WiFi.mode(WIFI_STA) / WiFi.begin(ssid, password) / WiFi.status()
WiFiの接続とサーバーモードで開始する設定です。WiFi.status()を監視することで接続状態を検出しています。
MDNS.begin(“esp8266”)
冒頭で説明したDNS設定ですね。IPアドレスとドメイン名を紐づけています。
server.on(“/”, handleRoot)
前項で設定した関数(handleRoot)を設定しています。デフォルトでのページになります。
server.on(“/inline”, [](){})
http:// IP-Address/inlineでアクセスできるページの設定です。ラムダ式という記述方法を使用しているようです。
server.onNotFound(handleNotFound);
誤ったルートパスでクライアントからリクエストがあった時に返すページです。前項で404エラーで登録した関数を呼び出すようになっています。
server.begin();
HTTPサーバー開始。
■クライアントからのリクエスト処理
1 2 3 4 |
void loop(void) { server.handleClient(); MDNS.update(); } |
server.handleClient()
クライアントからのリクエストに対して、セットアップで登録したルートパスのHTTPデータを返します。
コメント