Intel Edisonにオンライン機械学習を行うJubatusを導入する

1. 概要

オンライン機械学習のための分散処理フレームワークJubatusをEdison上で動作させる方法について説明します.
以前のエントリで説明した, Intelの提供するIoT Analyticsでは現在,データ集計が主な機能なので,Jubatusを利用することで,Edisonが担える機能,Edisonを含めたアーキテクチャでできることが広がると思います.

対象OSは,デフォルトのYocto Linux,およびubilinuxです.このエントリではそれぞれについてのインストール方法と動作確認までを行います.ちなみにubilinuxのほうが簡単です.

Jubatusについての説明は行いませんが,公式ページにまとめてくださっているので,そちらを参照してください.以下に概要のみ引用します.

Jubatusは「分散したデータ」を「常に素早く」「深く分析」することを狙った分散基盤技術です。

Jubatusの名前の由来は、俊敏な動物であるチータの学術名からの命名で、「ユバタス」と読みます。 株式会社Preferred InfrastructureとNTTソフトウェアイノベーションセンタが共同開発した、 日本発のオープンソースプロダクトです。

最終的に全ての人にスケーラブルなオンライン機械学習フレームワークを提供することがJubatusの目標です。

Jubatus は以下の特徴を持ったオンライン機械学習向け分散処理フレームワークです。

1-1. 利用するスクリプト

どちらのOSを利用する場合も,公式で用意してくださっているインストールスクリプトを利用します.
後述しますが,デフォルトのYocotoを利用する場合,利用できるコマンドやリポジトリの問題から,別PCでの作業が必要になります.

1-2. 共通する準備

1-2-1. インストール用スクリプトの導入

Edisonの/usr以下は容量が少ないので,/home/root以下で作業をします. また,導入先は/home/root/local以下とします.このディレクトリをインストールスクリプト実行時に指定します.ディレクトリの切り方はお好きなように決めてください.

$ cd /home/root
$ mkdir local
$ git clone https://github.com/jubatus/jubatus-installer

1-2-2. インストールスクリプトへの修正点

どちらのOSを利用する場合でも共通して,最後のRPCのテストでこけます.
Jubatus開発者の1人である@kumagiさんによると,遅いCPUでビルドする場合に,タイムアウトの時間設定が短くてこけるとのことでした.
ですので,install.sh中,最後のJubatusをビルドする部分(275行目)を以下のように修正します.

# install.sh中275行目が以下のようになっている
 ./waf build --checkall && ./waf install

 # これを以下のように修正
 ./waf install

2. ubilinuxへの導入

コマンドやリポジトリDebianベースなのであまり問題ありません.
前述したインストールスクリプトへの修正と,bzip2を事前に導入しておくことが必要です.

2-1. 準備

2-1-1. 必要なパッケージの導入

bzip2を導入しておきます.

$ sudo apt-get install bzip2

2-1-2. スクリプトへの修正点

前述したwaf --checkへの修正点のみで良いです.

2-2. install

インストールスクリプト実行時にインストール先をpオプションで指定します.

$ cd jubatus-installer
$ sudo ./install.sh -p /home/root/local

ubilinuxでは以上でインストール完了です.

3. デフォルトのyocto Linux

yocto linuxはコマンドやリポジトリが残念なので,あんまりセルフビルドする環境ではなくてめんどくさいです.
以下,順番に説明していきます.

3-1. 準備(別PCでの作業)

めんどくさい原因は,shasumとtarまわりです.jubatus-installerに手を入れたり,いろいろ整備するのもめんどくさいので,wgetと解凍は別PCでやって,SFTPとか使ってEdisonへファイルを転送しましょう.

3-1-1. ファイルのダウンロード

別PCでinstallスクリプトを使ってファイルをダウンロードします.
スクリプト実行時にdオプションを使ってダウンロードだけまず行いましょう.

$ git clone https://github.com/jubatus/jubatus-installer
$ cd jubatus-installer
# dオプションをつけることでダウンロードのみを実行.
$ sudo ./install.sh -d

3-1-2. ファイルの解凍

ここまでで,jubatus-installer/download 以下に各ファイルがダウンロードされました. 次にこれらのファイルを解凍します.
install.shの中の該当箇所のみが動作するようにスクリプトを修正しても良いですし,該当箇所だけ別のスクリプトに書き出して実行しても良いです.もちろん手打ちでもいいけどちょっとだるいですね.
インストールスクリプトの中で解凍の際に必要な箇所は以下のとおりです.

#!/bin/bash
JUBATUS_VER="0.6.4"
JUBATUS_CORE_VER="0.0.5"
MSG_VER="0.5.7"
LOG4CXX_VER="0.10.0"
APR_VER="1.5.1"
APR_UTIL_VER="1.5.4"
UX_VER="0.1.9"
MECAB_VER="0.996"
IPADIC_VER="2.7.0-20070801"
ZK_VER="3.4.6"
PKG_VER="0.25"
RE2_VER="20130115"
ONIG_VER="5.9.5"
JUBATUS_MPIO_VER="0.4.5"
JUBATUS_MSGPACK_RPC_VER="0.4.4"

cd download

tar zxf msgpack-${MSG_VER}.tar.gz
tar zxf apache-log4cxx-${LOG4CXX_VER}.tar.gz
tar zxf apr-${APR_VER}.tar.gz
tar zxf apr-util-${APR_UTIL_VER}.tar.gz
tar jxf ux-${UX_VER}.tar.bz2
tar zxf mecab-${MECAB_VER}.tar.gz
tar zxf mecab-ipadic-${IPADIC_VER}.tar.gz
tar zxf zookeeper-${ZK_VER}.tar.gz
tar zxf pkg-config-${PKG_VER}.tar.gz
tar zxf onig-${ONIG_VER}.tar.gz

