MENU

Raspberry Pi + OpenECHOでLチカ

ここ数日インフルエンザでぶっ倒れておりましたが、リハビリを兼ねて電子工作開始。

さて、自分のとりあえずの目標はRaspberry PiでOpenECHOを使えるようにすることです。その先にもう一個やりたいことがあるのだけれど、とりあえずはここまで。

前回、無事にRaspberry PiでのProcessing起動と、JavaでのGPIO制御ができるようになったので、あとはOpenECHO for Processingのライブラリを突っ込んでやるだけ。ライブラリはここからmasterのzipをとってきて、解凍した中のOpenECHO/OpenECHO for Processing/libraries/の中にある、controlP5ディレクトリとOpenECHOディレクトリを、前回のpi4jと同じように、各ユーザのsketchbook/librariesディレクトリにコピーする。今のところ、pi4jがrootになっていないとGPIO制御できないので、/root/sketchbook/libraries以下にコピーする。これで、/root/sketchbook/libraries以下には、pi4j, OpenECHO, controlP5の3つのライブラリ用ディレクトリが存在しているハズ。

続いて、Raspberry PiをOpenECHOのノードとしてECHONETに参加させるための、Processingのソースの作成。といっても、基本的に組み合わせるだけ。先ほど落としてきたOpenECHOのライブラリに含まれている、/OpenECHO/OpenECHO for Processing/libraries/OpenECHO/examples/Tutorial4_LightEmulator/Tutorial4_LightEmulator.pdeに、pi4jのLチカサンプルコードを組み合わせるだけです。

[code title=”GeneralLightingSample.pde” language=”java”]
import java.io.IOException;
import processing.net.*;
import controlP5.*;

import com.sonycsl.echo.Echo;
import com.sonycsl.echo.node.EchoNode;
import com.sonycsl.echo.eoj.EchoObject;
import com.sonycsl.echo.EchoProperty;
import com.sonycsl.echo.eoj.profile.NodeProfile;
import com.sonycsl.echo.eoj.device.DeviceObject;
import com.sonycsl.echo.eoj.device.housingfacilities.GeneralLighting;
import com.sonycsl.echo.processing.defaults.DefaultNodeProfile;
import com.sonycsl.echo.processing.defaults.DefaultController;
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;

color backgroundLightOnColor = color(255, 204, 0);
color backgroundLightOffColor = color(0, 0, 0);
color backgroundNow = backgroundLightOffColor;

GpioController gpio;
GpioPinDigitalOutput lightPin;

public class LightEmulator extends GeneralLighting{
byte[] mStatus = {0x31};
byte[] mLocation = {(byte) 0x80};
byte[] mFaultStatus = {0x42};
byte[] mManufactureCode = {0x00, 0x00, 0x00};

protected byte[] getOperationStatus() {
return mStatus;
}

protected boolean setOperationStatus(byte[] edt) {
mStatus[0] = edt[0];
if(mStatus[0] == 0x30){
backgroundNow = backgroundLightOnColor;
lightPin.setState(PinState.HIGH);
}else{
backgroundNow = backgroundLightOffColor;
lightPin.setState(PinState.LOW);
}
try{
inform().reqInformOperationStatus().send();
}catch(IOException e){
e.printStackTrace();
}
return true;
}

protected boolean setInstallationLocation(byte[] edt) {
mLocation[0] = edt[0];
try{
inform().reqInformInstallationLocation().send();
}catch(IOException e){
e.printStackTrace();
}
return true;
}

protected byte[] getInstallationLocation() {
return mLocation;
}

protected byte[] getFaultStatus() {
return mFaultStatus;
}

protected byte[] getManufacturerCode() {
return mManufactureCode;
}
}

// Use to create GUI
ControlP5 cp5;
LightEmulator lightEmu;

