V.062 11/3

Dependencies:   FT6206 SDFileSystem ILI9341_t3

Fork of ATT_AWS_IoT_demo_v06 by attiot

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()