tar zxf jubatus_mpio-${JUBATUS_MPIO_VER}.tar.gz
tar zxf jubatus_msgpack-rpc-${JUBATUS_MSGPACK_RPC_VER}.tar.gz
tar zxf jubatus_core-${JUBATUS_CORE_VER}.tar.gz
tar zxf jubatus-${JUBATUS_VER}.tar.gz

3-1-3. ファイルの転送

scpコマンドやFTPソフトなどを使ってEdisonへファイルを転送しておきます.
jubatus-installerディレクトリごと移動させておけばよいでしょう.
なおこの際に,tarファイルやbz2ファイルはもう必要ないので削除しておいてかまいません.

3-2. 準備(Edison上での作業)

Edisonへ各ファイルを転送したら,インストールの準備を行います.

3-2-1. 必要なパッケージの導入

デフォルトのままだとiconvのヘッダが足りないためmecabのテストが正常に終了しません. 以下のパッケージを導入しておきます.
この点についても,jubatus開発者の@kumagiさんに教えて頂きました.ありがとうございます.

$ sudo opkg install eglibc-gconv-euc-jp

3-2-2. スクリプトへの修正点

次の手順3-3インストールの際にiオプションを使って,ファイルのダウンロードを実行しないようにするのですが,デフォルトのままだと解凍は行われてしまいます.
ですので,install.sh中171行目〜189行目のtarコマンドを利用する箇所をコメントアウトしておきます.

3-3. install

インストールスクリプト実行時にインストール先をubilinuxの際と同様にpオプションで指定します.
なお,ダウンロードコマンド実行時にはiオプション をつけてインストール作業のみを行うようにします.

$ cd jubatus-installer
$ sudo ./install.sh -p /home/root/local -i

インストールが完了したら,パスの設定を追加しておきます.
~/.profile などへ以下を記述します.

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/root/local/lib
export PATH=$PATH:/home/root/local/bin

以上でyocto Linuxへの導入は完了です.

4. jubatusの動作確認

導入したJubatusが動作するかどうかを,公式のサンプルにそって確かめてみます.公式のチュートリアルが充実していますから,そちらを参照すれば以下は読む必要がありません.
なお,ここではPythonクライアントでの利用について述べますが,Ruby等他のクライアントも用意されています.

4-1. jubatus-client(python)の導入方法

jubatus-installerに導入用スクリプトが存在するのでそちらを用います.なお,事前にpipを導入しておく必要があります.

4-1-1. pipの導入

python用のパッケージマネージャであるpipを導入します.また,のちほどyamlのライブラリも必要になるので導入しておきましょう.

$ wget https://bootstrap.pypa.io/get-pip.py | python
$ pip install PyYAML

4-1-2. python用ライブラリの導入

jubatus-installerのディレクトリに移動してスクリプトを実行します.

$ cd jubatus-installer
$ sudo ./install_python.sh

4-2. 公式チュートリアルにそった動作確認

Edisonへsshしてターミナルを2枚開いておきましょう.一方でサーバ,もう一方でクライアントのプログラムを実行します.
以下,公式にそい,5つの機械学習手法についての動作確認を行います.
その前に公式サンプルをクローンしておきます.

$ git clone https://github.com/jubatus/jubatus-example.git
$ cd jubatus-example

4-2-1. Classifierの動作確認

多値分類を行います.スパム判定のように,入力されたデータを複数のグループに分類します.
shogunという,歴代将軍の苗字と名前を学習して,入力された未知の名前から苗字を当てるプログラムを動かします.

サーバ側

$ cd shogun
$ jubaclassifier --configpath shogun.json

クライアント側

$ cd shogun/python
$ python shogun.py

4-2-2. Recommenderの動作確認

推薦を行います.広告やamazonのおすすめ商品推薦のように,入力データに類似するものを推薦します.
ここでは,npb_similar_playerという,野球選手のプロフィールを学習し,入力された未知の選手に類似する選手を返却するプログラムを動かします.

サーバ側

$ cd npb_similar_player
$ jubarecommender --configpath npb_similar_player.json

クライアント側

$ cd npb_similar_player/python
$ python update.py
$ python analyze.py

4-2-3. Regressionの動作確認

回帰分析を行います.株などの予測に用いられます. ここでは,入力された物件の情報から家賃を返却するプログラムを動かします.

サーバ側

$ cd rent
$ jubaregression --configpath rent.json

クライアント側

$ cd rent/python
$ python jubahomes.py -t ../dat/rent-data.csv -a ../dat/myhome.yml

4-2-4. Graphの動作確認

ネットワーク構造分析に用いられる,グラフマイニングを行います.
ここでは,電車の駅の間の最短経路を探索するプログラムを動かします.

サーバ側

$ cd train_route
$ jubagraph --configpath train_route.json

クライアント側

$ cd train_route/python
# グラフを作成
$ python create_graph.py
# 2つの駅のIDを与えて最短経路を計算
$ python search_route.py 0 144

4-2-5. Statの動作確認

異常データ検知などに用いられる,統計分析を行います.

サーバ側

$ cd trival_stat
$ jubastat --configpath stat.json

クライアント側

$ cd trival_stat/python
$ python stat.py

もっとくわしいこと

Jubatus公式HPを参照してください.

Intel EdisonをiBeacon化する.

概要

今回はNode.jsのモジュールであるnode-bleconを使ってIntel EdisonをiBeacon化してみる.

Intel EdisonでLチカした後にすることもないし積んでるわ,みたいな人はiBeacon化してリポ挿してチャリとかバッグにでもつけておけばいいんじゃないですかね+。:.゚+。:.゚+。:.゚(๑>◡╹๑)(๑╹◡<๑):.。+゚:.。+゚:.。+゚

手順

  1. EdisonのBluetoothをオンにする
  2. bluez5-devの導入
  3. bleaconを導入する
  4. コード記述とPCを使った動作確認

1. EdisonのBluetoothをオンにする

デフォルトではBluetoothがオフになっているので,オンにしておきましょう.

$ rfkill unblock bluetooth
$ hciconfig hci0 up

2. bluez5-devの導入

