AWS CLIを用いたIoTcoreのthing管理と更新

# 本記事の概要
AWSIoTcoreにおいて、thingの作成や情報の更新をGUIではなくコマンドで実施する手順になります。

数台であればGUIのみでの作業で完結しますが、業務で利用する場合はそうもいきません。
いつか数十台のデバイスを管理するようになったときのためにコマンドで管理できるようになるための記事になります。

# AWS公式ドキュメント
本記事の執筆にあたり、以下のAWS公式ドキュメントから情報を取得しています。(英語のみ)
IoTcoreで使っているAPIの一覧が記載されています。
各APIのページ下部のSeeAlosoよりAWS Command Line Interfaceを選択して各コマンドの利用方法を確認しました。

https://docs.aws.amazon.com/ja_jp/iot/latest/apireference/Welcome.html

# 本記事で実施すること
以下をCloud9上で作成した端末から実施します。
・thingの作成
・グループの作成
・グループへの追加
・タイプの作成
・シャドウの更新

# 検証環境の作成
Could9にて、Linux環境を作成します。

1.Cloud9のサービスから"CreateEnviroment"をクリックする。

![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2337873/2d891802-7776-bce2-6160-581482fe2c85.jpeg)

2.環境名を入力して”Nextstep"をクリックする。

![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2337873/4e6ca804-1ef4-80c3-4a66-0f467f7f8dac.jpeg)

3.デフォルトのまま”Nextstep"をクリックする。

![3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2337873/8072c275-ec17-8c8b-5ef6-8f9322ab2e8d.jpeg)

4."CreateEnviroment"をクリックする。

![4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2337873/5c109e9b-43a4-c932-8f94-e88cbad2d623.jpeg)

4~5分で環境の作成が完了します。
以降の手順は作成した環境を用いて実施します。

# thingの作成

以下のコマンドを実行します。

```
aws iot create-thing  --thing-name test_thing1
```

以下のような結果が表示されればOKです。
(リージョンやthingIDは伏せた状態で記載しています。以降も同様にリージョンなどの環境によって異なる情報は*で置換しています。)

```
{
    "thingArn": "arn:aws:iot:*******:******:thing/test_thing1", 
    "thingName": "test_thing1", 
    "thingId": "******-******-******-******"
}
```

# グループの作成

以下のコマンドを実行します。

```
aws iot create-thing-group --thing-group-name test_group1
```
上記のコマンドは実行しても何も表示されません。
以下のコマンドで作成したグループが表示されていればOKです。

```
aws iot list-thing-groups
```

```
{
    "thingGroups": [
        {
            "groupName": "test_group1", 
            "groupArn": "arn:aws:iot:******:**********:thinggroup/test_group1"
        }
    ]
}
```

上記のコマンドは実行しても何も表示されません。
以下のコマンドで追加したグループが表示されていればOKです。

```
aws iot list-thing-groups-for-thing  --thing-name test_thing1
```

```
{
    "thingGroups": [
        {
            "groupName": "test_group1", 
            "groupArn": "arn:aws:iot:*******:**********:thinggroup/test_group1"
        }
    ]
}
```

# グループへの追加

コマンドで作成したthingをグループに追加します。

以下のコマンドを実行します。
```
aws iot add-thing-to-thing-group --thing-name test_thing1 --thing-group-name test_group1
```

# タイプの作成

以下のコマンドを実行します。

```
aws iot create-thing-type --thing-type-name test_type_1
```

以下のような結果が表示されればOKです。

```
{
    "thingTypeName": "test_type_1", 
    "thingTypeId": "*********-****-****-***********", 
    "thingTypeArn": "arn:aws:iot:*****:*******:thingtype/test_type_1"
}
```

# タイプへの追加
作成したタイプをモノに追加します。

```
aws iot update-thing --thing-name "test_thing1" --thing-type-name "test_type_1" 
```

# シャドウの変更

シャドウの更新にあたり、以下のjsonファイルを用意します。

```update.json
{"state":{"reported":{"power":"off"}},"metadata":{"reported":{"power":{"timestamp":1638316777}}},"version":1,"timestamp":1638316777}
```
上記のファイルを作業中のカレントディレクトリに配置して、以下のコマンドを実行します。

