東芝 FlashAir W-03 の挙動まとめ
「FlashAirをいじってわかったこと。」
https://sites.google.com/site/gpsnmeajp/electricmemo/flashairにいろいろとまとめてくださってあり、非常に参考になります。
ここでは、ウェブプログラマ的視点で、私が気が付いたことを、ネタがかぶらない範囲でまとめておきます。
ちなみに私の手持ちのFlashAir W-03のファームウェアバージョンは
FA9CAW3AW3.00.00
GET /command.cgi のキャッシュ防止には &TIME=xxxx を付ける。 → jQueryの {cache:false}は使えない。
HTTPのGETメソッドは通常のアクセスと同様に、ブラウザがキャッシュすることで同じページを2度目に開くときに時間を短縮します。が、時によってこの機能が邪魔な場合があります。
FlashAirの場合 command.cgi?op=121 でSDカードの更新状態を定期的にチェックするのですが、ブラウザがこの呼び出しの結果をキャッシュしてしまうとSDカードが更新されてもずっと同じ結果(タイムスタンプ)が返ってくるため期待した結果と異なることになります。
そこで、簡単な解決策としてアクセスするURLを少しずつ変えることでいつも新しいページを開くようにブラウザのキャッシュを回避する方法があります。
GET /command.cgi?t=10000
とアクセスした後
GET /command.cgi?t=10001
と適当に異なる番号をつければ、ブラウザは別のページだと解釈してかならず、サーバーから新しいコンテンツを取り寄せます。
ところが、FlashAirの /command.cgiは ?TIME=xxxx という書式は受け付けますが ?t=xxxx という書式だとなぜかエラー。
さらに困ったことに、、
jQuery.ajax には { cache: false } というオプションがあって先に説明した方法でブラウザのキャッシュを回避するオプションがあるのですが、これが t=xxxx という書式でURLの末尾に追加する方法なのです。このオプションはFlashAirに対しては使えません。
SDカードにカンマ(,)を含むディレクトリ名があるとそのページの自動更新が失敗する。
ウェブブラウザで接続した際の単純なバグです。
https://flashair-developers.com/ja/documents/api/commandcgi/#100
ではカンマを含むファイル名、ディレクトリ名について言及しているだけに残念です。
List.htmに挿入するための <!--WLANSDJLST--> というキーワードは" "で囲まれた書式のため心配が要りませんが
http://flashair/command.cgi?op=100&DIR....
の結果はCSV表現なのですがカンマの含まれる名前はEXCELなどでなされる""で囲むなどの処理がされていないため、読み込みプログラム側で柔軟に解析しないと失敗します。拙作の FlashAir List.htm と Chromeアプリ版 FlashAir Sync はこれの対策を入れてあります。
同時にダウンロードできるファイルは1つだけ ← HTTP(WiFi)経由でファイルをダウンロード中は API の応答が停止する。
ApacheやIISなどモダンなウェブサーバーになれているとハッとさせられる挙動です。大きな画像ファイル、デジカメのRAWファイルなどある程度転送の時間がかかる場合に注意が必要です。
ファイルは1つずつしか転送できません。APIにアクセスするアプリが同時に多数ある場合は、応答のパフォーマンスに配慮する必要があります。
当初、私は、複数のディレクトリを指定してゲリラ的にローカルと同期させるようなアプリを考えていましたが、この制限によって、ファイルの自動転送は、ディレクトリごと1つ1つが正しい作法だということになりました。
※WiFi経由の転送は同時に1つに制限されますが、その間SDカードへの直接書き込みはできまるから、デジカメでの撮影が滞ることはありません。
ブラウザユーティリティー <!--WLANSDJLST--> より command.cgi?op=100 のほうが速い
SDカードに内蔵のウェブサーバーは、小電力の限界もあってパフォーマンス的に期待するのは酷なのは想像に難くありません。
結論としては、SDカード側で難しいことはさせず、複雑な処理はできる限りクライアント側でやらせるというアプローチがいいことになります。
当方では List.htm のカスタマイズを公開していますが、当初 <!--WLANSDJLST--> を使ったアプローチで作成しましたが、
ディレクトリを移動するごとに HTMLのすべての転送、js/cssなどのファイルの転送が発生し、ページの表示が完了するまで数秒の待ちが発生してしまいました。
FlashAirオリジナルの List.htm の場合も同様です。
そこで、改良版として List.htm に <!--WLANSDJLST--> を一切含まないものを作成して、ファイルのリストはAPIの
/command.cgi?op=100&DIR=....
で取得するように変更しました。
その結果ページの表示に関して2割程度のスピードアップ。さらに、ディレクトリの移動はURLをリンクするのではなく、
ページ内のJavascriptからAJAXでAPIからファイルリストを取得しなおす「シングルページアプリ」として作ることで、
ディレクトリの移動も含め劇的に快適なスピードでアクセスできるようになりました。
ファイルアップロードのHTTP通信で注意すべきこと
ファイルのアップロード upload.cgi は本家ドキュメントで書かれていないことが数点あります。
- アップロードの multipart/form-dataの作り方で、Content-Disposition: ... filename="FILENAME.JPG"
のように filename を必ずダブルクォーテーションでくくる必要があります。.NETの一部のAPIでこれを付けないものがあるので要注意。
- ファイルアップロードで upload.cgi 呼び出しの戻りは text/html です。SUCCESS/ERROR ではありません。
FlashAirのウェブサーバーはブラウザのキャッシュ機構に優しくない・・・
ブラウザカスタマイズで List.htm を作成した場合、関連する jsやcssファイル、画像ファイルなどがSDカード側からロードされるのですが、どうやら、サーバー(FlashAir)のレスポンスに、サーバーがLast-Modifiedなどキャッシュ関連のヘッダーが付いておらず、唯一ETag がついているもののウェブブラウザからの If-None-Match に応答している気配がありません。したがって、ページを開くたびに関連するファイルがすべて転送されることとなり、ページが表示しきるまでの待ち時間がそれなりに生じてしまいます。
拙作 List.htm カスタマイズではディレクトリの移動を ajax でのみ更新するシングルページアプリとしたことでこの問題を回避しています。
luaスクリプトは・・・将来に期待
電子工作などの活用でいろんな記事を見ていると可能性があって面白いです。ただ、「写真を共有」「ファイルをダウンロード」的な典型的な使い方の範囲では先述の理由もあって、パフォーマンス、電力消費、安定性などからAPIを軽くたたきつつ、重い処理はウェブブラウザで・・・というアプローチが現状快適です。
たとえば、command.cgi?op=121 更新タイムスタンプの取得 はSDカードのどこかのディレクトリに変更があった場合に更新されますが必ずしも現在注目している(ブラウザで開いている)ディレクトリであるとは限りません。luaとの組み合わせで、特定のディレクトリのみをモニターする仕組みを考えたのですが、command.cgi?op=100 で変更があったかもないかもしれないファイルリストの列挙を呼び出すだけのほうが実はFlashAirの負荷が少ないんじゃないかと思ったりします。
一方で、1つのディレクトリに1万個以上の大量のファイルがある場合に、ファイルリスト取得のAPIは毎回巨大サイズのCSVファイルを転送することになり非効率です。欲を言えば、 command.cgi?op=100にページングのオプションが付けられないでしょうか。