PlatformIO for Visual Studio Code と esp-idfを利用したESP32用WiFiManager

tonyp7/esp32-wifi-manager をPlatformIO for VSCode で試したが、動作させるために結構時間がかかった。

ESP32用WiFi Manager

esp-idfで動作させることができるWiFi Manager
tonyp7/esp32-wifi-manager を MH-ET Live ESP32 Minikit で試した。

動作するようにするためには「Using it as a PlatformIO library #12」に書かれていることの対応が必要であった。

使用したソフトウェア・ハードウェア

  • Visual Studio Code 1.29.1
    • バージョン: 1.29.1 (user setup)
    • コミット: bc24f98b5f70467bc689abf41cc5550ca637088e
    • 日付: 2018-11-15T19:13:36.375Z
  • PlatformIO for Visual Studio Code 
    • Home 2.0.0
    • Core 3.6.2
  • esp-idf
    • Platform: Espressif 32
      • 1.5.0
    • Framework: espidf
  • MH-ET Live ESP32 Minikit
    • board = mhetesp32minikit
       

データの埋め込み

そのままビルドしようとすると、query.gz などのデータの埋め込みがうまくいかない。

http://docs.platformio.org/en/latest/platforms/espressif32.html#embedding-binary-data に記載の通り、データを埋め込むためには、platformio.ini に以下を追加する必要がある。

build_flags = 
    -DCOMPONENT_EMBED_TXTFILES=src/index.html:src/jquery.gz:src/code.js:src/style.css

ここでは、srcディレクトリの下にindex.htmlなどが収められているとする。このディレクトリに応じて、http_server.c の データを埋め込んでいる部分のasm内の文字列を修正する必要がある。srcの場合には以下のようになる。

/* embedded binary data */
extern const uint8_t style_css_start[] asm("_binary_src_style_css_start");
extern const uint8_t style_css_end[]   asm("_binary_src_style_css_end");
extern const uint8_t jquery_gz_start[] asm("_binary_src_jquery_gz_start");
extern const uint8_t jquery_gz_end[] asm("_binary_src_jquery_gz_end");
extern const uint8_t code_js_start[] asm("_binary_src_code_js_start");
extern const uint8_t code_js_end[] asm("_binary_src_code_js_end");
extern const uint8_t index_html_start[] asm("_binary_src_index_html_start");
extern const uint8_t index_html_end[] asm("_binary_src_index_html_end");

しかし、この指定をしてデータの埋め込みをしてビルドできるようになっても、プログラムを実行するとアクセスポイント(AP)のSSIDやパスワード設定のページが以下のような表示になって操作ができず、正常に動作しなかった。ブラウザで調べてみると jquery.js などの実行時にエラーになっていることがわかった。サーバーから送られてきているスクリプトやデータなどに支障がある。

ファイル末尾にNUL文字が入る

実行時のエラーを調べていったところ、ビルドの際に、ファイルの末尾にNUL文字(\0)が書き込まれてしまうという現象があり、それによるプログラムが不正文字でエラーになったり、読み込むべきデータサイズとファイルサイズが一致しないという問題が生じていることがわかった。この問題がPlatformIO の問題なのか Visual Studio Code やesp-idfの問題なのかを切り分ける調査はしていない。とりあえず、問題はそのままに対処した状況である。

症状と対症療法

COMPONENT_EMBED_TXTFILES に設定されているファイルの末尾にNULがないと追加される。たとえば、code.js のファイルの最後にNUL文字(\0)が書き込まれる。取り除いてもビルドすると追加される。ビルドを繰り返してもNULが増えることはない。

NUL文字がスクリプトなどに書き込まれると文法的なエラーが発生する。最後のNULを無視するためには、netconn_writeの第3引数のサイズを-1しなければブラウザでの実行時にエラーとなる。そのため、次のように -1 を加える。

netconn_write(conn, code_js_start, code_js_end - code_js_start - 1, NETCONN_NOCOPY);

他の index.html や jquery.gz などの部分も統一するために修正しておく。

jquery.gz についてはnetconn_write の引数を修正したら、以下のContent-Length:部分も修正する。また、gzipを転送する場合には Content-type: application/json にしないとスマートフォンの Chromeでうまく動作しなかった。
const static char http_jquery_gz_hdr[] = "HTTP/1.1 200 OK\nContent-type: application/json\nAccept-Ranges: bytes\nContent-Length: 29994\nContent-Encoding: gzip\n\n";

プロジェクトのスナップショット

動作確認をした際のプロジェクトのスナップショットを次に置いた。

https://github.com/kunsen-an/platformio-vscode-esp32-wifi-manager.git