今回の内容
前回からの続きで、3回目となります。(長くなってスミマセン・・・)
これまでの2回でプラットフォームへデータが送信できることを確認できましたので、今回と次回の2回に渡ってデバイスに取り付けたセンサーで取得したデータを、Amazon S3に保存するところまでやってみたいと思います。
トポロジ
アプリケーションサーバ側は下図のように、API Gateway
、Kinessis Firehose
(以下、Firehose)、S3
を使って構築します。
AWS側の準備
クラスメソッドさんが解りやすい情報を公開していましたので、その情報にある「AWSサービスプロキシ」方式に倣って設定してみます。
尚、クラスメソッドさんが情報を公開した時点では、東京リージョンでのFirehose利用はできませんでしたが、現在は利用できますので、AWS側は全て東京リージョンで構成することにしました。
Firehose
-
Delivery stream name
に任意のストリーム名を入力、Source
にDirect PUT or other sources
が選択されていることを確認し、ページ下部のNext
をクリック
-
Destination
にAmazon S3
を選択、S3 bucket
は任意のバケット(既存、またはCreate new
をクリックして新しいバケットを作成)を選択し、Next
をクリック
-
Buffer interval
を60
に変更し、IAM role
にあるCreate new, or Choose
ボタンをクリック
-
IAMロールページが閉じて元のページに戻るので、
IAM role
に上記で作成したロール名が表示されていることを確認し、Next
をクリック
以上の手順で、FirehoseがS3を操作するためのIAM Roleと、Firehoseストリーム、S3バケット(新規作成した場合)が作成されます。
またFirehoseストリームに対して、次のようなIAM Role(lorawan_delivery_role
)が作成されています。
信頼関係(Trust Relationships)
Firehose に対し、AssumeRoleすることを許可するポリシードキュメント
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "firehose.amazonaws.com"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "<アカウントID>"
}
}
}
]
}
アクセス権限(Permissions)
S3やAmazon Lambda、Logs、Kinesisに対して、操作を許可するインラインポリシー
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Action": [
"s3:AbortMultipartUpload",
"s3:GetBucketLocation",
"s3:GetObject",
"s3:ListBucket",
"s3:ListBucketMultipartUploads",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::<バケット名>",
"arn:aws:s3:::<バケット名>/*",
"arn:aws:s3:::%FIREHOSE_BUCKET_NAME%",
"arn:aws:s3:::%FIREHOSE_BUCKET_NAME%/*"
]
},
{
"Sid": "",
"Effect": "Allow",
"Action": [
"lambda:InvokeFunction",
"lambda:GetFunctionConfiguration"
],
"Resource": "arn:aws:lambda:ap-northeast-1:<アカウントID>:function:%FIREHOSE_DEFAULT_FUNCTION%:%FIREHOSE_DEFAULT_VERSION%"
},
{
"Sid": "",
"Effect": "Allow",
"Action": [
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:logs:ap-northeast-1:<アカウントID>:log-group:/aws/kinesisfirehose/lorawan:log-stream:*"
]
},
{
"Sid": "",
"Effect": "Allow",
"Action": [
"kinesis:DescribeStream",
"kinesis:GetShardIterator",
"kinesis:GetRecords"
],
"Resource": "arn:aws:kinesis:ap-northeast-1:<アカウントID>:stream/%FIREHOSE_STREAM_NAME%"
},
{
"Effect": "Allow",
"Action": [
"kms:Decrypt"
],
"Resource": [
"arn:aws:kms:region:accountid:key/%SSE_KEY_ARN%"
],
"Condition": {
"StringEquals": {
"kms:ViaService": "kinesis.%REGION_NAME%.amazonaws.com"
},
"StringLike": {
"kms:EncryptionContext:aws:kinesis:arn": "arn:aws:kinesis:%REGION_NAME%:<アカウントID>:stream/%FIREHOSE_STREAM_NAME%"
}
}
}
]
}
API Gateway向けIAMロール作成
API Gatewayのメソッド作成時に指定するIAMロールを、新たに作成します。
今回はfirehose_for_lorawan
という名前で作成しました。
信頼関係(Trust Relationships)
API GatewayがAssumeRoleすることを許可するポリシードキュメント
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "apigateway.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
アクセス権限(Permissions)
Firehoseにデータレコードを書き込むAPI(PutRecord
、PutRecordBatch
)を許可するインラインポリシー
- PutRecord
- 単一のデータレコードをストリームに書き込む
- PutRecordBatch
- 1回の呼出しで複数のデータレコードをストリームに書き込む
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt",
"Effect": "Allow",
"Action": [
"firehose:PutRecord",
"firehose:PutRecordBatch"
],
"Resource": [
"*"
]
}
]
}
API Gateway作成
-
AWSマネジメントコンソールから
API Gateway
を開き、APIの作成
をクリック、更に新しいAPI
を選択し、API名
に任意の名称を入力してAPIの作成
をクリック
-
リソース名に
api
を入力し、リソースの作成
をクリック(リソースパス
は、デフォルトでリソース名と同一文字が自動入力される)
-
項目 設定値 統合タイプ AWSサービス AWSリージョン Firehoseを作成したリージョン ※今回は東京リージョンなので ap-northeast-1
AWSサービス Firehose HTTPメソッド POST アクション PutRecord 実行ロール API Gateway向けIAMロール( firehose_for_lorawan
) -
本文マッピングテンプレート
をクリックして展開し、リクエストが定義されていない場合
を選択、更にマッピングテンプレートの追加
をクリックし、Content-Type
にapplication/json
と入力して確定アイコンをクリック
-
テンプレートの生成
欄が表示されるので、以下のコードを入力し、保存
ボタンをクリック{ "DeliveryStreamName": "lorawan_stream", "Record": { "Data": "$util.base64Encode($input.json('$.DevEUI_uplink'))" } }
[補足] マッピングテンプレートについて
公式ドキュメントを確認すると、Firehoseに単一のデータレコードを書き込むPutRecord
APIは、次のフォーマットになります。{ "DeliveryStreamName": "string", "Record": { "Data": blob } }
また、LoRaWANプラットフォーム(ThingPark)からAPI GatewayにPOST送信されるJSONオブジェクトは、次のようなフォーマットです。
{ "DevEUI_uplink": { "Time": "2017-11-02T08:48:47.595+01:00", "DevEUI": "47XXXXXXXXXXXXXX", "FPort": "8", "FCntUp": "35", "ADRbit": "1", "MType": "4", "FCntDn": "40", "payload_hex": "1b1083202fd06b8c5410350c16b5", "mic_hex": "41293adb", "Lrcid": "01234567", "LrrRSSI": "-116.000000", "LrrSNR": "-5.000000", "SpFact": "9", "SubBand": "G0", "Channel": "LC4", "DevLrrCnt": "1", "Lrrid": "65XXXXXX", "Late": "0", "LrrLAT": "33.588463", "LrrLON": "130.397446", "Lrrs": { "Lrr": [ { "Lrrid": "65XXXXXX", "Chain": "0", "LrrRSSI": "-116.000000", "LrrSNR": "-5.000000", "LrrESP": "-122.193314" } ] }, "CustomerID": "100008500", "CustomerData": { "alr": { "pro": "LORA/Generic", "ver": "1" } }, "ModelCfg": "0", "DevAddr": "01XXXXXX" } }
つまり、プラットフォームから送られてくるJSONオブジェクトの最上位メンバー
DevEUI_uplink
を、PutRecord APIのData
メンバーにマッピングするすることで、DevEUI_uplink
メンバー内のデータを、Firehoseストリームに書き込む仕組みとなっています。
更に、PutRecord APIのData
メンバーの値(上記APIフォーマットのblob
)は、Base64でエンコードする必要があるため、組み込み関数base64Encode()
を利用しています。
マッピングテンプレートのその他組み込み関数については、こちらに詳しく説明があります。
ここまでの手順で、AWS側の設定作業は完了です。
API Gatewayテスト
以下の手順で、API Gatewayのテストを行ってみます。
(背後でFirehoseストリームと連動していますので、実質AWS側の統合テストになります)
-
リクエスト本文
に以下のJSONコードを入力し、テスト
をクリック{ "DevEUI_uplink" : "Fukuoka City LoRaWAN" }
-
(レスポンスの)
ステータス
が200
になっているか確認
※ステータスが200
でない場合、表示されているログからエラー内容を確認できます。
-
S3バケットを確認し、データを確認
バケットに保存されたデータの中身"Fukuoka City LoRaWAN"
API Gatewayデプロイ
以下の手順で、作成したAPIをユーザーが呼び出せるようにデプロイします。
-
ステージエディタが表示されればデプロイ完了
尚、URLの呼び出し
に記載されたURLに続けてリソースパスを指定したアドレス(今回の場合、https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/api/vi
)が、プラットフォーム側で設定するアプリケーションサーバのアドレスになります。(=>前回のアプリケーションサーバの登録を参照)
次回
LoRaWANデバイスにセンサーを取り付け、送信してみます。