« 2013年9月8日 - 2013年9月14日 | トップページ | 2013年10月6日 - 2013年10月12日 »

2013年9月29日 - 2013年10月5日の1件の記事

2013年9月30日 (月)

RaspberryPiのライブカメラをストリーム画面で操作する

 RaspberryPiを使った猫監視用の自宅ライブカメラプロジェクトは、もうあと一息のところまで来た。残る次の課題は、ストリーミング映像(ポート8080)と、カメラの操作(SSHでポート22)でわかれている経路の一本化である。

 前回の記事にあるようにカメラの遠隔操作には成功した。しかしカメラ操作は、SSHのコマンド経由で、外部に向けてのポートが2つも開いている。不用心だ。それよりなによりコンソールのコマンドでカメラを動かすのでは実用性はほぼゼロである。

 ストリーム画像が出ているブラウザー画面にカメラの操作(パンとチルト)ボタンを追加し、CGIでGPIOを動かす機能の開発が残っている。これにより始めて一般ユーザー(家族だけだが)が使えるレベルになる。

Chrome_title  ストリーミングサーバーにしているmjpg-streamerには、本格的なホームページが用意され、HTMLサーバーも内蔵しているようなので、ここにカメラの操作指示ボタンを埋め込むのは、簡単にできると思っていた。ところが、これが難航したのである(まあ、へそ曲がりの癖がまた出たこともあるが)。

以下は、2週間の悪戦苦闘の記録である。

本格的なウェブページの改修に四苦八苦(9/15/2013)
 mjpg-streamerは、テスト用にウェブページが用意されており、出力プラグインには、自前のHTTPサーバーまで装備されている。普通にポート80でアクセスすると、しゃれたホームページが出現する。

Mjpghome  このホームページは、静止画から、単純なモーションJPEGのストリーミング、JavaScriptを使ったクライアント側でのストリーミング(これでIE6でもストリーミング可能)まで、複数の環境をサポートしており、ここに4つのカメラの方向指示ボタンを埋め込むのは簡単だと当初考えていた。

 しかし、このページは調べ始めると、相当高度なテクニックで作られていて、構造も複雑である。新たに機能を追加するのは容易に出来そうもない。カメラの操作ボタンまでついたJavaScriptの派生ページを見つけたが、こちらはこのあたりは素人同然なので全く手も足も出ない。

 しかも、このホームページのプロトコルは、HTMLでなくてXHTMLという新しい規格だ。スタイルシートはもちろん派手に使われ多数の外部ファイルがある。xformというHTMLの進化したタグまで使われているようだ。良くわからないが、時代の先端を行くページ構成のようだ。

 こちらは特に凝ったボタンを考えているわけではない。もともと、このホームページには画像を反転させたり、回転させたりするボタンが付いている。このボタン機能を真似れば、今、#22ポートでやっているGPIOの操作が動くはずだ。しかし、ソースは凝ったJavaScriptで書かれているので簡単には解読できない。

 所長は、HTML時代にはとっくに現場を離れているので、この世界は通り一遍の知識しかない。このあいだ仕事でホームページを制作する機会があったが、素人の作るホームページとプロの仕上がりレベルは、もう桁違いに違うので早々に自作を諦めて外注に出した(市販のホームページ制作ソフトまで用意したのだが)。

 mjpg-streamerのホームページを参考にせず、別の簡単なindex.htmlをいちから作り直したほうが早そうだったが、このJavaScript満載のソースを前に、すごすご退散するのは悔しい。逃げていてはいつまで経っても技術向上は望めない。生来の負けず嫌いの精神がまたむくむくと起き上がった。ちょうど良い機会である。少しはウェブページ制作に慣れておこうと腰をすえて本格的に挑戦してみることにした。

