This post is Private. Only a writer or those who know its URL can access this post.

FlashAirに書き込まれたcsvファイルをAmazon S3に転送し、さらにデータをDynamoDBに書き込む

IoT.kyoto IoTスターターパック

IoT.kyotoではFlashAirを使用したスターターパックをご用意しております。FlashAirにファイルとしてデータを書き込むと、そのファイルはLTEルーターを経由してAmazon S3に保存され、自由なデータの取り出しが可能になります。
スクリーンショット 2018-11-26 11.04.47.png

概要

スクリーンショット 2018-11-26 11.10.09.png

このチュートリアル記事では、上記スターターパックのアーキテクチャをもとに、FlashAirにcsvファイルを書き込むとS3にcsvファイルが転送され、さらにNoSQL DBであるDynamoDBに書き込まれるアーキテクチャの構築手順を説明します。

事前準備

  • パソコン
    • OS: macOSまたはWindows(macOSだとデータの送信に失敗する場合があります。その場合はWindowsでお試しください)
    • ブラウザ: Google Chrome
    • SDカードを接続できること(なければUSBのSD CARD READER等が必要)
    • LTEルーターに接続可能であること
  • LTEルーター
    • SORACOM Air SIM が接続可能なこと
    • Wi-Fiで接続可能なこと
    • 予めSSIDとパスワードをメモしておくこと
  • 有効な AWS アカウント
    • AWSコンソールのIAMから自分のアカウントを選択し、AdministratorAccessの権限が付与されていることを確認してください
  • 有効な SORACOM アカウント
  • SORACOM アカウントに登録済みの SORACOM Air SIM (LTEルーターに接続できるサイズであること)

料金

今回使用するサービスの料金体制については、それぞれのリンク先をご参照ください。

SORACOM Air SIM
https://soracom.jp/services/air/cellular/price/

SORACOM Beam
https://soracom.jp/services/beam/price/

Amazon API Gateway
https://aws.amazon.com/jp/api-gateway/pricing/

AWS Lambda
https://aws.amazon.com/jp/lambda/pricing/

Amazon S3
https://aws.amazon.com/jp/s3/pricing/

AWS DynamoDB
https://aws.amazon.com/jp/dynamodb/pricing/

AWS Cloud9
https://aws.amazon.com/jp/cloud9/pricing/

[1]FlashAirの設定

まずはFlashAirの設定を行います。
FlashAirをLTEルーターに紐付け、特定のフォルダのファイルをAWSに送信できるようにLuaファイルを作成します。

図で表すと、こちらの部分です。
FlashAirのみ.png

初期設定

FlashAir設定ソフトウェア

FlashAirの初期設定を行うため、FlashAir設定ソフトウェアをインストールして、ネットワークの設定を行います。
1. 下記のURLから、パソコンのOSに合わせて、ダウンロードします
https://jp.toshiba-memory.com/support/download/flashair/software/we/software02.htm
2. FlashAirのSDカードをパソコンと接続した状態で設定ソフトウェアを開くと、下図のような画面が表示されます
スクリーンショット 2018-11-09 13.52.25.png
3. 表示されたら、一番上の「ネットワークの設定」をクリック
ネットワーク設定が表示されるので、LTEルーターのSSIDとパスワードを記載し、リダイレクト機能をONにして、適用ボタンをクリックします。
スクリーンショット 2018-11-09 13.52.50.png

Configの設定

FlashAirには、ネットワーク設定やバージョン情報などを保持するファイルが予め用意されています。
Configファイルは、SDカード内部のSD_WLANフォルダに保存されています(SD_WLANフォルダは隠しフォルダになっています)。
上記のネットワーク設定を行った後、下記のような内容になっています(FlashAirによって設定値は異なります)。

/SD_WLAN/config.CONFIG
[Vendor]

CIPATH=/DCIM/100__TSB/FA000001.JPG
VERSION=F15DBW3BW4.00.03
CID=<CIDが表示されます>
PRODUCT=FlashAir
VENDOR=TOSHIBA
APPSSID=<SSID名>
APPNETWORKKEY=<SSIDのパスワード>
APPMODE=4
APPAUTOTIME=300000
DNSMODE=1
LOCK=1

