![](/media/cache/group/default_image.jpg.50x50_q85.jpg)
V.06 11/3
Dependencies: FT6206 SDFileSystem SPI_TFT_ILI9341 TFT_fonts
Fork of ATT_AWS_IoT_demo by
PythonGUI/ATT_AWS_IoT_Demo_GUI.py
- Committer:
- ampembeng
- Date:
- 2016-12-19
- Revision:
- 25:91d771247ac8
- Parent:
- 20:ee34856ae510
File content as of revision 25:91d771247ac8:
''' /* * 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 * from PIL import Image, ImageTk exePath = os.path.dirname(os.path.realpath(__file__)) assetPath = exePath + "\\assets\\" ####################################################################################################################### # # Set up our Tkinter based GUI # ####################################################################################################################### accepted = ["0", "1", "2", "4", "7"] colorDict = {0 : 'off', 1 : 'red', 2 : 'green', 4 : "blue", 7 : "white"} ledImgPaths = {0 : "LEDOff.png", 1 : 'LEDRed.png', 2 : 'LEDGreen.png', 4 : "LEDBlue.png", 7 : "LEDWhite.png"} window = Tkinter.Tk() window.wm_title("AT&T AWS IoT Starter Kit Demo") window.iconbitmap(assetPath + "ATT_Icon.ico") window.resizable(width=False, height=False) buttonColor = 'dark slate gray' buttonTxtColor = 'tv white' headerBgColor = 'snow' bgColor = 'steel blue' fgTextColor = 'white' # Setup frames def initFrames(_window, side, color=bgColor): frame = Frame(_window, background=color) frame.pack(fill=X, side=side) return frame headerframe = initFrames(window, TOP, headerBgColor) frameR1 = initFrames(window, TOP) frameR2 = initFrames(window, TOP) frameR3 = initFrames(window, TOP) frameR4 = initFrames(window, TOP) frameR5 = initFrames(window, TOP) frameR6 = initFrames(window, TOP) frameR7 = initFrames(window, TOP) frameR8 = initFrames(window, TOP) frameR9 = initFrames(window, TOP) buttonFrame = initFrames(window, BOTTOM) # So we can loop through our frames frameIndex = 0 frames = [headerframe, frameR1, frameR2, frameR3, frameR4, frameR5, frameR6, frameR7, frameR8, frameR9, buttonFrame] def curFrame(): return frames[frameIndex] def nextFrame(): global frameIndex frameIndex += 1 return frames[frameIndex] # 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(colorDict[ledStatus]) updateLEDImage(ledImgPaths[ledStatus]) tempStatusLabelTxt.set(str(tempStatus) + " (F)") humidStatusLabelTxt.set(str(humidStatus) + " %") isStale = "" if (versionLastValue == version): isStale = " (stale data)" else: versionLastValue = version versionStatusLabelTxt.set(str(version) + isStale) def updateLEDImage(path): global ledPicture img2 = ImageTk.PhotoImage(Image.open(assetPath + path)) ledPicture.configure(image=img2) ledPicture.image = img2 def offButtonCallBack(): sendLEDRequest("0") def redButtonCallBack(): sendLEDRequest("1") def greenButtonCallBack(): sendLEDRequest("2") def blueButtonCallBack(): sendLEDRequest("4") def whiteButtonCallBack(): sendLEDRequest("7") # Photos def initPhotoLabels(frame, photoName, color=bgColor, side=LEFT, pad=0): image = Image.open(assetPath + photoName) photo = ImageTk.PhotoImage(image) label = Label(frame, image=photo, background=color) label.image = photo # keep a reference! label.pack(side=side, padx=pad) return label # Create our Labels headerLabel1 = initPhotoLabels(curFrame(), "attLogo.png", headerBgColor) headerLabel2 = initPhotoLabels(curFrame(), "awsLogo.png", headerBgColor, pad=10) starterKitBoxLabel = initPhotoLabels(nextFrame(), "starterKitBox.png") labelFont = tkFont.Font(family='Times', size=14, weight='bold') def initLargeTextLabels(frame, text): label = Label(frame, font=labelFont, text=text, anchor=W, relief=FLAT, fg=fgTextColor, background=bgColor) label.pack(side=LEFT) setLEDColorLabel = initLargeTextLabels(nextFrame(),"Reported Values") def initLabels(frame, lableVar, text): lableVar.set(text) label = Label(frame, textvariable=lableVar, anchor=W, relief=FLAT, fg=fgTextColor, background=bgColor) label.pack(side = LEFT) return label ledStaticLabel = initLabels(nextFrame(), ledStaticLabelTxt, "LED Color: ") ledStatusLabel = initLabels(curFrame(), ledStatusLabelTxt, "unknown (needs to sync)") tempStaticLabel = initLabels(nextFrame(), tempStaticLabelTxt, "Temperature: ") tempStatusLabel = initLabels(curFrame(), tempStatusLabelTxt, "unknown (needs to sync)") humidStaticLabel = initLabels(nextFrame(), humidStaticLabelTxt, "Humidity: ") humidStatusLabel = initLabels(curFrame(), humidStatusLabelTxt, "unknown (needs to sync)") versionStaticLabel = initLabels(nextFrame(), versionStaticLabelTxt, "Shadow Version: ") versionStatusLabel = initLabels(curFrame(), versionStatusLabelTxt, "unknown (needs to sync)") lineLabel = initLargeTextLabels(nextFrame(), "_______________________________________") setLEDColorLabel = initLargeTextLabels(nextFrame(),"Set LED Color") starterKitBoardLabel = initPhotoLabels(nextFrame(), "startKitBoard.png", side=TOP) # Creates an LED label (image) that we can update. ledPicture = Label(starterKitBoardLabel, background=bgColor, relief=FLAT, width=10, height=12) ledPicture.place(relx=1.0, rely=1.0, x=(40-300), y=(85-245), anchor="se") updateLEDImage("LEDOff.png") # Create our Buttons def buttonInit(text, bg, command): return Tkinter.Button(buttonFrame, text =text, fg="snow", bg=bg, height=1, width=6, command=command) O = buttonInit("OFF", buttonColor, offButtonCallBack) R = buttonInit("RED", buttonColor, redButtonCallBack) G = buttonInit("GREEN", buttonColor, greenButtonCallBack) B = buttonInit("BLUE", buttonColor, blueButtonCallBack) W = buttonInit("WHITE", buttonColor, whiteButtonCallBack) ledButtons = [O, R, G, B, W] # Set font buttonFont = tkFont.Font(family='Arial', size=12, weight='bold') for button in ledButtons: button['font'] = buttonFont buttonPadX = 5 for button in ledButtons: button.pack(side=LEFT, padx=buttonPadX) # NOTE: If you want to test the GUI layout without running the AWS code comment these lines in #window.mainloop() #exit(0) ####################################################################################################################### # # 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(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) # NOTE: We make this slightly slower than the target loop (to prevent 'stale data') getTimer = Timer(3.5, customShadowTimer_Get, ()) getTimer.start() # GUI loop (loops until closed) window.mainloop() # Kill our timer after the GUI closes getTimerAlive = FALSE getTimer.cancel()