うーむ、JavaScriptではサーバーのコマンドを動かせない(9/17/2013)
 まず、このmjpg-serverの内蔵サーバーのドキュメントを探すが、どうも要約しかない。開発サイトのフォーラムなどを読んでいると、開発は止まっているようだが、「ソースを提供するから自分で好きにやってくれ」という姿勢のようだ。細かい仕様も見当たらない。仕方がない。少しづつ、HTMLソースから調べ始める。

 HTMLソースを読み込んでみると、スケルトンとしてのHTMLの構造は意外に簡単で、かなりの部分はスタイルシートで飾られていることがわかった。スタイルシート(CSS)も生半可な知識しかない。ちょうど良いチャンスだ。この際、CSSも本格的に勉強することにする。

 要するにスタイルシートの理念は、HTMLの文書の構造と、文書自体の修飾方法を分離させ、フォントや、位置、画像などのオブジェクトの取り扱いを独立して定義し、多種類の出力媒体(大小のPC画面、携帯やスマホ、タブレット)にも対応しようと言うことなのだ。

 これまで、やたらと複雑なスタイルシートに悩まされていたのだが、少し飲み込めてきた。ここが丁寧に教えてくれる。 こういう風に、「何故こんなことをするのか」という理由を先に教えられると、こういう規格は飲み込みが早い。

 スタイルシートの部分は殆ど理解できた。そろそろCGIの手順を考えなければいけない。改めて、ソースを調べる。おやあ、このソースの大部分の関数は、JavaScriptで書かれている。しかも、組み込みではなく外部ファイルになっている。

 JavaScriptの勉強をさらに続ける。JavaScriptの多彩な機能に感心するが、何かおかしい。CGIの部分が見つからないのだ。ウェブで手当たり次第に検索しながら機能をしらべるが、今ひとつ判然としない。

 どうも、JavaScriptはクライアント側のサービスで、今やろうとしているサーバー側のシェルスクリプトや、perlなどのCGIプログラムを駆動することは出来ないような気がする。調べていてもはっきりしないので、実際に適当なテスト用のHTMLファイルを用意して、CGIのテストを始めることにした。

mjpg-streamerのサーバーはCGIをサポートしていないことが判明(9/21/201)
 ところが、このmjpg-streamerのHTTPサーバーは、CGIそのものが通らないのだ。CGIは簡単にサーバー側の環境を変えることができるので、セキュリティが厳しいのはわかるが、HTMLソースをどんどん簡単にしていっても、CGIのシェルスクリプトや、perlプログラムが動かないのである。

 エラーメッセージは、Not Found 404だったり、MIME Error(400)とかNo file extention(500)だったり、ファイルタイプや、場所によって微妙に違う。ウェブのあちらこちらをさまよって、HTTPサーバーの勉強を続けるが、このパッケージが装備しているHTTPサーバーの仕様がわからない。

 Cソースまでついているのだが、1500ステップ以上あるソースコードを調べる気にはならない。HTTP:1.0準拠ということなので(これは開発サイトに明記してあった)cgiスクリプトはサポートしているはずなのだが、はっきりしない。

 いくらやってもらちがあかないので、原点に戻って、カメラ操作シェルではない、普通のテキストがCGIで出るのかやってみた。結果はやっぱりだめだった。このサーバーはCGIをサポートしていない。

このHTTPサーバーをさっさと諦めて、Apacheなどの正規サーバーをインストールすれば良いのだろうが、既に、RasPiのCPU使用率が80%以上になっており、これ以上負荷はかけたくない。何かオプションでもあるかと、再度、しつこく、開発元のサイトを調べたり、お得意のGoogleにエラーメッセージ全文を投げる検索をやってみるが、思わしい情報は得られなかった。

 やれやれ、Apacheか。いずれにしても、このまま引き下がるわけには行かない。CGI以外にカメラを動かすコマンドを画面で操作する方法はないだろう。今のRaspberryPiは、SDカードサイズが4GBなので、そろそろファイル容量が心配なのだが、そんなことにかまっておられない。先に進むしかない。

Apache2の設定に一苦労。やっとCGIを認めてもらった(9/23/2013)
 Apacheのインストールは数多くのウェブサイトで紹介されているし、apt-getなのでインストールそのものは至極簡単である。紹介しているサイトがむしろ多すぎて迷うくらいだ。ただし、