設定値の詳細については、下記のURLから確認できます。
https://www.flashair-developers.com/ja/documents/api/config/

/SD_WLAN/config.CONFIG を以下の通り加筆、修正します。

※ <>には、<>を抜いたユニークな値が入ります。ご自分の環境に合わせて入力してください
※ 下記の例に記述されているコメントは、実際には記入しないでください

  1. APPMODEの値を、5に変更
  2. STA_RETRY_CT=5を追記
  3. LUA_SD_EVENT=/lua/sendData.luaを追記

全て記載すると、下記のようなファイルになります。

/SD_WLAN/config.CONFIG
[Vendor]

CIPATH=/DCIM/100__TSB/FA000001.JPG
VERSION=F15DBW3BW4.00.03
CID=<CIDが表示されます>
PRODUCT=FlashAir
VENDOR=TOSHIBA
APPSSID=<SSID名>
APPNETWORKKEY=<SSIDのパスワード>
APPMODE=5 //変更
APPAUTOTIME=300000
DNSMODE=1
LOCK=1
LUA_SD_EVENT=/lua/sendData.lua //追記
STA_RETRY_CT=5 //追記

FlashAir設定ソフトウェアとCONFIG設定後

設定を反映させるために、FlashAirを再起動する必要があります。
一度FlashAirのマウントを解除し、FlashAirをパソコンから取り外します。
その後、FlashAirを再度パソコンに接続します。

Luaファイル

Luaファイルの作成

Luaファイルとは、FlashAirで使用することができる汎用スクリプト言語で作成されたもので、
データの転送やファイル操作などを行うことができます。
FlashAirが起動された時やファイルの更新があった場合に、
CONFIGファイルのLUA_SD_EVENTに設定されたファイルのスクリプトが起動されます。

今回はFlashAir直下にLuaフォルダを作成し、そこにsendData.luaという名前で保存します(/lua/sendData.lua)。
Luaファイルにも、SSIDの設定を記載します。

  1. 以下のソースコードを環境に合わせて変更し、貼り付けてください
sendData.lua
local TARGET_PATH = "/Send" -- データ送信するフォルダ
local GW_SSID = <SSID> -- SSIDを記載する
local DB_CONNECTION = <SSIDのパスワード> -- SSIDのパスワードを記載する

-- 更新されたファイルを探す
function find_latest_path()
  r, fl, t = fa.search("file", TARGET_PATH, -1)
  if r == 1 then
    return string.match(fl, '(.-),')
  end
end

-- 保存されたファイルをSORACOM経由でAWSに送信する
function request_api(path)
  endpoint = "http://beam.soracom.io:18080/dev/puts3"
  boundary = "--61141483716826"
  contenttype = "multipart/form-data; boundary=" .. boundary
  mes = "<!--WLANSDFILE-->\r\n"
  blen = lfs.attributes(path, "size")
  b, c, h = fa.request{
    url = endpoint,
    method = "POST",
    headers = {
      ["Content-Length"] = tostring(blen),
      ["Content-Type"] = contenttype
    },
    file = path,
    body = mes
  }
end

-- LTEルーターと再接続する
function connect()
  fa.Disconnect()
  sleep(5000)
  fa.Connect(GW_SSID, DB_CONNECTION)
  sleep(5000)
end

-- SDカード更新時に起動して処理が実施される
local latest = find_latest_path()
connect()
request_api(latest)

以上でFlashAirの設定は完了です。

[2]AWSの設定

FlashAir側の設定が終わりましたので、次はクラウド側の設定を行います。
APIGatewayで受け口を作成し、Lambdaで処理を行い、S3やDynamoDBに保存します。

図で表すと、こちらの部分です。
スクリーンショット 2018-11-26 11.10.36.png

AWS Cloud9を使用してServerless Frameworkを実行する

Serverless Frameworkとは

