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-07
- Revision:
- 20:ee34856ae510
- Parent:
- 19:488dad1e168e
- Child:
- 25:91d771247ac8
File content as of revision 20:ee34856ae510:
''' /* * 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 re 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") # Setup frames topframe = Frame(window) topframe.pack(fill=X, side = TOP) frameR1 = Frame(window) frameR1.pack(fill=X, side = TOP) frameR2 = Frame(window) frameR2.pack(fill=X, side = TOP) frameR3 = Frame(window) frameR3.pack(fill=X, side = TOP) bottomframe = Frame(window) bottomframe.pack(fill=X, side = BOTTOM) # Label vars (controls shown text) ledStaticLabelTxt = StringVar() ledStatusLabelTxt = StringVar() tempStaticLabelTxt = StringVar() tempStatusLabelTxt = StringVar() humidStaticLabelTxt = StringVar() humidStatusLabelTxt = StringVar() versionStaticLabelTxt = StringVar() versionStatusLabelTxt = StringVar() versionLastValue = -1 # Control callbacks def setStatus(ledStatus, tempStatus, humidStatus, version): global versionLastValue ledStatusLabelTxt.set(ledStatus) tempStatusLabelTxt.set(str(tempStatus) + " (F)") humidStatusLabelTxt.set(str(humidStatus) + " %") isStale = "" if (versionLastValue == version): isStale = " (stale)" else: versionLastValue = version versionStatusLabelTxt.set(str(version) + isStale) def offButtonCallBack(): sendLEDRequest("0") def redButtonCallBack(): sendLEDRequest("1") def greenButtonCallBack(): sendLEDRequest("2") def blueButtonCallBack(): sendLEDRequest("4") def whiteButtonCallBack(): sendLEDRequest("7") # Create our Labels ledStaticLabel = Label(topframe, textvariable=ledStaticLabelTxt, anchor=W, relief=FLAT) ledStaticLabelTxt.set("Reported LED Status: ") ledStatusLabel = Label(topframe, textvariable=ledStatusLabelTxt, anchor=W, relief=FLAT) ledStatusLabelTxt.set("unknown (needs to sync)") tempStaticLabel = Label(frameR1, textvariable=tempStaticLabelTxt, anchor=W, relief=FLAT) tempStaticLabelTxt.set("Reported Temperature: ") tempStatusLabel = Label(frameR1, textvariable=tempStatusLabelTxt, anchor=W, relief=FLAT) tempStatusLabelTxt.set("unknown (needs to sync)") humidStaticLabel = Label(frameR2, textvariable=humidStaticLabelTxt, anchor=W, relief=FLAT) humidStaticLabelTxt.set("Reported Humidity: ") humidStatusLabel = Label(frameR2, textvariable=humidStatusLabelTxt, anchor=W, relief=FLAT) humidStatusLabelTxt.set("unknown (needs to sync)") versionStaticLabel = Label(frameR3, textvariable=versionStaticLabelTxt, anchor=W, relief=FLAT) versionStaticLabelTxt.set("IoT Shadow Version: ") versionStatusLabel = Label(frameR3, textvariable=versionStatusLabelTxt, anchor=W, relief=FLAT) versionStatusLabelTxt.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 ledStaticLabel.pack(side = LEFT) ledStatusLabel.pack(side = LEFT) tempStaticLabel.pack(side = LEFT) tempStatusLabel.pack(side = LEFT) humidStaticLabel.pack(side = LEFT) humidStatusLabel.pack(side = LEFT) versionStaticLabel.pack(side = LEFT) versionStatusLabel.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: AIT (AWS IoT Thing) { "state": { "desired": { "ledColor": <UINT8> }, "reported": { "ledColor": <UINT8>, "temperature": <FLOAT>, "humidity": <INT16> } } } ''' def sendLEDRequest(color_input): if (color_input in accepted): JSONPayload = '{"state":{"desired":{"ledColor":' + str(color_input) + '}}}' AIT.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") # 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"] reportedTemp = payloadDict["state"]["reported"]["temperature"] reportedHumid = payloadDict["state"]["reported"]["humidity"] reportedVersion = payloadDict["version"] print("++++++++GET++++++++++") print("ledColor : " + str(reportedColor) + " (" + colorDict[reportedColor] + ")") print("temperature: " + str(reportedTemp)) print("humidity : " + str(reportedHumid)) print("version: " + str(reportedVersion)) print("+++++++++++++++++++++\n\n") # Send payload to our status setStatus(colorDict[reportedColor], reportedTemp, reportedHumid, reportedVersion) getTimerAlive = TRUE def customShadowTimer_Get(): while (getTimerAlive): AIT.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 # The FRDM-K64F demo isn't designed to work with web socket hardCodeMQTT = False # Set this to true if you want to hard code the MQTT params below # AWS parameters AWS_IOT_MQTT_HOST = "TODO" AWS_IOT_MQTT_PORT = 8883 AWS_IOT_MQTT_CLIENT_ID = "TODO" AWS_IOT_MY_THING_NAME = "TODO" AWS_MQTT_CONFIG_FILENAME = "C:/Temp/certs/mqtt_config.txt" 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 (TODO) # ####################################################################################################################### ''' 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 # ####################################################################################################################### # This block parses the MQTT file. ''' Example format for mqtt_config.txt: AWS_IOT_MQTT_HOST=1234asdf.iot.us-west-2.amazonaws.com AWS_IOT_MQTT_PORT=8883 AWS_IOT_MQTT_CLIENT_ID=MyThingName WS_IOT_MY_THING_NAME=MyThingName ''' if (not hardCodeMQTT): if not os.path.exists(AWS_MQTT_CONFIG_FILENAME): print "ERROR: MQTT Config file not found, " + AWS_MQTT_CONFIG_FILENAME exit(1) mqtt_file = open(AWS_MQTT_CONFIG_FILENAME) mqtt_tokens = re.split('=|\n', mqtt_file.read()) print mqtt_tokens if (len(mqtt_tokens) != 8): print "ERROR: Detected incorrect MQTT file format" exit(1) index = 0 for token in mqtt_tokens: if (token == "AWS_IOT_MQTT_HOST"): AWS_IOT_MQTT_HOST = mqtt_tokens[index+1] if (token == "AWS_IOT_MQTT_PORT"): AWS_IOT_MQTT_PORT = int(mqtt_tokens[index + 1]) if (token == "AWS_IOT_MQTT_CLIENT_ID"): AWS_IOT_MQTT_CLIENT_ID = mqtt_tokens[index + 1] if (token == "AWS_IOT_MY_THING_NAME"): AWS_IOT_MY_THING_NAME = mqtt_tokens[index+1] index += 1 print "MQTT Params:" print "AWS_IOT_MQTT_HOST = " + AWS_IOT_MQTT_HOST print "AWS_IOT_MQTT_PORT = " + str(AWS_IOT_MQTT_PORT) print "AWS_IOT_MQTT_CLIENT_ID = " + AWS_IOT_MQTT_CLIENT_ID print "AWS_IOT_MY_THING_NAME = " + AWS_IOT_MY_THING_NAME # Makes sure cert/key 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 AIT = myAWSIoTMQTTShadowClient.createShadowHandlerWithName(AWS_IOT_MY_THING_NAME, True) # Listen on deltas AIT.shadowRegisterDeltaCallback(customShadowCallback_Delta) # Delete shadow JSON doc #AIT.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()