ノート:ESP32(Arduino core)でWebサーバ&WebSocketサーバ

(1) Webサーバ

(1.1) ライブラリのインクルードとオブジェクトの定義

Arduino core for the ESP32に含まれるライブラリを使用する。
ポート番号を指定してオブジェクトを定義する。

#include <WebServer.h>

WebServer webServer(80);
(1.2) 初期化 (setup()での処理)

URLごとのコールバック関数を設定し、Webサーバを開始する。

  webServer.on("/", func_handleRoot);
  webServer.on("/index.html", func_handleRoot);
  webServer.onNotFound(func_notFound);
  webServer.begin();
(1.3) ループ処理 (loop()での処理)

loop()内で必ずhandleClientメソッドを呼ぶこと。
すなわち、loop()を他の同期処理などで止めてはならない。

  webServer.handleClient();
(1.4) リクエスト受信

リクエスト受信があると、初期化時に設定したコールバック関数が呼ばれる。
そこでクエリパラメータを取得できる。

  // パラメータの個数をチェック
  if(webServer.args() > 0){
    // 特定のパラメータがあるかチェック
    if (webServer.hasArg("hoge")){
      // パラメータの値を取得
      String val = webServer.arg("hoge");
    }
  }

また、リクエストのURLやメソッド、パラメータ名は下記のようにして取得できる。

  String uri = webServer.uri();
  HTTPMethod method = webServer.method(); // HTTP_GET, HTTP_POST など
  String argName = webServer.argName(0); // 最初のパラメータ名
(1.5) レスポンス送信

必要ならばHTTPヘッダを設定する。
HTTPステータスコード、コンテンツタイプ、コンテンツを指定してレスポンスを送信する。

  String message = "ほげほげ";
  webServer.sendHeader("Cache-Control", "no-cache");
  webServer.send(200, "text/plain", message);

ファイルを送信する場合にはSPIFFSライブラリを併用する。
ファイルを開き、コンテンツタイプを指定して送信し、最後にファイルを閉じる。

#include <FS.h>
#include <SPIFFS.h>
…
  File file = SPIFFS.open("/index.html", FILE_READ);
  size_t sent = webServer.streamFile(file, "text/html");
  file.close();

ファイルはアップローダーを使ってESP32に書き込む。アップローダーは下記ページからダウンロードできる。ZIPを解凍してArduoinoのtoolsフォルダに配置しておく。スケッチフォルダ内にdataフォルダを作成してそこに書き込みたいファイルを配置し、ツール → ESP32 Sketch Data Upload で書き込む。

【参考】

(2) WebSocketサーバ

(2.1) ライブラリのインクルードとオブジェクトの定義

WebSocketサーバはarduinoWebSocketsライブラリをGitHubからダウンロードして使用する。
ポート番号を指定してオブジェクトを定義する。

#include <WebSocketsServer.h>

static WebSocketsServer webSocket(81);


(2.2) 初期化 (setup()での処理)

WebSocketサーバを開始し、イベントハンドラ関数を設定する。

  webSocket.begin();
  webSocket.onEvent(webSocketEvent);
(2.3) ループ処理 (loop()での処理)

loop()内で必ずloopメソッドを呼ぶこと。
すなわち、loop()を他の同期処理などで止めてはならない。

  webSocket.loop();
(2.4) 受信

受信データは初期化時に設定したコールバック関数で取得する。また、接続時、切断時、エラー時にもコールバック関数が呼ばれるのでイベント種別を判定して各々を処理する。

  // num: クライアント番号
  // type: イベント種別
  // payload, length: 受信データとそのサイズ
  void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length)
  {
    switch(type) {
      case WStype_DISCONNECTED:
        切断時の処理;
        break;
      case WStype_CONNECTED:
        {
          IPAddress ip = webSocket.remoteIP(num); // クライアントのIPアドレスを取得
          接続時の処理
        }
        break;
      case WStype_TEXT:
        テキストデータ受信時の処理;
        break;
      case WStype_BIN:
        バイナリデータ受信時の処理;
        break;
      case WStype_ERROR:
        エラー時の処理;
        break;
    }
  }
(2.5) 送信

ブロードキャストであれば broadcastTXT メソッドを用いる。

  webSocket.broadcastTXT(tx_str); // 文字列を渡す場合 (文字数を指定しない場合)
  webSocket.broadcastTXT(tx_buff, tx_len); // バイト数を指定する場合

特定のクライアントに送信するのであれば sendTXT メソッドを用いる。

  webSocket.sendTXT(client_num, tx_str); // 文字列を渡す場合 (文字数を指定しない場合)
  webSocket.sendTXT(client_num, tx_buff, tx_len); // バイト数を指定する場合

また、バイナリデータを送信する場合は broadcastTXT に代えて broadcastBIN を、sendTXT に代えて sendBIN を用いる。