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.
Diff: PythonGUI/ATT_AWS_IoT_Demo_GUI.py
- Revision:
- 25:91d771247ac8
- Parent:
- 20:ee34856ae510
--- a/PythonGUI/ATT_AWS_IoT_Demo_GUI.py Fri Dec 16 18:04:39 2016 +0000 +++ b/PythonGUI/ATT_AWS_IoT_Demo_GUI.py Mon Dec 19 20:52:28 2016 +0000 @@ -28,6 +28,10 @@ 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\\" ####################################################################################################################### # @@ -36,21 +40,51 @@ ####################################################################################################################### 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 Demo") +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 -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) +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() @@ -67,17 +101,24 @@ def setStatus(ledStatus, tempStatus, humidStatus, version): global versionLastValue - ledStatusLabelTxt.set(ledStatus) + ledStatusLabelTxt.set(colorDict[ledStatus]) + updateLEDImage(ledImgPaths[ledStatus]) tempStatusLabelTxt.set(str(tempStatus) + " (F)") humidStatusLabelTxt.set(str(humidStatus) + " %") isStale = "" if (versionLastValue == version): - isStale = " (stale)" + 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") @@ -93,56 +134,80 @@ 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 -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)") +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") -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)") +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 = 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)") +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)") -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)") +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 -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) +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 -font = tkFont.Font(family='Times', size=24, weight='bold') -O['font'] = font -R['font'] = font -G['font'] = font -B['font'] = font -W['font'] = font +buttonFont = tkFont.Font(family='Arial', size=12, weight='bold') +for button in ledButtons: + button['font'] = buttonFont -# 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) +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) ####################################################################################################################### # @@ -225,7 +290,7 @@ print("+++++++++++++++++++++\n\n") # Send payload to our status - setStatus(colorDict[reportedColor], reportedTemp, reportedHumid, reportedVersion) + setStatus(reportedColor, reportedTemp, reportedHumid, reportedVersion) getTimerAlive = TRUE def customShadowTimer_Get(): @@ -425,7 +490,8 @@ # Delete shadow JSON doc #AIT.shadowDelete(customShadowCallback_Delete, 5) -getTimer = Timer(3.0, customShadowTimer_Get, ()) +# 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)