Dies Aliquanti

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

「RemoteStationで複数のチューナーを制御する」をLinux対応にしてみる (2)



前に作った、Remote Station

【キャンペーン併用でポイント最大12倍★9/14(月)AM9:59まで※要エントリー】バッファロー PCastTV2対応 PC用学習リモコンキット RemoteStation [PC-OP-RS1]【在庫目安:お取り寄せ】
用の制御プログラムをlinuxで動くようにしました。これで、我が家の録画系はWindowsからおさらば(笑)です。

もともと、linux上で作ればよかったのですが、rubyからRS232を制御するやり方がよく分からなかったので、常時電源onの Atom+ubuntu8.10上のVMPlayer+Windowsの上で動かす、というアホなことになっていたのですが、こちらの方がlinux上でrubyから RemoteStationを動作させる実験をかかれているのみつけて、真似て見ました。元の記事ではubuntu9.04(64ビット)で動作しているとのことですが、最初実験したubuntu9.04(32ビット、2.6.28-15-generic)ではうまくいかず、本番用のubuntu8.10(32ビット、2.6.27-14-generic)では問題なく動作しました。多分gemとか、ruby-devのインストールとかがうまくいってないのだと思いますが、よく分かりません。

元々のコードがやっつけ仕事だったので、自分の書いたコードにもかかわらず今回見直しても、すでによく分からず苦労しました。  orz

記憶が鮮明なうちに、「やっつけ」なところを修正して、ドキュメントを起こしておかないとまずいです。




スポンサーサイト

RemoteStationで複数のチューナーを制御する

 不調になった、メインの録画システムの対策で、サブ機と同じ自作のプログラムを動かして対策してみました。チューナーの制御が問題で、サブ機は


【リニューアル記念★ポイント最大6倍★7/27(月)09:59まで】バッファロー PCastTV2対応 PC用学習リモコンキット RemoteStation [PC-OP-RS1]【在庫目安:お取り寄せ】
これを使っています。もう一台買えばいいのですが、必ずしも安くないですし、同時に動作すると混信の可能性もあります。

複数のプログラムでRemoteStationを共有できたとしても、デジタル放送の選局は多くのチューナーでバンド(地上/BS,CS)+数字ですので、複数のキーに相当する赤外線信号をタイミングよく出す必要があります。つまり、あるチューナーへの複数のキーストロークと別のチューナーへの複数のキーストロークが混ざらないようにしなければなりません。

そこで、今回はdRrubyで、サーバー/クライアント型の共有をするようにしてみました。上記の「複数のキーストローク」単位で排他的にロックをかけることでキーストロークが混ざることを防げますし、サーバー/クライアント型にすることで、物理的に異なるPCでもRemoteStationを使うことができます。

dRubyでは、 サーバー/クライアント型の分散プログラミングはとても簡単にできます。通常のRubyのプログラムで、

foo1 = FOO.new
foo1.bar(...)
などと記述する場面で、サーバー側で、
foo1 = FOO.new
uri='druby://192.168.0.211:12345'

DRb.start_service( uri, foo )
sleep
と書いて(sleepはメインスレッドが停止しないようにするため)、クライアント側では
uri='druby://192.168.0.211:12345'
service = DRbObject.new_with_uri( uri )
service.bar(...)
とかけるのです.注意することは、
(1)サーバー/クライアントともRubyのバージョンが基本的に同じでなければならない。
(2)通常、Rubyでは参照渡しなのに対して、dRubyのサーバー/クライアントの間だけは、値渡しになる。
(3)サーバー/クライアント間の漢字のコードが異なる場合、明示的な変換が必要。
(4)セキュリティが弱い、というかdRubyのレベルで考える必要がある。
くらいかな.
今回は本当に「やっつけしごと」なので、すこし整理してからコードは載せます。
では、では。


Ruby用ライブラリと簡単なアプリを公開します

バッファロー PCastTV2対応 PC用学習リモコンキット RemoteStation (PC-OP-RS1)

用のRuby用ライブラリとアプリを公開します。こちらからどうぞ。 元ネタは、「スーの道具箱」さんのところです。

RemoteStationは最大4chのLEDが扱えるのだけど、1つのLEDでも異なるデータを出せば、複数の機器の制御はできますね。ただ、排他制御をなんとかしないと、異なるアプリからの制御がうまくいかなそう。。。やっぱり、drubyとかでサービスの形にしないとだめかしらん?



