BLOCCOを使ってなるべくGALAXY Tabに触らずに家の無線とMobile APを切り替えられるようにする

GALAXY Tab、ちまたでは買ってはいけないとか言われていますが、いいデバイスですよね。

Wi-Fiルーターとして(爆)

自分はデータカード契約のSIMで外ではbiblio(auのWi-Fi対応フィーチャーフォン)、iPhone 4といった各種デバイスをGALAXY TabのMobile APで繋いでいますが、これは家では家の無線につながってほしいのです。特に、GALAXY Tab自体ではこちらの記事で書いたとおり、家のネットワークから定期的にPodcastをダウンロードするため、家のWi-Fiに繋いでおく必要があります。

家に着いたらWi-Fiに切り替えて、家から離れたらMobile APを起動する。この操作が意外とめんどくさい。これを自動化できれば充電ケーブルを繋ぐ以外のことをしなくてよくなり大変便利になります。

最初は自力で実装しようとしたのですが、BLOCCOという、各種動作を自動化するアプリがありましたので、これを使うことにしました。

家に着いたときにWi-FiをONにする

まずは家についたときにMobile APを落としてWi-Fiにつなぐことを考えます。Wi-Fi ONはBLOCCO標準のアクションで可能です。Wi-FiをONにさえすれば、Mobile APは自動的にOFFになるので、これをONにするだけすればいい。

第一選択になるのはGPSですが、正直宅内ではあまり精度が出ません。やはり電気的な接点でないと。しかし、充電をトリガーにすると、今度は外で充電できなくなってしまいます。

家にいるときしかやらないこと、そう思って思案すると「家のメインマシンのDockにiPhone 4を繋ぐ」という動作は必ず家にいないとできないことだと気づきます。つまり外部からGALAXY Tabに通知を送ることになります。

ここで登場するのが、C2DM(Cloud to Device Messaging)プラグイン。専用のWebサイトでリンクをクリックするのをトリガーに、Android側で各種動作を行うことができます。

BLOCCO C2DM - Android Apps on Google Play

これで、PC側から通知を送ってWi-FiをONにすることができます。自動的に実行するためにはもう一手間必要で、Googleアカウントでログインできるプログラムが必要になります。僕は家のサーバーでRubyを使ってこのように書きました。

#!/usr/bin/env ruby
require 'rubygems'
require 'mechanize'

class BloccoC2DM
  def initialize(email, passwd)
    @email = email
    @passwd = passwd
  end

  def call(button)
    index = {'a' => 0, 'b' => 1, 'c' => 2, 'd' => 3}[button]
    if index == nil
      raise ArgumentError, "invalid argument"
    end

    agent = WWW::Mechanize.new
    agent.follow_meta_refresh = true
    agent.get('http://c2dm.gclue.jp/blocco/')
    agent.page.link_with(:text => 'login').click
    form = agent.page.forms[0]
    form.field_with("Email").value = @email
    form.field_with("Passwd").value = @passwd
    form.submit
    agent.page.links[index].click
  end
end

if $0 == __FILE__
  require 'pit'

  config = Pit.get("blocco_c2dm", :require => {
    "email" => "Your Google account mail address",
    "passwd" => "Your Google account password"
  })

  BloccoC2DM.new(config['email'], config['passwd']).call(ARGV[0])
end

コレを使えば ruby blocco_c2dm.rb a などでWebのボタンリンクを押すのと同じ効果を得ることができます。

ところがどっこい、LinuxにおいたんじゃWindowsから叩くことができません。というわけで、SinatraでWebAPI化します。

require 'rubygems'
require 'sinatra'
require 'defines'
require 'blocco_c2dm'

get '/wifion/' do
   BloccoC2DM.new(C2DM_USER, C2DM_PASS).call('a')
   'ok'
end

get '/apon/' do
   BloccoC2DM.new(C2DM_USER, C2DM_PASS).call('b')
   'ok'
end

defines.rb は C2DM_USER と C2DM_PASS を定数初期化してあるだけのファイルです。

あとはwget for Win32だけでOK!と思いきや、ここまでやって気がついたのですがiPhoneはちょっと居間に行くとかそういうときにDockからはずすことがあります。あまり短期間の間に乱発されるのも困りもの。そういうわけで結局WindowsにもRubyを入れて、以下のスクリプトを動かすことに...

require 'open-uri'

DIF=3600
URL='http://<your_web_api_url>/wifion/'
STATUS_FILE='C:/Users/your_home_directory/galaxytab_last_wifion_exec.txt'

now = Time.now.tv_sec
last_exec = File.read(STATUS_FILE).chomp.to_i

if (now - last_exec) > DIF
  open(URL){|f| f.read }
end

while true
  open(STATUS_FILE, 'w'){|f| f.puts Time.now.tv_sec.to_s }
  sleep 15
end

15秒ごとにチェック時間をファイルに書き込んで、起動したときに時間が1時間以上離れていたらWebAPIを叩いてGALAXY Tabの設定を変更します。

次にUSBにiPhoneが刺さった検知です。これはexeUSBで簡単にできます。iPhoneに対して以下のように設定します。

そうそう、GALAXY Tab側の設定がまだでした。BLOCCOで以下のようなミニアプリ設定を作ります。

これでiPhoneをDockにさすと、GALAXY Tabの設定が切り替わってWi-FiがONになり、家のネットワークを自動でつかみます。また、それ以外のMobile APにつながっていたデバイスも自動的に稲のネットワームを探し出し、接続します。

家から出たら、Mobile APを起動する

まず、Mobile APのプラグインが対応してなかったため、プラグインを書きました。

Tethering Setting for BLOCCO - Android Apps on Google Play

次に、どのようなときに家から出たかを判断するかですが、またGPSは第一選択に入るものの確実じゃないので、無線LANの圏外にGALAXY Tabが出たことを判断基準にします。

まず、無線LANにつながった際、GALAXY Tabに固定のIPが払い出されるよう、DHCPサーバーの設定を変更しておきます。

次に、サーバーで以下のスクリプトをcronで1分おきに実行します。

#!/usr/bin/env ruby
require 'open-uri'
require 'ping'

DIF=120
URL='http://<your_web_api_url>/apon/'
STATUS_FILE='/home/<your_home_directory>/.galaxytab_ping'
IPADDR='<your_galaxy_tab_fixed_ip>'

now = Time.now.tv_sec
last_exec = File.read(STATUS_FILE).chomp.to_i

if Ping.pingecho(IPADDR)
  File.open(STATUS_FILE, 'w'){|f| f.puts(now.to_s) }
elsif last_exec > 0 && ((now - last_exec) > DIF)
  File.open(STATUS_FILE, 'w'){|f| '0' }
  open(URL){|f| f.read }
end

2分以上GALAXY Tabが家のネットワークから圏外にいた場合はC2DMを送って、Mobile APを起動します。ミニアプリ側の設定はこんな感じ。

これで、GALAXY Tabをもって家から少し離れるとネットワークが切断されてMobile APが起動し、家のネットワークを見失った各デバイスもMobile APに接続します。

このように、無理くりやればGALAXY Tabを家のネットワークとMobile APとでスムーズにハンドオーバーできます。

こんなんやるのは僕だけだと思ったので適当に書きましたが、もし参考になればと。