LoginSignup
38
36

More than 5 years have passed since last update.

Kinesisで収集したデータをLambdaからkintoneに入れてみる

Last updated at Posted at 2014-12-22

はじめに

前回の記事でArduinoに付けた温度センサからRaspberry Pi経由でAWSにあげていたのですが、やはり温度変化をグラフでみたいなと思い、今回は、温度データをKinesisにPutし、Lambdaでデータを取得してkintoneに入れてグラフィカルにみることにチャレンジしてみました。
kintoneを使った理由は、プログラミングせずにリッチなアプリが簡単に作れるのとUIがとてもわかり易く、グラフ集計なども簡単にできるためです。

全体構成

qiita1.png

今回は、温度データをKinesis, Lambdaを介してkintoneに入れる構成を作りました。
Raspberry Piから直接kintoneにAPIコールすることも可能ですが、KinesisとLambdaを介すことでETL処理、他のデータとのJoinなどができるようになると思います。今回は、一定間隔で一括取得したデータの平均をLambda側で集計してkintoneに入れるようにしています。

kintoneの設定

Kinetoneの30日間無料お試しを利用させて頂きました!(https://kintone.cybozu.com/jp/)
初めてKinetoneを触ったのですが、はじめてのkintoneガイドを最初にみるとよいと思います。
手順的には、スペースを作り、そこにTempというアプリを作りました。

qiita2.png

qiita3.png

フォームは日時と温度だけの単純なカラムにしました。

qiita4.png

また、データを入れ時にカラム名をわかりやすくするためフィード名をroomに修正しました。
qiita5.png

これだけで格納先はできました!
まずは、Curlを使ってkintone API経由でデータを入れてみます。
(Kinetone APIはこちら)
認証は、Basic認証と独自のユーザ認証の2つがあります。両方ともBase64.Encode("アカウント:パスワード")です。

curl

curl -X POST -H 'Host: {自分のホスト名}.cybozu.com' -H 'Authorization: Basic {Base64.Enode("アカウント:パスワード")}' -H 'X-Cybozu-Authorization: {Base64.Encode("アカウント:パスワード")}' -H 'Content-Type: application/json' https://{自分のホスト名}.cybozu.com/k/guest/{スペースID}/v1/record.json -d '{'app':アプリID,'record': {'room': {'value': '13'}}'

これでデータを入力できると思います!

Raspberry PIの実装

Cognitoでトークンを取得し、Kinesisに対してPutしてます。

postKinesis.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import sys,traceback
import serial
import datetime,time
import boto
from boto import kinesis

STREAM = ''
ACCOUNT_ID = ''
IDENTITY_POOL_ID = ''
ROLE_ARN = ''

class Auth:
    def doAuth(self):
        cognito = boto.connect_cognito_identity()
        cognito_id = cognito.get_id(ACCOUNT_ID, IDENTITY_POOL_ID)
        print str(cognito_id)
        token = cognito.get_open_id_token(cognito_id['IdentityId'])
        sts = boto.connect_sts()
        assumedRoleObject = sts.assume_role_with_web_identity(ROLE_ARN, "bototest", token['Token'])
        self.client = kinesis.connect_to_region(
            "us-east-1",
            aws_access_key_id=assumedRoleObject.credentials.access_key,
            aws_secret_access_key=assumedRoleObject.credentials.secret_key,
            security_token=assumedRoleObject.credentials.session_token)
    def getClient(self):
        return self.client


if __name__ == '__main__':
    auth = Auth()
    auth.doAuth()
    while True:
        try:
            s = serial.Serial('/dev/ttyACM0', 9600)
            line = s.readline()
            temp = line.strip()
            if temp != '':
                print temp
                d = datetime.datetime.today()
                partitionKey = d.strftime("%Y%m%d%H%M%S")
                client = auth.getClient()
                client.put_record(STREAM, temp , partitionKey, b64_encode=True)
                time.sleep(900)
        except KeyboardInterrupt:
            sys.exit()
        except:
            info = sys.exc_info()
            tbinfo = traceback.format_tb( info[2] )
            print "Error:", tbinfo
            auth = Auth()
            auth.doAuth()


Lambda Functionの実装

特に意味はないのですが、@Keisuke69さんのAWS LambdaのfunctionをPythonで書くを試したかったのでLambda FunctionはPythonコードを読みだして実行するだけです。いや、試したかっただけです。

index.js
exports.handler = function(event, context) {
    var exec = require('child_process').exec;
    var temp = 0;
    console.log(JSON.stringify(event, null, '  '));
    for(i = 0; i < event.Records.length; ++i) {
        encodedPayload = event.Records[i].kinesis.data;
        payload = new Buffer(encodedPayload, 'base64').toString('ascii');
        temp += parseFloat(payload);
    }
    temp = temp/event.Records.length;
    var cmd = "curl -s https://s3.amazonaws.com/{バケット}/postkintone.py > /tmp/test.py;chmod 755 /tmp/test.py;/tmp/test.py " + temp;
    var child = exec(cmd, function(error, stdout, stderr) {
        if (!error) {
            context.done();
        } else {
            console.log("error code: " + error.code + ", err: " + error);
            context.done(error,'lambda');
        }
    });
};

Kinesisで取得したデータ群の平均をPython側のプログラムに標準入力で渡して、Python側でKinetonにPOSTするようにしてみました。

postkintone.py

#! /usr/bin/python

import urllib2,json,sys
AUTH = ''
X_CY_AUTH = ''
ENDPOINT = ''

def main(temp):
        try:
                postdata = {'app':00,'record': {'room': {'value': temp}}}
                print postdata
                req = urllib2.Request(ENDPOINT)
                req.add_header('Content-Type','application/json')
                req.add_header('Host', 'toshiake.cybozu.com')
                req.add_header('Authorization',AUTH)
                req.add_header('X-Cybozu-Authorization',X_CY_AUTH)
                data = json.dumps(postdata)
                response = urllib2.urlopen(req,data)
                print response
        except:
                print "Unexpected error:", sys.exc_info()[0]

if __name__ == '__main__':
        argvs = sys.argv
        argc = len(argvs)
        if (argc != 2):
                print 'Usage: # python %s temp' % argvs[0]
                sys.exit()
        temp = argvs[1]
        main(temp)

Lambda FunctionをKinesis Applicationとして利用する場合は、Invocation Roleを作成し、Event Sourceの追加が必要になります。
Invocation Roleは、以下のような感じです。

InvocationRole

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "lambda:InvokeFunction"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "kinesis:*"
      ],
      "Resource": "*"
    }
  ]
}

