FlashAirで始めるワイヤレス転送

FlashAir、最近はこういうのがあるんですね。無線LAN機能がついていて、リモートで操作できるSDカードです。

サイズから言ってmicro SDしか挿入できない最近のタブレット/スマホでは使えませんが、SDカードが使えるデバイスならいちいちPCに挿してデータコピー、という作業から解放されます。

私はデジタルフォトフレームに入れて画像ファイルの更新に使うことにしました。
東芝(メモリ)謹製の専用ソフトもありますが、SDカードの延長として使う分には必須というわけではありません。
今回は、WebDAVでのアクセスとPythonでの操作を試します。

もくじ:

セットアップ

第4世代のFlashAir(SD-UWA W-04)を購入しました。
まずは普通のSDカードと同じようにPCに接続して設定ファイル(CONFIGファイル)を編集します。既にFAT32にフォーマットされているので間違っても再フォーマットしないように注意。

某密林で買ったのですが、届いた外装パッケージが中華。。。
まあとりあえず技適マークはついているし、ウィルスチェック(という名の気休め)もクリア。
ついでに一応イメージのバックアップを作成。普通に読むと26MB/sec (200Mbps)くらいでした。さすがClass 10。

FlashAirはCONFIGという名前の設定ファイルを見て動作するようです。
パスは/SD_WLAN/CONFIGです。

初期のconfigファイルはこうなっていました(値は一部伏せています)。改行はWindowsの形式(CR+LF)ですね。

今回設定したいのは下記の項目。
・子機モードでの自動起動
・固定IPアドレス
・WebDAV機能の有効化
・アップロード(書き込み)の許可

家庭内LANなどで、無線アクセスポイントがすでに運用されている場合は、親機モードよりも子機モードで動作させたほうが便利です。NASサーバみたいな使い方ですね。

ということで変更した後のものがこちらです。値は環境に合わせて読み替えて下さい。項目の説明は後述します

設定ファイルを保存したら、PCからの接続を解除して利用予定のデバイスに挿入しなおします。

FlashAirは標準でHTTPサーバを持っているので、上記の設定がうまくいっていればブラウザでIPアドレスを指定して開くことができます。あたりまえですがドライブに挿して通電させる必要があります。

WebDAVでのアクセス

第3世代からWebDAVをサポートしているようですね。Windowsユーザなら特別なソフトをインストールすることなく標準のエクスプローラから開くことができます。

アドレスバーにパスを指定するとリダイレクトされます。
パスの形式はhttp://192.168.11.xxx/、または\\192.168.11.xxx\DavWWWRootのようにします。

あとは共有フォルダと同じような感覚で操作できます。
WebDAV経由でファイルを同期したい、といった使い方には別途WebDAVクライアントのソフトを探して下さい。

設定メモ

特に説明していないところは初期値またはテキトーで大丈夫です。
初期状態の設定ファイルには[Vendor]のセクションしかないので、必要に応じて[WLANSD]セクションを追記します。設定を反映するにはFlashAir側の再起動(接続を解除して挿入しなおす)が必要です。

子機として起動

FlashAirはデフォルトではアクセスポイントとして起動するようなので、LANに接続させて他のマシンのアクセス先を変えずに済むよう、子機として設定します。

セクション 項目 設定値 説明
[Vendor] APPMODE 5 動作モードの指定。5は子機モード(STAモード)で自動起動する設定
[Vendor] APPNETWORKKEY 無線LANアクセスポイントへ接続するためのパスワード
[Vendor] APPSSID アクセスポイントの名前(SSID)

APPMODE=5とすると子機モードで起動するようになります。

アドレスの設定

今回はアドレスを固定したいので、DHCPクライアント機能を切って、アドレスを指定しました。

セクション 項目 設定値 説明
[WLANSD] DHCP_Enabled NO DHCPクライアント機能の有効化、固定アドレスにしたいのでNOに設定
[WLANSD] IP_Address xxx.xxx.xxx.xxx IPアドレス
[WLANSD] Subnet_Mask 例) 255.255.255.0 サブネットマスク
[WLANSD] Default_Gateway xxx.xxx.xxx.xxx デフォルトゲートウェイ
[WLANSD] Preferred_DNS_Server xxx.xxx.xxx.xxx DNSサーバのアドレス(優先)。代替サーバはAlternate_...に設定