Lambda、API Gateway、DynamoDBなどのAWSサービスを作成、管理、デプロイできるツールです。
本来であればAWSのサービスごとにコンソールやコマンドから一つ一つ作る必要がありますが、
Serverless Frameworkを使用すると、複数のサービスを一括で作成・削除できます。

AWS Cloud9とは

AWS Cloud9とは、ブラウザから使えるクラウド型のIDEです。
Serverless Frameworkをdeployするにあたり、OS等の開発環境に依存した準備をするのは手間がかかります。
そこで、今回はAWS Cloud9を使うことで、どのOSでも同じIDEを用意し、Serverless Frameworkを実行します。

AWS Cloud9の作成

  1. AWSコンソールを開き、AWS Cloud9を選択
  2. 2018年11月現在、東京リージョンにサービスはないので、アジアパシフィック(シンガポール)で作成
  3. Create environmentから、environmentを作成
  4. 名前は任意に入力。Environment settingsは初期設定のままで問題ありません

ファイルの設置

AWS Cloud9のenvironmentの作成が完了すると、コンソールが表示されます。
AWS Cloud9コンソールの上部メニューからFile→New Fileで新規ファイルが作成されるので、下記の3ファイルを作成し、保存します。
S3のバケット名は、各自で分かりやすいものを代入してください。
また、S3バケットは全てのファイルで同じ名称にしてください。

handler.js
"use strict";

const AWS = require("aws-sdk");
const s3 = new AWS.S3()
const DYNAMO_DB = new AWS.DynamoDB.DocumentClient({
  region: "ap-northeast-1"
});
const CSV = require("comma-separated-values");
const TABLE_NAME = "FlashAirData";

// S3に保存されたCSVファイルを元に、DynamoDBにデータを挿入する
exports.sendData = (event, context) => {
  const bucket = event.Records[0].s3.bucket.name;
  const key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' '));
  const params = {
    Bucket: bucket,
    Key: key,
  };
  s3.getObject(params, (err, data) => {
    if (err) {
      console.log(err);
      return
    } else {
      const csv = new CSV(data.Body.toString("utf-8"), {header: true}).parse();
      console.log(csv);
      for(let num = 0 ; num < csv.length ; num++) {
        let dynamoDBParam = {
          TableName: TABLE_NAME,
          Item: csv[num]
        };
        DYNAMO_DB.put(dynamoDBParam).promise().then(data => {
          console.log(data);
        }).catch(err => {
          console.log(err);
          throw new Error(err);
      });
      }
    }
  });
};

// FlashAirから送信されたCSVファイルをS3に保存する
exports.putS3 = (event, context) => {
  console.log(event);
  s3.putObject({
    Body: event.body,
    Bucket: <バケット名>, // serverless.ymlと同じバケット名にする
    ContentType: 'text/csv',
    Key: 'data.csv'
  }).promise()
    .then((result) => {
      console.log("result!");
      return {
        statusCode: 200,
        body: JSON.stringify({
        message: "Success!! insert data to DynamoDB",
        input: event
    })
  };
    })
    .catch((err) => {
      return {
        statusCode: 400,
        body: JSON.stringify({
          message: err,
          input: event
      })
    };
    })
}
package.json
{
  "dependencies": {
    "comma-separated-values": "^3.6.4"
  }
}
serverless.yml
service: flashair-handson

# handler.jsと同じバケット名にする
custom:
  defaultStage: dev
  defaultProfile: default
  defaultRegion: ap-northeast-1
  defaultTableName: FlashAirData
  defaultBucket: <バケット名>

# サービスの設定やIAMの作成を行う
provider:
  name: aws
  runtime: nodejs8.10
  stage: ${opt:stage, self:custom.defaultStage}
  region: ${opt:region, self:custom.defaultRegion}
  apiKeys:
    - flashAirKey
  iamRoleStatements:
    -  Effect: "Allow"
       Action:
        - "dynamodb:PutItem"
        - "s3:getObject"
        - "s3:putObject"
       Resource: 
        - "arn:aws:dynamodb:${self:provider.region}:*:table/${self:custom.defaultTableName}"
        - "arn:aws:s3:::${self:custom.defaultBucket}/*"

