AWS IoT, AWS IoT Device Shadow

AWS

This article describes AWS IoT and AWS IoT Device Shadow, which allows you to easily integrate edge devices such as the Jetson Nano with the cloud. By connecting edge devices to the cloud, for example, it is possible to dynamically update YOLOv5 models from the cloud to edge devices.

    以下の操作はAWSアカウントが必要です。

    AWS CLIのインストールとセットアップも必要です。

    The following operations require an AWS account.

    AWS CLI installation and setup is also required

    AWS IoT

    AWS IoT makes it easy to connect edge devices to the cloud using a communication protocol called MQTT.

    To prepare for AWS IoT, create a thing, a certificate, and a policy, attach the certificate to the thing, and attach the policy to the certificate.

    Create things

    Create a thing below. In the following, we create a thing named test-thing.

    aws iot create-thing --thing-name test-thingCode language: Bash (bash)

    Create certificate and attach to thing

    Create the certificate below and attach it to the test-thing created above.

    $ aws iot create-keys-and-certificate --set-as-active --certificate-pem-outfile certificate.pem --public-key-outfile public.key --private-key-outfile private.key
    {
        "certificateArn": "arn:aws:iot:us-east-1:xxxxxxxxxxxx:cert/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        ...
    $ aws iot attach-thing-principal --principal arn:aws:iot:us-east-1:xxxxxxxxxxxx:cert/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --thing-name test-thingCode language: Bash (bash)

    The ARN (Amazon Resource Name) specified in aws iot attach-thing-principal--principal is the certificateArn returned by aws iot create-keys-and-certificate.

    The certificate is created in certificate.pem specified by --certificate-pem-outfile and the private key is created in private.key specified by --private-key-outfile.

    Create policy and attach to certificate

    Policies are mechanisms for restricting communication of a thing (or more precisely, a certificate attached to a thing), specifically when using MQTT to publish and subscribe to data.

    cat << EOS > thing-policy.json
    {
       "Version": "2012-10-17",
       "Statement": [{
             "Effect": "Allow",
             "Action": "iot:Connect",
             "Resource": "arn:aws:iot:us-east-1:xxxxxxxxxxxx:client/${iot:Connection.Thing.ThingName}"
          },
          {
             "Effect": "Allow",
             "Action": "iot:Publish",
             "Resource": [
                "arn:aws:iot:us-east-1:xxxxxxxxxxxx:topic/$aws/things/${iot:Connection.Thing.ThingName}/shadow/update",
                "arn:aws:iot:us-east-1:xxxxxxxxxxxx:topic/$aws/things/${iot:Connection.Thing.ThingName}/shadow/delete",
                "arn:aws:iot:us-east-1:xxxxxxxxxxxx:topic/$aws/things/${iot:Connection.Thing.ThingName}/shadow/get"
    
             ]
          },
          {
             "Effect": "Allow",
             "Action": "iot:Receive",
             "Resource": [
                "arn:aws:iot:us-east-1:xxxxxxxxxxxx:topic/$aws/things/${iot:Connection.Thing.ThingName}/shadow/get/*",
                "arn:aws:iot:us-east-1:xxxxxxxxxxxx:topic/$aws/things/${iot:Connection.Thing.ThingName}/shadow/update/*",
                "arn:aws:iot:us-east-1:xxxxxxxxxxxx:topic/$aws/things/${iot:Connection.Thing.ThingName}/shadow/delete/*"
             ]
          },
          {
             "Effect": "Allow",
             "Action": "iot:Subscribe",
             "Resource": [
                "arn:aws:iot:us-east-1:xxxxxxxxxxxx:topicfilter/$aws/things/${iot:Connection.Thing.ThingName}/shadow/get/*",
                "arn:aws:iot:us-east-1:xxxxxxxxxxxx:topicfilter/$aws/things/${iot:Connection.Thing.ThingName}/shadow/update/*",
                "arn:aws:iot:us-east-1:xxxxxxxxxxxx:topicfilter/$aws/things/${iot:Connection.Thing.ThingName}/shadow/delete/*"
    
             ]
          },
          {
             "Effect": "Allow",
             "Action": [
                "iot:GetThingShadow",
                "iot:UpdateThingShadow",
                "iot:DeleteThingShadow"
             ],
             "Resource": "arn:aws:iot:us-east-1:xxxxxxxxxxxx:thing/${iot:Connection.Thing.ThingName}"
          }
       ]
    }
    EOS
    aws iot create-policy --policy-name thing-policy --policy-document file://thing-policy.json
    aws iot attach-policy --policy-name thing-policy --target arn:aws:iot:us-east-1:xxxxxxxxxxxx:cert/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxCode language: Bash (bash)

    The ${iot:Connection.Thing.ThingName} is a policy variable. When this policy variable is used, it is evaluated as the name of the thing.

    Replace arn:aws:iot:us-east-1:xxxxxxxxxxxxxxxxx with your account ID. The account ID can be obtained at

    aws sts get-caller-identity|jq -r .AccountCode language: Bash (bash)

    Also, the arn:aws:iot:us-east-1:xxxxxxxxx… specified by aws iot attach-policy --policy-name thing-policy --target specifies the certificateArn used in aws iot attach-thing-principal--principal.

    As a precaution, if you use the following policy, the thing attached to this policy will be able to publish and subscribe to all resources (MQTT topics). This is generally dangerous and should not be configured, since it allows a thing to publish (send) a topic to another thing or subscribe (receive) a topic from another thing.

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": [
             "iot:Publish",
             "iot:Subscribe",
             "iot:Receive"
          ],
          "Resource": ["*"],
        },
      ]
    }Code language: JSON / JSON with Comments (json)

    AWS IoT Device Shadow

    Verify the operation of AWS IoT Device Shadow using AWS IoT Device SDK v2 for Python.

    $ python3 -m pip install awsiotsdk
    $ git clone https://github.com/aws/aws-iot-device-sdk-python-v2.git
    $ curl -o AmazonRootCA1.pem https://www.amazontrust.com/repository/AmazonRootCA1.pemCode language: Bash (bash)

    Run aws-iot-device-sdk-python-v2/samples/shadow.py. The endpoint specified in aws-iot-device-sdk-python-v2/samples/shadow.py is obtained by using aws iot describe-endpoint --endpoint-type iot:Data-ATS.

    $ aws iot describe-endpoint --endpoint-type iot:Data-ATS
    {
        "endpointAddress": "xxxxxxxxxxxxxx-ats.iot.us-east-1.amazonaws.com"
    }
    $ python3 aws-iot-device-sdk-python-v2/samples/shadow.py --endpoint xxxxxxxxxxxxxx-ats.iot.us-east-1.amazonaws.com --key private.key --cert certificate.pem --client_id test-thing --ca_file AmazonRootCA1.pem --thing_name test-thing
    Connecting to xxxxxxxxxxxxxx-ats.iot.us-east-1.amazonaws.com with client ID 'test-thing-jetson'...
    Connected!
    Subscribing to Update responses...
    Subscribing to Get responses...
    Subscribing to Delta events...
    Requesting current shadow state...
    Launching thread to read user input...
    Thing has no shadow document. Creating with defaults...
    Changed local shadow value to 'off'.
    Updating reported shadow value to 'off'...
    Update request published.
    Finished updating reported shadow value to 'off'.
    Enter desired value: 
    Code language: Bash (bash)

    shadow.py is a sample to realize the following functions.

    1. Indicate lighting color changes with an operating terminal (web app, smartphone app, etc.)
    2. The lighting device receiving the change request changes the color of the light according to the specified color

    The AWS IoT Device Shadow used in shadow.py has the following JSON format data shared between cloud and edge devices

    {
      "state": {
        "desired": {
          "color": "red",
        },
        "reported": {
          "color": "blue"
        },
        "delta": {
          "color": "red",
        }
      },
      "version": 1,
      "timestamp": 1669898853
    }Code language: JSON / JSON with Comments (json)

    When implementing the sample shadow.py as an actual product, updating the lighting color is done as follows

    • The operating terminal is
      1. Set the color of the lighting to be updated in state.desired
    • Lighting device is
      1. Receive the difference between state.required and state.reported
      2. Report the color of the changed lighting in state.reported
        • The sample does not have code to change the color of the lighting
      3. Report the color of the changed lighting in state.reported

    Important points to consider in the IoT Device Shadow are as follows

    • On the operating terminal side, change only state.required.
    • Lighting devices change only state.reported.
    • If there is a difference between state.required and state.reported, the delta information is automatically created in state.delta.
      • If the delta information is being subscribed, then the callback function specified when setting up the subscribe is called.
    • version is used to discard old requests. If state.desired is updated multiple times and the callback to subscribe to state.delta is called multiple times, the callbacks to state.delta will not be called in the same order as state.desired is updated. Therefore, if a version older than the subscribed version arrives, it is discarded.
      In the figure below, the lighting device saves the latest version and simply discards any later “version”: 1 message that arrives with a lower value than the latest version.

    Connecting edge devices to the cloud is explained in another article.

    That’s all.

    Reference

    AWS IoT Device Shadow サービス - AWS IoT Core
    のシャドウ AWS IoT、状態情報の保存と取得に使用されるJSONドキュメント、およびこれらのドキュメントが保存されている Device Shadow サービスについて説明します。
    GitHub - aws/aws-iot-device-sdk-python-v2: Next generation AWS IoT Client SDK for Python using the AWS Common Runtime
    Next generation AWS IoT Client SDK for Python using the AWS Common Runtime - aws/aws-iot-device-sdk-python-v2
    [AWS IoT] ポリシー変数で複数のモノをセキュアに管理してみた | DevelopersIO