Cylon.jsでのLED点灯側の実装
さて、今回はAnalytics Dashboard経由で2台のEdisonを連携させる予定ですが、まずは単体で動作する状態の実装を行っていきます。SensorTagと接続する1台目は、弊社ブログで実装したものを流用しますので、ここでは連携先の2台目でLEDを点灯させる実装をCylon.jsで行ってみます。
カラーLEDの点灯
今回はカラーLEDで、かつ、カソードが共有されている形のモジュール(参考)になっているものを利用しています。モジュールのR・G・B・KのコネクタをEdison Arduinoボードのデジタル出力のポート3、5、6、Groundに接続します。
温度によって色を切り替えることを想定していますので、まずは各色で順に発光するような簡単なコードを記述し、そこに連携させるためのコードの追記・変更を行っていくようにしてみます。順に光らせるだけであれば、以下のようなコードになります。
var Cylon = require('cylon'); Cylon.robot({ connections: { //adapterの設定 edison:{ adaptor: 'intel-iot'} }, devices:{ //カラーLED用ドライバと各色のポート番号指定 leds:{ driver: 'rgb-led', redPin: 3, greenPin: 5, bluePin: 6} }, work: function(my){ var red = "ff0000"; var green = "00ff00"; var blue = "0000ff"; var color; //2秒に1回発色を切り替え every((2).second(), function(){ if (color == red) { color = green; } else if (color == green) { color = blue; } else { color = red; } my.leds.setRGB(color); }); } }).start();
CylonのLED点灯用のドライバーにはLEDドライバーとRGB LEDドライバーがあります。今回はRGB LEDドライバーを利用しています。ドライバの指定はdevicesの中で行っていて、各色が接続されているポートを指定します。
ポートはデジタル入出力のうち、PWM(デジタルで擬似的なアナログ出力を出す仕組み)に対応したポートを利用していますが、PWMのポートは仕様上同時に4つまでしか使えず、初期状態では3、5、6、9の4つが使える状態です。設定はジャンパピンで行えますが、デフォルトの状態では10、11は利用できませんので、注意が必要です(実際私は最初は9、10、11に接続して実行してしまい、エラーが起きました)。
色の切り替えは16進数のカラーコードを渡して行うようになっています。等間隔での繰り返し点灯では、Cylonのutilityメソッドであるeveryを使って2秒置きに色が切り替わるようになっています。
IoT Analytics Dashboardからのアクチュエーション追加
カラーLEDが点灯できることが確認できたら、次にこのコードをAnalytics DashboardからのActuationでLEDが点灯するように書き換えてみます。手順としては以下のようになります。
- Edisonをデバイスとして登録する
- RGB LED点灯用のコンポーネントを作成し、Dashboardのカタログに登録する
- Edison上で利用するコンポーネントを登録する
- iotkit-agentのプロトコルをMQTTに切り替える
- Dashboardからの通知を受け取れるようにLED点灯用のコードを書き換える
1. Edisonをデバイスとして登録する
まず事前にDashboard側からEdisonが認識できるように登録をしておく必要があります。Edison上からiotkit-adminコマンドを利用して登録することになります。実際の手順については、ブログの方にまとめてありますので、そちらを参考にしてください。
手順はブログを参考にしていただくとして、iotkit-adminの話が出てきましたので、iotkit-agentと、このadminツールについて簡単に説明しておきます。
Intelが配布しているIoT Developer KitではAnalytics Dashboardとの間のメッセージのやりとりや、さまざまな処理のハンドリングを行うデーモンとして、iotkit-agentというものが利用できるようになっています。iotkit-adminはagentを通した各種の設定などを簡単に行えるようにするユーティリティーツールです。Nodeのモジュールとして配布されていて、Edisonではデフォルトでインストール済みとなっています。
ちなみに初期状態で入っているiotkit-adminとiotkit-agentではバグがあってアクチュエーションには対応できません。npm updateを使ってiotkit-adminのアップデートをかけると、agentを含め最新に更新されますので、事前に行っておきます。
2. RGB LED点灯用のコンポーネントを作成し、Dashboardのカタログに登録
Edisonの登録ができたら、こんどは接続しているLEDを扱えるようにコンポーネントを作成し、Dashboardのカタログに追加します。コンポーネントはセンサーやアクチュエータなど、接続する機器類に対応するもので、同一のパラメータ類を利用するものなどを、Dashboardから1つのコンポーネントで統一して扱えるようにできます。
デフォルトでpowerswitchというコンポーネントが登録されていて、こちらはLEDのオン・オフを行うようなものになっています。今回はLEDの発色を切り替えますので、単純なオン・オフのこちらは利用せず、新たにコンポーネントを作成・登録して利用します。
登録はDashboardのAccountメニューのCatalogタブから行います。Catalogタブを開くと最下部にAdd a New Catalog Itemボタンがありますので、こちらから表示される登録フォームに必要な項目を記入し、登録します。ここでは以下の画像のようになります。
今回必要な項目はComponent Name、Version、Type、Data type、Format、Command Stringと、あとはDashboardからの通知に含めるパラメーターをkey、valueの組み合わせで登録することになります。
Component NameやVersionは任意のもので、TypeはアクチュエーションしますのでActuatorを選択します。Data typeは通知時にパラメーターとして渡すものの型です。今回はStringです。Formatについては選択したData typeによって異なってきます。Data TypeにStringを選択した場合はFormatも自動でStringです。Command StringはDashboardからのコマンド通知の中に含まれるコマンドの種別を表す文字列です。
最後にパラメーターを登録します。パラメーターはAdd parameterボタンで複数追加することができます。今回はcolorというパラメーターでパラメーター値としてred、green、blueが選択できるようにしています。
3. Edison上で利用するコンポーネントを登録
続いて、Edison上から作成したコンポーネントを関連付けるための登録を行いますが、こちらについてもブログにまとめてありますので、そちらを参考にしてください。基本的にはiotkit-adminコマンドを使って、Edison側が知っているカタログの更新を行い、その中で利用するものを登録することになります。
4. iotkit-agentのプロトコルをMQTTに切り替え
また、アクチュエーションの実行にはMQTTを利用しますので、まずはiotkit-adminコマンドを使ってプロトコルを切り替えておきます。デフォルトではRESTになっていますので、以下のようにコマンドを実行して切り替えます。
$ iotkit-admin protocol mqtt
5. Dashboardからの通知を受け取れるようにLED点灯用のコードを書き換え
最後にLED点灯のコードをDashboardからの通知に対応させます。公式サイトのドキュメントにある実装例を参考に、以下のように変更しました。
var Cylon = require('cylon'); //agentからのUDPメッセージを受け取るためUDPソケットを利用 var server = require('dgram').createSocket("udp4"); const COMPONENT = "rgbled1"; const COMMAND = "RGBLED.V1.0"; Cylon.robot({ connections: { edison:{ adaptor: 'intel-iot'} }, devices:{ leds:{ driver: 'rgb-led', redPin: 3, greenPin: 5, bluePin: 6} }, work: function(my){ var color; var endpoint = "127.0.0.1"; var port = 41235; server.on("error", function(e){ console.log("error:\n"+e.stack); server.close(); }); //agentからのメッセージ取得時の処理 server.on("message",function(msg,rinfo){ //ローカルからのUDP以外は受け取らない if(rinfo.address != "127.0.0.1"){ return; } //Dashboardからのメッセージの中身を取り出し var msg_json = JSON.parse(msg); var argv = msg_json['argv']; if(msg_json['component'] == COMPONENT && msg_json['command'] == COMMAND) { for(var i = 0; i < argv.length; i++){ if(argv[i]['name'] == 'color'){ color = argv[i]['value']; } } } my.leds.setRGB(color); }); server.on("listening",function(){ console.log("start listening."); }); server.bind(port); } }).start();
アクチュエーションの実行では、MQTTでDashboardから送られてきたメッセージをEdison側のagentが一度受け取り、メッセージの内容をJSON形式に変換してから、ローカルのUDPメッセージとしてローカル内で再送信します。そのため、こちらのコードでは、UDPでリスニング状態にしておいて、ローカルからのUDPメッセージが来た場合に中身を取り出すようにしています。コンポーネント名はEdison上での使用コンポーネント登録時につけた短縮名を、コマンド名にはDashboard側でコンポーネントを登録した際に設定したコマンド名を利用します。
Dashboardからは文字列でカラーコードを送るようにしていますので、取り出したカラーコードをRGP LEDドライバーに渡しています。
実際にDashboardから試しにアクチュエーションのメッセージを送るには、Controlメニューを使います。Controlメニューのページを開くとデバイスの選択ができるようになっています。アクチュエーションのメッセージを送るデバイスを選択し、表示されるコンポーネントの中から、使用するものを選択します。ここで先ほど作成したRGB LED用のコンポーネントを使用します。こちらも登録した短縮名(今回の場合rgbled1)で表示されます。コンポーネントを選択すると、パラメーターの選択と送信方式の選択ができるようになります。それぞれ実行したい内容に合わせて適宜設定します。送信方式はMQTTを選択します。
すべて設定できたらAdd actionボタンで実行リストに追加します。リスト表示された右端に表示されるsendのリンクをクリックするとメッセージが送信されます。