apt-get install apache ではなく、apt-get install apache2 である。

 何と言っても、gccとならんでデファクトスタンダードになっているHTTPサーバーである。恐らく多くの企業のサーバーもこのApacheを使っているはずだ。盛りだくさんな機能がある。逆にこういう小さなマシンのサーバーをこじんまり設定する方がかえって難しい。

 CGIは元々セキュリティに気を遣わなければならないところなので、そう気楽に設定しても動かない。やたらと制限が多い。それでも、この前のmjpg-streamerのHTTPサーバーに比べれば格段に情報が多いので設定は楽にできそうだ。インストールが順調に済んだので早速設定に入る。

 ところが、Apacheの設定ファイルの中味が、バージョンや、ディストリビューションによって、微妙に違い、何が正しいのか良くわからないのである。だいたい設定ファイルそのものの名前が違う。一方の情報では、httpd.confだが、別の情報ではapache2.confである。

 中味のパラメーターも、必ずしもこの設定ファイルの中にすべてあるのではなく、分散して別のファイルに入っているものもある。沢山あるウェブの導入ガイドをあちこち見比べつつ、必要なパラメーターを定義していく。

 最後までうまくいかなかったのが、肝腎のサーバーアドレスの設定である。明示的にサーバーアドレスを指定すると、エラーで立ち上がらなくなり、指定しないと警告は出るが、ちゃんと立ち上がって、テスト用のindex.htmlが見える。気持ちが悪いけれど、動いていることを良いことに、とりあえずこのままにして先へ進むことにする。

Apache2でストリーム画像を出力する(9/25/2013)
 mjpg-streamerは、ポート8080に、ストリーミング画像を出力する。Apacheで、この画像を出力するのは、このポート8080をリンクするHTMLタグを書けば良いはずである。ただ、理屈でそうなると考えているだけで実際に試してみたわけではない。

 これが出来なければ、Apacheを動かす意味がない。Apacheが動き出したので早速、index.htmlに、必要と思われるタグを書いてテストしてみる。
<img src="ストリーミング映像のURL?入力パラメーター" > というようなタグである。

 最初は、うまく画像が出なかった。それにしても、このHTMLの仕様、何とかならないものか。ちょっとしたことで、簡単にサーバーは、"Internal Error..."を吐き出し、表示を拒絶する。あちこち調べまわるが、原因を究明できない。

 手当たり次第に行をコメントで外していって、やっと原因がわかった。画像が出ないのは、<img src=..というタグのエラーではなく、なんと、Content Type: text/html の行のあとに、改行がないというエラーだったのである。

 HTMLの頭の<meta ..などで始まるヘッダー行は、色々なファイルから適当にコピペしたもので代用している。コピーを繰り返すうち、改行をとってしまったらしい。どこかにHTMLチェッカーのようなものがあるとは思うけれど、人騒がせな仕様である。

 Content Type行のあとに空白行を入れて、めでたくApacheのテストHTMLにストリーミング画像がでた。いやあ、嬉しい。ここまで来ればもうあと一息だ。ApacheのCGIが動くことは、テキスト表示で確かめてある。

動作ボタンをつけたライブカメラ画面遂に完成(9/26/2013)
 ストリーム画像の出力に成功したので、勇躍、CGIの開発に移る。テキスト出力でCGIが動くことは確かめてあるので、その部分に、WiringPIのコマンドを
 system("./gpio -g write 27 1"); などとperlでgpioコマンドを実行するだけである。

 ボタンのコーディングが結構難しい。ハイパーテキストでリンクする方式より、formタグでボタンにする方が見栄えが良いのでこちらにしようと思ったが、formタグにはひとつのsubmitボタンしか定義できない。仕方がないので、パンの左右、チルトの上下、合わせて4つのformタグを定義した。

 わくわくしながらテストに入る。おやあ、上下左右にボタンを配置したつもりだが、真ん中にかたまって表示されている。表示はともかく、動かしてみよう。ダメだ。全く反応なし。まあ、こういうのには慣れている。

 あちこち調べたあげく、CGIのリンク先は、相対リンクでなくフルパスが必要ということがわかった。 Action="http://192.168.0.5/cgi-bin/gpio.cgi?22"などとして入れてみる。さあ、どうだ。おおお、動いた!

 テスト用のCGIプログラムのメッセージが画面に出て、カメラがグイッと回った。やった。できた。しかし、画面が完全にテキスト画面になり、画像を見るには「戻る」を押さないと映像が戻らない。

 考えてみれば、リンクするから当然なのだが、これはまずい。試しにテスト用のメッセージをとってみたが、今度は例の"Internal Error"が出るだけで当然モーターは動かず画面もエラー画面のままだ。そりゃそうだ。リンクしても出す材料がなければ、エラーにするしかない。

 困った時のウェブ頼みである。「元の画面に戻る HTML」などのキーワードで対策を調べてみる。すぐにその対策は見つかった。

 <meta httm-equiv="refresh" content="秒数; url=戻り先UR">

