AWS IoT Coreとlambdaを連携してAWS DynamoDBに環境データを登録する

# はじめに
> AWS IoT CoreとAWS Lambdaを連携してAWS DynamoDBに環境データを保存してみようと思います。


# 開発構成

- イメージは、こんな感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/1bed232c-edc8-6df3-b507-a262ced95f79.png)


# 検証環境

- RaspberryPi3B+
- 温湿度センサー(DHT22)
- AWS IoT Core
- AWS Lambda
- AWS DynamoDB

# 前提

- RaspberryPiから送られてくるデータをAWS IoT Coreで受信出来ていること

# DynamoDB作成

1) マネージメントコンソールにログインし**DynamoDBサービス**を開きます

[マネージメントコンソール](https://aws.amazon.com/jp/free/?trk=ps_a134p000003yhoPAAQ&trkCampaign=acq_paid_search_brand&sc_channel=ps&sc_campaign=acquisition_JP&sc_publisher=google&sc_category=core-main&sc_country=JP&sc_geo=JP&sc_outcome=devadopt&sc_detail=aws&sc_content=Brand_Core_aws_e&sc_matchtype=e&sc_segment=487544183164&sc_medium=ACQ-P|PS-GO|Brand|Desktop|SU|Core-Main|Core|JP|EN|Text|dx&ef_id=CjwKCAjwkvWKBhB4EiwA-GHjFnio1TmI7AZT18lHwqGIHaEZ7RWOQ4VtRW8b2aJ_-mSAaCl24k2-ZRoC7bYQAvD_BwE:G:s&s_kwcid=AL!4422!3!487544183164!e!!g!!aws&gclid=CjwKCAjwkvWKBhB4EiwA-GHjFnio1TmI7AZT18lHwqGIHaEZ7RWOQ4VtRW8b2aJ_-mSAaCl24k2-ZRoC7bYQAvD_BwE&all-free-tier.sort-by=item.additionalFields.SortRank&all-free-tier.sort-order=asc&awsf.Free%20Tier%20Types=*all&awsf.Free%20Tier%20Categories=*all)

2) 「**テーブルの作成**」をクリックします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/9217c262-81be-b6b0-19c1-d7796faf2df0.png)

3) テーブル作成に必要な項目を入力し「**テーブルの作成**」をクリックしてしばらくするとテーブルが作成されます

- テーブル名：**任意の名前**
- パーティションキー： **client_id**
- ソートキー・オプション：**sensorid**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/3c435792-c031-11c3-41aa-72cfba5596b2.png)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/b9adc752-ff33-093f-43ec-15477d6c311e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/2c001e31-9e0f-06d9-d1c3-0ae75b55def3.png)

# IAMロール作成

4) 「**IAM**」→　「**ロール**」→　「**ロールを作成**」をクリックします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/3557e57b-f983-2b85-74a4-82f68f7352da.png)

5) 「**AWSサービス**」→　「**Lambda**」→　「**次のステップ：アクセス権限**」をクリックします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/d76d3b3e-3b5d-66e8-75d9-203e83551628.png)


6) 「**Attachアクセス権限ポリシー**」の「**ポリシーフィルター**」から「**dynamo**」と検索して以下のキーワードを選択し、「**次のステップ：タグ**」をクリックします。

- **AmazonDynamoDBFullAccess**
- **AWSLambdaDynamoDBExecutionRole**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/06f91a4b-ba50-af0d-23a1-0890cae7004b.png)

7) 特に設定はしないので、「**次のステップ：確認**」をクリックします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/5e2bf502-7ac6-27a4-8869-f4ad8ec79f06.png)

8) 任意のロール名を入力して「**ロールの作成**」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/164127f7-bc46-8194-d020-949cf5a097f8.png)


# lambda作成

4) lambdaサービスを開き「**関数**」→ 「**関数の作成**」をクリックします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/3f173119-db98-6279-99af-bcfb079ce5ee.png)


5) 関数の作成に必要な項目を入力して「**関数の作成**」をクリックします

- オプション：**一から作成**
- 関数名：**任意の名前**
- ランタイム：**今回は、**node.js14x**
- ロール：**先ほど作成したロールを選択**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/d1575586-d0ad-9720-c4ab-aff101de98bf.png)

8) ローカルで必要なモジュールをインストールしてzipで圧縮します

```command
$ mkdir aws-sdk
$ npm install aws-sdk
```

