ESP-IDF標準HttpサーバーでEspHttpServerライブラリを作成

概要

ESP32のArduino用Httpサーバーといえばコアに内蔵しているHttpServerか、非同期型のESPAsyncWebServerライブラリを利用するのが一般的です。しかしながらESP-IDFには非同期型で高機能なesp_http_serverがありますので、そちらを利用するHttpServerライブラリを作ってみました。

作成物

GitHub – tanakamasayuki/EspHttpServer
Contribute to tanakamasayuki/EspHttpServer development by creating an account on GitHub.

上記のライブラリです。Arduino標準HttpServerは同時アクセスに弱いのと、設計が古いのであまりおすすめしません。ESPAsyncWebServerも設計自体はいいのですが、RP2040などに対応範囲が増えており、導入も少し面倒な感じです。

esp_http_serverはESP32専用でばりばりチューニングがされていますので非常におすすめです。そこに今風のArduino APIで利用できるクラスにしたのがEspHttpServerとなります。

ページの動的生成

  server.on("/", HTTP_GET, [](EspHttpServer::Request &req, EspHttpServer::Response &res)
            {
    (void)req;
    res.sendText(200, "text/plain", "EspHttpServer ready!"); });

onでPathを指定することでページを生成可能です。

チャンクに分割しての送信

  server.on("/stream", HTTP_GET, [](EspHttpServer::Request &req, EspHttpServer::Response &res)
            {
    (void)req;
    res.beginChunked(200, "application/json");
    res.sendChunk("[\n");
    res.sendChunk("  {\"index\":0},\n");
    res.sendChunk("  {\"index\":1}\n");
    res.sendChunk("]\n");
    res.endChunked(); });

大きなページなど省メモリにしたいときにはチャンクに分割して送信することも可能です。

テンプレート埋め込み

<!doctype html>
<html>
<head>
  <title>{{name}} demo</title>
</head>
<body>
  <h1>{{{name}}}</h1>
  <p>Version: {{version}}</p>
</body>
</html>

こんな感じでテンプレートを埋め込むこともできます。

  server.on("/template", HTTP_GET, [](EspHttpServer::Request &req, EspHttpServer::Response &res)
            {
    (void)req;

    // en: Inject runtime variables into the HTML template.
    // ja: 実行時変数をテンプレートへ埋め込む。
    res.setTemplateHandler([](const String& key, Print& out) -> bool {
      if (key == "name") {
        out.print("<b>ESP32</b>");
        return true;
      }
      if (key == "version") {
        out.print("0.0.1");
        return true;
      }
      return false;
    });

setTemplateHandlerで埋め込み用コールバックを設定していて置換されます。

FSに静的ページ埋め込み

  server.serveStatic("/www", LittleFS, "/wwwroot",
                     [](const EspHttpServer::StaticInfo &info, EspHttpServer::Request &req, EspHttpServer::Response &res)
                     {
                       (void)req;
                       if (!info.exists)
                       {
                         // en: Basic SPA fallback example.
                         // ja: SPA 用のフォールバック例。
                         res.sendFile(LittleFS, "/wwwroot/index.html");
                         return;
                       }
                       res.sendStatic();
                     });

FSにあらかじめファイルを保存しておき、そこを直接配信することが可能です。

ソースコード埋め込み

vscode用のArduino CLI拡張機能 その2 追加機能
概要作成した拡張機能で機能追加をいろいろして、一通りの開発ができそうな状態になったので追加機能の紹介をしたいと思います。全体機能ここはプロジェクト全体に関するコマンドです。コマンドセンター左メニューの上から紹介していきます。使えるコマンドが…

上記のVSCODEの拡張機能を利用するとassetフォルダに入れたファイルを自動的に.hに変換してくれる機能があります。そこで不要な改行やスペースを減らしたminifyや、ZIP圧縮を自動的にしてくれる機能があります。

EspHttpServer/examples/EmbeddedAssetsSimple at main ?? tanakamasayuki/EspHttpServer
Contribute to tanakamasayuki/EspHttpServer development by creating an account on GitHub.

上記のサンプルのようにFSを配信する感じでassetから配信が可能です。オリジナルのhtmlなどはプロジェクトの中に入れておいて、埋め込むデータだけminifyされる形となります。

PlainBindを利用してテンプレート埋め込み

軽量HtmlレンダリングのPlainBind.jsを作成
概要シンプルなHtmlでJavaScript経由でレンダリングするライブラリを作ってみました。通常用途ではあまり利用することがないと思いますが、ローカル環境でjsonファイルを準備しておくとそのデータを使ってレンダリングしてくれる機能があり…

上記のJavaScriptライブラリと組み合わせてのテンプレート機能もあります。通常の埋め込みテンプレートは{{name}}などのように通常のHtmlを汚してしまいます。

<h1 data-bind="title"></h1>

上記のようにdata-から始まる項目を埋め込んでいて、そこのデータをsetHeadInjectionという機能を利用して<head>の中に埋め込んでいます。

  String head;
  head.reserve(json.length() + 160);
  head += "<script id=\"plainbind-data\" type=\"application/json\">";
  head += json;
  head += "</script>";
  res.setHeadInjection(head);

こんな感じで埋め込みようのデータを利用して<head>に埋め込む処理をしているので、JavaScriptライブラリ側がデータを解釈して文字の差し替えや表示、非表示を変更しています。Html的にはきれいなのとローカルの場合には同じフォルダにデータをおいておけば描画テストがかんたんにできる構造となっています。ESP32ではなくブラウザ側でレンダリングをして、さらにデザイナーさんともデータ埋め込みの済みで動作確認が終わったHtmlテンプレートをお願いできるかもみたいな構造です。

EspHttpServer/examples/LoginPlainBind at main ?? tanakamasayuki/EspHttpServer
Contribute to tanakamasayuki/EspHttpServer development by creating an account on GitHub.

詳しくは上記の例をみてください。

まとめ

今風のHtmlレンダリングライブラリっぽい構成にしてみました。クッキーやセッションの処理、GetやPathなどの分解などにももちろん対応しています。

普通に利用するだけでも標準のHttpServerよりも安定するのでおすすめです。

コメント