# LambdaやS3、API Gatewayを作成する
functions:
  putS3:
    handler: handler.putS3
    events:
      - http:
          path: /puts3
          method: post
          private: true
  sendData:
    handler: handler.sendData
    events:
      - s3: ${self:custom.defaultBucket}

# DynamoDBを作成する
resources:
  Resources:
    usersTable:
      Type: AWS::DynamoDB::Table
      Properties:
        TableName: ${self:custom.defaultTableName}
        AttributeDefinitions:
          - AttributeName: deviceID
            AttributeType: S
          - AttributeName: record_time
            AttributeType: S
        KeySchema:
          - AttributeName: deviceID
            KeyType: HASH
          - AttributeName: record_time
            KeyType: RANGE
        ProvisionedThroughput:
          ReadCapacityUnits: 1
          WriteCapacityUnits: 1

コンソールからslsの実行

Lambda起動に必要なライブラリの準備や、Serverless Frameworkコマンドの準備を行います。
AWS Cloud9の右下にあるコンソールから、下記のコマンドを入力します。

AWSCloud9コンソール
$ sudo yum -y update
$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash
$ . ~/.bashrc
$ nvm install --lts=carbon
$ nvm use lts/carbon
$ node -v
$ npm update -g npm
$ npm install -g serverless
$ npm install
$ sls deploy

APIの確認

この後に行うSORACOMの設定のため、APIのエンドポイントとAPIキーを確認します。
sls deploy実施後、コンソールに以下のようにapi keysとendpointsが出力されますので、
メモしておきます。

AWSCloud9コンソール
api keys:
  flashAirKey: JQDRwWYCQ1V4Ly9DsLjw5Tn3MlazodH4UG9N5kEa
endpoints:
  POST - https://hoge.execute-api.ap-northeast-1.amazonaws.com/dev/puts3

上記内容はAWSコンソールからも確認できます。
東京リージョンにて、API Gatewayサービスを選択し、Serverless Frameworkで作成されたAPIを選択します。

エンドポイント:

  • dev-flashair-handsonを選択し、ステージ→devとクリックして表示されるURL

(例)https://hoge.execute-api.ap-northeast-1.amazonaws.com/dev

APIキー:

  • APIキーを選択し、flashAirKey→APIキーの表示をクリックした際に表示される文字列

(例)JQDRwWYCQ1V4Ly9DsLjw5Tn3MlazodH4UG9N5kEa

[3]SORACOMの設定

FlashAirとAWSの設定が完了したら、その間を通信するSORACOMの設定を行います。
今回はSORACOM Air SIM を使用し、SORACOM Beamというサービスを使い、AWSへの通信を行います。

図で表すと、こちらの部分です。
ソラコムのみ.png

グループの作成

SORACOMコンソールを開き、メニューからSIMグループをクリックする。
SIMグループ画面で追加ボタンを押す。
スクリーンショット 2018-11-09 16.58.44.png
ダイアログが表示されるので、グループ名にFlashAir_demoと入力し、グループ作成をクリックします。
スクリーンショット 2018-11-09 17.01.01.png
作成したSIMグループを選択し、基本設定から、SORACOM Beam設定を選択し、+ボタンをクリックします。
エントリポイントの選択が出てくるので、Webサイトエンドポイントをクリックします。
スクリーンショット 2018-11-09 17.08.59.png
SORACOM Beamの設定画面が表示されるので、以下の内容を入力して、保存します。

  • 設定名に任意の文字列を設定する
  • ホスト名に、API GatewayでメモしたURLの頭のhttps://と末尾の/devを削除して入力する
  • IMSIヘッダをONにする
  • IMEIヘッダをONにする
  • カスタムヘッダのヘッダ名にX-API-KEY、値にAPI GatewayでメモしたAPIキーを入力する

webサイト転送設定.png

ヘッダ操作.png

SIMグループができれば、SORACOMコンソールのSIMカード一覧から、LTEルーターに接続しているSIMを選択し、所属グループの変更をクリックします。
ダイアログが表示されるので、作成した所属グループを紐付けます。
これでSORACOMの設定は完了です。
スクリーンショット 2018-11-09 17.25.04.png
simの所属グループ変更.png

