Intel EdisonでIoTを実感する


こんにちは。インフォコム技術企画室のsatochanです。

今回は、2014年1月のCESで発表され、2014年9月(日本では10月)から発売になったインテル社のEdisonというシングルボードコンピュータを使ったIoTシステムの作成をレポートします。

Intel Edisionとは

Edison(エジソン)は、シングルボードコンピュータの一つで、その大きさはなんとSDカードサイズ(35.5 x 25.0mm)です。

edison02_body.jpg

この小さな基板の中にCPU、メモリ、ストレージ、WiFiモジュール、Bluetoothモジュールが入っており、電源を繋げばコンピュータとして動作します!

主なスペックは以下の通りです。

  • サイズ:35.5 x 25.0 x 3.9 mm
  • I/O:ヒロセ DF40シリーズ 70ピンコネクタ
  • CPU:Intel Atom 500MHz
  • RAM:1GB
  • フラッシュストレージ:4GB
  • WiFi:802.11 a/b/g/n(2.4/5GHz デュアルバンド)
  • Bluetooth:4.0

EdisonはIoT(Internet of Things)やウェアラブルの分野で利用されることが期待されており、とても小さくとても軽く作られていますが、I/Oコネクタも極小なもの(ヒロセ DF40シリーズ 70ピンコネクタ)が採用されており、そのままではセンサなどの部品と気軽に接続ができません。 そのため、インテルから

  • Edison Breakout Board
  • Edison Arduino expansion board

という2つの拡張ボードが販売されており、半田で部品を接続したり、Arduino互換のシールドを接続できるようになっています。

edison03_board.jpg

実験内容

このEdisonを利用して弊社オフィス室内の温度・照度をセンサで計測し、室内環境の変化を見える化してみようと思います。

収集データ

  • 温度
  • 照度

Edison Arduino expansion boardにArduino互換シールドが利用できるため、
speedstudio社製のGroveというものを用い、温度センサと照度センサを接続して使います。

edison04_grove.jpg

構成

edison05_system.jpg

  • 温度・照度センサの値をEdison2が読み取り、一定間隔でパブリッシングします
  • Edison1がそれをサブスクライブします
  • Edison1はセンサデータの10秒移動平均を計算し、10秒置きにクラウド(インテルが提供するIoT Analyticsというサービス)に対してパブリッシングします
  • Edison1とEdison2の間はZeroMQという通信方式を使い、Edison1とIoT Analyticsの間はhttpsで通信が行われます(後述しますが、通信はEdisonにインストールされているiotkitというフレームワークが行ってくれるため、ユーザプログラムが実装する必要はありません。)

実装方法

EdisonのOSはYocto Linuxがプリインストールされており、以下の開発環境がサポートされていますが、今回はこれらの開発環境は使わずにJavascriptファイルを直接作成してみました。(iotkit-commをJavascriptで利用する方法はコチラのドキュメントを参考にしました。)

  • Arduino IDE
  • Eclipse: C, C++, and Python
  • Intel XDK: Node.JS and HTML5

セットアップ

IoT Analyticsへつなぎデータ送信するために、Edision1に次のようなセットアップが必要です。

  • IoT Analyticsへデバイスを登録する

    1. ユーザ登録を行う
    2. アクティベーションキーをマイページで確認する
    3. dison上で以下のコマンドでアクティべーションを行う
    4. IoT Analytics上でデバイスが登録されたことを確認する

# iotkit-admin activate [acctivation-key]
2014-12-11T07:26:55.367Z - info: Activating ...
2014-12-11T07:26:57.052Z - info: Saving device token...
2014-12-11T07:26:57.066Z - info: Sending attributes...

edison06_register.png

  • iotkit-agentのサービス開始

    • EdisonからIoT Analyticsへデータ送信するエージェントサービスを有効にし開始します。
    • このiotkit-agentがクラウドとの仲介をしてくれます(ユーザプログラムとiotkit-agentの間がMQTTで通信され、iotkit-agentとIoT Analytics間がhttpsで通信される。)
    • 工場出荷時デフォルトはdisable, inactiveでした