サブネットマスク以下はよくある感じの設定。ルータの設定がわからない場合は同じLAN内のマシンで(ipやipconfig /allコマンドなどで)調べて参考にして下さい。

DHCPクライアント機能を有効化した場合(DHCP_Enabled=YES)は、IPアドレスの設定が無視されます。

WebDAVの有効化

WebDAVを有効化すると、上記のようにエクスプローラなどWebDAVクライアントから編集できるようになります。
リードオンリーの設定もありますが、今回はアップロードもできるよう設定しています。

セクション 項目 設定値 説明
[Vendor] UPLOAD 1 アップロードを許可
[Vendor] WEBDAV 2 WebDAVの有効化。書き込みを許可

その他、Basic認証などのアクセス制御をかけたりといった様々な機能があります。
外で持ち歩く場合にノーガード戦法はさすがにまずいので、使い方と設定はよく検討したほうがいいと思います。

Python経由でのアクセス

せっかくHTTPサーバを積んでいるので、プログラムやスクリプトから制御できると便利ですよね。今回はPythonで操作する例を記載しておきます。

REST APIっぽいやつなのかしら、と勝手に想像していましたが、調べると、これCGIなんですね。。。

試しにざっくり書くとこんな感じ。作成した環境はWindows 10 Pro + Python3.6です。
requestsモジュールを使っているので、無い場合はpip等での追加インストールが必要です。が、そんなに複雑なことをしているわけでもなく他のモジュールで代用することも可能です。

CGIのレスポンスはだいたい平文かHTMLで返ってきます(のでパースがちょっと面倒)。
以下に解説しておきます。

ファイルのダウンロード

ダウンロードの場合は、対象のパスを叩くとふつうにバイナリとして取得することができるので、ローカルのファイルに書き出すだけです。感覚的にcurl -O ...と同じ。

ここではfaclient.retrieve_file()メソッドが処理を実装しています。

リモートのパス(SDカード内でのパス)と、ローカルディレクトリのパスを指定させ、requests.get()メソッドで取得しています。

上記ではさぼっていますが、おそらく日本語などマルチバイト文字を含むファイル・ディレクトリ名の指定にはURLエンコードが必要になるはず。

ファイルリストの取得

情報の取得や設定関連の処理には、http://[flashair]/command.cgiを使用します。
操作(コード)やその他パラメータをクエリストリングにシリアライズする必要があります。

サンプルでは例としてファイルの一覧を取得しています。faclient.get_list()メソッドが処理を実装しています。
/command.cgi?op=100&DIR=...を指定してGETリクエストを投げます。この場合、op=100がリスト取得の指定、DIRが取得先パスの指定になります。

レスポンスはこんな感じの文字列が返ってきます。

カンマ区切り(ただしファイル名にカンマを許容)でファイルやディレクトリの属性が返ってきます。

ファイルのアップロード

ファイルをアップロードするには、①SDカード(FlashAir)を挿入しているデバイスからの書き込みを禁止する手順、②アップロード先のディレクトリを指定する手順、③ファイル作成日時を指定する手順、④アップロード自体の手順の4段階が必要になります。ディレクトリの指定を省略した場合はデフォルトの、SDカード直下がアップロード先とみなされます。

アップロード関連の処理には、http://[flashair]/upload.cgiを使用します。
ここではfaclient.send_file()メソッドが処理を実装しています。

書き込み禁止の処理には/upload.cgi?WRITEPROTECT=ON、アップロード先のディレクトリを指定する処理には、/upload.cgi?UPDIR=...を使用します。
プライベートメソッドfaclient.__set_upload_dir()を別途定義し、パラメータとしてクエリストリングに渡します。

ここではGETメソッドを使います。POSTではありません。

作成日時(/upload.cgi?FTIME=0x.....)はFAT32の仕様に合わせて8桁の16進数にフォーマットします。また、アップロード自体の処理には、ファイルをmultipart/form-data形式でPOSTします(フォーム送信に使うやつ)。

Pythonではmimetypesモジュールを使って(完全ではありませんが)MIMEタイプを判定させることができます。
request.postメソッドの、data引数ではなく、files引数に指定しなければいけない点にはちょっと注意が必要かも。

いやぁPCにいちいち挿さなくてもファイル転送ができるのは便利ですね。簡単なWebサーバとして動作するので、使い方によっては色んなアプリケーションが作成できそうです。

おわり。