[4]動作チェック

準備ができたら、実際に動かしてみましょう。

CSVファイルの設置

FlashAirにSendフォルダを作成し、下記のファイルをUTF-8の文字コードで保存します。
動作に問題がなければ、CSVがアーキテクチャ図の通りに流れ、DynamoDBに保存されます。

sample.csv
record_time,deviceID,temp
2018-11-07T00:00:00.000+0900,Device1,14
2018-11-07T01:00:00.000+0900,Device1,14
2018-11-07T02:00:00.000+0900,Device1,13
2018-11-07T03:00:00.000+0900,Device1,12
2018-11-07T04:00:00.000+0900,Device1,13
2018-11-07T05:00:00.000+0900,Device1,14
2018-11-07T06:00:00.000+0900,Device1,14
2018-11-07T07:00:00.000+0900,Device1,15
2018-11-07T08:00:00.000+0900,Device1,16
2018-11-07T09:00:00.000+0900,Device1,17
2018-11-07T10:00:00.000+0900,Device1,19
2018-11-07T11:00:00.000+0900,Device1,20
2018-11-07T12:00:00.000+0900,Device1,22
2018-11-07T13:00:00.000+0900,Device1,23
2018-11-07T14:00:00.000+0900,Device1,22
2018-11-07T15:00:00.000+0900,Device1,22
2018-11-07T16:00:00.000+0900,Device1,20
2018-11-07T17:00:00.000+0900,Device1,18
2018-11-07T18:00:00.000+0900,Device1,17
2018-11-07T19:00:00.000+0900,Device1,17
2018-11-07T20:00:00.000+0900,Device1,16
2018-11-07T21:00:00.000+0900,Device1,16
2018-11-07T22:00:00.000+0900,Device1,15
2018-11-07T23:00:00.000+0900,Device1,14
2018-11-07T24:00:00.000+0900,Device1,14

FlashAirをmacOSに接続して動作確認する場合、うまく動作しないことがあります。
その場合は、FlashAirをWindowsに接続して動作確認をお願いします。

データの確認(AWSコンソールから確認)

AWSコンソールからDynamoDBを選択し、FlashAirDataテーブルを確認します。
問題なく処理された場合、CSVの内容がDynamoDBに保存されています。

データの確認(IoT.kyoto VISで確認)

DynamoDBに保存されたデータは、IoT.kyoto VISで可視化することもできます。

IoT.kyoto VISは、IoT.kyotoが提供する無料でご利用いただけるIoTデータ可視化アプリです。
操作方法についてはこちらからご確認ください。

こちらのアプリはリアルタイムでのグラフ描画が可能です。どのような動きをするかは下記の動画をご覧ください。画像をクリックするとYouTubeのページに遷移します。

IMAGE ALT TEXT HERE

[5]各種アカウントの環境を削除

AWSやSORACOMは、上記の料金の項目に記載されている通り、課金が発生します。
そのため、今回ハンズオンで作成した環境が不要になった場合は、下記の手順で環境を削除してください。

AWS

  1. 予め作成したS3バケットの中身を全て削除します。
  2. AWS Cloud9のコンソールで、下記のコマンドを入力すると、AWSで作成したハンズオンの内容は全て削除されます。
  3. AWSのサービス一覧からAWS Cloud9を選択し、deleteボタンで作成したenvironmentsを削除します。
AWSCloud9コンソール
$ sls remove

sls removeする前に必ずS3バケットが空になっているかを確認してください
もしファイルが残っていると、削除がエラーとなってしまいます。

SORACOM

SORACOMコンソールから今回使用したSIMを選択し、今後のご利用予定に合わせてSIMの状態を変更することができます。
今回使用したSORACOM Air SIMを長期間(二ヶ月以上)利用しない場合は、利用中断に、
今後も利用する予定がある場合は、休止にしてください。

FlashAir

もし初期化する必要があるのであれば、FlashAir設定ソフトウェアから実施できます。
スクリーンショット 削除.png

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.