```
aws iot-data update-thing-shadow --thing-name test_thing1   --payload '{"state": {"reported" : {"power" : "off"}}}'   update.json   
```

更新されたシャドウの確認は以下のコマンドで実施します。

```
aws iot-data get-thing-shadow --thing-name test_thing1 output.json
```
カレントディレクトリにoutput.jsonが出力されていればOKです。


# thingの検索

今回は一例としてtypeを検索キーにして検索を行います。

```
aws iot search-index --query-string "thingTypeName:test_type_1"
```
search-indexコマンドで利用しているクエリ文"thingTypeName:test_type_1"はGUI上でも"高度な検索"から利用が可能です。

```
{
    "things": [
        {
            "thingTypeName": "test_type_1", 
            "thingGroupNames": [
                "test_group1"
            ], 
            "connectivity": {
                "connected": false
            }, 
            "thingName": "test_thing1", 
            "attributes": {
                "test": "0"
            }, 
            "shadow": "{\"reported\":{\"power\":\"off\"},\"metadata\":{\"reported\":{\"power\":{\"timestamp\":1638316777}}},\"version\":1}", 
            "thingId": "******-*****-****-*****-********"
        }
    ]
}
```

https://docs.aws.amazon.com/cli/latest/reference/iot/search-index.html


## (補足)検索とフリートインデックスの違い
本記事では、高度な検索(フリートインデックス)を利用したthingの検索を実施しました。
参考として通常の検索との違いについて以下にまとめました。

通常の検索でも以下は検索可能です。

``` 
モノの名前　
モノのタイプ
モノのグループ
請求グループ
検索可能な属性名
```

上記に加え、高度な検索(フリートインデックス)では以下も検索の対象となります。

```
シャドウの検索
AND検索(A且つB)
特殊文字のエスケープ (\と同様)
検索可能な属性名以外の属性
```

## (補足)IoTcoreの各設定値で使える文字種

以下では、IoTcoreで利用する各設定で利用できる文字種についてまとめています。
AWSCLIで実施すると使えない文字列を入れてしまってエラーになることが多々あり、その際に使用できない文字を利用していないか確認が必要になります。



| 　                   | 英数字(半角) | 英数字(全角) | - | : | _ | , | . | @ | / | # | スペース     | 日本語(カナ文字) | 備考(AWSのエラーメッセージを転記)                                                                                                  |
|----------------------|--------------|--------------|---|---|---|---|---|---|---|---|--------------|------------------|------------------------------------------------------------------------------------------------------------------------------------|
| thingname            | ○            | ×            | ○ | ○ | ○ | × | × | × | × | × | ×            | ×                | モノの名前に使用できるのは、英数字、ハイフン、コロン、アンダースコアのみです。                                                     |
| タイプ名             | ○            | ×            | ○ | ○ | ○ | × | × | × | × | × | ×            | ×                | モノのタイプの名前に使用できるのは、英数字、ハイフン、コロン、アンダースコアのみです                                               |
| 属性名               | ○            | ×            | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ×            | ×                | 属性キーには、英数字および _.,@/:#- のみを使用できます。                                                                           |
| 属性値               | ○            | ×            | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ×            | ×                | 属性値には、英数字および _.,@/:#- のみを使用できます。                                                                             |
| グループ名           | ○            | ×            | ○ | ○ | ○ | × | × | × | × | × | ×            | ×                | モノのグループの名前に使用できるのは、英数字、ハイフン、コロン、アンダースコアのみです。                                           |
| シャドウ名           | ○            | ×            | ○ | ○ | ○ | × | × | × | × | × | ×            | ×                | 文字、ハイフン、コロン、またはアンダースコアのみを含む一意の名前を入力してください。シャドウ名にスペースを含めることはできません。 |
| シャドウ値(json形式) | ○            | ○            | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○(全角/半角) | ○                | 　                                                                                                                                 |



# まとめ
今回の記事では、GUIを使わずにコマンドのみでAWSIotcoreの操作を行いました。
最終的にpythonなどで実装する場合でも、API単位での操作ができるとテストにも活かしやすくなると考えます。