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機器として認識されるようにします。ここまでやれば、だいぶ使えるものになる。。。ハズ。 […]