デフォルトだとBluetooth.hというヘッダがなくてbleaconを導入しても動作しないので,Bluetoothを扱うためのパッケージを導入します.
その前にパッケージのアップデート./etc/opkg/base-feeds.conf へ以下を追加.

# /etc/opkg/base-feeds.conf
src/gz all http://repo.opkg.net/edison/repo/all
src/gz edison http://repo.opkg.net/edison/repo/edison
src/gz core2-32 http://repo.opkg.net/edison/repo/core2-32

したらアップデートしておく.

$ opkg update
$ opkg upgrade

準備ができたらbluez5-devというパッケージをインストールする.

$ opkg install bluez5-dev

3. bleaconを導入する

Node.jsを使ってiBeaconを実現するモジュールとして,bleaconがある.今回はこれを利用するので,npmを使って導入しておく.

# テキトーにプロジェクト用ディレクトリをきる.
$ mkdir test_bleacon
$ cd test_bleacon
$ npm install bleacon

4. コード記述と動作確認

4-1. ibeaconにするためのコード

以下のコードをibeacon.jsみたいなjsファイルを作って記述する.複数のibeaconを使うようなシステムを組むときには,uuidをuuidgenコマンドとか使ってつくろう.

// ibeacon.js
var bleacon = require('bleacon');
var uuid = 'e2c56db5dffb48d2b060d0f5a71096e0';
var major = 0; // 0 - 65535
var minor = 0; // 0 - 65535
var measuredPower = -59; 

bleacon.startAdvertising(uuid, major, minor, measuredPower);

動作させる.

$ node ibeacon.js

このままだとホントに動いてるかよくわからないので,動作確認用プログラムを作る.

4-2. 動作確認用PC側プログラムの作成

bleaconはibeaconを検出するプログラムとしても使える.なので,PCにbleaconを導入して確認する.以下はPCで作業する.
PCの場合,bluez5-devを導入する必要はなく,PC側のBluetooth機能だけオンにしておく必要がある.

$ mkdir test_bleacon
$ cd test_bleacon
$ npm install bleacon

iBeaconを検出するコードをつくる.

//detect_ibeacon.js
var bleacon = require('bleacon');
bleacon.startScanning();

bleacon.on('discover', function(bleacon) {
       console.log(bleacon);
});

実行して検出できるか確認する.4-1でつくったibeaconプログラムを動作させておく.

$ node detect_ibeacon.js

4-3. 動作結果

すると,以下の様な感じで検出される.1ペアの中括弧でくくられたJSONっぽいやつが1回の検出で得られたデータ.rssiにもとづいて,Proximityが算出される.ここでは,Edisonを動かしたことによってimmediate〜nearに変化していることが分かる.

{ uuid: 'aebd140fa4884c39a5e6057f22f27ef5',
  major: 0,
  minor: 0,
  measuredPower: -59,
  rssi: -42,
  accuracy: 0.34164432192825195,
  proximity: 'immediate' }
{ uuid: 'aebd140fa4884c39a5e6057f22f27ef5',
  major: 0,
  minor: 0,
  measuredPower: -59,
  rssi: -42,
  accuracy: 0.34164432192825195,
  proximity: 'immediate' }
{ uuid: 'aebd140fa4884c39a5e6057f22f27ef5',
  major: 0,
  minor: 0,
  measuredPower: -59,
  rssi: -65,
  accuracy: 1.4609012747687342,
  proximity: 'near' }
{ uuid: 'aebd140fa4884c39a5e6057f22f27ef5',
  major: 0,
  minor: 0,
  measuredPower: -59,
  rssi: -64,
  accuracy: 1.3714628775092443,
  proximity: 'near' }

今後やりたいこと

ひと月くらい前に,BluetoothLEの仕様とか実装についてがっつり調べていたので,Central, Peripheralとして動作させる方法とか把握しておきたい.
前回のエントリで使ったIoT Analyticsも便利なんだけど,iOSAndroid端末にBLE経由でデータ収容する方法も把握しておきたいなあ〜と思ってる.

Intel Edisonからのセンサデータをお手軽にグラフプロットするIoT Analyticsの使い方

このエントリの概要

Intel Edison にくっつけたセンサのデータを, IoT AnalyticsというIntelのサービスへPublishし,リアルタイムにグラフとしてプロットする方法について説明します.
以下の様なグラフを簡単に作ることができます.

graph

IoT Analyticsの利点

まだ開発段階だと思うので,全ての機能が正常に動作してるかがわかりません(というかそもそもHow to 的なものが整備されていない……).手探りで触ってみて感じた利点は以下.

  • Edisonを使ってデータを収集するまでのハードルがめちゃくちゃ低い

    • これはiotkit-commの恩恵が主かな?
    • サーバの準備,サーバクライアント間のプロトコル選定,収集プロトコル,グラフ化プログラムなどなどが準備済み
  • ネットワーク越しのセンサデータをリアルタイムにグラフにプロットして確認できる

  • CSVもリアルタイムに得られるから他の分析ツールへ移行しやすい
  • 閾値などを使ってルールを記述して,マッチするときにアラートをメールで送れる?(と思うんだけどエラーが出ていて利用できてない……説明もない)
  • サーボとかもこれを通して操作できる??(と思うんだけどエラーが出て利用できていない……説明もない)

手順

  1. IoT Analytics アカウントをつくる
  2. EdisonをIoT Analyticsに登録する
  3. Edisonで取得したデータをPublishするためにEdisonのセットアップを行う
  4. dataをPublishする
  5. Publishされたデータを閲覧する
  6. CSVで取得してExcelでプロットしてみる
  7. CSVで取得してPythonでSciPy, matplotlibを使ってプロットしてみる

1. IoT Analytics アカウントをつくる

IoT Analyticsへアクセスする.OAuth使うと問題が起きるみたいなコメントがどっかにあった気がするけど実際どうなんだろう.不安だったのでメルアドで登録した.

2. EdisonをIoT Analyticsに登録する