とすると、一旦このページに飛んでも、「秒数」後、元のページに戻るというタグのようだ。秒数を0にして試してみる。よーし、一呼吸おいてだが、動かした後の画面にもどった。良いぞ。いやあ、ライブカメラの完成である。嬉しくなって、カメラ一式を居間に移し、早速フィールドテストに入る。

S_p9286083  ボタンを押しながら、周囲を見回せるというのは、とても気分が良い。何度かやっているうち、やっぱり猫がどこからともなく集まってきた。しかし、今のところカメラを置いたビューローの蓋を上げてあるので、猫はここに飛び上れない(まあ、いずれはやられるだろうが)。

制御を再帰方式にするが、画面更新時間は改善されない(9/27/2013)
 ストリーム画像と同じ画面でカメラを動かすことには成功した。しかし、ボタンは、見映えよく上下左右に配置できていないし、やっぱり、ボタンを押した後、一呼吸(1秒以下だが)、画面が消えるのはまずい。何とか改善したい。

Photo  画像の復帰が遅くなるのは、一旦リンクして別の画面に遷移した後、そこから再び元の画面に戻って来るからである。実は、metaタグを使わないで、画面を元へもどす方法を思いついている。現在は、index.htmlのリンクからCGIへ飛ばし、そこでgpioコマンドをだしたあとmetaタグのrefreshで元の画像ページに戻っている。

 これを、CGIプログラムにindex.htmlに相当するページを出力させ、ブラウザのURLをこのCGIから始まるような再帰的な構造にするのである。こうするとジャンプした先は最初の画面なので、1回分画面送出が減らせて画面遷移が早くなる理屈である。

 こういう工夫が一番楽しい。善は急げ、である。早速、perlに、index.htmlのHTML行を出力するコードを書き加える。ところがこれが言うことを聞かないのである。すべてperlのエラーとなる。

 最初、"(コーテーション)が入っているメッセージを print "  "で出そうとしていることがわかり、これを print << "EOF" という複数行をまとめて出力する方法に変えるがそれでもダメ。コンソールにプリントアウトしてみても正しいメッセージは出されているのに、CGIにすると"Internal Error"で動かない。

 暫くはまっていたが、これも意外なところが原因だった。終端文字のEOF(これは何でもかまわないが)の文字の後、こいつも空行が必要なのである! EOFが見つからずファイルの最後まで表示しているらしい。テキスト表示では無効キャラクターは表示されないが、HTMLでは不良文字としてはねられる。やれやれ。

 やっと、HTMLはカメラ操作のあとストリーム画像を表示する画面に戻った。しかし、期待したほどの速さではない。まあ、心持ち早くなったような気がするが、これだけ苦労して動いた割には報われなくてがっかりである。まあ、ソースコードは小さくなって満足だが。

 formタグのsubmitボタンが不揃いになるのは、ウェブ情報であっさり解決策が見つかった。HTMLの仕様上は、同一行に複数のボタンはおけないが、スタイルシートをつけると簡単に解決することが分かった。早速これを真似て実装する。うまくいった。

Livecam_title  まだまだ不満は多いが、この5月から始めたRaspberryPiのライブカメラプロジェクトは、めでたくこのあたりで大団円となったようである。本当の遠隔制御は、まだテストしていないが、これまでのポート8080と22を閉じて、80にポートマッピングすればうまくいくはずだ。ただ、80番はもっとも攻撃を受けやすいポートなので、何らかの防御策を考えておかねばなるまい。あ、猫対策も残っていたか。

| | コメント (0) | トラックバック (0)

« 2013年9月8日 - 2013年9月14日 | トップページ | 2013年10月6日 - 2013年10月12日 »