IchigoJamでパソコンとUSBシリアル通信。Node.jsでスマート電球Hueをコントロールしてみよう!
IchigoJamでUSBシリアル通信ができるとこんな事もできちゃう
手のひらサイズの小さなガジェットIchigoJamは子供向けの学習用パソコンです。手のひらに乗るほどの小さな基板で昔懐かしいBASICが動作するので、子供の頃にBASICで遊び倒した世代にはちょうどいいおもちゃです。そんな訳で、ここのところIchigoJamの工作にハマっています。
先日は、USBシリアル通信で、パソコンから操作する術を学びました。
これを一歩前進させ、本日はIchigoJamを使って、通信プロトコルの勉強をしたいと思います。
まずは結果から。本日の作品は、以下の動画のようなものです。
子供向けパソコンIchigoJamの基板には小さなプッシュ式のボタンが付いています。これを押すと動画の右側にある電球が赤く発光します。もう一度押すと、色が赤から黄色に変化。もう一度押すと、また色が変わります。ボタンを押す毎に色が何度か変化し、最後にはまた電球が消える、というものです。
これ自体にどんな意味があるかは、あまり深く考えないにしましょう笑。学習用の工作だと思ってください。
でも、プログラムとしては面白いと思いませんか??
IchigoJamでスマート電球Hueをコントロールしよう
動画の右側にある、電球はHueという商品で、フィリップスが作っているスマート電球です。この電球は、普通の電球取り付けるE26と呼ばれる電球ソケットに差し込みが可能なLED電球です。ちょっと普通のLED電球と違うのは、外からプログラムでコントロールが出来ることです。例えば、スマホのアプリを使って、電球を点けたり消したり、または、色をさまざまに変えることが出来るのです。
このHue電球。Node.jsでJavaScriptからコントロールするのは実は結構簡単で、数行のプログラムを記述することで実現できていまいます。
その手順や方法は以下の記事に書きましたので、詳しくはこちらをご覧ください。
本日のお題は、IchigoJamからUSBシリアル通信でパソコンに送られたコマンドをNode.jsで処理し、Hueのコントロールに使ってしまおうというものなのです。
Philips Hue(ヒュー)スターターセットv3 スマートLEDライト 【Amazon Alexa、Google Home、Apple HomeKit、LINE対応】
手順(プロトコル)を決める
まずはじめに、スマート電球HueとIchigoJamはどういう風につながっているかを説明します。IchigoJam自体はネットワークにつながる機能がありません。USBシリアル通信でパソコンと繋がっているだけです。つまり、最初にご紹介した動画の左側のケーブルの先にはパソコンがつながっています。このパソコンは自宅のホームネットワークにつながっているのです。
そして、一方のHue電球は、E26ソケットに刺さってはいるものの、そこから無線で、Hueの「ブリッジ」につながっています。ブリッジはパソコンと同じホームネットワークに接続されています。
簡単に図示すると以下のような接続になっています。
基板に付いているボタンを押されるとUSBシリアルポートでIchigoJamからパソコンにコマンドを送ります。パソコンでは、Node.jsで動作するJavaScriptのプログラムがUSBシリアルポートを監視して、コマンドをチェックします。そして、IchigoJamから来たコマンドを変換してHueスマート電球をコントロールする、という流れです。
USBシリアルケーブルを介して、パソコンにコマンドを送るためには、予めIchigoJamとパソコン間でどんなやり取りをするのかを決めておく必要があります。こういう手順のことを「プロトコル」と呼びます。
このシステムを動かすためには、まずこのプロトコルってのを決めなければなりません。そして、決められたプロトコルに従ってIchigoJam(BASIC)とパソコン(JavaScript)のそれぞれのプログラムを書くことになります。
私は今回、以下のようにプロトコル(手順)を決めました。IchigoJamのボタンが押されたときに、以下のような文字列を送ります。
LIGHT: number
「送る」と言ってもBASICのPRINT文で表示するだけです。PRINT分で表示することがすなわち、USBシリアルでコマンドを送ることに相当します。numberのところは、0から4の数字が入ります。numberが0のときは、電球を消す(LIGHT: 0)。そして、1から4の数字はそれぞれ、異なる電球色を意味することにします。
IchigoJamのプログラム
はじめにIchigoJamのBASICのプログラムから説明します。BASICのプログラムでは、基板に付いたプッシュボタンの状態をチェックして、ボタンが押されたときに限り、PRINT文で “LIGHT: number“を表示する、という動作をさせます。
コマンドBTN()というものがあります。このBTN()は、もし、プッシュボタンが押されていたら1が返ります。そして、押されていないときは0です。従って、プログラムでぐるぐるとループさせてBTN()が0から1に変化するのを監視します。
実際のプログラムは以下のようなものです。
10 S=0
20 L=0
50 B=BTN()
60 IF B=1 AND S=0 THEN GOSUB 100
80 S=B
90 GOTO 50
100 REM "SUB FUNCTION"
110 PRINT "LIGHT: ", L
120 L=L+1
130 IF 5<=L THEN L=0
140 RETURN
行番号50から行番号90の間でぐるぐるループさせてBTN()の値が0から1に変化したら、つまり、プッシュボタンが押されたら行番号100にジャンプする、という仕組みにしています。
行番号110が、パソコンに送るコマンド、LIGHT: numberを表示している部分です。Lが変数になっていて、最初は0ですが、行番号120に来るたびに1増えて、130行目で5になったらもう一度0に戻す処理をしています。
パソコンのNode.jsのプログラム
パソコン側のNode.jsのJavaScriptのプログラムは少し込み入っています。
'use strict';
// configuration parameters
const light_url = "http://10.0.0.11/api/pIvvuDG2LqEsz4f8MaVt2pqHeqH-ll6Y8BAoAav8/lights/2/state";
const serial_port_device = '/dev/ttyUSB0';
// initialize http request object
const request = require('request');
const light_commands = [
{on: false},
{on: true, bri:10, xy:[0.7,0.3]},
{on: true, bri:10, xy:[0.5,0.5]},
{on: true, bri:10, xy:[0.1,0.2]},
{on: true, bri:10, xy:[0.25,0.65]}
]
// initialize serial object
const SerialPort = require('serialport');
const port = new SerialPort(serial_port_device, {baudRate: 115200});
var parser = new SerialPort.parsers.Readline;
port.pipe(parser);
// receive text from serial SerialPort
// expected command is something like 'LIHGT: number'
// s[1] is storing the number as String
parser.on('data', function(data) {
console.log('>>>: ' + data);
var s = data.split(/\s+/).join('').split(':');
light(s[1]);
});
// make light control request
function light(s) {
var command = light_commands[parseInt(s)];
request.put({
url: light_url,
headers: {'Content-Type':'application/json'},
body: JSON.stringify(command)
},
function (error, response, body) {
console.log(body);
}
);
}
※ “baudRate: 112500″と、記載していた部分、正しくは、115200でした。上記修正しました(2020/3/22)
注意点としては、5行目のlight_urlは、Hue電球のコントロールするAPIのURLです。
ここは、以下の記事にて詳しく説明しています。簡単に言うと、HueブリッジのIPアドレスとUsernameを取得して、それぞれの環境に合わせて書き換える必要があります。
また、6行目のserial_port_deviceも、それぞれのパソコンで異なる場合があるので注意が必要です。こちらに関しても以前、下記の記事で記載しました。IchigoJamをUSBで接続したときに決まるUSBデバイスの名前を指定しなければなりません。私のパソコンはLinux(Ubuntu) OSです。
シリアル接続されたIchigoJamからLIGHT: 0などの文字列をシリアルのデバイス経由でNode.jsが読み取ると29行目が呼ばれます。dataの中には、"LIGHT: 0″の文字列が含まれます。それを31行目でコロンで分割しsという配列に格納します。s[1]には数字が入っていますので、ここで、light関数を呼び出します。
行番号37では、light() 関数が定義されています。ここで、JSONのHueブリッジがわかる形式のデータをHTTP経由で電球に送ります。これで、電球を消したり、色を変えたり出来るようになります。
動作手順
まずは、IchigoJam側のBASICのプログラムを動作させます。ボタンを押すたびに画面に
LIGHT: 0
LIGHT: 1
LIGHT: 2
…
と表示されていればOKです。
次に、パソコン側では、上記のJavaScriptを動作させます。JavaScriptがLIGHT: numberをIchigoJamから受け取るとHueが変化しますので、先程の動画のような挙動になります。
まとめ
- IchigoJamをUSBシリアルでパソコンにつないでスマート電球Hueをコントロールしました
- IchigoJamとパソコンの間の通信は手順(プロトコル)を決めて、BASIC、JavaScriptそれぞれでプログラミングします
- IchigoJamの基板のプッシュボタンをプチプチ押すと、そのタイミングでUSBシリアルを通してパソコンにコマンドが送られます
- パソコンではNode.jsのJavaScriptプログラムでUSBシリアルのデータを監視。コマンドが来たらHTTPでHueにJSONのデータを送ります