Buffalo RemoteStationを赤外線リモコンの受信用に使う

Buffalo RemoteStationの解析のおまけの話です。前回、Windows+Rubyで、PCから赤外線リモコンで外部の装置を制御できるようになりましたが、「学習」用に受信した赤外線データをチェックして、PCを動かすことはできないか?と思ってちょっと実験してみました。
 RemoteStationは、受信した240バイト分のデータをPC側で、記憶しておき、それをそのまま送信することで赤外線リモコンの出力としています。

まず、受信したデータを、記憶しているデータとそのままつき合わせてみます。

んー、不一致の数が適当に決めたスレッショルド以下だったら、一致判定としようと思いましたが、時々メチャメチャ不一致の値が大きくなりますね・・・データを眺めてみると、受信データに「リピート」(長押し)のコードが入っているようです。とりあえず200ビットほど'0'が続いたらそのあとは捨ててしまうように直します。

ぬ~、だいぶ確率は下がりましたが、やはり時々不一致の数が増えます…もう一度データを眺めてみると、1バイトなかのデータの並びが、LSB firstみたい。MSB firstで比べてた… orz

適当に直します(ビット順の反転ってRubyではどうやるのがスマートなんでしょ?) だいぶ、よくなりました。RemoteStationは受信データを「解釈」せずに、0.1ms程度でサンプルしたデータを送ってくるらしいので、場合によっては0→1、1→0のエッジがずれます。
そこで、本来の赤外線データよりも十分にサンプリングレートが速い、と仮定します。
 受信データと、参照用のデータをビットごとに比較し、一致した場合は、そのビットは一致(硬判定)とし、一致しなかった場合は前後のビットがともに一致する場合は一致(軟判定)としました。240ビット分調べて、不一致判定が0(もしくは数ビット)ならば、参照するデータに一致と最終的に判断します。ここまで、面倒くさいことをするくらいなら、データを「解釈」(家電協、NEC,ソニーフォーマットなどがあるらしい)してしまったほうがいいかも?

 ともかく、何とか受信データの判別ができるようになったので、Windowsのメディアセンター2005を動かしてみます。メディアセンター2005は起動や操作をすべてキーボードショートカットで操作できます。Rubyから、COMオブジェクトとしてWScript.Shellを呼び出し、Sendkeysでショートカット・キーを送ってみると、結構まともに動きます。悪くないですね。RemoteStation自体が、連続した赤外線データ受信には適していない(もともとそのための製品ではないですし)ようで、キー操作の間隔を少しあけなければならないです。制御プログラムのほうでも、受信データの判定がそこそこ重いと思うので、受信用のスレッドと判定用のスレッドを分ける(Ruby1.8xでは意味ないか・・・)とかする必要がありそうですが、実験としてはうまくいきました。
 メディアセンターのリモコンは死亡率が高い(3年間で2つ壊れた)ので、代替手段を持つのは、悪くないですね。

では、では。



Rubyでシリアルポートをつかう

Rubyで、Buffalo RemoteStationを使う話の続きです。まず、TEXCELL Rubyシリアル通信ライブラリ(Windwos用)だが、やってみると、ボーレートは115,200bpsに設定してみると問題なく動作した。ハマッたのは、Serial::receive()関数を呼んでも、nilが返ってきてしまい、うまくデータが受信できないこと。適当にsleepを埋め込んでみてやっとわかったのは、このメソッドは、データが受信できていないときに、ブロックせずにすぐにnilで戻ること。考えてみれば、そうなっていないとちょっと困る場合がありますね。
 そこで、nilが返ってきたら、sleepで0.1秒ほど待つというのを繰り返し、timeoutで与えられるまで、データが受け取れなかったら、タイムアウトで異常終了し、あとはあらかじめ与えられた(expectedLength)長さのデータがそろったらそれを返すようにしました。途中で1バイトでも受信したら、タイムアウト用のタイマはリセットしています。

ということで、RemoteStationをWindows+Rubyで使えるようになりました。なんか、やる気でてきたぞ・・・

  def receiveData( expectedLength, timeout = 1 )
    now = Time.now
    data = ""
    while (now + timeout > Time.now)
      str = receive()
      if str == nil
        sleep 0.1
      else
        data += str
        now = Time.now
        if data.length >= expectedLength
          return data
        end
      end
   end
   nil
  end # def receiveData( expectedLength, timeout = 0.5 )



FC2Ad

まとめ

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。