ESP-WROOM-32をHTTPで制御する
ESP-WROOM-32(以下ESP32)をWiFi経由で制御するのに、RESTful APIのようにGETで値の取得、POSTで値の設定をしたかったけど、HTTPのPOSTメソッドを受けるサーバーについての情報が少なかったので、ここにまとめます。
ちなみに、Arduino IDEを使用しています。
サンプル
コード
#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クラスを利用します。
server.on
サーバーを起動する前に、onメンバ関数で、特定のパス(URL)にアクセスされた際の動作を登録します。
第1引数にパス、第2引数にアクセスされた際に実行する関数を指定します。
サンプルコードのように引数内に直接処理を記述する他、以下のように存在する関数を直接渡すこともできます。
void handleTarget() {
// 省略
}
void setup() {
// 省略
// アクセスされた際に行う関数を登録する
server.on("/target", handleTarget);
// 省略
}
また、今回GETとPOST両方使うため指定していませんが、引数を3つにして第2引数に受け付けるHTTPメソッドを指定することができます。(その場合関数は第3引数に)
更に、POSTメソッドでファイルなど1度に処理できない大きなデータが送られた場合は途中で第4引数に指定された関数が実行されます。(今回そんなことは想定してないので省略)
今回僕の目的では不要だったので利用していませんが、気になる場合は以下リファレンスを見てください。
第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を使ってるからみんなこれを使うんだろうね。
コメント