USBセンサを使ってみよう 〜Phidgets活用講座 実践編 (4)〜
作成日: 2006/7/10  最終更新日: 2006/10/11



概要

このページの内容は,Software Design 2006年2月号pp.114-119,および2006年3月号pp.102-108に掲載された, 「USBセンサを使ってみよう Phidgets活用講座(2-3)」をHTML化したものです.分量が多いため,四つのページに分割してあります.本文中の「現在」などは「2005年12月」を指します.

ここでは,WebページやRSSを定期的に監視し,更新された場合に対応するLEDを点灯させる実世界版 Biffシステム「PhidgetBiff」を紹介します.USBセンサを使ってみよう(PhidgetApplication編)も参考にしてください.

連載目次




PhidgetApplicationの紹介(3)
1. PhidgetBiff
PhidgetBiffは,WebページやRSSを定期的に監視し,更新された場合に対応するLEDを点灯させる,いわば実世界版 Biffシステムです(図11).さらに,LEDとプッシュスイッチをペアで配置すれば,該当ページをスイッチひとつで表示することができます.このように,今回紹 介する中では,やや応用よりなシステムとなっています(図12).

ここでは,PhidgetBiffのハードウェア/ソフトウェアについて紹介していきます. なお,ソフトウェアのダウンロードはこちらから行えます.

図11 PhidetBiffの外観
(Web/RSSが更新されると,LEDが点灯する) (プッシュスイッチを押すと,該当するWebページが表示され,LEDが消灯する.)
 図12 PhidetBiffの使い方
ハードウェア
PhidgetBiff用のハードウェアとして,8つのLED/プッシュスイッチをペアで配置したデバイスを製作します(図13).
図13 PhidetBiffのハードウェア

LEDとプッシュスイッチは,ぷらっとホームで販売されているInterfaceKit Package に標準添付されています.また,バリエーションを増やしたい場合は,秋月電子千石電商のWebサイトから,1個あたり10〜100円程度で購入することが可能です.

今回のハードウェアは,LED/プッシュスイッチを上下に並べたものを1セットとして,ユニバーサル基板上に8セット配置しています.LED/スイッチは,半田付けして固定した後,適当なケーブルでInterfaceKitのデジタル出力/デジタル入力に接続します. そして,InterfaceKitとPCをUSBケーブルで接続すれば,ハードウェアの準備は完了です. ここでは,ノートパソコンのディスプレイの左上部分にデバイスを取り付けています.

ソフトウェア

PhidgetBiffのソフトウェアは,PhidgetServerに接続するTCPクライアントとして,Rubyを用いて記述しています.PhidgetBiffを利用するためには,Cygwinから以下のように入力します.

%./PhidgetBiff.rb

オプションの設定などは,PhidgetBrowserとほぼ同様です.

ここでは,ソースコードの主要部分を参照しながら,PhidgetServerの処理の流れについて簡単に説明します.なお,PhidgetBrowserと共通する説明については割愛します.

1. PhidgetServerへの接続
TCPSocketクラスを用いて,PhidgetServerに接続します.
2. リストファイルの読み込み
更新を監視するURLのリストを読み込みます.以下のように,一行にひとつのURLを記載したファイル("url.txt")を読み込み,配列に格納します.直接Webページを指定する以外に,RSSを指定することも可能です.
  ["url.txt"]
  http://mobiquitous.com/diary/index.rdf
  http://pitecan.com/
  http://namazu.org/~satoru/blog/index.rdf
  
  def load_url(file = "url.txt")
    uris = Array.new
    File.open(file)  do |f|
      f.each do |line|
        line.chomp!
        uris.push(URI.parse(line))
        break if uris.length > 8
      end
    end
    uris
  end
