RaspberryPiでJavaFXとGPIO制御を組み合わせてみる…が、まだ完成していないorz

この記事は[Tech Women Advent Calendar 2014](http://qiita.com/advent-calendar/2014/tech_women) 19日目の記事です。


へもへもエンジニアの@shikiyakです。業界歴は長いのに、業界歴のほぼ全てを職業エンジニアwwwとして過ごしていますので、たいしたことはできません。できるのは、ふつーに業務システムを開発することくらいです。

そんな、職業エンジニアな私でも、プログラミングは大好きですし、プログラムが動くと嬉しいので、遊びのためのプログラムを書くことは多いです。

そういう遊びの場面、ちょっと前まではスマホアプリを作るのが楽しかったのですが、ちょっと飽きてきて。
今は、RaspberryPiを使った、ちいさいヘボヘボシステム作りが、自分的楽しい遊びになっています。

##RaspberryPiは
子供向け教育用に作られたシングルボードコンピューターです。日本では、教育用というよりも、Arduinoと並んで電子工作用として有名ですね…Lチカとか…

でも、基本は「教育用」なので、いろんなことができます！
なにしろ、OSはLinux！
DebianベースのRaspbian、それ以外にもいくつかのものが提供されています。
プログラム言語も、Linux環境でのセットアップ方法があれば、だいたい使えます。

ただ、CPUがARM11のため、コンパイル時などの遅さは…否めません。

でも、いいんです！遊びだから！！！

##趣味でやってみた JavaFX & GPIO Control
いちばん長く使っているプログラミング言語はJavaなので、ちょっとしたプログラムならJavaがいちばん楽に書けるということと、あと、Java女子部メンバーなので、何かJavaで作ってみたいなーと思い…（以前にはTwitter4Jを使ったTweetBotを作ったので）今回のTech Women Advent Calendar用に、JavaFXを使ったプレゼン用アプリを作ってみることにしました。


通常のプレゼンツールは、マウスクリックや矢印キー押下でページ送りをしますが、今回は、RaspberryPiなのでGPIOにモーメンタリー型のボタンをマウス代わりに使います。

モーメンタリー型ボタンを使った回路図は、以下のようにしました。
![キャプチャ.jpg](https://qiita-image-store.s3.amazonaws.com/0/46387/9101cf76-2225-7988-9e4e-0317a035c736.jpeg)
LEDが付いているのは、ボタン押下のイベントが発生したことを確認するためのデバッグ用なので、本番利用の場合には、LEDと抵抗は取り外しても構いません（むしろ取り外してほしい…）。

２つ付けたスイッチのうち、片方をページ送り、片方を中断終了のボタンにしました。


JavaFXのほうは、skrb氏の資料を参考にしました。
http://skrb.hatenablog.com/entry/2012/06/13/233944

GPIO Controlは、java.ioパッケージでも可能なんですが、できるだけJavaFXのイベントハンドラと似たコーディングにしたかったので、Pi4Jを使ってみました。
Pi4J : http://pi4j.com/

GPIO Controlでは、ボタンのイベントリスナーの資料のサンプルコードがPi4Jにあるので、それも資料として参考にしました。
http://pi4j.com/example/listener.html

資料は、ほぼこれだけでスタートして、出来上がったソースコードは、以下です。

```java:xxx.java
package rasppijoshi;

import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinDigitalInput;
import com.pi4j.io.gpio.PinPullResistance;
import com.pi4j.io.gpio.RaspiPin;
import com.pi4j.io.gpio.event.GpioPinDigitalStateChangeEvent;
import com.pi4j.io.gpio.event.GpioPinListenerDigital;
import javafx.application.Application;
import static javafx.application.Platform.exit;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

/**
 *
 * @author shikiyak
 */
public class RPiJavaFXPresenter extends Application {
    
    //表示するスライド画像ファイル名を表示順に登録する
    private final String[] viewGraphs = {
        "no1.jpg",
        "no2.jpg",
        "no3.jpg"
    };
    // 現在表示しているページ番号
    private int viewGraphIndex;
    
    
    @Override
    public void start(Stage primaryStage) {
        
        // RaspberryPIのGPIOを使えるようにする
        final GpioController gpio = GpioFactory.getInstance();

        StackPane root = new StackPane();        
        
        // GPIOイベントのハンドリングをする
        final GpioPinDigitalInput myButtonLeft = gpio.provisionDigitalInputPin(RaspiPin.GPIO_04, PinPullResistance.PULL_DOWN);
        final GpioPinDigitalInput myButtonRight = gpio.provisionDigitalInputPin(RaspiPin.GPIO_05, PinPullResistance.PULL_DOWN);

        // 左ボタンは、処理終了
        myButtonLeft.addListener(new GpioPinListenerDigital() {
            @Override
            public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) {
                exit();
           }
            
        });
        
        //右ボタンは、ページ送り
        myButtonRight.addListener(new GpioPinListenerDigital() {
            @Override
            public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) {
                if("HIGH".equals(event.getState().toString())){
                    moveViewGraph(root);
                }
            }
            
        });

        //シーンをサイズ指定で作成
        Scene scene = new Scene(root, 800, 600);        
        primaryStage.setScene(scene);
        primaryStage.show();
        moveViewGraph(root);
        
    }

     public static void main(String[] args) {
        launch(args);
    }
    
    private void moveViewGraph(StackPane root){
// ページをロード
        String imageURL = getClass().getResource(viewGraphs[viewGraphIndex]).toString();
        Image image = new Image(imageURL);
        ImageView next = new ImageView(image);
        root.getChildren().add(next);

// ページインデックスを進める
// 最後までいったら終了する
        viewGraphIndex++;
        if (viewGraphIndex >= viewGraphs.length) {
            exit();
        }        
    }    
}
```

このプログラムの中に「myButtonLeft」「myButtonRight」というオブジェクトがありますが、これがGPIOにつながっているボタンになります。

プログラムは、RaspberryPiで作らず、PC状のNetBeansで作ってjarだけRaspberrPiにSCPする方法で作業しました。

RaspberryPiで実行するためのコマンドは、jarファイル名が「Presenter.jar」だとすると以下のようになります。

`sudo java -Djavafx.screen=eglfb -classpath .:classes:lib/'*':Presenter.jar rasppijoshi.RPiJavaFXPresenter`

注意点として、
JavaFXを利用している場合は、シリアル接続した端末やSSH接続した端末では動作不良になります。
面倒なのですが、HDMIモニターにつないで動かしてあげる必要があります。

##まだ完成していない
結論として…実は、このプログラム、まだ動作しません。
起動するし、GPIOもキチンと検出できているのですが、画面遷移が動かないのです。JavaFXのみでGPIOを使わないものは画面遷移していて、そのソースコードからマウスのイベントハンドラを削除して、GPIO経由でモーメンタリースイッチの押下イベントをハンドリングするように変えたので、そこで間違ったのかな？とも思ったのですが…

どうもそうではないようで、モーメンタリースイッチ押下イベントは取れても、次の画面表示が行われないようです。

##遊びなので、のんびりやろうと思っています
まぁ、仕事ではないですし、これから冬休みの時期に入るので、ゆっくり取り組もうと思っています。

解決したら、ここを更新します。

##RaspberryPiに興味のある女性、集まってワイワイしませんか？

…こんな感じでゆるーくふわわーんとRaspberryPiに取り組んでみようかな～などと思う女性といっしょに、ワイワイしながら遊びたいなーと思い、RaspberryPiの女性オンリーユーザーグループを作ってみました。電子工作とか分からないし、プログラミングもそんなバリバリできないし、ギークじゃないし…という女性から
バリッバリなハイテクギーグな女性まで、万人受け入れＯＫなユーザーグループにしたいと思っています。RaspberryPi本体もたくさん（10台くらい）持っているので、サーバ組んでみたりもできます。面白そうと思ったら、気軽にGoogle Groupに登録してください♪

ゆるふあ女子のためのRaspberryPi User Group
https://groups.google.com/forum/?hl=ja#!forum/raspijoshi