Archives for 12月2011

Play Frameworkのジョブ確認にCapsロックのLEDを使う!!

12月1日より始まったPlay! framework Advent Calendar 2011 jp #play_ja

第1回目は、PlayFrameworkの東京勉強会でも主催された @ikeike443 さんでした。

Play! framework 概要 Tipsもあるよ! – 複雑系スパゲティソース(はてな版)

僕は2日目を担当させていただきます。

今回のテーマは、
「Play Frameworkのジョブ確認にCapsロックのLEDを使う!!」
です。

いきなり、ニッチすぎる。。

ジョブっていつ実行されてるかわかんないですよね。ログとかターミナル見るのも面倒だし。手元で確認できたらいいよね、みたいな。ただ、今回の場合はローカルで実行しているPlayのみ対応です。サーバーで動いているジョブでも対応させようとしたら、なんらかのAPIを用意してやる感じになるでしょう。

@ikeike443 さんのブログにもありましたが、Play Frameworkのジョブは、play.jobs.Jobというクラスを継承して作ります。
ジョブには、@OnApplicationStartというアプリケーション起動時になにかを行うタイプのジョブと、Cronみたいに指定したタイミングで動作させるタイプのものがあります。

Cronみたいに使う際は、@On(“*/30 * * ? * * *”)みたいな感じで使います。この例では、30秒に1回起動する形になります。このあたりはCronとかと似ているので理解しやすいと思います。

Cronの指定をソースコード内に書く事で、Gitとかでバッチ処理のコードも管理することが出来るため、アプリケーションの一元管理をしやすくなります。PHPのときは、Cron用のファイルを用意したりしてました。
Play Frameworkのジョブを使う際には注意しなければいけない点として、DEVモードで起動している場合は一度どこかのページにアクセスする必要があるということがあります。

さて、本編に入る前にPlayと僕的なハナシをしようと思います。

Play Frameworkを使い始めたのは、play-1.0.3.2からです。ただ、その頃はちょっと触っただけでやめてしまったので、本格的に触り出したのは、1.1からです。自分の仕事ではずっとデザイントレンドのリサーチをライフワークとしており、これはCakePHPベースで作ってきたのですが、Play Frameworkでリニューアルしはじめたところから始まりました。

本編に戻ります。

僕はメイン機にMacBook Airを使っているんですが、US配列のキーボードを使っており、おまけにCapsロックキーをCtrlキーにしてしまっていて、Capsロックの出番は皆無です。というか使った事がありません。

しかしながら、Capsロックには、LEDがついており、MacBook Airのキーボードでも唯一といっていいコンピューターからのフィードバックがあるエリアなのです。

ここを有効活用したいと思い、今回はジョブを実行したら点滅させるということを目指します。ググると、いました!! 先人が。

Official Google Mac Blog: Manipulating keyboard LEDs through software

このソフトウェアは、Cで書かれていて、コンパイルをして使用します。
コンパイルにはXCodeが必要です。

karad @ device-f205b8 : ~
$ gcc -Wall -o keyboard_leds keyboard_leds.c \
>         -framework IOKit -framework CoreFoundation

こんな感じでコンパイルを終えたらテストをしてみます。
まずは、実行権限を与えて、

karad @ device-f205b8 : ~
$ chmod 707 ./keyboard_leds

-rwx---rwx    1 karad  staff           15296 11 21 10:41 keyboard_leds
-rw-r--r--@   1 karad  staff           11541 11 21 10:41 keyboard_leds.c

-hオプションをつけて、使い方を確認します。

karad @ device-f205b8 : ~
$ keyboard_leds -h

keyboard_leds (version 0.1)
Copyright (c) 2007,2008 Amit Singh. All Rights Reserved.
Manipulate keyboard LEDs

Usage: keyboard_leds [OPTIONS...], where OPTIONS is one of the following

  -c[1|0], --capslock[=1|=0] get or set (on=1, off=0) caps lock LED
  -h,      --help            print this help message and exit
  -n[1|0], --numlock[=1|=0]  get or set (on=1, off=0) num lock LED