void setup(){
// Set display window size
size(400,400);
frameRate(30);

// Set OpenEcho
try{
lightEmu = new LightEmulator();
Echo.start(new DefaultNodeProfile(), new DeviceObject[]{lightEmu});
}catch(IOException e){
e.printStackTrace();
}

Echo.addEventListener(new Echo.Logger(System.out));

// Set pi4j
gpio = GpioFactory.getInstance();
lightPin = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_01, "MyLED", PinState.LOW);
lightPin.low();
} // End of setup()

void draw(){
background(backgroundNow);
};
[/code]

ブレッドボードとLEDの配線は、pi4jのLチカサンプルコードに記載のとおり。

th_led_test

最後に、照明(GeneralLighting)としてECHONETに参加したRaspberry Piをコントロールするために、PCをコントローラとしてECHONETに参加させるためのProcessingのソースを作成します。これも、ひょっとしたら/OpenECHO/OpenECHO for Processing/libraries/OpenECHO/examples/Tutorial4_LightEmulator/Tutorial4_LightEmulator.pdeがそのまま使えたのかもしれませんが、前に別に作っていたものを流用して作成。

[code title=”LightControlSample.pde” language=”java”]
import controlP5.*;

import com.sonycsl.echo.Echo;
import com.sonycsl.echo.node.EchoNode;
import com.sonycsl.echo.eoj.EchoObject;
import com.sonycsl.echo.EchoProperty;
import com.sonycsl.echo.eoj.profile.NodeProfile;
import com.sonycsl.echo.eoj.device.DeviceObject;
import com.sonycsl.echo.eoj.device.housingfacilities.GeneralLighting;

import com.sonycsl.echo.processing.defaults.DefaultNodeProfile;
import com.sonycsl.echo.processing.defaults.DefaultController;

// Use to create GUI
ControlP5 cp5;

// Set Appliace IP Address
final String targetIp = "192.168.24.210";

GeneralLighting myLight;

static final int GENERAL_LIGHTING = 0;

String[] applianceName = {
"GeneralLighting"
};
int applianceNum = applianceName.length;
boolean applianceFound[] = {false};

String[] btFnName = {
"searchAppliances",
"lightOn",
"lightOff"
};

String[] btLabel = {
"Search Appliances",
"GeneralLighting: ON",
"GeneralLighting: OFF"
};

void setup(){
// Set display window size
size(400,400);
frameRate(30);
myDraw();

// Set GUI
textSize(12);
cp5 = new ControlP5(this);

int btFnNum = btFnName.length;
for(int i=0;i<btFnNum;i++){
/* // Processing 2.1.1
Button bt = cp5.addButton(btFnName[i])
.setCaptionLabel(btLabel[i])
.setSize(200,20)
.setPosition(0,120+30*i);
*/
// Processing 2.0.3
ControlP5 bt = new ControlP5(this);
bt.addBang(btFnName[i], 0, 120+40*i, 100, 20);
bt.controller(btFnName[i]).setLabel(btLabel[i]);
}

// Set OpenEcho
try{
Echo.start(new DefaultNodeProfile(), new DeviceObject[]{new DefaultController()});
}catch(IOException e){
e.printStackTrace();
}

Echo.addEventListener(new Echo.Logger(System.out));
Echo.addEventListener(new Echo.EventListener(){

public void onNewGeneralLighting(GeneralLighting device){
super.onNewGeneralLighting(device);
if(!device.getNode().getAddress().getHostAddress().equals(targetIp)){
println("A GeneralLighting has found, but this is NOT yours.");
return;
}

println("Your GneralLighting has Found!");
applianceFound[GENERAL_LIGHTING] = true;
myDraw();
myLight = (GeneralLighting)device;

device.setReceiver(new GeneralLighting.Receiver(){
// Set Callback to get return values

protected void onSetOperationStatus(EchoObject eoj, short tid, byte esv, EchoProperty property, boolean success){
super.onSetOperationStatus(eoj, tid, esv, property, success);
if(!success){
println("error in call reqSetOperationStatus");
println("setOperationStatus Param=" + toHexStr(property.edt));
return;
}
showMessage("Success: onSetOperationStatus");
}

protected void onGetOperationStatus(EchoObject eoj, short tid, byte esv, EchoProperty property, boolean success){
super.onGetOperationStatus(eoj, tid, esv, property, success);
if(!success){
showMessage("error in call reqGetOperationStatus");
return;
}
showMessage("OperationStatus=" + toHexStr(property.edt));
}
}); // End of setReceiver
} // End of onNewGeneralLighting
}); // End of addEventListener

// Search controllable appliances
searchAppliances();

} // End of setup()