下図を参照.AccountメニューのDetailsタブにアクティベーションキーがあるのでメモしておく.更新ボタンを押してから1時間アクティベーションキーが有効になる.目のボタンを押すとキーが見えるようになる.

アクティベーションキーの場所

アクティベーションキーを取得したら,そのキーを用いてEdisonをIoT Analyticsへ登録するためにEdison上で下記コマンドを実行する.

# [activation-key]は先ほどメモしたアクティベーションキーに置き換える
$ iotkit-admin activate [activation-key]

以下の様な表示がされたら登録は完了.

2014-11-02T14:40:07.571Z - info: Activating ...
2014-11-02T14:40:09.146Z - info: Saving device token...
2014-11-02T14:40:09.159Z - info: Sending attributes...

以下の様なエラーが出るときはアクティベーションキーが間違ってます.
ぼくはI(大文字アイ)l(小文字エル)を間違えてました.フォント的に見難い.

2014-11-02T14:39:58.188Z - error: Activation Rejected:  {"code":1410,"message":"Invalid Activation Code"}  --> error
2014-11-02T14:39:58.194Z - error: Error in the activation process ... 300

3. Edisonで取得したデータをPublishするためにEdisonのセットアップを行う

iotkit-agentを有効にして起動します.

$ systemctl enable iotkit-agent
$ systemctl start iotkit-agent

4. dataをPublishする

iotkit-commを使ってClientアプリケーションを記述します.iotkit-commについて分からなければ,以前のエントリを参考にしてください.

4-1. Service Specificationを記述する

まず,IoT Analyticsを使ったService Specificationを作ります(enableiot-cloud-spec.json)

//enableiot-cloud-spec.json
{
    “type”: {
        “name”: “enableiot-cloud”,
        “protocol”: “tcp”,
    },
    “address”: “127.0.0.1”,
    “port”: 1844
}

4-2. データをPublishするコードを書く

次に,データをIoT AnalyticsへPublishするためのコードを書きます.
公式のチュートリアルはデータを1回送って終わりだからグラフにした時におもしろくないので,5秒ごとにランダムなデータを送信するように修正します.

//temperature_sensor.js
var iotkit = require(‘iotkit-comm’);
var spec = new iotkit.ServiceSpec(“enableiot-cloud-spec.json”);
var sensor_value;

iotkit.createClient(spec, function(client){
    client.comm.registerSensor(“garage”, “temperature.v1.0”);

    setInterval(function(){
        sensor_value = 40 + Math.floor(Math.random() * 31);
        client.comm.publish(JSON.stringify({“n”: “garage”, “v”: sensor_value}));
    }, 5000);
});

コードを書いたら,node.jsを使って実行します.

node temperature_sensor.js

ここでのポイントは2つです.

  • client.comm.registerSensor() を使って利用するセンサの種別と名前(ID)を登録する.
  • cilent.comm.publish() を使ってデータをPublishする.データの形式は,client.comm.registerSensor()で登録した名前と,valueのペアで構成されるJSONです.

つまり,IoT Analytics側でセンサの持つ意味を判別するためのニックネーム(ID)をセンサ種別(温度,湿度など)と合わせて保持しておき,Publishする際にはどのセンサからのデータなのかということをIDを使ってIoT Analyticsへ教えてあげるということになります. ここで,センサのことをComponentと呼び,ひとつのデバイスは複数のComponentを持つことができます.

補足:接続確認

IoT Analyticsへ接続できているかを以下のコマンドで確認できる.うまくいかない場合の切り分けに.

$ iotkit-admin test
補足:Componentの初期化

センサを登録していくと,そのうち使わないやつばっかりになってくることがある.そんなときはデバイスに登録しているComponentを初期化してやる.個別に削除する方法は分かってない.

iotkit-admin initialize  
iotkit-admin reset-components 

4-3. 補足:センサ種別について

デフォルトで定義されているセンサーは,以下の3つです. - 温度センサ:temperature.v1.0 - 湿度センサ:humidity.v1.0 - 電源状態:Powerswitch.v1.0

4-4. 補足:独自センサをIoT Analyticsへ登録する

もし,上記の3つ以外のセンサを扱いたい場合,事前に登録をしておく必要があります.ここでは距離データ(mm)を得ることができる距離センサを登録してみましょう.

AccountページのCatalogタブを開くと,そのアカウントの中で定義されているセンサ種別が表示されます(正確にはアクチュエータも含まれますが,今回はセンサに絞って話を進めます).画面下部にあるAdd a new Catalog Itemというボタンをクリックします. Componentページ

すると,下図のように新しいComponentを定義するための画面が表示されます.ここでは図にあるように,mm単位で距離を出力する距離センサを定義してみます. Componentページ

Saveをボタンを押すとComponentが保存されます.確認のためにもう一度アカウントメニューのCatalogタブを開いてみます.さきほど作成した距離センサが作成されました. Componentページ

定義した距離センサをさきほど4-2で作成したコード中で以下のように記述すれば,距離センサから取得したデータをIoT AnalyticsへPublishすることができます.

client.comm.registerSensor(“living_tv”, “distance.v1.0”);
client.comm.publish(JSON.stringify({“n”: “garage”, “v”: distance_value}));

5. Publishされたデータを閲覧する

ChartメニューからグラフへプロットするDeviceとComponentを選択すると,取得したデータのグラフが表示されます.グラフ上部のボタンと,グラフ下部のスライダーを使って表示する時間幅を調整することができます.自動更新はされないので更新ボタンを押すことで新しいデータを確認する必要があります.リフレッシュボタンを押すと呼ばれる関数を定期的にコールするJavascriptを実行すれば良いでしょう.

graph

6. CSVで取得してExcelでプロットしてみる

グラフ上部のshareボタンを押すとCSVでエクスポートすることができます.

csv

これをExcelで読み込んで線グラフとしてプロットしてみます. excel

7. CSVで取得してPythonでSciPy, matplotlibを使ってプロットしてみる