3. 更新時間の初期化
リスト内の各URLの,最終更新時刻を取得し,ハッシュに格納します.最終更新時刻('last-modified')は,httpのheadメソッドを用いて取得することができます.接続がタイムアウトされるなど,最終更新時刻が取得できない場合は,GMTの起算時間(1970年1月1日午前0時)を返します.
  def init_modified_time(uris)
    modified_times = Hash.new
      uris.each do |uri|
        time  = get_modified_time(uri)
        modified_times[uri] = time
     end
     modified_times
  end
  
  def get_modified_time (uri, timeout = 2)
    return nil unless /^http/ =~ uri.to_s
    time = nil
    dead = Time.at(0)
    begin
      uri_const = URI.parse(uri.to_s)
      http = http_connect(uri_const, timeout)
      response = http.head(uri.to_s)
      if response.code.to_i != 200
        time = dead
      elsif response['last-modified']
        time = Time.httpdate(response['last-modified']) 
      else
        time = dead 
      end
    rescue Net::ProtoFatalError => e  # 404
      time = dead
    rescue 
      time = dead # timeout? 
    end
    time
  end
4. 更新時刻の監視
各URLの更新時刻を一定時間毎(標準では10秒間隔)に監視します.更新があった場合,LEDの点灯処理を行います.
def biff_loop (uris, modified_time, sleep_time = 10)
    while true
      uris.each do |uri|
        time  = get_modified_time(uri)
        next if time == nil
        if(modified_times[uri] < time)
          set_port(uris.index(uri), 1)
          modified_times[uri] = time
        end
      end
      sleep(sleep_time)  
    end
  end
 
5. LEDの制御
デジタル出力の状態を制御し,LEDを点灯/消灯します.
  def set_port(socket, port, state = 0)
    str = "Out,InterfaceKit,#{port},#{state}\r\n" 
    socket.print str
  end
6. スイッチ入力の監視
受信したコマンドを解析し,各プッシュスイッチの状態を検出します.プッシュスイッチが新たに押された場合,該当するURLを開きます.また,デジタル出力を介して,該当するLEDを消灯します.
  def main
    ...
    port, data = parse(line)
    if data  &&
     data != port_states[port]
     
     open_url(@uris[port])
     set_port(socket, port)
     port_states[port] = data
  end
 ...
 end
 
  def parse(line)
    args = line.split(",")
    if args[0] == "In" and
       args[1] == "InterfaceKit" and
       args[2] == "Digital" 
       
	   port = args[3].to_i
       data = args[4].to_i
      
       return port, data
    end
  end 
7. Webページを開く
プッシュスイッチが押された場合,該当するWebページを開きます.URLにRSSが指定されている場合は,RSSから適切なURLを抽出して利用します.
	def open_url(uri)
    url = uri.to_s
    if(uri.path =~ /[.]rdf$/)
      url = parse_rss(uri)
    end
    system "cygstart #{url}" 
  end
  
  def parse_rss(uri)
    url = nil
    Net::HTTP.start(uri.host) do |http|
      begin 
        response = http.get(uri.path)
        rss = RSS::Parser.parse(response.body)
        url = rss.channel.link.to_s
      rescue 
      end
    end
    url
  end
目次へ





2. おわりに

今回の記事では,PhidgetsとPhidgetServerを用いて,既存のPCのユーザ・インタフェースを拡張するさまざまな PhidgetApplicationを紹介しました. 今回紹介したシステムは単体ではシンプルなものが中心ですが,アイデアや使い方次第で,その可能性は大きく広がります.たとえば, PhidgetMouseではマウス入力を,PhidgetLauncherでは,アプリケーションの起動/終了を制御することができるため,両者を組み 合わせて利用すれば,PhidetsからWindows PCの基本的な操作をほとんど行うことが可能になります. 是非,さまざまなセンサと既存のアプリケーションやWebサービスを組み合わせたシステム製作に挑戦してみてください.

次回は,実際の生活の中で利用できる実世界システムの構築を通して,日曜ユビキタス環境の実例を示していきたいと思っています.

目次へ


[1] [2] [3] [4]

[デバイスぶらり旅]