Cオプションを使うことでLEDを点灯させたり出来るみたいですね。
ということで実験。

karad @ device-f205b8 : ~
$ keyboard_leds -c1

off
on

すると、、、

P2

おお、ついた(笑

karad @ device-f205b8 : ~
$ keyboard_leds -c0

on
off

とやると、、、

P1

消えた(笑

ただし、このままではつけるか消えるしかないので、点滅させてみましょう。
こちらはシェルスクリプトでやります。Play Framework側からアクセスしやすくする意味もあります。

#!/bin/bash
$1/keyboard_leds -c1
sleep 0.1
$1/keyboard_leds -c0
sleep 0.1
$1/keyboard_leds -c1
sleep 0.1
$1/keyboard_leds -c0
sleep 0.1
$1/keyboard_leds -c1
sleep 0.1
$1/keyboard_leds -c0
sleep 0.1

exit;

なんともベタな書き方ですが、今回はこんな感じでいきます。
このシェルスクリプトは引数をひとつとります。引数はkeyboard_leds自体へのパスです。
実行させると、ピカピカと点滅を3回繰り返します。

さて、ようやくPlay Framework側から使ってみます。
まずは、app/libというパッケージを用意して、その中にFlashLightというクラスを作ります。
このクラスを様々なコントローラーやジョブから使おうというわけです。

package lib;

public class FlashLight {
    public static void on(String appPath) {
        Runtime r = Runtime.getRuntime();
        try {
            Process p = r.exec(appPath + "/keyboard_leds.sh " + appPath);
            Thread.sleep(1000);
            System.out.println("LED is ok.");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

FlashLight.onというスタティックメソッドを用意しました。
onメソッドの引数としてkeyboard_ledsへのパスをとる形にしています。

これをテストしてみましょう。
テストコードはこんな感じですが、こういうのはどうテストするのかよくわかりません。とりあえず光らせるだけやってみる感じで。。

import org.junit.*;
import play.test.*;
import lib.*;

public class FlashLightTest extends UnitTest {

    @Before
    public void setUp() {
        //
    }

    @Test
    public void testFlashLightOnOff () {
        try {
            FlashLight.on("/Users/hogehoge");
            Thread.sleep(2000);
            FlashLight.on("/Users/hogehoge");
            Thread.sleep(2000);
            FlashLight.on("/Users/hogehoge");
            Thread.sleep(2000);
            FlashLight.on("/Users/hogehoge");
            Thread.sleep(2000);
        } catch (Exception e) {
            e.printStackTrace();
            fail(e.getMessage() + " is expected");
            return;
        }
    }
}

4回光るはずですが、光らない事があります。
いやな予感がしますね。ただ、今回はネタなので、気にせず進めます。

続いて、何かのページを表示させたらCapsロックのライトを光らしてみましょう。
適当なコントローラにこんな感じで、表示時に呼び出すように書きます。

public static void index() {
    // 表示データの取得
    entities = Model.getEntries().orderBy("modified DESC");
    FlashLight.on("/Users/hogehoge");
    renderTemplate("Sites/index.html", entities);
}

すると、当たり前ですが、光ります。ということで、続いてジョブに組み込んでみます。
組み込むというか差し込むだけですが。

@On("*/30 * * ? * * *")
public class MyJob extends Job {

    @Override
    public void doJob() {
        boolean result = false;
        System.out.println("My job start.");
        FlashLight.on("/Users/hogehoge");
        result = captureOverseas();
    }
}

ということで、無事ジョブが実行されるとCapsロックキーが点滅しますが、点滅しないこともあります。これは想定済みではあるのですが、どうも気分が悪いです。おそらく独立したプロセスで呼んでいるライブラリが、同じ事をしようとしておかしなことになっているような気がします。そこで、たぶんですが、もうちょっとちゃんと監視してごにょごにょするとよくなりそうです。

今回はこれで終わりにします。
ではでは。

Play! framework Advent Calendar 2011 jp3日目は @kitora_naoki さんです。

よろしくお願いします!!

Read More