# systemctl enable iotkit-agent
ln -s '/lib/systemd/system/iotkit-agent.service' '/etc/systemd/system/multi-user.target.wants/iotkit-agent.service'
# systemctl start iotkit-agent

コード

Edison1, 2それぞれに以下のようなファイルを作成しました。

Edison1

  • p00thermostatquery.json(センサの温度照度を受信するサービスクエリ)

    • zmqpubsubを指定することでiotkitがZeroMQという通信プロトコルを使用して通信してくれます
{
  "name": "/my/office/thermostat/sensor/*",
  "type": {
    "name": "zmqpubsub",
    "protocol": "tcp"
  },
  "properties": {"dataType": "float", "sensorType": "ambient"}
}
  • p00thermostatspec.json(クラウドにパブリッシュするのためのサービススペック)

    • enableiot-cloudを指定することでiotkit-agentとの間でMQTTという通信プロトコルを使用して通信してくれます
{
  "type": {
    "name": "enableiot-cloud",
    "protocol": "tcp"
  },
  "address": "127.0.0.1",
  "port": 1884
}
  • p00_thermostat.js(プログラム本体)
var iotkit = require("iotkit-comm");
var sensorQuery = new iotkit.ServiceQuery("p00_thermostat_query.json");

// moving average
var temperatureSampleCount = 0;
var lightSampleCount = 0;
var temperatureMovingAvg = 0;
var lightMovingAvg = 0;
var MOVING_SAMPLE = 10;

// cloud client
var SENSOR_ID_TEMPERATURE = "sensor_temperature00";
var SENSOR_ID_LIGHT = "sensor_light00";
var cloudSpec = new iotkit.ServiceSpec("p00_thermostat_spec.json");
iotkit.createClient(cloudSpec, function(cloudClient) {
  cloudClient.comm.registerSensor(SENSOR_ID_TEMPERATURE, "temperature.v1.0");
  cloudClient.comm.registerSensor(SENSOR_ID_LIGHT, "light.v1.0");
  setInterval(function() {
    // publish to cloud
    if (temperatureSampleCount >= MOVING_SAMPLE) {
      console.log("temperature to cloud: " + temperatureMovingAvg);
      cloudClient.comm.publish(JSON.stringify({"n": SENSOR_ID_TEMPERATURE, "v": temperatureMovingAvg}));
    }
    if (lightSampleCount >= MOVING_SAMPLE) {
      console.log("light to cloud: " + lightMovingAvg);
      cloudlient.comm.publish(JSON.stringify({"n": SENSOR_ID_LIGHT, "v": lightMovingAvg}));
    }
  }, 10000);
}, serviceFilter);

// sensor client
iotkit.createClient(sensorQuery, function(client) {
  console.log("Found new client: " + client.spec.address + ":" + client.spec.port + " - " + client.spec.name);
  client.comm.setReceivedMessageHandler(msgHandler);
  client.comm.subscribe("temperature");
  client.comm.subscribe("light");
}, serviceFilter);

msgHandler = function(binmsg) {
    //console.log(binmsg.toString());
    var message = binmsg.toString();
    var kind = message.substring(0, message.indexOf(":"));
    var value = parseFloat(message.substring(message.indexOf(":") + 1));

    //console.log("kind: " + kind + "  value: " + value);

    if (kind == "temperature") {
      temperatureMovingAvg = (value + temperatureSampleCount * temperatureMovingAvg) / (temperatureSampleCount + 1);
      temperatureSampleCount++;
    } else if (kind == "light") {
      lightMovingAvg = (value + lightSampleCount * lightMovingAvg) / (lightSampleCount + 1);
      lightSampleCount++;
    }
}

function serviceFilter() {
  return true;
}

Edison2

  • p00sensorlight_spec.json(照度のサービススペック)
{
  "name": "/my/office/thermostat/sensor/light",
  "type": {
    "name": "zmqpubsub",
    "protocol": "tcp"
  },
  "port": 11002,
  "properties": {"dataType": "float", "sensorType": "ambient"}
}
  • p00sensortemperature_spec.json(温度のサービススペック)
{
  "name": "/my/office/thermostat/sensor/temperature",
  "type": {
    "name": "zmqpubsub",
    "protocol": "tcp"
  },
  "port": 11001,
  "properties": {"dataType": "float", "unit": "C", "sensorType": "ambient"}
}
  • p00_sensor.js(計測してパブリッシュするスクリプト)
