V.062 11/3

Dependencies:   FT6206 SDFileSystem ILI9341_t3

Fork of ATT_AWS_IoT_demo_v06 by attiot

Revision:
17:46780b2de3e4
Child:
19:488dad1e168e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PythonGUI/ATT_AWS_IoT_Demo_GUI.py	Fri Dec 02 22:49:17 2016 +0000
@@ -0,0 +1,341 @@
+'''
+/*
+ * 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()