Python mock to try AWS IoT Device Shadow

Introduction

I think one of the reasons for using AWS IoT is that you can control Thing / Device by Thing shadow. On the other hand, although I understood the outline, many people think that it is not possible to check the operation because there is no "Thing". You can actually check this on Linux by using the Device SDK. Here, let's check the operation of Thing shadow using EC2 as a virtual device.

[Addition] I've been asked about the meaning of Shadow, so I'll add a little. If you manage one device like this sample, it is not difficult to organize it manually, but in the case of IoT, it is necessary to manage a large number of sensors and gateways. Also, it is not always nearby. I think the value of shadow is that you can manage / change the settings of many / distant devices via the cloud.

Preparation

AWS IoT

Creating Thing

Select registry and select things. When the Thing pane appears, press create at the top of the screen. スクリーンショット 2017-02-07 23.08.11.png

To create a Thing, set an arbitrary name and press create thing. Here, thinname is _ ** shadow-test ** _.

Select Certificate on the screen after creating Thing. Press create certificate on the displayed screen. スクリーンショット 2017-02-07 23.11.03.png

Please download the three certificates created. (cert.pem/public.key/private.key) Also, press ** Active ** displayed at the bottom of the screen to activate the certificate.

Confirm Endpoint

On the AWS IoT console, press Settings at the bottom left of the screen, check the endpoint on the displayed screen, copy it to text, etc. There will be one endpoint for each region. {random}.iot.{region}.amazon.com It is displayed in the form of.

EC2

Start EC2

Boot amazon linux on EC2. t2.micro is enough. If you don't know how to start EC2, please refer to here. The default HDD size is sufficient. Don't forget to set the Global IP to log in with SSH.

Install IoT Device SDK on EC2

Since mock is made with python SDK, install Python SDK. Issue the following command from the EC2 console

pip install AWSIoTPythonSDK

Installation of dummy program (mock)

As needed

Place In this post, I will assume that you will work under / tmp.

mkdir /tmp/dummy-shadow
cd /tmp/dummy-shadow
mkdir certs
cd certs

Certificate settings

Get rootCA (placed under certs) Obtained from VeriSign here

curl https://www.symantec.com/content/en/us/enterprise/veisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem -o /tmp/root.pem

Also, place the private / cert certificate created earlier in AWS IoT in this certs directory. You can also copy and paste with scp / vi. The file name is cert => cert.pem private => private.pem Please. Try to get the following result.

ls -1 /tmp/certs
cert.pem
private.pem
root.pem

Installation of dummy (mock)

Place the following files in / tmp / dummy-shadow. Please set YOUR_AWSIOT_DOMAIN according to your environment. To check your domain, see AWS IoT Console Settings => Custom endpoint.

setup.json


{
   "AWSIoT": {
        "ENDPOINT":"YOUR_AWSIOT_DOMAIN",
        "CERT_PATH":"./certs/",
        "KEYS":["cert.pem", "public.pem", "root.pem"]
   },
   "DEVICE":{
        "NAME":"shadow-test",
   }
}

Below is the dummy program

dummy-shadow.py


import os
import sys
import json
import time
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTShadowClient


CONFIG_FILE = './setup.json'

#Fixed definition of the state when the application starts(Variables that synchronize with shadow)
SIGNAL    = "green"
WAIT_TIME = 10

#Since shadow is read from the callback function, it is defined as global
shadow         = None
shadow_hundler = None

##########################################################
# setup.Read settings from json
##########################################################
def readConfig():
    print 'start readConfig func'

    try:
        # read config file
        f = open(CONFIG_FILE, "r")
        jsonData = json.load(f)
        f.close()

        list = {}
        list["ENDPOINT"]    = jsonData["AWSIoT"]["ENDPOINT"]
        list["CERT_PATH"]   = jsonData["AWSIoT"]["CERT_PATH"]
        list["DEVICE_NAME"] = jsonData["DEVICE"]["NAME"]
        
        return list

    except Exception as e:
        print 'Config load error'
        print e.message
        sys.exit()

##########################################################
#Issuance of Shadow update command
##########################################################
def updateThing(report):
    try: 
        report_json = '{"state":{"reported":'+ report + '}}'
        print "send currnet status to cloud-shadow"
        print report_json
        shadow_hundler.shadowUpdate(report_json, None, 5)
        
        return
    
    except Exception as e:
        print e.message
        sys.exit()
        
##########################################################
#Called as a callback type from shadowRegisterDeltaCallback
#
##########################################################
def getDelta(payload, responseStatus, token):
    try:
        print '======get Delta======'
        dict_delta = json.loads(payload)
        print dict_delta
        state = dict_delta["state"]
        
        if state.has_key("wait_time"):
            delta = int(state["wait_time"])
            global WAIT_TIME
            WAIT_TIME = delta
            print "wait time change :%s" % WAIT_TIME
        if state.has_key('signal'):
            global SIGNAL
            SIGNAL = state['signal']
            print "SIGNAL change :%s" % SIGNAL

        report = json.dumps(dict_delta["state"])
        updateThing(report)
        
        return

    except Exception as e:
        print "Error on Delta function"
        print e.message
        raise

