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.
AWS IoT
Select registry and select things. When the Thing pane appears, press create at the top of the screen.
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.
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.
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
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.
Since mock is made with python SDK, install Python SDK. Issue the following command from the EC2 console
pip install AWSIoTPythonSDK
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
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
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()
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.
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.
The rough sequence is shown below.
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.
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