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-thing
Code 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-thing
Code 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/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Code 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 .Account
Code 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.pem
Code 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.
- Indicate lighting color changes with an operating terminal (web app, smartphone app, etc.)
- 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
- Set the color of the lighting to be updated in
state.desired
- Set the color of the lighting to be updated in
- Lighting device is
- Receive the difference between
state.required
andstate.reported
- Report the color of the changed lighting in
state.reported
- The sample does not have code to change the color of the lighting
- Report the color of the changed lighting in
state.reported
- Receive the difference between
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
andstate.reported
, the delta information is automatically created instate.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.