今度はPythonを使ってプロットしてみる.scipyとmatplotlibを使う.

>>> import scipy as sp
>>> data = sp.genfromtxt("data.csv", delimiter=",")
>>> x = data[:, 5]
>>> y = data[:, 6]
>>> x = x[~sp.isnan(y)]
>>> y = y[~sp.isnan(y)]
>>> import matplotlib.pyplot as plt
>>> plt.plot(x, y, 'bo-')
[<matplotlib.lines.Line2D object at 0x109f73bd0>]
>>> plt.grid()
>>> plt.show()

グラフ

確認中のこと.

Controlメニューから,デバイスのアクチュエータを操作する方法

例えばサーボとかの動作角度を指定してサーバから動作させるとかができると思うんだけど,全然使い方がわからない… control

Rulesメニューからルールを登録する方法

デバイスのComponentのデータを監視して,設定しておいた閾値以上になるとアラートをメールで送るとか,そういうルールが記述できると思うんだけど,最後の登録のところでエラーがでる… rules

Intel Edisonで iotkit-commを使うその3:Service SpecificationsとService Queriesについて.

前回のエントリの続き.
前回の説明ではJSONのサンプルとしてしか触れていなかった,Service SpecificationsとService queriesについてのもう少し詳しい説明.

もっと詳しいことを学ぶその3. Service Specifications と queriesについて

Service Specifications と queriesは,分散アプリケーションの開発をシンプルにするiotki-commライブラリの使い方を理解するためのキーだ.iotkit-commで記述された分散アプリケーションは,基本的にサーバとクライアントで構成される.
開発者はService を以下のステップで開発する.

  1. service specification を記述する
  2. specification に基づいたServiceを生成するために,iotkit-commライブラリへリクエストを行う

また,開発者はClientを以下のステップで開発する.

  1. Service query の記述
  2. queryに記述されたAttributesにマッチするServiceの発見と接続をiotkit-commへリクエストする

Service Specifications と queriesはとてもよく似ています.コードについて言えば,Service Specificationsオブジェクトは,Service queryの子となっています.しかし,これらの2つには,根本的な違いが2つあります.

  1. queryはClientによってのみ利用されるのに対して, specificationsはClient,Serverの両者で利用される.Specificationsが初期化や,Serviceへの接続に利用されるが,queryはServiceの発見のみに利用される.
  2. queryはIPアドレスやPortを含むことができないが,対して,Service Specificationは含むことができる.なのでこれらの情報は事前に共有されていないと考えたほうが良い.

ここで,少し脱線するけど,ネットワーク上のServiceを発見することが,どういうことなのかについて詳しく説明をする.
Service発見の機能にともなって,nameやProtocolによる検索を行い,IPアドレスやポート番号を獲得する.Serviceはネットワークでの最初のAdvertiseによってのみ発見される.Service Specificationsのうちの1つがService queryにマッチした時,Serviceを発見した,と言う.Service SpecificationsのAdvertisingとService Queryとのマッチングを管理するプロトコルは,mDNS(Multicast DNS)と呼ばれる.mDNSのコンセプトに基づくために,Service Specifications, query,それらのマッチングはiotkit-commによって抽象化されていることを覚えておいてください.

続いて,Service SpecificationsとQueryの書き方について説明します.これらはJSONで記述されます.

Service Specifications

以下はService Specificationsの例です. 例に続いて各Attributeの説明を行います.

Server Specificationsの例

{
    "name": "/my/home/thermostat/temperature_sensor",
    "advertise": {"locally": true, "cloud": false},
    "type": {
        "name": "zmqpubsub",
        "protocol": "tcp"
    },
    "type_params": {"ssl": false},
    "address" : "127.0.0.1",
    "port": 8999,
    "properties": {"dataType": "float", "unit": "F", "sensorType": "ambient"}
}

各フィールドについての説明

  • name(例外を除いてオプション): 文字列.なるべくユーザフレンドリなものを.Service namesは他のアプリケーションでも表示される可能性がある.
    ※ nameは,もしネットワーク上でServiceがAdvertiseされる場合には設定しなければならない.

  • advertise(オプション): このオプションが設定されない場合,ServiceはLAN内でAdvertiseを行います. ※ 現在のiotkit-commはクラウドでのAdvertising Serviceをサポートしていません.そのため現在は,”cloud”フィールドは無視されてしまいます.

  • type(必須): メッセージの送信受信方法は typeフィールドによって設定されます.typeフィールドは通常,”name”と,”communication plugin”を含みます.iotkit-commでは,プラグインがどのようにメッセージが送信されるかを抽象化するので,開発者はメッセージの内容にフォーカスすることができる.

    • name(必須): このServiceが話すプロトコルの名前を示す.これはまた,利用する通信プラグインの名前にもなる.
    • protocol(必須): トランスポートプロトコルの種別を示す.”tcp”もしくは”udp”のみがサポートされている.
  • type_params(オプション): 通信プラグインがサポートできる設定パラメータ.iotkit-commはこのパラメータをそのまま通信プラグインに引き渡す.

  • port(必須): サーバが動作するポート番号.
  • properties(オプション): Serviceが持つユーザプロパティ.各プロパティは,”name”: valueのペアで記述されなければならない.この場合の例では,センサが周囲の温度を華氏で,FloatでPublishする,という設定を行っている.
  • address(オプション): サーバが動作するアドレス.記述しなければlocalhostが利用される.

このSpecificationはmodule:main.createServiceに渡すことができ,最終的には指定されたアドレスとポートで動作しているServiceのインスタンスを返します.

Service Query

以下にService queryの例を示し,続いて各Propertyの説明を行います.

Server Queriesの例

{
    "name": ".*temperature_sensor",
    "type": {
        "name": "zmqpubsub",
        "protocol": "tcp"
    }
}

このqueryは,Service Specificationセクションで示したSpecificationsと一致していることが大事です.さらに,このqueryはzmqpubsubプロトコルを利用して通信を行う,LAN内の全ての温度センサを発見しに行きます.以上を念頭において各Attributeについて見てみましょう.

