Edisonに繋いだデバイスを制御するアプリを、IoT Foundation/Bluemixでクラウド上に作成する


# **システムの概要**
Edisonに光センサーとLEDを繋ぎ、光センサーのセンサー値が小さくなったら（つまり暗くなったら）、LEDが点灯するといった単純なシステム。ただし、光センサーの値を元にLEDを点灯を制御するアプリはクラウド環境であるBluemix上に作成する。EdisonとBluemix上のアプリとのデータのやり取りはMQTTを利用する。

**1. [Edison]** Node.jsプログラムが**光センサーの値を取得**し、**MQTT**でIoT Foundation（クラウド上のMQTT Broker）に送信（**Publish**）
**2. [Bulemix]** Node-REDで作成したProgramがIoT Foundationより光センサーデータを取得し（**Subscribe**）、**暗い場合はLEDをONにする**コマンドをIoT Foundationに送信（**Publish**）
**3. [Edison]** Node.jsプログラムが、IoT Foundationに送信されたコマンドを取得し（**Subscribe**）し、LEDを点灯

![2015-10-14_11h29_23.png](https://qiita-image-store.s3.amazonaws.com/0/86169/ae1b5ea7-d89a-1dcc-0a54-15c941691071.png)

# **準備事項**
**1. 必要なもの**
    * [Intel Edison](http://www.intel.co.jp/content/www/jp/ja/do-it-yourself/edison.html)
    * [Intel Edison Kit for Arduino](http://www.intel.co.jp/content/www/jp/ja/do-it-yourself/edison.html)
    * [Grove starter kit](https://www.switch-science.com/catalog/1812/) (光センサとLEDを使用）
**2. 事前準備**
    * [Bluemixのフリーアカウント取得](https://console.ng.bluemix.net/)
    * Edisonのセットアップ([Get Started Guide](https://software.intel.com/en-us/iot/library/edison-getting-started?cm_mc_uid=21583562597014415759895&cm_mc_sid_50200000=1444478398)のStep1~5まで実施）
    * 光センサ（アナログ入力 A0）, LEDの設置（GPIO 13ピン））

![2015-10-11_17h32_56.png](https://qiita-image-store.s3.amazonaws.com/0/86169/82b56c05-3311-cdae-d8bd-657216ae516b.png)

# **作成の流れ**
1. EdisonのMACアドレスの確認
2. Bluemix上でアプリケーションの雛形作成
3. IoT FoundationにDevice(Edison)を登録
4. Edison用Node.jsプログラムの作成
5. Bluemixで稼動する制御プログラム作成（Node-RED）

# **1. EdisonのMACアドレス確認**
今回はEdisonとBluemix上の制御アプリケーションとのデータのやり取りはMQTTで行う。MQTTで通信を行うためには、デバイスとアプリケーションを仲介するMQTT Brokerが必要であり、クラウド環境で利用可能なMQTT BrokerであるIoT Foundationを使用する。

IoT Foundationを利用するためには、DeviceをIoT Foundationに登録する必要があり、今回は**EdisonからWifiで接続するため**、ifconfigコマンドで**wlan0のMACアドレス**を確認する。
![2015-10-11_18h01_14.png](https://qiita-image-store.s3.amazonaws.com/0/86169/a78b5468-45cb-a14f-e381-d08e06fa4fdb.png)

PuttyやTeraTerm、もしくはIntel XDK IoT Edition等でEdisonにシリアル接続し、ifconfigを実行し、**赤枠のHWaddrの「:」をとったもの**（上記の例だと、784b87a00ebf）をDeviceIdとして登録する。

# **2. Bluemix上でアプリケーションの雛形作成**
光センサーの値を元にLEDを点灯を制御するアプリは、BluemixのNode-REDを用いて作成する。また、IoT Foundationに送信されたセンサーデータをNode-REDアプリで取得するためには、Node-REDアプリとIoT Foundationの紐付けが必要となる。そこで、下記のステップで、Node-REDアプリケーションの雛形を作成し、IoT Foundationとの紐付けを行う。

**1. Node-RED StarterにてNode-REDアプリの作成**
**2. Internet of Thingsサービスのバインド**

### **2.1 Node-RED StarterにてNode-REDアプリの作成**
ボイラープレートより、Node-RED Starterを選択し、アプリ名を設定し、Node-REDアプリケーションを作成する。
![2015-10-11_19h11_25.png](https://qiita-image-store.s3.amazonaws.com/0/86169/5dda4b03-dfe1-20ea-94c5-d6ba6409ca6c.png)

ステージング完了後、アプリケーションのダッシュボードに表示されているURLをクリックし、Node-RED Flow Editorが表示されることを確認。
![2015-10-11_19h21_41.png](https://qiita-image-store.s3.amazonaws.com/0/86169/c4910291-5b73-0b40-08ee-bc12ca83bd6c.png)


### **2.2 Internet of Thingsサービスのバインド**
カタログの一番下にあるInternet of Thingsサービスをクリックし、次の画面でNode-REDアプリにバインドする。
![2015-10-11_19h32_42.png](https://qiita-image-store.s3.amazonaws.com/0/86169/e3da44d6-ddf9-c003-e30e-ddfaa69eb03f.png)

# **3. IoT FoundationにDevice(Edison)を登録**
アプリケーションのダッシュボードより、Internet of Thingsを選択し、IoT foundationのダッシュボードを開く。
![2015-10-11_19h40_19.png](https://qiita-image-store.s3.amazonaws.com/0/86169/ac684441-57eb-b1cf-e6a1-6076f67fa125.png)

ダッシュボードにて、デバイスタブを選択し、デバイスの追加を行う。デバイスタイプの作成時の「名前」は任意の名前でOK。

![2015-10-11_20h05_24.png](https://qiita-image-store.s3.amazonaws.com/0/86169/be136ece-d4f3-3a9f-9e1a-f4a21d03cbf7.png)

その後の画面は、特に何も設定せずに「次へ」を押して進める。

![2015-10-11_22h47_25.png](https://qiita-image-store.s3.amazonaws.com/0/86169/81607c27-d5af-be9b-f49a-00fcc396c692.png)

デバイスを追加する。
![2015-10-11_23h07_14.png](https://qiita-image-store.s3.amazonaws.com/0/86169/7ab3919a-06cc-109a-0145-9149f2309c15.png)

認証情報が表示されるので、メモする。以上でIoT Foundationへのデバイスの登録は完了。
![2015-10-11_23h12_41.png](https://qiita-image-store.s3.amazonaws.com/0/86169/d7a0b713-992a-a8cb-799f-8d12f27e0637.png)

# **4. Edison用Node.jsプログラムの作成**
Edisonに繋いだ光センサーの値を取得し、IoT FoundationにMQTT Publishするプログラムを作成する。また、このプログラムでは、Node-REDアプリがIoT FoundationにPublishしたLEDを点灯するためのコマンドをSubscribeする。

### **4.1. 必要なLibrary**

* [MQTT.js](https://www.npmjs.com/package/mqtt) (MQTT clientを作成するためのnode.js Libray）
* [Mraa](https://github.com/intel-iot-devkit/mraa) (Intelが提供するArduinoを操作するためのNode.js Library)

MQTT.jsはpackage.jsonのDependencyに記載。MraaはEdisonの初期セットアップ時にEdison内に配置される。

### **4.2. 開発方法**
Node.js プログラムは、最終的にはedison上にUploadして動かす。主な開発方法は、下記の三種類。

1. Edison上でvi Editorで開発
2. PC上のIntel XDK IoT Edisonで開発し、EdisonにUpload
3. PC上のテキストEditorで開発し、GitHubにPushし、Edison上からGit Cloneする

作成時は、Intel XDK IoT Edisionを使用した。使用方法はこちらの[Intel® XDK IoT Edition Getting Started Guide](https://software.intel.com/en-us/intel-xdk-iot-edition-guide)を参照。

### **4.3. Node.js プログラム**
**1. プログラムの流れ**
1. IoT Foundationにデバイスを登録した際に得られる情報を元に、接続先のIoT FoundationのURLや接続の際に必要なCredential情報を整形
2. MQTT.jsを用いて、IoT Foundationに接続
3. 接続確立後、Mraaで取得した光センサーの値を一定間隔でPublish
4. 平行してLED点灯コマンドをSubscribeし、LEDをOn/Offする

**2. ポイント**

1. MQTT Brokerのアドレス
    * mqtt://' + <組織ID> + '.messaging.internetofthings.ibmcloud.com:1883
2. Topicは下記のFormat設定。下記の設定は、Node-REDアプリケーション構築の際に使用する。
    * PublishするTopicは、iot-2/evt/**Event名**/fmt/json
    * SubscribeするTopicはiot-2/cmd/**Command名**/fmt/json
3. PublishするMessageはJSONで下記の形式
    * {"d": {<Message>}}
    * {"d": {"brightness": <光センサー値>}}とした
4. LEDをOn/Offするコマンド（Subscribeデータ）は、下記とした
    * {"LED": "on"}
    * {"LED": "off"}

**3. Sampleプログラム** 
試す場合は、GitHubに公開しているので（[Edison_to_IoTFoundation_Node](https://github.com/MasayaFujita/Edison_to_IoTFoundation_Node)）、Git Cloneをして導入。導入方法は、たとえば下記のようにする。

1. PC上にGit Cloneして、Intel XDK IoT EditionにImportし、BuildしてEdison上にUploadして実行
2. Edison上で直接Git Cloneして実行。その際、`npm install`を実行してMQTT.js等をセットアップした後に、`node main.js`でプログラムを実行。EdisonへのGitの導入は[こちら](http://shokai.org/blog/archives/10061)を参照。

```js:main.js
/*jslint node:true, vars:true, bitwise:true, unparam:true */
/*jshint unused:true */
// Leave the above lines for propper jshinting
//Type Node.js Here :)
var mqtt = require('mqtt');
var mraa = require('mraa');

// credential parameters assigned when you subscribe your device to IoT founcation
var org = "gyyqov";                     // <--- update!!
var type = "myedison";                  // <--- update!!
var id = "784b87a00ebf";                // <--- update!!
var auth_token = "kPSf9slYBK6vX+r4!3";  // <--- update!!

var authmethod = 'use-token-auth';      // You don't need update this parm

// create clientID and URL to connect IoT foundation
var clientId = 'd:' + org + ':' + type + ':' + id;
var mqtt_url = 'mqtt://' + org + '.messaging.internetofthings.ibmcloud.com:1883';
var credentials = { clientId: clientId, username: authmethod, password: auth_token };

// create a mqtt client
var client  = mqtt.connect(mqtt_url, credentials);

// connect and process
client.on('connect', function () {
    var pub_topic = 'iot-2/evt/status/fmt/json';    // publish a message to a topic
    var pub_message;                                // message to be published
    var sub_topic = 'iot-2/cmd/cid/fmt/json';       // topic to subscribe
    var sub_message;                                // message reached to topic subscribing

// publish message to IoT foundation
  setInterval(function(){
      pub_message = '{"d":{"brightness":' + analogVolts() + '}}'; 
      // publish value from light sensor
      client.publish(pub_topic, pub_message, function() {
          console.log("Message is published");
      });
  },1000);

//subscribe to a topic
    client.subscribe(sub_topic, function() {
        // when a message arrives, do something with it
        client.on('message', function(topic, message, packet) {
            sub_message = message;
            console.log("Received '" + sub_message + "' on '" + topic + "'");
            
            if (JSON.parse(sub_message).LED === "on") {  // when parameter LED is "on", LED is blinked.
                myOnboardLed.write(1);
            } else {
                myOnboardLed.write(0);
            }
        });
    });
});

// Read Analog output A0
var pin0 = new mraa.Aio(0);
var analogVolts = function() {
    var counts = pin0.read();
    return counts;
};

// Send signal to light LED connected to GPIO(13)
var myOnboardLed = new mraa.Gpio(13); //LED hooked up to digital pin 13 (or built in pin on Intel Galileo Gen2 as well as Intel Edison)
myOnboardLed.dir(mraa.DIR_OUT); //set the gpio direction to output
```

# **5. Bluemixで稼動する制御プログラム作成（Node-RED）**

### **5.1. Node-REDアプリの機能**

**1. 光センサーデータの取得 & 可視化**
IoT Foundationから**光センサーデータをSubscribe**し、Google visualization APIを使用した**グラフを表示するWeb Page**を作成

**2. 光センサーの値を元に、LEDをOn/Offするコマンド発行**
IoT Foundationに、光センサー値が100を切ったらLED ON、100以上の場合はLED OFFとする**コマンドをPublish**

![2015-10-12_11h44_58.png](https://qiita-image-store.s3.amazonaws.com/0/86169/60c894d5-5965-2376-6d0e-f5e0798b33aa.png)
### **5.2 Node-REDアプリの作成**
**1. Node-REDの使用方法**
下記のハンズオン資料を参照。

* [IBM Bluemix Node-REDを使って簡単アプリ作成を体験する](http://www.slideshare.net/masayafujita180/ibm-bluemix-nodered)

**2. Sampleプログラム**
[Edison_to_IoTFoundation_Node](https://github.com/MasayaFujita/Edison_to_IoTFoundation_Node)の[Node-RED sample](https://github.com/MasayaFujita/Edison_to_IoTFoundation_Node/blob/master/Node-red%20sample)をImportすることで、Node-REDアプリを一括導入可能。Importの方法は、こちらのQiitaの投稿（[Node-RED小ワザ集](http://qiita.com/asmanabu/items/d9ba9ff0fca745c8c216))を参照。


**3. 光センサーデータの取得**
EdisonからIoT FoundationにPublishされた光センサーデータをSubscribeするには、「ibmiot in」ノードを使用する。プロパティーを開き、下記のように設定。

* Device Type, Device Id : IoT Foundationに登録したEdisonの情報
* Event Type : Device Event
* Event : 光センサー値のpublish先Topic: `var pub_topic = 'iot-2/evt/status/fmt/json';`に記載されているEvent名

DebugノードをつなぎDeplpoy後、Edison上でNode.jsプログラムを実行し、Debugウィンドウに光センサーデータが表示されれば成功。

![2015-10-12_12h26_51.png](https://qiita-image-store.s3.amazonaws.com/0/86169/3116ddb5-e2eb-ee47-fbf6-f6029c5a6e06.png)

**4. センサーデータの可視化**
「http in」ノード, 「Template」ノード、「http response」ノードを使用し、下記のURLにGET Requestがきたら、センサーデータのグラフを表示するHTMLを返すWeb Pageを作成する。

* http://<アプリ名>.mybluemix.net/**brightness**

また、光センサーから**1秒間隔で送られてくるデータを、リアルタイムにグラフに反映させる**ため、データは**WebSocket**を使用して送信する。各ノードの設定は下記の通り。設定後、Deployし、/brightnessにアクセスして、グラフが表示され、センサーの値がリアルタイムに更新されたら成功。

* **http inノード**
    * Method : GET, URL : /brightness
* **Websocket outノード**
    * Path : /ws/brightness
* **Templateノード**
    * HTML Fileを記載。GitHubの[Graph.html](https://github.com/MasayaFujita/Edison_to_IoTFoundation_Node/blob/master/Graph.html)参照
    * Graph.htmlを使用する場合は、**HTML上のWebSoketのURLをアプリの名前に合わせて変更する必要がある**ので注意が必要。
   
  
 ![2015-10-12_21h13_40.png](https://qiita-image-store.s3.amazonaws.com/0/86169/6b2317b8-b405-8f37-0822-f6bd690cba8d.png)


**5. 光センサーの値を元に、LEDをOn/Offするコマンド発行**
光センサーの値を元に、下記の通り、コマンドをIoT FoundationにPublishする。

* 100以下の場合 : {"LED": "on"}
* 100以上の場合 : {"LED": "off"}

上記の処理は、「function」ノードにJavascriptを記載して行い、IoT FounadationへのPublishは、「ibmiot out」ノードを使用する。それぞれの設定は下記の通り。

* **function ノード**
    * Javascriptのif文でLED点灯コマンドを整形し、msg.payloadにセット。
* **ibmiot out ノード**
    * Authentication : Bulemix Service
    * Output Type : Device Command
    * Device Type : IoT Foundationに登録したDevice Type
    * Device IT : msg.deiveId（deviceId情報がFlowを流れてくるので、それを使用。直接指定でもOK）
    * Command Type : Topic名にかかわる設定であり、制御コマンド用Topic名 : `iot-2/cmd/cid/fmt/json`にあわせる。この例では、「cid」をCommand Typeに設定。

![2015-10-13_10h07_05.png](https://qiita-image-store.s3.amazonaws.com/0/86169/cb91f2f8-09bb-3ab2-d8a4-202829755870.png)

Node-REDアプリをDeployし、Edison上でNode.jsプログラムを起動後、光センサーを手で覆う等でセンサーの値を100以下にすると、LEDが点灯し、手を離すとLEDが消えることが確認できる。以上で完成！

# **6. 参考情報**

**MQTT関連**
* [MQTTについて詳しく知る](https://sango.shiguredo.jp/mqtt)
* [Node.js以外の言語のMQTT Library情報](https://github.com/mqtt/mqtt.github.io/wiki/libraries?cm_mc_uid=21583562597014415759895&cm_mc_sid_50200000=1444551442)
* [Explore MQTT and the Internet of Things service on IBM Bluemix](http://www.ibm.com/developerworks/cloud/library/cl-mqtt-bluemix-iot-node-red-app/index.html)

**EdisonとBluemix**
* [Intel Edison IoTF Recipe](https://developer.ibm.com/recipes/tutorials/intel-edison/) : Node.js
* [Intel EdisonとIBM IoT Foundation & Bluemixの連携](http://qiita.com/nmatsui/items/379b64b9a3766df21549) : Python

**Bluemixの基礎, Node-RED**
* [Bluemix Hands-onまとめ](http://qiita.com/mfujita/items/4d808c5648005e74b831)