- 「**node_moduleとpackage-lock.jsonを選択**」→ 「**右クリック**」→ 「**7-Zip**」→ 「**aws-sdk.zipに圧縮**」をクリックします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/d39093e9-34c5-02ba-eb4f-e626c86e5af6.png)

9) lambdaに戻り「**レイヤー**」を選択し、「**レイヤーの作成**」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/8c3cb827-60e4-9c5d-cc43-5b2435255599.png)


10) レイヤー作成に必要な項目を入力して「**作成**」をクリックします

- 名前：**任意の名前**
- .zipファイルをアップロード：先ほどzipに圧縮したファイルをアップロード
- ランタイム：**node.js 14x**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/dfe60e60-072b-af7e-d7fb-d1682f6c1704.png)

11) 先ほど、作成した関数に戻り「レイヤーの追加」をクリックします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/2118cadd-296b-7f11-f357-9c85834d6d87.png)


12) レイヤー追加に必要な項目を選択して「**追加**」をクリックします

- レイヤーソース：**カスタムレイヤーを選択**
- カスタムレイヤー：**先ほど作成したレイヤーを選択**
- バージョン：**先ほど作成したレイヤーのバージョンを選択**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/ded5a8e3-66a9-b60a-edf4-90daa5a0ec26.png)

13) IoT Coreとlambdaを紐づけます

- 「**トリガーを追加**」をクリックします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/4604c63b-e336-66ba-0432-91261797b94b.png)

14) 「**AWS IoT**」を選択しトリガー追加に必要な項目を入力して「**追加**」をクリックします

- IoTタイプ：**カスタムIoTルールを選択**
- ルール：**新規ルールの作成を選択** 
- - ルール名：**任意の名前**
- ルールクエリステートメント：**SELECT * FROM 'iot/topic'**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/1f06a27c-060e-bf38-ccab-8679aed72374.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/04c7ddb0-f304-b3d4-8473-f4159648332f.png)



# プログラム開発

15) 以下のソースを関数のindex.jsに張り付けて編集します

- TableNameに作成したテーブル名を入力してください

```node.js
const AWS = require('aws-sdk');
const docClient = new AWS.DynamoDB.DocumentClient();

const createItem = async (event) => {

    const params = {
        TableName: '--- Your table name ---',
        Item: {
            client_id: event.client_id,
            sensorid: event.sensorid,
            timestamp: event.timestamp,
            temp: event.temp,
            humid: event.humid
        }
    }
    try {
        await docClient.put(params).promise();
        console.log(params.Item);
        return params.Item;
    } catch (err) {
        return err;
    }
}

exports.handler = async (event) => {
    try {
        const res = await createItem(event);
        return res;
    } catch (err) {
        return { error: err }
    }
};
```


# lambdaのテストを使ってテストしてみる

16) 「**テスト**」を選択します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/05b29d14-88b8-9104-17ef-f31ead5883ac.png)


17) 任意の名前を入力して以下のjsonをコピーしてペーストして「**変更を保存**」をクリックします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/d0f646c6-30a0-9737-7fd7-8fef35ef97a4.png)

```json
{
  "client_id": "testGateway",
  "sensorid": "001",
  "timestamp": "2021/10/07 16:52:00",
  "temp": 11,
  "humid": 22
}
```

18) 「**テスト**」をクリックするとlambda関数が起動され実行結果の「**詳細**」をクリックすると詳細が見れるようになっています

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/70081c18-9cb1-8737-c05f-ed747553fca4.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/b61eacf9-01cb-0d6f-78fb-2e63bdf7aa34.png)

19) dynamoDBを確認してもデータが保存されてる事が確認できます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/19c97ac9-b13d-5770-8ec0-8ca00fe99f7c.png)

# RaspberryPiを使ってテスト

20) 実際にraspberryPiからデータをIoT Coreに送ってみます。

- RaspberryPi側

```command
pi@raspberrypi:~/sensor_aws $ node main.js 
connect
published message for 1 time
published message for 2 time
published message for 3 time
published message for 4 time
published message for 5 time
```

21) lambdaが正常に動作してるか確認してみます

- 「**モニタリング**」→　「**ログ**」→ 「**Recent invocations**」一番上の最新ログをクリックします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/fc0d7521-8707-8a8b-51d3-fc6c60598144.png)

- lambdaが正常に動作している事がわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/fcbf95c8-6a54-99bc-9b04-04394c50e381.png)

22) DynamoDBを確認してみてもデータ保存されている事がわかります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/0740c0fb-dbc7-d2ff-2951-7279b0363b5b.png)