ESP-WROOM-02(Arduino)によるWiFiネットワーキング (8) ~ HTTPサーバベースのアプリケーション
第一回で示したクマーシステムも回転灯システムも、共にESP-WROOM-02をHTTPサーバとして動かすアプリケーションである。今回はこれらのソフトウェアの骨格部分を説明しよう。ソースコードは下記のGitHubリポジトリに公開しており、FlagBearとBuildCopがそれぞれクマーシステムと回転灯システムに対応する。
GitHub - tomoto/ArduinoPlayGround
この手のアプリケーションで必要となる処理なんてどうせ同じ、ということでコードのほとんどはlibrariesの下にフレームワークとして実装してあり、アプリケーション本体である.inoのコードは最小で済むようになっている。このフレームワークにはいろいろ工夫が詰まっていて、おそらく読者の役に立つノウハウもあるので説明していこう。
最小のアプリケーションコード
このフレームワークを使って書いた最小のアプリケーションのコードはこんな感じだ。
#include <WiFiApp.h>
using namespace tomoto;
WiFiApp app(...);
void setup() {
app.init();
app.begin(...);
app.ws()->on(...); // ESP8266WebServerのリクエストハンドラ設定
app.beginWS();
}
void loop() {
app.loop();
delay(100);
}
これだけのコードの背後で一体何が行われるか以下に説明しよう。
初期化時
フレームワークが背後で次の仕事を行う。アプリケーションはWebサーバへのハンドラ登録と、その他固有の初期化を行うだけでよい。
- 省電力モードをlight sleepモードに設定する。ESP8266は通常80mA程度の電流を食うが、light sleepモードにすると、とある条件で20mA程度まで消費電流が下がる。「とある条件」とは、StationモードでどこかのAPに正しく接続していること、delayを呼ぶこと、など。
- シリアルポートの速度を9600 baudに設定する。デバッグ用。
- 起動後1秒以内にモードスイッチ(前回の説明でIO0に接続されたスイッチ)が押されたら後述の「ネットワーク設定用SoftAP」を起動する。
- Stationモードで前回接続したAPへの接続を試みる。一定時間APに接続できなかった場合、電気節約のためdeep sleepに落ち、一定時間後に再起動する。
- NETBIOSレスポンダを起動する。Windowsからホスト名でESP8266のIPアドレスを引くためのもの。パケット解析は自前で「なんちゃって」な実装をしている。ちなみに、ESP8266ライブラリにはmDNSレスポンダがも含まれており、Macを使う人はそれも使うとうれしいかもしれない。
- Webサーバを起動する。
- 後述の「ネットワーク設定用UI」をWebサーバに設定する。
ネットワーク設定用AP
アプリケーションは通常はStationモードで動作させたいものであり、接続先APのSSIDやパスワードを設定する必要がある。ESP8266のサンプルプログラムは大抵接続先をソースコードに決め打ちしてあるが、これだと設定変更のたびに再コンパイルが必要になって実用には耐え得ない。
そこで、起動後1秒以内にIO0に接続されたモードスイッチを押すとSoftAPモードが立ち上がり、スマフォからそこに接続してブラウザから設定変更できるようにした。この設定用APのSSID、パスワード、IPアドレス、ホスト名*1はアプリごとに決められるが、アプリのソースコードに(フレームワークに与えるパラメタとして)決め打ちする。
ただ、ちょっと落とし穴があって、このようにSoftAPモードとStationモードとを同時にONにし、SoftAPモードの方でESP8266に接続しながらStationモードの方でAPをスキャンしたり接続を試行したりすると、SoftAPモードの方の接続が巻き添えを食ってぶちぶち切れてしまうのである。そのため、設定変更リクエストを送った後は数秒待ってから再接続するような処理にしてあるのだが、それでもブラウザに「サーバに接続できません」「接続がリセットされました」と言われることが多く、あまり快適ではない。ESP8266のサポートフォーラムによると、ハードウェアは1つしかないのでStationモードの方でチャンネルをスキャンしたり変更したりするとSoftAPモードの方のチャンネルも変わってしまうとのこと。
また、最後に接続したAPの情報はESP8266の内部処理で不揮発性メモリに記憶されるのだが、接続失敗した後など、その記憶がクリアされてしまうことがよくある。なるべく回避を試みているが完全ではない。
ネットワーク設定用UI
/config/network という固定のURIにアクセスすると、現在のWiF設定やIPアドレス等の情報を確認・変更するための画面が表示される。WiFi設定の変更は上述のネットワーク設定用APから行なうことを想定。
ループ
app.loop()呼び出しの延長でフレームワークが次の処理を行う。アプリケーションはその他必要な処理を自由に記述する。
- Webサーバのリクエスト処理(ESP8266WebServer#handleClient())を行う。
- ネットワーク接続が生きているかチェックし、問題があれば再接続を試みる。一定時間回復しなければdeep sleepに落ち、一定時間後に再起動する。
delayは省電力機能の恩恵を受けるために必要である。delay時間はアプリのレスポンス要件と消費電力要件をバランスして適当に決めてよいが、私は100msにしている。
永続記憶
アプリケーション固有のデータを永続的に記憶するためには、SPIFFSというESP8266ライブラリ内の機能(フラッシュメモリの一部をファイルシステムとして使う)を利用している。例えばクマーシステムでは腕の上げ・下げ時の角度を記憶し、HTTP呼び出しで調整できるようにしている。
これを便利にするためのヘルパーライブラリも用意してある。ArduinoJsonを使用してデータをJSON形式でSPIFFSに読み書きできるもの。
なお書き込み中に電源落としたら情報壊れるんじゃないか?という気がするが細かいことは(゚ε゚)キニシナイ!!