Event Sourceの登録は、CLIで実行します。

add-event-source

$ aws lambda add-event-source \
   --region us-east-1 \
   --function-name {Function名}  \
   --role arn:aws:iam::{アカウントID}:{上で作ったロール名} \
   --event-source {Kinesis StreamのARN} \
   --batch-size 100 \
   --parameters '{"InitialPositionInStream": "LATEST"}'

パラメータに"InitialPositionInStream": "LATEST"を指定することで初回起動時に最新データから取得されるようになります。

kintoneのグラフビューで確認

こんな感じでみえました。異常に自分の部屋がサムイことがわかりました。。

qiita6.png

最後に

kintoneはプログラミングいらずにデータの格納やグラフィカルなViewの作成など簡単にできました。
今回は、温度センサーの情報を使ったのですが、AWSとkintoneの組み合わせですと、例えば、営業所からの報告書がS3に上がってきて、S3 Event NortificationトリガーでLambda Functionが呼ばれて、データの精査、マスタデータとの連結などをしてkintoneにいれるという使い道やS3,CloudFront,ELBなどのログを可視化するのにkintoneを利用することもできそうです。使い道は無限に広がりそうですね!

qiita7.png

免責

こちらは個人の意見で、所属する企業や団体は関係ありません。

38
36
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
38
36