V.062 11/3

Dependencies:   FT6206 SDFileSystem ILI9341_t3

Fork of ATT_AWS_IoT_demo_v06 by attiot

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)