################################################
#Shadow connection procedural function
################################################
def initShadow(Config):
    ##--need device cert / private / rootCA--
    # rootCA: get from symantec
    ROOT_KEY    = Config['CERT_PATH'] + 'root.pem'
    CERT_KEY    = Config['CERT_PATH'] + 'cert.pem'
    PRIVATE_KEY = Config['CERT_PATH'] + 'private.pem'
    
    try:
        # init shadow connect procedure
        global shadow
        shadow = AWSIoTMQTTShadowClient(Config["DEVICE_NAME"])
        shadow.configureEndpoint(Config["ENDPOINT"], 8883)    # Setting URL-ENDPOINT & Port
        shadow.configureCredentials(ROOT_KEY, PRIVATE_KEY, CERT_KEY ) # Cert file setting
        shadow.configureConnectDisconnectTimeout(10)# CONNACK wait time (sec)
        shadow.configureMQTTOperationTimeout(5)     # QoS1 publish (sec)
        print 'start connct shadow'
        shadow.connect()
        print 'shadow connect'
        
        return
    
    except Exception as e:
        print 'Error on Init Shadow'
        raise
        
####
if __name__ == '__main__':
    Config = readConfig()
    
    try:
        initShadow(Config)
        print 'satrt subscribe shadow'
        shadow_hundler = shadow.createShadowHandlerWithName(Config['DEVICE_NAME'], True)
        shadow_hundler.shadowRegisterDeltaCallback(getDelta)
        default_state = '{"wait_time":' + str(WAIT_TIME) + ', "signal":"green"}'
        updateThing(default_state)

        while True:
            time.sleep(WAIT_TIME)
            print 'Currnet WAIT_TIME=%s' % str(WAIT_TIME)
            pass

    except KeyboardInterrupt:
         print 'Keyboard Interrupt'
         sys.exit()

    except Exception as e:
        print e.message
        sys.exit()

Execution method

python PROGRAM.py &

Starts in the background with.

shadow update

Perform shadow update on the console or CLI. Select Resistor => Thing => [Thing Name] => Shadow.

Add a desired section as shown below, and try registering with wait_time: 30, signal: "green". Then, as delta, wait_time: 30 That is, only the difference is reported to thing as delta.

スクリーンショット 2017-02-19 22.20.44.png

If you look at the console on the program side, you should see the delta and the sole. So, as you can see from the code, I changed the variable wait_time and sent back [state]. Since the state that should be as eventual consistency is written in the state of delta, it is not necessary to create JSON one by one just by reporting this when __correct state transition __ is made. As mentioned above, please note that if you report in a state where the state transition cannot be performed correctly, it will be misaligned.

When this report is sent, the delta should be gone and desired / reported should have the same value.

Rough sequence

The rough sequence is shown below.

スクリーンショット 2017-02-19 22.38.16.png

Hard-coded as report status when the program starts SIGNAL = "green" WAIT_TIME = 10 Will be notified. If the shadow state is changed several times, the above initial parameters will be notified immediately after the program is started, and delta will be received immediately.

Disclaimer

This post is an individual opinion and is not related to the company or organization to which it belongs. In addition, we do not guarantee the operation of the sample program posted, so please use it as a reference only.

Recommended Posts

Python mock to try AWS IoT Device Shadow
Try to understand Python self
Script to easily create a client device environment for AWS IoT (Python v2 version)
Run AWS IoT Device SDK for Python on Raspberry Pi
[AWS] Try adding Python library to Layer with SAM + Lambda (Python)
Try to operate Facebook with Python
Try to calculate Trace in Python
Try converting cloudmonkey CLI to python3 -1
[AWS SAM] Introduction to Python version
The Python library `awsiot` to pub/sub to AWS IoT used the default port = 443.
Try to reproduce color film with Python
Try logging in to qiita with Python
Try python
[Cloudian # 1] Try to access object storage with AWS SDK for Python (boto3)
I want to play with aws with python
Try to operate Excel using Python (Xlwings)
Python amateurs try to summarize the list ①
AWS IoT device life and death monitoring
Connect to s3 with AWS Lambda Python
First steps to try Google CloudVision in Python
Try to implement Oni Maitsuji Miserable in python
Try sending Metrics to datadog via python, DogStatsD
Try to calculate a statistical problem in Python
3.14 π day, so try to output in Python
Try auto to automatically price Enums in Python 3.6
[2020 version] How to install Python3 on AWS EC2
Try to solve the man-machine chart with Python
Try to draw a life curve with python
Try to make a "cryptanalysis" cipher with Python
Try to automatically generate Python documents with Sphinx
How to specify attributes with Mock of python
Try to calculate RPN in Python (for beginners)
Try to make a dihedral group with Python
[AWS / Lambda] How to load Python external library
Getting started with AWS IoT easily in Python
Summary of studying Python to use AWS Lambda
Try to detect fish with python + OpenCV2.4 (unfinished)
Updated to Python 2.7.9
Python> try: / except:
Try running a Schedule to start and stop an instance on AWS Lambda (Python)
"Backport" to python 2
Try to solve the programming challenge book with python3
Python beginners try adding basic auth to Django admin
Try to make a Python module in C language
[Python] Try to read the cool answer to the FizzBuzz problem
Try to make a command standby tool with python
Try to improve your own intro quiz in Python
Fleet provisioning with AWS IoT SDK for Python v2
(Python) Try to develop a web application using Django
Try to solve the internship assignment problem with Python
Try to operate DB with Python and visualize with d3
Set constructor keyworded arguments to mock attributes in Python
termux × AWS Send smartphone location information to AWS with IoT
I want to write in Python! (3) Utilize the mock
I want to AWS Lambda with Python on Mac!
Try to automate pdf format report creation with Python
Try to extract high frequency words using NLTK (python)
Raspberry Pi + python + IoT device, environment construction procedure to start image processing and machine learning