Integrate IoT Device with AWS IoT using Python — Part III: command-and-response using API

Workflow of command-rand-response with API

Introduction

Before You Start

git pull origin master
git checkout -b new_branch_name command_and_response_API
.
├── config.py
├── credentials
│ ├── [upload_credential_id]-certificate.pem.crt
│ ├── [upload_credential_id]-private.pem.key
│ ├── [upload_credential_id]-public.pem.key
│ ├── AmazonRootCA1.pem
│ ├── [remote_credential_id]-certificate.pem.crt
│ ├── [remote_credential_id]-private.pem.key
│ ├── [remote_credential_id]-public.pem.key
│ └── readme.md
├── main.py
├── Pipfile
├── Pipfile.lock
├── pyproject.toml
├── scripts
│ ├── __init__.py
│ ├── script_config.py
│ └── update_lambda_code.py
├── setup.cfg
└── src
├── aws
│ ├── aws_iot_client_wrapper.py
│ └── __init__.py
├── child_processes
│ ├── child_processes.py
│ └── __init__.py
├── clients
│ ├── __init__.py
│ ├── remote.py
│ └── upload.py
├── errors
│ ├── __init__.py
│ └── network_connection_error.py
├── __init__.py
├── lambda_func
│ ├── __init__.py
│ └── remote_control_api
│ ├── __init__.py
│ └── lambda_function.py
├── logger
│ ├── __init__.py
│ ├── logger_config.py
│ └── ouput.py
├── remote_control
│ ├── command.py
│ ├── __init__.py
│ └── process.py
└── vehicle_detector
├── detect_vehicle.py
└── __init__.py

Workflow of command-and-response using API

Set up IAM Role

Create manage_iot_jobs_policy

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iot:CreateJob",
"iot:CancelJob",
"iot:DescribeJob",
"iot:DescribeJobExecution",
"iot:ListJobExecutionsForThing"
],
"Resource": [
"arn:aws:iot:*:[aws_account]:thing/*",
"arn:aws:iot:*:[aws_account]:job/*",
"arn:aws:iot:*:[aws_account]:thinggroup/*"
]
}
]
}

Create s3_access_policy

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::[bucket_name]/*"
}
]
}

Attach both policies to the lambda role

Set up AWS Lambda

IOT_PREFIX=arn:aws:iot:[region]:[aws_account]
S3_PREFIX=arn:aws:s3:::[bucket_name]

Explanation of The Lambda Code

lambda_handler( )

validate()

cancel()

respond()

command()

Test remote_control_api Lambda

Test command

{
"queryStringParameters": {
"action": "cmd",
"cmd": "greeting"
},
"multiValueQueryStringParameters": {
"thingNames": [
"vehicle_detector_1_REMOTE"
]
}
}
2021-08-16 18:39:17,258 - src.clients.remote - INFO - Recieved command "greeting", executing now...
2021-08-16 18:39:17,258 - src.clients.remote - INFO - Execution result: Hello from vehicle_detector_1
2021-08-16 18:39:17,259 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Performing sync publish...
2021-08-16 18:39:17,347 - src.clients.remote - INFO - Job status (4, 'SUCCEEDED') update SUCCESS for cmd "greeting"

Test response

{
"queryStringParameters": {
"action": "resp",
"thingName": "vehicle_detector_1_REMOTE",
"jobId": "test1"
},
"multiValueQueryStringParameters": []
}

Test cancel

{
"queryStringParameters": {
"action": "cancel",
"jobId": "f1834612-fee4-11eb-b54a-919eefa6b4af"
},
"multiValueQueryStringParameters": []
}

Set up API Gateway

Test command

Test response

Test cancel

Final Test

Test command

curl -X GET -H 'x-api-key:[your_api_key]' -H 'Accept:application/json' "https://[your_api_endpoint]/test?action=cmd&cmd=greeting&thingNames=vehicle_detector_1_REMOTE"
{"jobId": "021d673d-fef4-11eb-9200-0d5b5ed6a46e", "message": "cmd='greeting' SUCCEEDED!"}

Test response

curl -X GET -H 'x-api-key:[your_api_key]' -H 'Accept:application/json' "https://[your_api_endpoint]/test?action=resp&thingName=vehicle_detector_1_REMOTE&jobId=021d673d-fef4-11eb-9200-0d5b5ed6a46e"
{"output": "Hello from vehicle_detector_1", "message": "Respond SUCCEEDED!"}

Test cancel

curl -X GET -H 'x-api-key:[your_api_key]' -H 'Accept:application/json' "https://[your_api_endpoint]/test?action=cmd&cmd=greeting&thingNames=vehicle_detector_1_REMOTE"
{"jobId": "61afd4af-fef6-11eb-8d37-3fa1f0109e21", "message": "cmd='greeting' SUCCEEDED!"}
curl -X GET -H 'x-api-key:[your_api_key]' -H 'Accept:application/json' "https://[your_api_endpoint]/test?action=cancel&jobId=61afd4af-fef6-11eb-8d37-3fa1f0109e21"
{"message": "Cancel job 61afd4af-fef6-11eb-8d37-3fa1f0109e21 SUCCEEDED!"}

Robustness tests

Summary

Hi, I am from the Earth. And you?