24: Intel Edison実践編 (4) 〜 センサーデータをCloudWatchに送ってみる

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

よく訓練されたアップル信者、都元です。昨日のエントリーはこちらです。ビッグデータの送り先は是非ともAWSに。そうですよ、IoT Analyticsしてる場合じゃないです。

まぁ、本気でやるならKinesisに送り込む話なんですが、ここはライトに、こういった時系列データの扱いが得意なCloudWatchに送り込んでみましょう。

Cognitoの設定

AWS側の認証には、先日ご紹介したCognitoの仕組みを使います。ということで、UnAuthRoleに下記のようなポリシーを追加しておきましょう。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "cloudwatch:PutMetricData",
      "Resource": "*"
    }
  ]
}

aws-sdkの依存設定を記述

node.jsからCloudWatchのAPIを叩きますので、下記のようにdependencies設定を記述します。

(略)
  "dependencies": {
    "aws-sdk" : "*"
  }
(略)

コーディング

あとはこんな感じです。まずはCognito認証を行い、CloudWatchのクライアントオブジェクトを作ります。

// ==== Config
var accountId = "123456789012";
var cognitoRoleArn = "arn:aws:iam::123456789012:role/Cognito_WorkerBoxUnauth_DefaultRole";
var cognitoIdentityPoolId = "us-east-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";

 // ==== AWS
var AWS = require('aws-sdk');
var awsRegion = "us-east-1";
var cognitoParams = {
    AccountId: accountId,
    RoleArn: cognitoRoleArn,
    IdentityPoolId: cognitoIdentityPoolId
};

AWS.config.region = awsRegion;
AWS.config.credentials = new AWS.CognitoIdentityCredentials(cognitoParams);
AWS.config.credentials.get(function() {
    if (!err) {
        console.log("Cognito Identity Id: " + AWS.config.credentials.identityId);
    }
});

var cloudwatch = new AWS.CloudWatch({region: 'ap-northeast-1'});

続いて、センサーへのアクセスオブジェクトを作成。

// ==== Sensor
var groveSensor = require('jsupm_grove'); 
var tempPin = new groveSensor.GroveTemp(0);
var lightPin = new groveSensor.GroveLight(1);

あとはputMetricDataを使ってデータをひたすら送り続けます。複数の値でも1回のPutでいけますね。

// ==== Main Loop
setInterval(function(){
    var date = new Date();
    console.log("==== " + date + " ====");
    var temp = tempPin.value();
    var light = lightPin.value();

    console.log(tempPin.name() + ": " + temp);
    console.log(lightPin.name() + ": " + light);
    var params = {
      MetricData: [
        {
          MetricName: 'temp',
          Timestamp: date,
          Unit: 'None',
          Value: temp
        },
        {
          MetricName: 'light',
          Timestamp: date,
          Unit: 'None',
          Value: light
        }
      ],
      Namespace: 'edison'
    };
    
    cloudwatch.putMetricData(params, function(err, data) {
      if (err) console.log(err, err.stack); // an error occurred
      else     console.log(data);           // successful response
    });
}, 60000);

結果

2014-12-24_1728

カスタムメトリクスのネームスペースedison *1において、templightという値が届いて、きちんとプロットされていることが確認できました。

こぼれ話

実は本日は「Intel Edison実践編 (4) 〜 もっと高水準なAPI iotkit-comm を使う」をお届けの予定でしたが、どうにもこうにも上手く動かず、お蔵入りとなりました。下記はその残骸となります。勿体無いので放出。

iotkit-comm

iotkit-commのチュートリアルを見ながらやってみます。

まずenableiot-cloud-spec.jsonについて。チュートリアルでは1884という、恐らくMQTTサーバのポートを指定していますが、iotkit-agent1884で待ち受けていません。TCPならば7070で待ち受けているようです。そこでこのように。この辺りでもう失敗してそうですが。

{
    "type" : {
        "name": "enableiot-cloud",
        "protocol" : "tcp"
    },
    "address" : "127.0.0.1",
    "port" : 7070
}

その上で、こんなコードを動かしてみました。

var iotkit = require('iotkit-comm');
var spec = new iotkit.ServiceSpec('enableiot-cloud-spec.json');

// ==== Sensor
var groveSensor = require('jsupm_grove'); 
var tempPin = new groveSensor.GroveTemp(0);
var lightPin = new groveSensor.GroveLight(1);

iotkit.createClient(spec, function(client){
    client.comm.registerSensor('temp', 'temperature.v1.0');
    client.comm.registerSensor('light', 'light.v1.0');

    // ==== Main Loop
    setInterval(function(){
        var date = new Date();
        console.log("==== " + date + " ====");
        var temp = tempPin.value();
        var light = lightPin.value();

        console.log(tempPin.name() + ": " + temp);
        client.comm.publish(JSON.stringify({
            "n": "temp",
            "v": temp
        }));

        console.log(lightPin.name() + ": " + light);
        client.comm.publish(JSON.stringify({
            "n": "light",
            "v": light
        }));
    }, 60000);
});

が、IoT Analyticsに値は上がってきませんでしたorz

iotkit-agentをバージョンアップグレードする

opkgのリポジトリには iotkit-agent 0.8.7a-r0 がホストされていますが、実はかなり古い *2ようで、最新版は執筆時点で v1.5.6 です。これが古いから上手く動かないのかな、と思い、この辺りを見ながらアップグレードしてみました。

手順は以下の通り。

まず、既存のiotkit-agentは、動いていれば止めて無効化しておきます。その上でopkg removeします。

# systemctl stop iotkit-agent
# systemctl disable iotkit-agent
# opkg remove iotkit-agent

続いてnpmでインストールします。systemd用の起動設定ファイルもあるのでコピーします。

# npm install --global iotkit-agent
# cp iotkit-agent/iotkit-agent.service /lib/systemd/system/

デバイスのアクティベートを再び行い、起動すればバージョンアップされています。

# iotkit-admin activate XXXXXXXX
# systemctl start iotkit-agent
# systemctl enable iotkit-agent
# iotkit-admin -V
1.5.6

まぁ、結果的に上手く動きませんでした。という失敗の記録でした。

iotkit-commは、GitHubにリポジトリがあるのですが中身が空っぽでした。まだまだ、発展途上のプロダクトと言えそうです。今後に期待ですね。

明日のエントリーはこちらです。いよいよ千秋楽。

脚注

  1. 左下のドロップダウンリストから選択します
  2. またはiotkitの進化が早過ぎる?