Ideal Reality

興味の赴くままに

ESP-WROOM-32をHTTPで制御する

ESP-WROOM-32(以下ESP32)をWiFi経由で制御するのに、RESTful APIのようにGETで値の取得、POSTで値の設定をしたかったけど、HTTPのPOSTメソッドを受けるサーバーについての情報が少なかったので、ここにまとめます。

ちなみに、Arduino IDEを使用しています。

Contents
スポンサーリンク

サンプル

コード

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

const char* ssid     = "yourssid"; // 自分のSSIDに書き換える
const char* password = "yourpassword"; // 自分のパスワードに書き換える

WebServer server(80);
String target = "Initial String"; // この変数をPOSTメソッドで書き換える

void setup() {

  // シリアルコンソールのセットアップ
  Serial.begin(115200);
  delay(10);
  Serial.println();
  
  // WiFiに接続
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println();
  Serial.println("WiFi connected.");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  // アクセスされた際に行う関数を登録する
  server.on("/target", HTTP_ANY, [](){
    if (server.method() == HTTP_POST) { // POSTメソッドでアクセスされた場合
      target = server.arg("plain"); // server.arg("plain")でリクエストボディが取れる。targetに格納
    }
    server.send(200, "text/plain", target); // 値をクライアントに返す
  });

  // 登録されてないパスにアクセスがあった場合
  server.onNotFound([](){
    server.send(404, "text/plain", "Not Found."); // 404を返す
  });

  server.begin();
}

void loop() {
  // put your main code here, to run repeatedly:
  server.handleClient();
}

実行結果

簡単な解説

WebServer

SimpleWiFiServerで利用されているWiFiServerクラスはHTTPリクエストのパースを行ってくれないので、ここではWebServerクラスを利用します。

WebServerライブラリリファレンス

server.on

サーバーを起動する前に、onメンバ関数で、特定のパス(URL)にアクセスされた際の動作を登録します。

第1引数にパス、第2引数にアクセスされた際に実行する関数を指定します。

サンプルコードのように引数内に直接処理を記述する他、以下のように存在する関数を直接渡すこともできます。

void handleTarget() {
  // 省略
}

void setup() {
  // 省略

  // アクセスされた際に行う関数を登録する
  server.on("/target", handleTarget);

  // 省略
}

また、今回GETとPOST両方使うため指定していませんが、引数を3つにして第2引数に受け付けるHTTPメソッドを指定することができます。(その場合関数は第3引数に)

更に、POSTメソッドでファイルなど1度に処理できない大きなデータが送られた場合は途中で第4引数に指定された関数が実行されます。(今回そんなことは想定してないので省略)

今回僕の目的では不要だったので利用していませんが、気になる場合は以下リファレンスを見てください。

WebServer::on()

第4引数についてはArduinoOTA内にあるOTAWebUpdaterというスケッチ例が参考になるかも。

server.arg

このメンバ関数でリクエストパラメータを取得できるみたい。plainにリクエストボディが格納されてた。

curlコマンドで-H "Content-Type: text/plain"を省略すると何も入ってなかったので、リクエストのContent-Typeでおそらく動作が変わる。

server.args関数でリクエストパラメータの数、server.argNameでリクエストパラメータの名前を取得できるので、困ったときはforで回してシリアルコンソールに流してみるといいかも。

server.onNotFound

server.onで登録されていないURLやメソッドでアクセスされた場合に実行される関数を登録します。

server.send

クライアントに返事を返します。第1引数にステータスコード、第2引数にContent-Type、第3引数にレスポンスボディを指定します。

第2引数にtext/html、第3引数にHTMLのコードを入れるとブラウザから開けるWebページをESP32で配信できたりするけど、今回の目的はあくまで値の取得と設定をRESTful APIっぽくしたかっただけなので、text/plainで十分。

server.handleClient

loop関数内で呼んでね

スポンサーリンク

まとめ

リクエストボディの取得方法が分からなくて躓いた。

server.argはHTMLフォームで送信(application/x-www-form-urlencoded)とかすると変わってくれるのかな?試してないから分からないけど。

とりあえず簡単にESP32を操作できるようになったのでめでたしめでたし。

というか、普通にGETだけ使う場合でもプログラムが簡単になるので、フラッシュメモリの容量が足りないとか、特殊な理由がない限りWiFiServerクラスよりもWebServerクラスを使った方がいいと思う。

多分SimpleWiFiServerのスケッチ例がWiFiServerを使ってるからみんなこれを使うんだろうね。

スポンサーリンク

コメント

投稿されたコメントはありません

名前

メールアドレス(任意)

コメント

関連する投稿