Raspberry Pi + OpenECHOでECHOENT Lite機器を自作する【完全版】その②
前回の続きで、Raspberry PiのGPIOを制御するコードを追加していきます。
以下では、前回作成したプロジェクトのコピー(EchoDevicePi)を使って進めていきます。もちろん前回のプロジェクト(EchoDevice)にそのまま追記していく形で進めてもらってOKです。個人的に分けて残しておきたかっただけなので。
では早速。
JavaからRaspberry PiのGPIOを制御するためのライブラリPi4Jをここからもってきます。とりあえず、pi4j-1.0-SNAPSHOT.zipを使うことにします。
“pi4j-1.0-SNAPSHOT/lib/pi4j-core.jar”をEchoDevicePiの下にコピーしてきて、ビルドパスに追加します。
あとはMain.javaとLightEmulator.javaを修正します。
package jp.weblike.makemuda.echodevice; import java.io.IOException; import com.pi4j.io.gpio.GpioController; import com.pi4j.io.gpio.GpioFactory; import com.pi4j.io.gpio.GpioPinDigitalOutput; import com.pi4j.io.gpio.PinState; import com.pi4j.io.gpio.RaspiPin; import com.sonycsl.echo.Echo; import com.sonycsl.echo.eoj.device.DeviceObject; import com.sonycsl.echo.processing.defaults.DefaultNodeProfile; import jp.weblike.makemuda.echodevice.devices.*; public class Main { public static GpioController gpio; public static GpioPinDigitalOutput lightStatusPin; public static GpioPinDigitalOutput lightOperationPin; static private LightEmulator light; public static void main(String[] args) { Echo.addEventListener(new Echo.Logger(System.out)); // ログ出力 gpio = GpioFactory.getInstance(); lightStatusPin = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_00, "LightStatusLED", PinState.HIGH); lightOperationPin = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_02, "LightOperationLED", PinState.LOW); Main mainThread = new Main(); mainThread.exec(); } void exec() { Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { lightStatusPin.low(); lightOperationPin.low(); gpio.shutdown(); System.out.println("Quit ECHONET Lite Program."); System.out.flush(); } }); try { light = new LightEmulator(); Echo.start(new DefaultNodeProfile(), new DeviceObject[]{light}); } catch (IOException e) { e.printStackTrace(); } } }
package jp.weblike.makemuda.echodevice.devices; import java.io.IOException; import jp.weblike.makemuda.echodevice.Main; import com.sonycsl.echo.eoj.device.housingfacilities.GeneralLighting; public class LightEmulator extends GeneralLighting { byte[] mStatus = {0x31}; // 電源状態を格納する変数です。デフォルトは OFF と仮定します。 byte[] mLocation = {0x00}; // 機器の置き場所を格納する変数です。 byte[] mFaultStatus = {0x42}; // 機器に問題が発生した時に、そのコードを格納します。 byte[] mManufacturerCode = {0, 0, 0}; // ベンダー固有のメーカーコードです。 @Override protected boolean setOperationStatus(byte[] edt) { mStatus[0] = edt[0] ; //電源状態が変化したことを他のノードに通知します try{ // ------------------------------------------------------------------ // この部分に、実際に照明を点灯/消灯させるためのコードを書く。 if(mStatus[0] == 0x30){ System.out.println("Light ON!"); Main.lightOperationPin.high(); inform().reqInformOperationStatus().send(); }else if(mStatus[0] == 0x31){ System.out.println("Light OFF!"); Main.lightOperationPin.low(); inform().reqInformOperationStatus().send(); }else{ System.out.println("Parameter Error: Can NOT operate status"); } // ------------------------------------------------------------------ }catch(IOException e){ e.printStackTrace(); } return true; } @Override protected byte[] getOperationStatus() { return mStatus; } @Override protected byte[] getLightingModeSetting() { // TODO 自動生成されたメソッド・スタブ return null; } @Override protected boolean setLightingModeSetting(byte[] arg0) { // TODO 自動生成されたメソッド・スタブ return false; } @Override protected byte[] getFaultStatus() { // TODO 自動生成されたメソッド・スタブ return mFaultStatus; } @Override protected byte[] getInstallationLocation() { // TODO 自動生成されたメソッド・スタブ return mLocation; } @Override protected byte[] getManufacturerCode() { // TODO 自動生成されたメソッド・スタブ return mManufacturerCode; } @Override protected boolean setInstallationLocation(byte[] edt) { mLocation[0] = edt[0]; try{ inform().reqInformInstallationLocation().send(); }catch (IOException e) { e.printStackTrace(); } return true; } }
lightStatusPinは、プログラムが動作していることを示すためのLEDを光らせておくための制御ピンです。プログラムの開始と同時に点灯、終了と同時に消灯します。lightOperationPinは、ECHONET LiteのON/OFF操作で実際に照明代わりのLEDのON/OFF操作をするための制御ピンです。
ということで、このプログラムは2つのLEDに接続して使うことを想定しています。
Main.javaでスレッドを利用している理由は、Raspberry Pi上でjavaを実行させた後、Ctrl+Cで強制終了させるときにGPIO関係の後始末をさせたかったからです。
プログラムを修正したあとは、実行可能なjarファイルとしてエクスポートして、あとはRaspberry Piに持っていって実行するだけ!…とやれればスマートでカッコ良かったのですが、やってみた結果、プログラムは動くものの、なぜかGPIOの制御がきかず。。。仕方がないので、ソース(Main.javaとLightEmulator.java)とライブラリ(echo.jarとpi4j-core.jar)をRaspberry Piに持ってきて、Rsapberry Pi上でコンパイルして実行することにします。ああ、カッコ悪い。。。ライブラリの参照とかの問題なのだろうけれど。
Raspberry Piは事前にJavaを使えるようにしておいてください。自分はこのあたりを参考にJDKを入れましたが、少し時間が経っているので、他にもっとわかりやすい解説サイトがあるかもしれません。
Raspberry Pi上に、適当に”echonet”とかのフォルダを作って、その中に、以下のようにファイルを持ってきます。手段はscpでもsambaでも何でもOKです。
- Main.java
- LightEmulator.java
- lib/echo.java
- lib/pi4j-core.java
javaファイルにパッケージ云々の記述があると実行時に失敗するので、javacでコンパイルする前に、Raspberry Piに持ってきたMain.javaの1行目と14行目、LightEmulator.javaの1行目と5行目はコメントアウトしておいてください。ああカッコ悪い。。。
ファイルを置いたディレクトリに移動してきたら、javacでコンパイルします。
$ javac -cp lib/echo.jar:lib/pi4j-core.jar Main.java LightEmulator.java
日本語のコメント関係でエラーが出てくるようであれば、eclipseのテキストのエンコードがUTF-8になっている確認してください。
無事にclassファイルが生成されたら、以下で実行です。
$ sudo java -cp .:lib/echo.jar:lib/pi4j-core.jar Main
特に問題なければ、PCで実行したときと同じようなログが出力されるはずです。Raspberry PiとAndroid端末を同じローカルネットに繋いでいれば、Kadecotで新しいGeneralLightingが発見されます。
こんな感じで配線してもらえたら、プログラムの開始と同時に赤色LEDが点灯し、KadecotからのON/OFF操作で緑色LEDが点灯/消灯するはずです。Ctrl+Cで強制終了すると、両LED共に消灯します。
思ったよりつまづいた上に、大変カッコ悪い進め方になってしまいました。。。完全版をうたっておきながら。
とりあえず使えるものをつくるため、ラスト、Raspberry Piの電源ONで、このプログラムが自動スタートするようにしたいと思います。
ディスカッション
ピンバック & トラックバック一覧
[…] 前回の続き、最後です。Raspberry Piを立ち上げると、自動的にECHONET Lite機器として認識されるようにします。ここまでやれば、だいぶ使えるものになる。。。ハズ。 […]