Demo application for using the AT&T IoT Starter Kit Powered by AWS.
Dependencies: SDFileSystem
Fork of ATT_AWS_IoT_demo by
IoT Starter Kit Powered by AWS Demo
This program demonstrates the AT&T IoT Starter Kit sending data directly into AWS IoT. It's explained and used in the Getting Started with the IoT Starter Kit Powered by AWS on starterkit.att.com.
What's required
- AT&T IoT LTE Add-on (also known as the Cellular Shield)
- NXP K64F - for programming
- microSD card - used to store your AWS security credentials
- AWS account
- Python, locally installed
If you don't already have an IoT Starter Kit, you can purchase a kit here. The IoT Starter Kit Powered by AWS includes the LTE cellular shield, K64F, and a microSD card.
PythonGUI/ATT_AWS_IoT_Demo_GUI.py
- Committer:
- ampembeng
- Date:
- 2016-12-02
- Revision:
- 17:46780b2de3e4
- Child:
- 19:488dad1e168e
File content as of revision 17:46780b2de3e4:
''' /* * Copyright 2010-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file is distributed * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing * permissions and limitations under the License. */ ''' from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTShadowClient import sys import os.path import logging import time import json import getopt import Tkinter import tkFont import time from threading import Timer from Tkinter import * ####################################################################################################################### # # Set up our Tkinter based GUI # ####################################################################################################################### accepted = ["0", "1", "2", "4", "7"] colorDict = {0 : 'off', 1 : 'red', 2 : 'green', 4 : "blue", 7 : "white"} window = Tkinter.Tk() window.wm_title("AT&T AWS IoT Demo") topframe = Frame(window) topframe.pack() bottomframe = Frame(window) bottomframe.pack( side = BOTTOM ) statusLabel = StringVar() statusString = StringVar() # Control callbacks def setStatus(statusStr): if(statusString == statusStr): statusString.set("unknown") else: statusString.set(statusStr) def offButtonCallBack(): sendLEDRequest("0") def redButtonCallBack(): sendLEDRequest("1") def greenButtonCallBack(): sendLEDRequest("2") def blueButtonCallBack(): sendLEDRequest("4") def whiteButtonCallBack(): sendLEDRequest("7") # Create our Labels StaticLabel = Label(topframe, textvariable=statusLabel, relief=FLAT) statusLabel.set("AWS Reported LED Status: ") StatusLabel = Label(topframe, textvariable=statusString, relief=FLAT) statusString.set("unknown (needs to sync)") # Create our Buttons O = Tkinter.Button(bottomframe, text ="Off", fg="gray", bg="black", command = offButtonCallBack) R = Tkinter.Button(bottomframe, text ="R", fg="gray", bg="red", command = redButtonCallBack) G = Tkinter.Button(bottomframe, text ="G", fg="gray", bg="green", command = greenButtonCallBack) B = Tkinter.Button(bottomframe, text ="B", fg="gray", bg="blue", command = blueButtonCallBack) W = Tkinter.Button(bottomframe, text ="W", fg="gray", bg="white", command = whiteButtonCallBack) # Set font font = tkFont.Font(family='Times', size=24, weight='bold') O['font'] = font R['font'] = font G['font'] = font B['font'] = font W['font'] = font # Arrange our controls StaticLabel.pack(side = LEFT) StatusLabel.pack(side = LEFT) O.pack(side = LEFT) R.pack(side = LEFT) G.pack(side = LEFT) B.pack(side = LEFT) W.pack(side = LEFT) ####################################################################################################################### # # These functions are for AWS # ####################################################################################################################### # Shadow JSON schema: # # Name: Bot # { # "state": { # "desired":{ # "ledColor":<INT VALUE> # } # } #} def sendLEDRequest(color_input): if (color_input in accepted): JSONPayload = '{"state":{"desired":{"ledColor":' + str(color_input) + '}}}' Bot.shadowUpdate(JSONPayload, customShadowCallback_Update, 5) else: print("WARN: Color input invalid - " + color_input) # Custom Shadow callback def customShadowCallback_Delta(payload, responseStatus, token): # payload is a JSON string ready to be parsed using json.loads(...) # in both Py2.x and Py3.x print(responseStatus) payloadDict = json.loads(payload) print("++++++++DELTA++++++++++") print("ledColor: " + str(payloadDict["state"]["ledColor"])) print("version: " + str(payloadDict["version"])) print("+++++++++++++++++++++++\n\n") # Send payload to our status setStatus(colorDict[payloadDict["state"]["ledColor"]]) # Custom Shadow callback def customShadowCallback_Update(payload, responseStatus, token): # payload is a JSON string ready to be parsed using json.loads(...) # in both Py2.x and Py3.x if responseStatus == "timeout": print("Update request " + token + " time out!") if responseStatus == "accepted": payloadDict = json.loads(payload) print("~~~~~~~~~~~~~~~~~~~~~~~") print("Update request with token: " + token + " accepted!") print("ledColor: " + str(payloadDict["state"]["desired"]["ledColor"])) print("~~~~~~~~~~~~~~~~~~~~~~~\n\n") if responseStatus == "rejected": print("Update request " + token + " rejected!") def customShadowCallback_Delete(payload, responseStatus, token): if responseStatus == "timeout": print("Delete request " + token + " time out!") if responseStatus == "accepted": print("~~~~~~~~~~~~~~~~~~~~~~~") print("Delete request with token: " + token + " accepted!") print("~~~~~~~~~~~~~~~~~~~~~~~\n\n") if responseStatus == "rejected": print("Delete request " + token + " rejected!") # Custom Shadow callback def customShadowCallback_Get(payload, responseStatus, token): print(responseStatus) payloadDict = json.loads(payload) reportedColor = payloadDict["state"]["reported"]["ledColor"] print("++++++++GET++++++++++") print("ledColor: " + str(reportedColor) + " (" + colorDict[reportedColor] + ")") print("version: " + str(payloadDict["version"])) print("+++++++++++++++++++++\n\n") # Send payload to our status setStatus(colorDict[reportedColor]) getTimerAlive = TRUE def customShadowTimer_Get(): while (getTimerAlive): Bot.shadowGet(customShadowCallback_Get, 5) time.sleep(3) ####################################################################################################################### # # Vars # ####################################################################################################################### # Usage usageInfo = """Usage: Use certificate based mutual authentication: python basicShadowDeltaListener.py -e <endpoint> -r <rootCAFilePath> -c <certFilePath> -k <privateKeyFilePath> Use MQTT over WebSocket: python basicShadowDeltaListener.py -e <endpoint> -r <rootCAFilePath> -w Type "python basicShadowDeltaListener.py -h" for available options. """ # Help info helpInfo = """-e, --endpoint Your AWS IoT custom endpoint -r, --rootCA Root CA file path -c, --cert Certificate file path -k, --key Private key file path -w, --websocket Use MQTT over WebSocket -h, --help Help information """ ####################################################################################################################### # # AWS IoT Config Parameters. The user needs to enter these (they should match the parameters in aws_iot_config.h) # ####################################################################################################################### useWebsocket = False # TODO Move params to aws_iot_config.txt AWS_IOT_MQTT_HOST = "a3sptpklzib7sa.iot.us-west-2.amazonaws.com" AWS_IOT_MQTT_PORT = 8883 AWS_IOT_MQTT_CLIENT_ID = "EesFRDM" AWS_IOT_MY_THING_NAME = "EesFRDM" AWS_IOT_ROOT_CA_FILENAME = "C:/Temp/certs/rootCA-certificate.crt" AWS_IOT_PRIVATE_KEY_FILENAME = "C:/Temp/certs/private.pem.key" AWS_IOT_CERTIFICATE_FILENAME = "C:/Temp/certs/certificate.pem.crt" ####################################################################################################################### # # Arg Parser # ####################################################################################################################### ''' try: opts, args = getopt.getopt(sys.argv[1:], "hwe:k:c:r:", ["help", "endpoint=", "key=","cert=","rootCA=", "websocket"]) if len(opts) == 0: raise getopt.GetoptError("No input parameters!") for opt, arg in opts: if opt in ("-h", "--help"): print(helpInfo) exit(0) if opt in ("-e", "--endpoint"): AWS_IOT_MQTT_HOST = arg if opt in ("-r", "--rootCA"): AWS_IOT_ROOT_CA_FILENAME = arg if opt in ("-c", "--cert"): AWS_IOT_CERTIFICATE_FILENAME = arg if opt in ("-k", "--key"): AWS_IOT_PRIVATE_KEY_FILENAME = arg if opt in ("-w", "--websocket"): useWebsocket = True except getopt.GetoptError: print(usageInfo) #exit(1) # Missing configuration notification missingConfiguration = False if not AWS_IOT_MQTT_HOST: print("Missing '-e' or '--endpoint'") missingConfiguration = True if not AWS_IOT_ROOT_CA_FILENAME: print("Missing '-r' or '--rootCA'") missingConfiguration = True if not useWebsocket: if not AWS_IOT_CERTIFICATE_FILENAME: print("Missing '-c' or '--cert'") missingConfiguration = True if not AWS_IOT_PRIVATE_KEY_FILENAME: print("Missing '-k' or '--key'") missingConfiguration = True if missingConfiguration: exit(2) ''' # Configure logging logger = logging.getLogger("AWSIoTPythonSDK.core") logger.setLevel(logging.DEBUG) streamHandler = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') streamHandler.setFormatter(formatter) logger.addHandler(streamHandler) ####################################################################################################################### # # Main Code # ####################################################################################################################### # Makes sure files exist if not os.path.exists(AWS_IOT_ROOT_CA_FILENAME): print "ERROR: Root CA file not found, " + AWS_IOT_ROOT_CA_FILENAME exit(1) if not os.path.exists(AWS_IOT_PRIVATE_KEY_FILENAME): print "ERROR: Private Key file not found, " + AWS_IOT_PRIVATE_KEY_FILENAME exit(1) if not os.path.exists(AWS_IOT_CERTIFICATE_FILENAME): print "ERROR: AWS IOT cert file not found, " + AWS_IOT_CERTIFICATE_FILENAME exit(1) # Init AWSIoTMQTTShadowClient myAWSIoTMQTTShadowClient = None if useWebsocket: myAWSIoTMQTTShadowClient = AWSIoTMQTTShadowClient("basicShadowDeltaListener", useWebsocket=True) myAWSIoTMQTTShadowClient.configureEndpoint(AWS_IOT_MQTT_HOST, 443) myAWSIoTMQTTShadowClient.configureCredentials(AWS_IOT_ROOT_CA_FILENAME) else: myAWSIoTMQTTShadowClient = AWSIoTMQTTShadowClient("basicShadowDeltaListener") myAWSIoTMQTTShadowClient.configureEndpoint(AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT) myAWSIoTMQTTShadowClient.configureCredentials(AWS_IOT_ROOT_CA_FILENAME, AWS_IOT_PRIVATE_KEY_FILENAME, AWS_IOT_CERTIFICATE_FILENAME) # AWSIoTMQTTShadowClient configuration myAWSIoTMQTTShadowClient.configureAutoReconnectBackoffTime(1, 32, 20) myAWSIoTMQTTShadowClient.configureConnectDisconnectTimeout(10) # 10 sec myAWSIoTMQTTShadowClient.configureMQTTOperationTimeout(5) # 5 sec # Connect to AWS IoT myAWSIoTMQTTShadowClient.connect() # Create a deviceShadow with persistent subscription Bot = myAWSIoTMQTTShadowClient.createShadowHandlerWithName(AWS_IOT_MY_THING_NAME, True) # Listen on deltas Bot.shadowRegisterDeltaCallback(customShadowCallback_Delta) # Delete shadow JSON doc #Bot.shadowDelete(customShadowCallback_Delete, 5) getTimer = Timer(3.0, customShadowTimer_Get, ()) getTimer.start() # GUI loop (loops until closed) window.mainloop() # Kill our timer after the GUI closes getTimerAlive = FALSE getTimer.cancel()