ラズパイからnode.jsを使ってECHONET Liteエアコンの操作をする

  • 25
    Like
  • 0
    Comment
More than 1 year has passed since last update.

本記事ではラズパイからECHONET Liteのエアコンを動かす方法を解説します。
ECHONET Liteそのものの説明を加えていますので長くなってしまいましたが、プログラム自体はnode.jsで7行ほど書くだけです。

ちなみに次回の記事ではラズパイ+3GPIを使ってエアコンの遠隔操作をしたいと思います。そちらにもご興味がおありの方は、ラズパイに挿すSDカードとしては3GPI付属のものを用いておいてください。

遠隔操作に興味がない方は、普通のRaspbianでも大丈夫です。実はnpmが入れられさえすればラズパイである必要すらないのですが、それは聞かなかったことにしてくださいw

今回使用するシステム

・RaspberryPi 1 Model B Rev.2
・node.js
・ECHONET Liteのnpmパッケージ (https://www.npmjs.com/package/echonet-lite)
・ECHONET Liteエアコンまたはエアコンのエミュレータ

2.jpg
いわゆるいつものラズパイですね。(ちょっと古いけど)

ECHONET Liteとは

ECHONET Liteとは国内白物家電の標準プロトコルです。対応のエアコンとか照明とかいろんなものが動きます。全世帯に導入が決まっているスマートメーターもECHONET Liteでデータを取得可能です。スマートフォンなどから動かせるエアコンは、そうと明記してなくてもECHONET Lite対応のものがほとんどだと思っていいでしょう(赤外線学習リモコンで動かすものは別です)。
 Wikipedia : https://ja.wikipedia.org/wiki/ECHONET_Lite
 ECHONET Consortium : http://echonet.jp/
 ECHONET Lite製品リスト:http://echonet.jp/product/echonet-lite/

※ECHONET Lite対応機器をお持ちでない方は、私が作っているエミュレータを同じネットワーク内で立ち上げれば体験することができます。ぜひお試しください!
 http://kadecot.net/blog/1479/

echonet-lite npmパッケージのインストール

最近神奈川工科大学の杉村先生からECHONET Liteのnpmパッケージがリリースになったので、これを使ってみることにしました。
 https://www.npmjs.com/package/echonet-lite

では作業に取り掛かりましょう。

まず、ECHONET Liteのパッケージを入れるためのnpmを先にインストールします。さらにその前に、aptを更新しておきます。

sudo apt-get update
sudo apt-get upgrade

ラズパイ1だからか、upgradeのほうは結構時間がかかりますね。途中で

Configuration file '/etc/udev/rules.d/99-com.rules'
==> File on system created by you or by a script

なんて出て止まったりしますが、気にしないことにしてデフォルトのN (元のファイルをキープ)を選びます。(私の環境では、3GPIのSDカードを用いたときのみこの症状が起こりました)

upgradeが終わったら、npmをインストールしましょう。

sudo apt-get install npm

次に、ECHONET Lite用のnpmモジュールをインストールします。

npm install echonet-lite

機器一覧を取得するプログラムを作成する

では最初に、ネットワーク内に存在するECHONET Liteの家電リストを取得してみましょう!以下のソースコードをテキストエディタなどで作成してください。

run0.js
var EL=require('echonet-lite');
var objList=['05ff01'];
var elsocket=EL.initialize(objList,function(rinfo,els){
  console.dir(rinfo);
  console.dir(els);
});

EL.search();

これをnode.jsで動かします。

node run0.js

結果は例えばこんな感じになります。

{ address: '192.168.0.110', family: 'IPv4', port: 58319, size: 14 }
{ EHD: '1081', TID: '0000', SEOJ: '05ff01', DEOJ: '0ef001', EDATA: '6201d600',
ESV: '62', OPC: '01', DETAIL: 'd600', DETAILs: { d6: '' } }
{ address: '192.168.0.148', family: 'IPv4', port: 3610, size: 24 }
{ EHD: '1081', TID: '0000', SEOJ: '001101', DEOJ: '05ff01', EDATA: '72019f0a09e08281809e9f9d8a88',
ESV: '72', OPC: '01', DETAIL: '9f0a09e08281809e9f9d8a88', DETAILs: { '9f': '09e08281809e9f9d8a88' } }
{ address: '192.168.0.110', family: 'IPv4', port: 34199, size: 18 }
{ EHD: '1081', TID: '0000', SEOJ: '0ef001', DEOJ: '05ff01', EDATA: '7201d6040105ff01',
ESV: '72', OPC: '01', DETAIL: 'd6040105ff01', DETAILs: { d6: '0105ff01' } }
                  ・
                  ・
                  ・

ちょっとわかりづらいかもしれませんが、各行がJSON形式になっていることはわかると思います。
これらの文字列は、ラズパイからECHONET Liteのパケットが送受信された時に表示されます。大きく分けて、addressから始まる行と、EHDからはじまる行があります。これらの行を出力しているのは元のプログラムでの

console.dir(rinfo);
console.dir(els);

という2行ですから、rinfoにaddressが含まれ、elsにEHDが含まれることがわかります。
addressは、送信元のIPアドレスを表しています。ここのIPアドレスがラズパイと一致している行は送信です。そうでないものは、他のECHONET Lite機器からの受信です。

ECHONET Objectの形式

ECHONET Liteでは、一つのIPアドレス上に任意の種類、かつ複数の機器を配置することができます。これを特定するのがSEOJとDEOJです。これはSource ECHONET Object, Destination ECHONET Objectのことで、送信元と送信先を表し、それぞれ3バイトからなっています。

この3バイトのうち、最初の2バイトは機器の種類を表しています。
残り1バイトはインスタンスIDで、同じIPアドレス上に同じ種類の機器が複数ある場合にそれらを区別します。通常は1からカウントアップします。

機器の種類はさらに、クラスグループコードとクラスコード(各1バイト)に別けられ、機器の大分類・小分類を表していますがセットで扱われることが多いです。16進数で表示されていますが、ECHONET機器オブジェクト詳細規定を見れば、実際の機器種類との対応はわかります。

例えば、

SEOJ: '001101'

という部分があります。この001101というのは、種類を表す0011とインスタンスを表す01に分けられ、0011は「温度計」を表しています。その上の行に

address: '192.168.0.148'

とありますから、IPアドレスが192.168.0.148の機器の中に温度計オブジェクト1番があるということになります。
また、ソースコード中の

EL.initialize()

というメソッド呼び出しの最初の引数が文字列の配列になっており、

['05ff01']

が与えられています。これは、このプログラム自身をどんな機器としてECHONET Liteネットワークに参加するかという設定で、ECHONET Objectのフォーマットになっています。05ffというのは「コントローラ」という種類の機器です。ラズパイ上に載っている自分自身を表現する機器ですから、全ての送受信のSEOJかDEOJのどちらかにこのオブジェクトが乗っていることになります。逆に言えば、自分がECHONET Lite機器にならずしてECHONET Liteプロトコルでの通信をすることはできないわけです。

二行目にある

DEOJ: '0ef001'

というのはちょっと特殊なオブジェクトで、全てのECHONET機器が必ず持つ「ノードプロファイル」というものになります。詳細は省きますが、ネットワーク内すべての機器に「ノードプロファイル」を返答せよと呼びかけることによって、ネットワーク内にある全てのECHONET Lite機器を探索できることになります。これがEL.search()の動作です。

機器の種類のうち目ぼしいものは、最初に載せたエミュレータのページにもあります。
一応表のみ転記しておきます。

EOJ.png

長くなりましたが、結局のところ先程のプログラムの実行結果のSEOJ(とDEOJ)を注意深く見ていくことによって、ネットワーク内に存在する機器がわかるというわけです。

よくみていくと、こんな行がありました。(IPアドレス等、環境によって異なる部分が含まれます)

{ address: '192.168.0.148', family: 'IPv4', port: 3610, size: 19 }
{ EHD: '1081', TID: '0000', SEOJ: '013001', DEOJ: '05ff01', EDATA: '72019e0504b081b380',
ESV: '72', OPC: '01', DETAIL: '9e0504b081b380', DETAILs: { '9e': '04b081b380' } }

SEOJが013001になっています。0130はエアコンです。そう、私はECHONET Liteのエアコンを持っているんです。(エミュレータにも含まれています)

EL.sendOPC1で機器操作を行う

このエアコンの電源を入れてみましょう。先程のrun0.jsの最終行EL.search()をEL.sendOPC1()に置き換えます。

run0.js
var EL=require('echonet-lite');
var objList=['05ff01'];
var elsocket=EL.initialize(objList,function(rinfo,els){
  console.dir(rinfo);
  console.dir(els);
});

EL.sendOPC1('192.168.0.148',[0x05,0xff,0x01],[0x01,0x30,0x01],EL.SETI,0x80,[0x30]);

sendOPC1の引数は次のようになります。

・送信先IPアドレス
  先程エアコンが返答を返してきた192.168.0.148となります。
・SEOJ (送信元ECHONET Object)
  自分自身の機器オブジェクトです。EL.initialize()の引数に与えた05ff01です。
・DEOJ(送信先ECHONET Object)
  送信先エアコンで、先ほどの返答からインスタンスIDが1なので013001
・送信方式
  いろいろありますが通常は「値設定」(EL.SETI)か「値取得」(EL.GET)しか使いません。
  今回は電源の設定なので、EL.SETIです。
・対象プロパティ
  「プロパティ」とは、機器が持つ「機能」と言い替えてもよいでしょう。
  電源は0x80であるとECHONET機器オブジェクト詳細規定に書かれています。
  (先ほどの表もご覧ください)
・送信方式がEL.SETIの場合は設定する値の配列
  電源のONは[0x30]、OFFは[0x31]です。こちらもECHONET機器オブジェクト詳細規定をご参照ください。

こうしておいて、

node run0.js

と再度プログラムを走らせると、エアコンの電源が入りました。

AirconOn.jpg

ちなみに、ECHONET Lite経由で操作すると、赤外線リモコンで操作したときと異なり「ピッ」という操作音がしないことが多いです。
映画などの演出で風を出したりする時などにもってこいですね!(笑

エミュレータだとこのようになります。

[Before]

cap2.jpg

[After]

cap3.jpg

エアコンの電源が入っていますね。

まとめ

ECHONET Liteは意味さえ分かれば非常に簡単に機器を制御できる単純なプロトコルです。また、npmパッケージにもなっているので詳細を知らなくても使える環境が整ってきていると思います。
npm版はまだ出てきたばかりということもあり、割と素の16進数を使う必要がありますが、OpenECHOという、よりメソッドっぽく使えるオープンソースのECHONET Liteドライバライブラリもあります。Processing (Java)版や、C++版があります。こちらもよかったらどうぞ。

次回の記事では今度は3GPIやクラウドサーバなどを用いて、ラズパイ経由で家電を遠隔地からON/OFFできるようにしたいと思います。よろしければぜひご覧ください!