var iotkit = require("iotkit-comm");
var mraa = require("mraa");
var temperature_spec = new iotkit.ServiceSpec("p00_sensor_temperature_spec.json");
var light_spec = new iotkit.ServiceSpec("p00_sensor_light_spec.json");

// app config
var MEASURE_INTERVAL = 1000;
var TEMP_THERMISTOR_VAL = 3975;

// pin config
var pin_temperature = new mraa.Aio(0);
var pin_light = new mraa.Aio(1);

// temperature sensor sevice
iotkit.createService(temperature_spec, function(service) {
  setInterval(function() {
    var val = pin_temperature.read();
    var resistance = (1023 - val)*10000 / val; //get the resistance of the sensor;
    var temperature = 1 / (Math.log(resistance / 10000) / TEMP_THERMISTOR_VAL + 1 / 298.15) - 273.15;//convert to temperature via datasheet ;
    console.log("temperature: " + temperature);
    service.comm.publish("temperature: " + temperature);
  }, MEASURE_INTERVAL);
});

// light senor service
iotkit.createService(light_spec, function(service) {
  setInterval(function() {
    var val = pin_light.read();
    //var rsensor = (1023 - val) * 10 / val;
    console.log("light: " + val);
    //console.log("rsensor: " + rsensor);
    service.comm.publish("light: " + val);
  }, MEASURE_INTERVAL);
});

結果

クラウドに溜まった温度・照度データをIoT Analytics上で見ると次のようになりました(最終1時間分。)

edison07_iotanalytics.png

IoT Analyticsのグラフは制限(Y軸のレンジが変えられないなど)があるため、データをエクスポートしエクセルでグラフ化してみました。

edison08_excel.png

金曜日の夕方から月曜日の夕方までデータを取得してみましたが(12月)、

  • 土曜日は最低20.5度、最高23.5度だった
  • 日曜日は最低18.5度、最高22.0度だった
  • 月曜日の朝は16.0度近くまで冷え込んでいた
  • 平日日中は27度にもなる
  • 日曜日は土曜日よりも照度低いので曇ってたらしい

など連続的にデータを取り続けることで可視化される情報が出てきました。こういった環境測定データを解析し、快適な環境を作り出すためにフィードバック(空調制御や遮光制御など)したり、資源の有効活用に活かしたりすれば価値が生まれるのだろうと感じました。

まとめ

IoTシステム構築の容易さ

Edison1, 2ともに、今回作成したJavascriptの中に通信を行うコードや通信相手を特定するためのコードは必要ありませんでした。通信プロトコルや個々を特定する名称・属性は、サービススペックやサービスクエリと呼ばれるJSONファイルに定義しておくだけで、あとはiotkitが行ってくれます。
Edison1, 2を合わせておよそ100行程度のプログラムで

  • アンビエントセンサ
  • M2M通信
  • M2Cloud通信

を含むIoTシステム(というのは大げさですが)が完成してしまいました。
クラウドサービスや通信処理が用意されているのでインテルの場合は特にですが、Edisonのようなデバイスが登場してきたことで、ソフトウェア開発を専門行っている人や組織でも、簡単にH/Wを組み合わせ、モノとインターネットを融合させることができるようになってきました。

シングルボードコンピュータの可能性

インテルは今年のCESでさらに小型のボタンサイズコンピュータCurieを発表しました(発売は今年後半を予定)。また、シングルボードコンピュータとして古くから有名なRaspberry Piも先月新しいバージョンが発売されました。次々に新しいデバイスが登場し、できることや適用可能な領域が広がっています。

あなたの身の回りのモノがこういったデバイスによりインターネットと融合することで、何か大きな価値が生まれるかもしれません。何か大きなビジネスチャンスが眠っているかもしれません。意外に簡単にIoTシステムは作れてしまうので、ちょっと試してみるのはいかがでしょうか。