各フィールドの説明

  • name(オプション): 正規表現を利用可能.
  • type(必須)
    • name(必須): Serviceが利用する高レイヤの通信プロトコル.これによりClientは,数あるServiceの中から通信可能なものを探すことができる.例えば,type.nameフィールドに zmqpubsub を指定した場合,zmqsubscriber はzmq publishers のみを探すことができる.
    • protocol(必須): トランスポートプロトコル.”tcp”もしくは”udp”のみ利用可能.

このqueryはmodule:main.createClientに渡すことができ,最終的にはServiceに接続されたClientインスタンスが返されます.

Intel Edisonで iotkit-commを使うその2:ServerとClientについて.

前回のiotki-commチュートリアルの "4.もっと詳しいことを学ぶ" の続きです.

もっと詳しいことを学ぶその1. server(Service)の書き方

iotkit-commのチュートリアルその1,Clientについて

以下の3つのステップでService(Server)を作成する

  1. Service Specificationを記述する
  2. 1で決めたSpecificationにもとづいてServiceを作成する
  3. Serviceを実行する

以下でその例について述べる ※以下で示すサンプルコードは,/usr/share/iotkit-comm/examples/node/basic-client-serverに配置されています.

1. Service Specificationを記述する

Service SpecificationはJSONとして記述する.このJSONには,Serivceが動作するポート,Serviceの名前,通信時に利用するプロトコルといったAttributesを記述する.ここでは例として,以下の “server-spec.json”を記述してみる.

{
    “name”: “/ndg/temperature/cpuTemp”,
    “type:”: {
        “name”:”zmqreqrep”,
        “protocol”: “tcp”
    },
    “port”: 8333,
    “properties”: {“dataType”: “float”, “unit”: “F”},
    “advertise”: {“locally”: true, “cloud”: false}
}

2. 1で決めたSpecificationにもとづいてServiceを作成する

例として以下のServiceを作成する(server.js)