void draw(){

};

void myDraw(){
background(0,0,0);
for(int i=0;i<applianceNum;i++){
if(applianceFound[i]){
fill(0,255,0); // Green
text(applianceName[i] + " [FOUND!]", 0, 20+20*i);
}else{
fill(255,255,255); // white
text(applianceName[i] + " [NOT FOUND]", 0, 20+20*i);
}
}
}

public void searchAppliances(){
println("—-");
try{
// find other devices
NodeProfile.getG().reqGetSelfNodeInstanceListS().send();

println("Wait 3 seconds …");
try{
Thread.sleep(3000);
}catch(InterruptedException e){
e.printStackTrace();
}

println("—-");
EchoNode[] nodes = Echo.getNodes();
for(int i=0;i<nodes.length;i++){
EchoNode en = nodes[i];
println("node id=" + en.getAddress().getHostAddress());
println("node profile=" + en.getNodeProfile());
DeviceObject[] dos = en.getDevices();
println("There are " + dos.length + " devices in this node");
for(int j=0;j<dos.length;j++){
DeviceObject d = dos[j];
String typeName = d.getClass().getSuperclass().getSimpleName();
println("device type = " + typeName);
}
println("—-");
}
}catch(IOException e){
e.printStackTrace();
}
}

public void lightOn(){
println("–lightOn–");
if(applianceFound[GENERAL_LIGHTING]){
try{
myLight.set()
.reqSetOperationStatus(new byte[]{0x30}) // Light ON
.send();
}catch(IOException e){
e.printStackTrace();
}
}else{
showMessage("There are NO your controllable GeneralLightings.");
}
}

public void lightOff(){
println("–lightOff–");
if(applianceFound[GENERAL_LIGHTING]){
try{
myLight.set()
.reqSetOperationStatus(new byte[]{0x31}) // Light OFF
.send();
}catch(IOException e){
e.printStackTrace();
}
}else{
showMessage("There are NO your controllable GeneralLightings.");
}
}

String toHexStr(byte[] arg){
String ret = "" ;
for(int i=0;i<arg.length;++i){
ret += Integer.toHexString(arg[i] & 0xff) + " ";
}
return ret;
}

void showMessage(String message){
myDraw();
fill(255,255,255); // white
text(message, 0, 350);
println(message);
}
[/code]

targetIpの部分は、Raspberry Piの接続環境に応じて変更してください。

さて、これで準備完了。まず、Raspberry Piの方でGeneralLightingSample.pdeを(スーパーユーザ)で実行。続いて、同じローカルネット内のPCで、LightControlSample.pdeを実行。ProcessingのGUI上に”GeneralLighting [FOUND!]”と緑色で表示されていれば、Raspberry PiをECHONETのノードとして発見しており、制御可能な状態です。白色で”GeneralLighting [NOT FOUND”と表示されている場合は、”SEARCH APPLIANCES”ボタンを押してみてください。立ち上げ時にたまたま発見できなかった場合は、これで何度か手動で探しに行くことで見つかるハズです。それぞれ無事プログラムを起動できているにも関わらず、何度やっても見つからない場合は、PCとRaspberry Piの参加しているローカルネットが異なっている可能性があります。

さて、この状態になれば、後はPCのProcessing-GUI上のON/OFFボタンで、LEDのON/OFFができるようになっている…ハズ。自分の場合は、こんな感じになりました。

わかりにくくてすみませんが、マウスでGUIのON/OFF操作をしています。

さてさて、できたものはなんだかショボく見えるかもですが、ここまでできれば、あとはやる気次第でどうとでも拡張できるハズ。

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメント一覧 (1件)

目次