2013年12月2日

Raspberry PiにVFATをマウントする - いろいろ問題が…

Raspberry Pi(RPi)を車載して、低価格(~$50)のドライブレコーダ(車載カメラ+ストレージ)に記録された画像データを帰宅後ガラージュに停車したら自動的にWiFiで我が家のサーバに転送するプロジェクトを進めている。

セキュアなWiFiの接続(確実に自宅サーバだけに接続する)だのカメラのモード(撮影と転送)の切り替えだのカメラの電源のコントロールだのいろいろ問題はあるが、まずはRPiに接続したカメラのデータをWiFiでサーバに転送できるところから実装し始めたが、大まかには動作し始めたものの、カメラをRPiに接続するところからRPi特有と思われる問題いろいろが見つかった。

使用したドライブレコーダ

参考のために、使用したカメラ(ドライブレコーダ)と使用している動作モードを紹介する。
  • モデル: BlackView(当然のことながら中国製)
  • 解像度: 1280x720 30fps
  • 記録: MJPEG(motion JPEG) 約1GB/10min.
  • メディア: 32GB micro SD(最大5時間記録)
  • 電源・転送: USB2.0
  • GPS機能なし(よって時刻合わせは手動)
USBでPCに接続すると撮影モードからデータ転送モードになり、PCからはマスストレージに見える。最初に見つかった問題は、USBのデータ転送が約900MBを超えると必ずコケること。RPiだけでなくUbubtu、Win7などでも同じ症状を見せたのでこのカメラ特有の問題と思われる。これはファイルあたりの記録時間を5分(5、10、15分から選択、5分≒500MB)に制限することで回避。

ストレージクラスデバイスをマウントする

RPiの標準インスタレーションではマスストレージクラスのデバイスしか認識しない。iPhoneやディジタルカメラはイメージングクラスデバイスなので、USBレベルでは認識されても「/dev/sdX」としては認識されない。LinuxでこれらのイメージングデバイスをマウントするにはGVFSを使うが、ここで使ったカメラはストレージクラスなので取り敢えず問題なし。
 
ストレージクラスのカメラは、例えば「/dev/sda1」というブロックデバイスとしてして現れるので単純にマウントできるが、そのままでは自動的にはマウントされない。自動的にマウントするにはいろいろ方法があるようだが、成功したのはusbmountを使う方法。automountではできなかった。usbmountは/dev/sdXNデバイスを自動的に/media/usbMにマウントする(例えば/dev/sda1 on /media/usb0)が、N(パーティション番号)はともかく、XとMは再現性が保証されないので不確定性が残るが、マウント時に起動されるスクリプトが/var/run/usbmount/の下にデバイスのベンダとモデルから生成されたシンボリックリンク(この場合は「Syntek_USB_MSDC_1」)がマウントされたデバイスのルートを指すように作成するので、こちらでアクセスする限り不確定性は実用上問題ない。
 

タイムゾーンが違う!!

最悪にして最大の(同じこと!?)の問題は、RPiのカーネルに含まれるVFATFSがメディアのタイムスタンプをUTCと解釈してしまうこと。おかげでファイルの日付がタイムゾーンの分だけずれてしまう。VFATFSはtz=UTCのマウントオプションを受け付けるはずだが、実際には機能していないようだ。他にもいろいろやってみたが全て不発。複数のUSBマスストレージデバイスをRPiにマウントして同じ現象が発生し、他のLinux(例えばUbuntu)では発生しないので、RPiカーネル固有の問題だと思う。以下のカーネルバージョンでこの現象が確認されている。
  • 3.6.11+ #474 PREEMPT Thu Jun 13 17:14:42 BST 2013
  • 3.6.11+ #538 PREEMPT Fri Aug 30 20:42:08 BST 2013
  • 3.10.19+ #600 PREEMPT Sat Nov 16 20:34:43 GMT 2013
カーネルを自分でビルドするとかモジュールでパッチするとかはやりたくないので、アプリケーションレベルでの回避策を考える。

ローカルで回避

RPiにログインしてローカルでVFATFSのタイムゾーンの問題を回避するにはTZ環境変数を使う。例えば
$ ls -l /var/run/usbmount/Syntek_USB_MSDC_1
 とする代わりに
$ env TZ=UTC ls -l /var/run/usbmount/Syntek_USB_MSDC_1
 とする。ぎこちないが仕方ない。

リモートで回避

そもそもカメラのファイルシステムのタイムゾーンが間違っていると何故困るかと言うと、構築中のシステムではカメラの「RECxxxxx.AVI(xxxxxはシーケンス番号)」という名前のMJPEG録画ファイルをサーバに転送して、最終的に録画開始時刻を基にした「20131201_07:01:23.avi」のようなファイル名のMPEGファイルに変換して保存したいからだ。残念ながら

0 件のコメント:

コメントを投稿