var iotkit-comm = require(‘iotkit-comm’);
var path = require(‘path’);
var spec = new iotkit.ServiceSpec(path.join(__dirname, “server-spec.son”);

iotkit.createService(spec, function(service){
    service.comm.setReceivedMessageHandler(function(client, msg, context){
        cnosole.log(“received from client: “ + msg.toString());
        service.comm.sendTo(client, “hi”);
    });
});

※Serviceでは,どのような内容のメッセージかのみを記述するため,そのメッセージが届くかどうかは気にする必要がありません. type.nameフィールドでの記述があれば,iotkit-commはどのようにメッセージを送信すればよいかを判断することができます.(今回の例でいうと”zmqreqrep”) ※ zmqreqrep: ZeroMQ is a high-performance asynchronous messaging library

通信の詳細は,通信プラグインによって処理されます.今回の例で言うと,通信プラグイン(service.comm)は, zmqreqrepプラグインインスタンスです.通信プラグインの詳細は後述しますが,ここでは,通信プラグインは send や,sendTo といったファンクションを提供すると考えてください.
様々な通信プラグイン間の主な違いは,send や, sendTo といったファンクションのコールによって何が起こるかである(例えば,パケットフォーマットやヘッダが異なる).標準でいくつかの通信プラグインがiotkit-commにバンドルされているが,必要に応じて独自の通信プラグインを書くことも簡単にできる.

3. Serviceを実行する

これまでに記述した server-spec.json と, server.js を同じディレクトリに置き,以下のコマンドを実行すればServiceが起動します

node server.js

もっと詳しいことを学ぶその2. client の書き方

iotkit-commのチュートリアルその2,Clientについて

以下の3つのステップでClientを作成する

  1. Service queryを記述する
  2. ServiceのためのQueryにもとづいてClientを作成する
  3. Clientを実行する

以下でその例について述べる ※以下で示すサンプルコードは,/usr/share/iotkit-comm/examples/node/basic-client-serverに配置されています.

1. Service queryを記述する

Service QueryはJSONとして記述する.このJSONには,Clientが接続したいServerのAttributesが記述されている.ここでは例として,以下の “server-query.json”を記述してみる.

{
    "name": "/ndg/temperature/cpuTemp",
    "type": {
        "name": "zmqreqrep",
        "protocol": "tcp"
    },
    "properties": {"dataType": "float", "unit": "F"}
}

2. ServiceのためのQueryにもとづいてClientを作成する

例として以下のclientを作成する(client.js)

var iotkit = require('iotkit-comm');
var path = require('path');
var query = new iotkit.ServiceQuery(path.join(__dirname, "server-query.json"));
iotkit.createClient(query, function (client) {
    client.comm.setReceivedMessageHandler(function (message, context) {
        console.log("received from server: " + message.toString());
        client.comm.send("hello");
    });
    client.comm.send("hello");
});

※ ServiceのIPアドレスや,Serviceとの通信方法をClientが知っている必要はありません.代わりに,Service queryがそのような詳細について管理してくれます.例えば,ClientではServiceの名前とServiceが利用するプロトコル(この場合zmqreqrep)を記述します.Serviceが見つかると,iotkit-commは適切に初期化された通信ハンドル(client.comm)をClientオブジェクトとともに返します.このハンドルは,Serviceに接続されたzmqreqrepプラグインインスタンスです.
通信プラグインの詳細は後述しますが,ここでは,通信プラグインは send や,sendTo といったファンクションを提供すると考えてください.
様々な通信プラグイン間の主な違いは,send や, sendTo といったファンクションのコールによって何が起こるかである(例えば,パケットフォーマットやヘッダが異なる).標準でいくつかの通信プラグインがiotkit-commにバンドルされているが,必要に応じて独自の通信プラグインを書くことも簡単にできる.

3. Clientを実行する

これまでに記述した server-query.json と, client.js を同じディレクトリに置き,以下のコマンドを実行すればClientが起動します

node server.js

動作確認

Tutorial: Server で作成したServerと,このセクションで作成したClientを起動させると,以下のような実行結果が得られます.

f:id:concre_shiitake:20141026234929p:plain

Intel Edisonで iotkit-commを使う:サーモスタットサンプルによるGetting Started

IoTIoT言うとりますけども.
という感じでIntel Edisonに提供されているiotkit-comm.
いかにも!という感じがするライブラリ名だけど,解説記事が全然ないので,ひとまずGettingStartedを訳しながら試してみた.
というわけで,公式ドキュメントを参考にして,話を進めます.

iotkit-comm Getting Started

概要

iotkit-commは以下の様な機能を提供します.これを使うと,クライアント,サーバによって構成される分散アプリケーションの開発ができるようになります.

  • ネットワークに接続されたデバイスの発見
  • ネットワークに接続されたデバイス同士での通信
  • ネットワークに接続されたデバイスとクラウド間での通信

Intel Edison向けのプラットフォームとして設計されていますが,他のプラットフォームでも同様に動作しています.
iotkit-commは,CとNode.js向けのライブラリが存在しますが,以下ではNode.js向けの説明をします.

このドキュメントの読み方

2つのセクションがあるので,目的に応じて利用します.

  • APIリファレンスを閲覧するためのセクションは,”Modules”セクションです.

    • “main”モジュールから読み始めることをおすすめします
  • APIの利用方法についてのチュートリアルを閲覧するためのセクションは,”Tutorial”セクションです.

※ このドキュメントは,Modulesが,Classes, Methods, Variablesのどのような論理構成により実現されるのかを示したものであり,あくまでドキュメントであることに注意してください.コードベースでiotkit-commを説明したものではありません.

このドキュメントでの前提条件

  • Edisonがインターネットアクセス可能であること
    • 前回のエントリを参考にWiFi設定を行いましょう.
  • SampleプログラムやコマンドがEdison上で動作可能であること.
    • 後で記述する,iotkit-commにおけるHelloWorldを試してみましょう.

iotkit-comm ドキュメント(Tutorial編)

Start Here

iotkit-commライブラリを使って開発を行うために,以下のように学習していきます.

  1. iotkit-commのインストール
  2. hello world”プログラムを書いて実行する(オプション)
  3. 付属のサンプルプログラムを実行する(オプション)
  4. もっと詳しいことを学ぶ(オプション)

1. iotkit-commライブラリのインストール

  • Intel Edisonデバイスにはもうインストール済みだからこの手順は必要ないです.

    • 他のプラットフォームへのインストール方法は後日公開予定.
  • ただし,以下の方法でIoT Developer Kit librariesに関するアップデートだけしておきましょう.

$ echo "src intel-iotdk http://iotdk.intel.com/repos/1.1/intelgalactic" > /etc/opkg/intel-iotdk.conf
$ opkg update
$ opkg upgrade

2. Write “hello world”プログラムを書いて実行する

  • “helloworld.js”というJavascriptファイルを作成し,以下のプログラムを記述します.
var iotkit = require(‘iotkit-comm’);
console.log(iotkit.sayhello());
  • 記述した”helloworld.js”の動作をターミナルで確認します.
$ node helloworld.js
# 以下の文字が出力される
>Hello Edison user!

3. サンプルプログラムの実行

  • ※ 公式ページのディレクトリ構成は最新ファームと異なります.以下では,2014/10/26現在での最新ファームである,edison-weekly_build_68_2014-09-08_13-49-07 でのディレクトリ構成を基に話を進めます.
  • この章ではサーモスタットプログラムを試してみましょう.

3-1. 利用するサンプルの概要と補足情報

いくつかの温度センサからのデータを受信するサーモスタットプログラムを試してみます.このプログラムは公式リファレンスでは以下のディレクトリにあるとされていますが,

  • /usr/share/iotkit-comm-js/examples

現在のファームでは以下のディレクトリに移動しています.

  • /usr/share/iotkit-comm/examples/node/distributed-thermostat

3-2. 温度センサの実行

$cd /usr/share/iotkit-comm/examples/node/distributed-thermostat
# 温度センサの起動
$ node temperature-sensor.js
# ターミナル上には特に何も出力されません.

3-3. サーモスタットの実行

  • 3-2とは異なるターミナルを開き,サーモスタットを実行します.
    • 1つのEdison上で実行する場合は,2つのターミナルを開き,それぞれのターミナルからsshでEdisonへ接続すると良いです.
$cd /usr/share/iotkit-comm/examples/node/distributed-thermostat
# サーモスタットの起動
$ node thermostat.js 

3-4. 動作の確認

サーモスタットと温度センサを同時に実行すると,温度センサ(temperature-sensor.js)から送信される温度データを,サーモスタット側(thermostat.js)で受信し,ターミナル上で以下の様な出力が得られます.

# 温度センサ1台数の時
Found new temperature sensor - 127.0.0.1:20408
Received sample temperature 90 from 127.0.0.1:20408
New average ambient temperature (cumulative): 45
Received sample temperature 79 from 127.0.0.1:20408
New average ambient temperature (cumulative): 56.333333333333336
Received sample temperature 67 from 127.0.0.1:20408
New average ambient temperature (cumulative): 59
Received sample temperature 83 from 127.0.0.1:20408
New average ambient temperature (cumulative): 63.8
Received sample temperature 72 from 127.0.0.1:20408
New average ambient temperature (cumulative): 65.16666666666667
Received sample temperature 62 from 127.0.0.1:20408
New average ambient temperature (cumulative): 64.71428571428571

新しいセンサが追加された際も,発見と通信が自動で行われます.

# 途中から温度センサを追加した時
# Found new temperature sensor という所で新しいセンサが検出されています
eceived sample temperature 79 from 127.0.0.1:20408
New average ambient temperature (cumulative): 74.21212121212122
Received sample temperature 63 from 127.0.0.1:20408
New average ambient temperature (cumulative): 73.88235294117646
Received sample temperature 71 from 127.0.0.1:20408
New average ambient temperature (cumulative): 73.8
Found new temperature sensor - 127.0.0.1:54187
Received sample temperature 73 from 127.0.0.1:20408
New average ambient temperature (cumulative): 73.77777777777777
Received sample temperature 61 from 127.0.0.1:54187
New average ambient temperature (cumulative): 73.43243243243244
Received sample temperature 78 from 127.0.0.1:20408
New average ambient temperature (cumulative): 73.55263157894737
Received sample temperature 88 from 127.0.0.1:54187
New average ambient temperature (cumulative): 73.92307692307692
# 温度センサとサーモスタットプログラムをそれぞれ別のEdisonから実行した時.
Received sample temperature 85 from 192.168.11.13:13304
New average ambient temperature (cumulative): 73.75862068965517
Received sample temperature 85 from 192.168.11.13:13304
New average ambient temperature (cumulative): 73.94915254237289

# さらにサーモスタットが動作するEdison上でも温度センサを動作させる
Found new temperature sensor - 127.0.0.1:54453
Received sample temperature 90 from 192.168.11.13:13304
New average ambient temperature (cumulative): 74.21666666666667
Received sample temperature 64 from 127.0.0.1:54453
New average ambient temperature (cumulative): 74.04918032786885
Received sample temperature 87 from 192.168.11.13:13304
New average ambient temperature (cumulative): 74.25806451612904
Received sample temperature 71 from 127.0.0.1:54453
New average ambient temperature (cumulative): 74.2063492063492

4. もっと詳しいことを学ぶ

以下の様な手順で学んで行こう,とされています.後日追記予定.

  1. server の書き方
  2. client の書き方
  3. Service Specifications と queriesについて(重要)
  4. iotkit-commを使って分散アプリケーションを書く方法
  5. cloudにデータをPublishする方法
  6. iotkit-commを利用したソースのUnitテスト方法(未公開)
  7. iotkit-commアーキテクチャについて(未公開)

Intel EdisonのGetting startedその2.(Arduino IDEからの転送,Edison初期設定)

Getting Started Edison

  • このエントリは以下の2つの事項について説明します.

    • Arduino IDEからのプログラムの書き込み方法
    • Edisonの初期設定(デバイス名,パスワード,WiFi設定)を行う方法
  • これも公式の訳+アルファです.

  • 購入してからファームウェアを更新していない場合は,1つ前のエントリを参考にしてファームウェアの更新を行ってください.

step 1. Connectiong Edison

  • 箱から出したedisonをボードに接続する.順番としては前回エントリのファームウェア更新よりも前ですね〜

step 2. Download Edison Arduino IDE

step 2-1. Edison 用Arduino IDEのインストール

  • 公式ページから,Edison用のArduino IDEをダウンロードしてインストール
    • Macの場合,アプリ名が”Arduino.app”となっており,本家Arduinoと競合するので,”Arduino edison.app”とかにでもリネームしておきましょう.

step 2-2. テストとしてBlinkプログラムをEdisonへ書き込む

HWでのHello, World!であるBlink(LED点滅)プログラムを書き込みます.

  1. Arduino IDEを起動して,File -> Examples -> Basics -> Blink を開く
  2. Tools -> Board で”Intel Edison”を選択
  3. Tools -> Serial Portで,”/dev/cu.usbmodemxxxx”を選択

    • xxxx部分は各環境により異なります.
    • ttyではなくcuのものを選択します.
  4. IDE左上のチェックマークのアイコンをクリックしてビルドする

  5. チェックマークアイコンの隣の矢印アイコンを押してEdisonへプログラムを転送する

    • No, such file or directory というエラーが出たら指定しているSerial Portが間違っているので,3に戻ってSerial Portの選択を行います
  6. Arduinoボード上のLEDが点滅すればOKです.

    • Break out boardの場合は該当するGPIOにLEDつないで確認するのかな?未確認です!

Step 4. 初期設定(デバイス名,SSID名,パスワード,Wifi設定)

  • edisonの設定を行うために,”configure_edison”というコマンドが提供されている.さらに,setupオプションを付けることで初期設定を一括でできる.
# 初期設定の実施
 # configure_edison --setup
# これで実行される設定は以下の3つ.
# 1. デバイス名の設定.これはSSIDとしても利用されるようです.
# 2. rootパスワードの設定.これはSSIDパスワードとしても利用されるようです.
# 3. WiFiの設定.初回は失敗したけど,2回目でAPが見えるようになりました.
# 最後に表示されるIPかURLを使ってブラウザからアクセスするとEdisonに関する情報が確認できます.
# 各設定で間違えたら,以下の補足にあるようにconfigure_edisonコマンドのオプションを変えて実行しましょう.

補足

ちなみに,”configure_edison”コマンドのオプションは以下のようになっている.

# configure_edison --help
usage: configure_edison [-h] [--server]
                        [[--setup | --name | --password | --wifi]
                        [--showWiFiIP | --version | --latest-version | --upgrade | --disableOneTimeSetup | --enableOneTimeSetup | --flash <version> [<release name> ...]
                        | --showNames]

optional arguments:
  -h, --help            show this help message and exit
  --server              Starts the server (testing only)
  --setup               Goes through changing the device name, password, and
                        wifi options
  --name                Changes the device name
  --password            Changes the device password
  --wifi                Changes the wifi options
  --showWiFiIP          IP address associated with the wireless interface
  --version             Gets the current firmware version
  --latest-version      Gets the latest firmware version
  --upgrade             Downloads the latest firmware
  --disableOneTimeSetup
                        Disable one-time setup and WiFi access point
  --enableOneTimeSetup  Enable one-time setup and WiFi access point
  --flash <version> [<release name> ...]
                        Downloads and flashes an image
  --showNames           Show device name and SSID

wifi接続先を追加するときとか,Edisonの名前(SSID)変えたい時とかも使えますね.
例えばwifiの設定変更なら以下のようになります

# configure_edison --wifi